I want to have a timestamp in my label. I got it working for one individual item:
rule "Update label"
when
Item Tex_Window_W10_GV_Bureau_Zijkant received update
then
val label = Tex_Window_W10_GV_Bureau_Zijkant.label.toString.split(" ")
Tex_Window_W10_GV_Bureau_Zijkant.label = label.get(0) + " " + " " + " (" + Tex_Window_W10_GV_Bureau_Zijkant.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm") + ")"
end
It results in a label like “Livingroom window (30-05-17 11:43)”.
I wanted to apply this rule to all items in the group “gRamen”. So I updated the rule above to this:
rule "Update label"
when
Item gRamen received update
then
gRamen.members.forEach[raam |
val label = raam.label.toString.split(" ")
raam.label = label.get(0) + " " + " " + " (" + raam.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm") + ")"
]
end
Perhaps one of the Items (or Groups) in your Group doesn’t already have a label, or doesn’t have a label that can be split that way.
You could add a check at each step to see if values are what you expect.
Hi @rossko57,
Thanks for your help.
A good idea to check the individual items.
I created a new temp group (gRamen2) with only two items in it. I have updated the timestamp of both their labels successfully with a rule mentioning each of items individually (so no “for each” stuff). That worked.
Then I tried to update the labels again with a group-based rule (again on the temp group containing both items).
I’ve also put the “val” declaration outside the forEach part. And I used “var” instead of “val”.
rule "Update label"
when
Item gRamen2 received update
then
var currentlabel = gRamen2.label.toString.split(" ")
gRamen2.members.forEach[rm |
currentlabel = rm.label.toString.split(" ")
rm.label = currentlabel.get(0) + " " + " " + " (" + rm.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm") + ")"
]
end
No, I don’t think that will work at all. Java has this idea of lambdas, a local workspace, I’m hazy about it but essentially you cannot pass non-final var into a lambda, only final val. And then of course you are not allowed to modify val.
So you must do the work within the lambda
Got me beat. The Item.label feature isn’t exactly well documented, perhaps not intended for real use. But you can read it inside the forEach and set it outside. This going to be something weird about not setting the properties of an Item directly inside a closure, and needing an imaginary Item.updateLabel() method.
Right concept, wrong word. A lambda is a chunk of code that can be treated like a variable. The “local workspace” is called a “context”. A context can be defined by begin and end, { }, and [ ]. Stuff defined inside the context disappears outside of that context.
I’m afraid I’m not the guru you seek. The ability to access the label is a relatively new feature, oneI I’ve never used, is not really documented, and I’m not sure how well it is tested yet.
Since you know you can do each item individually without error, I would try one of the following:
Construct the String and store it in a val and assign that val to the label. Maybe it is having a hard time constructing the new label and assigning it.
Try adding a sleep to the loop to see it the problem is one of timing.
I’m not sure of the mechanism that connects the label to the Item object you get in the .rules. However, I know there is a reason why we must call sendCommand and postUpdate to change an Item’s state instead of just using =. I wonder if the label is intended to read only in rules.
Thank you for sticking around. I understand .label is new and rather unknown.
Sorry I couldn’t test this sooner.
I tried this:
rule "Update label"
when
Item gRamen2 received update
then
Tex_Window_W10_GV_Bureau_Zijkant.label = "This should work"
logInfo ("test", "A. " + Tex_Window_W10_GV_Bureau_Zijkant.label.toString)
gRamen2.members.forEach[rm |
Tex_Window_W10_GV_Bureau_Zijkant.label = "Might work, might not"
logInfo ("test", "B. " + Tex_Window_W10_GV_Bureau_Zijkant.label.toString)
val indirect = Tex_Window_W10_GV_Bureau_Zijkant
indirect.label = "Indirect Test Text"
logInfo ("test", "C. " + indirect.label.toString)
rm.label = "This hasn't worked before"
logInfo ("test", "D. " + rm.label.toString)
]
end
The output is this:
2017-06-01 12:34:11.822 [INFO ] [.eclipse.smarthome.model.script.test] - A. This should work
2017-06-01 12:34:11.826 [INFO ] [.eclipse.smarthome.model.script.test] - B. Might work, might not
2017-06-01 12:34:11.828 [INFO ] [.eclipse.smarthome.model.script.test] - C. Indirect Test Text
2017-06-01 12:34:11.829 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'Update label': Couldn't invoke 'assignValueTo' for feature JvmVoid: (eProxyURI: test.rules#|::0.2.2.2.0.2.7.0.1.0.5::0::/2)
So updating the label works fine in almost all cases, except on the for the “forEach[rm” part.
Any other creative ideas?
I could always go back to old-school approach and mention every individual item separately in my rule:
That’s so weird.
Just for completeness, i would try
indirect.label = "Indirect Test Text"
// just to be sure it gets back to real Item
logInfo ("test", "C. " +Tex_Window_W10_GV_Bureau_Zijkant.label.toString)
val doubleindirect = rm
doubleindirect.label = "Sure it wont work"
logInfo ("test", "C-2. " +Tex_Window_W10_GV_Bureau_Zijkant.label.toString)
rm.label = "This hasn't worked before"
logInfo ("test", "D. " + rm.label.toString)
No surprise, i would expect Items are created anew at each boot from file.items (or PaperUI equivalent), so the original definition is used - and that is desirable.
rule "Update label"
when
Item gRamen2 received update
then
Tex_Window_W10_GV_Bureau_Zijkant.label = "This should work"
logInfo ("test", "A. " + Tex_Window_W10_GV_Bureau_Zijkant.label.toString)
gRamen2.members.forEach[rm |
Tex_Window_W10_GV_Bureau_Zijkant.label = "Might work, might not"
logInfo ("test", "B. " + Tex_Window_W10_GV_Bureau_Zijkant.label.toString)
val indirect = Tex_Window_W10_GV_Bureau_Zijkant
indirect.label = "Indirect Test Text"
// just to be sure it gets back to real Item
logInfo ("test", "C. " + Tex_Window_W10_GV_Bureau_Zijkant.label.toString)
val doubleindirect = rm
doubleindirect.label = "Sure it wont work"
logInfo ("test", "C-2. " +Tex_Window_W10_GV_Bureau_Zijkant.label.toString)
rm.label = "This hasn't worked before"
logInfo ("test", "D. " + rm.label.toString)
]
end
Results in this:
2017-06-01 16:10:12.640 [INFO ] [.eclipse.smarthome.model.script.test] - A. This should work
2017-06-01 16:10:12.642 [INFO ] [.eclipse.smarthome.model.script.test] - B. Might work, might not
2017-06-01 16:10:12.643 [INFO ] [.eclipse.smarthome.model.script.test] - C. Indirect Test Text
2017-06-01 16:10:12.644 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'Update label': Couldn't invoke 'assignValueTo' for feature JvmVoid: (eProxyURI: test.rules#|::0.2.2.2.0.2.7.0.1.0.6::0::/2)
Very odd. What is it about the way the forEach gets the Item, presumably from following group links, that differs from the ‘ordinary’ way.
I think we need the guy who added the .label functionality to begin with … I had a look in smarthome issues but could not find anything related.
Umm, @Kai - are we chasing rainbows or is this supposed to work?