Examples
Porch light
Lights on a little before sunset, off at a fixed time, every day, and still correct after a reboot.
The classic evening light. Sunset moves every day, so the on-time is anchored to the hub's sun times; the off-time is a plain daily schedule.
What it shows
scheduleAtSunsetis one-shot and is re-armed inside its own handler and onsystemStart. See Daily sun-anchored behaviour.runDailyfor the fixed off-time; daily schedules persist on their own.- A brightness input that only appears when the picked lights can dim, via
requiresEntityFeature. See Gating on the picked device.
const definition = {
name: 'Porch Light',
namespace: 'com.example',
description: 'Turns lights on before sunset and off at a fixed time every night.',
category: 'lighting',
};
const preferences = {
pages: [{
id: 'main',
title: 'Porch Light',
inputs: [
{ key: 'lights', label: 'Lights', type: 'entity', domainFilter: 'light', multiple: true, required: true },
{ key: 'beforeSunsetMinutes', label: 'Turn on this many minutes before sunset',
type: 'number', default: 20, minValue: 0, maxValue: 120 },
{ key: 'brightness', label: 'Brightness (1–100)', type: 'number', minValue: 1, maxValue: 100,
requiresEntityFeature: { siblingKey: 'lights', domain: 'light', colorMode: 'brightness' } },
{ key: 'offTime', label: 'Turn off at', type: 'time', default: '23:00', required: true },
],
}],
};
function installed() { initialize(); }
function updated() { unsubscribe(); unschedule(); initialize(); }
function initialize() {
subscribeToLocationEvent('systemStart', armSunset); // a reboot may have dropped the pending one-shot
runDaily(typeof offTime === 'string' ? offTime : '23:00', lightsOff);
armSunset();
}
function armSunset() {
const minutes = typeof beforeSunsetMinutes === 'number' ? beforeSunsetMinutes : 20;
scheduleAtSunset(lightsOn, -minutes); // fires once, at the next sunset
}
function lightsOn() {
const params = typeof brightness === 'number' ? { brightnessPercent: brightness } : {};
lights.turnOn(params); // one light or many: the call fans out
state.lastOnAt = new Date().toISOString();
armSunset(); // re-arm for tomorrow
}
function lightsOff() {
lights.turnOff();
}
function run() { // the Run button: "do the evening thing now"
lightsOn();
}How it works
- Sunset is a one-shot.
scheduleAtSunsetarms a single firing at the next sunset.lightsOnends by arming the next one, which is what makes it daily. systemStartis the safety net. The hub restores pending timers after a reboot, but re-arming on boot costs nothing and protects against the edge cases (a reboot that spans the sunset, a hub that only got its location after install).runDailyneeds no re-arming. Cron and daily schedules are persistent; they are torn down inupdatedso a changed off-time does not leave the old one firing.- Before the hub has a location the sun times are unavailable and
scheduleAtSunsetcannot fire. Set the monitoring address in the Novon app;getSunTimes().availabletells you if it is set.
Try changing
- Turn the lights off at sunrise instead of a fixed time: replace
runDailywith ascheduleAtSunrise(lightsOff)that re-arms itself the same way. - Only run when nobody is home: wrap
lights.turnOninif (new EntityWrapper('system.group_presence').is('Not Present')). See System entities.