Git Product home page Git Product logo

mqtt2mqtt's Introduction

Mqtt To Mqtt

MQTT

Buy Me A Coffee

Fully configurable Mqtt to Mqtt gateway.

  • Backend: NodeJS, Express, Mqttjs, Aedes Mqtt Broker, Webpack
  • Frontend: Vue, Vuetify

Why

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:

Diagram

Note here there are some bold text GET/SET from/to. More about them in docs

๐Ÿ”Œ Installation

# 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

Usage

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.

Broker settings

Used to set up the MQTT Broker. To edit settings click on the fab button in the bottom right corner

  • Port: The port where the broker will listen for incoming connections
  • Websocket: Enable this to enable MQTT over websockets
  • Websocket Port: The port where the websocket server will listen for incoming connections
  • Require auth: Enable this to enable broker authentication check
  • Username/Password: If auth is enabled insert here the username and the password to connect to this broker.
  • SSL: Enable this to enable SSL
  • Self-Signed Certs: When ssl is enabled, enable to allow self-signed certificates (used to set the flag rejectAnauthorized).
  • Auto-generate certs: When ssl is enabled, flag this to auto-generate certificates
  • Key.pem/Cert.pem: If auto-generate is disabled insert here the key and the certs files

MQTT Clients

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

  • Name: A unique name that identify the Client.
  • Host: The url to the broker
  • Port: Broker port
  • Reconnect period: Milliseconds between two reconnection tries
  • Store: Enable/Disable persistent storage of packets (QoS > 0). If disabled in memory storage will be used but all packets stored in memory are lost in case of shutdowns or unexpected errors.
  • Clean: Sets the clean flag when connecting to the broker
  • Auth: Enable this if broker requires auth. If so you need to enter also a valid username and password.
  • Maps Get: List of maps to use for value updates coming from other gateways to forward to your broker
  • Maps Set: List of maps to use for value writes coming from your broker to forward to the gateways.

Maps

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:

    • Topic: prefix/multisensor/foo/temp Payload: "{"value": 10}"
    • Topic: prefix/multisensor/foo/air Payload: "{"value": 20}"
    • Topic: 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.

    • Keep original: The payload is not changed
    • Value --> JSON: The incoming payload is expected to be a raw value and I want to create a JSON object with a Value Property set to that value
    • JSON --> Value: The incoming payload is expected to be a JSON Object and I want to send a raw value payload using Value Property of original payload
    • JSON --> JSON: The incoming payload is expected to be a JSON Object and I want to map properties to another JSON object. If this option is choosed I will need to add a set of property From and To
  • 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.

Examples

Wildecards

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

  • 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}

Values

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

  • Client: The Mqtt client to connect to
  • Mode: Is this value used to GET updates from a gateway and forwarding them to your broker or is used to SET values? Check the sketch for more info about GET and SET
  • Custom Topic: Enable this to change the original topic
  • Topic: The topic where messages come from
  • Custom Topic: If Custom topic is enabled here you can add the destination topic where the packet received will be forwarded
  • Retain: Sets the retain flag of the outgoing packet
  • QoS: Sets the QoS level of the outgoing packet
  • Payload Map: Select the map to use to use to parse the payload, all other map values like retain, qos and wildecards are ignored

๐Ÿ“ TODOs

  • Dockerize application
  • Package application with PKG
  • Publish/Subscribe topics on UI for testing
  • Unit tests
  • JSON validator for settings

๐Ÿ“ท Screenshots

Broker status

Broker

Clients table

Clients

Values table

Values

Maps table

Maps

Map Function

Function

:bowtie: Author

Daniel Lando

Support me on Patreon โค๏ธ

mqtt2mqtt's People

Contributors

robertslando avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

mqtt2mqtt's Issues

use case: json packets to Home Assistant

I have an interprocess/device communication system based on json packets. To integrate with Home Assistant via mqtt required me to use before send hooks on any process needing to send to HA via mqtt that did "conversions/translations".

I have been thinking of using mcollina's stuff to write a custom broker that could do that. This would mean I won't have to add that code to every process wanting to talk with HA.

So I was looking at aedes and he links to your project!!

I'm just now evaluating it but it looks pretty much what I need. My topology is simpler than you suggest. I just need it to translate packets between select clients/topics (no borker2broker). I can use use it as a generic broker but for particular topics or clients (like HA) I can do the necessary translations at the broker instead of one off in each process (a hassle).

Thanks for your efforts. I'll try to provide some feedback as I use/modify it.

One thing I noticed already was that I'd like to build my mapping/translation functions directly in as opposed to via the interface. I assume there is some way to easily "register" them into the code/database

error after press button "save"

/opt/Mqtt2Mqtt/node_modules/mqtt/lib/client.js:622
cb.apply(null, arguments)
^

TypeError: cb.apply is not a function
at /opt/Mqtt2Mqtt/node_modules/mqtt/lib/client.js:622:14
at Store.close (/opt/Mqtt2Mqtt/node_modules/mqtt/lib/store.js:136:5)
at /opt/Mqtt2Mqtt/node_modules/mqtt/lib/client.js:620:26
at Store.close (/opt/Mqtt2Mqtt/node_modules/mqtt/lib/store.js:136:5)
at Immediate.closeStores (/opt/Mqtt2Mqtt/node_modules/mqtt/lib/client.js:619:24)
at processImmediate (internal/timers.js:458:21)

Bridge mode

I have a local mosquitto broker. I want to bridge it with Mqtt2Mqtt.

Do you support bridge mode?

Thanks!

Can it be used to transform content?

Maybe it is a wrong question for your application but I'm quite new in the MQTT stuff and like to build up this scenario:

  1. I have a ZigBee device
  2. Zigbee2Mqtt is a bridge getting and transferring the data to Mosquitto (topic1)
  3. Mosquitto will be the MQTT server
  4. Mqtt2Mqtt shall read from Mosquitto (topic1), transform the data and push back the transformed data to Mosquitto (topic 2)
  5. A custom node.js software will read the transformed data from Mosquitto (topic2)

The reason for this architecture is that the device may change during the lifecycle of the product. The idea is to adapt the product by just changing the data transfomation description in Mqtt2Mqtt and keep the node.js application stable.

Can this be achieved with Mqtt2Mqtt?

Mqtt2Mqtt client can't publish new topic to Mosquitto Broker

Hi Daniel,

I have a sensor that can publish data to a MQTT broker with topic "deviceId/events/rpc" and a nested JSON object payload. I need to change the topic to "json/apikey/deviceId/attrs" and the payload to a single-level JSON object. I believe Mqtt2Mqtt can help me achieve this perfectly.

Now I setup Mqtt2Mqtt and Mosquitto on a CentOS server, but on Mosquitto:1883 I can't receive anything. My configuration:

  1. In Mqtt2Mqtt->Broker, listening on 1884, when I use mosquito_sub, I can get the data from the sensor.
  2. I created a Maps 'gettest' and just enabled the "Custom Topic" and "use Function", keep "Wildecard From" empty and function with "return {topic: topic, payload: payload}". I think this will forward the original topic and payload to the third-party Broker.
  3. In Mqtt2Mqtt->Clients, set "Host URL:localhost, Port:1883, Reconnected period:3000" and "Maps Get: gettest".
  4. After appling the configuration, I can see "client Connectted" in Mqtt2Mqtt->Broker. Also in MosquittoBroker log, I can see this Mqtt2Mqtt->Client is connected with MosquittoBroker.
  5. But when I subscribe to the original topic on MosquittoBroker:1883, there is nothing received. but on Mqtt2Mqtt :1884, the sensor data still can be got.

Why the data can't be received on MosquittoBroker:1883? Could you help give me some guidance and comments?

In addition, next step I will create a function as below in Maps to do the topic and payload transformation, I hope it can work as I expected :).

          //topic transform;
          var parts = topic.split('/');
          var newTopic = 'json/iothouseapikey/' + parts.reverse().pop() + '/attrs';
          
          //payload transform
          var newPayload = {"src":"defaultSrc", "method":"NotifyStatus", "ts":1659606613.35, "switchId":0, "apower":0};
          const objPayload = JSON.parse(payload);
          
          newPayload.src = objPayload.src;
          newPayload.method = objPayload.method;
          newPayload.ts = objPayload.params.ts;
          newPayload.switchId = objPayload.params['switch:0'].id;
          newPayload.apower = objPayload.params['switch:0'].apower;
          
          return {topic: newTopic , payload: JSON.stringify(newPayload)}

Thank you very much.

payload map doesn't work

the Value --> JSON (value) function doesn't work

mqtt2mqtt:M2M-IH Message received on /devices/wb-msw-v3_52/controls/Input Voltage +62ms
mqtt2mqtt:Broker Client $BROKER PUBLISH on vin: "23.576" +91ms

value property must be "vinin"

Error building

I am running Ubuntu Server 20 on RPi3, getting following error while running npm run build:

npm ERR! code ELIFECYCLE
npm ERR! errno 137
npm ERR! [email protected] build: node build/build.js
npm ERR! Exit status 137
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /home/ubuntu/.npm/_logs/2021-04-07T22_12_18_180Z-debug.log

Contents of /home/ubuntu/.npm/_logs/2021-04-07T22_12_18_180Z-debug.log:

0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'run', 'build' ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'prebuild', 'build', 'postbuild' ]
5 info lifecycle [email protected]prebuild: [email protected]
6 info lifecycle [email protected]
build: [email protected]
7 verbose lifecycle [email protected]build: unsafe-perm in lifecycle true
8 verbose lifecycle [email protected]
build: PATH: /usr/share/npm/node_modules/npm-lifecycle/node-gyp-bin:/home/ubuntu/iot/Mqtt2Mqtt/node_modules/.bin:/home/ub>9 verbose lifecycle [email protected]build: CWD: /home/ubuntu/iot/Mqtt2Mqtt
10 silly lifecycle [email protected]
build: Args: [ '-c', 'node build/build.js' ]
11 silly lifecycle [email protected]build: Returned: code: 137 signal: null
12 info lifecycle [email protected]
build: Failed to exec build script
13 verbose stack Error: [email protected] build: node build/build.js
13 verbose stack Exit status 137
13 verbose stack at EventEmitter. (/usr/share/npm/node_modules/npm-lifecycle/index.js:332:16)
13 verbose stack at EventEmitter.emit (events.js:198:13)
13 verbose stack at ChildProcess. (/usr/share/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack at ChildProcess.emit (events.js:198:13)
13 verbose stack at maybeClose (internal/child_process.js:982:16)
13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
14 verbose pkgid [email protected]
15 verbose cwd /home/ubuntu/iot/Mqtt2Mqtt
16 verbose Linux 5.4.0-1028-raspi
17 verbose argv "/usr/bin/node" "/usr/bin/npm" "run" "build"
18 verbose node v10.19.0
19 verbose npm v6.14.4
20 error code ELIFECYCLE
21 error errno 137
22 error [email protected] build: node build/build.js
22 error Exit status 137
23 error Failed at the [email protected] build script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 137, true ]

Using pm2 to start the app

I try to use pm2 to start the app, but it is not working: pm2 start app.js

Bildschirmfoto 2020-04-08 um 06 56 22

but if I start with npm start it works.

Any hint? Thanks!

Error when saving configuration

I get the following error:

Bildschirmfoto 2020-05-21 um 22 27 45

when saving.

The content of the file is as follows:

0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'start' ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'prestart', 'start', 'poststart' ]
5 info lifecycle [email protected]prestart: [email protected]
6 info lifecycle [email protected]
start: [email protected]
7 verbose lifecycle [email protected]start: unsafe-perm in lifecycle true
8 verbose lifecycle [email protected]
start: PATH: /usr/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/root/Mqtt2Mqtt/node_modules/.bin$
9 verbose lifecycle [email protected]start: CWD: /root/Mqtt2Mqtt
10 silly lifecycle [email protected]
start: Args: [ '-c', 'node bin/www' ]
11 silly lifecycle [email protected]start: Returned: code: 1 signal: null
12 info lifecycle [email protected]
start: Failed to exec start script
13 verbose stack Error: [email protected] start: node bin/www
13 verbose stack Exit status 1
13 verbose stack at EventEmitter. (/usr/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:332:16)
13 verbose stack at EventEmitter.emit (events.js:198:13)
13 verbose stack at ChildProcess. (/usr/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack at ChildProcess.emit (events.js:198:13)
13 verbose stack at maybeClose (internal/child_process.js:982:16)
13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
14 verbose pkgid [email protected]
15 verbose cwd /root/Mqtt2Mqtt
16 verbose Linux 4.19.62-sunxi
17 verbose argv "/usr/bin/node" "/usr/bin/npm" "start"
18 verbose node v10.20.1
19 verbose npm v6.14.5
20 error code ELIFECYCLE
21 error errno 1
22 error [email protected] start: node bin/www
22 error Exit status 1
23 error Failed at the [email protected] start script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

Any idea?

Thanks!

A passthrough for JSON

I have some topics sending the info in a JSON. I want to receive the JSON and send it without changes to the MQTT client. A passthrough...

How should I configure it?

Thanks!

Topics parsing

I have a topic with name "display_targettemperature" and it is ignored. Other topics without "_" work. Is there any limitation here? Special characters in the name of the topics?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.