RPC Device Control Protocol
1. Purpose of this document
This document is intended for developers of third-party central control systems, integration platforms, and operation tools. It explains the two device control methods currently supported by this system:
- Server-forwarded RPC: the Admin End sends commands through the cloud server or a private deployment server, which then forwards them to the target device
- UDP direct control: a third-party controller sends UDP commands directly to the device's LAN address
This document only describes protocol capabilities that are already implemented and can be confirmed in the current codebase. It does not extend to control methods that have not been implemented.
2. Protocol overview
2.1 Two transport paths
This system currently supports two device control paths:
Server-forwarded RPC
The Admin End first calls the server API, and the server then forwards the command to the device.UDP direct control
A third-party controller sends commands directly to the device's locally exposed UDP port without going through the server.
These two methods share the same business-level command payload. The difference is only in the transport layer:
- HTTP RPC goes through the server or the device's local HTTP service
- UDP goes through the device's local UDP port
2.2 Unified business payload
All device control commands use the same RpcCmd JSON payload:
{
"method": "getPlayerStatus",
"params": {
"t": "q",
"idx": 1,
"p": null,
"v": null
}
}Field description:
method: command nameparams.t: message typeparams.idx: optional request sequence number, useful for matching requests and responsesparams.p: deprecated and not recommendedparams.v: business parameter or business return value
Current meanings of params.t:
q: requests: success responsese: business failure responsesd: processed response, mainly used for internal forwarding confirmation and usually not needed by third parties
Third-party integrations are recommended to rely only on these core fields:
methodparams.tparams.idxparams.v
3. Server-forwarded RPC
3.1 Cloud two-way RPC
This is suitable for cloud publishing or cloud-based private deployment scenarios.
- Endpoint:
POST https://api.example.com:9292/api/rpc/twoway/{deviceId} - Authentication:
X-Authorization: Bearer <jwt> - Description: the Admin End sends the command to the server, the server forwards it to the target device, and then waits for the device to return the business result
Best for:
- Querying device status
- Taking screenshots
- Getting logs
- Modifying settings
3.2 Cloud one-way RPC
- Endpoint:
POST https://api.example.com:9292/api/rpc/oneway/{deviceId} - Authentication:
X-Authorization: Bearer <jwt> - Description: sends the command only and does not wait for a business response from the device
Best for:
- Batch refresh operations
- Best-effort central control commands
3.3 Private deployment / LAN HTTP direct access
This is suitable when the Admin End and the device are in the same LAN, or in a private deployment environment where the device's local HTTP service can be reached directly.
- Login endpoint:
POST http://192.168.1.100:9393/api/nauth/login - RPC endpoint:
POST http://192.168.1.100:9393/api/device/rpc/{deviceId} - Authentication:
X-Authorization: Bearer <token>
Notes:
- The default port of the device's local HTTP service is
9393 - After a successful LAN login, the device returns a local JWT
- All later
/api/*requests must carry that JWT
3.4 Authentication methods
Cloud / private-deployment Admin End
Cloud RPC uses the Admin End JWT. Example request header:
X-Authorization: Bearer eyJhbGciOi...Notes:
X-Authorizationis the header currently used by the client by default- The server is also compatible with
Authorization - JWT acquisition follows the same login system as the Admin End, and the login flow itself is not expanded in this document
Device local HTTP service
The LAN service provides a login endpoint without a prior auth token:
POST http://192.168.1.100:9393/api/nauth/login
Content-Type: application/json
{
"username": "admin",
"password": "your-local-password"
}Success example:
{
"token": "eyJhbGciOi..."
}Example of the later request header:
X-Authorization: Bearer eyJhbGciOi...3.5 Common HTTP responses
Cloud RPC
200 OK: the request was delivered successfully, and the two-way RPC already received the device response401 Unauthorized: not logged in, or the token is invalid403 Forbidden: logged in, but not allowed to operate this device504 Gateway Timeout: the device is offline, timed out, or did not return in time
Device local HTTP RPC
200 OK: the HTTP layer call succeeded; business success should still be determined byparams.t401 Unauthorized: a valid JWT was not provided
Recommendation for business result checks
When integrating, do not look only at the HTTP status code. Also check:
params.t == "s": business succeededparams.t == "se": business failed
3.6 About additional server-side fields
Cloud /api/rpc/twoway/* and /api/rpc/oneway/* server-forwarded RPC implementations may also support top-level fields such as timeout, persistent, expirationTime, retries, and additionalInfo.
However, to stay compatible with both cloud mode and LAN mode, third parties should by default send only the business payload described in this document:
methodparams
Unless the deployment side has explicitly confirmed that the environment is cloud-only, it is not recommended to depend on cloud-specific persistent RPC fields.
4. UDP direct control
4.1 When to use it
UDP is a device-local control entry point exposed directly by the device, without going through the cloud server or a private deployment server.
A third-party controller can send UDP datagrams directly to the device's LAN address, for example:
192.168.1.120:9393
This is more suitable for central control devices, control hosts, or LAN automation systems.
4.2 Listening port
The device's local UDP service uses the same port as the local HTTP service:
9393
So a third-party controller only needs the device's LAN IP and port to start control.
4.3 UDP packet format
The business content transmitted through UDP is still the same RpcCmd JSON.
Example:
{
"method": "ping",
"params": {
"t": "q",
"idx": 1001,
"p": null,
"v": null
}
}Notes:
- The UDP request payload is exactly the same as the
datacontent used by HTTP RPC - The UDP response payload is still
RpcCmdJSON - The device sends the response back to the sender's source address and source port
- UDP mode does not require a
deviceIdURL and does not go through server routing
4.4 Security boundary
The current UDP receiving path does not show an extra HTTP/JWT authentication layer, so it should only be treated as a trusted LAN internal protocol.
Strong recommendations:
- Use it only inside a trusted local network
- Do not expose it to the public Internet
- Do not expose this port through public network penetration tools
4.5 Recommended use for central control systems
For third-party central control integration, UDP direct control is the preferred option.
Recommended small-payload, low-latency commands over UDP:
pingremoterupdate_castgetPlayerStatus
Recommended larger-payload or more response-dependent capabilities over HTTP RPC:
getScreenshotgetLog
Notes:
- These are recommendations, not implementation limits
- Some commands may also work over UDP in theory, but from an engineering stability perspective, it is not recommended to rely on UDP long term for large responses
5. Unified command reference
Only commands that are clearly implemented on the device side and are suitable for third-party use are listed below.
5.1 Basic connectivity
| Method | Request params.v | Response params.v | Description |
|---|---|---|---|
ping | null | "pong" | Connectivity check |
5.2 Status and diagnostics
| Method | Request params.v | Response params.v | Description |
|---|---|---|---|
getPlayerStatus | null | Map | Query the current device status |
getScreenshot | null or int | String | Returns a Base64 screenshot; if an integer is passed, it means the maximum target size in bytes, with a default around 49000 |
getLog | {"count": 100, "textSearch": "error"} | {"log": "..."} | Get device logs, supporting line count and keyword filtering |
clearLog | null | "OK" | Clear device logs |
getAuthLoc | null | {"authToken": "..."} | Get local device authorization information, mainly for LAN-related capabilities |
Common fields in the getPlayerStatus response:
ver: app version on the device sideinfo: device summary informationcurTs: current device timestampcurMHCast: current program summarycurPlay: current playback relation informationtaskLen: current schedule lengthplayTaskList: first several items in the current schedulehttpServerInfo: information about the device's local HTTP service
5.3 User interaction / central control keys
| Method | Request params.v | Response params.v | Description |
|---|---|---|---|
remoter | String | true | Inject a remote-control or key event into the device |
Currently recommended stable remoter key values:
- Direction keys:
updownleftright - Confirm / back:
selectback - Number keys:
0to9 - Fast forward / rewind:
forwardbackward
Notes:
- These values are converted on the device side into standard keyboard semantics such as direction keys, back key, and number keys
- Other custom strings may also be accepted by the event pipeline, but third parties should not depend on undocumented custom key values
5.4 Settings and execution
| Method | Request params.v | Response params.v | Description |
|---|---|---|---|
getSettings | "key" | Any type | Read a single setting item |
setSettings | {"key": value} | true/false | Write one or more setting items in batch |
execCmd | {"method": "xxx", "params": ...} | Any type | Call a registered execution command exposed by the device-side settings module |
Notes:
getSettingsusually receives a single key name inparams.vsetSettingssupports submitting multiple key-value pairs at onceexecCmdis suitable for action-style commands exposed by the settings module; the exactmethodvalue should be confirmed by the deployment side
5.5 Playback refresh and upgrade
| Method | Request params.v | Response params.v | Description |
|---|---|---|---|
update_cast | null, {"force": true}, or "updateAuth" | "OK" | Refresh the program schedule and support forced refresh |
updateDevice | null | "OK" | Refresh device information |
installApp | {"url": "...", "desc": "..."} | "OK" | Trigger package download and installation on the device, usually for Android terminals |
Notes:
- The most common usage of
update_castisnullor{"force": true} installApponly starts the installation flow; final success still depends on the device platform, download URL, and installation permissions
5.6 Advanced editing commands
| Method | Request params.v | Response params.v | Description |
|---|---|---|---|
editCast | Program JSON or patch JSON | true | Modify program content remotely |
editMedia | Media patch JSON | true | Modify parameters of a specific media item inside a program remotely |
Notes:
- These two commands directly modify program data
editCastsupports full overwrite and also a recursive patch mode witheditMode = "patch"editMediadepends on the internal media structure of the program and usually requires an accurateeidor target program context- These two commands are recommended only for deep integrations and are not recommended as the base capability of a general central control protocol
6. Reserved / internal commands
The following constants exist in the code, but are currently not recommended as public stable interfaces for third parties:
getDeviceSelfgetMHCastRelationListpostAttrslanAuthjumpTomhtRpcsyncdeleteDeviceBySelfpostSyncInfo
Common reasons include:
- They are only used by internal device-side flows or debug flows
- Their parameter structure is tightly coupled to internal implementation
- They are more likely to change in the future and are not suitable as a stable commitment for a third-party central control protocol
7. Call examples
7.1 Query device status through cloud RPC
curl -X POST "https://api.example.com:9292/api/rpc/twoway/11111111-2222-3333-4444-555555555555" \
-H "Content-Type: application/json" \
-H "X-Authorization: Bearer <jwt>" \
-d '{
"method": "getPlayerStatus",
"params": {
"t": "q",
"idx": 1,
"p": null,
"v": null
}
}'Example response:
{
"method": "getPlayerStatus",
"params": {
"t": "s",
"idx": 1,
"p": null,
"v": {
"ver": "1.2.3",
"info": "Device-A / Android",
"curTs": 1775179200000,
"taskLen": 6,
"httpServerInfo": {
"state": 1,
"localAddr": "http://192.168.1.120:9393"
}
}
}
}7.2 Send a back key through cloud RPC
curl -X POST "https://api.example.com:9292/api/rpc/twoway/11111111-2222-3333-4444-555555555555" \
-H "Content-Type: application/json" \
-H "X-Authorization: Bearer <jwt>" \
-d '{
"method": "remoter",
"params": {
"t": "q",
"idx": 2,
"p": null,
"v": "back"
}
}'7.3 Get a screenshot through cloud RPC
curl -X POST "https://api.example.com:9292/api/rpc/twoway/11111111-2222-3333-4444-555555555555" \
-H "Content-Type: application/json" \
-H "X-Authorization: Bearer <jwt>" \
-d '{
"method": "getScreenshot",
"params": {
"t": "q",
"idx": 3,
"p": null,
"v": 49000
}
}'If successful, params.v contains a Base64 image string.
7.4 Get logs through cloud RPC with keyword filtering
curl -X POST "https://api.example.com:9292/api/rpc/twoway/11111111-2222-3333-4444-555555555555" \
-H "Content-Type: application/json" \
-H "X-Authorization: Bearer <jwt>" \
-d '{
"method": "getLog",
"params": {
"t": "q",
"idx": 4,
"p": null,
"v": {
"count": 100,
"textSearch": "error"
}
}
}'7.5 Modify settings through cloud RPC
curl -X POST "https://api.example.com:9292/api/rpc/twoway/11111111-2222-3333-4444-555555555555" \
-H "Content-Type: application/json" \
-H "X-Authorization: Bearer <jwt>" \
-d '{
"method": "setSettings",
"params": {
"t": "q",
"idx": 5,
"p": null,
"v": {
"debugMode": 1,
"httpServerEnable": true
}
}
}'7.6 Log in over LAN and call device HTTP RPC
Log in first:
curl -X POST "http://192.168.1.100:9393/api/nauth/login" \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"password": "your-local-password"
}'Then call the RPC:
curl -X POST "http://192.168.1.100:9393/api/device/rpc/11111111-2222-3333-4444-555555555555" \
-H "Content-Type: application/json" \
-H "X-Authorization: Bearer <token>" \
-d '{
"method": "ping",
"params": {
"t": "q",
"idx": 6,
"p": null,
"v": null
}
}'7.7 Send ping over UDP direct control
Send a UDP datagram to the device, for example 192.168.1.120:9393, with this payload:
{
"method": "ping",
"params": {
"t": "q",
"idx": 1001,
"p": null,
"v": null
}
}Example response:
{
"method": "ping",
"params": {
"t": "s",
"idx": 1001,
"p": null,
"v": "pong"
}
}7.8 Send a back key over UDP direct control
Example payload sent to 192.168.1.120:9393:
{
"method": "remoter",
"params": {
"t": "q",
"idx": 1002,
"p": null,
"v": "back"
}
}7.9 Query device status over UDP direct control
Example payload sent to 192.168.1.120:9393:
{
"method": "getPlayerStatus",
"params": {
"t": "q",
"idx": 1003,
"p": null,
"v": null
}
}8. Optional one-way batch broadcast
If a third-party platform needs to broadcast the same command to a group of devices, it can use the extended interfaces provided by the Admin End.
Supported endpoints:
POST https://api.example.com:9292/api/mht/oneway/device/ids?ids=<id1>,<id2>POST https://api.example.com:9292/api/mht/oneway/asset/ids?ids=<assetId1>,<assetId2>POST https://api.example.com:9292/api/mht/oneway/customer/ids?ids=<customerId1>,<customerId2>POST https://api.example.com:9292/api/mht/oneway/tenant
Notes:
- The request body is still the same
RpcCmdJSON - These interfaces are one-way broadcasts and do not return a business result for each device
- They are suitable for batch triggering
update_cast, refreshing status, or sending simple control commands
9. Recommendations for third-party integration
9.1 Recommended priority
- For third-party central control, prefer UDP direct control
- For device status queries, prefer
getPlayerStatus - For central control key events, prefer
remoter - For schedule refresh, prefer
update_cast - For screenshots and logs, prefer HTTP RPC
9.2 Stability recommendations
- Include
idxin every request to make logs and callbacks easier to reconcile - Treat
params.t == "s"as the business success condition; do not rely only on HTTP 200 - Use only the stable
remoterkey values listed in this document - Open
editCastandeditMediaonly after joint debugging and verification - In cloud mode, prefer
twowayso the caller can receive explicit feedback - Do not rely on UDP long term for large response payloads
9.3 Security recommendations
- Do not store high-privilege JWTs in plain text in third-party systems for long periods
- If only part of the devices need control, use an account with the minimum required permissions
- Device installation and program editing commands should be covered by operation auditing
- The UDP port should only be exposed inside a trusted LAN
10. Version note
This document is compiled based on the actual implementation of the current management side, device side, and local HTTP / UDP services in this repository.
If you need to integrate commands not listed here, confirm the target version and available scope with the deployment side first, and then proceed with joint debugging.