const Gpio = require("pigpio").Gpio; const schedule = require("./schedule.json"); const HZ = 40000; const NAP_DURATION = 100 * 60 * 1000; let ledRed = new Gpio(12, {mode: Gpio.OUTPUT}); let ledGreen = new Gpio(13, {mode: Gpio.OUTPUT}); let napButton = new Gpio(6, {mode: Gpio.INPUT, pullUpDown: Gpio.PUD_UP, alert: true }); napButton.glitchFilter(10000); let timings = schedule.times.reduce((result, time) => { result.push({start: time.time, color: time.color}); return result; }, []).sort((a, b) => a.start - b.start).map((timing, i, arr) => { timing.end = arr[(i+1) % arr.length].start; return timing; }); splitAtMidnight(timings); let state = { color: "red" } updateState(); let updateStateInterval = setInterval(updateColorState, 1000); let renderInterval = setInterval(render, 50); napButton.on("alert", startNap); function startNap(level, tick) { state = { ...state, napTime: true, napEnd: Date.now() + NAP_DURATION } } function updateColorState() { let newColor = state.color; switch(state.napTime) { case true: if(Date.now() < state.napEnd) { newColor = "red"; break; } else { state = { ...state, napTime: false, napEnd: 0, }; } case false: let time = getTime(); let timing = timings.find(x => x.start <= time && x.end > time); newColor = timing.color } if(newColor !== state.color) { state = { ...state, color: timing.color }; } } function render() { switch(state.color) { case "red": if(ledGreen.digitalRead()) { return ledGreen.digitalWrite(0); } return ledRed.hardwarePwmWrite(HZ, getBrightness(Date.now())); break; case "green": if(ledRed.digitalRead()) { return ledRed.digitalWrite(0); } if(!ledGreen.digitalRead()) { return ledGreen.digitalWrite(1); } //Commenting out. Probably don't need breathing on green leds //return ledGreen.hardwarePwmWrite(HZ, getBrightness(Date.now())); break; } } function getBrightness(x) { return Math.floor(breathingCurve(x, 6000, 100000, 1000000)); } function breathingCurve(x, interval = 3000, min, max) { let t = x * Math.PI/(interval/2); let y = Math.sin(t + Math.sin(t) * 0.2); let untranslatedY = Math.sin(t + Math.sin(t) * 0.25); y = (untranslatedY + 1)/2; return y * (max - min) + min; } function splitAtMidnight(arr) { let last = arr[arr.length -1]; arr.unshift({ ...last, start: 0}); arr[arr.length - 1].end = 2400; } function getTime() { let date = new Date(Date.now()); return (date.getHours() * 100) + date.getMinutes() + 1 }