Adding timestamp in my label

Hi,

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

But now I get this error:

2017-05-30 11:50:53.114 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'Update label': Couldn't invoke 'assignValueTo' for feature JvmVoid:  (eProxyURI: test.rules#|::0.2.2.2.0.0.7.0.1.0.1::0::/2)

I don’t get it. Why would it work for a single item but not for a group?

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

Unfortunately, I get the same error. :frowning:

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

	gRamen2.members.forEach[rm |
		logInfo ("test", "raw label " + rm.label.toString)
		var currentlabel = rm.label.toString.split("   ")
		logInfo ("test", "processed label " + currentlabel.get(0))
		logInfo ("test", "raw datestamp " + rm.lastUpdate.toDateTime.toString)
		logInfo ("test", "processed datestamp " + rm.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm"))
		rm.label = currentlabel.get(0) + "   (" + rm.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm") + ")"
	]

Thanks.

With this approach, I can conclude that the first lines do their job. Openhab.log output shows:

2017-05-30 13:39:36.125 [INFO ] [.eclipse.smarthome.model.script.test] - raw label Raam Keuken zijkant rechts   (30-05-17 12:40)
2017-05-30 13:39:36.126 [INFO ] [.eclipse.smarthome.model.script.test] - processed label Raam Keuken zijkant rechts
2017-05-30 13:39:36.127 [INFO ] [.eclipse.smarthome.model.script.test] - raw datestamp 2017-05-30T12:44:18.334+02:00
2017-05-30 13:39:36.128 [INFO ] [.eclipse.smarthome.model.script.test] - processed datestamp 30-05-17 12:44

It goes wrong here;

rm.label = currentlabel.get(0) + "   (" + rm.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm") + ")"

And even when I want to update the label with a fixed value:

rm.label = "Something"

I get that “Couldn’t invoke ‘assignValueTo’ for feature JvmVoid” error.

I don’t get that updating a label outside of this loop works fine, and with this approach it doesn’t…

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.

Xtend guru required …

EDIT … try this out

	gRamen2.members.forEach[rm |
		var myItem = rm
		logInfo ("test", "raw label " + myItem.label.toString)
		var currentlabel = myItem.label.toString.split("   ")
		logInfo ("test", "processed label " + currentlabel.get(0))
		logInfo ("test", "raw datestamp " + myItem.lastUpdate.toDateTime.toString)
		logInfo ("test", "processed datestamp " + myItem.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm"))
		myItem.label = currentlabel.get(0) + "   (" + myItem.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm") + ")"
	]

rm is like a val and cannot be modified ?

I just tried it, to no avail… :frowning:

Let’s hope (another) Xtend guru has some additional ideas…

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.

As an experiment, I would test setting the .label directly in the forEach context (thankyou Rich!)

	Tex_Window_W10_GV_Bureau_Zijkant.label = "This should work"  
	gRamen2.members.forEach[rm |
		Tex_Window_W10_GV_Bureau_Zijkant.label = "Might work, might not"  
		val indirect = Tex_Window_W10_GV_Bureau_Zijkant
		indirect.label = "Indirect Test Text"
	]

Obviously its not useful, but should give an idea if the problem is to do with the [ ] context or with the way the forEach offers the Item.

Can’t play myself, no .label feature in OH1

Hi guys,

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? :slight_smile:

I could always go back to old-school approach and mention every individual item separately in my rule:

	var 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") + ")"
	label = Tex_Window_W06_GV_Keuken_ZijkantRechts.label.toString.split("   ")
	Tex_Window_W06_GV_Keuken_ZijkantRechts.label = label.get(0) + " " + " " + " (" + Tex_Window_W06_GV_Keuken_ZijkantRechts.lastUpdate.toDateTime.toString("dd-MM-yy hh:mm") + ")"

BTW, I’ve also learned that adjusted labels are not persisted (the value of that same item is). Not an issue for me, but maybe interesting to know.

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.

Unfortunately.

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"
				// 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)

@rlkoshak: adding sleep also didn’t do anything.

rule "Update label"

when
	Item gRamen2 received update
then
	gRamen2.members.forEach[rm |
		Tex_Window_W06_GV_Keuken_ZijkantRechts.label = "Try 0"  
		logInfo ("test", "A. " + Tex_Window_W06_GV_Keuken_ZijkantRechts.label.toString)
		val indirect = rm
		logInfo ("test", "B. " + indirect)
		Thread::sleep(1000)
		indirect.label = "Try 2"
		Thread::sleep(1000)
		logInfo ("test", "C. " + indirect)		
	]
end

Result:

2017-06-01 16:31:01.035 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'test.rules'
2017-06-01 16:31:09.191 [INFO ] [.eclipse.smarthome.model.script.test] - A. Try 0
2017-06-01 16:31:09.191 [INFO ] [.eclipse.smarthome.model.script.test] - B. Tex_Window_W06_GV_Keuken_ZijkantRechts (Type=NumberItem, State=0, Label=Try 0, Category=raam, Groups=[gAlarm, gGV_Keuken, gRamen, gRamen2])
2017-06-01 16:31:10.192 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'Update label': Couldn't invoke 'assignValueTo' for feature JvmVoid:  (eProxyURI: test.rules#|::0.2.2.2.0.0.7.0.1.0.5::0::/2)

I’m out of ideas…

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?

@Kai: I run an older 2.1 snapshot version (Build #838). I’m not sure if this is relevant information. But maybe this is fixed in a future release.