Skip to content

Instantly share code, notes, and snippets.

@bafonins
Created May 28, 2021 09:17
Show Gist options
  • Select an option

  • Save bafonins/c419f532ce43b1394c251c14d546dc0a to your computer and use it in GitHub Desktop.

Select an option

Save bafonins/c419f532ce43b1394c251c14d546dc0a to your computer and use it in GitHub Desktop.
light-control-example.js
// 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