Created
May 28, 2021 09:17
-
-
Save bafonins/c419f532ce43b1394c251c14d546dc0a to your computer and use it in GitHub Desktop.
light-control-example.js
This file contains hidden or 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
| // uplink-payload.js | |
| const _ = require("lodash"); | |
| class UplinkPayload { | |
| constructor(payload) { | |
| const jsonPayload = JSON.parse(payload.toString()); | |
| this._payload = jsonPayload; | |
| } | |
| getDecodedPayload() { | |
| return _.get(this._payload, "uplink_message.decoded_payload") || {}; | |
| } | |
| } | |
| module.exports = UplinkPayload; | |
| // light.js | |
| const v3 = require("node-hue-api").v3; | |
| const LightState = v3.lightStates.LightState; | |
| const COLORS = [ | |
| [0.214, 0.709], // green | |
| [0.139, 0.081], // blue | |
| [0.6758, 0.2953], // red | |
| ]; | |
| const MIN_BRIGHTNESS = 1; | |
| const MAX_BRIGHTNESS = 100; | |
| class Light { | |
| constructor(id) { | |
| this._id = id; | |
| this._currentState = -1; | |
| } | |
| _computeBrightness(lightIntensity) { | |
| if (!lightIntensity) { | |
| return MIN_BRIGHTNESS; | |
| } | |
| return Math.max( | |
| MIN_BRIGHTNESS, | |
| Math.min(MAX_BRIGHTNESS, lightIntensity / 10) | |
| ); | |
| } | |
| _computeColor() { | |
| this._currentState = (this._currentState + 1) % COLORS.length; | |
| return COLORS[this._currentState]; | |
| } | |
| getID() { | |
| return this._id; | |
| } | |
| getNextState(lightIntensity) { | |
| const brightness = this._computeBrightness(lightIntensity); | |
| const color = this._computeColor(); | |
| return new LightState().on().xy(color[0], color[1]).brightness(brightness); | |
| } | |
| } | |
| module.exports = Light; | |
| // mqtt.js | |
| const mqtt = require("mqtt"); | |
| const UplinkPayload = require("./models/uplink-payload"); | |
| class MQTT { | |
| constructor(host, port, username, password) { | |
| if (!host) { | |
| throw new Error("MQTT host is required, received:", host); | |
| } | |
| if (!port) { | |
| throw new Error("MQTT port is required, received:", port); | |
| } | |
| if (!username) { | |
| throw new Error("MQTT username is required, received:", username); | |
| } | |
| if (!password) { | |
| throw new Error("MQTT password is required, received:", password); | |
| } | |
| this._connection = mqtt.connect(undefined, { | |
| host: host, | |
| port: port, | |
| protocol: "mqtt", | |
| username: username, | |
| password: password, | |
| }); | |
| this._connection.on("connect", () => { | |
| console.log("Connected to", host + ":" + port); | |
| }); | |
| } | |
| subscribe(topic = "#") { | |
| this._connection.subscribe(topic); | |
| } | |
| close() { | |
| this._connection.close(); | |
| console.log("Closed connection to", host + ":" + port); | |
| } | |
| onUplink(cb) { | |
| this._connection.on("message", (topic, payload) => { | |
| cb(topic, new UplinkPayload(payload)); | |
| }); | |
| } | |
| onError(cb) { | |
| this._connection.on("error", (error) => { | |
| cb(error); | |
| }); | |
| } | |
| } | |
| module.exports = MQTT; | |
| // index.js | |
| const v3 = require("node-hue-api").v3; | |
| const MQTT = require("./mqtt"); | |
| const Light = require("./models/light"); | |
| const { | |
| BRIDGE_IP, | |
| HUE_USERNAME, | |
| LIGHT_ID, | |
| TTN_MQTT_ADDRESS, | |
| TTN_MQTT_PORT, | |
| TTN_MQTT_USERNAME, | |
| TTN_MQTT_PW, | |
| } = process.env; | |
| let mqttClient; | |
| v3.api | |
| .createLocal(BRIDGE_IP) | |
| .connect(HUE_USERNAME) | |
| .then((api) => { | |
| const lightStrip = new Light(LIGHT_ID); | |
| mqttClient = new MQTT( | |
| TTN_MQTT_ADDRESS, | |
| TTN_MQTT_PORT, | |
| TTN_MQTT_USERNAME, | |
| TTN_MQTT_PW | |
| ); | |
| mqttClient.subscribe(); | |
| mqttClient.onUplink((_, uplink) => { | |
| const { light, event } = uplink.getDecodedPayload(); | |
| if (event === "button") { | |
| return api.lights.setLightState( | |
| lightStrip.getID(), | |
| lightStrip.getNextState(light) | |
| ); | |
| } | |
| }); | |
| mqttClient.onError((error) => { | |
| console.log("Something went wrong with MQTT:", error); | |
| }); | |
| }) | |
| .catch((error) => { | |
| console.log("Something went wrong with HUE api:", error); | |
| if (mqttClient) { | |
| mqttClient.close(); | |
| } | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment