I’m currently working on a controlled dimmer using JSON from a Kodi plugin. The Kodi plugin allows me to send JSON data at certain points basically creating a Theater atmosphere. Here is my rule. At the top of the Rule file there is the default three items found on the wiki JSON Transformations · openhab/openhab1-addons Wiki · GitHub
rule "Home Theater Dimmer"
when
Item HT_Dimmer changed
then
var Number curstate = 0
if(HT_Dimmer.state instanceof PercentType) curstate = HT_Dimmer.state as PercentType
var String json = (HT_Dimmer.state as StringType).toString
// {"_type": "dimDown", "DimDownPercent": "70", "Increments": "5",
// "Speed": "400"}
var String type = transform("JSONPATH", "$._type", json)
if (type == "dimDown") {
var Number dimto = transform("JSONPATH", "$.DimDownPercent", json)
var Number inc = transform("JSONPATH", "$.Increments", json)
var long speed = transform("JSONPATH", "$.Speed", json)
while(curstate<dimto)
{
curstate=curstate - inc
sendCommand(Light_LivRoom_Steps_Dim,curstate)
Thread::sleep(speed)
}
}
end
My issue is openHAB Designer keeps showing transform as though it is not valid. It is telling me this: Couldn’t resolve reference to JvmIdentifiableElement ‘transform’.
I tried to run this anyway using POSTMAN in Chrome to test. I sent the header as application/json and the body of {“_type”: “dimDown”, “DimDownPercent”: 70, “Increments”: 5, “Speed”: 400} and i get a created and I see the variable gets set. However the logfile shows this.
Error during the execution of rule ‘Home Theater Dimmer’: Could not invoke method: org.openhab.model.script.lib.NumberExtensions.operator_lessThan(java.lang.Number,java.lang.Number) on instance: null
So first, why does transform show underlined red and second how can I send this information to my item to trigger my rule with the variables. Or can I send my JSON directly to the rule and fire it that way? Thanks for the help!
run? My guess is it didn’t convert either. Am I not using JSONPATH right? I can see the string does get set to the value string that I send it cause I displayed it on my sitemap to verify its getting passed, it seems that its not able to use transform to pull the information out or parse the data I’d say. Which would be why my values are returning null hence the error log entry and the rule not triggering. Is there something that I possibly didn’t install on my vm or should it of installed when installing OpenHAB? Please let me know.
What is the HT_Dimmer item? In the first ‘if’ statement, we are checking for a percentage type. However, in the later json assignment/transforms, you are expecting a json string. Which is correct?
Assuming that the HT_Dimer is actually getting a json string and is failing on the transforms, do you have the correct imports at the top of your rule file?
Do you know which line the null error is on? Given that it says operator_lessThan I assume it is failing on the while(curstate<dimto) line. This being the case, I would check the values of curstate first, and then the value of dimto. You can do this easily by printing to the log, or using e.g. logInfo etc. Again the question that comes to mind is what is HT_Dimmer.state, as this is being assigned to curstate.
I think once you get the above resolved, the triggering of rules with your variables should hopefully be straight forward.
Hello @smar - now that you are saying that I guess this is definately an issue. I’m sending the json string to HT_Dimmer item which I have as a string.state so there for curstate is more then likely getting the NULL value due to this. I’ve updated my rule to the following. It seems I no longer get the error to show in the log, however the state of the light does not change.
/* CinemaVision Slow Dimmer */
rule "Home Theater Dimmer"
when
Item HT_Dimmer changed
then
var Number curstate = 0
if(Light_MasterBed_Lamp_Dim.state instanceof PercentType) curstate = Light_MasterBed_Lamp_Dim.state as PercentType
var String json = (HT_Dimmer.state as StringType).toString
// {"_type": "dimDown", "DimDownPercent": "70", "Increments": "5",
// "speed": "400"}
var String type = transform("JSONPATH", "$._type", json)
if (type == "dimDown") {
var Number dimto = transform("JSONPATH", "$.DimDownPercent", json)
var Number inc = transform("JSONPATH", "$.increments", json)
var long speed = transform("JSONPATH", "$.speed", json)
logInfo("Rules", "Dimmer set", dimto)
logInfo("Rules", "Dimmer set", inc)
logInfo("Rules", "Dimmer set", speed)
while(curstate>dimto)
{
curstate=curstate - inc
sendCommand(Light_MasterBed_Lamp_Dim, curstate)
Thread::sleep(speed)
}
}
end
Currently I have this at the top of my rules file.
So here is an update and maybe someone can tell me why. In the while loop, I can not place ANY of the variables that I have declared. I verified that the value gets set by posting it to a variable and displaying the information with a sitemap. also another thing I was wondering that i have found is that every time I use post to trigger the rule I have to change the name of the type in order for it to reupdate. I can see this causing issues with how I am trying to use this. Though I could clear the HT_Dimmer State so each post is new, I can test this and I’m sure thats how I’ll do it. Another thing is I can’t seem to use the if statement. If I place my rule as this
/* CinemaVision Slow Dimmer */
rule "Home Theater Dimmer"
when
Item HT_Dimmer changed
then
var Number curstate = 0
if(Light_MasterBed_Lamp_Dim.state instanceof PercentType) curstate = Light_MasterBed_Lamp_Dim.state as PercentType
var String json = (HT_Dimmer.state as StringType).toString
// {"_type": "dimDown", "DimDownPercent": "70", "Increments": "5",
// "speed": "400"}
var String type = transform("JSONPATH", "$._type", json)
var Number dimto = transform("JSONPATH", "$.DimDownPercent", json)
var Number inc = transform("JSONPATH", "$.increments", json)
var long speed = transform("JSONPATH", "$.speed", json)
while(curstate>50)
{
curstate=curstate - 5
sendCommand(Light_MasterBed_Lamp_Dim, curstate)
Thread::sleep(500)
}
end
If I use this rule I can get a slow dim from 100% or whatever I have the light as down to 50% slowly. Is the system limited to where this is something I can not do? It seems everything I have written within the above rule should work but it does not and when I break it down it comes down to variables not allowed to be used.
I figured that was the case, I’ve actually made sure that when I updated it they are 100% case correct. I noticed my comment was wrong but didn’t bother with it. I know the extraction works because if I did say this in my rule after the
var String type = transform(“JSONPATH”, “$._type”, json) with
postUpdate(Test_var, type)
I created a string on my items file like so
String Test_var "Test Data output [%s]"
Added to sitemap like so
Text Item=Test_var
My sitemap shows that infact dimDown gets set to that variable and thats what displays. I can do that for each of the variables I pull out of the JSON string. The issue comes when trying to use those variables is where the issue now is. Nothing will trigger unless the value after curstate in the while loop start, the 5 and the 400. Unless those values are hardcoded nothing happens. Thats the issue I am currently having. I know the variables are there and set its just wont let me use them.
2015-09-16 00:51:42.987 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule ‘Home Theater Dimmer’: Could not invoke method: org.openhab.model.script.lib.NumberExtensions.operator_greaterThan(java.lang.Number,java.lang.Number) on instance: null
Rule
/* CinemaVision Slow Dimmer */
rule "Home Theater Dimmer"
when
Item HT_Dimmer changed
then
var Number curstate = 0
if(Light_MasterBed_Lamp_Dim.state instanceof PercentType) curstate = Light_MasterBed_Lamp_Dim.state as PercentType
var String json = (HT_Dimmer.state as StringType).toString
// {"_type": "dimDown", "DimDownPercent": "70", "Increments": "5",
// "speed": "400"}
var String type = transform("JSONPATH", "$._type", json)
logInfo("HT Rule", "JSON Information " + type)
if (type == "dimDown") {
logInfo("HT Rule", "Entered Loop")
var Number dimto = transform("JSONPATH", "$.DimDownPercent", json)
logInfo("HT Rule", "dimto variable = " + dimto)
var Number inc = transform("JSONPATH", "$.increments", json)
logInfo("HT Rule", "inc variable = " + inc)
var long speed = transform("JSONPATH", "$.speed", json)
logInfo("HT Rule", "speed variable = " + speed)
while(curstate>dimto)
{
curstate=curstate - inc
sendCommand(Light_MasterBed_Lamp_Dim, curstate)
Thread::sleep(speed)
}
}
end
The rule triggers, variable set however the while loop does not trigger. So I’m getting the null issue still but as you can see the log shows all of these variables were set.
I used the above as sample data, and then ran this block:
var String type = transform("JSONPATH", "$._type", json)
var Number dimto = transform("JSONPATH", "$.DimDownPercent", json)
var Number inc = transform("JSONPATH", "$.increments", json)
var long speed = transform("JSONPATH", "$.speed", json)
with a bunch of logInfo’s so I could see where it was failing… so I’m guessing your sample data-snippet is wrong (incorrect case) and the real data from the service has the correct case?
Either way, if Light_MasterBed_Lamp_Dim isn’t a PercentType, then it’ll bypass the code and curstate will be 0, so the latter dimming code will also be bypassed.
if(Light_MasterBed_Lamp_Dim.state instanceof PercentType) curstate = Light_MasterBed_Lamp_Dim.state as PercentType
Put this code in a {} block, and add in the logInfo("HT Rule", "... setting curstate to " ...) calls so you can see what’s really going on.
Whats interesting is when I place this in designer its giving me this error and underlining it in red.
Missig error message for org.eclipse.xtext.xbase.validation.IssueCodes.invalid_generic_argument_types
HOWEVER, this works, soon as I placed that new Integer line in there it works like a charm. THANK YOU THANK YOU THANK YOU. This is going to make my Home Theater setup that much closer to an actual theater!
I tend to do it all cmdline, and have never gotten the Designer to work. It’s faster to rev-test-rev on the cmdline anyhow (and thick desktop clients are soooo 90’s )
I was looking to see how I would send it to openhab if security was enabled. I got it to work but i decided I didnt need security internally just have it for external only. Thanks for the tip if I wanna send to securted devices though.