@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.
Files changed (68) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +62 -43
  3. package/api.html +22 -0
  4. package/api.js +176 -0
  5. package/examples/Basic usage.json +316 -0
  6. package/icons/homekit-logo.png +0 -0
  7. package/icons/icon-color.png +0 -0
  8. package/icons/icon.png +0 -0
  9. package/icons/icon.pxd/QuickLook/Icon.tiff +0 -0
  10. package/icons/icon.pxd/QuickLook/Thumbnail.tiff +0 -0
  11. package/icons/icon.pxd/data/15644CBE-CB2C-4054-AAB1-064FBC3F72DB +0 -0
  12. package/icons/icon.pxd/data/2D35D9CD-316A-4D5B-A1D9-1C09DB37FAC9 +0 -0
  13. package/icons/icon.pxd/data/BF7855C2-D304-4F39-84A3-141656F5E18C +0 -0
  14. package/icons/icon.pxd/data/selection/meta +33 -0
  15. package/icons/icon.pxd/data/selection/shapeSelection/meta +12 -0
  16. package/icons/icon.pxd/data/selection/shapeSelection/path +0 -0
  17. package/icons/icon.pxd/data/selectionForContentTransform/meta +33 -0
  18. package/icons/icon.pxd/data/selectionForContentTransform/shapeSelection/meta +12 -0
  19. package/icons/icon.pxd/data/selectionForContentTransform/shapeSelection/path +0 -0
  20. package/icons/icon.pxd/metadata.info +0 -0
  21. package/nodes/bridge.html +523 -0
  22. package/nodes/bridge.js +124 -0
  23. package/nodes/get.html +106 -0
  24. package/nodes/get.js +47 -0
  25. package/nodes/in.html +125 -0
  26. package/nodes/in.js +123 -0
  27. package/nodes/locales/en-US/bridge.html +23 -0
  28. package/nodes/locales/en-US/bridge.json +84 -0
  29. package/nodes/locales/en-US/get.html +19 -0
  30. package/nodes/locales/en-US/get.json +23 -0
  31. package/nodes/locales/en-US/in.html +24 -0
  32. package/nodes/locales/en-US/in.json +43 -0
  33. package/nodes/locales/en-US/out.html +24 -0
  34. package/nodes/locales/en-US/out.json +31 -0
  35. package/nodes/locales/en-US/server.html +12 -0
  36. package/nodes/locales/en-US/server.json +36 -0
  37. package/nodes/locales/sk-SK/bridge.html +23 -0
  38. package/nodes/locales/sk-SK/bridge.json +84 -0
  39. package/nodes/locales/sk-SK/get.html +18 -0
  40. package/nodes/locales/sk-SK/get.json +21 -0
  41. package/nodes/locales/sk-SK/in.html +23 -0
  42. package/nodes/locales/sk-SK/in.json +43 -0
  43. package/nodes/locales/sk-SK/out.html +23 -0
  44. package/nodes/locales/sk-SK/out.json +21 -0
  45. package/nodes/locales/sk-SK/server.html +12 -0
  46. package/nodes/locales/sk-SK/server.json +36 -0
  47. package/nodes/out.html +300 -0
  48. package/nodes/out.js +361 -0
  49. package/nodes/server.html +96 -0
  50. package/nodes/server.js +854 -0
  51. package/package.json +42 -6
  52. package/readme/1.png +0 -0
  53. package/readme/2.png +0 -0
  54. package/readme/3.png +0 -0
  55. package/readme/4.png +0 -0
  56. package/readme/5.png +0 -0
  57. package/readme/options.gif +0 -0
  58. package/resources/Zigbee2mqttHelper.js +470 -0
  59. package/resources/css/common.css +56 -0
  60. package/resources/css/multiple-select.css +183 -0
  61. package/resources/js/multiple-select.js +10 -0
  62. package/resources/js/multiple-select.min.js +10 -0
  63. package/resources/js/node-red-contrib-zigbee2mqtt-helpers.js +416 -0
  64. package/resources/js/zigbee2mqtt-helpers.js +416 -0
  65. package/resources/tokeninput/jquery.tokeninput.js +861 -0
  66. package/resources/tokeninput/token-input-facebook.css +134 -0
  67. package/resources/tokeninput/token-input-mac.css +204 -0
  68. package/resources/tokeninput/token-input.css +113 -0
package/nodes/out.html ADDED
@@ -0,0 +1,300 @@
1
+ <script type="text/x-red" data-template-name="zigbee2mqtt-eb-out">
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-enableMultiple' class="l-width"></label>-->
23
+ <!-- <input type="checkbox" id="node-input-enableMultiple" style="display: inline-block; width: auto; vertical-align: top;"> <span data-i18n="node-red-contrib-spruthub/server:label.enable_multiple"></span></input>-->
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-command" class="l-width"><i class="fa fa-tasks"></i> <span data-i18n="label.command"></span></label>
31
+ <input type="text" id="node-input-command" style="width:70%">
32
+ <input type="hidden" id="node-input-commandType">
33
+ </div>
34
+ <div class="form-row">
35
+ <label for="node-input-payload" class="l-width"><i class="fa fa-envelope"></i> <span data-i18n="label.payload"></span></label>
36
+ <input type="text" id="node-input-payload" style="width:70%">
37
+ <input type="hidden" id="node-input-payloadType">
38
+ </div>
39
+
40
+ <!--homekit-->
41
+ <div class="form-row help_block help_block__homekit_homekit">
42
+ <div class="form-tips">
43
+ <strong><span data-i18n="help.important"></span></strong><br>
44
+ <span data-i18n="help.command_homekit"></span>
45
+ </div>
46
+ </div>
47
+
48
+ <div class="form-row">
49
+ <label for="node-input-optionsValue" class="l-width"><i class="fa fa-gears"></i> <span data-i18n="label.options"></span></label>
50
+ <input type="text" id="node-input-optionsValue" style="width:70%">
51
+ <input type="hidden" id="node-input-optionsType">
52
+ </div>
53
+ <!--option description-->
54
+ <div class="form-tips optionsType_description">
55
+ <strong><div data-i18n="help.description"></div></strong>
56
+ <span></span>
57
+ </div>
58
+
59
+ <div class="form-row node-input-rule-container-row">
60
+ <ol id="node-input-rule-container"></ol>
61
+ </div>
62
+ <hr>
63
+
64
+
65
+ <!--brightness_move-->
66
+ <div class="form-tips help_block help_block__z2m_cmd_brightness_move">
67
+ <strong><span data-i18n="help.description"></span></strong><br>
68
+ <span data-i18n="help.command_brightness_move"></span>
69
+ </div>
70
+ <!--brightness_step-->
71
+ <div class="form-tips help_block help_block__z2m_cmd_brightness_step">
72
+ <strong><span data-i18n="help.description"></span></strong><br>
73
+ <span data-i18n="help.command_brightness_step"></span>
74
+ </div>
75
+
76
+ </script>
77
+
78
+ <script type='text/javascript'>
79
+ RED.nodes.registerType('zigbee2mqtt-eb-out', {
80
+ category: 'ZigBee2MQTT',
81
+ color: '#FDBF48',
82
+ align: 'right',
83
+ defaults: {
84
+ name: {
85
+ value: ""
86
+ },
87
+ server: {
88
+ type: "zigbee2mqtt-eb-server",
89
+ required: true
90
+ },
91
+ friendly_name: {
92
+ value: "",
93
+ required: false
94
+ },
95
+ device_id: {
96
+ value: null
97
+ },
98
+ command: {
99
+ value: 'state',
100
+ },
101
+ commandType: {
102
+ value: 'z2m_cmd',
103
+ },
104
+ payload: {
105
+ value: 'payload',
106
+ },
107
+ payloadType: {
108
+ value: 'msg',
109
+ },
110
+ optionsValue: {
111
+ value: null,
112
+ },
113
+ optionsType: {
114
+ value: null,
115
+ },
116
+ // enableMultiple: {
117
+ // value: false,
118
+ // required: true
119
+ // },
120
+ },
121
+ inputLabels: "value",
122
+ paletteLabel: 'out',
123
+ inputs: 1,
124
+ outputs: 0,
125
+ icon: "icon.png",
126
+ label: function() {
127
+ var label = 'z2m-out';
128
+
129
+ if (this.name) {
130
+ label = this.name;
131
+ } else if (typeof(this.friendly_name) == 'string' && this.friendly_name.length) {
132
+ label = this.friendly_name;
133
+ } else if (typeof(this.device_id) == 'string') {
134
+ label = this.device_id;
135
+ }
136
+ return label;
137
+ },
138
+ oneditprepare: function() {
139
+ let node = this;
140
+ let $inputCommand = $('#node-input-command');
141
+ let $inputCommandType = $('#node-input-commandType');
142
+
143
+ // setTimeout(()=>{
144
+ new Zigbee2MqttEditor(node, {
145
+ 'allow_empty': true
146
+ }).build();
147
+
148
+ showHelpBlock();
149
+ buildTypesInput();
150
+
151
+ $inputCommand.on('change', function(event, type, value) {
152
+ $('#node-input-payload').typedInput('types', getPayloadTypes(value));
153
+
154
+ //show/hide
155
+ if ('homekit' === type || 'nothing' === type) {
156
+ $('#node-input-payload').closest('.form-row').hide();
157
+ } else {
158
+ $('#node-input-payload').closest('.form-row').show();
159
+ }
160
+
161
+ showHelpBlock();
162
+ });
163
+
164
+
165
+ //init typedInput
166
+ $('#node-input-payload').typedInput({
167
+ types: getPayloadTypes(node.command),
168
+ default: 'msg',
169
+ value: 'payload',
170
+ typeField: $('#node-input-payloadType'),
171
+ });
172
+ $inputCommandType.val(node.commandType);
173
+ $('#node-input-payloadType').val(node.payloadType);
174
+
175
+ function showHelpBlock() {
176
+ var command = $('#node-input-command').val(); //state
177
+ var commandType = $('#node-input-commandType').val(); //z2m_cmd
178
+ if (command === '{}') command = 'json';
179
+ if (commandType === 'str') command = 'custom';
180
+ $('.help_block').hide();
181
+ $('.help_block__'+commandType+'_'+command).show();
182
+ }
183
+
184
+
185
+ function buildTypesInput() {
186
+ $('#node-input-command').typedInput({
187
+ types: getCommandTypes(),
188
+ default: 'msg',
189
+ value: 'topic',
190
+ typeField: $('#node-input-commandType'),
191
+ });
192
+ }
193
+
194
+ function getCommandTypes() {
195
+ return [
196
+ //z2m commands
197
+ {
198
+ value: 'z2m_cmd',
199
+ label: 'zigbee2mqtt-eb',
200
+ icon: 'icons/@evilbunny/node-red-contrib-zigbee2mqtt/icon.png',
201
+ options: [
202
+ {'value':'state', 'label':'State (on|off|toggle|lock|unlock|open|close)'},
203
+ {'value':'state_l1', 'label':'State_l1 (on|off|toggle)'},
204
+ {'value':'state_l2', 'label':'State_l2 (on|off|toggle)'},
205
+ {'value':'state_l3', 'label':'State_l3 (on|off|toggle)'},
206
+ {'value':'state_l4', 'label':'State_l4 (on|off|toggle)'},
207
+ {'value':'state_l5', 'label':'State_l5 (on|off|toggle)'},
208
+ {'value':'state_l6', 'label':'State_l6 (on|off|toggle)'},
209
+ {'value':'state_l7', 'label':'State_l7 (on|off|toggle)'},
210
+ {'value':'state_l8', 'label':'State_l8 (on|off|toggle)'},
211
+ {'value':'state_l9', 'label':'State_l9 (on|off|toggle)'},
212
+ {'value':'brightness', 'label':'Brightness (0..255)'},
213
+ {'value':'brightness_move', 'label':'Brightness Move (-255...255|stop)'},
214
+ {'value':'brightness_move_onoff', 'label':'Brightness Move On/Off (-255...255|stop)'},
215
+ {'value':'brightness_step', 'label':'Brightness Step (-255...255)'},
216
+ {'value':'brightness_step_onoff', 'label':'Brightness Step On/Off (-255...255)'},
217
+ {'value':'color', 'label':'Color: {}'},
218
+ {'value':'color_rgb', 'label':'Color: r,g,b'},
219
+ {'value':'color_hex', 'label':'Color: #hex'},
220
+ {'value':'color_hsb', 'label':'Color: h,s,b'},
221
+ {'value':'color_hsv', 'label':'Color: h,s,v'},
222
+ {'value':'color_hue', 'label':'Color: hue'},
223
+ {'value':'color_saturation', 'label':'Color: saturation'},
224
+ {'value':'color_temp', 'label':'Color Temperature (50..400)'},
225
+ {'value':'color_temp_move', 'label':'Color Temperature Move (50..400|stop)'},
226
+ {'value':'color_temp_step', 'label':'Color Temperature Step (50..400)'},
227
+ {'value':'position', 'label':'Position (0..100)'},
228
+ {'value':'scene', 'label':'Scene (0..255)'},
229
+ {'value':'lock', 'label':'Lock (lock|unlock|on|off|toggle)'},
230
+ {'value':'alert', 'label':'Alert'}
231
+ ]
232
+ },
233
+ //homekit
234
+ {
235
+ value:'homekit',
236
+ label:'homekit',
237
+ icon:'icons/@evilbunny/node-red-contrib-zigbee2mqtt/homekit-logo.png',
238
+ options:[{'value':'homekit', 'label':'Apple Homekit data format'}]
239
+ },
240
+ {
241
+ value: 'nothing',
242
+ label: RED._("@evilbunny/node-red-contrib-zigbee2mqtt/server:editor.nothing"),
243
+ options:['']
244
+ },
245
+ {value:'str', label: 'str'},
246
+ {value:'msg', label: 'msg'},
247
+ {value:'json',label:'JSON',options:['{}']}
248
+ ];
249
+ }
250
+
251
+ function getPayloadTypes(command) {
252
+ let types = ['msg', 'flow', 'global', 'str', 'num', 'json'];
253
+ let options = [];
254
+ if (command.startsWith("state")) {
255
+ options = [
256
+ {'value':'on', 'label':'On'},
257
+ {'value':'off', 'label':'Off'},
258
+ {'value':'toggle', 'label':'Toggle'},
259
+ {'value':'lock', 'label':'Lock'},
260
+ {'value':'unlock', 'label':'Unlock'},
261
+ {'value':'open', 'label':'Open'},
262
+ {'value':'close', 'label':'Close'}
263
+ ];
264
+ } else if ('color_temp' === command) {
265
+ options = [
266
+ {'value':'50', 'label':'Cold'},
267
+ {'value':'250', 'label':'White'},
268
+ {'value':'400', 'label':'Warm'}
269
+ ];
270
+ } else if ('alert' === command) {
271
+ options = [
272
+ {'value':'none', 'label':'None'},
273
+ {'value':'select', 'label':'Blink short'},
274
+ {'value':'lselect', 'label':'Blink log'}
275
+ ];
276
+ }
277
+ if (options.length) {
278
+ const predefinedValuesPayload = {
279
+ value: 'z2m_payload',
280
+ label: 'zigbee2mqtt-eb',
281
+ icon: 'icons/@evilbunny/node-red-contrib-zigbee2mqtt/icon.png',
282
+ options
283
+ };
284
+ return [predefinedValuesPayload, ...types]
285
+ } else {
286
+ return types;
287
+ }
288
+ }
289
+ // }, 100); //need timeout to load server node
290
+ },
291
+ oneditsave: function () {
292
+ //convert array for string if single mode
293
+ if (!$('#node-input-enableMultiple').is(':checked')) {
294
+ let device_id = $('#node-input-device_id').multipleSelect('getSelects', 'value');
295
+ this.device_id = device_id.length ? device_id[0] : null;
296
+ }
297
+ }
298
+ });
299
+ </script>
300
+
package/nodes/out.js ADDED
@@ -0,0 +1,361 @@
1
+ const Zigbee2mqttHelper = require('../resources/Zigbee2mqttHelper.js');
2
+
3
+ module.exports = function(RED) {
4
+ class Zigbee2mqttNodeOut {
5
+ constructor(config) {
6
+ RED.nodes.createNode(this, config);
7
+
8
+ var node = this;
9
+ node.config = config;
10
+ node.cleanTimer = null;
11
+ node.server = RED.nodes.getNode(node.config.server);
12
+
13
+ if (node.server) {
14
+ node.status({}); //clean
15
+
16
+ node.on('input', function(message) {
17
+ clearTimeout(node.cleanTimer);
18
+
19
+ let key = node.config.device_id;
20
+ if ((!key || key === 'msg.topic') && message.topic) {
21
+ key = message.topic;
22
+ }
23
+ let device = node.server.getDeviceOrGroupByKey(key);
24
+ if (device) {
25
+ let payload;
26
+ let options = {};
27
+ switch (node.config.payloadType) {
28
+ case '':
29
+ case null:
30
+ case 'nothing':
31
+ payload = null;
32
+ break;
33
+
34
+ case 'flow':
35
+ case 'global': {
36
+ RED.util.evaluateNodeProperty(node.config.payload, node.config.payloadType, this, message, function (error, result) {
37
+ if (error) {
38
+ node.error(error, message);
39
+ } else {
40
+ payload = result;
41
+ }
42
+ });
43
+ break;
44
+ }
45
+ case 'z2m_payload':
46
+ payload = node.config.payload;
47
+ break;
48
+
49
+ case 'num': {
50
+ payload = parseInt(node.config.payload);
51
+ break;
52
+ }
53
+
54
+ case 'str': {
55
+ payload = node.config.payload;
56
+ break;
57
+ }
58
+
59
+ case 'json': {
60
+ if (Zigbee2mqttHelper.isJson(node.config.payload)) {
61
+ payload = JSON.parse(node.config.payload);
62
+ } else {
63
+ node.warn('Incorrect payload. Waiting for valid JSON');
64
+ node.status({
65
+ fill: "red",
66
+ shape: "dot",
67
+ text: "@evilbunny/node-red-contrib-zigbee2mqtt/out:status.no_payload"
68
+ });
69
+ node.cleanTimer = setTimeout(function(){
70
+ node.status({}); //clean
71
+ }, 3000);
72
+ }
73
+ break;
74
+ }
75
+
76
+ // case 'homekit':
77
+ // payload = node.formatHomeKit(message, payload);
78
+ // break;
79
+
80
+ case 'msg':
81
+ default: {
82
+ payload = message[node.config.payload];
83
+ break;
84
+ }
85
+ }
86
+
87
+
88
+ var command;
89
+ switch (node.config.commandType) {
90
+ case '':
91
+ case null:
92
+ case 'nothing':
93
+ payload = null;
94
+ break;
95
+
96
+ case 'msg': {
97
+ command = message[node.config.command];
98
+ break;
99
+ }
100
+ case 'z2m_cmd':
101
+ command = node.config.command;
102
+ switch (command) {
103
+ case 'state':
104
+ if (payload === 'toggle') {
105
+ if (device.current_values && 'position' in device.current_values) {
106
+ payload = device.current_values.position > 0 ? 'close' : 'open';
107
+ }
108
+ }
109
+ break;
110
+ case 'brightness':
111
+ payload = parseInt(payload);
112
+ options["state"] = payload>0?"on":"Off";
113
+ break;
114
+
115
+ case 'position':
116
+ payload = parseInt(payload);
117
+ break;
118
+
119
+ case 'scene':
120
+ command = 'scene_recall';
121
+ payload = parseInt(payload);
122
+ break;
123
+
124
+ case 'lock':
125
+ command = 'state';
126
+ if (payload === 'toggle') {
127
+ if (device.current_values && 'lock_state' in
128
+ device.current_values && device.current_values.lock_state === 'locked') {
129
+ payload = 'unlock';
130
+ } else {
131
+ payload = 'lock';
132
+ }
133
+ } else if (payload === 'lock' || payload == 1 || payload === true || payload === 'on') {
134
+ payload = 'lock';
135
+ } else if (payload === 'unlock' || payload == 0 || payload === false || payload === 'off') {
136
+ payload = 'unlock';
137
+ }
138
+ break;
139
+
140
+ case 'color':
141
+ payload = {"color":payload};
142
+ break;
143
+ case 'color_rgb':
144
+ payload = {"color":{"rgb": payload}};
145
+ break;
146
+ case 'color_hex':
147
+ command = "color";
148
+ payload = {"color":{"hex": payload}};
149
+ break;
150
+ case 'color_hsb':
151
+ command = "color";
152
+ payload = {"color":{"hsb": payload}};
153
+ break;
154
+ case 'color_hsv':
155
+ command = "color";
156
+ payload = {"color":{"hsv": payload}};
157
+ break;
158
+ case 'color_hue':
159
+ command = "color";
160
+ payload = {"color":{"hue": payload}};
161
+ break;
162
+ case 'color_saturation':
163
+ command = "color";
164
+ payload = {"color":{"saturation": payload}};
165
+ break;
166
+
167
+ case 'color_temp':
168
+
169
+ break;
170
+
171
+ case 'brightness_move':
172
+ case 'brightness_step':
173
+ case 'alert':
174
+ default: {
175
+ break;
176
+ }
177
+ }
178
+ break;
179
+
180
+ case 'homekit':
181
+ payload = node.fromHomeKitFormat(message, device);
182
+ break;
183
+
184
+ case 'json':
185
+ break;
186
+
187
+ case 'str':
188
+ default: {
189
+ command = node.config.command;
190
+ break;
191
+ }
192
+ }
193
+
194
+ let optionsToSend = {};
195
+ switch (node.config.optionsType) {
196
+ case '':
197
+ case null:
198
+ case 'nothing':
199
+ break;
200
+
201
+ case 'msg':
202
+ if (node.config.optionsValue in message && typeof(message[node.config.optionsValue]) == 'object') {
203
+ optionsToSend = message[node.config.optionsValue];
204
+ } else {
205
+ node.warn('Options value has invalid format');
206
+ }
207
+ break;
208
+
209
+ case 'json':
210
+ if (Zigbee2mqttHelper.isJson(node.config.optionsValue)) {
211
+ optionsToSend = JSON.parse(node.config.optionsValue);
212
+ } else {
213
+ node.warn('Options value is not valid JSON, ignore: '+node.config.optionsValue);
214
+ }
215
+ break;
216
+
217
+ default:
218
+ optionsToSend[node.config.optionsType] = node.config.optionsValue;
219
+ break;
220
+ }
221
+
222
+ //apply options
223
+ if (Object.keys(optionsToSend).length) {
224
+ node.server.setDeviceOptions(device.friendly_name, optionsToSend);
225
+ }
226
+
227
+ //empty payload, stop
228
+ if (payload === null) {
229
+ return false;
230
+ }
231
+
232
+ if (payload !== undefined) {
233
+ var toSend = {};
234
+ var text = '';
235
+ if (typeof(payload) == 'object') {
236
+ toSend = payload;
237
+ text = 'json';
238
+ } else {
239
+ toSend[command] = payload;
240
+ text = command+': '+payload;
241
+ }
242
+
243
+ node.log('Published to mqtt topic: ' + node.server.getTopic('/'+device.friendly_name + '/set') + ' : ' + JSON.stringify(toSend));
244
+ node.server.mqtt.publish(node.server.getTopic('/'+device.friendly_name + '/set'), JSON.stringify(toSend),
245
+ {'qos':parseInt(node.server.config.mqtt_qos||0)},
246
+ function(err) {
247
+ if (err) {
248
+ node.error(err);
249
+ }
250
+ });
251
+
252
+ let fill = node.server.getDeviceAvailabilityColor(node.server.getTopic('/'+device.friendly_name));
253
+ node.status({
254
+ fill: fill,
255
+ shape: "dot",
256
+ text: text
257
+ });
258
+ let time = Zigbee2mqttHelper.statusUpdatedAt();
259
+ node.cleanTimer = setTimeout(function(){
260
+ node.status({
261
+ fill: fill,
262
+ shape: "ring",
263
+ text: text + ' ' + time
264
+ });
265
+ }, 3000);
266
+ } else {
267
+ node.status({
268
+ fill: "red",
269
+ shape: "dot",
270
+ text: "@evilbunny/node-red-contrib-zigbee2mqtt/out:status.no_payload"
271
+ });
272
+ }
273
+ } else {
274
+ node.status({
275
+ fill: "red",
276
+ shape: "dot",
277
+ text: "@evilbunny/node-red-contrib-zigbee2mqtt/out:status.no_device"
278
+ });
279
+ }
280
+ });
281
+
282
+ } else {
283
+ node.status({
284
+ fill: "red",
285
+ shape: "dot",
286
+ text: "@evilbunny/node-red-contrib-zigbee2mqtt/out:status.no_server"
287
+ });
288
+ }
289
+ }
290
+
291
+ fromHomeKitFormat(message, device) {
292
+ if ("hap" in message && message.hap.context === undefined) {
293
+ return null;
294
+ }
295
+
296
+ var payload = message['payload'];
297
+ var msg = {};
298
+
299
+ if (payload.On !== undefined) {
300
+ if ("current_values" in device) {
301
+ // if ("brightness" in device.current_values) msg['brightness'] = device.current_values.brightness;
302
+ }
303
+ msg['state'] = payload.On?"on":"off";
304
+ }
305
+ if (payload.Brightness !== undefined) {
306
+ msg['brightness'] = Zigbee2mqttHelper.convertRange(payload.Brightness, [0,100], [0,255]);
307
+ device.current_values.brightness = msg['brightness'];
308
+ if ("current_values" in device) {
309
+ if ("current_values" in device) device.current_values.brightness = msg['brightness'];
310
+ }
311
+ if (payload.Brightness >= 254) payload.Brightness = 255;
312
+ msg['state'] = payload.Brightness > 0?"on":"off"
313
+ }
314
+ if (payload.Hue !== undefined) {
315
+ msg['color'] = {"hue":payload.Hue};
316
+ device.current_values.color.hue = payload.Hue;
317
+ if ("current_values" in device) {
318
+ if ("brightness" in device.current_values) msg['brightness'] = device.current_values.brightness;
319
+ if ("color" in device.current_values && "saturation" in device.current_values.color) msg['color']['saturation'] = device.current_values.color.saturation;
320
+ if ("color" in device.current_values && "hue" in device.current_values.color) device.current_values.color.hue = payload.Hue;
321
+ }
322
+ msg['state'] = "on";
323
+ }
324
+ if (payload.Saturation !== undefined) {
325
+ msg['color'] = {"saturation":payload.Saturation};
326
+ device.current_values.color.saturation = payload.Saturation;
327
+ if ("current_values" in device) {
328
+ if ("brightness" in device.current_values) msg['brightness'] = device.current_values.brightness;
329
+ if ("color" in device.current_values && "hue" in device.current_values.color) msg['color']['hue'] = device.current_values.color.hue;
330
+ if ("color" in device.current_values && "saturation" in device.current_values.color) msg['color']['saturation'] = payload.Saturation;
331
+ }
332
+ msg['state'] = "on";
333
+ }
334
+ if (payload.ColorTemperature !== undefined) {
335
+ msg['color_temp'] = Zigbee2mqttHelper.convertRange(payload.ColorTemperature, [150,500], [150,500]);
336
+ device.current_values.color_temp = msg['color_temp'];
337
+ if ("current_values" in device) {
338
+ if ("color_temp" in device.current_values) device.current_values.color_temp = msg['color_temp'];
339
+ }
340
+ msg['state'] = "on";
341
+ }
342
+ if (payload.LockTargetState !== undefined) {
343
+ msg['state'] = payload.LockTargetState?"LOCK":"UNLOCK";
344
+ }
345
+ if (payload.TargetPosition !== undefined) {
346
+ msg['position'] = payload.TargetPosition;
347
+ }
348
+
349
+ return msg;
350
+ }
351
+ }
352
+
353
+
354
+ RED.nodes.registerType('zigbee2mqtt-eb-out', Zigbee2mqttNodeOut);
355
+ };
356
+
357
+
358
+
359
+
360
+
361
+