diff --git a/accessories/MiLight.js b/accessories/MiLight.js new file mode 100644 index 0000000..409fcb5 --- /dev/null +++ b/accessories/MiLight.js @@ -0,0 +1,181 @@ +var types = require("HAP-NodeJS/accessories/types.js"); +var Milight = require('node-milight-promise').MilightController; +var commands = require('node-milight-promise').commands; + +function MiLight(log, config) { + this.log = log; + this.ip_address = config["ip_address"]; + this.port = config["port"]; + this.name = config["name"]; + this.zone = config["zone"]; + this.type = config["type"]; + this.delay = config["delay"]; + this.repeat = config["repeat"]; +} + +var light = new Milight({ + ip: this.ip_address, + port: this.port, + delayBetweenCommands: this.delay, + commandRepeat: this.repeat +}); + +MiLight.prototype = { + + setPowerState: function(powerOn) { + + var binaryState = powerOn ? "on" : "off"; + var that = this; + + if (binaryState === "on") { + this.log("Setting power state of zone " + this.zone + " to " + powerOn); + light.sendCommands(commands[this.type].on(this.zone)); + } else { + this.log("Setting power state of zone " + this.zone + " to " + powerOn); + light.sendCommands(commands[this.type].off(this.zone)); + } + + }, + + setBrightnessLevel: function(value) { + + var that = this; + + this.log("Setting brightness level of zone " + this.zone + " to " + value); + + light.sendCommands(commands[this.type].brightness(value)); + }, + + setHue: function(value) { + + var that = this; + + this.log("Setting hue of zone " + this.zone + " to " + value); + + if (value == "0") { + light.sendCommands(commands.rgbw.whiteMode(this.zone)); + } else { + light.sendCommands(commands.rgbw.hue(commands.rgbw.hsvToMilightColor(Array(value, 0, 0)))); + } + }, + + + getServices: function() { + var that = this; + var services = [{ + sType: types.ACCESSORY_INFORMATION_STYPE, + characteristics: [{ + cType: types.NAME_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: this.name, + supportEvents: false, + supportBonjour: false, + manfDescription: "Name of the accessory", + designedMaxLength: 255 + }, { + cType: types.MANUFACTURER_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: "MiLight", + supportEvents: false, + supportBonjour: false, + manfDescription: "Manufacturer", + designedMaxLength: 255 + }, { + cType: types.MODEL_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: this.type, + supportEvents: false, + supportBonjour: false, + manfDescription: "Model", + designedMaxLength: 255 + }, { + cType: types.SERIAL_NUMBER_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: "MILIGHT1234", + supportEvents: false, + supportBonjour: false, + manfDescription: "SN", + designedMaxLength: 255 + }, { + cType: types.IDENTIFY_CTYPE, + onUpdate: null, + perms: ["pw"], + format: "bool", + initialValue: false, + supportEvents: false, + supportBonjour: false, + manfDescription: "Identify Accessory", + designedMaxLength: 1 + }] + }, { + sType: types.LIGHTBULB_STYPE, + characteristics: [{ + cType: types.NAME_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: this.name, + supportEvents: false, + supportBonjour: false, + manfDescription: "Name of service", + designedMaxLength: 255 + }, { + cType: types.POWER_STATE_CTYPE, + onUpdate: function(value) { + that.setPowerState(value); + }, + perms: ["pw", "pr", "ev"], + format: "bool", + initialValue: false, + supportEvents: false, + supportBonjour: false, + manfDescription: "Turn on the light", + designedMaxLength: 1 + }, { + cType: types.BRIGHTNESS_CTYPE, + onUpdate: function(value) { + that.setBrightnessLevel(value); + }, + perms: ["pw", "pr", "ev"], + format: "bool", + initialValue: 100, + supportEvents: false, + supportBonjour: false, + manfDescription: "Adjust brightness of light", + designedMinValue: 0, + designedMaxValue: 100, + designedMinStep: 1, + unit: "%" + }] + }]; + if (that.type == "rgbw" || that.type == "rgb") { + services[1].characteristics.push({ + cType: types.HUE_CTYPE, + onUpdate: function(value) { + that.setHue(value); + }, + perms: ["pw", "pr", "ev"], + format: "int", + initialValue: 0, + supportEvents: false, + supportBonjour: false, + manfDescription: "Adjust Hue of Light", + designedMinValue: 0, + designedMaxValue: 360, + designedMinStep: 1, + unit: "arcdegrees" + }); + } + return services; + } +}; + +module.exports.accessory = MiLight; diff --git a/config-sample.json b/config-sample.json index 3cfe0d7..dc8b7de 100644 --- a/config-sample.json +++ b/config-sample.json @@ -120,6 +120,16 @@ "host": "192.168.1.200", // IP address of the SER2SOCK service "port" : 4999, // Port the SER2SOCK process is running on "pin": "1234" // PIN used for arming / disarming + }, + { | + "accessory": "MiLight", | + "name": "Lamp", | + "ip_address": "255.255.255.255", // IP Address of the WiFi Bridge, or 255.255.255.255 to broadcast to all | + "port": 8899, // Default port 8899 (50000 for v1 or v2 bridge) | + "zone": 1, // Zone to address commands to (not used for rgb only bulbs) | + "type": "rgbw", // Bulb type (rgbw, rgb, white) | + "delay": 35, // Delay between commands sent to the WiFi bridge (default 35) | + "repeat": 3 // Number of times each command is repeated for reliability (default 3) | } ] } diff --git a/package.json b/package.json index 9f7efaa..c29afef 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "sonos": "0.8.x", "wemo": "0.2.x", "wink-js": "0.0.5", - "elkington": "kevinohara80/elkington" + "elkington": "kevinohara80/elkington", + "node-milight-promise": "0.0.2" } }