Which options exist to implement an automatic cycle color change to all bulbs of a scene?

Many thanks for this lot of infomation, @rikoshak!
It ironed out some folds and knots in my picture of openhab4.

I firstly installed npm including he bunch of dependencies. Then I installed your openhab_rules_tools. I now have a folder /etc/openhab/automation/js/node_modules/openhab_rules_tools with some files in it. Looks OK.

To find the templates, it took me awhile. The documentation tells, to look in Settings - Automation (I found Settings under Administration). And I looked a lot :slight_smile: without finding any. Not under Rules or under Scripts. I even reinstalled your openhab_rules_tools with openhabian-config - still no luck. I then looked in Add-ons Store - Automation and found “rule templates”. Don’t know whether this is only my misunderstanding as a not mothertongue or a flaw in the documentation in the README.md

Enough of my experience with the setup.

After implementing an item equivalent to your ColoreRampStart I copied your example into a script item (the menue entry below “Scenes”). After adapting ColorRampStart and AllLights to my items I tried to start it.

I got this error message in openhab.log:

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ChangeColorTest' failed: org.graalvm.polyglot.PolyglotException: TypeError: LoopingTimer is not a function

A quick search didn’t help fast as there are many hits concerning graalvm.polyglot.PolyglotException.

It’s not urgent; government decided that another topic has now priority over color-fiddeling:
Adapting a MainUI-Rule to accept a condition with a timeframe from 01:30 to civilDusk#event.
Hope, finding out the right syntax fast.

In OH 4.1 the add-ons installation moved from Settings to the Add-on Store. I’ve not managed to update the docs for that move yet.

The library is not installed correctly or LoopingTimer is not imported correctly. Show the Rule (click on the code tab and paste the YAML).

This is the core engine that runs JS Scripting. Type errors, no such symbol errors, and stuff like that come up as polyglot errors.

You need to link the civilDusk start Channel to a DateTime Item, we’ll call it CivilDusk. Then add a Script Condition using ECMAScript 2022+ (i.e. JS Scripting):

time.toZDT().isBetweenTimes(time.toZDT('01:30'), time.toZDT(items.CivilDusk));

The rule looks like this:

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: Farbwechsel_Start_Item
      state: ON
      previousState: OFF
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    label: Wechsele die Farben der Item(s) oder Groups(s) durch
    configuration:
      considerConditions: false
      ruleUIDs:
        - ChangeColorTest
    type: core.RunRuleAction

Use code fences.

```
code goes here
```

And that’s not the rule with the error. Post the ChangeColorTest

OK, than this script:

// Import looping timer
var LoopingTimer = require('openhab_rules_tools');

// Increment function, increment/decrement the hue by 5, change direction if boundary is met
var increment = (item) => {
  // get the current state or initialize if the Item is NULL or UNDEF, split out the three values
  const currState = (item.isUninitialized) ? ['0','75','100'] : item.state.split(',');

  // Calculate the new hue incremented/decremented by 5
  var newHue = parseInt(currState[0]) + (5 * cache.private.get(item.name+'_direction', () => 1));

  // Change the direction if we hit a boundary
  if(newHue >= 360) {
    newHue = 360;
    cache.private.put(item.name+'_direction', -1);
  } 
  else if(newHue <= 0) {
    newHue = 0;
    cache.private.put(item.name+'_direction', 1);
  }

  // command the Item with the new Hue
  item.sendCommand(newHue+','+currState[1]+','+currState[2]);
}

// Timer function, loop through all the members of AllLights and increment the hue
var loopFunction = () => {
  items.WZStrahlerSaulePhilips_Farbe.members.forEach(item => {
    increment(item);
    // add a tiny sleep here if commands get lost    
    // Java.type('java.lang.Thread').sleep(100);
  })

  // Looping timer reschedules itself based on the return value
  // Keep on changing the colors
  if(items.Farbwechsel_Start.state == 'ON') return 200;

  // Stop looping and changing the colors
  return null;
}

// Create the looping timer if one doesn't already exist
var loop = cache.private.get('timer', () => LoopingTimer());

// There isn't already a looping timer running
if(loop === null || loop.hasTerminated()) {
  // Make sure all the lights are ON
  items.WZStrahlerSaulePhilips_Farbe.sendCommand('ON');

  // Start the color changing loop
  loop.loop(loopFunction, 0);
}
// else ignore the trigger if the loop is already running

Comparing my script with the one in openhab_rules_tools/tests brings

var LoopingTimer = require('openhab_rules_tools');

should read

var { LoopingTimer } = require('openhab_rules_tools');

solves the “not a function” error.

Now I have to deal with this one

Script execution of rule with UID ‘ChangeColorTest’ failed: org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (getMembers) on org.openhab.core.library.items.ColorItem@94c24d failed due to: Unknown identifier: getMembers

Trying further …

HI @rlkoshak ,
I found this in some other thread:

//Cleaning.members.forEach[lamp|
    // 	If (lamp instanceof DimmerType){
    //		lamp.sendCommand(100)        ...

so I changed the loopFunction to

var loopFunction = () => {
  logger.info('In loopFunction');
  items.ColorTestGroup.members.forEach[item | {   
    increment(item);
    logger.info('item',item);
    // add a tiny sleep here if commands get lost    
    // Java.type('java.lang.Thread').sleep(100);
  }]

I couldn’t find the logger messages so I deleted openhab and events.log. No new messages rebuilt them. Therefore I restarted openhab.service. No change so I rebooted the whole system.
Now the logfiles are back and messages are coming in but there is an error because of a missing item.
Trying to recreate that item from its thing showed that openhab doesn’t display the Overview and the Things page any more.
There are a couple of messages like this:

2024-01-07 21:05:59.623 [WARN ] [.transport.servlet.ServletController] - Can't find the request for http://192.168.233.209:8080/rest/events's Observer 
2024-01-07 21:05:59.623 [WARN ] [.transport.servlet.ServletController] - Can't find the request for http://192.168.233.209:8080/rest/events/states's Observer

What might this be and how can I fix it?

That’s odd because “getMembers” doesn’t appear anywhere in the script. My guess would be that WZStrahlerSaulePhilips_Farbe isn’t a Group Item.

Are you on Firefox? There is a known issue with the way that Firefox does caching that causes newly created Items and Things from appearing until the browser forces a full reload of the page or restarts. It’s only a problem with Firefox and I think a solution has been found but it’s not in the releases.

Yes (1), it wasn’t a group item, I’m going to change that.

Yes (2), deleting the Firefox cache fixed the problem.

Many thanks for your help!

After some trial an error I managed to get rif of a couple of errors.

// To get rid of "ColorTestGroup not defined". const changed to var.
// From @jpg0:
// If it's needed for the group it will most probably also be needed for Farbwechsel_Start.
var Farbwechsel_Start = import('@runtime').ColorTestGroup;
var ColorTestGroup = import('@runtime').ColorTestGroup;

But now I run into this:

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ChangeColorTest' failed: org.graalvm.polyglot.PolyglotException: TypeError: Cannot read property "members" from undefined

The only function with members and the group is

var loopFunction = () => {
  //logger.info('In loopFunction');
  ColorTestGroup.members.forEach(item => {
    increment(item);
    //logger.info('item',item);
    // add a tiny sleep here if commands get lost    
    // Java.type('java.lang.Thread').sleep(100);
  })

  // Looping timer reschedules itself based on the return value
  // Keep on changing the colors
  if(items.Farbwechsel_Start.state == 'ON') return 200;

  // Stop looping and changing the colors
  return null;

It doesn’t throw the earlier errors any more but I think I haven’t got the meaning and syntax of that => construct right.

The error is pretty clear. ColorTestGroup is undefined. It’s not an Item. Even if you have an Item named ColorTestGroup , it’s not going to be defined in the JSR223 runtime (that’s what @runtime is).

I also worry that importing @runtime twice might be of concern. import copies all the code into the current rule. That’s why in JS Scripting we use the Node require to pull in stuff from libraries or @runtime.

What are you trying to accomplish with the import('@runtime').ColorTestGroup;? That isn’t going to do anything.

In the JSR223 runtime, the Items can be accessed through the ItemRegistry if that’s what you want, but you can access the raw Java Items through the helper library much easier.

items.ColorTestGroup.rawItem

Most of the time you really don’t want to mess with the raw Java Item though. So just:

items.ColorTestGroup
items['ColorTestGroup']
items.getItem('ColorTestGroup')

All three are equivalent.

Want to loop through the members of ColorTestGroup?

items.ColorTestGroup.members.forEach( item => {
    // code goes here
}

If for some reason you’d rather use the JSR223 API an not the helper library (can’t say I recommend it) you’d do something like this:

var runtime = require('@runtime');

var ColorTestGroup = runtime.ir.getItem('ColorTestGroup')

Note that in this case ColorTestGroup is going to be the Java Item so you will have to be very careful with your types. When you call ColorTestGroup.getMembers() you’re going to get a Java List<Item>, not a JavaScript Array so you will have to use Java syntax to loop and manipulate the list. That’s why we have a helper library in the first place, so that as we write JS rules, we use JS syntax and JS idioms.

So maybe you are trying to do something like this?

var loopFunction = () => {
  logger.info('In loopFunction');
  items.ColorTestGroup.members.forEach(item => {
    increment(item);
    // other stuff
  });

  if(items.Farbwechsel_Start.state == 'ON') return 200;

  return null;
}

All right @rlkoshak , I like to keep it as simple as possible and stick to the openhab4 possibilities.

I commented out the import(‘@runtime’) stuff and copied and pasted the loopFunction.

I learned that there is a problem with the logger:

org.graalvm.polyglot.PolyglotException: ReferenceError: "logger" is not defined
	at <js>.loopFunction(<eval>:49) ~[?:?]
	at <js>.expired(/etc/openhab/automation/js/node_modules/openhab_rules_tools/loopingTimer.js:40) ~[?:?]
	at <js>.loop(/etc/openhab/automation/js/node_modules/openhab_rules_tools/loopingTimer.js:27) ~[?:?]
	at <js>.:program(<eval>:74) ~[?:?]
	at org.graalvm.polyglot.Context.eval(Context.java:399) ~[?:?]
       [...]

This makes it difficult to find the source of the next error. Especially as I have little clue what it means. Obviously something with “state”.

org.graalvm.polyglot.PolyglotException: TypeError: Cannot get property "state" of null
	at <js>.loopFunction(<eval>:59) ~[?:?]
	at <js>.expired(/etc/openhab/automation/js/node_modules/openhab_rules_tools/loopingTimer.js:40) ~[?:?]
	at <js>.loop(/etc/openhab/automation/js/node_modules/openhab_rules_tools/loopingTimer.js:27) ~[?:?]
	at <js>.:program(<eval>:74) ~[?:?]
       [and some more from GraalVM, oracle, openhab, jdk, java, ...]

At least I see some change in events.log (awked ‘WZSaule_Farbe’ and printed from field $7) and also the color of the bulbs is changing:

- Item 'WZSaule_Farbe' changed from 35.982,42.97500,100 to 40,42.97500,79.698 
- Item 'WZSaule_Farbe' changed from 40,42.97500,79.698 to 40.007,42.94700,79.612 
- Item 'WZSaule_Farbe' received command 45,42.94700,79.612    
- Item 'WZSaule_Farbe' changed from 40.007,42.94700,79.612 to 40.007,42.94700,100 
Item 'WZSaule_Farbe' predicted to become 45,42.94700,79.612   
- Item 'WZSaule_Farbe' changed from 40.007,42.94700,100 to 45,42.94700,79.612 
- Item 'WZSaule_Farbe' changed from 45,42.94700,79.612 to 45.002,42.93900,79.369 
- Item 'WZSaule_Farbe' changed from 45.002,42.93900,79.369 to 44.988,43.01500,79.387 

Obviously the script runs at least until

“item.sendCommand(newHue+‘,’+currState[1]+‘,’+currState[2]);”

in function increment. Somewhere after it stops with the error above.
If I run it again, the color will change to the next increment and the script will stop again.

Something wrong in here?

  if(items.Farbwechsel_Start.state == 'ON') return 200;

  // Stop looping and changing the colors
  return null;

For unknown reasons, at least to me, the brightness will switch to 100 (because of the “ON” command?). I would prefer saturation and brightness will keep their value.

OK, I see, if on start of the script the lights are on, I could use something like

“item.sendCommand(newHue+‘,’+currState[1]+‘,’+currState[2]);”

with brightness instead of “ON”. If the bulb is OFF I can set it to let’s say 70% with it.

It’s kind of hard to follow what’s been done and not done and what the full rule looks like in a thread like this. Because I support lots of different threads at the same time sometimes they get confused.

If you’ve not separately defined a logger, use console.

Instead of logger.info(). Use console.info(). That’s probably a more idiomatic JS way to do it anyway.

Assuming the rule is unchanged from above, there’s only two lines of code where you get to get the .state from an item. The error is telling you that the Item you are trying to get the state from doesn’t exist.

The only line after that that gets the state of an item is if(items.Farbwechsel_Start.state == ‘ON’)`.

Focus on that. Typo perhaps?

That’s between you and the binding. It’s rude binding that’s interpreting the ON concerns as 100 brightness. I don’t think there’s anything you can do about that from a rule except to not send the ON concerns in the first place.

Hi Rich,

thanks again for your helpful hints.

I tweaked the script a litte. Now the brightness will be set to 60 foreach instead of ‘ON’ for the group. This works quite well but something decreases the brightness value or sets it to 0.

Next flaw is that the script doesn’t react on Farbwechsel_Start_Item = ‘OFF’. It runs and runs and runs until I do a “systemctl restart openhab”.

I tried many things and syntax but didn’t had any luck. The colors are changing fine but the brightness will decrease (sometimes for 1, sometimes for 10 and more).


// Import looping timer
var { LoopingTimer } = require('openhab_rules_tools');

// Increment function, increment/decrement the hue by 5, change direction if boundary is met
var increment = (item) => {
  // get the current state or initialize if the Item is NULL or UNDEF, split out the three values
  const currState = (item.isUninitialized) ? ['0','75','60'] : item.state.split(',');

  // Calculate the new hue incremented/decremented by 5
  var newCSB = parseInt(currState[0]) + (5 * cache.private.get(item.name+'_direction', () => 1));
  //console.info('currState[0]: ', item.name, (currState[0]));
  //console.info('parseInt(currState[0]): ', item.name, (parseInt(currState[0])));
  //console.info('item.name+_direction: ', item.name, (item.name+'_direction'));
  //console.info('cache.private.get(item.name+_direction: ', item.name, cache.private.get(item.name+'_direction'));
  //console.info('newHue: ', newHue);

  // Change the direction if we hit a boundary
  if(newCSB >= 360) {
    newCSB = 360;
    cache.private.put(item.name+'_direction', -1);
  } 
  else if(newCSB <= 0) {
    newCSB = 0;
    cache.private.put(item.name+'_direction', 1);
  }

  // command the Item with the new Hue and keep currState for second and third position
  console.info('vor sendCommand increment', newCSB, currState[1], currState[2] );
  item.sendCommand(newCSB+','+currState[1]+','+currState[2]);
}

// Timer function, loop through all the members of AllLights and increment the hue
//groupUtilsTests:var count = groupUtils.countList(items.getItem('AllLights').members, i => i.state == 'ON');
//

var loopFunction = () => {
  //console.info('In loopFunction');
  items.ColorTestGroup.members.forEach(item => {
    increment(item);
    console.info('increment item', item);
    // add a tiny sleep here if commands get lost    
    Java.type('java.lang.Thread').sleep(200);
  });

  // Looping timer reschedules itself based on the return value
  // Keep on changing the colors
  // console.info('vor items.Farbwechsel_Start.state');
  if(items.Farbwechsel_Start_Item.state == 'ON') return 200;
    // console.info('nach items.Farbwechsel_Start.state');
    // Stop looping and changing the colors
    return null;
  
}

// Create the looping timer if one doesn't already exist
var loop = cache.private.get('timer', () => LoopingTimer());

// if brightness = 0 set Brightness to 60
var getstate = (itemb) => {
  // get the current state or initialize if the Item is NULL or UNDEF, split out the three values
  const currState = (itemb.isUninitialized) ? ['0','75','60'] : itemb.state.split(',');
  //console.info('vor items.sendCommand(ON); Brightness: ', currState[2]);
  if(currState[2] <= 2) currState[2] = 60;;
  itemb.sendCommand(currState[0]+','+currState[1]+','+currState[2]);
  //console.info('nach items.sendCommand(ON); Brightness: ', currState[2]);
}

// There isn't already a looping timer running
if(loop === null || loop.hasTerminated()) {
  // Make sure all the lights are ON but not on 100% brightness
  items.ColorTestGroup.members.forEach(item => {
    getstate(item);
  })

  // Start the color changing loop
  console.info('Start loop.loop(loopFunction,0)');
  loop.loop(loopFunction, 0);
}
// else ignore the trigger if the loop is already running

// ToDo
// solve brightness decrease
// improve the stopping mechanism
// Brightness via dimmer widget and dimmer buttons
// Saturation via Slider
// Distance between Colors via Slider
// Color selection via random function

There might be a round trip interaction going on here to watch out for involving Autoupdate.

  1. Item receives a command
  2. Autoupdate predicts what new state the Item should be come and updates the Item with that
  3. Command goes out to the device
  4. The device publishes a new state to the binding which updates the Item.

Where problems can come into play is when the device reports a different state from what Autoupdate predicted. That can result in the Item’s state jumping around and in some cases end up in loops. It’s often a good idea to disable Autoupdate on Items where the binding does support reporting the Item’s state and almost a requirement when the device does something like gradually dimming up/down and reports the new state as it does so.

Add some logging around the if statement in the loopFunction to see wgat Farbwechsel_Start_Item is doing when the loop runs each time.

What do the logs say is going on with 'vor sendCommand increment'? Is the third number changing or does it remain 60?

Here the events.log:

- Item 'WZSaule_Farbe' received command 35,43,80   
Item 'WZSaule_Farbe' predicted to become 35,43,80   
- Item 'WZSaule_Farbe' changed from 35.982,42.97500,0 to 35,43,80 
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe
Item 'WZSaule_Farbe' predicted to become 35,43,80   
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 35,43,80 to 34.984,42.99000,79.789 
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 34.984,42.99000,79.789 to 34.978,43.08600,79.817 
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command 34,43,80   
Item 'WZSaule_Farbe' predicted to become 34,43,80   
- Item 'WZSaule_Farbe' changed from 34.978,43.08600,79.817 to 34,43,80 
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 34,43,80 to 34.002,42.97900,79.864 
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command OFF   
- Item 'WZStrahlerSaulePhilips_Farbe' received command OFF   
Item 'WZSaule_Farbe' predicted to become OFF   
- Item 'WZSaule_Farbe' changed from 34.002,42.97900,79.864 to 34.002,42.97900,0 
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe
Item 'WZStrahlerSaulePhilips_Farbe' predicted to become OFF   
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZStrahlerSaulePhilips_Farbe
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZSaule_Farbe

I changed the brightness manually in the MainUI Item dialog or via a scene setting because the script won’t stop running.

For unknown reason the color isn’t changing in this part of the log. But there are other parts, where the color is nicely changing by 5.

Here the openhab.log since the last restart via systemctl:

[ab.ui.habpanel.internal.HABPanelTile] - Started HABPanel at /habpanel     
[e.automation.internal.RuleEngineImpl] - Rule engine started.      
[.transport.mqtt.MqttBrokerConnection] - Starting MQTT broker connection to '192.168.233.209' with clientid e44c79f0-973d-48b1-ab76-62e8fe75eaa1
- Initializing GraalJS script engine...      
- Injecting ThreadsafeTimers into the JS runtime...    
- Evaluating cached global script...      
- Evaluating cached openhab-js injection...      
- Successfully initialized GraalJS script engine.     
[er.internal.dto.DwdWarningDataAccess] - Communication error occurred while getting data: java.util.concurrent.TimeoutException: Total timeout
[g.discovery.internal.PersistentInbox] - Added new thing 'deconz:deconz:00212E05BFA4' to inbox.   
[.io.rest.auth.internal.TokenResource] - Couldn't find a user with a session matching the
[.io.rest.auth.internal.TokenResource] - Couldn't find a user with a session matching the
[.io.rest.auth.internal.TokenResource] - Couldn't find a user with a session matching the
[.io.rest.auth.internal.TokenResource] - Couldn't find a user with a session matching the
[.io.rest.auth.internal.TokenResource] - Token issuing failed: invalid_grant     
[.io.rest.auth.internal.TokenResource] - Token issuing failed: invalid_grant     
[.io.rest.auth.internal.TokenResource] - Token issuing failed: invalid_grant     
[.io.rest.auth.internal.TokenResource] - Token issuing failed: invalid_grant     
[.io.rest.auth.internal.TokenResource] - Couldn't find a user with a session matching the
[.io.rest.auth.internal.TokenResource] - Token issuing failed: invalid_grant     
[.io.rest.auth.internal.TokenResource] - Couldn't find a user with a session matching the
[.io.rest.auth.internal.TokenResource] - Token issuing failed: invalid_grant     
[g.discovery.internal.PersistentInbox] - Added new thing 'deconz:deconz:00212E05BFA4' to inbox.   
[.io.rest.auth.internal.TokenResource] - Couldn't find a user with a session matching the
[.io.rest.auth.internal.TokenResource] - Token issuing failed: invalid_grant     
[g.discovery.internal.PersistentInbox] - Added new thing 'deconz:onofflight:homeserver:a4c138178e60982801' to inbox.   
[g.discovery.internal.PersistentInbox] - Added new thing 'deconz:onofflight:Phoscon2098090:a4c138178e60982801' to inbox.   
[er.internal.dto.DwdWarningDataAccess] - Communication error occurred while getting data: java.util.concurrent.TimeoutException: Total timeout
- Initializing GraalJS script engine...      
- Injecting ThreadsafeTimers into the JS runtime...    
- Evaluating cached global script...      
- Evaluating cached openhab-js injection...      
- Successfully initialized GraalJS script engine.     
[automation.script.ui.ChangeColorTest] - Start loop.loop(loopFunction,0)       
[automation.script.ui.ChangeColorTest] - vor sendCommand increment 105 59 60   
[automation.script.ui.ChangeColorTest] - increment item WZStrahlerSaulePhilips_Farbe (Type=ColorItem, State=100.012,58.99800,59.763, Label=WZ Strahler Farbe, Category=ColorLight,
[automation.script.ui.ChangeColorTest] - vor sendCommand increment 38 42.96600 59.692   
[automation.script.ui.ChangeColorTest] - increment item WZSaule_Farbe (Type=ColorItem, State=33.990,42.96600,59.692, Label=WZ Säule Farbe, Category=ColorLight,

The events.log for a single run (items.Farbwechsel_Start_Item.state was OFF):

- Item 'WZStrahlerSaulePhilips_Farbe' received command 100,59,60   
Item 'WZStrahlerSaulePhilips_Farbe' predicted to become 100,59,60   
- Item 'WZSaule_Farbe' received command 34.002,42.97900,60   
Item 'WZSaule_Farbe' predicted to become 34.002,42.97900,60   
- Item 'WZStrahlerSaulePhilips_Farbe' changed from 100,59,0 to 100,59,60 
- Item 'WZSaule_Farbe' changed from 34.002,42.97900,0 to 34.002,42.97900,60 
Item 'ColorTestGroup' changed from 0,0,0 to OFF through WZStrahlerSaulePhilips_Farbe
Item 'ColorTestGroup' changed from 0,0,0 to ON through WZSaule_Farbe
- Item 'WZStrahlerSaulePhilips_Farbe' changed from 100,59,60 to 100.012,58.99800,59.763 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZStrahlerSaulePhilips_Farbe
- Item 'WZSaule_Farbe' changed from 34.002,42.97900,60 to 33.990,42.96600,59.692 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZStrahlerSaulePhilips_Farbe' received command 105,59,60   
Item 'WZStrahlerSaulePhilips_Farbe' predicted to become 105,59,60   
- Item 'WZStrahlerSaulePhilips_Farbe' changed from 100.012,58.99800,59.763 to 105,59,60 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZStrahlerSaulePhilips_Farbe
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZStrahlerSaulePhilips_Farbe
- Item 'WZStrahlerSaulePhilips_Farbe' changed from 105,59,60 to 105.029,58.98800,59.877 
- Item 'WZSaule_Farbe' received command 38,42.96600,59.692   
Item 'WZSaule_Farbe' predicted to become 38,42.96600,59.692   
- Item 'WZSaule_Farbe' changed from 33.990,42.96600,59.692 to 38,42.96600,59.692 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 38,42.96600,59.692 to 37.987,42.97300,59.400 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 37.987,42.97300,59.400 to 38.005,42.94700,59.390 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command 37,43,59   
Item 'WZSaule_Farbe' predicted to become 37,43,59   
- Item 'WZSaule_Farbe' changed from 38.005,42.94700,59.390 to 37,43,59 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 37,43,59 to 36.994,42.98100,58.780 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZStrahlerSaulePhilips_Farbe
- Item 'WZSaule_Farbe' changed from 36.994,42.98100,58.780 to 37.009,42.88300,58.758 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZDimmerCouch_Batterieladung' changed from 1 to 2 

Here now the events.log for a sleep of 1000 filtered after WZSaule_Farbe. You can see how the brightness is going down.

- Item 'WZSaule_Farbe' changed from 277.987,67.22900,38.742 to 272,67.22900,38.742 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 272,67.22900,38.742 to 271.976,67.31700,38.418 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command 266,67.31700,38.418   
Item 'WZSaule_Farbe' predicted to become 266,67.31700,38.418   
- Item 'WZSaule_Farbe' changed from 271.976,67.31700,38.418 to 266,67.31700,38.418 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 266,67.31700,38.418 to 266.004,67.49500,37.785 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command 261,67.49500,37.785   
Item 'WZSaule_Farbe' predicted to become 261,67.49500,37.785   
- Item 'WZSaule_Farbe' changed from 266.004,67.49500,37.785 to 261,67.49500,37.785 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 261,67.49500,37.785 to 260.999,67.81900,36.478 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command 255,67.81900,36.478   
Item 'WZSaule_Farbe' predicted to become 255,67.81900,36.478   
- Item 'WZSaule_Farbe' changed from 260.999,67.81900,36.478 to 255,67.81900,36.478 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 255,67.81900,36.478 to 255.014,68.24000,34.950 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command 250,68.24000,34.950   
Item 'WZSaule_Farbe' predicted to become 250,68.24000,34.950   
- Item 'WZSaule_Farbe' changed from 255.014,68.24000,34.950 to 250,68.24000,34.950 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 250,68.24000,34.950 to 250.009,68.95600,32.512 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command 245,68.95600,32.512   
Item 'WZSaule_Farbe' predicted to become 245,68.95600,32.512   
- Item 'WZSaule_Farbe' changed from 250.009,68.95600,32.512 to 245,68.95600,32.512 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 245,68.95600,32.512 to 245.003,70.10000,29.207 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' received command 240,70.10000,29.207   
Item 'WZSaule_Farbe' predicted to become 240,70.10000,29.207   
- Item 'WZSaule_Farbe' changed from 245.003,70.10000,29.207 to 240,70.10000,29.207 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 240,70.10000,29.207 to 239.992,72.19400,24.598 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 239.992,72.19400,24.598 to 251.226,78.83800,25.474 
- Item 'WZSaule_Farbe' received command 239,72,25   
Item 'WZSaule_Farbe' predicted to become 239,72,25   
- Item 'WZSaule_Farbe' changed from 251.226,78.83800,25.474 to 239,72,25 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 239,72,25 to 239.016,72.40400,24.264 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 239.016,72.40400,24.264 to 251.226,78.83800,25.474 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe
- Item 'WZSaule_Farbe' changed from 251.226,78.83800,25.474 to 251.048,78.15200,25.172 
Item 'ColorTestGroup' changed from 0,0,100 to ON through WZSaule_Farbe

Since I set the sleep to values above 500, the script stops fine. Looks like it put to many commands into a queue and therefore it took a long time until the stop-sign was recognized.

And now I’m looking for a solution how to keep these events from the events.log. 12 bulbs continously changing during a party of 5 hours will store quite an amount of useless data.

Ignore the ColorTestGroup events in events.log. Those are not relevant.

Do the HSB values get translated to some other coordinate system? The values look like they are accumulating rounding errors as they are translated back and forth.

That’s possible. But I’m not deep enough in the bindings to find out yet. What different color coordinate systems are around? HSB looks to me like Hue, Saturation, Brightness. I called it CSB (Color, Saturation, Brightness).
A search for ‘color’ in the documentation brings up RGB (Red, Green, Blue?) sliders.
Another search for ‘hue’ brings up the ‘HUE Binding’, this is not installed here.

Both don’t help any further. If nobody comes up with some hints, I’m stuck here.

Perhaps not but the bulbs are Hue bulbs. So if the Hue binding needs to do such a translation the deconz binding will have to do the same translation.