What to do if you need a delay in commands in a scene

I’m having an issue where at least one of my lights was not comming on when it was supposed to. I don’t have a lot of time right now to debug issues like these so I’m doing triage. I had a little bit of time today and looked at the logs and it seems that the commands are being sent but one of my lights isn’t comming on when it’s commanded.

On a hunch I am guessing that the problem is too many commands are going out all at once on the same technology.

An important piece of info here is that I’m using Scenes.

I didn’t want to go through all of the effort of totally changing my approach so I did some digging and figured out a pretty simple rule that can retrieve the Items and the commands defined in a Scene.

The following code does the following:

  • maps the time of day to the UID of a Scene
  • pulls the Scene from the registry
  • extracts the Item names and commands to send
  • sends the commands with a 200 msec delay between them instead of all at once as fast as possible like the scene normally does
const { ruleRegistry } = require('@runtime/RuleSupport');
const { Gatekeeper } = require('openhab_rules_tools');

const gk = cache.private.get('gatekeeper', () => Gatekeeper());

const mapping = { "MORNING":   "lights-morning",
                  "DAY":       "lights-day",
                  "AFTERNOON": "lights_afternoon",
                  "EVENING":   "lights-evening",
                  "NIGHT":     "lights_night",
                  "BED":       "lights_bed" };
const sceneID = mapping[items.TimeOfDay.state];

const modules = utils.javaListToJsArray(ruleRegistry.getByTag('Scene').find(scene => scene.getUID() == sceneID).getModules());
modules.forEach(m => {
  const iName = m.getConfiguration().get('itemName');
  const cmd = m.getConfiguration().get('command');
  console.info('Sending command ' + iName + ' ' + cmd);
  gk.addCommand(200, () => items[iName].sendCommandIfDifferent(cmd));
});

Gatekeeper comes from my OHRT library (installable from openHABian or through the rule template on the marketplace) and the rule is triggered based on changes to the TimeOfDay Item which is driven by the Time State Machine rule template. Both tempaltes can be installed through the Add-on store.

When I have some time I’ll figure out a way to make this a reasonable rule template. But in the mean time I figured some might find it useful to see the code. The last seven lines of the code above are the main ones. You could use a sleep instead of Gatekeeper.

I know that some are very “attached” to the scene idea, despite them just really being simplified rules. But, perhaps there would be support for a button in the “Scene view” that said “Convert to rule”? Conversion from rule to Scene would be more difficult, because it would require checking that the rule strictly follows the “limitations” of a scene, but I guess it would be possible too.

Actually “converting” a scene to a rule is extremely simple. All that’s needed is to remove the Scene tag, and it would disappear from the “Scenes view” and appear in the “Rules view”. Then you could do whatever scripting you’d like to customize it, while still “benefitting” from being able to create it in the simplified “Scene view”?

Converting the scene to a rule doesn’t really help me here. Once converted it becomes just a bunch of ItemCommand Actions, right? I can’t really do anything with that scripting wise except to just start over with a new rule anyway.

Scenes are actually a pretty convenient way to provide a mapping between Items and commands in a nice and clear way with a compact UI that requires minimal clicks/interaction from the end user. They also address a common use case.

Without them I’d have to resort to a bunch of Groups and Item metadata type stuff (which is how I implemented scenes before Scenes became a thing) if I just wanted one rule or the much less easy to read and configure main Rules UI where I have to add each Item individually through a much more involved and “clicky” process.

I very much would argue against removal of Scenes from MainUI.

The value of a Scene is the easy mapping between Items and commands to send. The rule above takes advantage of that easy mapping do do more, in this case spread the commands out a little bit so teh barrage of commands do not overwhelm the devices/technology. There really is nothing equivalent in OH to create those mappings anywhere close to how easily it can be done in a Scene.

I get that, except that you could convert the “troublesome Item” to a scripted action and do it using a timer. But, I’ve seen other situations where people also hit the “limits” of what a Scene can do, and I think that’s the point where it could be convenient to “convert” it to a Rule, instead of having to start fresh, clicking your way through the wizard for selecting Item, Command etc.

Yes, it’s what it already is.

I get that, but they also pose challenges. Nobody has done an “update” to the YAML syntax for Scenes, they can’t be exported to “new YAML” etc. Actually, they can if you open the scene in MainUI, edit the URL and replace scenes with rules and then export it as any other rule from there, but that’s more of a “hack”. And, the scene in YAML format wouldn’t be presented as a scene but as a rule.

Once processed by the system, it would show up under “scenes”, not “rules” as long as the Scene tag is present in the YAML. But, this is also the problem. Any rule where you add a Scene tag in YAML “becomes” a scene, even if it has triggers, conditions and non-itemCommand actions. But, the “Scene view” can’t handle that, so they will probably be quite bugged if you try to view them.

This is why I call this an illusion, that is getting harder to maintain. You can even create a “scene” from DSL now, since DSL can specify tags. They won’t make any sense in “Scene view” either. The illusion is full of holes…

What I have been suggesting somewhere else where this was touched upon, was that the “rule designer” was modified so that ItemCommands could be entered just as easily from there. That’s really the main benefit of the whole thing, that you don’t have to “click through” the wizard, that you can easily see what Items and Commands are involved, and that you can “test” individual actions. All this could be integrated into the “main rule window” instead, giving the same “benefit” also for “mixed rules” where you have some simple ItemCommand actions, combined with other actions.

Only when this was in place, I think it would make sense to remove the “Scene view”. But, it doesn’t seem like people even agree with me that this would be a better solution.

As it now, there’s a “hole” in the consistency of how things are done, scenes are not part of the new “everything YAML” concept, and there are artificial limitations to what you can do with them. MainUI also prevents you from adding a Scene tag to a rule, but of course, that’s not true for YAML or DSL.

It’s not always the same Item that has the problem. So I’d have to convert allof them to use a timer. At that point I’m going to find another way, like I did above.

I’m not arguing against supporting converting them to “normal” rule. Just that it wouldn’t have helped me in this case and I do not want to lose Scenes from MainUi.

Transformations are not use supported in the YAML syntax either. :person_shrugging: So there’s more to do I guess. That doesn’t seem like a good argument to get rid of them.

Again, I don’t see this as an argument to get rid of them and replace the convenience to the end users with something that is a huge reduction in usability.

Seems like a relatively simple structural check (i.e. this rule has a Scene tag, are there no triggers, no conditions and are all the actions are ItemCommands.

Or maybe Scenes can be made into their own thing (a new Group Item type?). Or some other implementation that is just as easy to use.

I don’t really care how it’s implemented. But what ever replaces it needs to be just as easy to use for the end user and it needs to be in place before Scenes are removed. And there needs to be a migration path from what’s there now and what it becomes.

There seem to be very little interest in “solving” this and mostly just resistance to any change that could in some circumstance be seen as less convenient, so I think I’ll just let it be until the current problems becomes “visible enough” that others see a need to solve it, not just me.

But, with my suggestion, there would be no need for migration. Scenes are just rules, they would continue to work as they always have - you would just see them among other rules instead of in a separate list.

This is a clever solution!

Here’s how to do it in JRuby:

def run_scene_with_delay(scene_id, delay = 200.ms)
  scene = rules.scenes[scene_id]
  return unless scene

  commands = scene.modules.map { |m| m.configuration.fetch_values("itemName", "command") }
  after(0.ms) do |timer|
    commands.shift&.then do |item, command|
      items[item]&.ensure&.command(command)
      timer.reschedule delay unless commands.empty?
    end
  end
end

run_scene_with_delay("my_scene_id")