GPIO pin to MQTT bridge service
A service which connects MQTT topics to GPIO pins, configurable via YAML. Additionally supports input and output pin groups, and complex inching.
Prebuilt container images are available on Docker Hub.
Currently tested using native factory, run as a DaemonSet on K3s on a Raspberry Pi 4B with:
volumes: - name: config configMap: name: mqtt-gpio-config - name: sysfs hostPath: path: /sys containers: - name: mqtt-gpio image: sourcesimian/mqtt-gpio:latest command: ["/entrypoint.sh"] securityContext: privileged: true volumeMounts: - name: config mountPath: /config - name: sysfs mountPath: /sys readOnly: False Where entrypoint.sh looks like this, and uses the NODE_NAME environment variable to select different config based on the host name.
env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName An installation of mqtt-gpio will need a MQTT broker to connect to. There are many possibilities available. Eclipse Mosquitto is a great self hosted option with many ways of installation including pre-built containers on Docker Hub.
To control the messages on your MQTT broker you may consider mqtt-panel which is a simple web app panel that gives user interactivity with MQTT topics.
mqtt-gpio consumes a single YAML file. To start off you can copy config-basic.yaml
mqtt-gpio uses the gpiozero module, which builds on a number of pin factories. At present the only factories which have been tested are native and mock. I encountered a variety of technical obstacles and behaviour issues in using the other factories, especially since I wanted to run in a container on Kubernetes. Expect your mileage to vary with the other pin factories, as was my exprience of finding my garage door standing open one morning after an unexpected server restart during the night. With the native factory there have been no such "glitches".
gpio: pin-factory: <factory> # GPIO pin factory, currently only: mock, native mqtt: host: <host> # optional: MQTT broker host, default: 127.0.0.1 port: <port> # optional: MQTT broker port, default 1883 client-id: mqtt-gpio # MQTT client identifier, often brokers require this to be unique topic-prefix: <topic prefix> # optional: Scopes the MQTT topic prefix auth: # optional: Defines the authentication used to connect to the MQTT broker type: <type> # Auth type: none|basic|mtls, default: none ... (<type> specific options) type: basic username: <string> # MQTT broker username password: <string> # MQTT broker password type: mtls cafile: <file> # CA file used to verify the server certfile: <file> # Certificate presented by this client keyfile: <file> # Private key presented by this client keyfile_password: <string> # optional: Password used to decrypt the `keyfile` protocols: - <string> # optional: list of ALPN protocols to add to the SSL connection http: bind: <bind> # optional: Interface on which web server will listen, default 0.0.0.0 port: <port> # Port on which web server will listen, default 8080 max-connections: <integer> # optional: Limit the number of concurrent connections, default 100 logging: # Logging settings level: INFO # optional: Logging level, default DEBUG A binding is a functional element, which is used to connect MQTT topics and payloads to a set of GPIO pins.
Bindings are defined under the bindings key:
bindings: - ... All bindings have the following form:
- name: <string> # Binding identifier demand: <topic> # optional: Input MQTT topic to listen for values state: <topic> # optional: Output MQTT topic to publish values status: <topic> # optional: Output MQTT topic to publish full status in JSON qos: [0 | 1 | 2] # optional: MQTT QoS to use, default: 1 retain: [False | True] # optional: Publish with MQTT retain flag, default: False change-delay: <duration> # Delay notifications pin state change notifications initial-value: <identifier> # optional: Initial value written to pins at startup pins: # GPIO pins associated with this binding - (pin definitions) values: # MQTT payloads associated with this binding - (value definitions) inch: # optional: Inching sequences - (inch definitions) The change-delay can be used to avoid glitching when inputting a multi-pin binding, thus avoiding bursts of message publications at multi bit transitions. The <duration> is in floating point seconds.
The initial-value references one of the named values. Only the pins defined as output are written.
pins: - gpio: <pin> # Pin identifier, e.g.: GPIO21 mode: <direction> # Read/write: INPUT|OUTPUT pull-up-down: <pud> # optional: Pull-up pull-down: "OFF"|UP|DOWN. Default: "OFF" bounce-time: <duration> # Debounce time The bounce-time <duration> is in floating point seconds.
values: - payload: <payload> # optional: Payload which is matched to the value name: <identifier> # optional: Value identifier, referenced from inching value: <value> # The pin value(s), e.g. 1 or 1,0,0,1 If payload is defined and is received on demand, the pin(s) will be set to value. Where value represents all the pins which have been defined, in the same order. Pin value is either 0 or 1, multiple values are seperated with a ,.
inch: - payload: <payload> # Payload which is matched to this sequence steps: - <step> # The steps to replay when the payload is received - ...(repeat) If payload is is received on demand, then the steps will be run. Where each <step> can take the following forms:
<identifier>, <duration><identifier>, <duration>, <payload>
The <identifier> maps to the value <identifier>. The <duration> is in floating point seconds. And the <payload>, if given will be published to state. If payload is not given and the identified value is associated with a payload then that will be published to state at the beginning of the step. The <duration> of the last step will typically be 0.
If a value payload is received during a replay, this will abort the replay. If an inch payload is received during replay, the steps will be queued after current steps.
Yes sure! And please. I built mqtt-gpio because I couldn't find an solution to with the same capabilities. I want it to be a project that is quick and easy to get up and running, and helps open up MQTT to anyone.
Before pushing a PR please ensure that make check and make test are clean and please consider adding unit tests.
Setup the virtualenv:
python3 -m venv virtualenv . ./virtualenv/bin/activate python3 ./setup.py develop Run the server:
Note: this will only work on OS'es with epoll select, this excludes MacOS.
mqtt-gpio ./config-demo.yaml In the spirit of the Hackers of the Tech Model Railroad Club from the Massachusetts Institute of Technology, who gave us all so very much to play with. The license is MIT.