2
0

feat(actions): add click and double click actions

This commit is contained in:
Pierre CLEMENT
2018-01-01 03:31:51 +01:00
parent 27619fb7fa
commit 7742e99f75
10 changed files with 187 additions and 35 deletions

View File

@@ -1,19 +1,3 @@
<!--
Copyright JS Foundation and other contributors, http://js.foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- The Read Node -->
<script type="text/x-red" data-template-name="xiaomi-actions read">
<div class="form-row">
@@ -56,6 +40,7 @@
});
</script>
<!-- The get ids Node -->
<script type="text/x-red" data-template-name="xiaomi-actions get_id_list">
<div class="form-row">
@@ -89,3 +74,104 @@
}
});
</script>
<!-- The Single click Node -->
<script type="text/x-red" data-template-name="xiaomi-actions click">
<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>
</script>
<script type="text/x-red" data-help-name="xiaomi-actions click">
<p>
Virtual single click for switch.
Note: a gateway input node must be present to get gateway tokens.
</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>sid
<span class="property-type">string</span>
</dt>
<dd>Device <code>sid</code> to ask the report.</dd>
<dt>gateway
<span class="property-type">xiaomi-configurator</span>
</dt>
<dd>Device <code>sid</code> to ask the report.</dd>
</dl>
<h3>Outputs</h3>
<p class="node-ports">
Message to connect to a gateway out node.
</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('xiaomi-actions click',{
category: 'xiaomi actions',
color: '#64C4CD',
defaults: {
name: {value:""}
},
inputs:1,
outputs:1,
paletteLabel: "click",
icon: "function.png",
label: function() {
return this.name||"click";
}
});
</script>
<!-- The Double click Node -->
<script type="text/x-red" data-template-name="xiaomi-actions double_click">
<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>
</script>
<script type="text/x-red" data-help-name="xiaomi-actions double_click">
<p>
Virtual double click for switch.
Note: a gateway input node must be present to get gateway tokens.
</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>sid
<span class="property-type">string</span>
</dt>
<dd>Device <code>sid</code> to ask the report.</dd>
<dt>gateway
<span class="property-type">xiaomi-configurator</span>
</dt>
<dd>Device <code>sid</code> to ask the report.</dd>
</dl>
<h3>Outputs</h3>
<p class="node-ports">
Message to connect to a gateway out node.
</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('xiaomi-actions double_click',{
category: 'xiaomi actions',
color: '#64C4CD',
defaults: {
name: {value:""}
},
inputs:1,
outputs:1,
paletteLabel: "double click",
icon: "function.png",
label: function() {
return this.name||"double click";
}
});
</script>

View File

@@ -1,5 +1,6 @@
module.exports = function(RED) {
"use strict";
var miDevicesUtils = require('../utils');
function XiaomiActionRead(config) {
RED.nodes.createNode(this, config);
@@ -9,7 +10,7 @@ module.exports = function(RED) {
if(msg.sid) {
msg.payload = {
cmd: "read",
sid: msg.payload
sid: msg.sid
};
node.send(msg);
}
@@ -30,4 +31,46 @@ module.exports = function(RED) {
});
}
RED.nodes.registerType("xiaomi-actions get_id_list", XiaomiActionGetIdList);
function XiaomiActionSingleClick(config) {
RED.nodes.createNode(this, config);
var node = this;
node.on('input', function(msg) {
if(msg.gateway && msg.sid && msg.gateway.key && msg.gateway.lastToken) {
msg.payload = {
cmd: "write",
data: {
status: "click",
sid: msg.sid,
key: miDevicesUtils.getGatewayKey(msg.gateway.key, msg.gateway.lastToken)
}
};
node.send(msg);
}
});
}
RED.nodes.registerType("xiaomi-actions click", XiaomiActionSingleClick);
function XiaomiActionDoubleClick(config) {
RED.nodes.createNode(this, config);
var node = this;
node.on('input', function(msg) {
if(msg.gateway && msg.sid && msg.gateway.key && msg.gateway.lastToken) {
msg.payload = {
cmd: "write",
data: {
status: "double_click",
sid: msg.sid,
key: miDevicesUtils.getGatewayKey(msg.gateway.key, msg.gateway.lastToken)
}
};
node.send(msg);
}
});
}
RED.nodes.registerType("xiaomi-actions double_click", XiaomiActionDoubleClick);
}

View File

@@ -64,7 +64,6 @@
if(tmpNode.type.indexOf("xiaomi-gateway") === 0 && tmpNode.gateway == node.id) {
tmpNode.ip = $("#node-config-input-ip").val();
tmpNode.changed = true;
console.log(tmpNode);
}
});
var devicesArray = [];

View File

@@ -1,19 +1,3 @@
<!--
Copyright JS Foundation and other contributors, http://js.foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- The Input Node -->
<script type="text/x-red" data-template-name="xiaomi-gateway in">
<div class="form-row">

View File

@@ -22,6 +22,7 @@ module.exports = function(RED) {
// The Input Node
function GatewayIn(n) {
RED.nodes.createNode(this,n);
this.gateway = RED.nodes.getNode(n.gateway);
this.group = "224.0.0.50";
this.port = 9898;
this.iface = null;
@@ -62,6 +63,9 @@ module.exports = function(RED) {
jsonMsg.data = JSON.parse(jsonMsg.data) || jsonMsg.data;
}
msg = { payload: jsonMsg };
if(jsonMsg.token && node.gateway && jsonMsg.data.ip && jsonMsg.data.ip === node.gateway.ip) {
node.gateway.lastToken = jsonMsg.token;
}
node.send(msg);
}
});

View File

@@ -22,6 +22,7 @@ module.exports = function(RED) {
var payload = msg.payload;
node.log("Received message from: " + payload.model + " sid: " + payload.sid + " payload: " + payload.data);
// Input from gateway
if (payload.sid == node.sid && ["sensor_ht", "weather.v1"].indexOf(payload.model) >= 0) {
var data = payload.data;
miDevicesUtils.setStatus(node, data);
@@ -74,6 +75,11 @@ module.exports = function(RED) {
node.send([temp, humidity, pressure]);
}
}
// Prepare for request
else {
miDevicesUtils.prepareForGatewayRequest(node, msg);
node.send(msg);
}
});
node.on("close", function() {

View File

@@ -56,6 +56,11 @@ module.exports = function(RED) {
node.send([status]);
}
}
// Prepare for request
else {
miDevicesUtils.prepareForGatewayRequest(node, msg);
node.send(msg);
}
});
node.on("close", function() {

View File

@@ -62,6 +62,11 @@ module.exports = function(RED) {
node.send([status]);
}
}
// Prepare for request
else {
miDevicesUtils.prepareForGatewayRequest(node, msg);
node.send(msg);
}
});
node.on("close", function() {

View File

@@ -19,6 +19,8 @@ module.exports = function(RED) {
node.on('input', function(msg) {
// var payload = JSON.parse(msg);
var payload = msg.payload;
// Input from gateway
if (payload.sid == node.sid && ["switch", "sensor_switch.aq2"].indexOf(payload.model) >= 0) {
var data = payload.data;
miDevicesUtils.setStatus(node, data);
@@ -47,6 +49,11 @@ module.exports = function(RED) {
}
}
}
// Prepare for request
else {
miDevicesUtils.prepareForGatewayRequest(node, msg);
node.send(msg);
}
});
node.on("close", function() {

View File

@@ -1,4 +1,5 @@
var crypto = require("crypto");
var iv = Buffer.from([0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58, 0x56, 0x2e]);
module.exports = {
computeBatteryLevel: function(voltage) {
@@ -29,5 +30,17 @@ module.exports = {
payload.data.batteryLevel = this.computeBatteryLevel(payload.data.voltage);
}
return payload;
},
getGatewayKey: function(password, token) {
var cipher = crypto.createCipheriv('aes-128-cbc', password, iv);
var gatewayToken = token;
var key = cipher.update(gatewayToken, "ascii", "hex");
cipher.final('hex');
return key;
},
prepareForGatewayRequest: function(node, msg) {
msg.sid = node.sid;
msg.gateway = node.gateway;
}
}