Last active
April 27, 2018 21:19
-
-
Save ConnorGriffin/be4b380f105578bcf5fbd98af401d831 to your computer and use it in GitHub Desktop.
Home Assistant Node-RED Scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var homeStatus = msg.payload.data.state | |
var homeStatusMinutes = Math.floor((msg.payload.timeSinceChangedMs/1000)/60) | |
var notHome = (homeStatus == "not_home" && homeStatusMinutes >= 10) | |
var ecobeeStatus = flow.get("ecobeeStatus") | |
var holdMode = ecobeeStatus.data.attributes.hold_mode | |
var climateMode = ecobeeStatus.data.attributes.climate_mode | |
var operationMode = ecobeeStatus.data.attributes.operation_mode | |
// Set the holdMatch criteria based on whether we're home or not, this is so we don't cancel temp or vacation holds | |
if (notHome) { | |
var holdMatch = (holdMode == "away" || holdMode == "home" || holdMode == "temp" || !holdMode) | |
} else { | |
var holdMatch = (holdMode == "away" || holdMode == "home" || !holdMode) | |
} | |
// Set the possible return payloads | |
var away = { | |
"payload": { | |
"switchAction": "hold", | |
"data": {"hold_mode": "away"} | |
} | |
} | |
var home = { | |
"payload": { | |
"switchAction": "hold", | |
"data": {"hold_mode": "home"} | |
} | |
} | |
var resume = { | |
"payload": { | |
"switchAction": "resume", | |
"data": {"resume_all": true} | |
} | |
} | |
// Doesn't evaluate if ecobee is off or in vacation mode, or we're home and in a temp hold | |
if (operationMode != "off" && holdMatch) { | |
if (notHome) { | |
if (holdMode != "away" && climateMode != "Away") { | |
// Set an Away hold if confort setting isn't Away, and we haven't set an away hold | |
return away | |
} else if (holdMode && climateMode == "Away") { | |
// Resume operation if comfort setting is Away and there is a home/away hold | |
return resume | |
} | |
// Do nothing if holdMode is null and climateMode is Away (already away) | |
// Do nothing if holdMode is away and climateMode is not Away (away hold already set) | |
} else { | |
// If we are home | |
if (holdMode != "home" && climateMode == "Away") { | |
// If we're home during a standard away time, set a home hold | |
return home | |
} else if (holdMode && climateMode != "Away") { | |
// If we're home during any hold where the comfort setting would normally be a home/sleep setting, resume schedule | |
return resume | |
} | |
// Do nothing if we're home during a home/sleep time with no hold set | |
} | |
} | |
// Return a switchAction of null if nothing happens, just for debugging | |
return {"payload": {"switchAction": null,}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var occupied = flow.get("occupied") | |
var lightOn = flow.get("lightOn") | |
var override = flow.get("override") | |
var currentBrightness = flow.get("light").data.attributes.brightness | |
var lightSchedule = [ | |
{ | |
"pct": 100, | |
"start": "10:00", | |
"end": "16:00" | |
}, | |
{ | |
"pct": 70, | |
"start": "18:00", | |
"end": "18:00" | |
}, | |
// Between 6 PM and 10 PM, linearly scale from 100 to 10% brightness, then do the inverse from 6 AM to 10 AM | |
{ | |
"pct": 10, | |
"start": "21:00", | |
"end": "06:00" | |
} | |
] | |
// If the room is occupied and the light is on, use the schedule | |
if (occupied && lightOn && !override) { | |
// Get the current minutes from 00:00 (ex: 5:00 would be 300) | |
var d = new Date() | |
var hh = d.getHours() | |
var mm = d.getMinutes() | |
var currentMs = hh * 60 + mm | |
/* | |
if next start hours is less than current start hours, subtract difference from 24? | |
current time: 7 | |
next start: 6 | |
start - current + 24 | |
Calculate the difference between the end and start of the next two schedules | |
Calcuate the difference between the brightness levels | |
Calculate how far into that difference we are, determine what brightness to set based on this | |
*/ | |
// Iterate through each schedule item | |
for (i = 0; i < lightSchedule.length; i++) { | |
// Get the minutes for the current schedule | |
var scheduleStartMs = lightSchedule[i].start.split(":")[0] * 60 + parseInt(lightSchedule[i].start.split(":")[1]) | |
var scheduleEndMs = lightSchedule[i].end.split(":")[0] * 60 + parseInt(lightSchedule[i].end.split(":")[1]) | |
// Change calculation if schedule end carries into the next day | |
if (scheduleEndMs < scheduleStartMs) { | |
if (currentMs < scheduleEndMs) { | |
var currentMs = -currentMs + 24 * 60 | |
} | |
var scheduleEndMs = scheduleEndMs + 24 * 60 | |
} | |
if (currentMs >= scheduleStartMs && currentMs <= scheduleEndMs) { | |
// If we're actually in the schedule, return the set percentage | |
var targetPercent = lightSchedule[i].pct | |
break // Don't evaluate any more schedules | |
} else { | |
// Get the nextSchedule item, go to 0 (wrap around) if we're on the last schedule | |
if (i+1 == lightSchedule.length) { | |
var nextSchedule = lightSchedule[0] | |
} else { | |
nextSchedule = lightSchedule[i+1] | |
} | |
// Get the minutes for the next schedule start time | |
var nextScheduleStartMs = nextSchedule.start.split(":")[0] * 60 + parseInt(nextSchedule.start.split(":")[1]) | |
// If the next schedule starts before the current schedule ends, calculate the minutes based on going into tomorrow (4:00 becomes 28:00) | |
if (nextScheduleStartMs < scheduleEndMs || scheduleEndMs < scheduleStartMs) { | |
var nextScheduleStartMs = nextScheduleStartMs + 24 * 60 | |
} | |
// if we are between the two schedules, calculate the brightness percentage | |
if (currentMs >= scheduleEndMs && currentMs <= nextScheduleStartMs) { | |
var timeDiff = nextScheduleStartMs - scheduleEndMs | |
var brightDiff = lightSchedule[i].pct - nextSchedule.pct | |
var brightPerMin = brightDiff / timeDiff | |
var targetPercent = lightSchedule[i].pct - (timeDiff - (timeDiff - (currentMs - scheduleEndMs))) * brightPerMin | |
break | |
} | |
//console.log(nextScheduleStartMs) | |
} | |
} | |
} | |
if (targetBrightness) { | |
var setBrightnessDiff = Math.abs((targetPercent * 2.55) - currentBrightness) | |
// Don't do anything if the diffence is less than 5 (2%) | |
if (setBrightnessDiff > 5) { | |
flow.set("lastSetBrightness",targetPercent) | |
return { | |
"payload": { | |
"entity_id": "light.ge_14294_inwall_smart_dimmer", | |
"data": { | |
"brightness_pct": targetPercent | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment