Customize MQTT messages between two brokers
MIT License
Fully configurable Mqtt to Mqtt gateway.
There is almost an MQTT gateway for every protocol out there.
The problem is every gateway maps reads and writes in different ways depending on the protocol used. There isn't a standard way to map a protocol in MQTT topics and also there isn't a standard payload, some sends a JSON payload with different properties (like val
or value
or data
for the value and tms
time
timestamp
for the timestamp/date), others use a payload with just a numeric value.
This gateway inits an MQTT broker that sits between your MQTT gateways (or devices) and your broker to parse incoming/outgoing MQTT messages from/to your broker in the format you need.
Here is an example schema of how it works:
Note here there are some bold text GET/SET from/to. More about them in docs
# Clone repo
git clone https://github.com/robertsLando/
cd Mqtt2Mqtt
# install dependencies
npm install
# build for production with minification
npm run build
# Start the server
npm start
Once the app is running open the web browser to http://localhost:8100. Here you need to declare the Broker settings, Mqtt clients, the maps and (optionally) the values.
Used to set up the MQTT Broker. To edit settings click on the fab button in the bottom right corner
rejectAnauthorized
).Used to init a connection to an MQTT broker. To add a new client connection click on the fab button in the bottom right corner
Set of rules to use for incoming/outgoing packets. To add a new map click on the fab button in the bottom right corner
Name: A unique name that identify the map.
Custom Topic: Enable this to customize the topic
Use function: Enable this to use a JS function to map topic and payload. The function takes 2 args topic
and payload
and expects to return an object or an Array of objects like {topic: "theNewTopic", payload: "theNewPayload"}
. If you return an Array of objects an MQTT message will be published for each Object in the Array using its payload and topic (qos, and retain flag are taken from map configuration). ATTENTION: Returned topic and payload must be string
.
Example code to write inside the function:
var parts = topic.split('/');
var sensor = parts.pop();
var data = {}
data[sensor] = JSON.parse(payload).value;
return {topic: topic, payload: JSON.stringify(data)}
This function takes last topic level and uses it as a payload attribute and uses the payload value as value for that attribute.
Example that returns an Array.
var topic = topic.split('/');
topic[0] = "myPrefix";
topic = topic.join('/')
payload = JSON.parse(payload);
var res = []
for(const k in payload){
var p = JSON.stringify({value: payload[k]})
var t = topic + '/' + k
res.push({topic: t, payload: p})
}
return res
This example maps an incoming MQTT payload with a JSON key/value object into one MQTT message for each key of the payload with value the key value and the topic with the prefix changed and the key as suffix
Example of map:
Topic: prefix/multisensor/foo
Payload: {"temp": 10, "air": 20, "pressure": 50}
Result:
prefix/multisensor/foo/temp
Payload: "{"value": 10}"
prefix/multisensor/foo/air
Payload: "{"value": 20}"
prefix/multisensor/foo/pressure
Payload: "{"value": 50}"
Code: If both custom Topic and Use functions flag are enabled this field will contain the JS code of the function used to map the topic
Wildecard From: The topic wildecard to use to identify packets that need to be parsed using this map.
Wildecard To: If custom wildecard is enabled this field is used to specify the wildecard to use to transform the original topic to the destination topic (more about this later).
From suffix: The suffix to add to the from wildecard. If a packet topic matches the wildecard but doesn't have this suffix it is discarded. This filed is needed because wildecards like prefix/#/suffix
are not valid wildecards as after a # char the topic cannot have anything.
To suffix: The suffix to add to the destination topic after the wildecards conversion is done.
Retain: Sets the retain flag of the outgoing packet
QoS: Sets the QoS level of the outgoing packet
Payload: The type of payload conversion.
Add timestamp: Can be used when destination payload is a JSON object, if enabled I can add a time property (the name of the prioperty needs to be specified in Time property) to outgoing packets and the value will be Date.now()
, the timestamp when the original packet is received.
Topic From | Wildecard From | Wildecard To | Topic To |
---|---|---|---|
a/b/c/d/e | a/b/# | myprefix/# | myprefix/c/d/e |
a/b/c/d/e | +/b/+/d/e | myprefix/+/+ | myprefix/a/c |
a/b/c/d/e | +/b/# | +/my/# | a/my/c/d/e |
Payload: Value --> JSON
Value Property: "myvalue"
25
---> { "myvalue": 25}
Payload: JSON --> Value
Value Property: "myvalue"
{ "myvalue": 25}
---> 25
Payload: JSON --> JSON
Paylod JSON:
From | To |
---|---|
val | value |
tms | time |
{ "val": 25, "tms": 1556548668373}
---> { "value": 25, "time": 1556548668373}
If you don't want to map all values coming from the gateway but just some values you can add the values you want here using fixed topics instead of wildecards
Support me on Patreon ❤️