Hi,
this is in my opinion a simple and nice solution to perform a sendCommand to an item at a specified time. I tested it with multiple items and item types.
For example, let’s assume that we have the following items:
// Bulb1
Switch Light1_Toggle { channel="hue:0210:1:bulb1:color" }
Dimmer Light1_Dimmer { channel="hue:0210:1:bulb1:color" }
Color Light1_Color { channel="hue:0210:1:bulb1:color" }
Dimmer Light1_ColorTemp { channel="hue:0210:1:bulb1:color_temperature" }
String Light1_Alert { channel="hue:0210:1:bulb1:alert" }
Switch Light1_Effect { channel="hue:0210:1:bulb1:effect" }
// Bulb2
Switch Light2_Toggle { channel="hue:0220:1:bulb2:brightness" }
Dimmer Light2_Dimmer { channel="hue:0220:1:bulb2:brightness" }
Dimmer Light2_ColorTemp { channel="hue:0220:1:bulb2:color_temperature" }
In my solution you then have to create:
// Bulb1
String Light1_Toggle_Scheduler "[%s]"
String Light1_Dimmer_Scheduler "[%s]"
String Light1_Color_Scheduler "[%s]"
String Light1_ColorTemp_Scheduler "[%s]"
String Light1_Alert_Scheduler "[%s]"
String Light1_Effect_Scheduler "[%s]"
// Bulb2
String Light2_Toggle_Scheduler "[%s]"
String Light2_Dimmer_Scheduler "[%s]"
String Light2_ColorTemp_Scheduler "[%s]"
The scheduler rule looks like this:
from datetime import datetime
from core.rules import rule
from core.triggers import when
from core.actions import LogAction
import time
import pytz
def execute_command(item_name, command, schedule_date_str):
timezone = pytz.timezone('Europe/Berlin') # Wähle die entsprechende Zeitzone
current_date = datetime.now(timezone).replace(microsecond=0) # Setze Mikrosekunden auf 0
schedule_date = datetime.strptime(schedule_date_str, "%Y-%m-%dT%H:%M:%S")
schedule_date = timezone.localize(schedule_date).replace(microsecond=0) # Setze Mikrosekunden auf 0
if current_date == schedule_date:
LogAction.logInfo("rules", "Scheduler will sendCommand {} to item {}", command, item_name)
events.sendCommand(item_name, command)
time.sleep(1)
events.postUpdate(item_name, "")
@rule("Command Scheduler")
@when("Time cron * * * * * ?")
def command_scheduler(event):
items_data = {
"Light1_Toggle_Scheduler": "Light1_Toggle",
"Light1_Dimmer_Scheduler": "Light1_Dimmer",
"Light1_Color_Scheduler": "Light1_Color",
"Light1_ColorTemp_Scheduler": "Light1_ColorTemp",
"Light1_Alert_Scheduler": "Light1_Alert",
"Light1_Effect_Scheduler": "Light1_Effect",
"Light2_Toggle_Scheduler": "Light2_Toggle",
"Light2_Dimmer_Scheduler": "Light2_Dimmer",
"Light2_ColorTemp_Scheduler": "Light2_ColorTemp"
}
for item_scheduler, item_name in items_data.items():
item_state = str(ir.getItem(item_scheduler).state)
if item_state != "NULL" and item_state != "":
state = item_state.replace(" ", "").split(",")
schedule_date = state[0]
command = state[1]
execute_command(item_name, command, schedule_date)
On the left side you have to say which schedule item (String type) belongs to which item (this item should receive the command at the specific time) on the right side.
I also had to use pytz to make sure that both datetime objects are really in the same time zone. Otherwise the alignment does not work.
For testing I used the karaf console. As example you can make following command:
openhab:send Light1_Toggle_Scheduler "2023-07-20T13:55:00,ON"
This means that the cron trigger which runs every second will check if 2023-07-20T13:55:00 is reached and then makes an sendCommand with “ON” to Light1_Toggle.
Advantages
- You can run a command exactly at a specific time. (This could also work after restarting openHAB if you have a persistence for your scheduler item which is a String item.)
- You can access it easily via the REST API because your schedule is an item.
Disadvantages
- For each item you have to create a String item which receives the command and splits it into a schedule date and a command
- You can only create one schedule. As example you can’t say that at 13:15 the bulb should receive an ON command and on 13:30 an OFF command. (Of course, this can still be optimized.)
A second-by-second check does not even increase CPU usage by 1% for me.