127.0.0.1:8000 smart-home-server / master server / routes / lights.js
master

Tree @master (Download .tar.gz)

lights.js @masterraw · history · blame

const utils = require('../utils');
const hue = require('../utils/hue');
const tplink = require('../utils/tplink');
const actions = require('../utils/actions');
const location = require('../utils/location');
const ifttt = require('../utils/ifttt');
const time = require('../utils/time');

let off_action_override = false;

actions.register(function(invoke) {
    if (!location.num_home().curr && location.num_home().prev && !off_action_override) {
        invoke();
    }
}, function() {
    tplink.set_devices(false).then(function() {
        return hue.set_all_lights(function(light) {
            if (light.state.on) {
                return hue.state.off();
            }
        });
    }).then(function() {
        ifttt({
            event: "notification",
            data: "All lights are off"
        });
    }).catch(function(error) {
        console.error(error);
        ifttt({
            event: "notification",
            data: "Error turning all lights off"
        });
    });
}, {
    id: "All lights off when no one is home",
    type: "location"
});

actions.register(function(invoke) {
    if (location.num_home().curr && !location.num_home().prev && !time.daytime(location.coords.home)) {
        invoke();
    }
}, function() {
    off_action_override = false;
    hue.set_all_lights(function() {
        return hue.state.on().brightness(100);
    }).then(function() {
        ifttt({
            event: "notification",
            data: "All lights are on"
        });
    }).catch(function(error) {
        console.error(error);
        ifttt({
            event: "notification",
            data: "Error turning all lights on"
        });
    });
}, {
    id: "All lights on when first arriving home",
    type: "location"
});

let deactivate_porch_lights_timeout;

actions.register(function(invoke) {
    if (location.num_home().curr > location.num_home().prev && !time.daytime(location.coords.home)) {
        invoke();
    }
}, function() {
    hue.set_all_lights(function(light) {
        if (light.name.toLowerCase().includes("porch")) {
            return hue.state.on().brightness(100);
        }
    }).then(function() {
        ifttt({
            event: "notification",
            data: "Porch lights are on"
        });

        clearTimeout(deactivate_porch_lights_timeout);
        deactivate_porch_lights_timeout = setTimeout(function() {
            hue.set_all_lights(function(light) {
                if (light.name.toLowerCase().includes("porch")) {
                    return hue.state.off();
                }
            }).then(function() {
                console.log("Porch lights turned back off after timeout");
            }).catch(console.error);
        }, 1000 * 60 * 5);
    }).catch(function(error) {
        console.error(error);
        ifttt({
            event: "notification",
            data: "Error turning porch lights on"
        });
    });
}, {
    id: "Porch light on when arriving home",
    type: "location"
});

// Auto dim Lights at sunset every day
let sunset_time = time.sunset(location.coords.home);
if (time.now().isBefore(sunset_time)) {
    schedule_lights_dim_at_sunset();
} else {
    setTimeout(schedule_lights_dim_at_sunset, time.one_day * 0.5);
}

function schedule_lights_dim_at_sunset() {
    time.trigger_at_time(time.sunset(location.coords.home), function() {
        console.log("There were", location.num_home().curr, "home when sunset was triggered");
        if (location.num_home().curr) {
            hue.set_all_lights(function(light) {
                if (light.state.on) {
                    if (light.getSupportedStates().includes("ct")) {
                        return hue.state.on().brightness(50).ct(250);
                    }
                    return hue.state.on().brightness(50);
                }
            }).then(function() {
                ifttt({
                    event: "notification",
                    data: "Lights dimmed after sunset"
                });
            }).catch(function(error) {
                console.error(error);
                ifttt({
                    event: "notification",
                    data: "Error dimming lights after sunset"
                });
            });
        }

        // Reschedule in half a day
        setTimeout(schedule_lights_dim_at_sunset, time.one_day * 0.5);
    });
}

// Start transitioning to night mode at 11:00 pm. Transition takes 1 hour (see hue.state.night)
let night_mode_time = time.now().hours(23).minutes(0).seconds(0);
if (time.now().isBefore(night_mode_time)) {
    schedule_night_mode();
} else {
    setTimeout(schedule_night_mode, time.one_day * 0.5);
}

function schedule_night_mode() {
    time.trigger_at_time(night_mode_time, function() {
        console.log("There were", location.num_home().curr, "home when night mode was triggered");
        if (location.num_home().curr) {
            hue.set_all_lights(function(light) {
                if (light.state.on && !light.name.toLowerCase().includes("office")) {
                    return hue.state.night()[hue.color_of(light)];
                }
            }).then(function() {
                return tplink.set_devices("bathroom", true);
            }).then(function() {
                ifttt({
                    event: "notification",
                    data: "Night Mode activated"
                });
            }).catch(function(error) {
                console.error(error);
                ifttt({
                    event: "notification",
                    data: "Error activating Night Mode"
                });
            });
        }

        // Reschedule in half a day
        setTimeout(schedule_night_mode, time.one_day * 0.5);
    });
}

// Reset Lights to day mode at 9:00 am every day
let day_mode_time = time.now().hours(9).minutes(0).seconds(0);
if (time.now().isBefore(day_mode_time)) {
    schedule_day_mode();
} else {
    setTimeout(schedule_day_mode, time.one_day * 0.5);
}

function schedule_day_mode() {
    time.trigger_at_time(day_mode_time, function() {
        hue.set_all_lights(function(light) {
            return hue.state.bright()[hue.color_of(light)];
        }).catch(function(error) {
            console.error(error);
            ifttt({
                event: "notification",
                data: "Error activating Day Mode"
            });
        });

        // Reschedule in half a day
        setTimeout(schedule_day_mode, time.one_day * 0.5);
    });
}

module.exports = {
    post: {
        "stay-on": function(req, res) {
            off_action_override = true;
            res.send(utils.ok());
        },
        "dark-mode": function(req, res) {
            return hue.set_all_lights(function(light) {
                if (light.state.on) {
                    return hue.state.night_fast()[hue.color_of(light)];
                }
            }).then(function() {
                res.send(utils.ok());
            }).catch(function(error) {
                console.error(error);
                res.send(utils.error());
            });
        },
        "movie-mode": function(req, res) {
            hue.set_all_lights(function(light) {
                if (light.name.toLowerCase().includes("living room") ||
                    light.name.toLowerCase().includes("dining room") ||
                    light.name.toLowerCase().includes("porch")
                ) {
                    return hue.state.off();
                }
            }).then(function() {
                res.send(utils.ok());
            }).catch(function(error) {
                console.error(error);
                res.send(utils.error());
            });
        },
        "off": {
            "all": function(req, res) {
                return hue.set_all_lights(function() {
                    return hue.state.off();
                }).then(function() {
                    return tplink.set_devices("bathroom", false);
                }).then(function() {
                    res.send(utils.ok());
                }).catch(function(error) {
                    console.error(error);
                    res.send(utils.error());
                });
            },
            "public-area": function(req, res) {
                hue.set_all_lights(function(light) {
                    if (light.name.toLowerCase().includes("living room") ||
                        light.name.toLowerCase().includes("dining room") ||
                        light.name.toLowerCase().includes("porch") ||
                        light.name.toLowerCase().includes("office")
                    ) {
                        return hue.state.off();
                    }
                }).then(function() {
                    res.send(utils.ok());
                }).catch(function(error) {
                    console.error(error);
                    res.send(utils.error());
                });
            },
            "bedroom-area": function(req, res) {
                hue.set_all_lights(function(light) {
                    if (light.name.toLowerCase().includes("bedroom") ||
                        light.name.toLowerCase().includes("hallway")
                    ) {
                        return hue.state.off();
                    }
                }).then(function() {
                    res.send(utils.ok());
                }).catch(function(error) {
                    console.error(error);
                    res.send(utils.error());
                });
            }
        },
        "on": {
            "all": function(req, res) {
                hue.set_all_lights(function(light) {
                    return hue.state.bright()[hue.color_of(light)].on();
                }).then(function() {
                    clearTimeout(deactivate_porch_lights_timeout);
                    res.send(utils.ok());
                }).catch(function(error) {
                    console.error(error);
                    res.send(utils.error());
                });
            },
            "public-area": function(req, res) {
                hue.set_all_lights(function(light) {
                    if (light.name.toLowerCase().includes("living room") ||
                        light.name.toLowerCase().includes("dining room") ||
                        light.name.toLowerCase().includes("porch") ||
                        light.name.toLowerCase().includes("office")
                    ) {
                        return hue.state.on();
                    }
                }).then(function() {
                    res.send(utils.ok());
                }).catch(function(error) {
                    console.error(error);
                    res.send(utils.error());
                });
            },
            "bedroom-area": function(req, res) {
                hue.set_all_lights(function(light) {
                    if (light.name.toLowerCase().includes("bedroom") ||
                        light.name.toLowerCase().includes("hallway")
                    ) {
                        return hue.state.on();
                    }
                }).then(function() {
                    res.send(utils.ok());
                }).catch(function(error) {
                    console.error(error);
                    res.send(utils.error());
                });
            }
        }
    }
};