[SOLVED] MQTT, JSONPATH transformation & strange results in Basic UI

Maybe just data without brackets. As i said i am no pro with jsonpath. Just what i read from the manual. And i did not test it.

@ewrw edit:

This

{mqtt="<[mybroker:tele/RFBridge/RESULT:state:JSONPATH($.RfReceived[?(@.Data=~ /123.*/ ).Data] ]"}

Should return this

[
   "123B"
]

I did an exact copy/paste to ensure I had no mistakes written in, and strangely, I still just get the [ ] as the return.

I did try removing the [ and ] from just after RfReceived and the one after .Data… and I still get the [ and ]… Even after deleting my internet history and re-starting the browser (perhaps because without the extra [ and ], the line wont process and its keeping the data through persistence).

I have however settled on a solution.

I am using 1 Item to pull in my original MQTT line and then Im not mapping, but using rules to push the command out to other variables. e.g.

rule "Alarm Sensors"
when
    Item ALARMDATA received update
then 
	if (ALARMDATA.state == "123A") SENSORWINDOW.postUpdate("Closed")
	if (ALARMDATA.state == "123B") SENSORWINDOW.postUpdate("Open")
	if (ALARMDATA.state == "123C") SENSORWINDOW.postUpdate("Tamper")
	if (ALARMDATA.state == "456A") REARDOOR.postUpdate("Closed")
	if (ALARMDATA.state == "456B") REARDOOR.postUpdate("Open")
	if (ALARMDATA.state == "456C") REARDOOR.postUpdate("Tamper")
end

Its perhaps not as elegant, will require a small amount of system overhead and may process slightly slower by a few milliseconds… but it works and I will only have 8 actual sensors to add in.

So I do have a working solution at this time… however, like yourself, Id like to understand JSONPATH better and perhaps I will re-visit this in future (I will post an update if I do).

Thanks for your time, thoughts and help with looking into this, it was really appreciated!!

You can make it a bit easier by naming the Items for the contacts as follows.

String  contact_123 "Front Door" ...
String  contact_456 "Rear Door" ...

And make a rule that is valid for all Items.

rule "Alarm Sensors"
when
    Item ALARMDATA received update
then 
        // Get name of Number Item by removing the numbers
        val contactNumber = ALARMDATA.state.toString.substr(1,3)
        val stateOf = ALARMDATA.state.toString.substr(3,1)

        logInfo("Contact", "Number "+ contactNumber +" changed to "+ stateOf ) 

        // post the new value to the Number Item
	if (stateOf == "A") { 
           postUpdate( "contact_"+ contactNumber.toString , "Closed" ) 
        }
	else if (stateOf == "B"){ 
           postUpdate( "contact_"+ contactNumber.toString , "Open" ) 
        }
	else if (stateOf == "C"){ 
           postUpdate( "contact_"+ contactNumber.toString  , "Tamper" ) 
       }
end

Ahh… yes!!! Thats brilliant, much cleaner, easier and less code to have to amend!

Thank-you so much!! :slight_smile: Ill go and implement it now.

Can you please confirm if you got this working. And please post your confing for this (items, sitemap, rules etc). Have been struggling a few nights with this.

Hi Tom

The answer to your question of can I confirm I got this working, is both a a yes and a no. The code above works. The 1 issue I did struggle with, which I didnt know at the time, was that the VAL lines (for some reason) had to be initially declared in the top of my RULES (literally at the very top of the rules file). This is listed in the documentation https://docs.openhab.org/configuration/rules-dsl.html#the-syntax on the “Variable Declarations” area.

So you would need to put these at the TOP of the rules file:

        val contactNumber = ALARMDATA.state.toString.substr(1,3)
        val stateOf = ALARMDATA.state.toString.substr(3,1)

If you dont put them there, you get an error in the log about parsing the rules file on the line numbers where the VAL’s are declared.

So that was issue 1 for me… Issue 2 for me was that in the examples above, I listed that my sensors very simply separated Open/Closed/Tamper via the use of A, B and C… so the code example above is reading if there is an A, B or C sent via the sensors and then updating the contact_XXXXX site map entry… However, I ended up with a bunch of sensors that dont work with A, B and C, but give a random code e.g.

Open - USH3438
Closed - AUF8234
Tamper - IAS0238

Obviously, there is NO simple way, when you have multiple sensors with random codes like the above to progmatically use a simple 1 off rule on its own to pick out the difference between multiple sensors… Well, not easily.

I did look at using a MAP file, that would list each unique code and what that code mapped to… But I found an issue with … I cant recall exactly what it was, but somewhere along the line, I found that my variable couldnt work correctly because of the translation… I cannot remember it it was within the ITEMS, RULES or SITEMAP I had a problem… but I did.

So, I have ended up with having to define each code from the sensor and then the action taken for each code, within my rules file… which does look like a lot of code and it could probably be cleaned up by someone with more code knowledge than myself. but I dont have a huge rules file anyway and the code does work.

ITEMS - Creates a variable to pull in the code from a sensor, via a MQTT source

String ALARMSENSOR1 {mqtt="<[mybroker:tele/RFBridge/RESULT:state:JSONPATH($.RfReceived.Data)]"}

ITEMS - I created a variable which is On/Off which is basically is the alarm On or Off (is someone in the house)
Switch HOUSEOCCUPIED “Status”

ITEMS - Creates a variable for use within the sitemap, that will display the Open/Closed/Tamper status

String FRONTDOOR "Front Door [%s]"	<doorsensor>	(Alarmsensors)

ITEMS - I also wanted to record the LAST sensor triggered information, what time it was triggered and the alert type (Open/Closed/Tamper etc)

String 	ALERT		         		"Sensor Triggered [%s]"			<alerticon>
String 	ALERTTIME	         		"Alert Time [%s]" 				<alerticon>
String 	ALERTTRIGGER         		"Alert Trigger [%s]"     		<alerticon>

SITEMAP - As simple as displaying the variables you created above

    Frame label="Security" {	
		Switch item=HOUSEOCCUPIED				mappings=["ON"="Armed","OFF"="Disarmed"]
		Text label="Alarm System" icon="alarm1"{
			Frame label="Last Alert" {	
				Text 		item=ALERT			
				Text		item=ALERTTIME	
				Text		item=ALERTTRIGGER
			}
			Frame label="Sensor Status" {	
				Text		item=FRONTDOOR
				Text		item=REARDOOR
				Text		item=SENSORWINDOW
			}
			Frame {	
				Text 		item=MOTIONSENSOR1	
				Text		item=LANDINGSENSOR		
			}
		}
	}

RULES - At the top of my rules file I have imported Java date/time

import java.text.SimpleDateFormat
import java.util.Date

RULES - As for a rule to work with 1 sensor, because they are using different codes, each rule would look like the following

For my example below, use the following example as being sent by the sensor:
Open - USH3438
Closed - AUF8234
Tamper - IAS0238

The code will say that IF the alarm is ARMED, and the sensor sends Open/closed, then I DO want a telegram notification message sent to my phone with the details of that sensor & the date and time, along with updating the ALERT, ALERTTRIGGER and ALERTTIME variables.

If the alarm is DISARMED, and the door is Open/Closed then it wont send a notification to my phone OR update the ALERT, ALERTTRIGGER and ALERTTIME variables.

Either of the above actions will update the sitemap text variables to show the current state of the sensor as Open/Closed.

For Tamper events, I have chosen to recieve a notification via Telegram, even if the alarm is disarmed.

So yes, I have ended up with one rule like the below for each sensor, which is messy, but it works, my rules file is not very large anyway and I thought I would re-visit it one day in the future to see if there was a better way to do this, when working with sensors that send codes you cannot easily delinite programmatically.

rule "Alarm sensor 1 - Front Door"
when
    Item ALARMSENSOR1 received update
then 
	if (ALARMSENSOR1.state == "AUF8234" && HOUSEOCCUPIED.state == ON) 	{ FRONTDOOR.postUpdate("Closed") 		
			sendTelegram("TELEGRAMBOTNAME", "Alarm - Front Door Closed" + Current_DateTime.state.format(" %1$td/%1$tm/%1$tY at %1$tH:%1$tM")) 							
			ALERT.postUpdate("Front Door")
			ALERTTRIGGER.postUpdate("Closed")
			ALERTTIME.postUpdate(Current_DateTime.state.format("%1$td/%1$tm/%1$tY at %1$tH:%1$tM")) }						
	if (ALARMSENSOR1.state == "AUF8234" && HOUSEOCCUPIED.state == OFF) 	{ FRONTDOOR.postUpdate("Closed") }
	if (ALARMSENSOR1.state == "USH3438" && HOUSEOCCUPIED.state == ON) 	{ FRONTDOOR.postUpdate("Open") 			
			sendTelegram("TELEGRAMBOTNAME", "Alarm - Front Door Open" + Current_DateTime.state.format(" %1$td/%1$tm/%1$tY at %1$tH:%1$tM")) 								
			ALERT.postUpdate("Front Door") 	
			ALERTTRIGGER.postUpdate("Open")
			ALERTTIME.postUpdate(Current_DateTime.state.format("%1$td/%1$tm/%1$tY at %1$tH:%1$tM")) }						
	if (ALARMSENSOR1.state == "USH3438" && HOUSEOCCUPIED.state == OFF) 	{ FRONTDOOR.postUpdate("Open") }
	if (ALARMSENSOR1.state == "IAS0238" && HOUSEOCCUPIED.state == ON) 	{ FRONTDOOR.postUpdate("Tamper")
			sendTelegram("TELEGRAMBOTNAME", "Alarm - Front Door Tamper - Alarm was Armed" + Current_DateTime.state.format(" %1$td/%1$tm/%1$tY at %1$tH:%1$tM"))  			
			ALERT.postUpdate("Front Door") 	
			ALERTTRIGGER.postUpdate("Tamper")
			ALERTTIME.postUpdate(Current_DateTime.state.format("%1$td/%1$tm/%1$tY at %1$tH:%1$tM")) }						
	if (ALARMSENSOR1.state == "IAS0238" && HOUSEOCCUPIED.state == OFF) 	{ FRONTDOOR.postUpdate("Tamper") 		
			sendTelegram("TELEGRAMBOTNAME", "Alarm - Front Door Tamper - Alarm was Disarmed" + Current_DateTime.state.format(" %1$td/%1$tm/%1$tY at %1$tH:%1$tM")) }
end

Obviously, I dont know exactly what sensors/devices you are working with and what they send you, but hopefully this gives you some help figuring out what you need to do.

1 Like

Thank you Will!

Nice code. Some minor adjustments in my setup still needed.

By the way I’m using an ITead/Sonoff model DW1 door sensor, tiny booklet says it is a “CD100S wireless magnetic door detector”. I’m using it with a Sonoff RF Bridge 433.
Unfortunately it only sends a single MQTT message each time door is opened. No closed or tamper signal with this sensor.

I have the sonoff bridge too and Im using Tasmota firmware on it, though for the door/window sensors I used Kerui D026 which are a bit more than the Sonoff door sensors, but not too expensive. They do support the Open/Closed and Tamper… so if you really need one that does all 3 and dont want to spend too much, have a look at those.

Good luck!!

1 Like

Thanks Will,
Cool, your example got my Sonoff RF Bridge working for me.
As a Start of Code get me going to implement my own Stuff …

A bit of Disappointment are the Sonoff door sensors, a orderd a bunch of them, but only the open event is detected.
someone any idee to change this ???

regards

Hi Michael

Its a limitation of what the actual door sensors will send, rather than the bridge or openhab etc… So the only way to change this on the Sonoff sensors would be to dump new firmware on the sensors to send a closed signal (Im not claiming any such firmware exists… to my knowledge anyway… and even then I dont know how easy it would be to re-program them). This is why I went with the Kerui D026 sensors and they support all 3 actions out the box and have a good battery life of about 10-12 months (plus they are relatively cheap if you hunt around). The open/closed is performed by the magnetic relay switch and the tamper is supported by a push button on the back of the sensor, that activates if the sensor was removed from the door/window (which I dont think the Sonoff sensors have a button on the rear of the units, so couldn’t do tamper anyway).

Maybe if you could do a mixed solution and use a couple of the Kerui D026 for your doors in the house and the Sonoff’s for the windows or something.

Probably not the answer you were after, but hopefully it will save you a few frustrating hours hunting the internet for an answer!

Best of luck!

1 Like

Hmm, maybe do some hardware modifications … second reed relais ?

Well a order one Kerui D026 for Test :smile: 7,28 Euro by AliExpress.

In the mean time, finally i got my RF 433 Remote Control working with your Code.
This Stupid Control sends 4 Different Data codes for each key press.

Question: in a rule, is there a way to log the state ?
What i tried to do is something like this, where RFSensor is my Item:

rule "React on RFSensor update"
when
    Item RFSensor received update
then
     if (RFSensor.state == "4AFBB0" || RFSensor.state == "417430" || RFSensor.state == "479E40" || RFSensor.state == "40E770")  {
        FB_EasyHome_A.sendCommand(ON)
    } else if (RFSensor.state == "431A10" || RFSensor.state == "4CC190" || RFSensor.state == "458DA0" || RFSensor.state == "493C20") {
        FB_EasyHome_A.sendCommand(OFF)
    } else {
        logInfo("unknown rf Data", RFSensor.state)
    }
end

this gives me a Nullpointer Exception in the else statement, i don’t understand ??

regards

missing toString

1 Like

:smile::smile::smile::smile: Thanks, tested and works

HI Will,
I just got the Kerui D026. Can you share your current working solution for thing, item and rules for these contact sensors under MQTT 2.4?

Hi J

The post further back on here from February 18th is pretty much still what Im using Items/Sitemap/Rules wise. Im not sure what version of MQTT Im using, so Im not sure if youre implying something has changed in a recent version, though Id imagine MQTT wont have changed in any way. EDIT- MQTT 2.4 binding: Items go to UNDEF after reboot (reading this post, theres a suggestion on it that there was an issue with implementation of MQTT on Openhab 2.4 and that 2.5 resolves this, though I have no issues myself and havnt looked any further into this, but perhaps this will point you in the right direction).

Each Kerui DO26 will send its own unique codes through via your RF Bridge to MQTT, so you need to use something like MQTT.fx (or similar) that can live look at what gets sent to your RFBrige, you will see when you press the buttons on the sensor, you get a different code sent for Open/Closed/Tamper (and battery too… but you need a bad battery or variable power supply to figure that out), so you will note those codes down for each sensor and use the codes in the rules.

Beyond that, everything is pretty much as per my previous post, though you will create additional rules for each sensor and its unique codes.

Does that help or is there something specific you need help with, or perhaps describe your problem with MQTT 2.4 and the rules?

Thanks

Hi Will,
I previously got a contact sensor that only gave out specific rf data on open and close. @vzorglub helped me with a JS transformation which did the trick.
However with the Kerui D026, I cannot use the same JS transformation as it gives out 4 different types of RF data . So I want to model it exactly after someone who have used it successfully (which you have) . I have not figured out how to get the battery RF data but I assume the only change is the last character, as that is true for the open,close and tamper data.

Yes I am using MQTT 2.4 binding, which needs specific thing and item files. I hope that is also what you used currently.

Could you share your thing, item and rule file for one of your D026 sensor?

I looked over my config files etc and everything was as I showed above… I think the answer though is that Im still using Openhab 2.3.0 and not Openhab 2.4.x, so its not a challenge Ive yet taken on and investigated.

The bindings/actions/persistence I have installed are:

MQTT Binding

binding-mqtt1 - 1.12.0

MQTT Action

action-mqtt - 1.12.0

MQTT Persistence

persistence-mqtt - 1.12.0

Which are all shown in paper UI. Im not declaring anything in either the text file or webui things at this time.

So it looks like this will be a new challenge to investigate at some point in the future when I upgrade.

As for the battery, yes it is a different number on the end… so either you could make something that looks for all the possible end variants (but not the other 3 that you know of)… or if you have an almost worn out battery, put that in the device and get it to send the code… or you need a variable power supply to hook up and slowly drop the voltage until it starts sending out its “low battery” code. I dont know of any other route for this (I suppose it may be possible to write a “device hasnt checked in for X period of time” which you may be able to cover all the sensors in one go with that type of code, as well as cover off the bridge being switched off)

Upgrading is something I may do one day, but not at the moment as I dont have spare time.

I hope however this gives you some insight and Id be grateful if you do find any answers.

Thanks

Hi Will,
Looks like you have not moved to MQTT 2.4 binding yet. Unfortunately I have, and I am still figuring things out.thanks very much for your input

To anyone who looks at this post in the future. I did upgrade my system to 2.4 build and yes my MQTT related devices stopped working. It looks as though (reading the documentation) that MQTT has been changed in 2.4 on wards, so yes you will need to configure MQTT Binding/Broker and possibly change your items setups to query/use the MQTT Bridge/Broker…

Alternatively, I re-enabled the old version 1 MQTT binding in Paper UI (Go to settings and enable 1.x bindings). From here, I went into the Bindings in Paper UI, re-added/enabled the older MQTT 1.x binding and everything started working again (I will obviously have to look at updating properly some time, when I have the time… but this is 1 quick fix for anyone using this whom updates to 2.4 or later).

Thanks Will. Look forward to learning from you 2.4 updates