Counter for rollershutter shading

Hello,

I have programmed a script, which closes the rollershutter at a certain temperature to avoid heating in a room by sun.

It happens often, that the rollershutter closes within a room, which is hot, but no sun is shinning inside. If I then open the rollershutter, it closes after a while a again, due to the temperature.

My idea would be, that I implement a counter. If the count is >2 the roller should stay open. Counter to be deleted once a day.

But I run on error with the attached script:

>     rule "Sommerhitzetest"
>     when 
>         Item Declenche_switch changed to ON
>     then
>               if (Season.state == ON){
>             logInfo("DEBUG", "Hitzeprüfung Test startet")
>             gH_Rolladen.allMembers.forEach[rs|
>             var nameParts = rs.name.split("_")
>             val tempName = nameParts.get(0) + "_" + nameParts.get(1) + "_ht_"
>             val windowName = nameParts.get(0) + "_" + nameParts.get(1) + "_fk_" + nameParts.get(3)
>             var Number windowcounter = nameParts.get(0) + "_" + nameParts.get(1) + "_Counter"
>             logInfo("DEBUG", "tempName = " + tempName)   
>                 if (gH_Temperature?.allMembers.filter [ht | ht.name.startsWith(tempName)].head.state > 21){
>                         logInfo("DEBUG", "Zimmer " + tempName + " is too hot!")
>                         if (windowcounter < 2 && gH_Contact_global.members.filter [fk | fk.name == windowName].head.state != OPEN)
>                             {
>                             logInfo("DEBUG", "Fahre runter")
>                             sendCommand(rs,50)
>                             logInfo("DEBUG", "Windowcountername="+ windowcounter)
>                             windowcounter = windowcounter + 1 
>                             }
>                         }
>                    else {(gH_Temperature?.allMembers.filter [ht | ht.name.startsWith(tempName)].head.state < 22){
>                         logInfo("DEBUG", "Zimmer ist wieder angenehm warm!")
>                         if (rs.state == 50 && gH_Contact_global.members.filter [fk | fk.name == windowName].head.state != OPEN)
>                             {
>                             //postUpdate(rs,UP)
>                             logInfo("DEBUG", "Fahre hoch")
>                             sendCommand(rs,UP)
>                             }
>                         } 
>                             
>                     }]
>             }
>         
>         else {
>                      logInfo("DEBUG", "Noch nicht warm genug für Zimmertemp.-Check")
>                   }
>     end

I think, it is related, that the variable windowcounter is created as a dynamic variable with different names.

Does someone have a guess, what is wrong?

It’s all a bit confusing. Here, you declare a Number variable but set it to a String value.

I guess you are building the name of an Item here, for your counter? You probably want to get hold of the Item with that name, so that you can examine and update its state.
Later in the rule, you’ve used a method to get hold of an Item via a Group filter, that would also work here. I think you know what to do but have just lost sight of the need to do it :smiley:

Hi,

Not an actual answer to your question, but rather a suggestion.

In my system I use the sun elevation and azimuth values from the Astro binding to determine if the sun is in a position to come through a window.
This has the advantage that it works all year round as it works on the sun position.

The main trick is to watch the window when the sun moves and get an idea of when it is in the right position.
I displayed the azimuth and elevation in charts and identified the limits.
I then have 4 items for the highest and lowest values for each and if it is within the values the sun is deemed to be on the window.
Then I determined whether I want to allow heat from the sun (cooler weather) or not.

Regards,
John

No, not an item, I try to get a variable with a name similar to the item I trigger. My idea is, that I need different variable names for the different roller shutters.

But I think, I make something wrong with the variables. How could I create a variable, with different name within the if-statement, which I could fill with a numeric value?

Don’t know why you must use a variable. You could do this with an Item. It’s a well-known method.

First decide if you need your variable to survive between different runs of the same rules. (I think you do?)
If so, you’ll need to use global variables, not create new ones every time the rule runs.

Next, if you want to access a variable using a string with the target name, you will have to do it indirectly.
One way is to create a global Map object, and key it by name-string. This is like having an array indexed by name-string in other languages.

As I don’t get further with my solution, are you willing to share your code? I think it could be a good idea as well.

Thanks
Dom

Happy to do what I can but it may be a lot more than you need.
I am currently using node-red for my rules on OH2.3.
I am working on trying to redo my rules for OH2.4 but it is a very big job and I know this can be improved greatly.
Below is the section of the flow that handles the front shutter, I hope it helps.

It takes into account whether automation is turned on, the air conditioner state, THI inside and outside, temperature thresholds, day/night, weather forecast, position of the sun elevation and azimuth (high and low for each to provide the limits), a high and low level for the open positions and whether the door it covers is open or closed. It collects the variables as they change and waits until it has all before it does anything.

The code is:

var shutterauto = context.get(“shutterauto”) || false;
var airconon = context.get(“airconon”);
var thiinside = context.get(“thiinside”);
var thioutside = context.get(“thioutside”);
var hotinside = context.get(“hotinside”);
var coldinside = context.get(“coldinside”);
var hotoutside = context.get(“hotoutside”);
var coldoutside = context.get(“coldoutside”);
var shutterlevel = context.get(“shutterlevel”);
var mqtttopic = context.get(“mqtttopic”);
var ready = context.get(“ready”);
var toplevel = context.get(“toplevel”);
var bottomlevel = context.get(“bottomlevel”);
var mystatus = “”;
var isday = context.get(“isday”);
var sunazimuth = context.get(“sunazimuth”);
var sunelevation = context.get(“sunelevation”);
var highazimuth = context.get(“highazimuth”) || 0;
var lowazimuth = context.get(“lowazimuth”) || 360;
var highelevation = context.get(“highelevation”) || 0;
var lowelevation = context.get(“lowelevation”) || 90;
var highforecast = context.get(“highforecast”);
var lowforecast = context.get(“lowforecast”);

if (msg.topic === “ShutterAuto”)
{
shutterauto = msg.payload;
context.set(“shutterauto”, shutterauto);
}
else if (msg.topic === “AirConOn”)
{
airconon = msg.payload;
context.set(“airconon”, airconon);
}
else if (msg.topic === “THIInside”)
{
thiinside = Number(msg.payload);
context.set(“thiinside”, thiinside);
}
else if (msg.topic === “THIOutside”)
{
thioutside = Number(msg.payload);
context.set(“thioutside”, thioutside);
}
else if (msg.topic === “HotInside”)
{
hotinside = Number(msg.payload);
context.set(“hotinside”, hotinside);
}
else if (msg.topic === “ColdInside”)
{
coldinside = Number(msg.payload);
context.set(“coldinside”, coldinside);
}
else if (msg.topic === “HotOutside”)
{
hotoutside = Number(msg.payload);
context.set(“hotoutside”, hotoutside);
}
else if (msg.topic === “ColdOutside”)
{
coldoutside = Number(msg.payload);
context.set(“coldoutside”, coldoutside);
}
else if (msg.topic === “ShutterLevel”)
{
shutterlevel = Number(msg.payload);
context.set(“shutterlevel”, shutterlevel);
}
else if (msg.topic === “mqtttopic”)
{
mqtttopic = msg.payload;
context.set(“mqtttopic”, mqtttopic);
}
else if (msg.topic === “Ready”)
{
ready = msg.payload;
context.set(“ready”, ready);
}
else if (msg.topic === “BottomLevel”)
{
bottomlevel = msg.payload;
context.set(“bottomlevel”, bottomlevel);
}
else if (msg.topic === “TopLevel”)
{
toplevel = msg.payload;
context.set(“toplevel”, toplevel);
}
else if (msg.topic.includes(“isDay”))
{
isday = msg.payload;
context.set(“isday”, isday);
}
else if (msg.topic.includes(“SunAzimuth”))
{
sunazimuth = msg.payload;
context.set(“sunazimuth”, sunazimuth);
}
else if (msg.topic.includes(“SunElevation”))
{
sunelevation = msg.payload;
context.set(“sunelevation”, sunelevation);
}
else if (msg.topic.includes(“HighAzimuth”))
{
highazimuth = msg.payload;
context.set(“highazimuth”, highazimuth);
}
else if (msg.topic.includes(“HighElevation”))
{
highelevation = msg.payload;
context.set(“highelevation”, highelevation);
}
else if (msg.topic.includes(“LowElevation”))
{
lowelevation = msg.payload;
context.set(“lowelevation”, lowelevation);
}
else if (msg.topic.includes(“SunElevation”))
{
sunelevation = msg.payload;
context.set(“sunelevation”, sunelevation);
}
else if (msg.topic.includes(“HighForecast”))
{
highforecast = msg.payload;
context.set(“highforecast”, highforecast);
}
else if (msg.topic.includes(“LowForecast”))
{
lowforecast = msg.payload;
context.set(“lowforecast”, lowforecast);
}

node.status({text: shutterauto+":"+shutterauto+":"+airconon+":"+thiinside+":"+thioutside+":"+hotinside+":"+coldinside+":"+hotoutside+":"+coldoutside+":"+shutterlevel+":"+toplevel+":"+bottomlevel+":"+mqtttopic+":"+isday+":"+ready});
if ((shutterauto === undefined) ||
(shutterauto === false) ||
(airconon === undefined) ||
(thiinside === undefined) ||
(thioutside === undefined) ||
(hotinside === undefined) ||
(coldinside === undefined) ||
(hotoutside === undefined) ||
(coldoutside === undefined) ||
(shutterlevel === undefined) ||
(toplevel === undefined) ||
(bottomlevel === undefined) ||
(mqtttopic === undefined) ||
(isday === undefined) ||
(sunazimuth === undefined) ||
(sunelevation === undefined) ||
(highazimuth === undefined) ||
(lowazimuth === undefined) ||
(highelevation === undefined) ||
(lowelevation === undefined) ||
(ready === undefined))
{
return;
}
if ((sunelevation >= lowelevation) && (sunelevation <= highelevation) && (sunazimuth >= lowazimuth) && (sunazimuth <= highazimuth))
{
toplevel = (sunelevation - lowelevation) * ((toplevel - bottomlevel) / (highelevation - lowelevation)) + bottomlevel;
}
else
{
toplevel = 100;
bottomlevel = 0;
}
if ((lowforecast < coldoutside) || (highforecast > hotoutside))
{
toplevel = 50;
bottomlevel = 0;
}
if (airconon === true)
{
mystatus = “airconon:”;
if (ready === true)
{
mystatus = “airconon:ready:bottom:”;
msg.payload = bottomlevel;
}
else
{
mystatus = “airconon:ready:0:”;
msg.payload = 0;
}
}
else if (((thioutside < coldoutside) ||
(thioutside > hotoutside)) &&
((ready === false) && (shutterlevel > 0))
)
{
mystatus = “outsideworse:”;
if (ready === true)
{
mystatus = “outsideworse:ready:bottom:”;
msg.payload = bottomlevel;
}
else
{
mystatus = “outsideworse:ready:0:”;
msg.payload = 0;
}
}
else if ((thiinside < coldinside) || (thiinside > hotinside))
{
mystatus = “insidehotcold::top:”;
msg.payload = toplevel;
}
else if (isday === true)
{
mystatus = “isday::top:”;
msg.payload = toplevel;
}
else
{
mystatus = “::bottom:”;
msg.payload = bottomlevel;
}
msg.topic = mqtttopic;
mystatus = mystatus + mqtttopic.replace(“openhab2/in/”,"").replace("/command","") + “:” + msg.payload;
mystatus = mystatus+":"+shutterauto+":"+shutterauto+":"+airconon+":"+thiinside+":"+thioutside+":"+hotinside+":"+coldinside+":"+hotoutside+":"+coldoutside+":"+shutterlevel+":"+toplevel+":"+bottomlevel+":"+mqtttopic+":"+isday+":"+ready;

node.status({text: mystatus});
if (msg.payload === shutterlevel)
{
return;
}

return msg;