Difference between revisions of "Developer:LPEC"
m (→Services and Actions Discovery) |
|||
(99 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
= Introduction<br> = | = Introduction<br> = | ||
− | Linn' | + | This article describes the ''Linn Protocol for Eventing and Control'' (''LPEC''), which is a TCP/IP point-2-point protocol that can be used to control Linn's home network products (e.g. DS players).<br> |
+ | |||
+ | The primary means of control for such products is, of course, UPnP. But LPEC provides an alternative mechanism for accessing UPnP services over a basic "telnet-like" protocol. | ||
+ | |||
+ | The UPnP architecture subdivides product control into smaller named units called "services". A DS player, for instance, provides some standard UPnP AV services:<br> | ||
* AVTransport <br> | * AVTransport <br> | ||
Line 9: | Line 13: | ||
and additional Linn-specific services, such as:<br> | and additional Linn-specific services, such as:<br> | ||
− | * | + | * Playlist |
− | * | + | * Radio |
* Product | * Product | ||
− | |||
− | + | By opening a raw TCP/IP socket connection to port 23 on a Bute (or later) home network product, these same services can be controlled using ''LPEC''.<br> | |
− | + | The rest of this article describes the format of the messages that LPEC expects and delivers. Examples are given.<br> | |
− | + | = Connection<br> = | |
− | + | ''LPEC'' can be accessed by connecting a raw socket session to port 23 on the device.<br> | |
+ | The Linn DS can only support up to '''4''' simultaneous sessions. If there are more than 4sessions open at the same time, the DS will ignore any commands from these new sessions, but remain in full control by the first 4 sessions. | ||
− | + | It has been noted that some Crestron processors will re-open TELNET ports without closing existing ones. So it is recommend that on any control device, if the Touchpanel is asleep the TELNET connection is closed. | |
− | = <br> Control<br> = | + | = <br>Control<br> = |
Each service contains actions, which are like methods that can be called on the device with input and output arguments. | Each service contains actions, which are like methods that can be called on the device with input and output arguments. | ||
An action can be perfomed by sending a message of the following form: | An action can be perfomed by sending a message of the following form: | ||
− | <blockquote>ACTION [sub-device]/[ | + | <blockquote>ACTION [sub-device]/[service] [version] [action] "[inarg1]" "[inarg2]" ... "[inargn]"</blockquote> |
e.g. | e.g. | ||
<blockquote>ACTION MediaRenderer/RenderingControl 1 SetVolume "0" "Master" "50"</blockquote> | <blockquote>ACTION MediaRenderer/RenderingControl 1 SetVolume "0" "Master" "50"</blockquote> | ||
− | All messages sent using LPEC get a response. The response to an ACTION message | + | All messages sent using LPEC get a response. The response to an ACTION message is a RESPONSE message that reports the values of all the output arguments: |
− | <blockquote>RESPONSE "[outarg1]" "[outarg2]" ... "[ | + | <blockquote>RESPONSE "[outarg1]" "[outarg2]" ... "[outargn]"</blockquote> |
The SetVolume example given above has no output arguments, so the message received will simply be a <CR><LF> terminated RESPONSE message. | The SetVolume example given above has no output arguments, so the message received will simply be a <CR><LF> terminated RESPONSE message. | ||
Line 45: | Line 49: | ||
In order to subscribe to a service's events, issue a SUBSCRIBE message of the following form: | In order to subscribe to a service's events, issue a SUBSCRIBE message of the following form: | ||
− | <blockquote>SUBSCRIBE [sub-device]/[ | + | <blockquote>SUBSCRIBE [sub-device]/[service]<br></blockquote> |
− | The device | + | The device responds with:<br> |
<blockquote>SUBSCRIBE [subscription-id]<br></blockquote> | <blockquote>SUBSCRIBE [subscription-id]<br></blockquote> | ||
− | and | + | and follows this with an initial event message, which contains the current state of all the service's evented variables:<br> |
<blockquote>EVENT [subscription-id] 0 [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]"<br></blockquote> | <blockquote>EVENT [subscription-id] 0 [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]"<br></blockquote> | ||
e.g<br> | e.g<br> | ||
<blockquote>SUBSCRIBE Ds/Product<br>SUBSCRIBE 49<br>EVENT 49 0 ProductName "Sneaky Music DS" ProductRoom "Main Room" ProductStandby "true" ProductSourceIndex "0"</blockquote> | <blockquote>SUBSCRIBE Ds/Product<br>SUBSCRIBE 49<br>EVENT 49 0 ProductName "Sneaky Music DS" ProductRoom "Main Room" ProductStandby "true" ProductSourceIndex "0"</blockquote> | ||
− | Subsequent changes to the service's evented variables | + | Subsequent changes to the service's evented variables cause unsolicited EVENT messages to be sent from the device as follows: |
<blockquote>EVENT [subscription-id] [sequence-no] [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]"</blockquote> | <blockquote>EVENT [subscription-id] [sequence-no] [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]"</blockquote> | ||
− | Only those variables that have changed | + | Only those variables that have changed are reported. |
The sequence number is a 32-bit unsigned number which increments with each event message and wraps around to 1. | The sequence number is a 32-bit unsigned number which increments with each event message and wraps around to 1. | ||
Line 60: | Line 64: | ||
A sequence number of 0 is reserved for the initial EVENT message, which contains the current state of all the service's evented variables (see above) | A sequence number of 0 is reserved for the initial EVENT message, which contains the current state of all the service's evented variables (see above) | ||
− | <br> | + | By issuing multiple SUBSCRIBE messages, it is possible to subscribe to up to 16 services simultaneously.<br> |
In order to unsubscribe from a service, send an UNSUBSCRIBE message of the form:<br> | In order to unsubscribe from a service, send an UNSUBSCRIBE message of the form:<br> | ||
<blockquote>UNSUBSCRIBE [subscription-id]<br></blockquote> | <blockquote>UNSUBSCRIBE [subscription-id]<br></blockquote> | ||
alternatively:<br> | alternatively:<br> | ||
− | <blockquote>UNSUBSCRIBE [sub-device]/[ | + | <blockquote>UNSUBSCRIBE [sub-device]/[service]<br></blockquote> |
or, to unsubscribe from all previous subscriptions, just:<br> | or, to unsubscribe from all previous subscriptions, just:<br> | ||
<blockquote>UNSUBSCRIBE<br></blockquote> | <blockquote>UNSUBSCRIBE<br></blockquote> | ||
Line 73: | Line 77: | ||
e.g. | e.g. | ||
− | <blockquote>UNSUBSCRIBE<br>UNSUBSCRIBE 62<br>UNSUBSCRIBE 61<br></blockquote> | + | <blockquote>UNSUBSCRIBE<br>UNSUBSCRIBE 62<br>UNSUBSCRIBE 61<br></blockquote> |
+ | |||
= Discovery = | = Discovery = | ||
− | Although LPEC does not include a mechanism for discovering devices across a home network, it does contain a mechanism for | + | Although LPEC does not include a mechanism for discovering devices across a home network, it does contain a mechanism for discovering sub-devices within a single product.<br> |
− | When an LPEC connection is made, the device sends an ALIVE | + | When an LPEC connection is made, the device sends an ALIVE message for each sub-device that is currently enabled:<br> |
− | <blockquote>ALIVE | + | <blockquote>ALIVE [sub-device] [udn]<br></blockquote> |
− | e.g.<br> | + | e.g. (from a Sneaky Music DS)<br> |
<blockquote>ALIVE Ds 4c494e4e-0050-c221-71e5-df000003013f<br>ALIVE Preamp 4c494e4e-0050-c221-71e5-df0000030133<br>ALIVE MediaRenderer 4c494e4e-0050-c221-71e5-df0000030171</blockquote> | <blockquote>ALIVE Ds 4c494e4e-0050-c221-71e5-df000003013f<br>ALIVE Preamp 4c494e4e-0050-c221-71e5-df0000030133<br>ALIVE MediaRenderer 4c494e4e-0050-c221-71e5-df0000030171</blockquote> | ||
− | It is possible for these sub-devices to be disabled and enabled during the normal operation of a product. | + | It is possible for these sub-devices to be disabled and enabled during the normal operation of a product. If this occurs, further BYEBYE and ALIVE messages are issued accordingly. |
If a device is rebooted, the appropriate BYEBYE messages are sent and the LPEC connection is closed by the device. | If a device is rebooted, the appropriate BYEBYE messages are sent and the LPEC connection is closed by the device. | ||
− | When a sub-device is disabled, all subscriptions to the services on that sub-device are forcibly revoked. | + | When a sub-device is disabled, all subscriptions to the services on that sub-device are forcibly revoked. So, a BYEBYE message is commonly preceded by a number of unsolicited UNSUBSCRIBE messages. |
= Errors = | = Errors = | ||
Line 94: | Line 99: | ||
The following errors are defined:<br> | The following errors are defined:<br> | ||
<blockquote>ERROR 101 "Command not recognised"<br>ERROR 102 "Service not specified"<br>ERROR 103 "Service not found"<br>ERROR 104 "Version invalid"<br>ERROR 105 "Version not specified"<br>ERROR 106 "Version not supported"<br>ERROR 107 "Method not specified"<br>ERROR 108 "Method execution exception"<br>ERROR 201 "Boolean argument invalid"<br>ERROR 202 "String argument invalid"<br>ERROR 203 "Unsigned numeric argument invalid"<br>ERROR 204 "Signed numeric invalid"<br>ERROR 205 "Binary argument invalid"<br>ERROR 206 "Invalid argument escaping"<br>ERROR 301 "Argument list incomplete"<br>ERROR 302 "Argument not quoted"<br>ERROR 303 "Argument incomplete"<br>ERROR 401 "Already subscribed"<br>ERROR 402 "Client has too many subscriptions"<br>ERROR 403 "Service has too many subscriptions"<br>ERROR 404 "Subscription not found"<br>ERROR 405 "Service not subscribed"<br>ERROR 406 "Invalid XML escaping"<br></blockquote> | <blockquote>ERROR 101 "Command not recognised"<br>ERROR 102 "Service not specified"<br>ERROR 103 "Service not found"<br>ERROR 104 "Version invalid"<br>ERROR 105 "Version not specified"<br>ERROR 106 "Version not supported"<br>ERROR 107 "Method not specified"<br>ERROR 108 "Method execution exception"<br>ERROR 201 "Boolean argument invalid"<br>ERROR 202 "String argument invalid"<br>ERROR 203 "Unsigned numeric argument invalid"<br>ERROR 204 "Signed numeric invalid"<br>ERROR 205 "Binary argument invalid"<br>ERROR 206 "Invalid argument escaping"<br>ERROR 301 "Argument list incomplete"<br>ERROR 302 "Argument not quoted"<br>ERROR 303 "Argument incomplete"<br>ERROR 401 "Already subscribed"<br>ERROR 402 "Client has too many subscriptions"<br>ERROR 403 "Service has too many subscriptions"<br>ERROR 404 "Subscription not found"<br>ERROR 405 "Service not subscribed"<br>ERROR 406 "Invalid XML escaping"<br></blockquote> | ||
− | + | Service-specific ERROR messages may also be sent.<br> | |
+ | |||
+ | = Examples = | ||
+ | |||
+ | ==Transport state== | ||
+ | Play, Pause, Skip a DS player using the UPnP AVTransport service: | ||
+ | <blockquote>ACTION MediaRenderer/AVTransport 1 Play "0" "1"<br></blockquote><blockquote> | ||
+ | ACTION MediaRenderer/AVTransport 1 Pause "0"<br> | ||
+ | </blockquote><blockquote> | ||
+ | ACTION MediaRenderer/AVTransport 1 Next "0"<br> | ||
+ | </blockquote><blockquote> | ||
+ | ACTION MediaRenderer/AVTransport 1 Previous "0"<br> | ||
+ | </blockquote><blockquote></blockquote> | ||
+ | ==Volume state== | ||
+ | Get the volume of a Linn pre-amplifier using the Linn Preamp service | ||
+ | <blockquote>ACTION Preamp/Preamp 1 Volume</blockquote><blockquote> | ||
+ | RESPONSE "40" | ||
+ | </blockquote> | ||
+ | ==Mute== | ||
+ | Set mute on a Linn pre-amplifier using the Linn Preamp service | ||
+ | <blockquote>ACTION Preamp/Preamp 1 SetMute "true"</blockquote><blockquote> | ||
+ | RESPONSE | ||
+ | |||
+ | |||
+ | |||
+ | </blockquote> | ||
+ | ==Source selection== | ||
+ | Select an Input on the DS/DSI/DSM | ||
+ | <blockquote>'''ACTION Ds/Product 1 SetSourceIndex "0"'''<br></blockquote> | ||
+ | <span style="color:red"> | ||
+ | '''These input numbers are not guarenteed and may change with different versions of Linn firmware or if sources are disabled<br>''' | ||
+ | In Davaar50+ making sources invisible may change the ''' ''SourceIndex'' ''' number.<br>''' | ||
+ | You will better using the Sourcename or the Systemname: | ||
+ | |||
+ | ::'''Action Ds/Product 2 SetSourceBySystemName "Balanced"''' | ||
+ | :or | ||
+ | ::'''Action Ds/Product 2 SetSourceIndexByName "CD12"''' | ||
+ | to select the Balanced input use the name CD12 in Konfig Source Name | ||
+ | |||
+ | To find out the SourceIndex, Systemname and ByName use the | ||
+ | <blockquote> | ||
+ | :'''Action Ds/Product 2 Source "9"</blockquote>''' | ||
+ | With the value ('9' above) reports for SourceIndex 9, this has the following names. | ||
+ | |||
+ | |||
+ | System names and examples of Sourcenames | ||
+ | {| border ="1" cellspacing = "0" cellalign="center" cellpadding = "2" style="text-align:center; width:600px; background:#6699CC; color:white" | ||
+ | |-bgcolour=grey | ||
+ | ! SetSourceIndex !! '''SetSourceBySystemName''' !! Example SetSourceIndexByName | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | ! Can change !! Always fixed !! Adjusted by Konfig input name | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | 0 || Playlist || ''Playlist'' | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | 1 || Radio || ''Radio'' | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | 2 || Songcast || ''Songcast'' | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | 3 || NetAux || ''Airplay '' | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | 4 || UpnpAv || ''UpnpAv '' | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || Analog1 || ''Analog1'' | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || ..etc || ..etc | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || Phono || LP12 | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || Balanced || CD12 | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || Front Aux || iPod | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || HDMI1 || SKY | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || ..etc || ..etc | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || SPDIF1 || DAT Player | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || ..etc || ..etc | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || TOSLINK1 || CD Player | ||
+ | |-style="background:#FFFFCC; color:black" | ||
+ | | -- || ..etc || ..etc | ||
+ | |} | ||
+ | |||
+ | ==PIN selection== | ||
+ | Select a PIN on the DS/DSI/DSM | ||
+ | <blockquote>'''Action Ds/Pins 1 InvokeId "1"'''<br></blockquote> | ||
+ | <span style="color:red"> | ||
+ | '''These PIN numbers are not guarenteed and may change after a reboot if they have recently been altered<br>''' | ||
+ | The Linn DS/DSM requires '''Davaar 67+''' to get this LPEC function to work.<br>'''</span> | ||
+ | To get the contents of the PIN: | ||
+ | |||
+ | ::'''Action Ds/Pins 1 ReadList "[ 1]" | ||
+ | To find out the live PIN numbers | ||
− | + | ::'''Action Ds/Pins 1 GetIdArray''' | |
− | + | ==Detailed examples== | |
− | + | See attachment below for more detail: | |
+ | [http://docs.linn.co.uk/wiki/images/7/76/LPEC_V2-1.pdf LPEC examples] | ||
= Other Considerations<br> = | = Other Considerations<br> = | ||
− | If a control point closes an LPEC session, all outstanding subscriptions | + | If a control point closes an ''LPEC'' session, all outstanding subscriptions are automatically cleaned up by the device. |
+ | |||
+ | Each product supports only one concurrent ''LPEC'' session. | ||
+ | |||
+ | There is a bug which means that the '''first''' command sent after initial ALIVE messages are received will generate an error. All subsequent commands will work as expected. To work around this it is suggested that blank command is sent immediately after ALIVE messages ar received to clear this spurious error response. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | = Services and Actions Discovery = | ||
− | + | LPEC doesn't implement a service discovery protocol. | |
+ | |||
+ | The specific set of services and actions implemented on each device is dependent on the device type. The simplest method of determining which ACTIONs are available over LPEC is to ''discover''the services via UPnP which can then be trivially mapped onto LPEC ACTIONs. This can be done as follows: | ||
+ | |||
+ | * Use UPnP service discovery tools. (such as Intel's ''Device Spy'' or ''Device Monitor'' [http://www.intel.com/cd/ids/developer/asmo-na/eng/downloads/upnp/tools/index.htm Intel] [http://software.intel.com/en-us/articles/intel-software-for-upnp-technology-download-tools/?wapkw=%28UPnP+AV+media+tools+package%29 Intel tools] or [https://www.meshcommander.com/upnptools Open-Source Dev Tools]) | ||
+ | * Inspecting the device and service description directly from the device, (eg, a DS device on IP address 192.168.0.123:55178 is described by <pre>http://192.168.0.123:55178/Ds/device.xml</pre>From this description we can (for example) see that the device has a "Media" service, which is described here, <pre>http://192.168.0.123:55178/Ds/Media/service.xml</pre> | ||
+ | * ...or if you know the device type, you can inspect the published service description online. | ||
+ | |||
+ | <!--UPnP documentation for the Linn DS products can be found in [http://www.openhome.org/wiki/OhMediaDevelopers Openhone.org]---> | ||
+ | |||
+ | =[https://docs.linn.co.uk/wiki/images/3/32/LPEC_V2-5.pdf LPEC Examples]= | ||
+ | |||
+ | = Command Summary<br> = | ||
+ | |||
+ | [https://docs.linn.co.uk/wiki/images/3/32/LPEC_V2-5.pdf LPEC examples] | ||
+ | |||
+ | <u>[https://www.dropbox.com/scl/fi/j9ahh8b2nsxqs3o9zpetz/LPEC-Terminal-V9.01.zip?rlkey=1aitbcne35q4pfcmoouog2pkh&dl=0 LINK to Developers LPEC Terminal]</u> This is a Windows10 app used in comms for development | ||
+ | == Sent<br> == | ||
+ | |||
+ | {| cellspacing="1" cellpadding="1" border="1" style="width: 730px; height: 132px;" | ||
+ | |- | ||
+ | | '''Invoke Action''' | ||
+ | | ACTION [sub-device]/[service] [version] [action] "[inarg1]" "[inarg2]" ... "[inargn]"<br> | ||
+ | |- | ||
+ | | '''Subscribe Service<br>''' | ||
+ | | SUBSCRIBE [sub-device]/[service] | ||
+ | |- | ||
+ | | '''Unsubscribe Id<br>''' | ||
+ | | UNSUBSCRIBE [subscription-id]<br> | ||
+ | |- | ||
+ | | '''Unsubscribe Service''' | ||
+ | | UNSUBSCRIBE [sub-device]/[service]<br> | ||
+ | |- | ||
+ | | '''Unsubscribe All'''<br> | ||
+ | | UNSUBSCRIBE<br> | ||
+ | |} | ||
+ | |||
+ | == Received<br> == | ||
+ | |||
+ | {| width="730" cellspacing="1" cellpadding="1" border="1" align="left" style="" | ||
+ | |- | ||
+ | | '''Action Response<br>''' | ||
+ | | RESPONSE "[outarg1]" "[outarg2]" ... "[outargn]"<br> | ||
+ | |- | ||
+ | | '''Subscribe Response<br>''' | ||
+ | | SUBSCRIBE [subscription-id]<br> | ||
+ | |- | ||
+ | | '''Initial Event<br>''' | ||
+ | | EVENT [subscription-id] 0 [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]"<br> | ||
+ | |- | ||
+ | | '''Event<br>''' | ||
+ | | EVENT [subscription-id] [sequence-no] [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]"<br> | ||
+ | |- | ||
+ | | '''Unsubscribe Response<br>''' | ||
+ | | UNSUBSCRIBE [subscription-id]<br> | ||
+ | |- | ||
+ | | '''Sub-Device Enabled<br>''' | ||
+ | | ALIVE [sub-device] [udn]<br> | ||
+ | |- | ||
+ | | '''Sub-Device Disabled<br>''' | ||
+ | | BYEBYE [sub-device] [udn]<br> | ||
+ | |- | ||
+ | | '''Error'''<br> | ||
+ | | ERROR [code] "[description]"<br> | ||
+ | |} | ||
+ | <br><br> | ||
+ | |||
+ | |||
+ | <br> |
Latest revision as of 09:54, 16 October 2023
Contents
Introduction
This article describes the Linn Protocol for Eventing and Control (LPEC), which is a TCP/IP point-2-point protocol that can be used to control Linn's home network products (e.g. DS players).
The primary means of control for such products is, of course, UPnP. But LPEC provides an alternative mechanism for accessing UPnP services over a basic "telnet-like" protocol.
The UPnP architecture subdivides product control into smaller named units called "services". A DS player, for instance, provides some standard UPnP AV services:
- AVTransport
- RenderingControl
- ConnectionManager
and additional Linn-specific services, such as:
- Playlist
- Radio
- Product
By opening a raw TCP/IP socket connection to port 23 on a Bute (or later) home network product, these same services can be controlled using LPEC.
The rest of this article describes the format of the messages that LPEC expects and delivers. Examples are given.
Connection
LPEC can be accessed by connecting a raw socket session to port 23 on the device.
The Linn DS can only support up to 4 simultaneous sessions. If there are more than 4sessions open at the same time, the DS will ignore any commands from these new sessions, but remain in full control by the first 4 sessions.
It has been noted that some Crestron processors will re-open TELNET ports without closing existing ones. So it is recommend that on any control device, if the Touchpanel is asleep the TELNET connection is closed.
Control
Each service contains actions, which are like methods that can be called on the device with input and output arguments.
An action can be perfomed by sending a message of the following form:
ACTION [sub-device]/[service] [version] [action] "[inarg1]" "[inarg2]" ... "[inargn]"
e.g.
ACTION MediaRenderer/RenderingControl 1 SetVolume "0" "Master" "50"
All messages sent using LPEC get a response. The response to an ACTION message is a RESPONSE message that reports the values of all the output arguments:
RESPONSE "[outarg1]" "[outarg2]" ... "[outargn]"
The SetVolume example given above has no output arguments, so the message received will simply be a <CR><LF> terminated RESPONSE message.
The following subsequent interaction better illustrates the RESPONSE message:
ACTION MediaRenderer/RenderingControl 1 GetVolume "0" "Master"
RESPONSE "50"
It should be mentioned that all input and output arguments are escaped according to XML escaping rules and enclosed in double-quotes.
Eventing
In order to subscribe to a service's events, issue a SUBSCRIBE message of the following form:
SUBSCRIBE [sub-device]/[service]
The device responds with:
SUBSCRIBE [subscription-id]
and follows this with an initial event message, which contains the current state of all the service's evented variables:
EVENT [subscription-id] 0 [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]"
e.g
SUBSCRIBE Ds/Product
SUBSCRIBE 49
EVENT 49 0 ProductName "Sneaky Music DS" ProductRoom "Main Room" ProductStandby "true" ProductSourceIndex "0"
Subsequent changes to the service's evented variables cause unsolicited EVENT messages to be sent from the device as follows:
EVENT [subscription-id] [sequence-no] [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]"
Only those variables that have changed are reported.
The sequence number is a 32-bit unsigned number which increments with each event message and wraps around to 1.
A sequence number of 0 is reserved for the initial EVENT message, which contains the current state of all the service's evented variables (see above)
By issuing multiple SUBSCRIBE messages, it is possible to subscribe to up to 16 services simultaneously.
In order to unsubscribe from a service, send an UNSUBSCRIBE message of the form:
UNSUBSCRIBE [subscription-id]
alternatively:
UNSUBSCRIBE [sub-device]/[service]
or, to unsubscribe from all previous subscriptions, just:
UNSUBSCRIBE
In all instances, the response will be:
UNSUBSCRIBE [subscription-id]
When using the form that unsubscribes from all previous subscriptions, multiple UNSUBSCRIBE responses may be received.
e.g.
UNSUBSCRIBE
UNSUBSCRIBE 62
UNSUBSCRIBE 61
Discovery
Although LPEC does not include a mechanism for discovering devices across a home network, it does contain a mechanism for discovering sub-devices within a single product.
When an LPEC connection is made, the device sends an ALIVE message for each sub-device that is currently enabled:
ALIVE [sub-device] [udn]
e.g. (from a Sneaky Music DS)
ALIVE Ds 4c494e4e-0050-c221-71e5-df000003013f
ALIVE Preamp 4c494e4e-0050-c221-71e5-df0000030133
ALIVE MediaRenderer 4c494e4e-0050-c221-71e5-df0000030171
It is possible for these sub-devices to be disabled and enabled during the normal operation of a product. If this occurs, further BYEBYE and ALIVE messages are issued accordingly.
If a device is rebooted, the appropriate BYEBYE messages are sent and the LPEC connection is closed by the device.
When a sub-device is disabled, all subscriptions to the services on that sub-device are forcibly revoked. So, a BYEBYE message is commonly preceded by a number of unsolicited UNSUBSCRIBE messages.
Errors
After sending an ACTION, SUBSCRIBE, or UNSUBSCRIBE message, it is possible to receive an ERROR message of the form:
ERROR [code] "[description]"
The following errors are defined:
ERROR 101 "Command not recognised"
ERROR 102 "Service not specified"
ERROR 103 "Service not found"
ERROR 104 "Version invalid"
ERROR 105 "Version not specified"
ERROR 106 "Version not supported"
ERROR 107 "Method not specified"
ERROR 108 "Method execution exception"
ERROR 201 "Boolean argument invalid"
ERROR 202 "String argument invalid"
ERROR 203 "Unsigned numeric argument invalid"
ERROR 204 "Signed numeric invalid"
ERROR 205 "Binary argument invalid"
ERROR 206 "Invalid argument escaping"
ERROR 301 "Argument list incomplete"
ERROR 302 "Argument not quoted"
ERROR 303 "Argument incomplete"
ERROR 401 "Already subscribed"
ERROR 402 "Client has too many subscriptions"
ERROR 403 "Service has too many subscriptions"
ERROR 404 "Subscription not found"
ERROR 405 "Service not subscribed"
ERROR 406 "Invalid XML escaping"
Service-specific ERROR messages may also be sent.
Examples
Transport state
Play, Pause, Skip a DS player using the UPnP AVTransport service:
ACTION MediaRenderer/AVTransport 1 Play "0" "1"
ACTION MediaRenderer/AVTransport 1 Pause "0"
ACTION MediaRenderer/AVTransport 1 Next "0"
ACTION MediaRenderer/AVTransport 1 Previous "0"
Volume state
Get the volume of a Linn pre-amplifier using the Linn Preamp service
ACTION Preamp/Preamp 1 Volume
RESPONSE "40"
Mute
Set mute on a Linn pre-amplifier using the Linn Preamp service
ACTION Preamp/Preamp 1 SetMute "true"
RESPONSE
Source selection
Select an Input on the DS/DSI/DSM
ACTION Ds/Product 1 SetSourceIndex "0"
These input numbers are not guarenteed and may change with different versions of Linn firmware or if sources are disabled
In Davaar50+ making sources invisible may change the SourceIndex number.
You will better using the Sourcename or the Systemname:
- Action Ds/Product 2 SetSourceBySystemName "Balanced"
- or
- Action Ds/Product 2 SetSourceIndexByName "CD12"
to select the Balanced input use the name CD12 in Konfig Source Name
To find out the SourceIndex, Systemname and ByName use the
- Action Ds/Product 2 Source "9"
With the value ('9' above) reports for SourceIndex 9, this has the following names.
System names and examples of Sourcenames
SetSourceIndex | SetSourceBySystemName | Example SetSourceIndexByName |
---|---|---|
Can change | Always fixed | Adjusted by Konfig input name |
0 | Playlist | Playlist |
1 | Radio | Radio |
2 | Songcast | Songcast |
3 | NetAux | Airplay |
4 | UpnpAv | UpnpAv |
-- | Analog1 | Analog1 |
-- | ..etc | ..etc |
-- | Phono | LP12 |
-- | Balanced | CD12 |
-- | Front Aux | iPod |
-- | HDMI1 | SKY |
-- | ..etc | ..etc |
-- | SPDIF1 | DAT Player |
-- | ..etc | ..etc |
-- | TOSLINK1 | CD Player |
-- | ..etc | ..etc |
PIN selection
Select a PIN on the DS/DSI/DSM
Action Ds/Pins 1 InvokeId "1"
These PIN numbers are not guarenteed and may change after a reboot if they have recently been altered
The Linn DS/DSM requires Davaar 67+ to get this LPEC function to work.
To get the contents of the PIN:
- Action Ds/Pins 1 ReadList "[ 1]"
To find out the live PIN numbers
- Action Ds/Pins 1 GetIdArray
Detailed examples
See attachment below for more detail: LPEC examples
Other Considerations
If a control point closes an LPEC session, all outstanding subscriptions are automatically cleaned up by the device.
Each product supports only one concurrent LPEC session.
There is a bug which means that the first command sent after initial ALIVE messages are received will generate an error. All subsequent commands will work as expected. To work around this it is suggested that blank command is sent immediately after ALIVE messages ar received to clear this spurious error response.
Services and Actions Discovery
LPEC doesn't implement a service discovery protocol.
The specific set of services and actions implemented on each device is dependent on the device type. The simplest method of determining which ACTIONs are available over LPEC is to discoverthe services via UPnP which can then be trivially mapped onto LPEC ACTIONs. This can be done as follows:
- Use UPnP service discovery tools. (such as Intel's Device Spy or Device Monitor Intel Intel tools or Open-Source Dev Tools)
- Inspecting the device and service description directly from the device, (eg, a DS device on IP address 192.168.0.123:55178 is described by
http://192.168.0.123:55178/Ds/device.xml
From this description we can (for example) see that the device has a "Media" service, which is described here,http://192.168.0.123:55178/Ds/Media/service.xml
- ...or if you know the device type, you can inspect the published service description online.
LPEC Examples
Command Summary
LINK to Developers LPEC Terminal This is a Windows10 app used in comms for development
Sent
Invoke Action | ACTION [sub-device]/[service] [version] [action] "[inarg1]" "[inarg2]" ... "[inargn]" |
Subscribe Service |
SUBSCRIBE [sub-device]/[service] |
Unsubscribe Id |
UNSUBSCRIBE [subscription-id] |
Unsubscribe Service | UNSUBSCRIBE [sub-device]/[service] |
Unsubscribe All |
UNSUBSCRIBE |
Received
Action Response |
RESPONSE "[outarg1]" "[outarg2]" ... "[outargn]" |
Subscribe Response |
SUBSCRIBE [subscription-id] |
Initial Event |
EVENT [subscription-id] 0 [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]" |
Event |
EVENT [subscription-id] [sequence-no] [var1-name] "[var1]" [var2-name] "[var2]" ... [varn-name] "[varn]" |
Unsubscribe Response |
UNSUBSCRIBE [subscription-id] |
Sub-Device Enabled |
ALIVE [sub-device] [udn] |
Sub-Device Disabled |
BYEBYE [sub-device] [udn] |
Error |
ERROR [code] "[description]" |