@evilbunny/node-red-contrib-zigbee2mqtt 0.0.0 → 3.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +62 -43
- package/api.html +22 -0
- package/api.js +176 -0
- package/examples/Basic usage.json +316 -0
- package/icons/homekit-logo.png +0 -0
- package/icons/icon-color.png +0 -0
- package/icons/icon.png +0 -0
- package/icons/icon.pxd/QuickLook/Icon.tiff +0 -0
- package/icons/icon.pxd/QuickLook/Thumbnail.tiff +0 -0
- package/icons/icon.pxd/data/15644CBE-CB2C-4054-AAB1-064FBC3F72DB +0 -0
- package/icons/icon.pxd/data/2D35D9CD-316A-4D5B-A1D9-1C09DB37FAC9 +0 -0
- package/icons/icon.pxd/data/BF7855C2-D304-4F39-84A3-141656F5E18C +0 -0
- package/icons/icon.pxd/data/selection/meta +33 -0
- package/icons/icon.pxd/data/selection/shapeSelection/meta +12 -0
- package/icons/icon.pxd/data/selection/shapeSelection/path +0 -0
- package/icons/icon.pxd/data/selectionForContentTransform/meta +33 -0
- package/icons/icon.pxd/data/selectionForContentTransform/shapeSelection/meta +12 -0
- package/icons/icon.pxd/data/selectionForContentTransform/shapeSelection/path +0 -0
- package/icons/icon.pxd/metadata.info +0 -0
- package/nodes/bridge.html +523 -0
- package/nodes/bridge.js +124 -0
- package/nodes/get.html +106 -0
- package/nodes/get.js +47 -0
- package/nodes/in.html +125 -0
- package/nodes/in.js +123 -0
- package/nodes/locales/en-US/bridge.html +23 -0
- package/nodes/locales/en-US/bridge.json +84 -0
- package/nodes/locales/en-US/get.html +19 -0
- package/nodes/locales/en-US/get.json +23 -0
- package/nodes/locales/en-US/in.html +24 -0
- package/nodes/locales/en-US/in.json +43 -0
- package/nodes/locales/en-US/out.html +24 -0
- package/nodes/locales/en-US/out.json +31 -0
- package/nodes/locales/en-US/server.html +12 -0
- package/nodes/locales/en-US/server.json +36 -0
- package/nodes/locales/sk-SK/bridge.html +23 -0
- package/nodes/locales/sk-SK/bridge.json +84 -0
- package/nodes/locales/sk-SK/get.html +18 -0
- package/nodes/locales/sk-SK/get.json +21 -0
- package/nodes/locales/sk-SK/in.html +23 -0
- package/nodes/locales/sk-SK/in.json +43 -0
- package/nodes/locales/sk-SK/out.html +23 -0
- package/nodes/locales/sk-SK/out.json +21 -0
- package/nodes/locales/sk-SK/server.html +12 -0
- package/nodes/locales/sk-SK/server.json +36 -0
- package/nodes/out.html +300 -0
- package/nodes/out.js +361 -0
- package/nodes/server.html +96 -0
- package/nodes/server.js +854 -0
- package/package.json +42 -6
- package/readme/1.png +0 -0
- package/readme/2.png +0 -0
- package/readme/3.png +0 -0
- package/readme/4.png +0 -0
- package/readme/5.png +0 -0
- package/readme/options.gif +0 -0
- package/resources/Zigbee2mqttHelper.js +470 -0
- package/resources/css/common.css +56 -0
- package/resources/css/multiple-select.css +183 -0
- package/resources/js/multiple-select.js +10 -0
- package/resources/js/multiple-select.min.js +10 -0
- package/resources/js/node-red-contrib-zigbee2mqtt-helpers.js +416 -0
- package/resources/js/zigbee2mqtt-helpers.js +416 -0
- package/resources/tokeninput/jquery.tokeninput.js +861 -0
- package/resources/tokeninput/token-input-facebook.css +134 -0
- package/resources/tokeninput/token-input-mac.css +204 -0
- package/resources/tokeninput/token-input.css +113 -0
package/nodes/bridge.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const Zigbee2mqttHelper = require('../resources/Zigbee2mqttHelper.js');
|
|
2
|
+
|
|
3
|
+
module.exports = function(RED) {
|
|
4
|
+
|
|
5
|
+
class Zigbee2mqttNodeBridge {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
|
|
8
|
+
RED.nodes.createNode(this, config);
|
|
9
|
+
|
|
10
|
+
let node = this;
|
|
11
|
+
node.config = config;
|
|
12
|
+
node.cleanTimer = null;
|
|
13
|
+
node.is_subscribed = false;
|
|
14
|
+
node.server = RED.nodes.getNode(node.config.server);
|
|
15
|
+
|
|
16
|
+
if (node.server) {
|
|
17
|
+
node.listener_onMQTTConnect = function() { node.onMQTTConnect(); }
|
|
18
|
+
node.server.on('onMQTTConnect', node.listener_onMQTTConnect);
|
|
19
|
+
|
|
20
|
+
node.listener_onMQTTMessageBridge = function(data) { node.onMQTTMessageBridge(data); }
|
|
21
|
+
node.server.on('onMQTTMessageBridge', node.listener_onMQTTMessageBridge);
|
|
22
|
+
|
|
23
|
+
node.on('close', () => node.onClose());
|
|
24
|
+
|
|
25
|
+
if (typeof(node.server.mqtt) === 'object') {
|
|
26
|
+
node.onMQTTConnect();
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
node.status({
|
|
30
|
+
fill: "red",
|
|
31
|
+
shape: "dot",
|
|
32
|
+
text: "@evilbunny/node-red-contrib-zigbee2mqtt/bridge:status.no_server"
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (node.server) {
|
|
37
|
+
node.on('input', function (message_in) {
|
|
38
|
+
node.log('Published to mqtt topic: ' + message_in.topic + ' Payload: ' + JSON.stringify(message_in.payload));
|
|
39
|
+
node.server.mqtt.publish(message_in.topic, JSON.stringify(message_in.payload));
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
} else {
|
|
43
|
+
node.status({
|
|
44
|
+
fill: "red",
|
|
45
|
+
shape: "dot",
|
|
46
|
+
text: "@evilbunny/node-red-contrib-zigbee2mqtt/bridge:status.no_server"
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
onClose() {
|
|
52
|
+
let node = this;
|
|
53
|
+
node.setNodeStatus();
|
|
54
|
+
|
|
55
|
+
//remove listeners
|
|
56
|
+
if (node.listener_onMQTTConnect) {
|
|
57
|
+
node.server.removeListener('onMQTTConnect', node.listener_onMQTTConnect);
|
|
58
|
+
}
|
|
59
|
+
if (node.listener_onMQTTMessageBridge) {
|
|
60
|
+
node.server.removeListener("onMQTTMessageBridge", node.listener_onMQTTMessageBridge);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
onMQTTConnect() {
|
|
65
|
+
let node = this;
|
|
66
|
+
node.setNodeStatus();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
setNodeStatus() {
|
|
70
|
+
let node = this;
|
|
71
|
+
|
|
72
|
+
if (node.server.bridge_info && node.server.bridge_info.permit_join && node.server.bridge_state) {
|
|
73
|
+
node.status({
|
|
74
|
+
fill: "yellow",
|
|
75
|
+
shape: "ring",
|
|
76
|
+
text: "@evilbunny/node-red-contrib-zigbee2mqtt/bridge:status.searching"
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
let text = node.server.bridge_state?RED._("@evilbunny/node-red-contrib-zigbee2mqtt/bridge:status.online"):RED._("@evilbunny/node-red-contrib-zigbee2mqtt/bridge:status.offline");
|
|
80
|
+
if (node.server.bridge_info && "log_level" in node.server.bridge_info) {
|
|
81
|
+
text += ' (log: '+node.server.bridge_info.log_level+')';
|
|
82
|
+
}
|
|
83
|
+
node.status({
|
|
84
|
+
fill: node.server.bridge_state?"green":"red",
|
|
85
|
+
shape: "dot",
|
|
86
|
+
text: text
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
onMQTTMessageBridge(data) {
|
|
92
|
+
let node = this;
|
|
93
|
+
let payload = Zigbee2mqttHelper.isJson(data.payload)?JSON.parse(data.payload):data.payload;
|
|
94
|
+
|
|
95
|
+
if (node.server.getTopic('/bridge/state') === data.topic) {
|
|
96
|
+
node.setNodeStatus();
|
|
97
|
+
} else if (node.server.getTopic('/bridge/info') === data.topic) {
|
|
98
|
+
if (payload.permit_join != (node.status.fill === 'yellow')) {
|
|
99
|
+
node.setNodeStatus();
|
|
100
|
+
}
|
|
101
|
+
} else if (node.server.getTopic('/bridge/event') === data.topic) {
|
|
102
|
+
node.status({
|
|
103
|
+
fill: "yellow",
|
|
104
|
+
shape: "ring",
|
|
105
|
+
text: payload.type
|
|
106
|
+
});
|
|
107
|
+
clearTimeout(node.cleanTimer);
|
|
108
|
+
node.cleanTimer = setTimeout(function(){
|
|
109
|
+
node.setNodeStatus();
|
|
110
|
+
}, 10000);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
node.send({
|
|
114
|
+
payload: payload,
|
|
115
|
+
topic: data.topic
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
RED.nodes.registerType('zigbee2mqtt-eb-bridge', Zigbee2mqttNodeBridge);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
package/nodes/get.html
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<script type="text/x-red" data-template-name="zigbee2mqtt-eb-get">
|
|
2
|
+
<link rel="stylesheet" href="resources/@evilbunny/node-red-contrib-zigbee2mqtt/css/multiple-select.css" type="text/css" />
|
|
3
|
+
<link rel="stylesheet" href="resources/@evilbunny/node-red-contrib-zigbee2mqtt/css/common.css" type="text/css" />
|
|
4
|
+
|
|
5
|
+
<div class="form-row">
|
|
6
|
+
<label for="node-input-name" class="l-width"><i class="fa fa-bookmark"></i> <span data-i18n="label.name"></span></label>
|
|
7
|
+
<input type="text" id="node-input-name" data-i18n="[placeholder]placeholder.name">
|
|
8
|
+
</div>
|
|
9
|
+
<div class="form-row" style="display:none;">
|
|
10
|
+
<label for="node-input-friendly_name" class="l-width"><i class="fa fa-bookmark"></i> <span data-i18n="label.friendly_name"></span></label>
|
|
11
|
+
<input type="text" id="node-input-friendly_name" data-i18n="[placeholder]placeholder.friendly_name">
|
|
12
|
+
</div>
|
|
13
|
+
<div class="form-row">
|
|
14
|
+
<label for="node-input-server" class="l-width"><i class="fa fa-globe"></i> <span data-i18n="label.server"></span></label>
|
|
15
|
+
<input type="text" id="node-input-server">
|
|
16
|
+
</div>
|
|
17
|
+
<div class="form-row">
|
|
18
|
+
<label for="node-input-device_id" class="l-width"><i class="fa fa-crosshairs"></i> <span data-i18n="label.topic"></span></label>
|
|
19
|
+
<select id="node-input-device_id" class="s-width" multiple="multiple"></select>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="form-row">
|
|
22
|
+
<label for="node-input-state" class="l-width"><i class="fa fa-tag"></i> <span data-i18n="label.state"></span></label>
|
|
23
|
+
<select id="node-input-state" class="s-width" multiple="multiple" data-i18n="[placeholder]multiselect.complete_payload"></select>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="form-row">
|
|
26
|
+
<label for="force-refresh" class="l-width"><i class="fa fa-refresh"></i> <span data-i18n="label.refresh"></span></label>
|
|
27
|
+
<a class="red-ui-button s-width" id="force-refresh" name="force-refresh"><span data-i18n="label.refresh_devices_list"></span></a>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="form-row">
|
|
30
|
+
<label for='node-input-enableMultiple' class="l-width"><i class='fa fa-filter'></i> <span data-i18n="label.enable_multiple"></span></label>
|
|
31
|
+
<input type="checkbox" id="node-input-enableMultiple" style="display: inline-block; width: auto; vertical-align: top;"> <span data-i18n="label.enable_mu>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<script type='text/javascript'>
|
|
39
|
+
RED.nodes.registerType('zigbee2mqtt-eb-get', {
|
|
40
|
+
category: 'ZigBee2MQTT',
|
|
41
|
+
color: '#FDBF48',
|
|
42
|
+
defaults: {
|
|
43
|
+
name: {
|
|
44
|
+
value: ''
|
|
45
|
+
},
|
|
46
|
+
server: {
|
|
47
|
+
type: 'zigbee2mqtt-eb-server',
|
|
48
|
+
required: true
|
|
49
|
+
},
|
|
50
|
+
friendly_name: {
|
|
51
|
+
value: '',
|
|
52
|
+
required: false
|
|
53
|
+
},
|
|
54
|
+
device_id: {
|
|
55
|
+
value: null,
|
|
56
|
+
required: false
|
|
57
|
+
},
|
|
58
|
+
state: {
|
|
59
|
+
value: []
|
|
60
|
+
},
|
|
61
|
+
enableMultiple: {
|
|
62
|
+
value: false,
|
|
63
|
+
required: true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
inputs: 1,
|
|
67
|
+
outputs: 1,
|
|
68
|
+
outputLabels: ["value"],
|
|
69
|
+
paletteLabel: 'get',
|
|
70
|
+
icon: "icon.png",
|
|
71
|
+
label: function () {
|
|
72
|
+
var label = 'z2m-get';
|
|
73
|
+
|
|
74
|
+
if (this.name) {
|
|
75
|
+
label = this.name;
|
|
76
|
+
} else if (typeof(this.friendly_name) == 'string' && this.friendly_name.length) {
|
|
77
|
+
label = this.friendly_name;
|
|
78
|
+
} else if (typeof(this.device_id) == 'string') {
|
|
79
|
+
label = this.device_id;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return label;
|
|
83
|
+
},
|
|
84
|
+
oneditprepare: function () {
|
|
85
|
+
let node = this;
|
|
86
|
+
|
|
87
|
+
setTimeout(()=>{
|
|
88
|
+
new Zigbee2MqttEditor(node, {
|
|
89
|
+
'allow_empty': true
|
|
90
|
+
}).build();
|
|
91
|
+
}, 100); //need timeout to load server node
|
|
92
|
+
},
|
|
93
|
+
oneditsave: function () {
|
|
94
|
+
//convert array for string if single mode
|
|
95
|
+
if (!$('#node-input-enableMultiple').is(':checked')) {
|
|
96
|
+
let device_id = $('#node-input-device_id').multipleSelect('getSelects', 'value');
|
|
97
|
+
this.device_id = device_id.length ? device_id[0] : null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// state/attribute select is now multi-select — always store as an array
|
|
101
|
+
let state = $('#node-input-state').multipleSelect('getSelects', 'value');
|
|
102
|
+
this.state = state || [];
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
</script>
|
|
106
|
+
|
package/nodes/get.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module.exports = function(RED) {
|
|
2
|
+
class Zigbee2mqttNodeGet {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
RED.nodes.createNode(this, config);
|
|
5
|
+
|
|
6
|
+
let node = this;
|
|
7
|
+
node.config = config;
|
|
8
|
+
node.cleanTimer = null;
|
|
9
|
+
node.last_successful_status = {};
|
|
10
|
+
node.server = RED.nodes.getNode(node.config.server);
|
|
11
|
+
node.status({});
|
|
12
|
+
if (node.server) {
|
|
13
|
+
node.on('input', function(message_in) {
|
|
14
|
+
|
|
15
|
+
let key = node.config.device_id;
|
|
16
|
+
if ((!key || key === 'msg.topic') && message_in.topic) {
|
|
17
|
+
key = message_in.topic;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
node.server.nodeSend(node, {
|
|
21
|
+
'msg': message_in,
|
|
22
|
+
'key': key,
|
|
23
|
+
'state': node.config.state,
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
} else {
|
|
28
|
+
node.status({
|
|
29
|
+
fill: 'red',
|
|
30
|
+
shape: 'dot',
|
|
31
|
+
text: '@evilbunny/node-red-contrib-zigbee2mqtt/server:status.no_server',
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setSuccessfulStatus(obj) {
|
|
37
|
+
this.status(obj);
|
|
38
|
+
this.last_successful_status = obj;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
RED.nodes.registerType('zigbee2mqtt-eb-get', Zigbee2mqttNodeGet);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
package/nodes/in.html
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<script type="text/x-red" data-template-name="zigbee2mqtt-eb-in">
|
|
2
|
+
<link rel="stylesheet" href="resources/@evilbunny/node-red-contrib-zigbee2mqtt/css/multiple-select.css" type="text/css" />
|
|
3
|
+
<link rel="stylesheet" href="resources/@evilbunny/node-red-contrib-zigbee2mqtt/css/common.css" type="text/css" />
|
|
4
|
+
|
|
5
|
+
<div class="form-row">
|
|
6
|
+
<label for="node-input-name" class="l-width"><i class="fa fa-bookmark"></i> <span data-i18n="label.name"></span></label>
|
|
7
|
+
<input type="text" id="node-input-name" data-i18n="[placeholder]placeholder.name">
|
|
8
|
+
</div>
|
|
9
|
+
<div class="form-row" style="display:none;">
|
|
10
|
+
<label for="node-input-friendly_name" class="l-width"><i class="fa fa-bookmark"></i> <span data-i18n="label.friendly_name"></span></label>
|
|
11
|
+
<input type="text" id="node-input-friendly_name" data-i18n="[placeholder]placeholder.friendly_name">
|
|
12
|
+
</div>
|
|
13
|
+
<div class="form-row">
|
|
14
|
+
<label for="node-input-server" class="l-width"><i class="fa fa-globe"></i> <span data-i18n="label.server"></span></label>
|
|
15
|
+
<input type="text" id="node-input-server">
|
|
16
|
+
</div>
|
|
17
|
+
<div class="form-row">
|
|
18
|
+
<label for="node-input-device_id" class="l-width"><i class="fa fa-crosshairs"></i> <span data-i18n="label.topic"></span></label>
|
|
19
|
+
<select id="node-input-device_id" class="s-width" multiple="multiple"></select>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="form-row">
|
|
22
|
+
<label for="node-input-state" class="l-width"><i class="fa fa-tag"></i> <span data-i18n="label.state"></span></label>
|
|
23
|
+
<select id="node-input-state" class="s-width" data-i18n="[placeholder]multiselect.complete_payload"></select>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="form-row">
|
|
26
|
+
<label for="force-refresh" class="l-width"><i class="fa fa-refresh"></i> <span data-i18n="label.refresh"></span></label>
|
|
27
|
+
<a class="red-ui-button s-width" id="force-refresh" name="force-refresh"><span data-i18n="label.refresh_devices_list"></span></a>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="form-row">
|
|
30
|
+
<label for='node-input-enableMultiple' class="l-width"><i class='fa fa-filter'></i> <span data-i18n="label.enable_multiple"></span></label>
|
|
31
|
+
<input type="checkbox" id="node-input-enableMultiple" style="display: inline-block; width: auto; vertical-align: top;"> <span data-i18n="label.enable_multiple_help"></span></input>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="form-row">
|
|
34
|
+
<label for='node-input-outputAtStartup' class="l-width"><i class='fa fa-share-square'></i> <span data-i18n="label.start_output"></span></label>
|
|
35
|
+
<input type="checkbox" id="node-input-outputAtStartup" checked="checked" style="display: inline-block; width: auto; vertical-align: top;"> <span data-i18n="label.start_output_help"></span></input>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="form-row">
|
|
38
|
+
<label for='node-input-filterChanges' class="l-width"><i class='fa fa-share-square'></i> <span data-i18n="label.filter_changes"></span></label>
|
|
39
|
+
<input type="checkbox" id="node-input-filterChanges" checked="checked" style="display: inline-block; width: auto; vertical-align: top;"> <span data-i18n="label.filter_changes_help"></span></input>
|
|
40
|
+
</div>
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<script type='text/javascript'>
|
|
44
|
+
RED.nodes.registerType('zigbee2mqtt-eb-in', {
|
|
45
|
+
category: 'ZigBee2MQTT',
|
|
46
|
+
color: '#FDBF48',
|
|
47
|
+
defaults: {
|
|
48
|
+
name: {
|
|
49
|
+
value: ""
|
|
50
|
+
},
|
|
51
|
+
server: {
|
|
52
|
+
type: "zigbee2mqtt-eb-server",
|
|
53
|
+
required: true
|
|
54
|
+
},
|
|
55
|
+
friendly_name: {
|
|
56
|
+
value: "",
|
|
57
|
+
required: false
|
|
58
|
+
},
|
|
59
|
+
device_id: {
|
|
60
|
+
value: null,
|
|
61
|
+
required: true
|
|
62
|
+
},
|
|
63
|
+
state: {
|
|
64
|
+
value: null
|
|
65
|
+
},
|
|
66
|
+
outputAtStartup: {
|
|
67
|
+
value: true,
|
|
68
|
+
required: true
|
|
69
|
+
},
|
|
70
|
+
filterChanges: {
|
|
71
|
+
value: false,
|
|
72
|
+
required: true
|
|
73
|
+
},
|
|
74
|
+
enableMultiple: {
|
|
75
|
+
value: false,
|
|
76
|
+
required: true
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
inputs: 0,
|
|
80
|
+
outputs: 1,
|
|
81
|
+
outputLabels: ["value"],
|
|
82
|
+
paletteLabel: 'in',
|
|
83
|
+
icon: "icon.png",
|
|
84
|
+
label: function () {
|
|
85
|
+
var label = 'z2m-input';
|
|
86
|
+
|
|
87
|
+
if (this.name) {
|
|
88
|
+
label = this.name;
|
|
89
|
+
} else if (typeof(this.friendly_name) == 'string' && this.friendly_name.length) {
|
|
90
|
+
label = this.friendly_name;
|
|
91
|
+
} else if (typeof(this.device_id) == 'string') {
|
|
92
|
+
label = this.device_id;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return label;
|
|
96
|
+
},
|
|
97
|
+
oneditprepare: function () {
|
|
98
|
+
let node = this;
|
|
99
|
+
|
|
100
|
+
setTimeout(()=>{
|
|
101
|
+
new Zigbee2MqttEditor(node).build();
|
|
102
|
+
}, 100); //need timeout to load server node
|
|
103
|
+
},
|
|
104
|
+
oneditsave: function () {
|
|
105
|
+
//convert array for string if single mode
|
|
106
|
+
if (!$('#node-input-enableMultiple').is(':checked')) {
|
|
107
|
+
let device_id = $('#node-input-device_id').multipleSelect('getSelects', 'value');
|
|
108
|
+
this.device_id = device_id.length ? device_id[0] : null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let selectedOptions = $('#node-input-device_id option:selected');
|
|
112
|
+
if (selectedOptions) {
|
|
113
|
+
this.topic = selectedOptions.map(function () {
|
|
114
|
+
return $(this).val();
|
|
115
|
+
});
|
|
116
|
+
} else {
|
|
117
|
+
this.topic = null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let $property = $('#node-input-state');
|
|
121
|
+
this.state = $property.val()!=='0'?$property.val():null;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
</script>
|
package/nodes/in.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module.exports = function(RED) {
|
|
2
|
+
class Zigbee2mqttNodeIn {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
RED.nodes.createNode(this, config);
|
|
5
|
+
|
|
6
|
+
let node = this;
|
|
7
|
+
node.config = config;
|
|
8
|
+
node.firstMsg = true;
|
|
9
|
+
node.cleanTimer = null;
|
|
10
|
+
node.server = RED.nodes.getNode(node.config.server);
|
|
11
|
+
node.last_value = null;
|
|
12
|
+
node.last_successful_status = {};
|
|
13
|
+
node.status({});
|
|
14
|
+
|
|
15
|
+
if (node.server) {
|
|
16
|
+
node.listener_onMQTTAvailability = function(data) { node.onMQTTAvailability(data); }
|
|
17
|
+
node.server.on('onMQTTAvailability', node.listener_onMQTTAvailability);
|
|
18
|
+
|
|
19
|
+
node.listener_onConnectError = function(data) { node.onConnectError(); }
|
|
20
|
+
node.server.on('onConnectError', node.listener_onConnectError);
|
|
21
|
+
|
|
22
|
+
node.listener_onMQTTMessage = function(data) { node.onMQTTMessage(data); }
|
|
23
|
+
node.server.on('onMQTTMessage', node.listener_onMQTTMessage);
|
|
24
|
+
|
|
25
|
+
node.listener_onMQTTBridgeState = function(data) { node.onMQTTBridgeState(data); }
|
|
26
|
+
node.server.on('onMQTTBridgeState', node.listener_onMQTTBridgeState);
|
|
27
|
+
|
|
28
|
+
node.on('close', () => node.onClose());
|
|
29
|
+
|
|
30
|
+
} else {
|
|
31
|
+
node.status({
|
|
32
|
+
fill: "red",
|
|
33
|
+
shape: "dot",
|
|
34
|
+
text: "@evilbunny/node-red-contrib-zigbee2mqtt/in:status.no_server"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
onMQTTAvailability(data) {
|
|
40
|
+
let node = this;
|
|
41
|
+
|
|
42
|
+
if (data.item && 'ieee_address' in data.item && data.item.ieee_address === node.config.device_id) {
|
|
43
|
+
node.server.nodeSend(node, {
|
|
44
|
+
'node_send': false
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
onMQTTMessage(data) {
|
|
50
|
+
let node = this;
|
|
51
|
+
|
|
52
|
+
if (node.config.enableMultiple) {
|
|
53
|
+
if (data.item &&
|
|
54
|
+
(("ieee_address" in data.item && (node.config.device_id).includes(data.item.ieee_address))
|
|
55
|
+
|| ("id" in data.item && (node.config.device_id).includes(data.item.id)))
|
|
56
|
+
) {
|
|
57
|
+
node.server.nodeSend(node, {
|
|
58
|
+
'changed' : data
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
} else {
|
|
64
|
+
if (data.item &&
|
|
65
|
+
(("ieee_address" in data.item && data.item.ieee_address === node.config.device_id)
|
|
66
|
+
|| ("id" in data.item && parseInt(data.item.id) === parseInt(node.config.device_id)))
|
|
67
|
+
) {
|
|
68
|
+
node.server.nodeSend(node, {
|
|
69
|
+
'filter': node.config.filterChanges
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
onMQTTBridgeState(data) {
|
|
77
|
+
let node = this;
|
|
78
|
+
if (data.payload) {
|
|
79
|
+
node.status(node.last_successful_status);
|
|
80
|
+
} else {
|
|
81
|
+
node.onConnectError();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
onConnectError() {
|
|
86
|
+
this.status({
|
|
87
|
+
fill: "red",
|
|
88
|
+
shape: "dot",
|
|
89
|
+
text: "@evilbunny/node-red-contrib-zigbee2mqtt/in:status.no_connection"
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
onClose() {
|
|
95
|
+
let node = this;
|
|
96
|
+
|
|
97
|
+
if (node.listener_onMQTTAvailability) {
|
|
98
|
+
node.server.removeListener("onMQTTAvailability", node.listener_onMQTTAvailability);
|
|
99
|
+
}
|
|
100
|
+
if (node.listener_onConnectError) {
|
|
101
|
+
node.server.removeListener("onConnectError", node.listener_onConnectError);
|
|
102
|
+
}
|
|
103
|
+
if (node.listener_onMQTTMessage) {
|
|
104
|
+
node.server.removeListener("onMQTTMessage", node.listener_onMQTTMessage);
|
|
105
|
+
}
|
|
106
|
+
if (node.listener_onMQTTBridgeState) {
|
|
107
|
+
node.server.removeListener("onMQTTBridgeState", node.listener_onMQTTBridgeState);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
node.onConnectError();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
setSuccessfulStatus(obj) {
|
|
114
|
+
this.status(obj);
|
|
115
|
+
this.last_successful_status = obj;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
RED.nodes.registerType('zigbee2mqtt-eb-in', Zigbee2mqttNodeIn);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script type="text/x-red" data-help-name="zigbee2mqtt-eb-bridge">
|
|
2
|
+
<p>Listens all <code>zigbee2mqtt/bridge/#</code> messages.</p>
|
|
3
|
+
<h3>Configuration</h3>
|
|
4
|
+
<dl class="message-properties">
|
|
5
|
+
<dt class="optional">Name <span class="property-type">string</span></dt><dd>Choose any name to identify your node.</dd>
|
|
6
|
+
<dt>Server <span class="property-type">object</span></dt><dd>Choose the zigbee2mqtt server instance to use.</dd>
|
|
7
|
+
</dl>
|
|
8
|
+
|
|
9
|
+
<h3>Inputs</h3>
|
|
10
|
+
<h5>Input</h5>
|
|
11
|
+
<dl class="message-properties">
|
|
12
|
+
<dt>payload <span class="property-type">string</span></dt><dd>mqtt message</dd>
|
|
13
|
+
<dt>topic<span class="property-type">string</span></dt><dd>mqtt topic</dd>
|
|
14
|
+
</dl>
|
|
15
|
+
|
|
16
|
+
<h3>Outputs</h3>
|
|
17
|
+
<h5>Output</h5>
|
|
18
|
+
<dl class="message-properties">
|
|
19
|
+
<dt>payload <span class="property-type">string</span></dt><dd>mqtt message</dd>
|
|
20
|
+
<dt>topic<span class="property-type">string</span></dt><dd>mqtt topic</dd>
|
|
21
|
+
</dl>
|
|
22
|
+
</script>
|
|
23
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"label": {
|
|
3
|
+
"name": "Name",
|
|
4
|
+
"server": "Server",
|
|
5
|
+
"permit_join": "Permit Join",
|
|
6
|
+
"permit_join_help": "Start searching devices for 3 minutes",
|
|
7
|
+
"permit_join_cancel_help": "Stop search",
|
|
8
|
+
"log_level": "Log Level",
|
|
9
|
+
"log_level_info": "info",
|
|
10
|
+
"log_level_debug": "debug",
|
|
11
|
+
"log_level_warning": "warning",
|
|
12
|
+
"log_level_error": "error",
|
|
13
|
+
"version": "Version",
|
|
14
|
+
"restart_required": "Restart required",
|
|
15
|
+
"no_legacy_api": "No Legacy API",
|
|
16
|
+
"coordinator": "Coordinator",
|
|
17
|
+
"turn_off_legacy_api": "Should be off",
|
|
18
|
+
"restart_needed": "Restart needed",
|
|
19
|
+
"ok": "OK",
|
|
20
|
+
"advanced_output": "Output json",
|
|
21
|
+
"should_be_json": "Should be 'json'",
|
|
22
|
+
"restart_zigbee2mqtt": "Restart zigbee2mqtt",
|
|
23
|
+
"retain_disabled_error": "force_disable_retain should be FALSE",
|
|
24
|
+
"mqtt_disable_retain": "Retain mqtt",
|
|
25
|
+
"restart": "Restart",
|
|
26
|
+
"disabled": "disabled",
|
|
27
|
+
"last_seen": "Last seen",
|
|
28
|
+
"availability": "Availability",
|
|
29
|
+
"sure_restart": "Are you sure?",
|
|
30
|
+
"refresh": "Refresh",
|
|
31
|
+
"refresh_all": "Refresh all data"
|
|
32
|
+
},
|
|
33
|
+
"placeholder": {
|
|
34
|
+
"name": "Name"
|
|
35
|
+
},
|
|
36
|
+
"status": {
|
|
37
|
+
"no_server": "no server",
|
|
38
|
+
"no_device": "no device",
|
|
39
|
+
"no_value": "no value",
|
|
40
|
+
"no_connection": "no connection",
|
|
41
|
+
"searching": "looking for devices...",
|
|
42
|
+
"paired": "paired!",
|
|
43
|
+
"online": "online",
|
|
44
|
+
"offline": "offline",
|
|
45
|
+
"pairing": "pairing...",
|
|
46
|
+
"connected": "connected",
|
|
47
|
+
"failed": "failed!"
|
|
48
|
+
},
|
|
49
|
+
"tabs": {
|
|
50
|
+
"bridge": "Bridge",
|
|
51
|
+
"devices": "Devices",
|
|
52
|
+
"groups": "Groups",
|
|
53
|
+
"map": "Map"
|
|
54
|
+
},
|
|
55
|
+
"devices": {
|
|
56
|
+
"ieee_addr": "ieee_address",
|
|
57
|
+
"friendly_name": "Friendly name",
|
|
58
|
+
"model": "Model",
|
|
59
|
+
"device": "Device",
|
|
60
|
+
"set": "set",
|
|
61
|
+
"remove": "remove",
|
|
62
|
+
"sure_remove": "Are you sure you want to remove device?"
|
|
63
|
+
},
|
|
64
|
+
"groups": {
|
|
65
|
+
"id": "ID",
|
|
66
|
+
"friendly_name": "Friendly name",
|
|
67
|
+
"devices": "Devices",
|
|
68
|
+
"set": "set",
|
|
69
|
+
"remove": "remove",
|
|
70
|
+
"add": "Add group",
|
|
71
|
+
"enter_group_name": "Enter group name",
|
|
72
|
+
"sure_remove": "Are you sure you want to remove group?"
|
|
73
|
+
},
|
|
74
|
+
"map": {
|
|
75
|
+
"refresh": "Refresh map",
|
|
76
|
+
"fullscreen": "Open in full screen",
|
|
77
|
+
"loading": "Loading..."
|
|
78
|
+
},
|
|
79
|
+
"tokeninput": {
|
|
80
|
+
"searching": "Searching...",
|
|
81
|
+
"type_to_search": "Type to search device",
|
|
82
|
+
"no_results": "No results"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script type="text/x-red" data-help-name="zigbee2mqtt-eb-get">
|
|
2
|
+
<p>Get last value of device.</p>
|
|
3
|
+
<h3>Configuration</h3>
|
|
4
|
+
<dl class="message-properties">
|
|
5
|
+
<dt class="optional">Name <span class="property-type">string</span></dt><dd>Choose any name to identify your node</dd>
|
|
6
|
+
<dt>Server <span class="property-type">object</span></dt><dd>Choose the zigbee2mqtt server instance to use</dd>
|
|
7
|
+
<dt>Device <span class="property-type">string</span></dt><dd>Select device to listen to</dd>
|
|
8
|
+
</dl>
|
|
9
|
+
|
|
10
|
+
<h3>Outputs</h3>
|
|
11
|
+
<h5>Output</h5>
|
|
12
|
+
<dl class="message-properties">
|
|
13
|
+
<dt>payload <span class="property-type">string</span></dt><dd>current value</dd>
|
|
14
|
+
<dt>payload_in<span class="property-type">object</span></dt><dd>input payload</dd>
|
|
15
|
+
<dt>payload_raw<span class="property-type">object</span></dt><dd>complete payload</dd>
|
|
16
|
+
<dt>device<span class="property-type">object</span></dt><dd>device info</dd>
|
|
17
|
+
</dl>
|
|
18
|
+
</script>
|
|
19
|
+
|