I replaced almost all my lights with HUE and Tadfri bulbs and Osram/HUE plugs all connected to the HUE bridge. The people in the house hold also use the physical switches to turn of lights. As a consequence the lights in the HUE app and the physical state of the lights are no longer in sync.
( i do try to minimize this by automating as much as possible).
I created this Homeyscript (needs +/- 1 second run time) which is executed every 2 minutes. If a light is unreachable for a set amount of time, it is turned off.
It took quit some time combining, googling, asking people for help; now it working sharing it here . Maybe it can spark other ideas, maybe people see improvements in my code?
The trick is to get the HUE key and to give the HUE hub a fixed IP address (the key below was altered after copying). This is explained here in this post:
[Updated april 11, to include different tag values for reachable/unreachable]
// Performance indicator: calculate + report execution time @EOF
StartTime = _.now();
// Assume a execution frequency of every minute
// Frequecy is determined in the flow card.
// Alternative is calculating DeltaRun by uncommenting code below
DeltaRun = 60; // seconds
// Time limit after which a light is turned off
let TimeLimit = 600; // seconds
// Set uri for Homeyscript
let uri = 'homey:app:com.athom.homeyscript';
// set and build basis HUE API Url
let hueBridgeIP = '192.168.1.2'
hueBridgeAPI = '2cHXcel6RJWnVuH5oHWaqASV28KKNlMAQu1wJQl0'
let urltext = "http://" + hueBridgeIP +"/api/" + hueBridgeAPI + "/lights"
// call and process the HUE light overview
let response = await fetch(urltext);
let json = await response.text();
var obj = JSON.parse(json);
//Determine how many seconds have passed since previous execution of this script
// If the tag does not yet exist (during first run / restart of Homey), start at 0
// this step increases execution time with +/- 200ms
//try {
// let PreviousRun = await Homey.flowToken.getFlowToken({ uri: uri, id: 'HUE run'});
// DeltaRun = _.toInteger( (_.now() - PreviousRun.value)/1000);}
//catch(err) {
// DeltaRun = 0};
// reset the HUE run tag with the current time, to be used next execution time
// run frequency is determined in the flow card
//await tag('HUE run', _.now());
// Loop through all the lights in the HUE setup, pick up the lightname as it is used frequently in the script
for (const [i,light] of Object.entries(obj)) {
LightName = light.name;
// If light can be reached, reset tag to 0
// If light cannot be reached, reset tag to -1
// Alternative is to only put those lights tags to 0 if existing tag <> 0. (Takes 3 seconds extra execution time.)
if (light.state.reachable )
{await tag(light.name, 0)};
//Light cannot be reached, and light is on -> increase the light tag with the no of seconds between excution runs
if (!light.state.reachable && light.state.on){
// Pull current tag value. if tag does not exist, create it. (first run / Homey restart / adding new light)
try {
let LightTag = await Homey.flowToken.getFlowToken({ uri: uri, id: LightName});
TimeLightNotReached = LightTag.value }
catch(err) {
TimeLightNotReached = 0 ;
};
// increase timer with the time between runs
TimeLightNotReached = TimeLightNotReached + DeltaRun;
log(LightName + ' cannot be reached, but it is on in HUE app ' + ' Counter =' + TimeLightNotReached);
// if light is unreachable multiple executions and the time is up, switch it off, set tag to 0
if (TimeLightNotReached > TimeLimit)
{log ('Switching off ' + LightName +' (' + TimeLightNotReached + '>' + TimeLimit + ")" );
a = await fetch(urltext + '/' + i + '/state', { method : 'PUT',body : JSON.stringify({"on":false})})
TimeLightNotReached = -1
};
// write back the new timer value to the tag. -1 if it was just switched off and unreachable,
// else it will be the increased number
await tag(LightName, TimeLightNotReached);}
} //loop back to next light
// calculate and report the execution time (as part of performance )
log(( _.now() - StartTime)/1000 + ' seconds')