Most control protocols for Broadcast routers come from the era of RS422 serial comms. Even those routers which support control via IP tend to use proprietary protocols that are not easily compatible with web-based control applications.
The Routemaster Websocket protocol was designed to use web standards to enable router control from web applications running on any modern browser. This allows web pages to easily control routers and receive status from any router controlled via the RouteMaster system.
Routemaster Web Panels use this protocol to control routers connected to the RouteMaster system. Routemaster can also use the same protocol to control routers that support it, or downstream Routemaster systems.
Client vs Server
The ‘client’ is typically any application that wants to make routes or receive router status, and the ‘server’ is typically the RouteMaster system (or any other router using this protocol).
The ‘server’ typically listens for connections on TCP/IP port 81, although other ports can be configured. Servers support multiple simultaneous client connections. RouteMaster limits the number of simultaneous clients according to the number of installed licenses.
WebSocket protocol
Messages are exchanged between client and server using the WebSocket protocol, described in overview here. https://en.wikipedia.org/wiki/WebSocket Basically, unlike HTTP it offers a persistent full-duplex connection. RouteMaster currently does not use encrypted Websocket (‘wss:’)
JSON
WebSockets give a way of sending ‘messages’ between endpoints, but does not define the content and structure of those messages. Messages could be binary, XML or any proprietary format. RouteMaster uses JSON for the message structure, which fits well with JavaScript used in browser-side applications. http://json.org/
Message Flow
The protocol does not impose any restrictions on message flow. Messages can normally be sent by both client and server at any time, and in any order. However, when a new client connects to a server, it should be sent the entire router state including source and destination names, protect and crosspoint status.
The final message after the initial state has been sent will be the connectComplete message.
No Ack/Nak
Messages do not implicitly cause Ack or Nak replies to be sent. but the success of messages forcing a change of state can be determined by the tally messages returning when an operation completes.
Input/Output numbering
All sources, destinations and levels are numbered starting from ZERO.
JSON Message fields
Every JSON message has a mandatory string field “event” which is describes the message type. A structure ‘data’ then contains parameters and data regarding the event. Unknown incoming events will be ignored, and unknown fields in the JSON data are also ignored.
Messages from server to client
event | Function | data` | example |
tallyCrosspoint | Notifies client of crosspoint change | destination: integer sources : array of integers, one per level |
{"event":"tallyCrosspoint", "data": "destination":0 } } |
sourceName | Notifies client of source name change | source: integer names : array of strings for names starting at specified source. |
{"event":"sourceName", "data": { "names":["XXX A", "SRC 1", "SRC 2", "SRC 3"], "source":0 } } |
destName | Notifies client of destination name change | destination: integer names : array of strings for names starting at specified destination. |
{"event":"destName", "data": { "names":["MON", ”DST 1", ”DST 2", ”DST 3"], "destination":0 } } |
levelName | Notifies client of level name change | level: integer names : array of strings for names starting at specified level. |
{"event":"levelName", "data": { "names":["Video”, ”Audio”], "level":0 } } |
routerData | Basic information about the router size, etc | sources: integer dests: integer levels: integer name: string |
{"event":"routerData", "data": { "sources":64, "levels":2, "dests":64, "name":"DUMMY" } } |
inputGroups | Information about input (source) groups | TBC | |
outputGroups | Information about output (destination) groups | TBC | |
protectState | Notifies client of destination protect change | dest: integer state : array of .. { prot: “Unlocked”,”Locked” or “Protected” user: string } |
{"event":"protectState", "data": { "state":[ {"prot":"Unlocked"}, {"prot":"Locked", “user”:”Joe”}], "dest":0 } } |
connectComplete | Indicates that the initial status transfer to client has finished. | none | {"event":"connectComplete"} |
salvoNames | The list of available Salvo Names | names: array of strings | {"event":"salvoNames", "data": { "names":[ "Salvo 1", "Salvo 2", "My Salvo"] } } |
Messages from client to server
event | Function | data | example |
makeCrosspoint | Request a crosspoint change | destination: integer source: integer levels: |
{“event”:”makeCrosspoint”, “data”:{ “source”:6, “destination”:2, “levels”:”L0″ } } |
lockOutput | Lock/unlock an output | destination: integer state: “Locked”/”Unlocked” |
|
fireSalvo | Fire a ‘salvo’ of multiple routes | id: name or id number of salvo to fire |
Javascript implementation of WebSocket clients
For a good overview of how to handle JSON-based WebSockets from Javascript, see this page:
https://www.new-bamboo.co.uk/blog/2010/02/10/json-event-based-convention-websockets/