MQTT <--> REST Bridge

Hi,

just a thought. In openHAB 2.5+ and openHAB 3 there is no MQTT eventbus. So you can not publish and subscribe all Items with an MQTT Broker. Theoretically, you wouldn’t need the MQTT broker in openHAB for this procedure. So there is no need for a Thing. With Python you could use pip install paho-mqtt and then use the paho-mqtt client. What you need is to add in /etc/default/openhab is you PYTHONPATH:

echo $PYTHONPATH
/usr/lib/python3/dist-packages

and of course:

EXTRA_JAVA_OPTS="-Xms1024m -Xmx1536m -XX:+HeapDumpOnOutOfMemoryError -Xbootclasspath/a:/etc/openhab/automation/jython/jython-standalone-2.7.2.jar -Dpython.home=/etc/openhab/automation/jython -Dpython.path=/etc/openhab/automation/lib/python:$PYTHONPATH -Dgnu.io.rxtx.SerialPorts=/dev/ttyACM0"

Well at first you can try to run Jython manually:

sudo java -jar /etc/openhab/automation/jython/jython-standalone-2.7.2.jar -Dpython.path=$PYTHONPATH

Note: If you use openHAB 2.5 it could be possible that you run Jython 2.7.0. If you are using openHAB 3 you have to run Jytho 2.7.1 or 2.7.2 because of Java 11.

Instead of sudo java -jar /etc/openhab/automation/jython/jython-standalone-2.7.2.jar -Dpython.path=$PYTHONPATH you can test following with python 3:

Jython 2.7.2 (v2.7.2:925a3cc3b49d, Mar 21 2020, 10:03:58)
[OpenJDK 64-Bit Server VM (Azul Systems, Inc.)] on java11.0.11
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> response = requests.get("http://localhost:8080/rest/items")
>>> print(response.json())
....

What you will find, unfortunately, is that Jython is enormously slower than Python. With Python I need a few seconds and with Jython several minutes.

But let us come to the concept of my thoughts:

You could create a Jython or JavaScript script and add a cronjob/crontask that runs all the time. This in turn publishes all states for each item. With Jython as I said paho-mqtt. In general, however, Paho MQTT then also exists for JavaScript, theoretically also for Groovy. So you don’t have to use Jython if you are more comfortable with JavaScript as example.

If you use http://localhost:8080/rest/items you will receive all items. And if you are using a loop you can iterate through all items. Let give me an example. If you use http://localhost:8080/rest/items/iKueche_Homematic_Steckdose_Leistung you will get the item iKueche_Homematic_Steckdose_Leistung.

This looks like:

{"link":"http://localhost:8080/rest/items/iKueche_Homematic_Steckdose_Leistung",
"state":"NULL",
"stateDescription":{"minimum":0.0,"maximum":163830.0,"step":0.1,"pattern":"%.2f %unit%","readOnly":true,"options":[]},
"editable":false,
"type":"Number:Power",
"name":"iKueche_Homematic_Steckdose_Leistung",
"label":"Leistung",
"category":"text",
"tags":[],
"groupNames":["gKueche_Homematic_Steckdose_EnergieMesser"]}

What is important for us? name and state. Inside you loop you could do something like:

client.publish("/path/to/topic" + "/" + name, state)

Let’s say client is really the previously configured client. You can access a broker via Paho MQTT without using a Thing from openHAB. For each iteration, a different topic would then be created with the state of the current JSON object of the REST query.

This could be a REST to MQTT Bridge.

The other way round, you have to use the possibility of wildcards later on and then also proceed iteratively. As example /path/to/topic/# instead of /path/to/topic/iKueche_Homematic_Steckdose_Leistung and all the others individually.

For the MQTT to REST Bridge you could receive the name of the item because of the topic name. So /path/to/topic/iKueche_Homematic_Steckdose_Leistung could refer to iKueche_Homematic_Steckdose_Leistung. This means it is the name for a put request. The state is the transmitted value:

requests.put("http://localhost:8080/rest/items" + name, data = {'state':state})

As example:

requests.put("http://localhost:8080/rest/items/iKueche_Homematic_Steckdose_Leistung", data = {'state':NULL})

As I said, it is a rough representation of how this works. I have not used the crontask, written the loops or configured the Paho MQTT client yet. I might get to that tomorrow.

But as I said. First impression is that Jython takes significantly longer to evaluate and is enormously slow.

Kind regards

See

You can very easily reproduce the MQTT EventBus with just a dozen lines of code and a couple of Groups. Or you can just use the library I posted at GitHub - rkoshak/openhab-rules-tools: Library functions, classes, and examples to reuse in the development of new Rules..

Or you can subscribe to OH’s REST APS SSE stream from Python if you’d rather make things more complicated and have it running in a separate process. But don’t poll. Use the SSE as it is intended to be used. You can see an example of this at GitHub - rkoshak/sensorReporter: A python based service that receives sensor inputs and publishes them over REST (should work with any API but mainly tested with openHAB) or MQTT. It can also receive commands and perform an action (e.g. set a GPIO pin to HIGH). It currently supports Bluetooth, GPIO on Raspberry Pi, Amazon Dash buttons, command line scripts, and Roku IP address discovery..

Over all, having implemented this both ways, I can say it is by far less work and less complicated to just create the Thing and dozen lines of code (or download and use my library) that it would be to implement a bridge.

Also note that there is an add-on that will install Jython 2.7.1 onto openHAB for you, no need to download or install anything separately nor modify the arguments passed to Java when starting up openHAB.

With HABApp this is an easy rule. The other way around works basically the same way but it’s a little bit more work.