Problem with MQTT - How to configure the item?

I found out why i got startet two mqtt server connections…

I looked into config/org/openhab/mqtt.config and there were two configurations inside.

I removed the wrong one, now it is only starting one connection.

When i change my item to this, i don´t get any error in the log:

Number rfid1 "RFID Test [%d]" {mqtt="<[mosquitto:esprfid/uid:command:*:default]"}

But my item still stays empty.

esprfid looks like the topic. Which is you put it into a string value shoudl return the entire json payload.

But that should return the json payload, so there’s a structure to your mqtt command you’ll need to pull the uid parameter of the json payload.

Something like

Number rfid1 "RFID Test [%d]" {mqtt="<[mosquitto:esprfid:state:JSONPATH($.uid)]"}

Thanks, that seems to work partially.

I now get a value to rfid1-number-item, but only 2 numbers “27”

My rfid-token-number is much longer…

EDIT:
There was an error in the openhab.log too, some minutes ago: But this was only a heartbeat- with no uid in the mqtt message… So how to prevent this error?

018-11-22 07:46:47.784 [WARN ] [.mqtt.internal.MqttMessageSubscriber] - Error processing MQTT message.

org.openhab.core.transform.TransformationException: Invalid path '$.uid' in '{"type":"hearthbeat","time":1542869208}'

	at org.openhab.core.transform.TransformationHelper$TransformationServiceDelegate.transform(TransformationHelper.java:67) ~[199:org.openhab.core.compat1x:2.4.0.201811151136]

	at org.openhab.binding.mqtt.internal.MqttMessageSubscriber.processMessage(MqttMessageSubscriber.java:133) [258:org.openhab.binding.mqtt:1.13.0.201811180829]

	at org.openhab.io.transport.mqtt.internal.MqttBrokerConnection.messageArrived(MqttBrokerConnection.java:570) [259:org.openhab.io.transport.mqtt:1.13.0.201811180829]

	at org.eclipse.paho.client.mqttv3.internal.CommsCallback.deliverMessage(CommsCallback.java:475) [259:org.openhab.io.transport.mqtt:1.13.0.201811180829]

	at org.eclipse.paho.client.mqttv3.internal.CommsCallback.handleMessage(CommsCallback.java:379) [259:org.openhab.io.transport.mqtt:1.13.0.201811180829]

	at org.eclipse.paho.client.mqttv3.internal.CommsCallback.run(CommsCallback.java:183) [259:org.openhab.io.transport.mqtt:1.13.0.201811180829]

	at java.lang.Thread.run(Thread.java:748) [?:?]

Take your json payload to an online Json parser to get the path string properly.

I based it on one of mine and guessed your value.

1 Like

This is the whole string i get from mqtt, when i enter it into an online parser, without the leading esprfid, then i get shown exactly the same data, only every value in one line.

???

How can i read out the whole string with all values in one single item? Then i would be able to split this in a rule to get the needed values…

Can you try the folloiwng (if you haven’t already done so)?

String json {mqtt="<[mosquitto:esprfid:state:default]"}

This should give you the entire JSON “message” as a string that you could put on a sitemap (just to show that you actually get it all), write to the log, or - as you really need - parse in a rule.

1 Like

Thanks, that works! Now i get the whole mqtt-message to my string-item.

I think, i will divide my string-item with the split-command into small parts and then work with this.

Or is there a better way to do that? Maybe with json-commands? I have never used json, i only know how to split my string…

So i hope you can give me some advice, what would be the better way?

I am sure there is some Java JSON library that you can use for this, but I have never done this, so I am afraid I cannot help on this account.

My suggestion for capturing the complete JSON message in a string was only because you asked if it was possible - and as a way to verify that you actually receive the JSON message in openHAB, i.e. a debugging measure.

This is not neccessarily the way I would do this.

Given the following JSON message (from your original post):

{"type":"access","time":1542734830,"isKnown":"true","access":"Always","username":"schwarz","uid":"12361353"}

I would suggest to try to map this directly to separate items using JSONPATH (as proposed by @psyciknz above) like this:

String      rfid1_type      { mqtt="<[mosquitto:esprfid:state:JSONPATH($.type)]" }
DateTime    rfid1_time      { mqtt="<[mosquitto:esprfid:state:JSONPATH($.time)]" }
String      rfid1_isknown   { mqtt="<[mosquitto:esprfid:state:JSONPATH($.isKnown)]" }
String      rfid1_access    { mqtt="<[mosquitto:esprfid:state:JSONPATH($.access)]" }
String      rfid1_username  { mqtt="<[mosquitto:esprfid:state:JSONPATH($.username)]" }
Number      rfid1_uid       { mqtt="<[mosquitto:esprfid:state:JSONPATH($.uid)]" }

This really should work (with the disclaimer that I may have made a typo in the above). If not let’s try to find out why…

1 Like

Hi, i think i can´t use this, because the heartbeat only gives me type and time, so there is no uid in the message and there i get error messages.

So my plan is to get the whole string, then look with jsonpath-transformation if the type is access and if yes, send the uid to openhab and do some stuff.

If type is only heartbeat, then the rule will stop at this point and do nothing.

Ah… I didn’t notice that post. Sorry!

There may still be a way forward, though.

The MQTT binding supports a fifth parameter for inbound messages, called a " <regex_filter>". Using this you can make sure that only messages that matches certain criteria will be passed on to the transformation stage (JSONPATH, in your case).

Please try this:

String      rfid1_uid       { mqtt="<[mosquitto:esprfid:state:JSONPATH($.uid):.*uid.*]" }

Note! As a first attempt, I suggest you define all your items as String items just to see that you can sucessfully split your JSON message into separate parts in openHAB. If this works, then you can try to use Number and DateTime (as above) to do “automatic type conversion” if this is needed - I guess it all depends on what you will use the data for in your rules.

Hi, i tested your Json-String with Online-Parser, and got this:

  1. Wildcard

  2. uid

So this seems to work.

I’m using the [%s] Formatter in my items-setup like this:

Number    Sonoff_Pow_02_RSSI                "Stehlampe RSSI [%s]"                             <qualityofservice>      (EG_Wohnen,gRSSI)                               { mqtt="<[peter:tele/stehlampe/STATE:state:JSONPATH($.Wifi.RSSI)]" }

Have you tried it ? In a way as

as @psyciknz suggested, but changing the formatter to [%s].

Got it working, this is my rule:

rule "RFID Haustür MQTT"
	when
		Item rfid_all_haustuer received changed
	then
		val newValue_type = transform("JSONPATH", "$.type", rfid_all_haustuer.state.toString)
		if (newValue_type == "hearthbeat") {
				logInfo("RFID", "RFID Haustür -3- ---> MQTT --> only heartbeat --> " + newValue_type)
		}
		else if (newValue_type == "access") {
				val newValue_uid = transform("JSONPATH", "$.uid", rfid_all_haustuer.state.toString)
				logInfo("RFID", "RFID Haustür -4- ---> MQTT --> access : uid --> " + newValue_type + " : " + newValue_uid)
		}		
end

I have another small problem:
in time i get the epoch (ms since 1970 i think), how can i convert this into a readable format?

This gives me an error:

val newValue_time = transform("JSONPATH", "$.time", rfid_all_haustuer.state.toString)
val DateTimeType MyDateTimeTypeFromEpoch = new DateTimeType(new DateTime(newValue_time).toString)
1 Like

See this tutorial

Use a JAVASCRIPT transform instead of the JSON transform:

See:

In the script you can check if uid exists before forwarding the info

I already get the data from my controller, if the rfid tag is valid.

And i don´t have any skills in javascript… So i will stay inside openhab rules.

I already tried the date format examples from the tutorial thread, see my post with my rules file.

Here is what i tried also, but not working. First gives me an error

[ERROR] [ntime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'RFID Haustür MQTT': Invalid format: "1542997079" is malformed at "9"

and second one gives me nothing, no error, no value.

val Number newValue_time = transform("JSONPATH", "$.time", rfid_all_haustuer.state.toString)
logInfo("RFID", "RFID Haustür -1- ---> MQTT --> number newValue_time: " + newValue_time)
		
		val MyJodaFromEpoch = new DateTime(newValue_time)
		logInfo("RFID", "RFID Haustür -1-0- ---> MQTT --> joda time: " + MyJodaFromEpoch)

		var SimpleDateFormat df = new SimpleDateFormat( "dd.MM., HH:mm" )
		var String timestamp = df.format( newValue_time )
		logInfo("RFID", "RFID Haustür -1-1- ---> MQTT --> string time: " + timestamp)

This works, but only a workaround…

		val String now_string = now.toString
		logInfo("RFID", "RFID Haustür -1-0- ---> MQTT --> now_string time: " + now_string)

With this i get the time, when openhab receives the data, but not the time from my rfid-controller. But it is better than nothing…

** Install the JAVASCRIPT transformation**

Create a file called uid.js in the transform folder with the following contents:

(function(jsonString) {
var data = JSON.parse(jsonString);
if (data.hasOwnProperty("uid")) {
    var uid = data.uid;
}
return uid;
})(input)

Your item then becomes:

String      rfid1_uid       { mqtt="<[mosquitto:esprfid:state:JS($.uid.js)]" }

Reading to learn more on js code and have a question. Should there be a extra “)” in the if statement like below?

(function(jsonString) {
var data = JSON.parse(jsonString);
if (data.hasOwnProperty("uid")) {        // extra ")" added to this line
    var uid = data.uid;
}
return uid;
})(input)

Thanks

1 Like

Correct. Sorry for the typo.