This module provides an EPICS driver for the MQTT protocol, allowing EPICS clients to communicate with MQTT brokers and devices directly from EPICS.
Contributions are welcome - feel free to open issues and pull requests!
- Auto-update of EPICS PVS via
I/O Intrrecords; - Support for read/write flat MQTT topics (i.e, topics where the payload is a single value or array);
- Support for MQTT QoS levels;
- Checks and reject invalid messages (based mostly on type-checking);
- Auto reconnection of broker;
- Planned - short term:
- Support for parsing fields from one-level JSON topic payloads
- Support for MQTT retained messages.
- Support for MQTT last will messages.
- Support for MQTT authentication and TLS.
Note: Virtually all features from the Paho C++ MQTT client are available to be implemented in this driver, so feel free to open an issue if you need a specific feature.
This module is built on top of Cosylab autoparamDriver, which uses the standard asyn interfaces for device support. For now, the supported interfaces are the following:
asynInt32asynFloat64asynUInt32DigitalasynOctetasynInt32ArrayasynFloat64Array
See Implementation status to check the status of development of the interface you need.
- Install the dependencies:
The versions below are the ones in use for development, but it is very likely that EPICS Base >= 3.15 should work.
- EPICS Base 7.0.8.1: https://github.com/epics-base/epics-base/releases/tag/R7.0.8.1
- Asyn 4.45: https://github.com/epics-modules/asyn/releases/tag/R4-45
- autoparamDriver 2.0.0: https://github.com/Cosylab/autoparamDriver/releases/tag/v2.0.0
- Paho 1.5.3: Follow these instructions.
- Clone this repository:
git clone https://github.com/AndreFavotto/epicsMQTT.git-
Edit the
configure/RELEASEfile to include your paths to the dependencies:EPICS_BASE = /path/to/epics/base ASYN = /path/to/asyn AUTOPARAM = /path/to/autoparamDriver PAHO_CPP_INC = /path/to/paho/cpp/include #by default, should be /usr/local/include PAHO_CPP_LIB = /path/to/paho/cpp/lib #by default, should be /usr/local/lib
For now we have two macros for setting paho path because we build the module with separate linking flags -I and -L, but this might change soon.
-
Run
make. The library should now be ready for usage.
- Include the module in your IOC build instructions:
-
Add asyn and mqtt to your
configure/RELEASEfile:## Other definitions ... ASYN = /path/to/asyn MQTT = /path/to/epicsMqtt ## Other definitions ...
-
Add the mqtt database definition and include the necessary libraries to your
yourApp/src/Makefile:#### Other commands ... yourIOC_DBD += mqtt.dbd #### Other commands ... yourIOC_LIBS += asyn yourIOC_LIBS += mqtt
-
- In your database file, link the EPICS records and the MQTT topics through the
INPandOUTfields. The syntax is as follows:
field(INP|OUT, "@asyn(<PORT>) <FORMAT>:<TYPE> <TOPIC> [<FIELD>]")Where:
<PORT>is the name of the asyn port defined in theasynPortDriverconfiguration.<FORMAT>is the format of the payload, eitherFLATorJSON. For now, onlyFLATis supported.<TYPE>is the general type of the expected value [INT|FLOAT|DIGITAL|STRING|INTARRAY|FLOATARRAY].<TOPIC>is the MQTT topic to which the record will be subscribed/published.<FIELD>is an optional field name to be used when parsing JSON payloads (not yet implemented).
Important: Due to the pub/sub nature of MQTT, ALL input records are expected to be I/O Intr.
Example:
record(ai, "$(P)$(R)AnalogIn"){
field(DESC, "Analog Input Record")
field(DTYP, "asynInt32")
field(SCAN, "I/O Intr")
field(INP, "@asyn($(PORT)) FLAT:INT test/analogtopic")
}
record(ai, "$(P)$(R)AnalogOut"){
field(DESC, "Analog Output Record")
field(DTYP, "asynInt32")
field(OUT, "@asyn($(PORT)) FLAT:INT test/analogtopic")
}- Load the module in your startup script using the following syntax:
mqttDriverConfigure(const char *portName, const char *brokerUrl, const char *mqttClientID, const int qos)Example:
# (... other startup commands ...)
epicsEnvSet("PORT", "test")
epicsEnvSet("BROKER_URL", "mqtt://localhost:1883")
epicsEnvSet("CLIENT_ID", "mqttEpics")
epicsEnvSet("QOS", "1")
mqttDriverConfigure($(PORT), $(BROKER_URL), $(CLIENT_ID), $(QOS))
# (... other startup commands ...)
dbLoadRecords("your_database.db", "PORT=$(PORT)")
iocInit()Below is a table with the supported interfaces for the FLAT topics, example of I/O link strings and current status of the implementation. The JSON payload support is planned to come next.
| Message type | Asyn Parameter Type | FORMAT:TYPE string to use |
Status |
|---|---|---|---|
| Integer | asynInt32 | FLAT:INT |
Supported |
| Float | asynFloat64 | FLAT:FLOAT |
Supported |
| Bit masked integers | asynUInt32Digital | FLAT:DIGITAL |
Supported |
| Strings | asynOctetRead/asynOctetWrite | FLAT:STRING |
Supported |
| Integer Array | asynInt32ArrayIn/asynInt32ArrayOut | FLAT:INTARRAY |
Supported |
| Float Array | asynFloat64ArrayIn/asynFloat64ArrayOut | FLAT:FLOATARRAY |
Supported |