├── images ├── PlugBase.jpg ├── QingPinboard.jpg ├── PlugBaseWithUSB.jpg ├── MiPlugBaseEnhanced.jpg ├── QingPinboardWithUSB.jpg └── IntelligencePinboard.jpg ├── Devices ├── Base.js ├── MiQingPinboard.js ├── MiQingPinboardWithUSB.js ├── MiPlugBaseWithUSB.js ├── MiPlugBase.js ├── MiIntelligencePinboard.js └── MiPlugBaseEnhanced.js ├── package.json ├── index.js └── README.md /images/PlugBase.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/HEAD/images/PlugBase.jpg -------------------------------------------------------------------------------- /images/QingPinboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/HEAD/images/QingPinboard.jpg -------------------------------------------------------------------------------- /images/PlugBaseWithUSB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/HEAD/images/PlugBaseWithUSB.jpg -------------------------------------------------------------------------------- /images/MiPlugBaseEnhanced.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/HEAD/images/MiPlugBaseEnhanced.jpg -------------------------------------------------------------------------------- /images/QingPinboardWithUSB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/HEAD/images/QingPinboardWithUSB.jpg -------------------------------------------------------------------------------- /images/IntelligencePinboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/HEAD/images/IntelligencePinboard.jpg -------------------------------------------------------------------------------- /Devices/Base.js: -------------------------------------------------------------------------------- 1 | // Base 2 | Base = function() { 3 | this.platform = null; 4 | } 5 | 6 | Base.prototype.init = function(platform, config) { 7 | this.platform = platform; 8 | this.config = config; 9 | } 10 | 11 | Base.prototype.obj2array = function(obj) { 12 | var array = []; 13 | for(var item in obj) { 14 | array.push(obj[item]); 15 | } 16 | return array; 17 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homebridge-mi-outlet", 3 | "version": "0.3.0", 4 | "description": "XiaoMi outlet plugins for HomeBridge(https://github.com/nfarina/homebridge).", 5 | "keywords": [ 6 | "homebridge-plugin", 7 | "xiaomi", 8 | "mi", 9 | "outlet", 10 | "plug", 11 | "socket" 12 | ], 13 | "author": "YinHang", 14 | "homepage": "https://github.com/YinHangCode/homebridge-mi-outlet", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/YinHangCode/homebridge-mi-outlet" 18 | }, 19 | "bugs": { 20 | "url": "https://github.com/YinHangCode/homebridge-mi-outlet/issues" 21 | }, 22 | "engines": { 23 | "node": ">=7.0.0", 24 | "homebridge": ">=0.4.1" 25 | }, 26 | "dependencies": { 27 | "miio": "0.14.1" 28 | } 29 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./Devices/MiPlugBase'); 2 | require('./Devices/MiPlugBaseWithUSB'); 3 | require('./Devices/MiIntelligencePinboard'); 4 | require('./Devices/MiQingPinboard'); 5 | require('./Devices/MiQingPinboardWithUSB'); 6 | require('./Devices/MiPlugBaseEnhanced'); 7 | 8 | var fs = require('fs'); 9 | var packageFile = require("./package.json"); 10 | var PlatformAccessory, Accessory, Service, Characteristic, UUIDGen; 11 | 12 | module.exports = function(homebridge) { 13 | if(!isConfig(homebridge.user.configPath(), "platforms", "MiOutletPlatform")) { 14 | return; 15 | } 16 | 17 | PlatformAccessory = homebridge.platformAccessory; 18 | Accessory = homebridge.hap.Accessory; 19 | Service = homebridge.hap.Service; 20 | Characteristic = homebridge.hap.Characteristic; 21 | UUIDGen = homebridge.hap.uuid; 22 | 23 | homebridge.registerPlatform('homebridge-mi-outlet', 'MiOutletPlatform', MiOutletPlatform, true); 24 | } 25 | 26 | function isConfig(configFile, type, name) { 27 | var config = JSON.parse(fs.readFileSync(configFile)); 28 | if("accessories" === type) { 29 | var accessories = config.accessories; 30 | for(var i in accessories) { 31 | if(accessories[i]['accessory'] === name) { 32 | return true; 33 | } 34 | } 35 | } else if("platforms" === type) { 36 | var platforms = config.platforms; 37 | for(var i in platforms) { 38 | if(platforms[i]['platform'] === name) { 39 | return true; 40 | } 41 | } 42 | } else { 43 | } 44 | 45 | return false; 46 | } 47 | 48 | function MiOutletPlatform(log, config, api) { 49 | if(null == config) { 50 | return; 51 | } 52 | 53 | this.Accessory = Accessory; 54 | this.PlatformAccessory = PlatformAccessory; 55 | this.Service = Service; 56 | this.Characteristic = Characteristic; 57 | this.UUIDGen = UUIDGen; 58 | 59 | this.log = log; 60 | this.config = config; 61 | 62 | if (api) { 63 | this.api = api; 64 | } 65 | 66 | this.log.info("[MiOutletPlatform][INFO]**************************************************************"); 67 | this.log.info("[MiOutletPlatform][INFO] MiOutletPlatform v%s By YinHang", packageFile.version); 68 | this.log.info("[MiOutletPlatform][INFO] GitHub: https://github.com/YinHangCode/homebridge-mi-outlet "); 69 | this.log.info("[MiOutletPlatform][INFO] QQ Group: 107927710 "); 70 | this.log.info("[MiOutletPlatform][INFO]**************************************************************"); 71 | this.log.info("[MiOutletPlatform][INFO]start success..."); 72 | } 73 | 74 | MiOutletPlatform.prototype = { 75 | accessories: function(callback) { 76 | var myAccessories = []; 77 | 78 | var deviceCfgs = this.config['deviceCfgs']; 79 | if(deviceCfgs instanceof Array) { 80 | for (var i = 0; i < deviceCfgs.length; i++) { 81 | var deviceCfg = deviceCfgs[i]; 82 | if(null == deviceCfg['type'] || "" == deviceCfg['type'] || null == deviceCfg['token'] || "" == deviceCfg['token'] || null == deviceCfg['ip'] || "" == deviceCfg['ip']) { 83 | continue; 84 | } 85 | 86 | if (deviceCfg['type'] == "MiPlugBase") { 87 | new MiPlugBase(this, deviceCfg).forEach(function(accessory, index, arr){ 88 | myAccessories.push(accessory); 89 | }); 90 | } else if (deviceCfg['type'] == "MiPlugBaseWithUSB") { 91 | new MiPlugBaseWithUSB(this, deviceCfg).forEach(function(accessory, index, arr){ 92 | myAccessories.push(accessory); 93 | }); 94 | } else if (deviceCfg['type'] == "MiIntelligencePinboard") { 95 | new MiIntelligencePinboard(this, deviceCfg).forEach(function(accessory, index, arr){ 96 | myAccessories.push(accessory); 97 | }); 98 | } else if (deviceCfg['type'] == "MiQingPinboard") { 99 | new MiQingPinboard(this, deviceCfg).forEach(function(accessory, index, arr){ 100 | myAccessories.push(accessory); 101 | }); 102 | } else if (deviceCfg['type'] == "MiQingPinboardWithUSB") { 103 | new MiQingPinboardWithUSB(this, deviceCfg).forEach(function(accessory, index, arr){ 104 | myAccessories.push(accessory); 105 | }); 106 | } else if (deviceCfg['type'] == "MiPlugBaseEnhanced") { 107 | new MiPlugBaseEnhanced(this, deviceCfg).forEach(function(accessory, index, arr){ 108 | myAccessories.push(accessory); 109 | }); 110 | } else { 111 | } 112 | } 113 | this.log.info("[MiOutletPlatform][INFO]device size: " + deviceCfgs.length + ", accessories size: " + myAccessories.length); 114 | } 115 | 116 | callback(myAccessories); 117 | } 118 | } -------------------------------------------------------------------------------- /Devices/MiQingPinboard.js: -------------------------------------------------------------------------------- 1 | require('./Base'); 2 | 3 | const inherits = require('util').inherits; 4 | const miio = require('miio'); 5 | 6 | var Accessory, PlatformAccessory, Service, Characteristic, UUIDGen; 7 | 8 | MiQingPinboard = function(platform, config) { 9 | this.init(platform, config); 10 | 11 | Accessory = platform.Accessory; 12 | PlatformAccessory = platform.PlatformAccessory; 13 | Service = platform.Service; 14 | Characteristic = platform.Characteristic; 15 | UUIDGen = platform.UUIDGen; 16 | 17 | this.device = new miio.Device({ 18 | address: this.config['ip'], 19 | token: this.config['token'] 20 | }); 21 | 22 | this.accessories = {}; 23 | if(!this.config['outletDisable'] && this.config['outletName'] && this.config['outletName'] != "") { 24 | this.accessories['outletAccessory'] = new MiQingPinboardOutlet(this); 25 | } 26 | if(!this.config['temperatureDisable'] && this.config['temperatureName'] && this.config['temperatureName'] != "") { 27 | this.accessories['temperatureAccessory'] = new MiQingPinboardTemperature(this); 28 | } 29 | var accessoriesArr = this.obj2array(this.accessories); 30 | 31 | this.platform.log.debug("[MiOutletPlatform][DEBUG]Initializing " + this.config["type"] + " device: " + this.config["ip"] + ", accessories size: " + accessoriesArr.length); 32 | 33 | return accessoriesArr; 34 | } 35 | inherits(MiQingPinboard, Base); 36 | 37 | MiQingPinboardOutlet = function(dThis) { 38 | this.device = dThis.device; 39 | this.name = dThis.config['outletName']; 40 | this.platform = dThis.platform; 41 | } 42 | 43 | MiQingPinboardOutlet.prototype.getServices = function() { 44 | var services = []; 45 | 46 | var infoService = new Service.AccessoryInformation(); 47 | infoService 48 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 49 | .setCharacteristic(Characteristic.Model, "Qing Pinboard") 50 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 51 | services.push(infoService); 52 | 53 | var outletService = new Service.Outlet(this.name); 54 | outletService 55 | .getCharacteristic(Characteristic.On) 56 | .on('get', this.getPower.bind(this)) 57 | .on('set', this.setPower.bind(this)); 58 | outletService 59 | .getCharacteristic(Characteristic.OutletInUse) 60 | .on('get', this.getOutletInUse.bind(this)); 61 | services.push(outletService); 62 | 63 | return services; 64 | } 65 | 66 | MiQingPinboardOutlet.prototype.getOutletInUse = function(callback) { 67 | var that = this; 68 | this.device.call("get_prop", ["power_consume_rate"]).then(result => { 69 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiQingPinboard - Outlet - getOutletInUse: " + result); 70 | callback(null, result[0] && result[0] > 0 ? true : false); 71 | }).catch(function(err) { 72 | that.platform.log.error("[MiOutletPlatform][ERROR]MiQingPinboard - Outlet - getOutletInUse Error: " + err); 73 | callback(err); 74 | }); 75 | } 76 | 77 | MiQingPinboardOutlet.prototype.getPower = function(callback) { 78 | var that = this; 79 | this.device.call("get_prop", ["power"]).then(result => { 80 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiQingPinboard - Outlet - getPower: " + result); 81 | callback(null, result[0] === 'on' ? 1 : 0); 82 | }).catch(function(err) { 83 | that.platform.log.error("[MiOutletPlatform][ERROR]MiQingPinboard - Outlet - getPower Error: " + err); 84 | callback(err); 85 | }); 86 | } 87 | 88 | MiQingPinboardOutlet.prototype.setPower = function(value, callback) { 89 | var that = this; 90 | that.device.call("set_power", [value ? "on" : "off"]).then(result => { 91 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiQingPinboard - Outlet - setPower Result: " + result); 92 | if(result[0] === "ok") { 93 | callback(null); 94 | } else { 95 | callback(new Error(result[0])); 96 | } 97 | }).catch(function(err) { 98 | that.platform.log.error("[MiOutletPlatform][ERROR]MiQingPinboard - Outlet - setPower Error: " + err); 99 | callback(err); 100 | }); 101 | } 102 | 103 | MiQingPinboardTemperature = function(dThis) { 104 | this.device = dThis.device; 105 | this.name = dThis.config['temperatureName']; 106 | this.platform = dThis.platform; 107 | } 108 | 109 | MiQingPinboardTemperature.prototype.getServices = function() { 110 | var services = []; 111 | 112 | var infoService = new Service.AccessoryInformation(); 113 | infoService 114 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 115 | .setCharacteristic(Characteristic.Model, "Qing Pinboard") 116 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 117 | services.push(infoService); 118 | 119 | var temperatureService = new Service.TemperatureSensor(this.name); 120 | temperatureService 121 | .getCharacteristic(Characteristic.CurrentTemperature) 122 | .on('get', this.getTemperature.bind(this)) 123 | services.push(temperatureService); 124 | 125 | return services; 126 | } 127 | 128 | MiQingPinboardTemperature.prototype.getTemperature = function(callback) { 129 | var that = this; 130 | this.device.call("get_prop", ["temperature"]).then(result => { 131 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiQingPinboard - Temperature - getTemperature: " + result); 132 | callback(null, result[0]); 133 | }).catch(function(err) { 134 | that.platform.log.error("[MiOutletPlatform][ERROR]MiQingPinboard - Temperature - getTemperature Error: " + err); 135 | callback(err); 136 | }); 137 | } 138 | -------------------------------------------------------------------------------- /Devices/MiQingPinboardWithUSB.js: -------------------------------------------------------------------------------- 1 | require('./Base'); 2 | 3 | const inherits = require('util').inherits; 4 | const miio = require('miio'); 5 | 6 | var Accessory, PlatformAccessory, Service, Characteristic, UUIDGen; 7 | 8 | MiQingPinboardWithUSB = function(platform, config) { 9 | this.init(platform, config); 10 | 11 | Accessory = platform.Accessory; 12 | PlatformAccessory = platform.PlatformAccessory; 13 | Service = platform.Service; 14 | Characteristic = platform.Characteristic; 15 | UUIDGen = platform.UUIDGen; 16 | 17 | this.device = new miio.Device({ 18 | address: this.config['ip'], 19 | token: this.config['token'] 20 | }); 21 | 22 | this.accessories = {}; 23 | if(!this.config['outletDisable'] && this.config['outletName'] && this.config['outletName'] != "") { 24 | this.accessories['outletAccessory'] = new MiQingPinboardWithUSBOutlet(this); 25 | } 26 | if(!this.config['temperatureDisable'] && this.config['temperatureName'] && this.config['temperatureName'] != "") { 27 | this.accessories['temperatureAccessory'] = new MiQingPinboardWithUSBTemperature(this); 28 | } 29 | var accessoriesArr = this.obj2array(this.accessories); 30 | 31 | this.platform.log.debug("[MiOutletPlatform][DEBUG]Initializing " + this.config["type"] + " device: " + this.config["ip"] + ", accessories size: " + accessoriesArr.length); 32 | 33 | return accessoriesArr; 34 | } 35 | inherits(MiQingPinboardWithUSB, Base); 36 | 37 | MiQingPinboardWithUSBOutlet = function(dThis) { 38 | this.device = dThis.device; 39 | this.name = dThis.config['outletName']; 40 | this.platform = dThis.platform; 41 | } 42 | 43 | MiQingPinboardWithUSBOutlet.prototype.getServices = function() { 44 | var services = []; 45 | 46 | var infoService = new Service.AccessoryInformation(); 47 | infoService 48 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 49 | .setCharacteristic(Characteristic.Model, "Qing Pinboard With USB") 50 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 51 | services.push(infoService); 52 | 53 | var outletService = new Service.Outlet(this.name); 54 | outletService 55 | .getCharacteristic(Characteristic.On) 56 | .on('get', this.getPower.bind(this)) 57 | .on('set', this.setPower.bind(this)); 58 | outletService 59 | .getCharacteristic(Characteristic.OutletInUse) 60 | .on('get', this.getOutletInUse.bind(this)); 61 | services.push(outletService); 62 | 63 | return services; 64 | } 65 | 66 | MiQingPinboardWithUSBOutlet.prototype.getOutletInUse = function(callback) { 67 | var that = this; 68 | this.device.call("get_prop", ["power_consume_rate"]).then(result => { 69 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiQingPinboardWithUSB - Outlet - getOutletInUse: " + result); 70 | callback(null, result[0] && result[0] > 0 ? true : false); 71 | }).catch(function(err) { 72 | that.platform.log.error("[MiOutletPlatform][ERROR]MiQingPinboardWithUSB - Outlet - getOutletInUse Error: " + err); 73 | callback(err); 74 | }); 75 | } 76 | 77 | MiQingPinboardWithUSBOutlet.prototype.getPower = function(callback) { 78 | var that = this; 79 | this.device.call("get_prop", ["power"]).then(result => { 80 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiQingPinboardWithUSB - Outlet - getPower: " + result); 81 | callback(null, result[0] === 'on' ? 1 : 0); 82 | }).catch(function(err) { 83 | that.platform.log.error("[MiOutletPlatform][ERROR]MiQingPinboardWithUSB - Outlet - getPower Error: " + err); 84 | callback(err); 85 | }); 86 | } 87 | 88 | MiQingPinboardWithUSBOutlet.prototype.setPower = function(value, callback) { 89 | var that = this; 90 | that.device.call("set_power", [value ? "on" : "off"]).then(result => { 91 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiQingPinboardWithUSB - Outlet - setPower Result: " + result); 92 | if(result[0] === "ok") { 93 | callback(null); 94 | } else { 95 | callback(new Error(result[0])); 96 | } 97 | }).catch(function(err) { 98 | that.platform.log.error("[MiOutletPlatform][ERROR]MiQingPinboardWithUSB - Outlet - setPower Error: " + err); 99 | callback(err); 100 | }); 101 | } 102 | 103 | MiQingPinboardWithUSBTemperature = function(dThis) { 104 | this.device = dThis.device; 105 | this.name = dThis.config['temperatureName']; 106 | this.platform = dThis.platform; 107 | } 108 | 109 | MiQingPinboardWithUSBTemperature.prototype.getServices = function() { 110 | var services = []; 111 | 112 | var infoService = new Service.AccessoryInformation(); 113 | infoService 114 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 115 | .setCharacteristic(Characteristic.Model, "Qing Pinboard With USB") 116 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 117 | services.push(infoService); 118 | 119 | var temperatureService = new Service.TemperatureSensor(this.name); 120 | temperatureService 121 | .getCharacteristic(Characteristic.CurrentTemperature) 122 | .on('get', this.getTemperature.bind(this)) 123 | services.push(temperatureService); 124 | 125 | return services; 126 | } 127 | 128 | MiQingPinboardWithUSBTemperature.prototype.getTemperature = function(callback) { 129 | var that = this; 130 | this.device.call("get_prop", ["temperature"]).then(result => { 131 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiQingPinboardWithUSB - Temperature - getTemperature: " + result); 132 | callback(null, result[0]); 133 | }).catch(function(err) { 134 | that.platform.log.error("[MiOutletPlatform][ERROR]MiQingPinboardWithUSB - Temperature - getTemperature Error: " + err); 135 | callback(err); 136 | }); 137 | } 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # homebridge-mi-outlet 2 | [![npm version](https://badge.fury.io/js/homebridge-mi-outlet.svg)](https://badge.fury.io/js/homebridge-mi-outlet) 3 | 4 | XiaoMi outlet plugins for HomeBridge. 5 | 6 | Thanks for [nfarina](https://github.com/nfarina)(the author of [homebridge](https://github.com/nfarina/homebridge)), [OpenMiHome](https://github.com/OpenMiHome/mihome-binary-protocol), [aholstenson](https://github.com/aholstenson)(the author of [miio](https://github.com/aholstenson/miio)), all other developer and testers. 7 | 8 | **Note: I have only a part of these devices, so some devices don't have tested. If you find bugs, please submit them to [issues](https://github.com/YinHangCode/homebridge-mi-outlet/issues) or [QQ Group: 107927710](//shang.qq.com/wpa/qunwpa?idkey=8b9566598f40dd68412065ada24184ef72c6bddaa11525ca26c4e1536a8f2a3d).** 9 | 10 | ![](https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/master/images/PlugBase.jpg) 11 | ![](https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/master/images/PlugBaseWithUSB.jpg) 12 | ![](https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/master/images/IntelligencePinboard.jpg) 13 | ![](https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/master/images/QingPinboard.jpg) 14 | ![](https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/master/images/QingPinboardWithUSB.jpg) 15 | ![](https://raw.githubusercontent.com/YinHangCode/homebridge-mi-outlet/master/images/MiPlugBaseEnhanced.jpg) 16 | 17 | ## Supported Devices 18 | 1. MiPlugBase(米家智能插座基础版) 19 | 2. MiPlugBaseWithUSB(小米智能插座_USB版) 20 | 3. MiIntelligencePinboard(米家智能插线板) 21 | 4. MiQingPinboard(青米智能插线板_五孔位版) 22 | 5. MiQingPinboardWithUSB(青米智能插线板_USB版) 23 | 6. MiPlugBaseEnhanced(米家智能插座增强版) 24 | 25 | ## Installation 26 | 1. Install HomeBridge, please follow it's [README](https://github.com/nfarina/homebridge/blob/master/README.md). 27 | If you are using Raspberry Pi, please read [Running-HomeBridge-on-a-Raspberry-Pi](https://github.com/nfarina/homebridge/wiki/Running-HomeBridge-on-a-Raspberry-Pi). 28 | 2. Make sure you can see HomeBridge in your iOS devices, if not, please go back to step 1. 29 | 3. Install packages. 30 | ``` 31 | npm install -g homebridge-mi-outlet 32 | ``` 33 | ## Configuration 34 | ``` 35 | "platforms": [{ 36 | "platform": "MiOutletPlatform", 37 | "deviceCfgs": [{ 38 | "type": "MiPlugBase", 39 | "ip": "192.168.88.xx", 40 | "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 41 | "outletName": "living room outlet", 42 | "outletDisable": false, 43 | "temperatureName": "living room outlet temperature", 44 | "temperatureDisable": false, 45 | "switchLEDName": "living room led light switch", 46 | "switchLEDDisable": true 47 | }, { 48 | "type": "MiPlugBaseWithUSB", 49 | "ip": "192.168.88.xx", 50 | "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 51 | "outletName": "study room outlet", 52 | "outletDisable": false, 53 | "temperatureName": "study room outlet temperature", 54 | "temperatureDisable": false, 55 | "switchUSBName": "study room outlet usb switch", 56 | "switchUSBDisable": false 57 | }, { 58 | "type": "MiIntelligencePinboard", 59 | "ip": "192.168.88.xx", 60 | "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 61 | "outletName": "master room outlet", 62 | "outletDisable": false, 63 | "temperatureName": "master room outlet temperature", 64 | "temperatureDisable": false, 65 | "switchLEDName": "master room led light switch", 66 | "switchLEDDisable": true 67 | }, { 68 | "type": "MiQingPinboard", 69 | "ip": "192.168.88.xx", 70 | "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 71 | "outletName": "dining room outlet", 72 | "outletDisable": false, 73 | "temperatureName": "dining room outlet temperature", 74 | "temperatureDisable": false 75 | }, { 76 | "type": "MiQingPinboardWithUSB", 77 | "ip": "192.168.88.xx", 78 | "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 79 | "outletName": "kitchen room outlet", 80 | "outletDisable": false, 81 | "temperatureName": "kitchen room outlet temperature", 82 | "temperatureDisable": false 83 | }, { 84 | "type": "MiPlugBaseEnhanced", 85 | "ip": "192.168.88.xx", 86 | "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 87 | "outletName": "living room outlet2", 88 | "outletDisable": false, 89 | "temperatureName": "living room outlet2 temperature", 90 | "temperatureDisable": false, 91 | "switchUSBName": "living room outlet2 usb switch", 92 | "switchUSBDisable": false, 93 | "switchLEDName": "living room outlet2 led light switch", 94 | "switchLEDDisable": true 95 | }] 96 | }] 97 | ``` 98 | ## Get token 99 | ### Get token by miio2.db (Recommend) 100 | setup MiJia(MiHome) app in your android device or android virtual machine. 101 | open MiJia(MiHome) app and login your account. 102 | refresh device list and make sure device display in the device list. 103 | get miio2.db(path: /data/data/com.xiaomi.smarthome/databases/miio2.db) file from your android device or android virtual machine. 104 | open website [[Get MiIo Tokens By DataBase File](http://miio2.yinhh.com/)], upload miio2.db file and submit. 105 | ### Get token by network 106 | Open command prompt or terminal. Run following command: 107 | ``` 108 | miio --discover 109 | ``` 110 | Wait until you get output similar to this: 111 | ``` 112 | Device ID: xxxxxxxx 113 | Model info: Unknown 114 | Address: 192.168.88.xx 115 | Token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx via auto-token 116 | Support: Unknown 117 | ``` 118 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" is token. 119 | If token is "???", then reset device and connect device created Wi-Fi hotspot. 120 | Run following command: 121 | ``` 122 | miio --discover --sync 123 | ``` 124 | Wait until you get output. 125 | For more information about token, please refer to [OpenMiHome](https://github.com/OpenMiHome/mihome-binary-protocol) and [miio](https://github.com/aholstenson/miio). 126 | ## Version Logs 127 | ### 0.3.0 (2018-09-10) 128 | 1. add support for Mi PlugBase Enhanced: outlet, temperature sensor, LED switch, USB switch. 129 | ### 0.2.8 (2018-02-10) 130 | 1. update 'package.json'. 131 | ### 0.2.7 (2017-11-18) 132 | 1. modify class name, reduce the probability of conflicts due to the same class name and other plugins. 133 | ### 0.2.6 (2017-09-11) 134 | 1. optimized code. 135 | ### 0.2.5 (2017-09-05) 136 | 1. optimized code. 137 | ### 0.2.4 (2017-08-31) 138 | 1. add outlet inuse display. 139 | ### 0.2.3 (2017-08-30) 140 | 1. fixed bug that 'log of undefined' error. 141 | 2. config item 'accessories' renamed 'deviceCfgs'. 142 | ### 0.2.2 (2017-08-29) 143 | 1. fixed bug that many of the same type of device conflict with each other. 144 | ### 0.2.1 (2017-08-27) 145 | 1. optimized code. 146 | ### 0.2.0 (2017-08-26) 147 | 1. add support for Intelligence Pinboard: outlet, temperature sensor, LED switch. 148 | 2. add support for Qing Pinboard: outlet, temperature sensor. 149 | 3. add support for Qing Pinboard With USB: outlet, temperature sensor. 150 | 4. fixed bug that homebridge not works when device is not responding. 151 | 5. optimized code. 152 | 6. fixed bug that run homebridge error there is no MiOutletPlatform in config.json file. 153 | ### 0.1.0 (2017-08-25) 154 | 1. add support for PlugBaseWithUSB: outlet, temperature sensor, USB switch. 155 | 2. add PlugBase LED switch. 156 | ### 0.0.1 (2017-08-24) 157 | 1. support for PlugBase: outlet, temperature sensor. 158 | -------------------------------------------------------------------------------- /Devices/MiPlugBaseWithUSB.js: -------------------------------------------------------------------------------- 1 | require('./Base'); 2 | 3 | const inherits = require('util').inherits; 4 | const miio = require('miio'); 5 | 6 | var Accessory, PlatformAccessory, Service, Characteristic, UUIDGen; 7 | 8 | MiPlugBaseWithUSB = function(platform, config) { 9 | this.init(platform, config); 10 | 11 | Accessory = platform.Accessory; 12 | PlatformAccessory = platform.PlatformAccessory; 13 | Service = platform.Service; 14 | Characteristic = platform.Characteristic; 15 | UUIDGen = platform.UUIDGen; 16 | 17 | this.device = new miio.Device({ 18 | address: this.config['ip'], 19 | token: this.config['token'] 20 | }); 21 | 22 | this.accessories = {}; 23 | if(!this.config['outletDisable'] && this.config['outletName'] && this.config['outletName'] != "") { 24 | this.accessories['outletAccessory'] = new MiPlugBaseWithUSBOutlet(this); 25 | } 26 | if(!this.config['temperatureDisable'] && this.config['temperatureName'] && this.config['temperatureName'] != "") { 27 | this.accessories['temperatureAccessory'] = new MiPlugBaseWithUSBTemperature(this); 28 | } 29 | if(!this.config['switchUSBDisable'] && this.config['switchUSBName'] && this.config['switchUSBName'] != "") { 30 | this.accessories['switchUSBAccessory'] = new MiPlugBaseWithUSBSwitchUSB(this); 31 | } 32 | var accessoriesArr = this.obj2array(this.accessories); 33 | 34 | this.platform.log.debug("[MiOutletPlatform][DEBUG]Initializing " + this.config["type"] + " device: " + this.config["ip"] + ", accessories size: " + accessoriesArr.length); 35 | 36 | return accessoriesArr; 37 | } 38 | inherits(MiPlugBaseWithUSB, Base); 39 | 40 | MiPlugBaseWithUSBOutlet = function(dThis) { 41 | this.device = dThis.device; 42 | this.name = dThis.config['outletName']; 43 | this.platform = dThis.platform; 44 | } 45 | 46 | MiPlugBaseWithUSBOutlet.prototype.getServices = function() { 47 | var services = []; 48 | 49 | var infoService = new Service.AccessoryInformation(); 50 | infoService 51 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 52 | .setCharacteristic(Characteristic.Model, "Plug Base With USB") 53 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 54 | services.push(infoService); 55 | 56 | var outletService = new Service.Outlet(this.name); 57 | outletService 58 | .getCharacteristic(Characteristic.On) 59 | .on('get', this.getPower.bind(this)) 60 | .on('set', this.setPower.bind(this)); 61 | outletService 62 | .getCharacteristic(Characteristic.OutletInUse) 63 | .on('get', this.getOutletInUse.bind(this)); 64 | services.push(outletService); 65 | 66 | return services; 67 | } 68 | 69 | MiPlugBaseWithUSBOutlet.prototype.getOutletInUse = function(callback) { 70 | var that = this; 71 | this.device.call("get_prop", ["on"]).then(result => { 72 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseWithUSB - Outlet - getOutletInUse: " + result); 73 | callback(null, result[0]); 74 | }).catch(function(err) { 75 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseWithUSB - Outlet - getOutletInUse Error: " + err); 76 | callback(err); 77 | }); 78 | } 79 | 80 | MiPlugBaseWithUSBOutlet.prototype.getPower = function(callback) { 81 | var that = this; 82 | this.device.call("get_prop", ["on"]).then(result => { 83 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseWithUSB - Outlet - getPower: " + result); 84 | callback(null, result[0]); 85 | }).catch(function(err) { 86 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseWithUSB - Outlet - getPower Error: " + err); 87 | callback(err); 88 | }); 89 | } 90 | 91 | MiPlugBaseWithUSBOutlet.prototype.setPower = function(value, callback) { 92 | var that = this; 93 | that.device.call(value ? "set_on" : "set_off", []).then(result => { 94 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseWithUSB - Outlet - setPower Result: " + result); 95 | callback(null); 96 | }).catch(function(err) { 97 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseWithUSB - Outlet - setPower Error: " + err); 98 | callback(err); 99 | }); 100 | } 101 | 102 | MiPlugBaseWithUSBTemperature = function(dThis) { 103 | this.device = dThis.device; 104 | this.name = dThis.config['temperatureName']; 105 | this.platform = dThis.platform; 106 | } 107 | 108 | MiPlugBaseWithUSBTemperature.prototype.getServices = function() { 109 | var services = []; 110 | 111 | var infoService = new Service.AccessoryInformation(); 112 | infoService 113 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 114 | .setCharacteristic(Characteristic.Model, "Plug Base With USB") 115 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 116 | services.push(infoService); 117 | 118 | var temperatureService = new Service.TemperatureSensor(this.name); 119 | temperatureService 120 | .getCharacteristic(Characteristic.CurrentTemperature) 121 | .on('get', this.getTemperature.bind(this)) 122 | services.push(temperatureService); 123 | 124 | return services; 125 | } 126 | 127 | MiPlugBaseWithUSBTemperature.prototype.getTemperature = function(callback) { 128 | var that = this; 129 | this.device.call("get_prop", ["temperature"]).then(result => { 130 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseWithUSB - Temperature - getTemperature: " + result); 131 | callback(null, result[0]); 132 | }).catch(function(err) { 133 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseWithUSB - Temperature - getTemperature Error: " + err); 134 | callback(err); 135 | }); 136 | } 137 | 138 | MiPlugBaseWithUSBSwitchUSB = function(dThis) { 139 | this.device = dThis.device; 140 | this.name = dThis.config['switchUSBName']; 141 | this.platform = dThis.platform; 142 | } 143 | 144 | MiPlugBaseWithUSBSwitchUSB.prototype.getServices = function() { 145 | var services = []; 146 | 147 | var infoService = new Service.AccessoryInformation(); 148 | infoService 149 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 150 | .setCharacteristic(Characteristic.Model, "Plug Base With USB") 151 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 152 | services.push(infoService); 153 | 154 | var switchService = new Service.Switch(this.name); 155 | switchService 156 | .getCharacteristic(Characteristic.On) 157 | .on('get', this.getUSBPower.bind(this)) 158 | .on('set', this.setUSBPower.bind(this)); 159 | services.push(switchService); 160 | 161 | return services; 162 | } 163 | 164 | MiPlugBaseWithUSBSwitchUSB.prototype.getUSBPower = function(callback) { 165 | var that = this; 166 | this.device.call("get_prop", ["usb_on"]).then(result => { 167 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseWithUSB - SwitchUSB - getUSBPower: " + result); 168 | callback(null, result[0]); 169 | }).catch(function(err) { 170 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseWithUSB - SwitchUSB - getUSBPower Error: " + err); 171 | callback(err); 172 | }); 173 | } 174 | 175 | MiPlugBaseWithUSBSwitchUSB.prototype.setUSBPower = function(value, callback) { 176 | var that = this; 177 | that.device.call(value ? "set_usb_on" : "set_usb_off", []).then(result => { 178 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseWithUSB - SwitchUSB - setUSBPower Result: " + result); 179 | callback(null); 180 | }).catch(function(err) { 181 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseWithUSB - SwitchUSB - setUSBPower Error: " + err); 182 | callback(err); 183 | }); 184 | } -------------------------------------------------------------------------------- /Devices/MiPlugBase.js: -------------------------------------------------------------------------------- 1 | require('./Base'); 2 | 3 | const inherits = require('util').inherits; 4 | const miio = require('miio'); 5 | 6 | var Accessory, PlatformAccessory, Service, Characteristic, UUIDGen; 7 | 8 | MiPlugBase = function(platform, config) { 9 | this.init(platform, config); 10 | 11 | Accessory = platform.Accessory; 12 | PlatformAccessory = platform.PlatformAccessory; 13 | Service = platform.Service; 14 | Characteristic = platform.Characteristic; 15 | UUIDGen = platform.UUIDGen; 16 | 17 | this.device = new miio.Device({ 18 | address: this.config['ip'], 19 | token: this.config['token'] 20 | }); 21 | 22 | this.accessories = {}; 23 | if(!this.config['outletDisable'] && this.config['outletName'] && this.config['outletName'] != "") { 24 | this.accessories['outletAccessory'] = new MiPlugBaseOutlet(this); 25 | } 26 | if(!this.config['temperatureDisable'] && this.config['temperatureName'] && this.config['temperatureName'] != "") { 27 | this.accessories['temperatureAccessory'] = new MiPlugBaseTemperature(this); 28 | } 29 | if(!this.config['switchLEDDisable'] && this.config['switchLEDName'] && this.config['switchLEDName'] != "") { 30 | this.accessories['switchLEDAccessory'] = new MiPlugBaseSwitchLED(this); 31 | } 32 | var accessoriesArr = this.obj2array(this.accessories); 33 | 34 | this.platform.log.debug("[MiOutletPlatform][DEBUG]Initializing " + this.config["type"] + " device: " + this.config["ip"] + ", accessories size: " + accessoriesArr.length); 35 | 36 | return accessoriesArr; 37 | } 38 | inherits(MiPlugBase, Base); 39 | 40 | MiPlugBaseOutlet = function(dThis) { 41 | this.device = dThis.device; 42 | this.name = dThis.config['outletName']; 43 | this.platform = dThis.platform; 44 | } 45 | 46 | MiPlugBaseOutlet.prototype.getServices = function() { 47 | var services = []; 48 | 49 | var infoService = new Service.AccessoryInformation(); 50 | infoService 51 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 52 | .setCharacteristic(Characteristic.Model, "Plug Base") 53 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 54 | services.push(infoService); 55 | 56 | var outletService = new Service.Outlet(this.name); 57 | outletService 58 | .getCharacteristic(Characteristic.On) 59 | .on('get', this.getPower.bind(this)) 60 | .on('set', this.setPower.bind(this)); 61 | outletService 62 | .getCharacteristic(Characteristic.OutletInUse) 63 | .on('get', this.getOutletInUse.bind(this)); 64 | services.push(outletService); 65 | 66 | return services; 67 | } 68 | 69 | MiPlugBaseOutlet.prototype.getOutletInUse = function(callback) { 70 | var that = this; 71 | this.device.call("get_prop", ["power"]).then(result => { 72 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBase - Outlet - getOutletInUse: " + result); 73 | callback(null, result[0] === 'on' ? true : false); 74 | }).catch(function(err) { 75 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBase - Outlet - getOutletInUse Error: " + err); 76 | callback(err); 77 | }); 78 | } 79 | 80 | MiPlugBaseOutlet.prototype.getPower = function(callback) { 81 | var that = this; 82 | this.device.call("get_prop", ["power"]).then(result => { 83 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBase - Outlet - getPower: " + result); 84 | callback(null, result[0] === 'on' ? true : false); 85 | }).catch(function(err) { 86 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBase - Outlet - getPower Error: " + err); 87 | callback(err); 88 | }); 89 | } 90 | 91 | MiPlugBaseOutlet.prototype.setPower = function(value, callback) { 92 | var that = this; 93 | that.device.call("set_power", [value ? "on" : "off"]).then(result => { 94 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBase - Outlet - setPower Result: " + result); 95 | if(result[0] === "ok") { 96 | callback(null); 97 | } else { 98 | callback(new Error(result[0])); 99 | } 100 | }).catch(function(err) { 101 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBase - Outlet - setPower Error: " + err); 102 | callback(err); 103 | }); 104 | } 105 | 106 | MiPlugBaseTemperature = function(dThis) { 107 | this.device = dThis.device; 108 | this.name = dThis.config['temperatureName']; 109 | this.platform = dThis.platform; 110 | } 111 | 112 | MiPlugBaseTemperature.prototype.getServices = function() { 113 | var services = []; 114 | 115 | var infoService = new Service.AccessoryInformation(); 116 | infoService 117 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 118 | .setCharacteristic(Characteristic.Model, "Plug Base") 119 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 120 | services.push(infoService); 121 | 122 | var temperatureService = new Service.TemperatureSensor(this.name); 123 | temperatureService 124 | .getCharacteristic(Characteristic.CurrentTemperature) 125 | .on('get', this.getTemperature.bind(this)) 126 | services.push(temperatureService); 127 | 128 | return services; 129 | } 130 | 131 | MiPlugBaseTemperature.prototype.getTemperature = function(callback) { 132 | var that = this; 133 | this.device.call("get_prop", ["temperature"]).then(result => { 134 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBase - Temperature - getTemperature: " + result); 135 | callback(null, result[0]); 136 | }).catch(function(err) { 137 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBase - Temperature - getTemperature Error: " + err); 138 | callback(err); 139 | }); 140 | } 141 | 142 | MiPlugBaseSwitchLED = function(dThis) { 143 | this.device = dThis.device; 144 | this.name = dThis.config['switchLEDName']; 145 | this.platform = dThis.platform; 146 | } 147 | 148 | MiPlugBaseSwitchLED.prototype.getServices = function() { 149 | var services = []; 150 | 151 | var infoService = new Service.AccessoryInformation(); 152 | infoService 153 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 154 | .setCharacteristic(Characteristic.Model, "Plug Base") 155 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 156 | services.push(infoService); 157 | 158 | var switchLEDService = new Service.Lightbulb(this.name); 159 | switchLEDService 160 | .getCharacteristic(Characteristic.On) 161 | .on('get', this.getLEDPower.bind(this)) 162 | .on('set', this.setLEDPower.bind(this)); 163 | services.push(switchLEDService); 164 | 165 | return services; 166 | } 167 | 168 | MiPlugBaseSwitchLED.prototype.getLEDPower = function(callback) { 169 | var that = this; 170 | this.device.call("get_prop", ["wifi_led"]).then(result => { 171 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBase - SwitchLED - getLEDPower: " + result); 172 | callback(null, result[0] === 'on' ? true : false); 173 | }).catch(function(err) { 174 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBase - SwitchLED - getLEDPower Error: " + err); 175 | callback(err); 176 | }); 177 | } 178 | 179 | MiPlugBaseSwitchLED.prototype.setLEDPower = function(value, callback) { 180 | var that = this; 181 | that.device.call("set_wifi_led", [value ? "on" : "off"]).then(result => { 182 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBase - SwitchLED - setLEDPower Result: " + result); 183 | if(result[0] === "ok") { 184 | callback(null); 185 | } else { 186 | callback(new Error(result[0])); 187 | } 188 | }).catch(function(err) { 189 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBase - SwitchLED - setLEDPower Error: " + err); 190 | callback(err); 191 | }); 192 | } -------------------------------------------------------------------------------- /Devices/MiIntelligencePinboard.js: -------------------------------------------------------------------------------- 1 | require('./Base'); 2 | 3 | const inherits = require('util').inherits; 4 | const miio = require('miio'); 5 | 6 | var Accessory, PlatformAccessory, Service, Characteristic, UUIDGen; 7 | 8 | MiIntelligencePinboard = function(platform, config) { 9 | this.init(platform, config); 10 | 11 | Accessory = platform.Accessory; 12 | PlatformAccessory = platform.PlatformAccessory; 13 | Service = platform.Service; 14 | Characteristic = platform.Characteristic; 15 | UUIDGen = platform.UUIDGen; 16 | 17 | this.device = new miio.Device({ 18 | address: this.config['ip'], 19 | token: this.config['token'] 20 | }); 21 | 22 | this.accessories = {}; 23 | if(!this.config['outletDisable'] && this.config['outletName'] && this.config['outletName'] != "") { 24 | this.accessories['outletAccessory'] = new MiIntelligencePinboardOutlet(this); 25 | } 26 | if(!this.config['temperatureDisable'] && this.config['temperatureName'] && this.config['temperatureName'] != "") { 27 | this.accessories['temperatureAccessory'] = new MiIntelligencePinboardTemperature(this); 28 | } 29 | if(!this.config['switchLEDDisable'] && this.config['switchLEDName'] && this.config['switchLEDName'] != "") { 30 | this.accessories['switchLEDAccessory'] = new MiIntelligencePinboardSwitchLED(this); 31 | } 32 | var accessoriesArr = this.obj2array(this.accessories); 33 | 34 | this.platform.log.debug("[MiOutletPlatform][DEBUG]Initializing " + this.config["type"] + " device: " + this.config["ip"] + ", accessories size: " + accessoriesArr.length); 35 | 36 | return accessoriesArr; 37 | } 38 | inherits(MiIntelligencePinboard, Base); 39 | 40 | MiIntelligencePinboardOutlet = function(dThis) { 41 | this.device = dThis.device; 42 | this.name = dThis.config['outletName']; 43 | this.platform = dThis.platform; 44 | } 45 | 46 | MiIntelligencePinboardOutlet.prototype.getServices = function() { 47 | var services = []; 48 | 49 | var infoService = new Service.AccessoryInformation(); 50 | infoService 51 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 52 | .setCharacteristic(Characteristic.Model, "Intelligence Pinboard") 53 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 54 | services.push(infoService); 55 | 56 | var outletService = new Service.Outlet(this.name); 57 | outletService 58 | .getCharacteristic(Characteristic.On) 59 | .on('get', this.getPower.bind(this)) 60 | .on('set', this.setPower.bind(this)); 61 | outletService 62 | .getCharacteristic(Characteristic.OutletInUse) 63 | .on('get', this.getOutletInUse.bind(this)); 64 | services.push(outletService); 65 | 66 | return services; 67 | } 68 | 69 | MiIntelligencePinboardOutlet.prototype.getOutletInUse = function(callback) { 70 | var that = this; 71 | this.device.call("get_prop", ["power_consume_rate"]).then(result => { 72 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiIntelligencePinboard - Outlet - getOutletInUse: " + result); 73 | callback(null, result[0] && result[0] > 0 ? true : false); 74 | }).catch(function(err) { 75 | that.platform.log.error("[MiOutletPlatform][ERROR]MiIntelligencePinboard - Outlet - getOutletInUse Error: " + err); 76 | callback(err); 77 | }); 78 | } 79 | 80 | MiIntelligencePinboardOutlet.prototype.getPower = function(callback) { 81 | var that = this; 82 | this.device.call("get_prop", ["power"]).then(result => { 83 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiIntelligencePinboard - Outlet - getPower: " + result); 84 | callback(null, result[0] === 'on' ? true : false); 85 | }).catch(function(err) { 86 | that.platform.log.error("[MiOutletPlatform][ERROR]MiIntelligencePinboard - Outlet - getPower Error: " + err); 87 | callback(err); 88 | }); 89 | } 90 | 91 | MiIntelligencePinboardOutlet.prototype.setPower = function(value, callback) { 92 | var that = this; 93 | that.device.call("set_power", [value ? "on" : "off"]).then(result => { 94 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiIntelligencePinboard - Outlet - setPower Result: " + result); 95 | if(result[0] === "ok") { 96 | callback(null); 97 | } else { 98 | callback(new Error(result[0])); 99 | } 100 | }).catch(function(err) { 101 | that.platform.log.error("[MiOutletPlatform][ERROR]MiIntelligencePinboard - Outlet - setPower Error: " + err); 102 | callback(err); 103 | }); 104 | } 105 | 106 | MiIntelligencePinboardTemperature = function(dThis) { 107 | this.device = dThis.device; 108 | this.name = dThis.config['temperatureName']; 109 | this.platform = dThis.platform; 110 | } 111 | 112 | MiIntelligencePinboardTemperature.prototype.getServices = function() { 113 | var services = []; 114 | 115 | var infoService = new Service.AccessoryInformation(); 116 | infoService 117 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 118 | .setCharacteristic(Characteristic.Model, "Intelligence Pinboard") 119 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 120 | services.push(infoService); 121 | 122 | var temperatureService = new Service.TemperatureSensor(this.name); 123 | temperatureService 124 | .getCharacteristic(Characteristic.CurrentTemperature) 125 | .on('get', this.getTemperature.bind(this)) 126 | services.push(temperatureService); 127 | 128 | return services; 129 | } 130 | 131 | MiIntelligencePinboardTemperature.prototype.getTemperature = function(callback) { 132 | var that = this; 133 | this.device.call("get_prop", ["temperature"]).then(result => { 134 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiIntelligencePinboard - Temperature - getTemperature: " + result); 135 | callback(null, result[0]); 136 | }).catch(function(err) { 137 | that.platform.log.error("[MiOutletPlatform][ERROR]MiIntelligencePinboard - Temperature - getTemperature Error: " + err); 138 | callback(err); 139 | }); 140 | } 141 | 142 | MiIntelligencePinboardSwitchLED = function(dThis) { 143 | this.device = dThis.device; 144 | this.name = dThis.config['switchLEDName']; 145 | this.platform = dThis.platform; 146 | } 147 | 148 | MiIntelligencePinboardSwitchLED.prototype.getServices = function() { 149 | var services = []; 150 | 151 | var infoService = new Service.AccessoryInformation(); 152 | infoService 153 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 154 | .setCharacteristic(Characteristic.Model, "Intelligence Pinboard") 155 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 156 | services.push(infoService); 157 | 158 | var switchLEDService = new Service.Lightbulb(this.name); 159 | switchLEDService 160 | .getCharacteristic(Characteristic.On) 161 | .on('get', this.getLEDPower.bind(this)) 162 | .on('set', this.setLEDPower.bind(this)); 163 | services.push(switchLEDService); 164 | 165 | return services; 166 | } 167 | 168 | MiIntelligencePinboardSwitchLED.prototype.getLEDPower = function(callback) { 169 | var that = this; 170 | this.device.call("get_prop", ["wifi_led"]).then(result => { 171 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiIntelligencePinboard - SwitchLED - getLEDPower: " + result); 172 | callback(null, result[0] === 'on' ? true : false); 173 | }).catch(function(err) { 174 | that.platform.log.error("[MiOutletPlatform][ERROR]MiIntelligencePinboard - SwitchLED - getLEDPower Error: " + err); 175 | callback(err); 176 | }); 177 | } 178 | 179 | MiIntelligencePinboardSwitchLED.prototype.setLEDPower = function(value, callback) { 180 | var that = this; 181 | that.device.call("set_wifi_led", [value ? "on" : "off"]).then(result => { 182 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiIntelligencePinboard - SwitchLED - setLEDPower Result: " + result); 183 | if(result[0] === "ok") { 184 | callback(null); 185 | } else { 186 | callback(new Error(result[0])); 187 | } 188 | }).catch(function(err) { 189 | that.platform.log.error("[MiOutletPlatform][ERROR]MiIntelligencePinboard - SwitchLED - setLEDPower Error: " + err); 190 | callback(err); 191 | }); 192 | } -------------------------------------------------------------------------------- /Devices/MiPlugBaseEnhanced.js: -------------------------------------------------------------------------------- 1 | require('./Base'); 2 | 3 | const inherits = require('util').inherits; 4 | const miio = require('miio'); 5 | 6 | var Accessory, PlatformAccessory, Service, Characteristic, UUIDGen; 7 | 8 | MiPlugBaseEnhanced = function(platform, config) { 9 | this.init(platform, config); 10 | 11 | Accessory = platform.Accessory; 12 | PlatformAccessory = platform.PlatformAccessory; 13 | Service = platform.Service; 14 | Characteristic = platform.Characteristic; 15 | UUIDGen = platform.UUIDGen; 16 | 17 | this.device = new miio.Device({ 18 | address: this.config['ip'], 19 | token: this.config['token'] 20 | }); 21 | 22 | this.accessories = {}; 23 | if(!this.config['outletDisable'] && this.config['outletName'] && this.config['outletName'] != "") { 24 | this.accessories['outletAccessory'] = new MiPlugBaseEnhancedOutlet(this); 25 | } 26 | if(!this.config['temperatureDisable'] && this.config['temperatureName'] && this.config['temperatureName'] != "") { 27 | this.accessories['temperatureAccessory'] = new MiPlugBaseEnhancedTemperature(this); 28 | } 29 | if(!this.config['switchUSBDisable'] && this.config['switchUSBName'] && this.config['switchUSBName'] != "") { 30 | this.accessories['switchUSBAccessory'] = new MiPlugBaseEnhancedSwitchUSB(this); 31 | } 32 | if(!this.config['switchLEDDisable'] && this.config['switchLEDName'] && this.config['switchLEDName'] != "") { 33 | this.accessories['switchLEDAccessory'] = new MiPlugBaseEnhancedSwitchLED(this); 34 | } 35 | var accessoriesArr = this.obj2array(this.accessories); 36 | 37 | this.platform.log.debug("[MiOutletPlatform][DEBUG]Initializing " + this.config["type"] + " device: " + this.config["ip"] + ", accessories size: " + accessoriesArr.length); 38 | 39 | return accessoriesArr; 40 | } 41 | inherits(MiPlugBaseEnhanced, Base); 42 | 43 | MiPlugBaseEnhancedOutlet = function(dThis) { 44 | this.device = dThis.device; 45 | this.name = dThis.config['outletName']; 46 | this.platform = dThis.platform; 47 | } 48 | 49 | MiPlugBaseEnhancedOutlet.prototype.getServices = function() { 50 | var services = []; 51 | 52 | var infoService = new Service.AccessoryInformation(); 53 | infoService 54 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 55 | .setCharacteristic(Characteristic.Model, "Plug Base Enhanced") 56 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 57 | services.push(infoService); 58 | 59 | var outletService = new Service.Outlet(this.name); 60 | outletService 61 | .getCharacteristic(Characteristic.On) 62 | .on('get', this.getPower.bind(this)) 63 | .on('set', this.setPower.bind(this)); 64 | outletService 65 | .getCharacteristic(Characteristic.OutletInUse) 66 | .on('get', this.getOutletInUse.bind(this)); 67 | services.push(outletService); 68 | 69 | return services; 70 | } 71 | 72 | MiPlugBaseEnhancedOutlet.prototype.getOutletInUse = function(callback) { 73 | var that = this; 74 | this.device.call("get_prop", ["power"]).then(result => { 75 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseEnhanced - Outlet - getOutletInUse: " + result); 76 | callback(null, result[0] === '100' ? true : false); 77 | }).catch(function(err) { 78 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseEnhanced - Outlet - getOutletInUse Error: " + err); 79 | callback(err); 80 | }); 81 | } 82 | 83 | MiPlugBaseEnhancedOutlet.prototype.getPower = function(callback) { 84 | var that = this; 85 | this.device.call("get_prop", ["power"]).then(result => { 86 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseEnhanced - Outlet - getPower: " + result); 87 | callback(null, result[0] === '100' ? true : false); 88 | }).catch(function(err) { 89 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseEnhanced - Outlet - getPower Error: " + err); 90 | callback(err); 91 | }); 92 | } 93 | 94 | MiPlugBaseEnhancedOutlet.prototype.setPower = function(value, callback) { 95 | var that = this; 96 | that.device.call("set_power", [value ? "on" : "off"]).then(result => { 97 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseEnhanced - Outlet - setPower Result: " + result); 98 | if(result[0] === "ok") { 99 | callback(null); 100 | } else { 101 | callback(new Error(result[0])); 102 | } 103 | }).catch(function(err) { 104 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseEnhanced - Outlet - setPower Error: " + err); 105 | callback(err); 106 | }); 107 | } 108 | 109 | MiPlugBaseEnhancedTemperature = function(dThis) { 110 | this.device = dThis.device; 111 | this.name = dThis.config['temperatureName']; 112 | this.platform = dThis.platform; 113 | } 114 | 115 | MiPlugBaseEnhancedTemperature.prototype.getServices = function() { 116 | var services = []; 117 | 118 | var infoService = new Service.AccessoryInformation(); 119 | infoService 120 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 121 | .setCharacteristic(Characteristic.Model, "Plug Base Enhanced") 122 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 123 | services.push(infoService); 124 | 125 | var temperatureService = new Service.TemperatureSensor(this.name); 126 | temperatureService 127 | .getCharacteristic(Characteristic.CurrentTemperature) 128 | .on('get', this.getTemperature.bind(this)) 129 | services.push(temperatureService); 130 | 131 | return services; 132 | } 133 | 134 | MiPlugBaseEnhancedTemperature.prototype.getTemperature = function(callback) { 135 | var that = this; 136 | this.device.call("get_prop", ["temperature"]).then(result => { 137 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBase - MiPlugBaseEnhanced - getTemperature: " + result); 138 | callback(null, result[0]); 139 | }).catch(function(err) { 140 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBase - MiPlugBaseEnhanced - getTemperature Error: " + err); 141 | callback(err); 142 | }); 143 | } 144 | 145 | MiPlugBaseEnhancedSwitchLED = function(dThis) { 146 | this.device = dThis.device; 147 | this.name = dThis.config['switchLEDName']; 148 | this.platform = dThis.platform; 149 | } 150 | 151 | MiPlugBaseEnhancedSwitchLED.prototype.getServices = function() { 152 | var services = []; 153 | 154 | var infoService = new Service.AccessoryInformation(); 155 | infoService 156 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 157 | .setCharacteristic(Characteristic.Model, "Plug Base Enhanced") 158 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 159 | services.push(infoService); 160 | 161 | var switchLEDService = new Service.Lightbulb(this.name); 162 | switchLEDService 163 | .getCharacteristic(Characteristic.On) 164 | .on('get', this.getLEDPower.bind(this)) 165 | .on('set', this.setLEDPower.bind(this)); 166 | services.push(switchLEDService); 167 | 168 | return services; 169 | } 170 | 171 | MiPlugBaseEnhancedSwitchLED.prototype.getLEDPower = function(callback) { 172 | var that = this; 173 | this.device.call("get_prop", ["wifi_led"]).then(result => { 174 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseEnhanced - SwitchLED - getLEDPower: " + result); 175 | callback(null, result[0] === 'on' ? true : false); 176 | }).catch(function(err) { 177 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseEnhanced - SwitchLED - getLEDPower Error: " + err); 178 | callback(err); 179 | }); 180 | } 181 | 182 | MiPlugBaseEnhancedSwitchLED.prototype.setLEDPower = function(value, callback) { 183 | var that = this; 184 | that.device.call("set_wifi_led", [value ? "on" : "off"]).then(result => { 185 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseEnhanced - SwitchLED - setLEDPower Result: " + result); 186 | if(result[0] === "ok") { 187 | callback(null); 188 | } else { 189 | callback(new Error(result[0])); 190 | } 191 | }).catch(function(err) { 192 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseEnhanced - SwitchLED - setLEDPower Error: " + err); 193 | callback(err); 194 | }); 195 | } 196 | 197 | MiPlugBaseEnhancedSwitchUSB = function(dThis) { 198 | this.device = dThis.device; 199 | this.name = dThis.config['switchUSBName']; 200 | this.platform = dThis.platform; 201 | } 202 | 203 | MiPlugBaseEnhancedSwitchUSB.prototype.getServices = function() { 204 | var services = []; 205 | 206 | var infoService = new Service.AccessoryInformation(); 207 | infoService 208 | .setCharacteristic(Characteristic.Manufacturer, "XiaoMi") 209 | .setCharacteristic(Characteristic.Model, "Plug Base Enhanced") 210 | .setCharacteristic(Characteristic.SerialNumber, "Undefined"); 211 | services.push(infoService); 212 | 213 | var switchService = new Service.Switch(this.name); 214 | switchService 215 | .getCharacteristic(Characteristic.On) 216 | .on('get', this.getUSBPower.bind(this)) 217 | .on('set', this.setUSBPower.bind(this)); 218 | services.push(switchService); 219 | 220 | return services; 221 | } 222 | 223 | MiPlugBaseEnhancedSwitchUSB.prototype.getUSBPower = function(callback) { 224 | var that = this; 225 | this.device.call("get_prop", ["usb_on"]).then(result => { 226 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseEnhanced - SwitchUSB - getUSBPower: " + result); 227 | callback(null, result[0]); 228 | }).catch(function(err) { 229 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseEnhanced - SwitchUSB - getUSBPower Error: " + err); 230 | callback(err); 231 | }); 232 | } 233 | 234 | MiPlugBaseEnhancedSwitchUSB.prototype.setUSBPower = function(value, callback) { 235 | var that = this; 236 | that.device.call(value ? "set_usb_on" : "set_usb_off", []).then(result => { 237 | that.platform.log.debug("[MiOutletPlatform][DEBUG]MiPlugBaseEnhanced - SwitchUSB - setUSBPower Result: " + result); 238 | callback(null); 239 | }).catch(function(err) { 240 | that.platform.log.error("[MiOutletPlatform][ERROR]MiPlugBaseEnhanced - SwitchUSB - setUSBPower Error: " + err); 241 | callback(err); 242 | }); 243 | } --------------------------------------------------------------------------------