Skip to content

Instantly share code, notes, and snippets.

@suhajdab
Last active August 26, 2022 22:22
Show Gist options
  • Save suhajdab/2f162833369751a07239b6736ddb6d5f to your computer and use it in GitHub Desktop.
Save suhajdab/2f162833369751a07239b6736ddb6d5f to your computer and use it in GitHub Desktop.
Calculate Color Temperature and Brightness for current time in HomeyScript
/**
* Adjust Color temperature and Brightness based on time of day
* as if it were April 16th, a nice long spring day in southern Sweden
*/
const VARIABLE_PREFIX = 'CircadianRhythm_';
const MIN_BRIGHTNESS = 0.12;
const MAX_BRIGHTNESS = 1;
const sys = await Homey.system.getInfo();
// hack because sys date no longer returns local time, but rather UTC :(
const regex = /(\d\d):(\d\d):(\d\d)/;
const timeMatches = sys.dateHuman.match(regex)
const solarNoon = 0.546 // on April 16 is 13:06
// defaults
let temperature = 1; // Homey color temperature: 0 (coolest, midday) to 1 (warmest, sunset/sunrise)
let brightness = MIN_BRIGHTNESS; // [0-1]
// used standard normal distribution curve to derive equation [https://en.wikipedia.org/wiki/Normal_distribution#Standard_normal_distribution]
// equations adjusted for color temperature and brightness [https://codepen.io/suhajdab/pen/wvzpqdQ?editors=0010]
getTemperaturePoint = x => {
const r = 0.20; // adjust curve width
return Math.pow(Math.E, -0.3 * Math.pow((x - solarNoon) / r, 4));
}
getBrightnessPoint = x => {
const r = 0.28; // adjust curve width
return Math.min(1 * Math.pow(Math.E, -0.3 * Math.pow((x - solarNoon) / r, 8)), 1);
}
// round to 2 decimal places to avoid 'invalid token error' when reading in a flow
const roundDecimals = (num, places = 2) => {
return Math.round(num * Math.pow(10, places)) / Math.pow(10, places);
}
const dayStart = new Date(sys.date).setHours(0, 0);
const dayEnd = new Date(sys.date).setHours(23, 59);
const now = new Date(sys.date).setHours(timeMatches[1]); // adjust for borked timezones in Homey v5
const dayProgress = roundDecimals((now - dayStart) / (dayEnd - dayStart), 4);
console.log('At', new Date(now).toLocaleTimeString([], { hour12: false }));
console.log('Day progress:\t\t', `${Math.round(dayProgress * 100)}%`);
// use Better Logic app to store values and use later in Flows
let BLApp = await Homey.apps.getApp({ id: 'net.i-dev.betterlogic' });
// color temperature transitions from 1 to 0 to 1 during the day
temperature = roundDecimals(1 - getTemperaturePoint(dayProgress));
console.log(`${VARIABLE_PREFIX}_temperature:\t`, temperature);
// brightness transitions from MIN to MAX to MIN during day
brightness = roundDecimals((MIN_BRIGHTNESS + (MAX_BRIGHTNESS - MIN_BRIGHTNESS) * getBrightnessPoint(dayProgress)));
console.log(`${VARIABLE_PREFIX}_brightness:\t`, brightness);
BLApp.apiPut(`${VARIABLE_PREFIX}temperature/${temperature}`);
BLApp.apiPut(`${VARIABLE_PREFIX}brightness/${brightness}`);
return true;
@suhajdab
Copy link
Author

getTemperaturePoint and getBrightnessPoint return points on these curves during the course of the day.
image
source: codepen

@clipse2004
Copy link

Hi,
Just discovered your script and immediately packed in homeyscript!
But I still have some questions:
which flows have you made? Do you let homey do the
script every second?
Which flow did you create so that the temperature etc. are retrieved? Are they stored in a logic?
Definitely want to have this :slight_smile:
Maybe you could share your flows on this?
I would be mega grateful to you 😉

Nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment