Sorry if this develops a little bit into rant. OpenHAB is great, but this is a recurring issue for me that is just hugely frustrating. Let me say in advance, I really do not want to click any rules in any webinterface. I want to keep writing them in text files, versioning them in GIT and so on.
I am trying to write some rules for automatic wakeup light. Tasker on my phone will send the next alert time to an MQTT channel at 1 o’clock in the night, and OpenHAB rules will set up a Timer start the light at minimum and then after a defined time increase brightness until a target brightness is reached at wakeup time.
I have this working in another room. Now I tried to set it up for our bedroom, with warm and cold lights to be controlled independently.
Unfortunately, I get this very informative error in the log:
08:30:53.948 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'LE_FirstFloor_Bedroom_AlertMinute_Rule': org.eclipse.smarthome.core.library.types.DecimalType
This is problem number one with OpenHAB: The log is just absolutely useless. Either it throws about a million log lines per second at you, or it doesnt even tell you that you forgot the item= in the sitemap. This is the most useless log entry for a rule I ever got, but all the rest is not far away.
So I tried to fire up the SmarthomeDesigner, which I hate, (I like to just write that stuff in vim in an ssh session, like every other config on the server). Anyways, the OpenHABDesigner in OH1 was halfway useful to find issues. Unfortunately, it shows me this:
Apparently, even postUpdate() is allegedly undefined.
can anybody tell me if there is a way to develop rules that doesn’t make me want to electrocute myself with a zwave powerswitch?
Although I am not primarily looking for help on that particular ruleset, but on developing rules in general, here is the code for completeness (EDIT: The screenshot above is the WORKING code for the other room. Below is the adaption for the main bedroom)
import org.eclipse.smarthome.core.library.types.*
import org.joda.time.*
import java.lang.Math
var Timer masterAlarmTimeWarm = null
var Timer masterAlarmTimeCold = null
rule LE_FirstFloor_Bedroom_Mainlight_Warm_Min_Rule
when
Item LE_FirstFloor_Bedroom_Mainlight_Warm_Min received command ON
then
postUpdate(LE_FirstFloor_Bedroom_Mainlight_Warm_Min, OFF);
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Warm1, 1);
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Warm2, 1);
end
rule LE_FirstFloor_Bedroom_Mainlight_Cold_Min_Rule
when
Item LE_FirstFloor_Bedroom_Mainlight_Cold_Min received command ON
then
postUpdate(LE_FirstFloor_Bedroom_Mainlight_Cold_Min, OFF);
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Cold1, 1);
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Cold2, 1);
end
rule LE_FirstFloor_Bedroom_AlertMinute_Rule
when
Item LE_FirstFloor_Bedroom_AlertMinute received update
then
var String alarmTimeStr = now.getYear() + "-" + now.getMonthOfYear() + "-" + now.getDayOfMonth() + "T" + (LE_FirstFloor_Bedroom_AlertHour.state as DecimalType).intValue() + ":" + (LE_FirstFloor_Bedroom_AlertMinute.state as DecimalType).intValue()
var DateTime alarmTimeWarm = DateTime::parse(alarmTimeStr)
alarmTimeWarm = alarmTimeWarm.minusMinutes((LE_FirstFloor_Bedroom_AlertStartMinWarm.state as DecimalType).intValue)
if (alarmTimeWarm.beforeNow)
alarmTimeWarm = alarmTimeWarm.plusDays(1)
masterAlarmTimeWarm = createTimer(alarmTimeWarm) [|
LE_FirstFloor_Bedroom_AlertEvent_Warm.sendCommand(ON)
]
var DateTime alarmTimeCold = DateTime::parse(alarmTimeStr)
alarmTimeCold = alarmTime.minusMinutes((LE_FirstFloor_Bedroom_AlertStartMinCold.state as DecimalType).intValue)
if (alarmTimeCold.beforeNow)
alarmTimeCold = alarmTimeCold.plusDays(1)
masterAlarmTimeCold = createTimer(alarmTimeCold) [|
LE_FirstFloor_Bedroom_AlertEvent_Cold.sendCommand(ON)
]
logInfo("Wakeup Light", "Alarm time "+alarmTimeWarm)
end
rule LE_FirstFloor_Bedroom_AlertEvent_Warm_Rule
when
Item LE_FirstFloor_Bedroom_AlertEvent_Warm received command ON
then
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Warm2, 1);
var int sleepTime = ((LE_FirstFloor_Bedroom_AlertStartMinWarm.state as DecimalType).intValue - (LE_FirstFloor_Bedroom_AlertIncreaseMinWarm.state as DecimalType).intValue)*60*1000
logInfo("Wakeup Light", "Sleeping "+sleepTime+" milliseconds")
Thread::sleep(sleepTime)
var int sleepTime2 = 1000*60*(LE_FirstFloor_Bedroom_AlertIncreaseMinWarm.state as DecimalType).intValue / ((LE_FirstFloor_Bedroom_AlertEndBrightnessWarm.state as DecimalType).intValue-1)
logInfo("Wakeup Light", "Sleeping "+sleepTime2+" milliseconds between increases")
while ((LE_FirstFloor_Bedroom_Mainlight_Warm2.state as DecimalType).intValue < (LE_FirstFloor_Bedroom_AlertEndBrightnessWarm.state as DecimalType).intValue) {
Thread::sleep(sleepTime2)
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Warm1, ((LE_FirstFloor_Bedroom_Mainlight_Warm1.state as DecimalType).intValue+1);
}
postUpdate(LE_FirstFloor_Bedroom_AlertHour, -1)
postUpdate(LE_FirstFloor_Bedroom_AlertMinute, -1)
end
rule LE_FirstFloor_Bedroom_AlertEvent_Cold_Rule
when
Item LE_FirstFloor_Bedroom_AlertEvent_Cold received command ON
then
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Cold1, 1);
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Cold2, 1);
var int sleepTime = ((LE_FirstFloor_Bedroom_AlertStartMinCold.state as DecimalType).intValue - (LE_FirstFloor_Bedroom_AlertIncreaseMinCold.state as DecimalType).intValue)*60*1000
logInfo("Wakeup Light", "Sleeping "+sleepTime+" milliseconds")
Thread::sleep(sleepTime)
var int sleepTime2 = 1000*60*(LE_FirstFloor_Bedroom_AlertIncreaseMinCold.state as DecimalType).intValue / ((LE_FirstFloor_Bedroom_AlertEndBrightnessCold.state as DecimalType).intValue-1)
logInfo("Wakeup Light", "Sleeping "+sleepTime2+" milliseconds between increases")
while ((LE_FirstFloor_Bedroom_Mainlight_Cold2.state as DecimalType).intValue < (LE_FirstFloor_Bedroom_AlertEndBrightnessCold.state as DecimalType).intValue) {
Thread::sleep(sleepTime2)
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Cold1, ((LE_FirstFloor_Bedroom_Mainlight_Cold1.state as DecimalType).intValue+1);
sendCommand(LE_FirstFloor_Bedroom_Mainlight_Cold2, ((LE_FirstFloor_Bedroom_Mainlight_Cold2.state as DecimalType).intValue+1);
}
postUpdate(LE_FirstFloor_Bedroom_AlertHour, -1)
postUpdate(LE_FirstFloor_Bedroom_AlertMinute, -1)
end