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:”;
msg.payload = toplevel;
}
else if (isday === true)
{
mystatus = “isday:”;
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;