node-red-contrib-homebridge-automation 0.1.12-beta.31 → 0.1.12-beta.33

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/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "node-red-contrib-homebridge-automation",
3
- "version": "0.1.12-beta.31",
3
+ "version": "0.1.12-beta.33",
4
4
  "description": "NodeRED Automation for HomeBridge",
5
5
  "main": "src/HAP-NodeRed.js",
6
6
  "scripts": {
7
- "api": "documentation build HAP-NodeRed.js -f md --config docs/documentation.yml > docs/API.md",
8
7
  "document": "./gh-md-toc --insert --no-backup --hide-footer README.md",
9
8
  "watch": "nodemon",
10
9
  "coverage": "nyc npm t",
@@ -28,9 +27,8 @@
28
27
  "url": "git+https://github.com/NorthernMan54/node-red-contrib-homebridge-automation.git"
29
28
  },
30
29
  "devDependencies": {
31
- "@types/node-red": "^0.20.7",
30
+ "@types/node-red": "^1.3.5",
32
31
  "@types/jest": "^29.5.12",
33
- "documentation": "14.0.3",
34
32
  "@eslint/js": "^9.14.0",
35
33
  "eslint": "^8.57.1",
36
34
  "eslint-plugin-format": "^0.1.2",
@@ -42,13 +40,13 @@
42
40
  "nodemon": "^3.1.4",
43
41
  "nyc": "^17.0.0",
44
42
  "prettier": "^3.3.2",
45
- "rimraf": "^5.0.7",
43
+ "rimraf": "^6.0.1",
46
44
  "semver": "^7.6.2"
47
45
  },
48
46
  "dependencies": {
49
47
  "better-queue": ">=3.8.12",
50
48
  "debug": "^4.3.5",
51
- "@homebridge/hap-client": "2.0.5-beta.5"
49
+ "@homebridge/hap-client": "2.0.5-beta.12"
52
50
  },
53
51
  "author": "NorthernMan54",
54
52
  "license": "ISC",
@@ -30,7 +30,7 @@ class HapDeviceRoutes {
30
30
  getDeviceById(req, res, key) {
31
31
  const devices = this.RED.nodes.getNode(req.params.id)?.[key];
32
32
  if (devices) {
33
- debug(`${key} devices`, devices.length);
33
+ // debug(`${key} devices`, devices.length);
34
34
  res.send(devices);
35
35
  } else {
36
36
  res.status(404).send();
@@ -8,6 +8,7 @@ class HBConfigNode {
8
8
  if (!config.jest) {
9
9
  RED.nodes.createNode(this, config);
10
10
 
11
+ // Initialize properties
11
12
  this.username = config.username;
12
13
  this.macAddress = config.macAddress || '';
13
14
  this.users = {};
@@ -18,7 +19,9 @@ class HBConfigNode {
18
19
  this.clientNodes = [];
19
20
  this.monitorNodes = [];
20
21
  this.log = new Log(console, true);
22
+ this.discoveryTimeout = null;
21
23
 
24
+ // Initialize queue
22
25
  this.reqisterQueue = new Queue(this._register.bind(this), {
23
26
  concurrent: 1,
24
27
  autoResume: false,
@@ -29,39 +32,40 @@ class HBConfigNode {
29
32
  });
30
33
  this.reqisterQueue.pause();
31
34
 
35
+ // Initialize HAP client
32
36
  this.hapClient = new HapClient({
33
- config: { debug: false },
37
+ config: { debug: true },
34
38
  pin: config.username,
35
39
  logger: this.log,
36
40
  });
37
41
 
38
- this.waitForNoMoreDiscoveries();
39
42
  this.hapClient.on('instance-discovered', this.waitForNoMoreDiscoveries);
40
-
43
+ this.waitForNoMoreDiscoveries();
41
44
  this.on('close', this.close.bind(this));
42
45
  }
43
46
  }
44
47
 
45
48
  waitForNoMoreDiscoveries = () => {
46
- if (this.discoveryTimeout) {
49
+ if (!this.discoveryTimeout) {
47
50
  clearTimeout(this.discoveryTimeout);
51
+ this.discoveryTimeout = setTimeout(() => {
52
+ this.log.debug('No more instances discovered, publishing services');
53
+ this.hapClient.removeListener('instance-discovered', this.waitForNoMoreDiscoveries);
54
+ this.hapClient.on('instance-discovered', async (instance) => { debug('instance-discovered', instance); await this.monitorDevices(); });
55
+ this.hapClient.on('discovery-ended', async () => { debug('discovery-ended'); });
56
+ this.handleReady();
57
+ this.discoveryTimeout = null;
58
+ }, 5000);
48
59
  }
49
-
50
- this.discoveryTimeout = setTimeout(() => {
51
- this.log.debug('No more instances discovered, publishing services');
52
- this.hapClient.removeListener('instance-discovered', this.waitForNoMoreDiscoveries);
53
- this.handleReady();
54
- }, 5000);
55
60
  };
56
61
 
57
62
  async handleReady() {
58
63
  this.hbDevices = await this.hapClient.getAllServices();
59
64
  this.evDevices = this.toList({ perms: 'ev' });
60
65
  this.ctDevices = this.toList({ perms: 'pw' });
61
- console.log('evDevices', this.evDevices);
62
- console.log('ctDevices', this.ctDevices);
66
+ this.log.info(`Devices initialized: evDevices: ${this.evDevices.length}, ctDevices: ${this.ctDevices.length}`);
63
67
  this.handleDuplicates(this.evDevices);
64
- debug('Queue', this.reqisterQueue.getStats());
68
+ debug('Queue stats:', this.reqisterQueue.getStats());
65
69
  this.reqisterQueue.resume();
66
70
  }
67
71
 
@@ -92,23 +96,19 @@ class HBConfigNode {
92
96
  const seenFullNames = new Set();
93
97
  const seenUniqueIds = new Set();
94
98
 
95
- for (const endpoint of list) {
96
- if (seenFullNames.has(endpoint.fullName)) {
99
+ list.forEach(endpoint => {
100
+ if (!seenFullNames.add(endpoint.fullName)) {
97
101
  console.warn('WARNING: Duplicate device name', endpoint.fullName);
98
- } else {
99
- seenFullNames.add(endpoint.fullName);
100
102
  }
101
103
 
102
- if (seenUniqueIds.has(endpoint.uniqueId)) {
103
- console.error('ERROR: Parsing failed, duplicate uniqueID.', endpoint.fullName);
104
- } else {
105
- seenUniqueIds.add(endpoint.uniqueId);
104
+ if (!seenUniqueIds.add(endpoint.uniqueId)) {
105
+ console.error('ERROR: Duplicate uniqueId detected.', endpoint.fullName);
106
106
  }
107
- }
107
+ });
108
108
  }
109
109
 
110
110
  register(clientNode) {
111
- debug('Register %s -> %s', clientNode.type, clientNode.name);
111
+ debug('Register: %s type: %s', clientNode.type, clientNode.name);
112
112
  this.clientNodes[clientNode.id] = clientNode;
113
113
  this.reqisterQueue.push(clientNode);
114
114
  clientNode.status({ fill: 'yellow', shape: 'ring', text: 'connecting' });
@@ -116,64 +116,62 @@ class HBConfigNode {
116
116
 
117
117
  async _register(clientNodes, cb) {
118
118
  for (const clientNode of clientNodes) {
119
- debug('_Register %s -> %s', clientNode.type, clientNode.name);
120
- clientNode.hbDevice = this.hbDevices.find(service => {
121
- const deviceUnique = `${service.instance.name}${service.instance.username}${service.accessoryInformation.Manufacturer}${service.serviceName}${service.uuid.slice(0, 8)}`;
122
- if (clientNode.device === deviceUnique) {
123
- clientNode.status({ fill: 'green', shape: 'dot', text: 'connected' });
124
- clientNode.emit('hbReady', service);
119
+ debug('_Register: %s type: %s', clientNode.type, clientNode.name, clientNode.instance);
120
+ const matchedDevice = this.hbDevices.find(service =>
121
+ clientNode.device === `${service.instance.name}${service.instance.username}${service.accessoryInformation.Manufacturer}${service.serviceName}${service.uuid.slice(0, 8)}`
122
+ );
123
+
124
+ if (matchedDevice) {
125
+ clientNode.hbDevice = matchedDevice;
126
+ clientNode.status({ fill: 'green', shape: 'dot', text: 'connected' });
127
+ clientNode.emit('hbReady', matchedDevice);
128
+ debug('_Registered: %s type: %s', matchedDevice.type, matchedDevice.serviceName, matchedDevice.instance);
129
+ if (clientNode.config.type === 'hb-status' || clientNode.config.type === 'hb-event') {
130
+ this.monitorNodes[clientNode.device] = matchedDevice;
125
131
  }
126
- return clientNode.device === deviceUnique;
127
- });
128
-
129
- if (clientNode.config.type === 'hb-status') {
130
- this.monitorNodes[clientNode.device] = clientNode.hbDevice;
131
- }
132
-
133
- if (!clientNode.hbDevice) {
134
- console.error('ERROR: _register - HB Device Missing', clientNode.name);
132
+ } else {
133
+ console.error('ERROR: Device registration failed', clientNode.name);
135
134
  }
136
135
  }
137
136
 
137
+ await this.monitorDevices();
138
+
139
+ cb(null);
140
+ }
141
+
142
+ async monitorDevices() {
143
+ debug('monitorDevices', Object.keys(this.monitorNodes).length);
138
144
  if (Object.keys(this.monitorNodes).length) {
139
145
  this.monitor = await this.hapClient.monitorCharacteristics(Object.values(this.monitorNodes));
140
146
  this.monitor.on('service-update', (services) => {
141
- for (const service of services) {
142
- const eventNodes = Object.values(this.clientNodes).filter(
143
- clientNode =>
144
- clientNode.config.device === `${service.instance.name}${service.instance.username}${service.accessoryInformation.Manufacturer}${service.serviceName}${service.uuid.slice(0, 8)}`
147
+ services.forEach(service => {
148
+ const eventNodes = Object.values(this.clientNodes).filter(clientNode =>
149
+ clientNode.config.device === `${service.instance.name}${service.instance.username}${service.accessoryInformation.Manufacturer}${service.serviceName}${service.uuid.slice(0, 8)}`
145
150
  );
146
-
147
- eventNodes.forEach((eventNode) => {
148
- if (eventNode._events && typeof eventNode.emit === 'function') {
149
- eventNode.emit('hbEvent', service);
150
- }
151
- });
152
- }
151
+ eventNodes.forEach(eventNode => eventNode.emit('hbEvent', service));
152
+ });
153
153
  });
154
+ this.monitor.on('monitor-close', (hadError) => {
155
+ debug('monitor-close', hadError)
156
+ if (!this.hapClient.this.discoveryInProgress) {
157
+ this.monitor.finish();
158
+ this.hapClient.resetInstancePool();
159
+ }
160
+ })
154
161
  }
155
- cb(null);
156
162
  }
157
- /*
158
- deregister(clientNode) {
159
- clientNode.status({ text: 'disconnected', shape: 'ring', fill: 'red' });
160
- delete this.clientNodes[clientNode.id];
161
- }
162
- */
163
163
  close() {
164
- if (this.hapClient) {
165
- this.hapClient.destroy();
166
- }
164
+ debug('hb-config: close');
165
+ this.hapClient?.destroy();
167
166
  }
168
-
169
167
  }
170
168
 
171
- // Cameras have multiple AID's of 1....
169
+
170
+ // Filter unique devices by AID, service name, username, and port
172
171
  const filterUnique = (data) => {
173
172
  const seen = new Set();
174
173
  return data.filter(item => {
175
174
  const uniqueKey = `${item.aid}-${item.serviceName}-${item.instance.username}-${item.instance.port}`;
176
- console.log(uniqueKey, seen.has(uniqueKey))
177
175
  if (seen.has(uniqueKey)) return false;
178
176
  seen.add(uniqueKey);
179
177
  return true;
@@ -6,7 +6,7 @@ class HbControlNode extends hbBaseNode {
6
6
  super(config, RED);
7
7
  }
8
8
 
9
- async handleInput(message, send) {
9
+ async handleInput(message, send, done) {
10
10
  debug('handleInput', message.payload, this.name);
11
11
 
12
12
  if (!this.hbDevice) {
@@ -54,6 +54,7 @@ class HbControlNode extends hbBaseNode {
54
54
  const result = await this.hbDevice.setCharacteristicByType(key, message.payload[key]);
55
55
  results.push({ [result.type]: result.value });
56
56
  } catch (error) {
57
+ console.log(error)
57
58
  this.error(`Failed to set value for "${key}": ${error.message}`);
58
59
  results.push({ [key]: `Error: ${error.message}` });
59
60
  fill = 'red';
@@ -64,15 +65,13 @@ class HbControlNode extends hbBaseNode {
64
65
  // Update status
65
66
  const statusText = this.statusText(JSON.stringify(Object.assign({}, ...results)));
66
67
  this.status({ text: statusText, shape: 'dot', fill });
68
+ done
67
69
  } catch (error) {
68
70
  this.error(`Unhandled error: ${error.message}`);
69
71
  this.status({ text: 'Unhandled error', shape: 'dot', fill: 'red' });
72
+ done(`Unhandled error: ${error.message}`);
70
73
  }
71
74
  }
72
75
  }
73
76
 
74
- function btoa(str) {
75
- return Buffer.isBuffer(str) ? str.toString('base64') : Buffer.from(str.toString(), 'binary').toString('base64');
76
- }
77
-
78
77
  module.exports = HbControlNode;
@@ -6,7 +6,7 @@ class HbStatusNode extends HbBaseNode {
6
6
  super(config, RED);
7
7
  }
8
8
 
9
- async handleInput(message, send) {
9
+ async handleInput(message, send, done) {
10
10
  debug('handleInput', message.payload, this.name);
11
11
 
12
12
  if (!this.hbDevice) {
@@ -15,13 +15,21 @@ class HbStatusNode extends HbBaseNode {
15
15
  }
16
16
 
17
17
  const result = await this.hbDevice.refreshCharacteristics();
18
- this.status({
19
- text: this.statusText(JSON.stringify(await this.hbDevice.values)),
20
- shape: 'dot',
21
- fill: 'green'
22
- });
18
+ if (result) {
19
+ this.status({
20
+ text: this.statusText(JSON.stringify(await this.hbDevice.values)),
21
+ shape: 'dot',
22
+ fill: 'green'
23
+ });
24
+
25
+ send(Object.assign(message, this.createMessage(result)));
26
+ done
27
+ } else {
28
+ this.status({ fill: "red", shape: "ring", text: "disconnected" });
29
+ this.error("No response from device", this.name);
30
+ done("No response from device");
31
+ }
23
32
 
24
- send(Object.assign(message, this.createMessage(result)));
25
33
  }
26
34
  }
27
35
 
@@ -22,12 +22,12 @@
22
22
  "tosidebar": true,
23
23
  "console": false,
24
24
  "tostatus": true,
25
- "complete": "payload",
26
- "targetType": "msg",
25
+ "complete": "true",
26
+ "targetType": "full",
27
27
  "statusVal": "payload",
28
28
  "statusType": "auto",
29
- "x": 800,
30
- "y": 140,
29
+ "x": 820,
30
+ "y": 40,
31
31
  "wires": []
32
32
  },
33
33
  {
@@ -39,12 +39,12 @@
39
39
  "tosidebar": true,
40
40
  "console": false,
41
41
  "tostatus": true,
42
- "complete": "payload",
43
- "targetType": "msg",
42
+ "complete": "true",
43
+ "targetType": "full",
44
44
  "statusVal": "payload",
45
45
  "statusType": "auto",
46
- "x": 800,
47
- "y": 260,
46
+ "x": 820,
47
+ "y": 100,
48
48
  "wires": []
49
49
  },
50
50
  {
@@ -68,12 +68,11 @@
68
68
  "topic": "",
69
69
  "payload": "",
70
70
  "payloadType": "date",
71
- "x": 250,
72
- "y": 140,
71
+ "x": 270,
72
+ "y": 40,
73
73
  "wires": [
74
74
  [
75
- "3d7babac3a298e60",
76
- "452e3e6171aa7a25"
75
+ "3d7babac3a298e60"
77
76
  ]
78
77
  ]
79
78
  },
@@ -87,8 +86,8 @@
87
86
  "Service": "Lightbulb",
88
87
  "device": "homebridge1C:22:3D:E3:CF:34TasmotaWest Bedroom00000043",
89
88
  "conf": "557aec8e8c47e61e",
90
- "x": 480,
91
- "y": 140,
89
+ "x": 500,
90
+ "y": 40,
92
91
  "wires": [
93
92
  [
94
93
  "902c5887b6877df6"
@@ -96,27 +95,58 @@
96
95
  ]
97
96
  },
98
97
  {
99
- "id": "696e04753d952daf",
100
- "type": "hb-status",
98
+ "id": "452e3e6171aa7a25",
99
+ "type": "hb-resume",
101
100
  "z": "caef1e7b5b399e80",
102
- "d": true,
103
101
  "name": "West Bedroom",
104
102
  "Homebridge": "homebridge",
105
103
  "Manufacturer": "Tasmota",
106
104
  "Service": "Lightbulb",
107
105
  "device": "homebridge1C:22:3D:E3:CF:34TasmotaWest Bedroom00000043",
108
106
  "conf": "557aec8e8c47e61e",
109
- "x": 480,
110
- "y": 260,
107
+ "x": 500,
108
+ "y": 160,
111
109
  "wires": [
112
110
  [
113
- "a866ae0bb24ce682"
111
+ "1093ab38b01fd39f"
114
112
  ]
115
113
  ]
116
114
  },
117
115
  {
118
- "id": "bb88544904b343a1",
119
- "type": "hb-event",
116
+ "id": "1093ab38b01fd39f",
117
+ "type": "debug",
118
+ "z": "caef1e7b5b399e80",
119
+ "name": "debug 3",
120
+ "active": true,
121
+ "tosidebar": true,
122
+ "console": false,
123
+ "tostatus": true,
124
+ "complete": "payload",
125
+ "targetType": "msg",
126
+ "statusVal": "payload",
127
+ "statusType": "auto",
128
+ "x": 820,
129
+ "y": 160,
130
+ "wires": []
131
+ },
132
+ {
133
+ "id": "0ed3cd7e0d60beda",
134
+ "type": "hb-control",
135
+ "z": "caef1e7b5b399e80",
136
+ "name": "West Bedroom Fan",
137
+ "Homebridge": "homebridge",
138
+ "Manufacturer": "Tasmota",
139
+ "Service": "Fan",
140
+ "device": "homebridge1C:22:3D:E3:CF:34TasmotaWest Bedroom Fan00000040",
141
+ "conf": "557aec8e8c47e61e",
142
+ "outputs": 0,
143
+ "x": 510,
144
+ "y": 220,
145
+ "wires": []
146
+ },
147
+ {
148
+ "id": "6703815a8874b156",
149
+ "type": "hb-control",
120
150
  "z": "caef1e7b5b399e80",
121
151
  "name": "West Bedroom",
122
152
  "Homebridge": "homebridge",
@@ -124,16 +154,251 @@
124
154
  "Service": "Lightbulb",
125
155
  "device": "homebridge1C:22:3D:E3:CF:34TasmotaWest Bedroom00000043",
126
156
  "conf": "557aec8e8c47e61e",
127
- "sendInitialState": false,
128
- "x": 220,
157
+ "outputs": 1,
158
+ "x": 500,
159
+ "y": 300,
160
+ "wires": [
161
+ [
162
+ "f194fc4bcb1997a9"
163
+ ]
164
+ ]
165
+ },
166
+ {
167
+ "id": "24660f9d2862cee9",
168
+ "type": "inject",
169
+ "z": "caef1e7b5b399e80",
170
+ "name": "",
171
+ "props": [
172
+ {
173
+ "p": "payload"
174
+ },
175
+ {
176
+ "p": "topic",
177
+ "vt": "str"
178
+ }
179
+ ],
180
+ "repeat": "",
181
+ "crontab": "",
182
+ "once": false,
183
+ "onceDelay": 0.1,
184
+ "topic": "",
185
+ "payload": "{\"On\": true, \"RotationSpeed\": 33}",
186
+ "payloadType": "json",
187
+ "x": 90,
188
+ "y": 180,
189
+ "wires": [
190
+ [
191
+ "0ed3cd7e0d60beda"
192
+ ]
193
+ ]
194
+ },
195
+ {
196
+ "id": "8c0ecac45b01df73",
197
+ "type": "inject",
198
+ "z": "caef1e7b5b399e80",
199
+ "name": "",
200
+ "props": [
201
+ {
202
+ "p": "payload"
203
+ },
204
+ {
205
+ "p": "topic",
206
+ "vt": "str"
207
+ }
208
+ ],
209
+ "repeat": "",
210
+ "crontab": "",
211
+ "once": false,
212
+ "onceDelay": 0.1,
213
+ "topic": "",
214
+ "payload": "{\"On\": false}",
215
+ "payloadType": "json",
216
+ "x": 110,
217
+ "y": 240,
218
+ "wires": [
219
+ [
220
+ "0ed3cd7e0d60beda"
221
+ ]
222
+ ]
223
+ },
224
+ {
225
+ "id": "b14ebf264be0c60d",
226
+ "type": "inject",
227
+ "z": "caef1e7b5b399e80",
228
+ "name": "",
229
+ "props": [
230
+ {
231
+ "p": "payload"
232
+ },
233
+ {
234
+ "p": "topic",
235
+ "vt": "str"
236
+ }
237
+ ],
238
+ "repeat": "",
239
+ "crontab": "",
240
+ "once": false,
241
+ "onceDelay": 0.1,
242
+ "topic": "",
243
+ "payload": "{\"On\": true}",
244
+ "payloadType": "json",
245
+ "x": 110,
246
+ "y": 300,
247
+ "wires": [
248
+ [
249
+ "6703815a8874b156"
250
+ ]
251
+ ]
252
+ },
253
+ {
254
+ "id": "f872545e74246764",
255
+ "type": "inject",
256
+ "z": "caef1e7b5b399e80",
257
+ "name": "",
258
+ "props": [
259
+ {
260
+ "p": "payload"
261
+ },
262
+ {
263
+ "p": "topic",
264
+ "vt": "str"
265
+ }
266
+ ],
267
+ "repeat": "",
268
+ "crontab": "",
269
+ "once": false,
270
+ "onceDelay": 0.1,
271
+ "topic": "",
272
+ "payload": "{\"On\": false}",
273
+ "payloadType": "json",
274
+ "x": 110,
275
+ "y": 340,
276
+ "wires": [
277
+ [
278
+ "6703815a8874b156"
279
+ ]
280
+ ]
281
+ },
282
+ {
283
+ "id": "7eae7b87f319966e",
284
+ "type": "inject",
285
+ "z": "caef1e7b5b399e80",
286
+ "name": "",
287
+ "props": [
288
+ {
289
+ "p": "payload"
290
+ },
291
+ {
292
+ "p": "topic",
293
+ "vt": "str"
294
+ }
295
+ ],
296
+ "repeat": "",
297
+ "crontab": "",
298
+ "once": false,
299
+ "onceDelay": 0.1,
300
+ "topic": "",
301
+ "payload": "",
302
+ "payloadType": "date",
303
+ "x": 320,
304
+ "y": 260,
305
+ "wires": [
306
+ [
307
+ "6703815a8874b156",
308
+ "0ed3cd7e0d60beda"
309
+ ]
310
+ ]
311
+ },
312
+ {
313
+ "id": "6a7b40f6149f2d36",
314
+ "type": "inject",
315
+ "z": "caef1e7b5b399e80",
316
+ "name": "",
317
+ "props": [
318
+ {
319
+ "p": "payload"
320
+ },
321
+ {
322
+ "p": "topic",
323
+ "vt": "str"
324
+ }
325
+ ],
326
+ "repeat": "",
327
+ "crontab": "",
328
+ "once": false,
329
+ "onceDelay": 0.1,
330
+ "topic": "",
331
+ "payload": "{\"Off\": false}",
332
+ "payloadType": "json",
333
+ "x": 110,
129
334
  "y": 380,
130
335
  "wires": [
131
- []
336
+ [
337
+ "6703815a8874b156"
338
+ ]
132
339
  ]
133
340
  },
134
341
  {
135
- "id": "452e3e6171aa7a25",
136
- "type": "hb-resume",
342
+ "id": "80ffdbb93cd24b48",
343
+ "type": "inject",
344
+ "z": "caef1e7b5b399e80",
345
+ "name": "",
346
+ "props": [
347
+ {
348
+ "p": "payload"
349
+ },
350
+ {
351
+ "p": "topic",
352
+ "vt": "str"
353
+ }
354
+ ],
355
+ "repeat": "",
356
+ "crontab": "",
357
+ "once": false,
358
+ "onceDelay": 0.1,
359
+ "topic": "",
360
+ "payload": "{\"On\": true}",
361
+ "payloadType": "json",
362
+ "x": 110,
363
+ "y": 80,
364
+ "wires": [
365
+ [
366
+ "452e3e6171aa7a25"
367
+ ]
368
+ ]
369
+ },
370
+ {
371
+ "id": "d0e413b3c28f757a",
372
+ "type": "inject",
373
+ "z": "caef1e7b5b399e80",
374
+ "name": "",
375
+ "props": [
376
+ {
377
+ "p": "payload"
378
+ },
379
+ {
380
+ "p": "topic",
381
+ "vt": "str"
382
+ }
383
+ ],
384
+ "repeat": "",
385
+ "crontab": "",
386
+ "once": false,
387
+ "onceDelay": 0.1,
388
+ "topic": "",
389
+ "payload": "{\"On\": false}",
390
+ "payloadType": "json",
391
+ "x": 110,
392
+ "y": 140,
393
+ "wires": [
394
+ [
395
+ "452e3e6171aa7a25"
396
+ ]
397
+ ]
398
+ },
399
+ {
400
+ "id": "82638dac6ac32bb1",
401
+ "type": "hb-event",
137
402
  "z": "caef1e7b5b399e80",
138
403
  "name": "West Bedroom",
139
404
  "Homebridge": "homebridge",
@@ -141,19 +406,20 @@
141
406
  "Service": "Lightbulb",
142
407
  "device": "homebridge1C:22:3D:E3:CF:34TasmotaWest Bedroom00000043",
143
408
  "conf": "557aec8e8c47e61e",
144
- "x": 480,
145
- "y": 460,
409
+ "sendInitialState": true,
410
+ "x": 500,
411
+ "y": 100,
146
412
  "wires": [
147
413
  [
148
- "1093ab38b01fd39f"
414
+ "a866ae0bb24ce682"
149
415
  ]
150
416
  ]
151
417
  },
152
418
  {
153
- "id": "1093ab38b01fd39f",
419
+ "id": "f194fc4bcb1997a9",
154
420
  "type": "debug",
155
421
  "z": "caef1e7b5b399e80",
156
- "name": "debug 3",
422
+ "name": "debug 4",
157
423
  "active": true,
158
424
  "tosidebar": true,
159
425
  "console": false,
@@ -163,26 +429,137 @@
163
429
  "statusVal": "payload",
164
430
  "statusType": "auto",
165
431
  "x": 800,
166
- "y": 460,
432
+ "y": 300,
167
433
  "wires": []
168
434
  },
169
435
  {
170
- "id": "0ed3cd7e0d60beda",
436
+ "id": "12ce98441601c981",
437
+ "type": "hb-event",
438
+ "z": "caef1e7b5b399e80",
439
+ "name": "Driveway",
440
+ "Homebridge": "ECI-T24F2",
441
+ "Manufacturer": "HikVision",
442
+ "Service": "MotionSensor",
443
+ "device": "ECI-T24F2CB:6F:94:DD:43:77HikVisionDriveway00000085",
444
+ "conf": "557aec8e8c47e61e",
445
+ "sendInitialState": true,
446
+ "x": 320,
447
+ "y": 520,
448
+ "wires": [
449
+ [
450
+ "e2919464e7c4ab5c",
451
+ "08bc0ab3e3f2439f"
452
+ ]
453
+ ]
454
+ },
455
+ {
456
+ "id": "6216377792cba653",
171
457
  "type": "hb-control",
172
458
  "z": "caef1e7b5b399e80",
173
- "name": "West Bedroom",
174
- "Homebridge": "homebridge",
175
- "Manufacturer": "Tasmota",
176
- "Service": "Lightbulb",
177
- "device": "homebridge1C:22:3D:E3:CF:34TasmotaWest Bedroom00000043",
459
+ "name": "Driveway 8E52",
460
+ "Homebridge": "ECI-T24F2",
461
+ "Manufacturer": "HikVision",
462
+ "Service": "CameraRTPStreamManagement",
463
+ "device": "ECI-T24F2CB:6F:94:DD:43:77HikVisionDriveway 8E5200000110",
178
464
  "conf": "557aec8e8c47e61e",
179
- "outputs": 0,
180
- "x": 500,
181
- "y": 600,
465
+ "outputs": 1,
466
+ "x": 940,
467
+ "y": 500,
468
+ "wires": [
469
+ [
470
+ "9dc75e95be7ba465",
471
+ "12d2a40f6441c49c"
472
+ ]
473
+ ]
474
+ },
475
+ {
476
+ "id": "08bc0ab3e3f2439f",
477
+ "type": "debug",
478
+ "z": "caef1e7b5b399e80",
479
+ "name": "debug 5",
480
+ "active": true,
481
+ "tosidebar": true,
482
+ "console": false,
483
+ "tostatus": true,
484
+ "complete": "true",
485
+ "targetType": "full",
486
+ "statusVal": "payload",
487
+ "statusType": "auto",
488
+ "x": 600,
489
+ "y": 580,
182
490
  "wires": []
183
491
  },
184
492
  {
185
- "id": "24660f9d2862cee9",
493
+ "id": "e2919464e7c4ab5c",
494
+ "type": "switch",
495
+ "z": "caef1e7b5b399e80",
496
+ "name": "",
497
+ "property": "payload.MotionDetected",
498
+ "propertyType": "msg",
499
+ "rules": [
500
+ {
501
+ "t": "eq",
502
+ "v": "1",
503
+ "vt": "num"
504
+ }
505
+ ],
506
+ "checkall": "true",
507
+ "repair": false,
508
+ "outputs": 1,
509
+ "x": 590,
510
+ "y": 500,
511
+ "wires": [
512
+ [
513
+ "4982be53458df3a8"
514
+ ]
515
+ ]
516
+ },
517
+ {
518
+ "id": "4982be53458df3a8",
519
+ "type": "change",
520
+ "z": "caef1e7b5b399e80",
521
+ "name": "",
522
+ "rules": [
523
+ {
524
+ "t": "set",
525
+ "p": "payload",
526
+ "pt": "msg",
527
+ "to": "",
528
+ "tot": "date"
529
+ }
530
+ ],
531
+ "action": "",
532
+ "property": "",
533
+ "from": "",
534
+ "to": "",
535
+ "reg": false,
536
+ "x": 740,
537
+ "y": 500,
538
+ "wires": [
539
+ [
540
+ "6216377792cba653"
541
+ ]
542
+ ]
543
+ },
544
+ {
545
+ "id": "9dc75e95be7ba465",
546
+ "type": "debug",
547
+ "z": "caef1e7b5b399e80",
548
+ "name": "debug 6",
549
+ "active": true,
550
+ "tosidebar": true,
551
+ "console": false,
552
+ "tostatus": true,
553
+ "complete": "true",
554
+ "targetType": "full",
555
+ "statusVal": "payload",
556
+ "statusType": "msg",
557
+ "x": 1120,
558
+ "y": 500,
559
+ "wires": []
560
+ },
561
+ {
562
+ "id": "25a7fbf22f944415",
186
563
  "type": "inject",
187
564
  "z": "caef1e7b5b399e80",
188
565
  "name": "",
@@ -200,18 +577,89 @@
200
577
  "once": false,
201
578
  "onceDelay": 0.1,
202
579
  "topic": "",
203
- "payload": "",
204
- "payloadType": "date",
205
- "x": 200,
206
- "y": 600,
580
+ "payload": "{ \"MotionDetected\": 1 }",
581
+ "payloadType": "json",
582
+ "x": 340,
583
+ "y": 460,
207
584
  "wires": [
208
585
  [
209
- "0ed3cd7e0d60beda"
586
+ "e2919464e7c4ab5c"
587
+ ]
588
+ ]
589
+ },
590
+ {
591
+ "id": "12d2a40f6441c49c",
592
+ "type": "file",
593
+ "z": "caef1e7b5b399e80",
594
+ "name": "",
595
+ "filename": "/Users/sgracey/Desktop/image.jpeg",
596
+ "filenameType": "str",
597
+ "appendNewline": false,
598
+ "createDir": false,
599
+ "overwriteFile": "true",
600
+ "encoding": "none",
601
+ "x": 1210,
602
+ "y": 620,
603
+ "wires": [
604
+ []
605
+ ]
606
+ },
607
+ {
608
+ "id": "4b787bfb023ccf23",
609
+ "type": "hb-event",
610
+ "z": "caef1e7b5b399e80",
611
+ "name": "Backyard",
612
+ "Homebridge": "Default Model",
613
+ "Manufacturer": "NRCHKB",
614
+ "Service": "TemperatureSensor",
615
+ "device": "Default Model69:62:B7:AE:38:D4NRCHKBBackyard0000008A",
616
+ "conf": "557aec8e8c47e61e",
617
+ "sendInitialState": true,
618
+ "x": 160,
619
+ "y": 660,
620
+ "wires": [
621
+ [
622
+ "c68bef6563c5d07e"
623
+ ]
624
+ ]
625
+ },
626
+ {
627
+ "id": "c68bef6563c5d07e",
628
+ "type": "debug",
629
+ "z": "caef1e7b5b399e80",
630
+ "name": "debug 7",
631
+ "active": true,
632
+ "tosidebar": true,
633
+ "console": false,
634
+ "tostatus": true,
635
+ "complete": "payload",
636
+ "targetType": "msg",
637
+ "statusVal": "payload",
638
+ "statusType": "auto",
639
+ "x": 620,
640
+ "y": 740,
641
+ "wires": []
642
+ },
643
+ {
644
+ "id": "3c36252a6f45eed9",
645
+ "type": "hb-status",
646
+ "z": "caef1e7b5b399e80",
647
+ "name": "Backyard Tree",
648
+ "Homebridge": "Default Model",
649
+ "Manufacturer": "NRCHKB",
650
+ "Service": "TemperatureSensor",
651
+ "device": "Default Model69:62:B7:AE:38:D4NRCHKBBackyard Tree0000008A",
652
+ "conf": "557aec8e8c47e61e",
653
+ "x": 360,
654
+ "y": 800,
655
+ "wires": [
656
+ [
657
+ "c68bef6563c5d07e"
210
658
  ]
211
659
  ]
212
660
  },
213
661
  {
214
- "id": "d9f8181e9e6b3cfd",
662
+ "id": "3b7537939b63eee8",
215
663
  "type": "inject",
216
664
  "z": "caef1e7b5b399e80",
217
665
  "name": "",
@@ -231,12 +679,85 @@
231
679
  "topic": "",
232
680
  "payload": "",
233
681
  "payloadType": "date",
234
- "x": 210,
235
- "y": 460,
682
+ "x": 150,
683
+ "y": 800,
236
684
  "wires": [
237
685
  [
238
- "452e3e6171aa7a25"
686
+ "3c36252a6f45eed9"
687
+ ]
688
+ ]
689
+ },
690
+ {
691
+ "id": "aabce5ff7fbbeec6",
692
+ "type": "status",
693
+ "z": "caef1e7b5b399e80",
694
+ "name": "",
695
+ "scope": [
696
+ "3d7babac3a298e60",
697
+ "452e3e6171aa7a25",
698
+ "0ed3cd7e0d60beda",
699
+ "6703815a8874b156",
700
+ "82638dac6ac32bb1",
701
+ "6216377792cba653",
702
+ "12ce98441601c981",
703
+ "4b787bfb023ccf23",
704
+ "3c36252a6f45eed9"
705
+ ],
706
+ "x": 1020,
707
+ "y": 380,
708
+ "wires": [
709
+ [
710
+ "94f051597d18eaa3"
711
+ ]
712
+ ]
713
+ },
714
+ {
715
+ "id": "94f051597d18eaa3",
716
+ "type": "debug",
717
+ "z": "caef1e7b5b399e80",
718
+ "name": "Status",
719
+ "active": true,
720
+ "tosidebar": true,
721
+ "console": false,
722
+ "tostatus": true,
723
+ "complete": "true",
724
+ "targetType": "full",
725
+ "statusVal": "status.source.name",
726
+ "statusType": "msg",
727
+ "x": 1190,
728
+ "y": 380,
729
+ "wires": []
730
+ },
731
+ {
732
+ "id": "296297c79b544f59",
733
+ "type": "catch",
734
+ "z": "caef1e7b5b399e80",
735
+ "name": "",
736
+ "scope": null,
737
+ "uncaught": false,
738
+ "x": 1020,
739
+ "y": 300,
740
+ "wires": [
741
+ [
742
+ "0073218b1ebc53f1"
239
743
  ]
240
744
  ]
745
+ },
746
+ {
747
+ "id": "0073218b1ebc53f1",
748
+ "type": "debug",
749
+ "z": "caef1e7b5b399e80",
750
+ "name": "Catch",
751
+ "active": true,
752
+ "tosidebar": true,
753
+ "console": false,
754
+ "tostatus": true,
755
+ "complete": "true",
756
+ "targetType": "full",
757
+ "statusVal": "payload",
758
+ "statusType": "msg",
759
+ "x": 1190,
760
+ "y": 300,
761
+ "wires": []
241
762
  }
242
763
  ]
@@ -243,7 +243,7 @@
243
243
  "payload": "{\"On\": true}",
244
244
  "payloadType": "json",
245
245
  "x": 110,
246
- "y": 280,
246
+ "y": 300,
247
247
  "wires": [
248
248
  [
249
249
  "6703815a8874b156"
@@ -436,14 +436,14 @@
436
436
  "id": "12ce98441601c981",
437
437
  "type": "hb-event",
438
438
  "z": "caef1e7b5b399e80",
439
- "name": "Driveway 8E52",
439
+ "name": "Driveway",
440
440
  "Homebridge": "ECI-T24F2",
441
441
  "Manufacturer": "HikVision",
442
- "Service": "CameraRTPStreamManagement",
443
- "device": "ECI-T24F2CB:6F:94:DD:43:77HikVisionDriveway 8E5200000110",
442
+ "Service": "MotionSensor",
443
+ "device": "ECI-T24F2CB:6F:94:DD:43:77HikVisionDriveway00000085",
444
444
  "conf": "557aec8e8c47e61e",
445
445
  "sendInitialState": true,
446
- "x": 340,
446
+ "x": 320,
447
447
  "y": 520,
448
448
  "wires": [
449
449
  [
@@ -603,5 +603,161 @@
603
603
  "wires": [
604
604
  []
605
605
  ]
606
+ },
607
+ {
608
+ "id": "4b787bfb023ccf23",
609
+ "type": "hb-event",
610
+ "z": "caef1e7b5b399e80",
611
+ "name": "Backyard",
612
+ "Homebridge": "Default Model",
613
+ "Manufacturer": "NRCHKB",
614
+ "Service": "TemperatureSensor",
615
+ "device": "Default Model69:62:B7:AE:38:D4NRCHKBBackyard0000008A",
616
+ "conf": "557aec8e8c47e61e",
617
+ "sendInitialState": true,
618
+ "x": 160,
619
+ "y": 660,
620
+ "wires": [
621
+ [
622
+ "c68bef6563c5d07e"
623
+ ]
624
+ ]
625
+ },
626
+ {
627
+ "id": "c68bef6563c5d07e",
628
+ "type": "debug",
629
+ "z": "caef1e7b5b399e80",
630
+ "name": "debug 7",
631
+ "active": true,
632
+ "tosidebar": true,
633
+ "console": false,
634
+ "tostatus": true,
635
+ "complete": "payload",
636
+ "targetType": "msg",
637
+ "statusVal": "payload",
638
+ "statusType": "auto",
639
+ "x": 620,
640
+ "y": 740,
641
+ "wires": []
642
+ },
643
+ {
644
+ "id": "3c36252a6f45eed9",
645
+ "type": "hb-status",
646
+ "z": "caef1e7b5b399e80",
647
+ "name": "Backyard Tree",
648
+ "Homebridge": "Default Model",
649
+ "Manufacturer": "NRCHKB",
650
+ "Service": "TemperatureSensor",
651
+ "device": "Default Model69:62:B7:AE:38:D4NRCHKBBackyard Tree0000008A",
652
+ "conf": "557aec8e8c47e61e",
653
+ "x": 360,
654
+ "y": 800,
655
+ "wires": [
656
+ [
657
+ "c68bef6563c5d07e"
658
+ ]
659
+ ]
660
+ },
661
+ {
662
+ "id": "3b7537939b63eee8",
663
+ "type": "inject",
664
+ "z": "caef1e7b5b399e80",
665
+ "name": "",
666
+ "props": [
667
+ {
668
+ "p": "payload"
669
+ },
670
+ {
671
+ "p": "topic",
672
+ "vt": "str"
673
+ }
674
+ ],
675
+ "repeat": "60",
676
+ "crontab": "",
677
+ "once": true,
678
+ "onceDelay": "60",
679
+ "topic": "",
680
+ "payload": "",
681
+ "payloadType": "date",
682
+ "x": 150,
683
+ "y": 800,
684
+ "wires": [
685
+ [
686
+ "3c36252a6f45eed9"
687
+ ]
688
+ ]
689
+ },
690
+ {
691
+ "id": "aabce5ff7fbbeec6",
692
+ "type": "status",
693
+ "z": "caef1e7b5b399e80",
694
+ "name": "",
695
+ "scope": [
696
+ "3d7babac3a298e60",
697
+ "452e3e6171aa7a25",
698
+ "0ed3cd7e0d60beda",
699
+ "6703815a8874b156",
700
+ "82638dac6ac32bb1",
701
+ "6216377792cba653",
702
+ "12ce98441601c981",
703
+ "4b787bfb023ccf23",
704
+ "3c36252a6f45eed9"
705
+ ],
706
+ "x": 1020,
707
+ "y": 380,
708
+ "wires": [
709
+ [
710
+ "94f051597d18eaa3"
711
+ ]
712
+ ]
713
+ },
714
+ {
715
+ "id": "94f051597d18eaa3",
716
+ "type": "debug",
717
+ "z": "caef1e7b5b399e80",
718
+ "name": "Status",
719
+ "active": true,
720
+ "tosidebar": true,
721
+ "console": false,
722
+ "tostatus": true,
723
+ "complete": "true",
724
+ "targetType": "full",
725
+ "statusVal": "status.source.name",
726
+ "statusType": "msg",
727
+ "x": 1190,
728
+ "y": 380,
729
+ "wires": []
730
+ },
731
+ {
732
+ "id": "296297c79b544f59",
733
+ "type": "catch",
734
+ "z": "caef1e7b5b399e80",
735
+ "name": "",
736
+ "scope": null,
737
+ "uncaught": false,
738
+ "x": 1020,
739
+ "y": 300,
740
+ "wires": [
741
+ [
742
+ "0073218b1ebc53f1"
743
+ ]
744
+ ]
745
+ },
746
+ {
747
+ "id": "0073218b1ebc53f1",
748
+ "type": "debug",
749
+ "z": "caef1e7b5b399e80",
750
+ "name": "Catch",
751
+ "active": true,
752
+ "tosidebar": true,
753
+ "console": false,
754
+ "tostatus": true,
755
+ "complete": "true",
756
+ "targetType": "full",
757
+ "statusVal": "payload",
758
+ "statusType": "msg",
759
+ "x": 1190,
760
+ "y": 280,
761
+ "wires": []
606
762
  }
607
763
  ]