feat(gateway): addset light and play sounds
This commit is contained in:
@@ -1,204 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- The Gateway light Node -->
|
|
||||||
<script type="text/javascript">
|
|
||||||
RED.nodes.registerType('mi-devices-actions gateway_light', {
|
|
||||||
category: 'xiaomi actions',
|
|
||||||
color: '#64C4CD',
|
|
||||||
defaults: {
|
|
||||||
name: {value: ""},
|
|
||||||
brightness: {value: 100},
|
|
||||||
hexRgbColor: {value: "#ffffff"},
|
|
||||||
color: {value:{red: 255, green: 255, blue: 255}}
|
|
||||||
},
|
|
||||||
inputs: 1,
|
|
||||||
outputs: 1,
|
|
||||||
paletteLabel: "set light",
|
|
||||||
icon: "mi-bulb.png",
|
|
||||||
label: function () {
|
|
||||||
return this.name || "set light";
|
|
||||||
},
|
|
||||||
oneditsave: function() {
|
|
||||||
var hexRgbColor = $("#node-input-hexRgbColor").val();
|
|
||||||
var split = hexRgbColor.slice(1).match(/.{1,2}/g).map(function(hexColor) {
|
|
||||||
return parseInt(hexColor, 16);
|
|
||||||
});
|
|
||||||
this.color = {
|
|
||||||
red: split[0],
|
|
||||||
green: split[1],
|
|
||||||
blue: split[2]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/x-red" data-template-name="mi-devices-actions gateway_light">
|
|
||||||
<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-brightness"><i class="icon-tag"></i> Brightness</label>
|
|
||||||
<input type="range" id="node-input-brightness" min="0" max="100">
|
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-hexRgbColor"><i class="icon-tag"></i> Color</label>
|
|
||||||
<input type="color" id="node-input-hexRgbColor">
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="mi-devices-actions gateway_light">
|
|
||||||
<p>Change the light of the gateway.</p>
|
|
||||||
|
|
||||||
<h3>Inputs</h3>
|
|
||||||
<dl class="message-properties">
|
|
||||||
<dt>brightness
|
|
||||||
<span class="property-type">number</span>
|
|
||||||
</dt>
|
|
||||||
<dd>The brightness value between <code>0</code> and <code>100</code>.</dd>
|
|
||||||
<dt>color
|
|
||||||
<span class="property-type">object</span>
|
|
||||||
</dt>
|
|
||||||
<dd>The color itself. This object must contain the followinf properties:
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<code>red</code> - amout of red, between <code>0</code> and <code>255</code>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<code>green</code> - amout of green, between <code>0</code> and <code>255</code>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<code>blue</code> - amout of blue, between <code>0</code> and <code>255</code>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h3>Outputs</h3>
|
|
||||||
<ol class="node-ports">
|
|
||||||
<li>Message to connect to a gateway out node.</li>
|
|
||||||
</ol>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- The Gateway sound Node -->
|
|
||||||
<script type="text/javascript">
|
|
||||||
RED.nodes.registerType('mi-devices-actions gateway_sound', {
|
|
||||||
category: 'xiaomi actions',
|
|
||||||
color: '#64C4CD',
|
|
||||||
defaults: {
|
|
||||||
name: {value: ""},
|
|
||||||
mid: {value: ""},
|
|
||||||
volume: {value: ""}
|
|
||||||
},
|
|
||||||
inputs: 1,
|
|
||||||
outputs: 1,
|
|
||||||
paletteLabel: "play sound",
|
|
||||||
icon: "mi-sound.png",
|
|
||||||
label: function () {
|
|
||||||
return this.name || "play sound";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/x-red" data-template-name="mi-devices-actions gateway_sound">
|
|
||||||
<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-mid"><i class="icon-tag"></i> Sound</label>
|
|
||||||
<select id="node-input-mid">
|
|
||||||
<option value="0">Police car tone 1</option>
|
|
||||||
<option value="1">Police car tone 2</option>
|
|
||||||
<option value="2">Safety incident sound</option>
|
|
||||||
<option value="3">Missile countdown</option>
|
|
||||||
<option value="4">Ghost cry</option>
|
|
||||||
<option value="5">Sniper rifle</option>
|
|
||||||
<option value="6">Battle sound</option>
|
|
||||||
<option value="7">Air raid alarm</option>
|
|
||||||
<option value="8">Barking</option>
|
|
||||||
<option value="10">Doorbell tone</option>
|
|
||||||
<option value="11">Door knocking tone</option>
|
|
||||||
<option value="12">Funny tone</option>
|
|
||||||
<option value="13">Alarm clock tone</option>
|
|
||||||
<option value="20">MiMix</option>
|
|
||||||
<option value="21">Enthusisatic</option>
|
|
||||||
<option value="22">GuitarClassic</option>
|
|
||||||
<option value="23">IceWorldPiano</option>
|
|
||||||
<option value="24">LeisureTime</option>
|
|
||||||
<option value="25">ChildHood</option>
|
|
||||||
<option value="26">MorningStreamLet</option>
|
|
||||||
<option value="27">MusicBox</option>
|
|
||||||
<option value="28">Orange</option>
|
|
||||||
<option value="29">Thinker</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-volume"><i class="icon-tag"></i> Volume</label>
|
|
||||||
<input type="range" id="node-input-volume" min="0" max="100">
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="mi-devices-actions gateway_sound">
|
|
||||||
<p>Play a sound on the gateway.</p>
|
|
||||||
|
|
||||||
<h3>Inputs</h3>
|
|
||||||
<dl class="message-properties">
|
|
||||||
<dt>mid
|
|
||||||
<span class="property-type">number</span>
|
|
||||||
</dt>
|
|
||||||
<dd>Music ID (user define sounds start from <code>1001</code>, <code>1000</code> means stop).</dd>
|
|
||||||
<dt>volume
|
|
||||||
<span class="property-type">number</span>
|
|
||||||
</dt>
|
|
||||||
<dd>Playing volume, between <code>0</code> and <code>100</code>.</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h3>Outputs</h3>
|
|
||||||
<ol class="node-ports">
|
|
||||||
<li>Message to connect to a gateway out node.</li>
|
|
||||||
</ol>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- The Gateway stop sound Node -->
|
|
||||||
<script type="text/javascript">
|
|
||||||
RED.nodes.registerType('mi-devices-actions gateway_stop_sound',{
|
|
||||||
category: 'xiaomi actions',
|
|
||||||
color: '#64C4CD',
|
|
||||||
defaults: {
|
|
||||||
name: {value:""}
|
|
||||||
},
|
|
||||||
inputs:1,
|
|
||||||
outputs:1,
|
|
||||||
paletteLabel: "stop sound",
|
|
||||||
icon: "mi-mute.png",
|
|
||||||
label: function() {
|
|
||||||
return this.name||"stop sound";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<script type="text/x-red" data-template-name="mi-devices-actions gateway_stop_sound">
|
|
||||||
<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="mi-devices-actions gateway_stop_sound">
|
|
||||||
<p>
|
|
||||||
Stop current playing sound on the gateway.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Outputs</h3>
|
|
||||||
<ol class="node-ports">
|
|
||||||
<li>Message to connect to a gateway out node.</li>
|
|
||||||
</ol>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- The "on" Node -->
|
<!-- The "on" Node -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
RED.nodes.registerType('mi-devices-actions on',{
|
RED.nodes.registerType('mi-devices-actions on',{
|
||||||
|
|||||||
@@ -1,133 +1,5 @@
|
|||||||
const miDevicesUtils = require('../src/utils');
|
const miDevicesUtils = require('../src/utils');
|
||||||
|
|
||||||
module.exports = (RED) => {
|
module.exports = (RED) => {
|
||||||
/*********************************************
|
|
||||||
Read data from Gateway
|
|
||||||
*********************************************/
|
|
||||||
function XiaomiActionRead(config) {
|
|
||||||
RED.nodes.createNode(this, config);
|
|
||||||
|
|
||||||
this.on('input', (msg) => {
|
|
||||||
if(msg.sid) {
|
|
||||||
msg.payload = { cmd: "read", sid: msg.sid };
|
|
||||||
this.send(msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
RED.nodes.registerType("mi-devices-actions read", XiaomiActionRead);
|
|
||||||
|
|
||||||
/*********************************************
|
|
||||||
Get registred ids of devices on gateway
|
|
||||||
*********************************************/
|
|
||||||
function XiaomiActionGetIdList(config) {
|
|
||||||
RED.nodes.createNode(this, config);
|
|
||||||
|
|
||||||
this.on('input', (msg) => {
|
|
||||||
msg.payload = { cmd: "get_id_list" };
|
|
||||||
node.send(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
RED.nodes.registerType("mi-devices-actions get_id_list", XiaomiActionGetIdList);
|
|
||||||
|
|
||||||
/*********************************************
|
|
||||||
Virtual single click on a button
|
|
||||||
*********************************************/
|
|
||||||
function XiaomiActionSingleClick(config) {
|
|
||||||
RED.nodes.createNode(this, config);
|
|
||||||
|
|
||||||
this.on('input', (msg) => {
|
|
||||||
msg.payload = {
|
|
||||||
cmd: "write",
|
|
||||||
data: { status: "click", sid: msg.sid }
|
|
||||||
};
|
|
||||||
this.send(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
RED.nodes.registerType("mi-devices-actions click", XiaomiActionSingleClick);
|
|
||||||
|
|
||||||
/*********************************************
|
|
||||||
Virtual Double click on a button
|
|
||||||
*********************************************/
|
|
||||||
function XiaomiActionDoubleClick(config) {
|
|
||||||
RED.nodes.createNode(this, config);
|
|
||||||
|
|
||||||
this.on('input', (msg) => {
|
|
||||||
msg.payload = {
|
|
||||||
cmd: "write",
|
|
||||||
data: { status: "double_click", sid: msg.sid }
|
|
||||||
};
|
|
||||||
this.send(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
RED.nodes.registerType("mi-devices-actions double_click", XiaomiActionDoubleClick);
|
|
||||||
|
|
||||||
/*********************************************
|
|
||||||
Set the gateway light
|
|
||||||
*********************************************/
|
|
||||||
function XiaomiActionGatewayLight(config) {
|
|
||||||
RED.nodes.createNode(this, config);
|
|
||||||
this.color = config.color;
|
|
||||||
this.brightness = config.brightness;
|
|
||||||
|
|
||||||
this.on('input', (msg) => {
|
|
||||||
let color = msg.color || this.color;
|
|
||||||
let brightness = msg.brightness || this.brightness;
|
|
||||||
if(msg.sid) {
|
|
||||||
let rgb = miDevicesUtils.computeColorValue(color.red, color.green, color.blue, brightness);
|
|
||||||
msg.payload = {
|
|
||||||
cmd: "write",
|
|
||||||
data: { rgb: rgb, sid: msg.sid }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg.payload = {
|
|
||||||
color: miDevicesUtils.computeColorValue(color.red, color.green, color.blue),
|
|
||||||
brightness: brightness
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.send(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
RED.nodes.registerType("mi-devices-actions gateway_light", XiaomiActionGatewayLight);
|
|
||||||
|
|
||||||
/*********************************************
|
|
||||||
Play a sound on the gateway
|
|
||||||
*********************************************/
|
|
||||||
function XiaomiActionGatewaySound(config) {
|
|
||||||
RED.nodes.createNode(this, config);
|
|
||||||
this.mid = config.mid;
|
|
||||||
this.volume = config.volume;
|
|
||||||
|
|
||||||
this.on('input', (msg) => {
|
|
||||||
msg.payload = {
|
|
||||||
cmd: "write",
|
|
||||||
data: {
|
|
||||||
mid: parseInt(msg.mid || this.mid),
|
|
||||||
volume: parseInt(msg.volume || this.volume),
|
|
||||||
sid: msg.sid
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.send(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
RED.nodes.registerType("mi-devices-actions gateway_sound", XiaomiActionGatewaySound);
|
|
||||||
|
|
||||||
/*********************************************
|
|
||||||
Stop playing a sound on the gateway
|
|
||||||
*********************************************/
|
|
||||||
function XiaomiActionGatewayStopSound(config) {
|
|
||||||
RED.nodes.createNode(this, config);
|
|
||||||
|
|
||||||
this.on('input', (msg) => {
|
|
||||||
msg.payload = {
|
|
||||||
cmd: "write",
|
|
||||||
data: { mid: 1000, sid: msg.sid }
|
|
||||||
};
|
|
||||||
this.send(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
RED.nodes.registerType("mi-devices-actions gateway_stop_sound", XiaomiActionGatewayStopSound);
|
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
Turn device on
|
Turn device on
|
||||||
*********************************************/
|
*********************************************/
|
||||||
|
|||||||
@@ -1,124 +0,0 @@
|
|||||||
<script type="text/javascript">
|
|
||||||
RED.nodes.registerType('xiaomi-all', {
|
|
||||||
category: 'xiaomi',
|
|
||||||
color: '#3FADB5',
|
|
||||||
defaults: {
|
|
||||||
gateway: {value:"", type:"xiaomi-configurator"},
|
|
||||||
name: {value: ""},
|
|
||||||
onlyModels: {value: []},
|
|
||||||
excludedSids: { value: []}
|
|
||||||
},
|
|
||||||
inputs: 1,
|
|
||||||
outputs: 1,
|
|
||||||
outputLabels: ["All devices"],
|
|
||||||
paletteLabel: "all",
|
|
||||||
icon: "mi-all.png",
|
|
||||||
label: function () {
|
|
||||||
return this.name || "xiaomi-all";
|
|
||||||
},
|
|
||||||
oneditprepare: function() {
|
|
||||||
var node = this;
|
|
||||||
|
|
||||||
function getOnlyModelsValue(input) {
|
|
||||||
var cleanOnlyModels = [];
|
|
||||||
input.forEach((value) => {
|
|
||||||
cleanOnlyModels = cleanOnlyModels.concat(value.split(','));
|
|
||||||
});
|
|
||||||
return cleanOnlyModels;
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeGateway(gateway, onlyModels, excludedSids) {
|
|
||||||
var configNodeID = gateway || $('#node-input-gateway').val();
|
|
||||||
if (configNodeID) {
|
|
||||||
var configNode = RED.nodes.node(configNodeID);
|
|
||||||
if(configNode) {
|
|
||||||
onlyModels = getOnlyModelsValue(onlyModels || $('#node-input-onlyModels').val() || []);
|
|
||||||
excludedSids = excludedSids || $('#node-input-excludedSids').val() || [];
|
|
||||||
$('#node-input-excludedSids').empty();
|
|
||||||
for (key in configNode.deviceList) {
|
|
||||||
var device = configNode.deviceList[key];
|
|
||||||
if (onlyModels.length == 0 || onlyModels.indexOf(device.model) >= 0) {
|
|
||||||
var option = $('<option value="' + device.sid + '">' + device.desc + '</option>');
|
|
||||||
if(excludedSids && excludedSids.indexOf(device.sid) >= 0) {
|
|
||||||
option.prop('selected', true);
|
|
||||||
}
|
|
||||||
$('#node-input-excludedSids').append(option);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changeGateway(this.gateway, this.onlyModels, this.excludedSids);
|
|
||||||
$("#node-input-gateway, #node-input-onlyModels").change(function () {
|
|
||||||
changeGateway();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
oneditsave: function() {
|
|
||||||
if(!$('#node-input-onlyModels').val()) {
|
|
||||||
this.onlyModels = [];
|
|
||||||
}
|
|
||||||
if(!$('#node-input-excludedSids').val()) {
|
|
||||||
this.excludedSids = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/x-red" data-template-name="xiaomi-all">
|
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-gateway"><i class="icon-tag"></i> Gateway</label>
|
|
||||||
<input type="text" id="node-input-gateway" placeholder="xiaomi gateway">
|
|
||||||
</div>
|
|
||||||
<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>
|
|
||||||
<hr />
|
|
||||||
<h5>Filters</h5>
|
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-onlyModels"><i class="icon-tag"></i> Only</label>
|
|
||||||
<select multiple id="node-input-onlyModels">
|
|
||||||
<option value="sensor_ht,weather.v1">Temperature/humidty</option>
|
|
||||||
<option value="motion">Motion</option>
|
|
||||||
<option value="switch,sensor_switch.aq2">Switches</option>
|
|
||||||
<option value="magnet,sensor_magnet.aq2">Contacts</option>
|
|
||||||
<option value="plug">Plugs</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-excludedSids"><i class="icon-tag"></i> Exclude</label>
|
|
||||||
<select multiple id="node-input-excludedSids" size=10></select>
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="xiaomi-all">
|
|
||||||
<p>All devices registred in the gateway, except gateway itself.</p>
|
|
||||||
|
|
||||||
<h3>Inputs</h3>
|
|
||||||
<dl class="message-properties">
|
|
||||||
<dt>payload
|
|
||||||
<span class="property-type">object</span>
|
|
||||||
</dt>
|
|
||||||
<dd>When use as an incoming filter node, <code>sid</code> and <code>model</code> are mandatory.</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h3>Outputs</h3>
|
|
||||||
<ol class="node-ports">
|
|
||||||
<li>Devices output
|
|
||||||
<dl class="message-properties">
|
|
||||||
<dt>payload <span class="property-type">array</span></dt>
|
|
||||||
<dd>Array of devices.</dd>
|
|
||||||
</dl>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<h4>Details</h4>
|
|
||||||
<p>Sample payload:</p>
|
|
||||||
<p><pre>[
|
|
||||||
{sid: "128d0901db1fa8", desc: "Door sensor" model: "magnet"},
|
|
||||||
{sid: "151d0401ab2491", desc: "Heat sensor", model: "sensor_ht"},
|
|
||||||
{sid: "658d030171427c", desc: "Button", model: "switch"}
|
|
||||||
]</pre>
|
|
||||||
</p>
|
|
||||||
</script>
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
module.exports = (RED) => {
|
|
||||||
function getOnlyModelsValue(input) {
|
|
||||||
var cleanOnlyModels = [];
|
|
||||||
input.forEach((value) => {
|
|
||||||
cleanOnlyModels = cleanOnlyModels.concat(value.split(','));
|
|
||||||
});
|
|
||||||
return cleanOnlyModels;
|
|
||||||
}
|
|
||||||
|
|
||||||
function XiaomiAllNode(config) {
|
|
||||||
RED.nodes.createNode(this, config);
|
|
||||||
this.gateway = RED.nodes.getNode(config.gateway);
|
|
||||||
this.onlyModels = getOnlyModelsValue(config.onlyModels || []);
|
|
||||||
this.excludedSids = config.excludedSids;
|
|
||||||
|
|
||||||
|
|
||||||
this.isDeviceValid = (device) => {
|
|
||||||
if((!this.onlyModels || this.onlyModels.length == 0) && (!this.excludedSids || this.excludedSids.length == 0)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Is excluded
|
|
||||||
if((this.excludedSids && this.excludedSids.length != 0) && this.excludedSids.indexOf(device.sid) >= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if((this.onlyModels && this.onlyModels.length != 0) && this.onlyModels.indexOf(device.model) >= 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.gateway) {
|
|
||||||
this.on('input', (msg) => {
|
|
||||||
// Filter input
|
|
||||||
if(msg.payload && msg.payload.model && msg.payload.sid) {
|
|
||||||
if(!this.isDeviceValid(msg.payload)) {
|
|
||||||
msg = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Prepare for request
|
|
||||||
else {
|
|
||||||
msg.payload = this.gateway.deviceList.filter((device) => this.isDeviceValid(device));
|
|
||||||
}
|
|
||||||
this.send(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RED.nodes.registerType("xiaomi-all", XiaomiAllNode);
|
|
||||||
}
|
|
||||||
@@ -39,7 +39,7 @@ export class Gateway extends events.EventEmitter {
|
|||||||
|
|
||||||
if (msg.isGetIdListAck()) {
|
if (msg.isGetIdListAck()) {
|
||||||
(<MessageData.GatewayMessageGetIdListData> msg.data).forEach((sid) => {
|
(<MessageData.GatewayMessageGetIdListData> msg.data).forEach((sid) => {
|
||||||
this.send({cmd: "read", sid: sid});
|
this.read(sid);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,17 @@ export class Gateway extends events.EventEmitter {
|
|||||||
return !!this._subdevices[sid];
|
return !!this._subdevices[sid];
|
||||||
}
|
}
|
||||||
|
|
||||||
setLight(brightness, rgb) {
|
getIdList() {
|
||||||
|
this.send({
|
||||||
|
cmd: "get_id_list",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
read(sid?: string) {
|
||||||
|
this.send({cmd: "read", sid: sid || this.sid});
|
||||||
|
}
|
||||||
|
|
||||||
|
setLight(brightness: number, rgb: { red: number, green: number, blue: number }) {
|
||||||
this.send({
|
this.send({
|
||||||
cmd: "write",
|
cmd: "write",
|
||||||
data: {
|
data: {
|
||||||
@@ -79,8 +89,15 @@ export class Gateway extends events.EventEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
playSound() {
|
playSound(musicId: number, volume: number) {
|
||||||
|
this.send({
|
||||||
|
cmd: "write",
|
||||||
|
data: {
|
||||||
|
mid: musicId,
|
||||||
|
volume: volume,
|
||||||
|
sid: this.sid
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
send(message: any) {
|
send(message: any) {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export class GatewayServer extends events.EventEmitter {
|
|||||||
if ((msg.isHeartbeat() || msg.isIam()) && msg.model === "gateway") {
|
if ((msg.isHeartbeat() || msg.isIam()) && msg.model === "gateway") {
|
||||||
if (!this._gateways[msg.sid]) {
|
if (!this._gateways[msg.sid]) {
|
||||||
this._gateways[msg.sid] = new Gateway(msg.sid, remote.address);
|
this._gateways[msg.sid] = new Gateway(msg.sid, remote.address);
|
||||||
this.sendToGateway(msg.sid, {cmd: "get_id_list"});
|
this._gateways[msg.sid].getIdList();
|
||||||
this.emit("gateway-online", msg.sid);
|
this.emit("gateway-online", msg.sid);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
import { Red, NodeProperties } from "node-red";
|
|
||||||
import { Constants } from "../constants";
|
|
||||||
|
|
||||||
export default (RED:Red) => {
|
|
||||||
class GatewayLight {
|
|
||||||
public color:string;
|
|
||||||
public brightness:number;
|
|
||||||
|
|
||||||
constructor(props:NodeProperties) {
|
|
||||||
RED.nodes.createNode(<any> this, props);
|
|
||||||
(<any> this).setListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected setListeners() {
|
|
||||||
(<any> this).on('input', (msg) => {
|
|
||||||
let color = msg.color || this.color;
|
|
||||||
let brightness = msg.brightness || this.brightness;
|
|
||||||
if(msg.sid) {
|
|
||||||
msg.payload = {
|
|
||||||
cmd: "write",
|
|
||||||
data: { rgb: 123, sid: msg.sid }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg.payload = {
|
|
||||||
brightness: brightness
|
|
||||||
};
|
|
||||||
}
|
|
||||||
(<any> this).send(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RED.nodes.registerType(`${Constants.NODES_PREFIX}-actions gateway_light`, <any> GatewayLight);
|
|
||||||
};
|
|
||||||
81
src/nodes/actions/GatewayPlaySound.ejs
Normal file
81
src/nodes/actions/GatewayPlaySound.ejs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<!-- The Gateway sound Node -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('<%= NODES_PREFIX %>-actions gateway_play_sound', {
|
||||||
|
category: 'xiaomi actions',
|
||||||
|
color: '#64C4CD',
|
||||||
|
defaults: {
|
||||||
|
name: {value: ""},
|
||||||
|
mid: {value: ""},
|
||||||
|
volume: {value: ""}
|
||||||
|
},
|
||||||
|
inputs: 1,
|
||||||
|
outputs: 1,
|
||||||
|
paletteLabel: "play sound",
|
||||||
|
icon: "mi-sound.png",
|
||||||
|
label: function () {
|
||||||
|
return this.name || "play sound";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="<%= NODES_PREFIX %>-actions gateway_play_sound">
|
||||||
|
<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-mid"><i class="icon-tag"></i> Sound</label>
|
||||||
|
<select id="node-input-mid">
|
||||||
|
<option value="0">Police car tone 1</option>
|
||||||
|
<option value="1">Police car tone 2</option>
|
||||||
|
<option value="2">Safety incident sound</option>
|
||||||
|
<option value="3">Missile countdown</option>
|
||||||
|
<option value="4">Ghost cry</option>
|
||||||
|
<option value="5">Sniper rifle</option>
|
||||||
|
<option value="6">Battle sound</option>
|
||||||
|
<option value="7">Air raid alarm</option>
|
||||||
|
<option value="8">Barking</option>
|
||||||
|
<option value="10">Doorbell tone</option>
|
||||||
|
<option value="11">Door knocking tone</option>
|
||||||
|
<option value="12">Funny tone</option>
|
||||||
|
<option value="13">Alarm clock tone</option>
|
||||||
|
<option value="20">MiMix</option>
|
||||||
|
<option value="21">Enthusisatic</option>
|
||||||
|
<option value="22">GuitarClassic</option>
|
||||||
|
<option value="23">IceWorldPiano</option>
|
||||||
|
<option value="24">LeisureTime</option>
|
||||||
|
<option value="25">ChildHood</option>
|
||||||
|
<option value="26">MorningStreamLet</option>
|
||||||
|
<option value="27">MusicBox</option>
|
||||||
|
<option value="28">Orange</option>
|
||||||
|
<option value="29">Thinker</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-volume"><i class="icon-tag"></i> Volume</label>
|
||||||
|
<input type="range" id="node-input-volume" min="0" max="100">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="<%= NODES_PREFIX %>-actions gateway_play_sound">
|
||||||
|
<p>Play a sound on the gateway.</p>
|
||||||
|
|
||||||
|
<h3>Inputs</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>mid
|
||||||
|
<span class="property-type">number</span>
|
||||||
|
</dt>
|
||||||
|
<dd>Music ID (user define sounds start from <code>1001</code>, <code>1000</code> means stop).</dd>
|
||||||
|
<dt>volume
|
||||||
|
<span class="property-type">number</span>
|
||||||
|
</dt>
|
||||||
|
<dd>Playing volume, between <code>0</code> and <code>100</code>.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3>Outputs</h3>
|
||||||
|
<ol class="node-ports">
|
||||||
|
<li>Message to connect to a gateway out node.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
</script>
|
||||||
31
src/nodes/actions/GatewayPlaySound.ts
Normal file
31
src/nodes/actions/GatewayPlaySound.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import {Red, NodeProperties} from "node-red";
|
||||||
|
import {Constants} from "../constants";
|
||||||
|
|
||||||
|
export default (RED: Red) => {
|
||||||
|
class GatewayPlaySound {
|
||||||
|
public mid: number;
|
||||||
|
public volume: number;
|
||||||
|
|
||||||
|
constructor(props: NodeProperties) {
|
||||||
|
RED.nodes.createNode(<any> this, props);
|
||||||
|
this.mid = parseInt((<any>props).mid);
|
||||||
|
this.volume = parseInt((<any>props).volume);
|
||||||
|
(<any> this).setListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected setListeners() {
|
||||||
|
(<any> this).on('input', (msg) => {
|
||||||
|
if (msg.sid) {
|
||||||
|
msg.payload = {
|
||||||
|
action: "playSound",
|
||||||
|
mid: msg.mid || this.mid,
|
||||||
|
volume: msg.volume || this.volume
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(<any> this).send(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType(`${Constants.NODES_PREFIX}-actions gateway_play_sound`, <any> GatewayPlaySound);
|
||||||
|
};
|
||||||
36
src/nodes/actions/GatewayStopSound.ejs
Normal file
36
src/nodes/actions/GatewayStopSound.ejs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<!-- The Gateway stop sound Node -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('<%= NODES_PREFIX %>-actions gateway_stop_sound', {
|
||||||
|
category: 'xiaomi actions',
|
||||||
|
color: '#64C4CD',
|
||||||
|
defaults: {
|
||||||
|
name: {value: ""}
|
||||||
|
},
|
||||||
|
inputs: 1,
|
||||||
|
outputs: 1,
|
||||||
|
paletteLabel: "stop sound",
|
||||||
|
icon: "mi-mute.png",
|
||||||
|
label: function () {
|
||||||
|
return this.name || "stop sound";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<script type="text/x-red" data-template-name="<%= NODES_PREFIX %>-actions gateway_stop_sound">
|
||||||
|
<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="<%= NODES_PREFIX %>-actions gateway_stop_sound">
|
||||||
|
<p>
|
||||||
|
Stop current playing sound on the gateway.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Outputs</h3>
|
||||||
|
<ol class="node-ports">
|
||||||
|
<li>Message to connect to a gateway out node.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
</script>
|
||||||
26
src/nodes/actions/GatewayStopSound.ts
Normal file
26
src/nodes/actions/GatewayStopSound.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import {Red, NodeProperties} from "node-red";
|
||||||
|
import {Constants} from "../constants";
|
||||||
|
|
||||||
|
export default (RED: Red) => {
|
||||||
|
class GatewayStopSound {
|
||||||
|
|
||||||
|
constructor(props: NodeProperties) {
|
||||||
|
RED.nodes.createNode(<any> this, props);
|
||||||
|
(<any> this).setListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected setListeners() {
|
||||||
|
(<any> this).on('input', (msg) => {
|
||||||
|
if (msg.sid) {
|
||||||
|
msg.payload = {
|
||||||
|
action: "playSound",
|
||||||
|
mid: 1000
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(<any> this).send(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType(`${Constants.NODES_PREFIX}-actions gateway_stop_sound`, <any> GatewayStopSound);
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<!-- The Gateway light Node -->
|
<!-- The Gateway light Node -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
RED.nodes.registerType('<%= NODES_PREFIX %>-actions gateway_light', {
|
RED.nodes.registerType('<%= NODES_PREFIX %>-actions light', {
|
||||||
category: 'xiaomi actions',
|
category: 'xiaomi actions',
|
||||||
color: '#64C4CD',
|
color: '#64C4CD',
|
||||||
defaults: {
|
defaults: {
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/x-red" data-template-name="<%= NODES_PREFIX %>-actions gateway_light">
|
<script type="text/x-red" data-template-name="<%= NODES_PREFIX %>-actions light">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
<input type="text" id="node-input-name" placeholder="Name">
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="<%= NODES_PREFIX %>-actions gateway_light">
|
<script type="text/x-red" data-help-name="<%= NODES_PREFIX %>-actions light">
|
||||||
<p>Change the light of the gateway.</p>
|
<p>Change the light of the gateway.</p>
|
||||||
|
|
||||||
<h3>Inputs</h3>
|
<h3>Inputs</h3>
|
||||||
31
src/nodes/actions/Light.ts
Normal file
31
src/nodes/actions/Light.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import {Red, NodeProperties} from "node-red";
|
||||||
|
import {Constants} from "../constants";
|
||||||
|
|
||||||
|
export default (RED: Red) => {
|
||||||
|
class Light {
|
||||||
|
public color: string;
|
||||||
|
public brightness: number;
|
||||||
|
|
||||||
|
constructor(props: NodeProperties) {
|
||||||
|
RED.nodes.createNode(<any> this, props);
|
||||||
|
this.color = (<any>props).color;
|
||||||
|
this.brightness = (<any>props).brightness;
|
||||||
|
(<any> this).setListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected setListeners() {
|
||||||
|
(<any> this).on('input', (msg) => {
|
||||||
|
if (msg.sid) {
|
||||||
|
msg.payload = {
|
||||||
|
action: "setLight",
|
||||||
|
color: msg.color || this.color,
|
||||||
|
brightness: msg.brightness || this.brightness
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(<any> this).send(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType(`${Constants.NODES_PREFIX}-actions light`, <any> Light);
|
||||||
|
};
|
||||||
@@ -30,4 +30,6 @@
|
|||||||
docTitle: "Virtual double click for switch."
|
docTitle: "Virtual double click for switch."
|
||||||
}) %>
|
}) %>
|
||||||
|
|
||||||
<%- include('./GatewayLight', {}) %>
|
<%- include('./Light', {}) %>
|
||||||
|
<%- include('./GatewayPlaySound', {}) %>
|
||||||
|
<%- include('./GatewayStopSound', {}) %>
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Red, NodeProperties } from "node-red";
|
import {Red} from "node-red";
|
||||||
import * as LumiAqara from 'lumi-aqara';
|
|
||||||
|
|
||||||
import {default as ReadAction} from './ReadAction';
|
import {default as ReadAction} from './ReadAction';
|
||||||
import {default as WriteAction} from './WriteAction';
|
import {default as WriteAction} from './WriteAction';
|
||||||
import {default as GatewayLight} from './GatewayLight';
|
import {default as Light} from './Light';
|
||||||
|
import {default as GatewayPlaySound} from './GatewayPlaySound';
|
||||||
|
import {default as GatewayStopSound} from './GatewayStopSound';
|
||||||
|
|
||||||
export = (RED:Red) => {
|
export = (RED: Red) => {
|
||||||
GatewayLight(RED);
|
|
||||||
["read", "get_id_list"].forEach((action) => {
|
["read", "get_id_list"].forEach((action) => {
|
||||||
ReadAction(RED, action);
|
ReadAction(RED, action);
|
||||||
});
|
});
|
||||||
@@ -14,4 +14,7 @@ export = (RED:Red) => {
|
|||||||
["click", "double_click"].forEach((action) => {
|
["click", "double_click"].forEach((action) => {
|
||||||
WriteAction(RED, action);
|
WriteAction(RED, action);
|
||||||
});
|
});
|
||||||
|
Light(RED);
|
||||||
|
GatewayPlaySound(RED);
|
||||||
|
GatewayStopSound(RED);
|
||||||
};
|
};
|
||||||
@@ -4,32 +4,43 @@ import { Constants } from "../constants";
|
|||||||
|
|
||||||
export interface IGatewayNode extends Node {
|
export interface IGatewayNode extends Node {
|
||||||
gatewayConf:any;
|
gatewayConf:any;
|
||||||
gateway: LumiAqara.Gateway;
|
|
||||||
|
|
||||||
setGateway(gateway:LumiAqara.Gateway);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (RED:Red) => {
|
export default (RED:Red) => {
|
||||||
class Gateway {
|
class Gateway {
|
||||||
protected gatewayConf: any;
|
protected gatewayConf: any;
|
||||||
protected gateway: LumiAqara.Gateway;
|
|
||||||
|
|
||||||
constructor(props:NodeProperties){
|
constructor(props:NodeProperties){
|
||||||
RED.nodes.createNode(<any> this, props);
|
RED.nodes.createNode(<any> this, props);
|
||||||
this.gatewayConf = RED.nodes.getNode((<any> props).gateway);
|
this.gatewayConf = RED.nodes.getNode((<any> props).gateway);
|
||||||
this.gateway = null;
|
|
||||||
|
|
||||||
(<any> this).status({fill:"red", shape:"ring", text: "offline"});
|
(<any>this).status({fill: "red", shape: "ring", text: "offline"});
|
||||||
|
|
||||||
|
if (this.gatewayConf.gateway) {
|
||||||
|
this.gatewayOnline();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gatewayConf.on('gateway-online', () => this.gatewayOnline());
|
||||||
|
this.gatewayConf.on('gateway-offline', () => this.gatewayOffline());
|
||||||
|
|
||||||
this.setMessageListener();
|
this.setMessageListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected gatewayOnline() {
|
||||||
|
(<any>this).status({fill: "blue", shape: "dot", text: "online"});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected gatewayOffline() {
|
||||||
|
(<any>this).status({fill: "red", shape: "ring", text: "offline"});
|
||||||
|
}
|
||||||
|
|
||||||
protected setMessageListener() {
|
protected setMessageListener() {
|
||||||
(<any> this).on('input', (msg) => {
|
(<any> this).on('input', (msg) => {
|
||||||
if (this.gateway) {
|
if (this.gatewayConf.gateway) {
|
||||||
var payload = msg.payload;
|
var payload = msg.payload;
|
||||||
|
|
||||||
// Input from gateway
|
// Input from gateway
|
||||||
if(payload.sid && payload.sid == this.gateway.sid) {
|
if(payload.sid && payload.sid == this.gatewayConf.gateway.sid) {
|
||||||
if(payload.data.rgb) {
|
if(payload.data.rgb) {
|
||||||
/*var decomposed = miDevicesUtils.computeColor(payload.data.rgb);
|
/*var decomposed = miDevicesUtils.computeColor(payload.data.rgb);
|
||||||
payload.data.brightness = decomposed.brightness;
|
payload.data.brightness = decomposed.brightness;
|
||||||
@@ -39,23 +50,13 @@ export default (RED:Red) => {
|
|||||||
}
|
}
|
||||||
// Prepare for request
|
// Prepare for request
|
||||||
else {
|
else {
|
||||||
msg.sid = this.gateway.sid;
|
msg.sid = this.gatewayConf.gateway.sid;
|
||||||
|
msg.gateway = this.gatewayConf.gateway;
|
||||||
(<any> this).send(msg);
|
(<any> this).send(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setGateway(gateway:LumiAqara.Gateway) {
|
|
||||||
this.gateway = gateway;
|
|
||||||
this.gateway.setPassword(this.gatewayConf.password);
|
|
||||||
(<any> this).status({fill:"blue", shape:"dot", text: "online"});
|
|
||||||
|
|
||||||
this.gateway.on('offline', () => {
|
|
||||||
this.gateway = null;
|
|
||||||
(<any> this).status({fill:"red", shape:"ring", text: "offline"});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RED.nodes.registerType(`${Constants.NODES_PREFIX}-gateway`, <any> Gateway);
|
RED.nodes.registerType(`${Constants.NODES_PREFIX}-gateway`, <any> Gateway);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {Red, NodeProperties} from "node-red";
|
import {Red, NodeProperties} from "node-red";
|
||||||
import {Constants} from "../constants";
|
import {Constants} from "../constants";
|
||||||
|
import {GatewayServer} from "../../devices/GatewayServer";
|
||||||
|
|
||||||
export default (RED: Red) => {
|
export default (RED: Red) => {
|
||||||
class GatewayOut {
|
class GatewayOut {
|
||||||
@@ -11,7 +12,22 @@ export default (RED: Red) => {
|
|||||||
protected setMessageListener() {
|
protected setMessageListener() {
|
||||||
(<any> this).on("input", (msg) => {
|
(<any> this).on("input", (msg) => {
|
||||||
if (msg.hasOwnProperty("payload") && msg.hasOwnProperty("gateway")) {
|
if (msg.hasOwnProperty("payload") && msg.hasOwnProperty("gateway")) {
|
||||||
msg.gateway.gateway.send(msg);
|
let gateway = GatewayServer.getInstance().getGateway(msg.gateway.sid);
|
||||||
|
if(gateway) {
|
||||||
|
if (msg.payload.cmd) {
|
||||||
|
gateway.send(msg);
|
||||||
|
}
|
||||||
|
else if (msg.payload.action) {
|
||||||
|
switch (msg.payload.action) {
|
||||||
|
case 'setLight':
|
||||||
|
gateway.setLight(msg.payload.brightness, msg.payload.color);
|
||||||
|
break;
|
||||||
|
case 'playSound':
|
||||||
|
gateway.playSound(msg.payload.mid, msg.payload.volume);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
94
src/utils.js
94
src/utils.js
@@ -1,94 +0,0 @@
|
|||||||
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) {
|
|
||||||
/*
|
|
||||||
When full, CR2032 batteries are between 3 and 3.4V
|
|
||||||
http://farnell.com/datasheets/1496885.pdf
|
|
||||||
*/
|
|
||||||
return Math.min(Math.round((voltage - 2200) / 10), 100);
|
|
||||||
},
|
|
||||||
setStatus: function(node, data) {
|
|
||||||
if (data.voltage) {
|
|
||||||
var batteryPercent = Math.min(Math.round((data.voltage - 2200) / 14), 100);
|
|
||||||
var status = {
|
|
||||||
fill: "green", shape: "dot",
|
|
||||||
text: "battery - " + batteryPercent + "%"
|
|
||||||
};
|
|
||||||
|
|
||||||
if (data.voltage < 2500) {
|
|
||||||
status.color = "red";
|
|
||||||
} else if (data.voltage < 2900) {
|
|
||||||
status.color = "yellow";
|
|
||||||
}
|
|
||||||
node.status(status);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
prepareFullDataOutput: function(payload) {
|
|
||||||
if(payload.data.voltage) {
|
|
||||||
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;
|
|
||||||
},
|
|
||||||
computeColorValue: function (red, green, blue, brightness) {
|
|
||||||
return (brightness !== undefined ? 256*256*256*brightness : 0) + (256*256*red) + (256*green) + blue;
|
|
||||||
},
|
|
||||||
computeColor: function (rgb) {
|
|
||||||
var blue = rgb % 256;
|
|
||||||
rgb = Math.max(rgb - blue, 0);
|
|
||||||
|
|
||||||
var green = rgb % (256 * 256);
|
|
||||||
rgb = Math.max(rgb - green, 0);
|
|
||||||
green /= 256;
|
|
||||||
|
|
||||||
var red = rgb % (256 * 256 * 256);
|
|
||||||
rgb = Math.max(rgb - red, 0);
|
|
||||||
red /= 256 * 256;
|
|
||||||
|
|
||||||
var brightness = rgb / (256*256*256);
|
|
||||||
|
|
||||||
return {
|
|
||||||
brightness: brightness,
|
|
||||||
color: { red: red, green: green, blue: blue }
|
|
||||||
};
|
|
||||||
},
|
|
||||||
defaultNode: function(RED, config, node) {
|
|
||||||
RED.nodes.createNode(node, config);
|
|
||||||
node.gateway = RED.nodes.getNode(config.gateway);
|
|
||||||
node.sid = config.sid;
|
|
||||||
|
|
||||||
node.status({fill:"grey", shape:"ring", text:"battery - na"});
|
|
||||||
|
|
||||||
if (node.gateway) {
|
|
||||||
node.on('input', (msg) => {
|
|
||||||
let payload = msg.payload;
|
|
||||||
|
|
||||||
// Input from gateway
|
|
||||||
if (payload.sid) {
|
|
||||||
if (payload.sid == node.sid) {
|
|
||||||
this.setStatus(node, payload.data);
|
|
||||||
node.send([msg]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Prepare for request
|
|
||||||
else {
|
|
||||||
this.prepareForGatewayRequest(node, msg);
|
|
||||||
node.send(msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user