node-red-contrib-homebridge-automation 0.1.12-beta.25 → 0.1.12-beta.26
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 +1 -1
- package/src/hbBaseNode.js +112 -106
- package/src/hbConfigNode.js +7 -6
- package/src/hbEventNode.js +9 -8
- package/src/hbStatusNode.js +1 -2
- package/test/node-red/flows.json +34 -6
package/package.json
CHANGED
package/src/hbBaseNode.js
CHANGED
|
@@ -38,127 +38,133 @@ class HbBaseNode {
|
|
|
38
38
|
this.send({ payload: service.values });
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
createMessage(
|
|
41
|
+
createMessage(service) {
|
|
42
42
|
return {
|
|
43
|
-
name: this.
|
|
44
|
-
payload:
|
|
45
|
-
Homebridge:
|
|
46
|
-
Manufacturer:
|
|
47
|
-
Service:
|
|
48
|
-
_device: this.
|
|
49
|
-
_confId: this.
|
|
50
|
-
_rawEvent: isInitialState ? event : undefined,
|
|
43
|
+
name: this.name,
|
|
44
|
+
payload: service.values,
|
|
45
|
+
Homebridge: service.instance.name,
|
|
46
|
+
Manufacturer: service.accessoryInformation.Manufacturer,
|
|
47
|
+
Service: service.type,
|
|
48
|
+
_device: this.device,
|
|
49
|
+
_confId: this.confId,
|
|
51
50
|
};
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
debug("Registering node:", this.fullName);
|
|
56
|
-
this.hbDevice = hbDevices.findDevice(this.device);
|
|
57
|
-
|
|
58
|
-
if (!this.hbDevice) {
|
|
59
|
-
this.error(`Device not found: ${this.device}`);
|
|
60
|
-
} else {
|
|
61
|
-
this.deviceType = this.hbDevice.deviceType;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
handleClose(callback) {
|
|
53
|
+
handleClose(removed, done) {
|
|
66
54
|
debug('close', this.name);
|
|
67
|
-
|
|
55
|
+
done();
|
|
68
56
|
}
|
|
69
57
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
});
|
|
58
|
+
/*
|
|
59
|
+
registerNode() {
|
|
60
|
+
debug("Registering node:", this.fullName);
|
|
61
|
+
this.hbDevice = hbDevices.findDevice(this.device);
|
|
62
|
+
|
|
63
|
+
if (!this.hbDevice) {
|
|
64
|
+
this.error(`Device not found: ${this.device}`);
|
|
65
|
+
} else {
|
|
66
|
+
this.deviceType = this.hbDevice.deviceType;
|
|
81
67
|
}
|
|
82
|
-
} else {
|
|
83
|
-
payload = hbMessage.payload;
|
|
84
68
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
69
|
+
|
|
70
|
+
handleClose(callback) {
|
|
71
|
+
debug('close', this.name);
|
|
72
|
+
callback();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_convertHBcharacteristicToNode(hbMessage, node) {
|
|
76
|
+
let payload = {};
|
|
77
|
+
if (!hbMessage.payload) {
|
|
78
|
+
const device = hbDevices.findDevice(node.device);
|
|
79
|
+
if (device) {
|
|
80
|
+
hbMessage.forEach(characteristic => {
|
|
81
|
+
const charKey = `${characteristic.aid}.${characteristic.iid}`;
|
|
82
|
+
if (device.characteristics[charKey]) {
|
|
83
|
+
payload[device.characteristics[charKey].characteristic] = characteristic.value;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
98
87
|
} else {
|
|
99
|
-
|
|
100
|
-
node.status({ text: `Invalid characteristic: ${key}`, shape: 'ring', fill: 'yellow' });
|
|
88
|
+
payload = hbMessage.payload;
|
|
101
89
|
}
|
|
90
|
+
return payload;
|
|
102
91
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return device.type === "00000110" || device.type === "00000111"
|
|
121
|
-
? { characteristics: { payload: this.btoa(status) } }
|
|
122
|
-
: status;
|
|
123
|
-
} catch (err) {
|
|
124
|
-
debug("Error in _status:", err);
|
|
125
|
-
node.status({ text: 'Error retrieving status', shape: 'ring', fill: 'red' });
|
|
126
|
-
throw err;
|
|
92
|
+
|
|
93
|
+
_createControlMessage(payload, node, device) {
|
|
94
|
+
const response = [];
|
|
95
|
+
for (const key in payload) {
|
|
96
|
+
const characteristic = this._getKey(device.characteristics, key);
|
|
97
|
+
if (characteristic) {
|
|
98
|
+
response.push({
|
|
99
|
+
aid: device.aid,
|
|
100
|
+
iid: characteristic.iid,
|
|
101
|
+
value: payload[key],
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
this.warn(`Invalid characteristic: '${key}'. Available: ${device.descriptions}`);
|
|
105
|
+
node.status({ text: `Invalid characteristic: ${key}`, shape: 'ring', fill: 'yellow' });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { characteristics: response };
|
|
127
109
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const message =
|
|
135
|
-
|
|
110
|
+
|
|
111
|
+
async _status(nrDevice, node, perms) {
|
|
112
|
+
try {
|
|
113
|
+
const device = hbDevices.findDevice(node.device, perms);
|
|
114
|
+
if (!device) throw new Error(`Device not found: ${nrDevice}`);
|
|
115
|
+
|
|
116
|
+
const message = device.type === "00000110" || device.type === "00000111"
|
|
117
|
+
? { "resource-type": "image", "image-width": 1920, "image-height": 1080 }
|
|
118
|
+
: `?id=${device.getCharacteristics}`;
|
|
119
|
+
|
|
120
|
+
const status = device.type === "00000110" || device.type === "00000111"
|
|
121
|
+
? await this.HAPresourceByDeviceIDAsync(device.id, JSON.stringify(message))
|
|
122
|
+
: await this.HAPstatusByDeviceIDAsync(device.id, message);
|
|
123
|
+
|
|
124
|
+
node.status({ text: 'Success', shape: 'dot', fill: 'green' });
|
|
125
|
+
return device.type === "00000110" || device.type === "00000111"
|
|
126
|
+
? { characteristics: { payload: this.btoa(status) } }
|
|
127
|
+
: status;
|
|
128
|
+
} catch (err) {
|
|
129
|
+
debug("Error in _status:", err);
|
|
130
|
+
node.status({ text: 'Error retrieving status', shape: 'ring', fill: 'red' });
|
|
131
|
+
throw err;
|
|
136
132
|
}
|
|
137
|
-
} catch (err) {
|
|
138
|
-
debug("Error in _register:", err);
|
|
139
|
-
node.status({ text: 'Register error', shape: 'ring', fill: 'red' });
|
|
140
133
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
134
|
+
|
|
135
|
+
async _register(node) {
|
|
136
|
+
try {
|
|
137
|
+
const device = hbDevices.findDevice(node.device, { perms: 'ev' });
|
|
138
|
+
if (device) {
|
|
139
|
+
const message = { characteristics: device.eventRegisters };
|
|
140
|
+
await hapEventByDeviceIDAsync(device.id, JSON.stringify(message));
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
debug("Error in _register:", err);
|
|
144
|
+
node.status({ text: 'Register error', shape: 'ring', fill: 'red' });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_getKey(obj, value) {
|
|
149
|
+
return Object.values(obj).find(char => char.characteristic.toLowerCase() === value.toLowerCase()) || null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
btoa(str) {
|
|
153
|
+
return Buffer.from(str.toString(), 'binary').toString('base64');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async HAPresourceByDeviceIDAsync(deviceId, message) {
|
|
157
|
+
return new Promise((resolve, reject) => {
|
|
158
|
+
homebridge.HAPresourceByDeviceID(deviceId, message, (err, status) => err ? reject(err) : resolve(status));
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async HAPstatusByDeviceIDAsync(deviceId, message) {
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
homebridge.HAPstatusByDeviceID(deviceId, message, (err, status) => err ? reject(err) : resolve(status));
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
*/
|
|
162
168
|
}
|
|
163
169
|
|
|
164
170
|
module.exports = HbBaseNode;
|
package/src/hbConfigNode.js
CHANGED
|
@@ -152,17 +152,18 @@ class HBConfigNode {
|
|
|
152
152
|
}
|
|
153
153
|
cb(null);
|
|
154
154
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
155
|
+
/*
|
|
156
|
+
deregister(clientNode) {
|
|
157
|
+
clientNode.status({ text: 'disconnected', shape: 'ring', fill: 'red' });
|
|
158
|
+
delete this.clientNodes[clientNode.id];
|
|
159
|
+
}
|
|
160
|
+
*/
|
|
161
161
|
close() {
|
|
162
162
|
if (this.hapClient) {
|
|
163
163
|
this.hapClient.destroy();
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
+
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
module.exports = HBConfigNode;
|
package/src/hbEventNode.js
CHANGED
|
@@ -9,15 +9,16 @@ class HbEventNode extends hbBaseNode {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
handleHbReady(service) {
|
|
12
|
-
this.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
debug('handleHbReady', this.id, this.name, service.values)
|
|
13
|
+
if (this.sendInitialState) {
|
|
14
|
+
this.status({
|
|
15
|
+
text: JSON.stringify(service.values),
|
|
16
|
+
shape: 'dot',
|
|
17
|
+
fill: 'green',
|
|
18
|
+
});
|
|
19
|
+
this.send({ ...this.createMessage(service) });
|
|
20
|
+
}
|
|
18
21
|
}
|
|
19
|
-
// Create a message payload for event or initial state
|
|
20
|
-
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
module.exports = HbEventNode;
|
package/src/hbStatusNode.js
CHANGED
package/test/node-red/flows.json
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"tosidebar": true,
|
|
23
23
|
"console": false,
|
|
24
24
|
"tostatus": true,
|
|
25
|
-
"complete": "
|
|
26
|
-
"targetType": "
|
|
25
|
+
"complete": "true",
|
|
26
|
+
"targetType": "full",
|
|
27
27
|
"statusVal": "payload",
|
|
28
28
|
"statusType": "auto",
|
|
29
29
|
"x": 800,
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"tosidebar": true,
|
|
40
40
|
"console": false,
|
|
41
41
|
"tostatus": true,
|
|
42
|
-
"complete": "
|
|
43
|
-
"targetType": "
|
|
42
|
+
"complete": "true",
|
|
43
|
+
"targetType": "full",
|
|
44
44
|
"statusVal": "payload",
|
|
45
45
|
"statusType": "auto",
|
|
46
46
|
"x": 800,
|
|
@@ -72,8 +72,7 @@
|
|
|
72
72
|
"y": 140,
|
|
73
73
|
"wires": [
|
|
74
74
|
[
|
|
75
|
-
"3d7babac3a298e60"
|
|
76
|
-
"452e3e6171aa7a25"
|
|
75
|
+
"3d7babac3a298e60"
|
|
77
76
|
]
|
|
78
77
|
]
|
|
79
78
|
},
|
|
@@ -440,5 +439,34 @@
|
|
|
440
439
|
"a866ae0bb24ce682"
|
|
441
440
|
]
|
|
442
441
|
]
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"id": "56633636bd2e624c",
|
|
445
|
+
"type": "inject",
|
|
446
|
+
"z": "caef1e7b5b399e80",
|
|
447
|
+
"name": "",
|
|
448
|
+
"props": [
|
|
449
|
+
{
|
|
450
|
+
"p": "payload"
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"p": "topic",
|
|
454
|
+
"vt": "str"
|
|
455
|
+
}
|
|
456
|
+
],
|
|
457
|
+
"repeat": "60",
|
|
458
|
+
"crontab": "",
|
|
459
|
+
"once": true,
|
|
460
|
+
"onceDelay": "60",
|
|
461
|
+
"topic": "",
|
|
462
|
+
"payload": "",
|
|
463
|
+
"payloadType": "date",
|
|
464
|
+
"x": 190,
|
|
465
|
+
"y": 280,
|
|
466
|
+
"wires": [
|
|
467
|
+
[
|
|
468
|
+
"452e3e6171aa7a25"
|
|
469
|
+
]
|
|
470
|
+
]
|
|
443
471
|
}
|
|
444
472
|
]
|