Once started with ag_start_remotecontrol_loop
the WebSocket connection will be re-connected automatically if it drops. Additionally "ping" messages will be sent automatically every 30 seconds to prevent idle timeouts.
The Audiogum Remote Control system provides the means to control a connected device via a long-standing WebSocket connection over the internet.
Example use cases:
This document provides integration guidance in two parts:
The command message vocabulary for Remote Control is described separately here: Remote Control Commands
To secure the control of the device and to protect the user's privacy, the Audiogum Remote Control system operates as follows:
The remotecontrol token requirements ensure that no controller client can issue commands to the wrong device, either maliciously or accidentally, for example by enumerating other device identifiers such as MAC addresses or serial numbers. The remotecontrol token contains encrypted data about the device and is also random such that it will not be the same if generated again, even for the same device.
This also provides a means to revoke remote control access from any previous users or controlling apps simply by refreshing the remotecontrol token on the device. This could be done on factory reset for example.
The general approach to integrating Remote Control in device firmware is as follows:
The Audiogum Embedded C SDK (libaudiogum) provides much of the necessary plumbing, but any client platform capable of making secure WebSocket connections and handling JSON data can use the Web APIs directly. Both approaches are included here for reference.
A remotecontrol token is requested automatically (if one is not already stored) and persisted at a file location specified, when calling ag_start_remotecontrol_loop
A remotecontrol token can be obtained using the main Audiogum REST API by POST /v1/remotecontrol/tokens
. There is no need for a body in this request, but a device access token is required.
POST /v1/remotecontrol/tokens
Authorization: Bearer {access_token}
Example response:
{
"remotecontroltoken": "v1::dSxwOotdwTT3nCQ5MPx4mg==::FOHfjq1g5BE0byibonVtDYNTE38asbPXuHwbXN+Kp1IF+46A4i/WCaN1O+VPNGTyvAWnYcBF2gSXeitp0KUx2VGQiY2ZP2h9Vt7Eme+HPjE="
}
The device should only make this request once and then persist the remotecontrol token for future use, otherwise controlling apps that have been granted access will lose it.
A connection is made by calling ag_start_remotecontrol_loop
To make the connection, make a WebSocket upgrade request to wss://remote.audiogum.com/v1/remotecontrol
. The following parameters must be provided, either as HTTP headers or query string parameters:
Header | Query string parameter | Example |
---|---|---|
Authorization | access_token | Authorization: Bearer v1::YIiKfEuko4wOXS... ?access_token=v1::YIiKfEuko4wOXS... |
remotecontroltoken | remotecontroltoken | remotecontroltoken: v1::dSxwOotdwTT3nCQ5MP... &remotecontroltoken=v1::dSxwOotdwTT3nCQ5MP... |
capabilities | capabilities | capabilities: play,stop,skipnext,skipprev &capabilities=play,stop,skipnext,skipprev |
If using query parameters don't forget the URL-encode the tokens.
The capabilities
parameter specified when making the connection indicates to the service which features the device can support. This is to allow controlling applications to know what kind of commands can be sent.
Capabilities must include all action
values that the device supports. See Remote Control Commands for full command message vocabulary, intended behaviour and guidance for implementation.
Capabilities must also specify the types of playback that a device supports. This could include one or all of the following: http
, https
, applesdk
. http
and https
indicate that the device is capable of streaming playback from http or https streamurls returned by audiogum, applesdk
indicates that the device can handle apple music refs using MusicKit (this is only relevant for iOS devices).
Additional special features that are not represented as action
values may also require capability values. For example the capability value expectreply
enables additional conversation features for Natural Language Understanding.
The actions_understood
parameter for ag_start_remotecontrol_loop
must be provided as an AG_ACTION
bit flag, similarly with the optional voice_capabilities
parameter.
For web socket connections, the capabilities
header or query parameter as described above takes a comma separated list of all the action
values that the device implements. For the REST API, a json string array is sent.
Once connected, the device may receive TEXT messages from the WebSocket. These are command messages as described in Remote Control Commands. Note that some of these require responses to be sent back to the service.
ag_start_remotecontrol_loop
requires a callback function pointer action_callback
. This must implement the intended behaviour and/or return appropriate response data.
When implementing directly against the WebSocket API, each command is received as an individual TEXT message, in JSON form, as described in Remote Control Commands. Responses, if required, should be sent similarly as JSON formatted TEXT messages on the same WebSocket.
To ensure the device can receive commands at any time, it should automatically attempt to re-connect whenever the WebSocket connection is closed. This can happen for a variety of reasons, either automatically due to idle timeouts or due to temporary network connectivity issues.
To prevent idle timeouts closing the connection and potentially missing commands whilst re-connecting, we also advise that devices send a "ping" message to the service every 30 seconds.
Once started with ag_start_remotecontrol_loop
the WebSocket connection will be re-connected automatically if it drops. Additionally "ping" messages will be sent automatically every 30 seconds to prevent idle timeouts.
When implementing directly against the WebSocket API, devices should re-connect in the same way as described above if the connection drops.
To implement the "ping" message, send a TEXT message on the WebSocket in JSON form as follows:
{"type":"ping"}
The service will respond with a TEXT message contining an empty JSON object which may be ignored:
{}
To revoke remote access from all users/apps who have previously been granted access, simply delete the remotecontrol token, request and persist a new one for subsequent connections.
In the case of using libaudiogum, this can be done by calling ag_delete_remote_control_token
and then cancelling and re-starting the remote control loop.
It is recommended that on factory reset a device should revoke remote control access, either by simply wiping the appropriate part of the file system or as described above.
Audiogum Remote Control service provides REST API features for controller apps and services to send commands to and receive state data from device clients.
To use these features requires user authentication as described on the authentication page and knowledge of the remotecontrol token of the target device.
API | Purpose |
---|---|
HEAD /v1/user/remotecontrol | Check whether a device is currently connected |
GET /v1/user/remotecontrol | Get details of connected device including capabilities |
POST /v1/user/remotecontrol/commands | Send commands to a device |
GET /v1/user/remotecontrol/state/{type} | Get state data from a device |
Example request:
HEAD /v1/user/remotecontrol?remotecontroltoken=v1::X28+U9f98YDX4...
Authorization: Bearer {access_token}
Response if device connected:
204 No Content
or if not:
404 Not Found
Example request:
GET /v1/user/remotecontrol?remotecontroltoken=v1::X28+U9f98YDX4...
Authorization: Bearer {access_token}
Response:
200 OK
{
"deviceid": "abc123xyz",
"capabilities": ["play", "stop"]
}
Example request:
POST /v1/user/remotecontrol/commands
Authorization: Bearer {access_token}
{
"remotecontroltoken": "v1::X28+U9f98YDX4...",
"command": {
"action": "stop"
}
}
The command
object represents the command message sent to the device via its WebSocket connection and should be formed as described on the Remote Control Commands page.
Response:
202 No Content
GET /v1/user/remotecontrol/state/player?remotecontroltoken=v1::X28+U9f98YDX4...
Authorization: Bearer {access_token}
Response:
200 OK
{
"type": "player",
"playstate": "playing",
"source": "playable",
"presetnumber": 1,
"offset": 45,
"playable": { ... },
"item": { ... },
"volume": {
"value": 30,
"mute": false
}
}
The type
part of the request (e.g. player
) maps to a "get" command with an action such as getplayer
sent to the device via its WebSocket connection as described on the Remote Control Commands page. The service waits for a response from the device before returning the result to the client.
We have a demo web player to help test integrations.