Last active
January 5, 2022 11:47
-
-
Save mrpapercut/901f9e7d1525969f339ad65f9e1df187 to your computer and use it in GitHub Desktop.
Philips Hue automatic lighting based on sunrise/sunset
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
/** | |
* Automatically turns on lights based on sunrise/sunset | |
* Usage: use cronjob to trigger every night after midnight | |
* | |
* NPM packages required: superagent, node-hue-api | |
*/ | |
import request from 'superagent'; | |
import HueApi from 'node-hue-api'; | |
const config = { | |
hue: { | |
bridge: { | |
hostname: <bridge IP address>, | |
id: <bridgeId> | |
}, | |
user: { | |
username: <username>, | |
description: <user description> | |
}, | |
scenes: { | |
'Sunrise': <sceneId>, | |
'Sunset': <sceneId> | |
} | |
}, | |
sunsettings: { | |
latitude: <latitude>, | |
longitude: <longitude>, | |
minSunrise: '07:00:00 AM', // Don't turn lights on before this time | |
minSunset: '06:30:00 PM' // Don't turn lights on before this time | |
} | |
} | |
class SunriseSunset { | |
constructor() { | |
this.api = new HueApi(config.hue.bridge.hostname, config.hue.user.username); | |
this.scenes = config.hue.scenes; | |
this.fetchSunriseSunset(); | |
} | |
fetchSunriseSunset() { | |
const {latitude, longitude} = sunSettings; | |
request | |
.get(`https://api.sunrise-sunset.org/json?lat=${latitude}&lng=${longitude}`) | |
.end((err, {body}) => { | |
if (err) { | |
console.error(err); | |
} else { | |
// Time options: | |
// sunrise, sunset | |
// civil_twilight_begin, civil_twilight_end | |
// nautical_twilight_begin, nautical_twilight_end | |
// astronomical_twilight_begin, astronomical_twilight_end | |
// IMO nautical_twilight works best to start lights | |
this.setSchedules(body.results.nautical_twilight_begin, body.results.nautical_twilight_end); | |
} | |
}); | |
} | |
// Determine times to use for schedule | |
setSchedules(sunrise, sunset) { | |
let {minSunrise, minSunset} = config.sunSettings; | |
[sunrise, minSunrise, sunset, minSunset] = | |
[sunrise, minSunrise, sunset, minSunset].map(t => this.formatDate(t)); | |
const [pSunrise, pMinSunrise, pSunset, pMinSunset] = | |
[sunrise, minSunrise, sunset, minSunset].map(t => Date.parse(this.formatDate(t))); | |
this.setHueSchedule(pSunrise > pMinSunrise ? sunrise : minSunrise, 'Sunrise'); | |
this.setHueSchedule(pSunset > pMinSunset ? sunset : minSunset, 'Sunset'); | |
} | |
// Set schedule on Hue device | |
setHueSchedule(time, name) { | |
const scheduleEvent = { | |
name: name, | |
time: time, | |
localtime: time, | |
description: name, | |
command: { | |
address: `/api/${hueSettings.user.username}/groups/0/action`, | |
body: { | |
scene: this.scenes[name] | |
}, | |
method: 'PUT' | |
} | |
}; | |
this.api.createSchedule(scheduleEvent).catch(e => console.error(e)).done(); | |
} | |
// Format sunrise-sunset-api-format to node-hue-api-format | |
// Example input: "6:15:00 PM" | |
// Example output: "2017-04-01T18:15:00" | |
formatDate(timestring) { | |
return timestring.replace(/^([0-9]{1,2}):([0-9]{2}):([0-9]{2})\s(PM|AM)$/, (match, h, m, s, ap) => { | |
const p = s => ('00' + s).substr(-2); | |
let [Y, M, d] = ['FullYear', 'Month', 'Date'].map(s => new Date()['get'+s]()); | |
ap === 'PM' ? h = parseInt(h, 10) + 12 : null; | |
[h, m, s] = [h, m, s].map(p); | |
return `${Y}-${p(++M)}-${p(d)}T${h}:${m}:${s}` | |
}); | |
} | |
} | |
new SunriseSunset(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment