2
0

Added (basic) support for WiFi power plug

This commit is contained in:
Harald Rietman
2017-07-11 22:58:15 +02:00
parent a057c10f07
commit 9fee86f6d3
6 changed files with 279 additions and 4 deletions

View File

@@ -9,12 +9,14 @@ The following devices are currently supported:
* Button switch
* Motion sensor
* Power plug (zigbee)
* Power plug (wifi)
## Preperation
To receive the gateway json messages on your network you need to enable the developer mode, aka LAN mode in the gateway.
A UDP input node is needed to receive the json messages. An UDP output node to send command's to the gateway.
To control the Wifi-Plug, extensive use is made of the miio library created by [Andreas Holstenson](https://github.com/aholstenson/miio). Make sure to check his page for compatible devices.
## Install
@@ -27,6 +29,8 @@ npm install node-red-contrib-xiaomi-devices
From the Xiaomi configurator screen add your different devices by selecting the type of device and a readable description. The readable discription is used on the different edit screen of the nodes to easily select the device you associate to the node.
Note that the Wifi power plug is not configured through the configurator as it is not connected to the gateway.
The Xiaomi configurator screen with ease of use to configure your different devices.
![Xiaomi configurator in node-red](https://raw.githubusercontent.com/hrietman/node-red-contrib-xiaomi-devices/master/xiaomi-configurator.png)
@@ -57,5 +61,6 @@ Here an example of how to use the different nodes.
## Roadmap
* Support for other devices like the smart-socket WiFi
* ~~Support for other devices like the smart-socket WiFi~~ Done!
* Import (new) devices directly from the gateway

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,119 @@
<script type="text/javascript">
RED.nodes.registerType('xiaomi-plug-wifi', {
category: 'xiaomi',
color: '#3FADB5',
defaults: {
name: {value: ""},
ip: {value: "", required: true},
onmsg: {value: ""},
offmsg: {value: ""},
output: {value: "0"}
},
inputs: 1,
outputs: 1,
outputLabels: ["Status"],
paletteLabel: "plug (wifi)",
icon: "outlet-wifi-icon.png",
label: function () {
return this.name || "xiaomi-plug-wifi";
},
oneditprepare: function() {
var node = this;
$("#node-input-output").change(function () {
if ($(this).val() == "2") {
$(".node-input-msg").show();
} else {
$(".node-input-msg").hide();
}
});
},
oneditsave: function() {
}
});
</script>
<script type="text/x-red" data-template-name="xiaomi-plug-wifi">
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-ip"><i class="icon-tag"></i> Ip</label>
<input type="text" id="node-input-ip" placeholder="ip address">
</div>
<div class="form-row">
<label for="node-input-output"><i class="icon-tag"></i> Output</label>
<select id="node-input-output" style="width:70%;">
<option value="0">Full data</option>
<option value="1">Just values</option>
<option value="2">Template</option>
</select>
</div>
<div class="form-row node-input-msg">
<label for="node-input-onmsg"><i class="fa fa-power-off"></i> On msg</label>
<input type="text" id="node-input-onmsg">
</div>
<div class="form-row node-input-msg">
<label for="node-input-offmsg"><i class="fa fa-power-off"></i> Off msg</label>
<input type="text" id="node-input-offmsg">
</div>
</script>
<script type="text/x-red" data-help-name="xiaomi-plug-wifi">
<p>The Xiaomi plug (wifi) node</p>
<p>This is the wiFi plug (socket). To control the Wifi-Plug, extensive use is made of the miio library created by <a href="https://github.com/aholstenson/miio">Andreas Holstenson</a>. Make sure to check his page for compatible devices.</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>payload
<span class="property-type">string</span>
</dt>
<dd><code>on</code> or <code>off</code>.</dd>
</dl>
<h3>Outputs</h3>
<ol class="node-ports">
<li>Status output
<dl class="message-properties">
<dt>payload <span class="property-type">string | json</span></dt>
<dd>raw data, value or template.</dd>
</dl>
</li>
</ol>
<h3>Details</h3>
<p>On the input you can send the string <code>on</code> to switch the plug on. To turn it off just send the string <code>off</code></p>
<p>Output 1 reports the status</p>
<p>Three output types are supported:
<ul>
<li>Full data</li>
<li>Just values</li>
<li>Template</li>
</ul>
</p>
<h4>Full data</h4>
<p>Passes a json object with detailed information about the plug. Use this if you need the raw data.</p>
<h4>Just values</h4>
<p>Only passes the values <code>on</code> or <code>off</code></p>
<h4>Template</h4>
<p>Use your own template to pass the values on. The template can contain <a href="http://mustache.github.io/mustache.5.html">mustache-style</a> tags.
Any property from the data section of the full object can be used.</p>
<p>Sample message full data:</p>
<p><pre>
{
"type": "power-plug",
"model": "chuangmi.plug.m1",
"capabilities: [ {'0': "power-channels"} ],
"address": "192.168.178.31",
"port": 54321,
"power": { '0': false }
}"
}</pre></p>
</script>

View File

@@ -0,0 +1,149 @@
module.exports = function(RED) {
"use strict";
var mustache = require("mustache");
var crypto = require("crypto");
var miio = require("miio");
function XiaomiPlugWifiNode(config) {
RED.nodes.createNode(this, config);
this.ip = config.ip;
this.output = config.output;
this.onmsg = config.onmsg;
this.offmsg = config.offmsg;
var node = this;
var connectionState = "timeout";
var plug = {};
var retryTimer;
node.status({fill:"yellow", shape:"dot", text:"connecting"});
miio.device({ address: node.ip })
.then(function(result) {
if (result.type === "power-plug") {
plug = result;
node.status({fill:"green", shape:"dot", text:"connected"});
connectionState = "connected";
setTimeout(function() {
if (result.power()['0']) {
setState("on");
} else {
setState("off");
}
}, 1500);
watchdog();
plug.on('propertyChanged', function(e) {
if (e.property === "power") {
if (e.value['0']) {
setState("on");
} else {
setState("off");
}
}
});
}
})
.catch(function(error) {
node.status({fill:"red", shape:"dot", text:"time out"});
connectionState = "reconnecting";
watchdog();
});
node.on('input', function(msg) {
var payload = msg.payload;
if (payload == 'on') {
if (connectionState === "connected") {
plug.setPower(true);
}
}
if (payload == 'off') {
if (connectionState === "connected") {
plug.setPower(false);
}
}
});
this.on('close', function(done) {
if (retryTimer) {
clearTimeout(retryTimer);
}
if (plug) {
plug.destroy();
}
done();
});
var setState = function(state) {
var status = null;
var info = {"payload": {
"id": plug.id,
"type": plug.type,
"model": plug.model,
"capabilities": plug.capabilities,
"address": plug.address,
"port": plug.port,
"power": plug.power()
}};
if (state === "on") {
node.status({fill:"green", shape:"dot", text:"on"});
status = {"payload": mustache.render(node.onmsg, info.payload)}
}
if (state === "off") {
node.status({fill:"red", shape:"dot", text:"off"});
status = {"payload": mustache.render(node.offmsg, info.payload)}
}
if (node.output == 0) {
status = info;
} else if (node.output == "1") {
status = {"payload": state}
} else if (node.output == "2") {
// do nothing, just send status parsed with mustache
}
node.send([status]);
};
var watchdog = function() {
var interval = 10;
retryTimer = setInterval(function() {
if (interval == 0) {
miio.device({address: node.ip})
.then(function (result) {
if (connectionState === "reconnecting") {
node.status({fill:"green", shape:"dot", text:"connected"});
connectionState = "connected";
setTimeout(function() {
if (result.power()['0']) {
setState("on");
} else {
setState("off");
}
}, 1500);
}
})
.catch(function (error) {
connectionState = "reconnecting";
})
interval = 10;
} else {
interval--;
if (connectionState === "reconnecting") {
node.status({fill: "red", shape: "dot", text: "retrying in " + interval + " sec."});
}
}
}, 1000);
}
}
RED.nodes.registerType("xiaomi-plug-wifi", XiaomiPlugWifiNode);
}

View File

@@ -1,6 +1,6 @@
{
"name": "node-red-contrib-xiaomi-devices",
"version": "1.0.8",
"version": "1.0.9",
"description": "A set of nodes to control some of the popular Xiaomi sensors which are connected to the Xiaomi Gateway.",
"repository": {
"type": "git",
@@ -13,8 +13,9 @@
"xiaomi-ht": "node-red-contrib-xiaomi-ht/xiaomi-ht.js",
"xiaomi-magnet": "node-red-contrib-xiaomi-magnet/xiaomi-magnet.js",
"xiaomi-motion": "node-red-contrib-xiaomi-motion/xiaomi-motion.js",
"xiaomi-socket": "node-red-contrib-xiaomi-socket/xiaomi-socket.js",
"xiaomi-switch": "node-red-contrib-xiaomi-switch/xiaomi-switch.js",
"xiaomi-socket": "node-red-contrib-xiaomi-socket/xiaomi-socket.js",
"xiaomi-socket-wifi": "node-red-contrib-xiaomi-socket-wifi/xiaomi-socket-wifi.js",
"xiaomi-configurator": "node-red-contrib-xiaomi-configurator/xiaomi-configurator.js"
}
},
@@ -24,6 +25,7 @@
},
"dependencies": {
"cryptojs": "^2.5.3",
"mustache": "^2.3.0"
"mustache": "^2.3.0",
"miio": "0.13.0"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 218 KiB