Counter in If-statement (Javascript) not working consistently

I’d like to have a counter showing how many lights (and similarly windows, too) are currently running (brightness >0). I simply check if a light’s brightness>0 and then increase the counter by 1.
However, this doesn’t work consistently:

Here’s the code, most of it for logging purposes:

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);

anzahl = 0;   // counter starts with 0
logger.info("---- Test Anzahl, start with 0, (should increase in following lines) : " +  anzahl);
if (items["LeuchteHuegross_Farbe"].toString().split(",")[2] >0 ) {anzahl=anzahl+1; logger.info("LeuchteHuegross_Farbe" +  items["LeuchteHuegross_Farbe"]);}
if (items["LeuchteHueklein_Farbe"].toString().split(",")[2] >0 ) {anzahl=anzahl+1;logger.info("LeuchteHueklein_Farbe" +  items["LeuchteHueklein_Farbe"]);}
if (items["LeuchteMobil_Farbe"].toString().split(",")[2] >0 ) {anzahl=anzahl+1;logger.info("LeuchteMobil_Farbe" +  items["LeuchteMobil_Farbe"]);}
if (items["LeuchteWohnzimmer_Farbe"].toString().split(",")[2] >0 ) {anzahl=anzahl+1;logger.info("LeuchteWohnzimmer_Farbe" +  items["LeuchteWohnzimmer_Farbe"]);}
if (items["EsszimmerTisch_Farbe"].toString().split(",")[2] >0 ) {anzahl=anzahl+1;logger.info("EsszimmerTisch_Farbe" +  items["EsszimmerTisch_Farbe"]);}
if (items["EsszimmerWein_Farbe"].toString().split(",")[2] >0 ) {anzahl=anzahl+1;logger.info("EsszimmerWein_Farbe" +  items["EsszimmerWein_Farbe"]);}
if (items["EsszimmerKlavier_Farbe"].toString().split(",")[2] >0 ) {anzahl=anzahl+1;logger.info("EsszimmerKlavier_Farbe" +  items["EsszimmerKlavier_Farbe"]);}
if (items["Frosch_Farbe"].toString().split(",")[2] >0 ) {anzahl=anzahl+1;logger.info("Frosch_Farbe" +  items["Frosch_Farbe"]);}


logger.info("------- now just logging values ------------");
logger.info("Test Anzahl gesamt (should be as many as lines above): " +  anzahl);
events.sendCommand("AnzahlLampenAn",anzahl); 

logger.info("------- all lightbulbs incl off ------------");
logger.info("LeuchteHuegross_Farbe" +  items["LeuchteHuegross_Farbe"]);
logger.info("LeuchteHueklein_Farbe" +  items["LeuchteHueklein_Farbe"]);
logger.info("LeuchteMobil_Farbe" +  items["LeuchteMobil_Farbe"]);
logger.info("LeuchteWohnzimmer_Farbe" +  items["LeuchteWohnzimmer_Farbe"]);
logger.info("EsszimmerTisch_Farbe" +  items["EsszimmerTisch_Farbe"]);
logger.info("EsszimmerWein_Farbe" +  items["EsszimmerWein_Farbe"]);
logger.info("EsszimmerKlavier_Farbe" +  items["EsszimmerKlavier_Farbe"]);
logger.info("Frosch_Farbe" +  items["Frosch_Farbe"]);


The rule is executed when a member of the group Leuchten (Lightbulbs) receives a command or changes (one should’ve been enough, but when it wasn’t working I added another but I guess thats not relevant).

triggers:
  - id: "1"
    configuration:
      groupName: Leuchten_Alle
    type: core.GroupCommandTrigger
  - id: "3"
    configuration:
      itemName: Leuchten_Alle
    type: core.ItemStateChangeTrigger

I’d appreciate hints what to look for :slight_smile:

A point might be that the trigger ReceivedCommand can raise the rule before the command is prosecuted the lamp(I.e. the lamp did not change to ON yet). If always one lamp is missing and that’s the one that triggered the rule you have the cause.

2 Likes

I can’t read pictures of logs so I don’t know the specific behavior you are looking for. Some things I notice:

  • the comparisons in the if statement will be comparing a String to an int. That may not give you the result you are expecting. You need to parse the String to an int or, in some limited cases, it might be OK to convert the 0 to a "0". Alphabetical comparisons of Strings will work as long as the number strings are less than two digits.

  • if these Items are Color Items or Dimmer Items forget all the complicated string manipulation, pull the Item from the ir and call getStateAs(OnOffType) and the if statements will be much more self documenting.

  • having said all that, you can also use a filter on the Group’s members. That’s probably better anyway as you won’t have to modify the rule when adding or removing lights from the Group.

var Collectors = Java.type("java.util.stream.Collectors");
var numOn = ir.getItem("Leuchten_Alle")
              .members
              .stream()
              .filter(function(i){ return i.getStateAs(OnOffType) == ON; }
              .collect(Collectors.counting());
events.sendCommand("AnzahlLampenAn", numOn);

NOTE: I just typed in the above, there might be a typo.

  • As opus indicates, for received command, the Item that received the command is unlikely to have changed state in response to the command yet.
2 Likes

Hello Rich and opus,
thank you for your ideas and support.
The version with ir seems quite the thing to use. I have an idea what is supposed to happen there, although I (by far) couldn’t have done this myself (is there a documentation /beginner-friendly introduction to this way of programming somewhere? But if it would require to also learn Java, that would be too much for me).
There might be a slight mistake in your code, as I got this message in the log:

 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Leuchten_An_Anzahl' failed: <eval>:39:45 Expected , but found ;

Line 39 is the next to last line in your code (simply replacing ; with , wouldn’t work)

And opus’ remark seems to hit the spot, too. Is there anything I can do about it ?

Here’s the thing though. No matter what rules language you are using, be it Rules DSL, Python, JavaScript, whatever, every time you are interacting with openHAB, you are interacting with Java Objects. The code above is using the Java Streams API to work with the Java List Object returned by calling members on the Java GroupItem Object. Sending the command to the Item is done through the Java events Object that gets injected into the rule.

If you are using Rules DSL, there are enough examples where you probably never have to look at actual Java stuff. In JavaScript there are not enough examples or docs posted yet. If you are going to use JavaScript as a rules language, you will have to be able to find, browse, and search through at least the JavaDocs for openHAB and for the Java language itself.

Even when a bunch of docs are written and examples posted, I do not see a world where you will be able to avoid using these references at least some of the time. But luckily the only two pages you’ll probably ever have to look at are ZonedDateTime and the Stream API which is used above.

As for doing this yourself, well no one expects that you would have been able to. But now you can and now you should have the tools to do more along these lines. And future readers of this thread will be able to as well.

A quick look shows that the .filter line is missing the closing ).

This is an important thing to understand about openHAB. It’s been written about a bunch and discussed a little in the docs as well.

A command is fundamentally different from an update or a change. Take a Dimmer Item for example. It has a PercentType as it’s state. But you can sendCommand(INCREASE) to a Dimmer Item. A rule that triggers on received command will run and in that rule receivedCommand will be INCREASE. But the state of the Dimmer Item will never be INCREASE. INCREASE is a command, not a state.

And as opus described, a command will trigger a rule immediately when the command is received. Even with autoupdate enabled, it will likely be some time before the Item’s state updates in response to the command. Without autoupdate, it could be quite some time before the Item updates in response to the command.

If the purpose of this rule is to simply keep track of which of your Color Items are ON, then you don’t care about commands at all. You care about the Item’s state. So trigger the rule when the Items change state. The Item will be the new state before the rule triggers because the changed event doesn’t occur until after the Item changes state.

1 Like

Hello Rich,

thank you for your great explanations! I think I understood your explanation about the trigger command vs change state.
(Edit: found my mistake I had described and and now deleted it)

But I get this error message:

2021-04-15 08:06:07.433 [ERROR] [e.automation.internal.RuleEngineImpl] - Failed to execute rule 'Leuchten_An_Anzahl': Fail to execute action: 2

And here the code (incl. the “)”)

var Collectors = Java.type("java.util.stream.Collectors");
var numOn = ir.getItem("Leuchten_Alle")
              .members
              .stream()
              .filter(function(i){ return i.getStateAs(OnOffType) == ON; })
              .collect(Collectors.counting());

logger.info("Rule triggered!");                       
logger.info("numOn " + numOn);                      
events.sendCommand("AnzahlLampenAn", numOn);

It’s possible for group member Items to have states that cannot be had as OnOffType e.g. NULL or UNDEF. Inspect your Items to find outif you need to code around this.

While that’s true I don’t think that would generate an error in the above code. If one of the members is NULL or UNDEF it wouldn’t make it past the filter.

@Ursusprimus, add a log statement before the var numOn line to verify that is the line that is falling.

Then try changing the collect to use Collectors.toList() in case there is a problem with counting. Then log out the list the filter returned and confirm it’s the expected set of Items.

Pure curiosity: Is there a benefit to using the collector over just using the stream count method?

Probably not. I tend towards Collectors because I remember them more than anything else. And Collectors are the only way I know of to get back to a List or Map or Set at the end of the stream.

I’m not really sure if I did what you asked me to. But if I interpret the message correctly, the problem may indeed have something to do with null (line 6):

2021-04-15 17:24:45.915 [INFO ] [org.openhab.rule.Leuchten_An_Anzahl ] - What to log here?
2021-04-15 17:24:45.932 [INFO ] [org.openhab.rule.Leuchten_An_Anzahl ] - Like this??: java.util.stream.Collectors$CollectorImpl@19691bc
2021-04-15 17:24:45.934 [INFO ] [org.openhab.rule.Leuchten_An_Anzahl ] - Rule triggered!
2021-04-15 17:24:45.936 [INFO ] [org.openhab.rule.Leuchten_An_Anzahl ] - numOn java.util.stream.ReferencePipeline$2@109a8b9
2021-04-15 17:24:45.951 [WARN ] [e.automation.internal.RuleEngineImpl] - Fail to execute action: 2
java.lang.IllegalArgumentException: The argument 'command' must not be null.
	at org.openhab.core.events.AbstractEventFactory.checkNotNull(AbstractEventFactory.java:115) ~[?:?]
	at org.openhab.core.items.events.ItemEventFactory.assertValidArguments(ItemEventFactory.java:401) ~[?:?]
	at org.openhab.core.items.events.ItemEventFactory.createCommandEvent(ItemEventFactory.java:221) ~[?:?]
	at org.openhab.core.items.events.ItemEventFactory.createCommandEvent(ItemEventFactory.java:237) ~[?:?]
	at org.openhab.core.automation.module.script.internal.defaultscope.ScriptBusEvent.sendCommand(ScriptBusEvent.java:94) ~[?:?]
	at jdk.nashorn.internal.scripts.Script$Recompilation$1497$\^eval\_$cu1$restOf.:program(<eval>:45) ~[?:?]

Here’s the code:

var Collectors = Java.type("java.util.stream.Collectors");
logger.info("What to log here?");
var numOn = ir.getItem("Leuchten_Alle")
              .members
              .stream()
              .filter(function(i){ return i.getStateAs(OnOffType) == ON; })
           //   .Collectors.toList()
           //   .collect(Collectors.counting());
logger.info("Like this??: " + Collectors.toList());
logger.info("Rule triggered!");                       
logger.info("numOn " + numOn);                      
events.sendCommand("AnzahlLampenAn", numOn);

OK, I didn’t want you to comment out the collect, just change Collectors.counting() with Collectors.toList().

.collect(Collectors.toList());

Instead of a number, that will give you a List containing all the Items that passed the filter function (i.e. they are ON).

Without that conversion the log statements don’t really tell us anything.

These errors are shown

2021-04-15 19:47:56.412 [WARN ] [e.automation.internal.RuleEngineImpl] - Fail to execute action: 2
java.lang.ClassCastException: Cannot cast jdk.dynalink.beans.StaticClass to java.lang.Class
	at java.lang.Class.cast(Class.java:3605) ~[?:?]
	at jdk.nashorn.internal.scripts.Script$Recompilation$410$2538A$\^eval\_.numOn(<eval>:39) ~[?:?]
	at jdk.nashorn.javaadapters.java_util_function_Predicate.test(Unknown Source) ~[?:?]
and many more similar lines

when running this rule

var Collectors = Java.type("java.util.stream.Collectors");
var numOn = ir.getItem("Leuchten_Alle")
              .members
              .stream()
              .filter(function(i){ return i.getStateAs(OnOffType) == ON; })
              .collect(Collectors.toList());

logger.info("Like this??: " + Collectors.toList());
logger.info("Rule triggered!");                       
logger.info("numOn " + numOn);                      
events.sendCommand("AnzahlLampenAn", numOn);

That’s a new error to me. Add logging to see which of the lines it’s failing on. Why did you remove the log before the var numnOn?

This one?:

logger.info("What to log here?");

because it doesn’t add any information. But I can insert it again. My problem is that I can’t exactly place the logging and its specifics because I don’t really understand what’s happening …
I tried this, but that doesn’t seem to work/add information:

var Collectors = Java.type("java.util.stream.Collectors");
logger.info("What to log here?");
var numOn = ir.getItem("Leuchten_Alle")
              .members
              .stream()
              .filter(function(i){ return i.getStateAs(OnOffType) == ON; })
              .collect(Collectors.toList());

logger.info("Like this - collector list??: " + Collectors.toList());
logger.info("Like this - ir.get item??: " + ir.getItem("Leuchten_Alle")); 
logger.info("Like this - members??: " + ir.members); 
logger.info("Rule triggered!");                       
logger.info("numOn " + numOn);                      
events.sendCommand("AnzahlLampenAn", numOn);

which gets this output (the entire post this time, maybe it helps:

2021-04-15 20:52:08.804 [INFO ] [org.openhab.rule.Leuchten_An_Anzahl ] - What to log here?
2021-04-15 20:52:08.824 [WARN ] [e.automation.internal.RuleEngineImpl] - Fail to execute action: 2
java.lang.ClassCastException: Cannot cast jdk.dynalink.beans.StaticClass to java.lang.Class
	at java.lang.Class.cast(Class.java:3605) ~[?:?]
	at jdk.nashorn.internal.scripts.Script$Recompilation$506$2538A$\^eval\_.numOn(<eval>:39) ~[?:?]
	at jdk.nashorn.javaadapters.java_util_function_Predicate.test(Unknown Source) ~[?:?]
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176) ~[?:?]
	at java.util.Iterator.forEachRemaining(Iterator.java:133) ~[?:?]
	at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[?:?]
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[?:?]
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[?:?]
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[?:?]
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:?]
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[?:?]
	at jdk.nashorn.internal.scripts.Script$Recompilation$505$\^eval\_$cu1$restOf.:program(<eval>:40) ~[?:?]
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:655) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:527) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:456) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:413) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:409) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:162) ~[jdk.scripting.nashorn:?]
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) ~[java.scripting:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:62) ~[?:?]
	at java.util.Optional.ifPresent(Optional.java:183) ~[?:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:59) ~[?:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1179) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1031) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1047) [bundleFile:?]
	at org.openhab.core.automation.rest.internal.RuleResource.runNow(RuleResource.java:314) [bundleFile:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
	at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179) [bundleFile:1.0.9]
	at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) [bundleFile:1.0.9]
	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:201) [bundleFile:1.0.9]
	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:104) [bundleFile:1.0.9]
	at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) [bundleFile:1.0.9]
	at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) [bundleFile:1.0.9]
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) [bundleFile:1.0.9]
	at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [bundleFile:1.0.9]
	at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:216) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:301) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:220) [bundleFile:1.0.9]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) [bundleFile:3.1.0]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:276) [bundleFile:1.0.9]
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:852) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:544) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) [bundleFile:?]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:536) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1581) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1307) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:293) [bundleFile:?]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:482) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1549) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1204) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) [bundleFile:?]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.Server.handle(Server.java:494) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:374) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:268) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:782) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:918) [bundleFile:9.4.20.v20190813]
	at java.lang.Thread.run(Thread.java:834) [?:?]

But maybe I/we might have to accept that this won’t work and use a less elegant version?

Yes it does. It tells us where the error is occurring on the var Collectors line for some reason or on the var numOn line. The error posted is inscrutable and could be coming from either line.

Replacing the line confirms that something weird isn’t suddenly happening with the import.

This will work. I have done this in multiple places in my rules and in much more complicated ways. For example:

  context.getNames = function(groupName, filterFunc) {
    var Collectors = Java.type("java.util.stream.Collectors");
    return context.ir.getItem(groupName)
                     .members
                     .stream()
                     .filter(filterFunc)
                     .map(function(i) {
                       return context.getName(i.name);
                     })
                     .collect(Collectors.joining(", "));
  };

That pulls all the Items from a Group that match a filter function (passed in as an argument), extracts the Item’s name and creates a comma separated list of the names as a String to return. I use it for reports like “The following batteries are low: Front Door Lock, Top Floor Smoke Alarm”.

I’ve not see the class cast exception before so I want to understand what is causing it so I can tell people how to avoid it in the future.

Here’s an idea, lets add logging to the filter function to see if it’s the getStateAs that’s failing.

var Collectors = Java.type("java.util.stream.Collectors");
logger.info("Collectors imported, about to filter the Group members");
var numOnList = ir.getItem("Leuchten_Alle")
              .members
              .stream()
              .filter(function(i){ 
                  var currState = i.getStateAs(OnOffType);
                  logger.info(i.name +"'s state is " + currState);
                  return currState == ON; 
              })
              .collect(Collectors.toList());
logger.info("The filter returned the following Items: " + numOnList.toString());
logger.info("There are " + numOnList.size() + " lights that are ON");

All right, then let’s get to the bottom of this. I ran your code and this is what happens (to make sure I added a line above and a few below):

2021-04-16 07:52:49.803 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'AlexaHolger_MedienSpielzeit' changed from 229 s to 230 s
==> /var/log/openhab/openhab.log <==
2021-04-16 07:52:50.050 [INFO ] [org.openhab.rule.Leuchten_An_Anzahl ] - Collectors imported, about to filter the Group members
2021-04-16 07:52:50.051 [ERROR] [e.automation.internal.RuleEngineImpl] - Failed to execute rule 'Leuchten_An_Anzahl': Fail to execute action: 2
==> /var/log/openhab/events.log <==
2021-04-16 07:52:50.039 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'LeuchteHuegross_Farbe' received command 36,30,56
2021-04-16 07:52:50.042 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'LeuchteHuegross_Farbe' predicted to become 36,30,56
2021-04-16 07:52:50.046 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'LeuchteHuegross_Farbe' changed from 36,30,16 to 36,30,56
2021-04-16 07:52:50.804 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'AlexaHolger_MedienSpielzeit' changed from 230 s to 231 s

The last two logger-infos don’t seem to appear…

Edit:
Since this is an unusual problem that may have different causes than the pure code, I checked for other possibly related errors and found this:

2021-04-16 07:51:46.635 [ERROR] [y.upnp.internal.UpnpDiscoveryService] - Participant 'org.openhab.binding.hue.internal.discovery.HueBridgeDiscoveryParticipant' threw an exception
java.lang.IllegalArgumentException: ID segment '73:ED:34:05:' contains invalid characters. Each segment of the ID must match the pattern [\w-]*.
	at org.openhab.core.common.AbstractUID.validateSegment(AbstractUID.java:98) ~[bundleFile:?]
	at org.openhab.core.common.AbstractUID.<init>(AbstractUID.java:76) ~[bundleFile:?]
	at org.openhab.core.common.AbstractUID.<init>(AbstractUID.java:59) ~[bundleFile:?]
	at org.openhab.core.thing.UID.<init>(UID.java:57) ~[bundleFile:?]
	at org.openhab.core.thing.ThingUID.<init>(ThingUID.java:47) ~[bundleFile:?]
	at org.openhab.binding.hue.internal.discovery.HueBridgeDiscoveryParticipant.getThingUID(HueBridgeDiscoveryParticipant.java:80) ~[?:?]
	at org.openhab.binding.hue.internal.discovery.HueBridgeDiscoveryParticipant.createResult(HueBridgeDiscoveryParticipant.java:54) ~[?:?]
	at org.openhab.core.config.discovery.upnp.internal.UpnpDiscoveryService.remoteDeviceAdded(UpnpDiscoveryService.java:158) [bundleFile:?]
	at org.jupnp.registry.RemoteItems$1.run(RemoteItems.java:114) [bundleFile:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
	at java.lang.Thread.run(Thread.java:834) [?:?]

I didn’t pay much attention to this because the lights are working as expected; but in our context it might be relevant.

The second error isn’t relevant. That’s something internal o the Hue binding.

OK, one more change.

logger.info("Collectors imported, about to filter the Group members");
var numOnList = ir.getItem("Leuchten_Alle")
              .members
              .stream()
              .filter(function(i){ 
                  logger.info("Processing Item " + i.name + " whose current state is " + i.state);
                  var currState = i.getStateAs(OnOffType);
                  logger.info(i.name +"'s state is " + currState);
                  return currState == ON; 
              })
              .collect(Collectors.toList());
logger.info("The filter returned the following Items: " + numOnList.toString());
logger.info("There are " + numOnList.size() + " lights that are ON");

Here’s the result:

2021-04-16 16:39:11.989 [INFO ] [org.openhab.rule.Leuchten_An_Anzahl ] - Collectors imported, about to filter the Group members
2021-04-16 16:39:12.011 [INFO ] [org.openhab.rule.Leuchten_An_Anzahl ] - Processing Item EsszimmerTisch_Farbe whose current state is 29,83,0
2021-04-16 16:39:12.014 [WARN ] [e.automation.internal.RuleEngineImpl] - Fail to execute action: 2
java.lang.ClassCastException: Cannot cast jdk.dynalink.beans.StaticClass to java.lang.Class
	at java.lang.Class.cast(Class.java:3605) ~[?:?]
	at jdk.nashorn.internal.scripts.Script$Recompilation$498$340A$\^eval\_.numOnList(<eval>:10) ~[?:?]
	at jdk.nashorn.javaadapters.java_util_function_Predicate.test(Unknown Source) ~[?:?]
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176) ~[?:?]
	at java.util.Iterator.forEachRemaining(Iterator.java:133) ~[?:?]
	at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[?:?]
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[?:?]
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[?:?]
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[?:?]
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:?]
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[?:?]
	at jdk.nashorn.internal.scripts.Script$Recompilation$497$\^eval\_$cu1$restOf.:program(<eval>:14) ~[?:?]
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:655) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:527) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:456) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:413) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:409) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:162) ~[jdk.scripting.nashorn:?]
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) ~[java.scripting:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:62) ~[?:?]
	at java.util.Optional.ifPresent(Optional.java:183) ~[?:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:59) ~[?:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1179) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1031) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1047) [bundleFile:?]
	at org.openhab.core.automation.rest.internal.RuleResource.runNow(RuleResource.java:314) [bundleFile:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
	at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179) [bundleFile:1.0.9]
	at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) [bundleFile:1.0.9]
	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:201) [bundleFile:1.0.9]
	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:104) [bundleFile:1.0.9]
	at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) [bundleFile:1.0.9]
	at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) [bundleFile:1.0.9]
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) [bundleFile:1.0.9]
	at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [bundleFile:1.0.9]
	at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:216) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:301) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:220) [bundleFile:1.0.9]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) [bundleFile:3.1.0]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:276) [bundleFile:1.0.9]
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:852) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:544) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) [bundleFile:?]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:536) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1581) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1307) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:293) [bundleFile:?]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:482) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1549) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1204) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) [bundleFile:?]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.Server.handle(Server.java:494) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:374) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:268) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:782) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:918) [bundleFile:9.4.20.v20190813]
	at java.lang.Thread.run(Thread.java:834) [?:?]

By the way: My fronttail-logger sometimes quits showing values:


I then have to reboot the raspi. Do you have an idea what I could do about it?