Groups, and new JavaScript rules

This is my first stab at a JavaScript Rule, and I’m also setting up a new installation managing 14 air conditioners, with more to come later.
I am pulling in a calendar, and am seeing events update from that, and I want to schedule rooms to be cooled some time before the event starts, and then revert to a different condition after the event is over. The question is how to best define my group memberships.
Three classrooms, D1, D2 and D3.

Group gOC_D1        "d1/108"                  (gOC,gHVACZONE_OC_D1)["Room"]
Group gOC_D2        "d2/107"                  (gOC,gHVACZONE_OC_D2)["Room"]
Group gOC_D3        "d3/106"                  (gOC,gHVACZONE_OC_D3)["Room"]

three thermostats, and one setpoint as example:

Group gHVAC_OC_D1         "Thermostat D1"    (gOC_D1)        ["HVAC"] {synonyms="Thermostats" }
Group gHVAC_OC_D2         "Thermostat D2"    (gOC_D2)        ["HVAC"] {synonyms="Thermostats" }
Group gHVAC_OC_D3         "Thermostat D3"    (gOC_D3)        ["HVAC"] {synonyms="Thermostats" }
Number   Room106_ControlsCoolsetpoint       "Cool setpoint"                       <temperature> (gHVAC_OC_D3)    ["Setpoint","Temperature"]    {channel="mqtt:homie300:a40be34a38:somecomfort4778499:controls#coolsetpoint",stateDescription=""[min="72",max="100",step="1"],widget="oh-stepper-card",listWidget="oh-stepper-item",cellWidget="oh-stepper-cell"}

Calendar feed:

DateTime   FeedD3Result0Begin              "Start of result"   (gCalendarTstat,gHVACZONE_OC_D3){channel="icalendar:eventfilter:feed_d3:result_0#begin"}

Is this the correct approach, or is there a better way? In JavaScript I would:
Rule is triggered when member of gCalendarTstat is updated.
From the triggering item, get the groups it belongs to. From that group, get the one group whose name contains HVACZONE.
From that group, get the members, filtered by the item whose name contains setpoint, and that item should be the cooling setpoint I need to set for the duration of the event.
I havent found any group operation examples for JavaScript, so pointers there would be helpful.
Oh, and I’m new to JavaScript. I know Java, but not JavaScript. I’m doing this new system without Rules DSL.

If you are just getting started, I highly recommend starting with the JS Scripting add-on if you want to use JavaScript over the built in JavaScript. It provides a much more recent version of ECMAScript (11 vs. 5.1) and the helper library comes with it and is much better.

I usually let my rules drive my Groups when writing code like this. Without more specific details I couldn’t say if it’s the best or not.

Given your Item names, you may not need most if any of these Groups at all. openhab-js presents a nice interface to the ItemRegistry as your primary way to access Items. It doesn’t just inject them all into your rule like Rules DSL does.

So, if your naming is consistent you might be able to do something simpler like:

  let setpointItem = items.getItem(event.itemName.replace('Calendar', 'Setpoint'));

You don’t need to mess with navigating a bunch of Groups for this. Just name your Items so that you can derive the names of all the associated Items given the name of any one of them. See Design Pattern: Associated Items.

Another approach you can use is to leverage the Semantic Model. Put the calendar Item as well as all the HVAC control and status Items for one HVAC into the same equipment Group (which is what you would want to do anyway if using the Semantic Model). Then you can use Semantics.getEquipment(items.getItem(event.itemName)) to get the parent Equipment Group and with that you’ll have all the Items that are a part of that equipment. See actions - Documentation.

In JS Scripting, they have gone to great lengths to only ever give you JavaScript Objects to deal with. So, according to the docs when you use items.getItem(itemName) you get back a JavaScript Item Object. Calling .members on that Item returns a JavaScript Array<Item> which is an array of those JavaScript Objects. So you can and should use any standard JavaScript Array operation to search through, sort, iterate, etc. the members of the Group. It’s all JavaScript. JavaScript Array Iteration

I use your design pattern extensively in my Rules DSL on my older systems. You’ve given me several solid approaches here.
So, I installed the JSScripts, and get the option to choose ECMAv11. When looking through the forum, I think I know the difference of (in the UI) writing the rule from “new rule”, vs writing the rule from “new script”. The ones from “new script” have triggers and conditions in the code.

See Rules - Introduction | openHAB for now and stay tuned for a complete rewrite of the rules docs in the not to distant future which will discuss this more. For the most part you are correct, a Script in MainUI is just a rule that consists of a single Script Action and is tagged with “Script”. In all other respects it’s a rule.

1 Like

I’m grappling with the multiple groups problem. A member can be only in one semantic group, correct?
Let’s say I have three rooms, A, B, C. Rooms A,B are in one HVAC zone, but rooms B,C are in a light switch group. Or does the single group only apply to location?

For the Equipment group, what tag should I use? Closest I can find that makes sense is WebService. This equipment would have as members, the calendar event item and the HVAC items.

It would be wise to go through Semantic Model | openHAB and perhaps A Deep Dive into the Semantic Model to make sure you understand what the semantic model is for and how to best set it up.

Correct. The Semantic model represents the physical layout of your home automation system as seen from your home automation’s users. You can’t have something (e.g. a switch) that is physically part of two different pieces of equipment or have something that is in two different locations at the same time. That doesn’t make sense.

If you have equipment that spans rooms which isn’t uncommon with HVAC, you might need to model the grouping of rooms as a separate location (e.g. like the floor of a building). For example

    |_ Floor 1
        |_HVAC Zone 1
            |_ HVAC 1
            |   |_ HVAC 1 Setpoint
            |   |_ ...
            |_ Room A
            |   |_ Room A Lights
            |   |_ ...
            |_ Room B
                |_ Room B Lights
                |_ ...

Your light switch Group doesn’t sound like something that even belongs in the Semantic Model. Not all Items belong in the model. In practice only about 60% of your Items and Groups have any business in the model with the remaining

The Semantic Model may not even make sense in this particular case, and that’s OK too. Remember, the “H” in “openHAB” stands for “Home”. OH was never designed to handle automating a commercial/industrial environment like a school so many features, like the Semantic Model, might not make sense in such cases.

Ultimately it doesn’t matter unless you use HABot. But why wouldn’t you use the “HVAC” equipment tag? That’s what all these Items collectively represent, the sensors and controls for a HVAC system. The fact that one of the Items comes from a calendar event is irrelevant. That doesn’t change the fact that all those Items, even the calendar one, represent everything to do with one of the physical HVAC systems.

The Calendar Item would have a Point/Property tag, probably “Control” for the Point since it controls the HVAC and “Temperature” for the Property since the primary job of this Item is to control the HVAC which controls the temperature based on a schedule.

The key with the Semantic Model is to forget the technology behind the Items. That does not and should not matter. You need to focus on the intent of the Items. What’s that Item for (Point/Property)? What physical “thing” in the real world is it associated with (Equipment)? Where is that “thing” in the real world physically located (Location)?

That last one needs a bit of caution though. For example, you might have a relay in a closet that controls the lights in the kitchen. Where would that relay belong in the model? It belongs in the kitchen because that’s where the thing it controls is located. That’s what that relay actually represents to the end users.