The proxy server module

OpenSwitcher provides a proxy server application on top of the ATEM python library. It is designed to easily interface with one or more ATEM switchers using different protocols that are easier to implement for small tools. It also aims to provide an ATEM emulation layer in the future so more official and unofficial clients can be connected to the same hardware than the low connection limit in the hardware itself.

Configuration

The proxy is configured with a toml configuration file. It defines which hardware it should connect to and which protocol frontends it should host.

[[hardware]]
id = "mini"
label = "Atem Mini"
address = "192.168.2.84"

[[hardware]]
id = "mini2"
label = "Local switcher"
address = "usb"

[[frontend]]
type = "http-api"
bind = ":8080"
auth = true
username = "bob"
password = "hunter2"
hardware = "mini,mini2"

[[frontend]]
type = "status"
bind = "127.0.0.1:8082"
auth = false

For every device there needs to be a [[hardware]] section that describes the address to connect to, the internal id and a display label.

The frontends are described in [[frontend]] sections and instead of id fields their unique identification is the bind field which sets the port and optionally the IP to bind the protcol to.

Frontend sections

The required keys for the frontend sections are type, bind, auth and hardware. If auth is enabled then the username and password argument are also required.

The auth setting enables HTTP basic authentication on the webserver for that specific protocol.

The hardware argument is a comma seperated list of hardware ids that are exposed in that specific frontend.

The status frontend

The status frontend is a webserver that provides only a single page, a html view of the connected hardware with their status and a list of the frontend configurations that are enabled.

Screenshot of the webpage generated by the status frontend
[[frontend]]
type = "status"
bind = "127.0.0.1:8082"
auth = false
hardware = "mini"

The HTTP API frontend

The HTTP API frontend will host an api that allows querying the mixer state as JSON objects. It also allows sending commands by sending POST requests with either a query string, form-encoded data or json encoded data.

[[frontend]]
type = "http-api"
bind = "127.0.0.1:8080"
auth = true
username = "admin"
password = "verysecure"
hardware = "mini,secondswitcher,constellation"

A list of the exposed hardware can be retrieved by sending a GET to /

$ curl http://localhost:8080/
{
  "hardware": [
    {
      "id": "mini",
      "status": "connected (ATEM Mini Pro fw 2.30)"
    }
  ]
}

To get data, send a GET request to /{hardware}/{field}. The field in this case is the same as the class names in the API documentation for fields but with the camelcasing replaced with dashes and the word “Field” removed.

To query for a ProductNameField the name would be product-name, to get the product name of a device with the id set to mini you’d send this request:

$ curl http://localhost:8080/mini/product-name
{
  "name": "ATEM Mini Pro"
}

To send a command to the device the same transform applies, but a POST request is sent instead.

# Send as query in the url
$ curl -X POST "http://localhost:8080/mini/program-input?index=0&source=2"

# Send as application/x-www-form-urlencoded
$ curl -X POST "http://localhost:8080/mini/program-input" -d "index=0&source=2"

# Send as json
$ curl -X POST "http://localhost:8080/mini/program-input" -d '{"index": 0, "source": 2}' -H "Content-Type: application/json"

The TCP frontend

The TCP frontend is a custom protocol implementation. The TCP protocol works between the OpenSwitcher proxy and the OpenSwitcher application and is basically the simplified atem USB protocol tunneled over TCP. It also adds authentication and device multiplexing. Using this protocol it’s possible to control any amount of hardware switcheres over a single TCP port and have as many clients connected as required.

[[frontend]]
type = "tcp"
bind = "127.0.0.1:8084"
auth = true
username = "admin"
password = "verysecure"
hardware = "mini,secondswitcher,constellation"

The pyatem library can connect to this frontend by passing an URL to it:

tcp://username:password@myproxyserver:8084/secondswitcher

The hardware list is also send to clients in the connection phase. The protocol is designed so clients can show a popup for authentication when it’s enabled and show a device selection popup with the labels set in the hardware section.

The MQTT frontend

The MQTT frontend will connect to an MQTT server and will sync the hardware state to a topic.

[[frontend]]
type = "mqtt"
connect = "localhost:1883"
auth = false
hardware = "mini"
allow-writes = false
topic = "atem/{hardware}/{field}"
topic-subscribe = "atem/{hardware}/set/{field}"

The proxy will send a new message the the configured MQTT topic every time the state of one of the connected switchers changes. There’s also a special field generated called status that contains the connection state to the hardware on the other side of the proxy.

The topic setting defines which topic the messages will go to. In this path you can use the hardware variable which will be the label of the switcher that generated the event and the field variable which will be the name of the changed field in the same format as the The HTTP API frontend above.

The topic-subscribe is an optional setting that sets the path the proxy will subscribe to the MQTT broker to receive messages back. If this is not set the subscribe topic will be the same as the topic setting used to send messages.

The allow-writes setting defaults to false. If this setting is changed to true it will make the proxy subscribe to a topic and allow changing the switcher state my sending MQTT messages to that topic.

# Switch to input 4 using MQTT
$ mosquitto_pub -t atem/mini/program-input -m '{"index":0, "source": 4}'

# Switch to a named input on the hardware
$ mosquitto_pub -t atem/mini/program-input -m '{"index":0, "source": "PC"}'

# Receive all MQTT messages from the proxy
$ mosquitto_sub -F '\e[92m%t \e[96m%p\e[0m' -t "atem/#"

The MQTT module uses the MQTTv5 protocol