1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
|
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.
.. code-block:: toml
[[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.
.. image:: images/proxy-status.png
:width: 600
:alt: Screenshot of the webpage generated by the status frontend
.. code-block:: toml
[[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.
.. code-block:: toml
[[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 /
.. code-block:: shell-session
$ 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:
.. code-block:: shell-session
$ 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.
.. code-block:: shell-session
# 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.
.. code-block:: toml
[[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:
.. code-block:: url
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.
.. code-block:: toml
[[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.
.. code-block:: shell-session
# 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
|