node-red-contrib-homebridge-automation 0.3.0-beta.1 → 0.3.0-beta.10
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/README.md +54 -53
- package/package.json +2 -2
- package/src/HAP-NodeRed.html +18 -1
- package/src/hbConfigNode.js +12 -8
- package/src/hbConfigNode.test.js +11 -14
- package/src/hbControlNode.js +0 -1
- package/test/homebridge-automation-endpoints.json +7740 -7736
- package/test/homebridge-automation-hbDevices-v3.json +19 -19
- package/test/node-red/flows.json +285 -2
package/README.md
CHANGED
|
@@ -9,59 +9,59 @@ The above Node-RED Flow, turns on my 'Outside Office' light when the powder room
|
|
|
9
9
|
# Table of Contents
|
|
10
10
|
|
|
11
11
|
<!--ts-->
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
12
|
+
* [Homebridge Automation powered by Node-RED](#homebridge-automation-powered-by-node-red)
|
|
13
|
+
* [Table of Contents](#table-of-contents)
|
|
14
|
+
* [Introduction](#introduction)
|
|
15
|
+
* [Caveats](#caveats)
|
|
16
|
+
* [Changes](#changes)
|
|
17
|
+
* [Mar 18, 2019 - Version 0.0.39](#mar-18-2019---version-0039)
|
|
18
|
+
* [Mar 19, 2019 - Version 0.0.42](#mar-19-2019---version-0042)
|
|
19
|
+
* [Mar 31, 2019 - Version 0.0.](#mar-31-2019---version-00)
|
|
20
|
+
* [May 9, 2019 - Version 0.0.43](#may-9-2019---version-0043)
|
|
21
|
+
* [May 15, 2019 - Version 0.0.44](#may-15-2019---version-0044)
|
|
22
|
+
* [May 29, 2019 - Version 0.0.45](#may-29-2019---version-0045)
|
|
23
|
+
* [July 27, 2019 - Version 0.0.50](#july-27-2019---version-0050)
|
|
24
|
+
* [Feb 24, 2020 - Version 0.0.56](#feb-24-2020---version-0056)
|
|
25
|
+
* [Mar 18, 2020 - Version 0.0.59](#mar-18-2020---version-0059)
|
|
26
|
+
* [Oct 13, 2020 - Version 0.0.71](#oct-13-2020---version-0071)
|
|
27
|
+
* [Oct 24, 2020 - Version 0.0.71](#oct-24-2020---version-0071)
|
|
28
|
+
* [Nov 1, 2020 - Version 0.0.73](#nov-1-2020---version-0073)
|
|
29
|
+
* [Nov 13, 2020 - Version 0.0.76](#nov-13-2020---version-0076)
|
|
30
|
+
* [Feb 2, 2021 - Version 0.0.78](#feb-2-2021---version-0078)
|
|
31
|
+
* [Mar 9, 2021 - Version 0.0.80](#mar-9-2021---version-0080)
|
|
32
|
+
* [April 23, 2021 - Version 0.0.82](#april-23-2021---version-0082)
|
|
33
|
+
* [Dec 31, 2022 - Version 0.1.3](#dec-31-2022---version-013)
|
|
34
|
+
* [Jan 6, 2023 - Version 0.1.5](#jan-6-2023---version-015)
|
|
35
|
+
* [Jan 11, 2023 - Version 0.1.7](#jan-11-2023---version-017)
|
|
36
|
+
* [Jan 15, 2023 - Version 0.1.8](#jan-15-2023---version-018)
|
|
37
|
+
* [Dec 15, 2024 - Version 0.2.0](#dec-15-2024---version-020)
|
|
38
|
+
* [April 15, 2025 - Version 0.3.0](#april-15-2025---version-030)
|
|
39
|
+
* [Breaking Change](#breaking-change)
|
|
40
|
+
* [Fixes](#fixes)
|
|
41
|
+
* [Backlog / Roadmap](#backlog--roadmap)
|
|
42
|
+
* [Dropped items](#dropped-items)
|
|
43
|
+
* [Installation Steps](#installation-steps)
|
|
44
|
+
* [1 - Install Node-RED and Homebridge](#1---install-node-red-and-homebridge)
|
|
45
|
+
* [2 - Prepare Homebridge for integration with Homebridge-Automation](#2---prepare-homebridge-for-integration-with-homebridge-automation)
|
|
46
|
+
* [3 - Install Homebridge-Automation into Node-Red](#3---install-homebridge-automation-into-node-red)
|
|
47
|
+
* [4 - Start Node-Red](#4---start-node-red)
|
|
48
|
+
* [5 - Initial setup and configuration inside Node-Red](#5---initial-setup-and-configuration-inside-node-red)
|
|
49
|
+
* [6 - Configure 'hb event' to receive updates from your Accessories](#6---configure-hb-event-to-receive-updates-from-your-accessories)
|
|
50
|
+
* [Node-RED Homebridge-Automation Message Structure](#node-red-homebridge-automation-message-structure)
|
|
51
|
+
* [hb event](#hb-event)
|
|
52
|
+
* [Output](#output)
|
|
53
|
+
* [hb resume](#hb-resume)
|
|
54
|
+
* [input](#input)
|
|
55
|
+
* [output](#output-1)
|
|
56
|
+
* [hb status](#hb-status)
|
|
57
|
+
* [input](#input-1)
|
|
58
|
+
* [output](#output-2)
|
|
59
|
+
* [hb control](#hb-control)
|
|
60
|
+
* [Input](#input-2)
|
|
61
|
+
* [Flows Shared from Community](#flows-shared-from-community)
|
|
62
|
+
* [Donations](#donations)
|
|
63
|
+
* [Troubleshooting / DEBUG MODE](#troubleshooting--debug-mode)
|
|
64
|
+
* [To start Node-RED in DEBUG mode, and output Homebridge-Automation debug logs start Node-RED like this.](#to-start-node-red-in-debug-mode-and-output-homebridge-automation-debug-logs-start-node-red-like-this)
|
|
65
65
|
<!--te-->
|
|
66
66
|
|
|
67
67
|
# Introduction
|
|
@@ -199,6 +199,7 @@ With a plugin, you can see if it supports Real Time events, by opening the Home
|
|
|
199
199
|
|
|
200
200
|
- Add common supported types Window, Window Covering, Light Sensor #151, tks @HDeKnop
|
|
201
201
|
- HB-Control Node Turns Off then On when this message is received #152
|
|
202
|
+
- Added `Debug logging` configuration option that creates a file `homebridge-automation-endpoints.json`, which contains all the homebridge devices discovered. It can be used as part of troubleshooting device issues.
|
|
202
203
|
|
|
203
204
|
# Backlog / Roadmap
|
|
204
205
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-homebridge-automation",
|
|
3
|
-
"version": "0.3.0-beta.
|
|
3
|
+
"version": "0.3.0-beta.10",
|
|
4
4
|
"description": "NodeRED Automation for HomeBridge",
|
|
5
5
|
"main": "src/HAP-NodeRed.js",
|
|
6
6
|
"scripts": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"better-queue": ">=3.8.12",
|
|
44
44
|
"debug": "^4.3.7",
|
|
45
|
-
"@homebridge/hap-client": "^2.1.0
|
|
45
|
+
"@homebridge/hap-client": "^2.1.0"
|
|
46
46
|
},
|
|
47
47
|
"author": "NorthernMan54",
|
|
48
48
|
"license": "ISC",
|
package/src/HAP-NodeRed.html
CHANGED
|
@@ -7,10 +7,23 @@
|
|
|
7
7
|
<label for="node-config-input-macAddress"><i class="icon-wifi"></i> MAC Address (optional)</label>
|
|
8
8
|
<input type="text" id="node-config-input-macAddress" placeholder="00:00:00:A1:2B:CC">
|
|
9
9
|
</div>
|
|
10
|
+
<div class="form-row">
|
|
11
|
+
<label for="node-config-input-debug"><i class="icon-tag"></i>Debug Logging</label>
|
|
12
|
+
<input type="checkbox" id="node-config-input-debug" placeholder=false>
|
|
13
|
+
</div>
|
|
10
14
|
</script>
|
|
11
15
|
|
|
12
16
|
<script type="text/x-red" data-help-name="hb-conf">
|
|
13
|
-
<p>
|
|
17
|
+
<p>Configuration Node for Homebridge</p>
|
|
18
|
+
<h3>Settings</h3>
|
|
19
|
+
<dl class="message-properties">
|
|
20
|
+
<dt>PIN<span class="property-type">string</span></dt>
|
|
21
|
+
<dd>Please enter the PIN from your homebridge instances. Please note that the same pin must be used for all instances.</dd>
|
|
22
|
+
<dt>MAC Address<span class="property-type">object</span></dt>
|
|
23
|
+
<dd>Optional - Not implemented</dd>
|
|
24
|
+
<dt>Debug Logging<span class="property-type">string</span></dt>
|
|
25
|
+
<dd>Enables debug logging and creates a file `homebridge-automation-endpoints.json`, which contains all the homebridge devices discovered. It can be used as part of troubleshooting device issues.</dd>
|
|
26
|
+
</dl>
|
|
14
27
|
</script>
|
|
15
28
|
|
|
16
29
|
<script type="text/javascript">
|
|
@@ -36,6 +49,10 @@
|
|
|
36
49
|
},
|
|
37
50
|
required: false
|
|
38
51
|
},
|
|
52
|
+
debug: {
|
|
53
|
+
value: false,
|
|
54
|
+
required: false
|
|
55
|
+
}
|
|
39
56
|
},
|
|
40
57
|
credentials: {
|
|
41
58
|
password: {
|
package/src/hbConfigNode.js
CHANGED
|
@@ -2,6 +2,7 @@ const { HapClient } = require('@homebridge/hap-client');
|
|
|
2
2
|
const debug = require('debug')('hapNodeRed:hbConfigNode');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const process = require('process');
|
|
5
6
|
|
|
6
7
|
class HBConfigNode {
|
|
7
8
|
constructor(config, RED) {
|
|
@@ -10,6 +11,7 @@ class HBConfigNode {
|
|
|
10
11
|
// Initialize properties
|
|
11
12
|
this.username = config.username;
|
|
12
13
|
this.macAddress = config.macAddress || '';
|
|
14
|
+
this.debugLogging = config.debug || false;
|
|
13
15
|
this.users = {};
|
|
14
16
|
this.homebridge = null;
|
|
15
17
|
this.evDevices = [];
|
|
@@ -53,14 +55,14 @@ class HBConfigNode {
|
|
|
53
55
|
*/
|
|
54
56
|
async handleReady() {
|
|
55
57
|
const updatedDevices = await this.hapClient.getAllServices();
|
|
56
|
-
if (this.
|
|
58
|
+
if (this.debugLogging && updatedDevices && updatedDevices.length && process.uptime() < 300) {
|
|
57
59
|
try {
|
|
58
|
-
const storagePath = path.join(process.cwd(), '
|
|
60
|
+
const storagePath = path.join(process.cwd(), 'homebridge-automation-endpoints.json');
|
|
59
61
|
this.warn(`Writing Homebridge endpoints to ${storagePath}`);
|
|
60
62
|
fs.writeFileSync(storagePath, JSON.stringify(updatedDevices, null, 2));
|
|
61
63
|
} catch (e) {
|
|
62
64
|
this.error(`Error writing Homebridge endpoints to file: ${e.message}`);
|
|
63
|
-
}
|
|
65
|
+
}
|
|
64
66
|
}
|
|
65
67
|
// Fix broken uniqueId's from HAP-Client
|
|
66
68
|
updatedDevices.forEach((service) => {
|
|
@@ -136,10 +138,12 @@ class HBConfigNode {
|
|
|
136
138
|
async connectClientNodes() {
|
|
137
139
|
debug('connect %s nodes', Object.keys(this.clientNodes).length);
|
|
138
140
|
for (const [key, clientNode] of Object.entries(this.clientNodes)) {
|
|
139
|
-
// debug('_Register: %s type: %s', clientNode.type, clientNode.name, clientNode.instance);
|
|
140
|
-
const matchedDevice = this.hbDevices.find(service =>
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
// debug('_Register: %s type: "%s" "%s" "%s"', clientNode.type, clientNode.name, clientNode.instance, clientNode.device);
|
|
142
|
+
const matchedDevice = this.hbDevices.find(service => {
|
|
143
|
+
const friendlyName = (service.accessoryInformation.Name ? service.accessoryInformation.Name : service.serviceName);
|
|
144
|
+
const deviceIdentifier = `${service.instance.name}${service.instance.username}${service.accessoryInformation.Manufacturer}${friendlyName}${service.uuid.slice(0, 8)}`;
|
|
145
|
+
return clientNode.device === deviceIdentifier;
|
|
146
|
+
});
|
|
143
147
|
|
|
144
148
|
if (matchedDevice) {
|
|
145
149
|
clientNode.hbDevice = matchedDevice;
|
|
@@ -147,7 +151,7 @@ class HBConfigNode {
|
|
|
147
151
|
clientNode.emit('hbReady', matchedDevice);
|
|
148
152
|
debug('_Registered: %s type: %s', clientNode.type, matchedDevice.type, matchedDevice.serviceName);
|
|
149
153
|
} else {
|
|
150
|
-
this.error(`ERROR: Device registration failed '${clientNode.fullName}'`);
|
|
154
|
+
this.error(`ERROR: Device registration failed '${clientNode.fullName}' - '${clientNode.device}'`);
|
|
151
155
|
}
|
|
152
156
|
};
|
|
153
157
|
|
package/src/hbConfigNode.test.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
const { HapClient } = require('@homebridge/hap-client');
|
|
1
|
+
// File: src/hbConfigNode.test.js
|
|
3
2
|
const HBConfigNode = require('./hbConfigNode'); // Update the path as necessary
|
|
4
3
|
const fs = require('fs');
|
|
5
4
|
const path = require('path');
|
|
5
|
+
const process = require('process');
|
|
6
6
|
|
|
7
7
|
jest.mock('@homebridge/hap-client', () => {
|
|
8
8
|
return {
|
|
@@ -16,11 +16,10 @@ jest.mock('@homebridge/hap-client', () => {
|
|
|
16
16
|
};
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
describe
|
|
19
|
+
describe('Issue 142', () => {
|
|
20
20
|
let mockConfig;
|
|
21
21
|
let RED;
|
|
22
22
|
let node;
|
|
23
|
-
let mockHapClient;
|
|
24
23
|
|
|
25
24
|
beforeEach(() => {
|
|
26
25
|
mockConfig = {
|
|
@@ -57,7 +56,6 @@ describe('HBConfigNode', () => {
|
|
|
57
56
|
let mockConfig;
|
|
58
57
|
let RED;
|
|
59
58
|
let node;
|
|
60
|
-
let mockHapClient;
|
|
61
59
|
|
|
62
60
|
beforeEach(() => {
|
|
63
61
|
mockConfig = {
|
|
@@ -90,11 +88,10 @@ describe('HBConfigNode', () => {
|
|
|
90
88
|
});
|
|
91
89
|
});
|
|
92
90
|
|
|
93
|
-
describe
|
|
91
|
+
describe('from files', () => {
|
|
94
92
|
let mockConfig;
|
|
95
93
|
let RED;
|
|
96
94
|
let node;
|
|
97
|
-
let mockHapClient;
|
|
98
95
|
|
|
99
96
|
beforeEach(() => {
|
|
100
97
|
mockConfig = {
|
|
@@ -114,10 +111,10 @@ describe.only('from files', () => {
|
|
|
114
111
|
node.log = console.log;
|
|
115
112
|
});
|
|
116
113
|
|
|
117
|
-
test('Retrieve devices, and compare with current (v2)', async () => {
|
|
118
|
-
console.log('Reading Homebridge endpoints from file', process.cwd());
|
|
114
|
+
test.skip('Retrieve devices, and compare with current (v2)', async () => {
|
|
115
|
+
// console.log('Reading Homebridge endpoints from file', process.cwd());
|
|
119
116
|
var storagePath = path.join(process.cwd(), 'test/homebridge-automation-endpoints.json');
|
|
120
|
-
console.log(`Reading Homebridge endpoints from ${storagePath}`);
|
|
117
|
+
// console.log(`Reading Homebridge endpoints from ${storagePath}`);
|
|
121
118
|
const fileHbDevices = JSON.parse(fs.readFileSync(storagePath, 'utf8'));
|
|
122
119
|
|
|
123
120
|
node.hapClient.getAllServices.mockResolvedValue(fileHbDevices);
|
|
@@ -126,7 +123,7 @@ describe.only('from files', () => {
|
|
|
126
123
|
const result = node.toList({ perms: 'ev' });
|
|
127
124
|
|
|
128
125
|
storagePath = path.join(process.cwd(), 'test/homebridge-automation-hbDevices-v2.json');
|
|
129
|
-
console.log(`Reading Homebridge results from ${storagePath}`);
|
|
126
|
+
// console.log(`Reading Homebridge results from ${storagePath}`);
|
|
130
127
|
const fileResult = JSON.parse(fs.readFileSync(storagePath, 'utf8'));
|
|
131
128
|
expect(result.length).toBe(107);
|
|
132
129
|
expect(result).toEqual(fileResult);
|
|
@@ -138,9 +135,9 @@ describe.only('from files', () => {
|
|
|
138
135
|
});
|
|
139
136
|
|
|
140
137
|
test('Retrieve devices, and compare with future (v3)', async () => {
|
|
141
|
-
console.log('Reading Homebridge endpoints from file', process.cwd());
|
|
138
|
+
// console.log('Reading Homebridge endpoints from file', process.cwd());
|
|
142
139
|
var storagePath = path.join(process.cwd(), 'test/homebridge-automation-endpoints.json');
|
|
143
|
-
console.log(`Reading Homebridge endpoints from ${storagePath}`);
|
|
140
|
+
// console.log(`Reading Homebridge endpoints from ${storagePath}`);
|
|
144
141
|
const fileHbDevices = JSON.parse(fs.readFileSync(storagePath, 'utf8'));
|
|
145
142
|
|
|
146
143
|
node.hapClient.getAllServices.mockResolvedValue(fileHbDevices);
|
|
@@ -149,7 +146,7 @@ describe.only('from files', () => {
|
|
|
149
146
|
const result = node.toList({ perms: 'ev' });
|
|
150
147
|
|
|
151
148
|
storagePath = path.join(process.cwd(), 'test/homebridge-automation-hbDevices-v3.json');
|
|
152
|
-
console.log(`Reading Homebridge results from ${storagePath}`);
|
|
149
|
+
// console.log(`Reading Homebridge results from ${storagePath}`);
|
|
153
150
|
const fileResult = JSON.parse(fs.readFileSync(storagePath, 'utf8'));
|
|
154
151
|
expect(result.length).toBe(107);
|
|
155
152
|
expect(result).toEqual(fileResult);
|
package/src/hbControlNode.js
CHANGED
|
@@ -53,7 +53,6 @@ class HbControlNode extends hbBaseNode {
|
|
|
53
53
|
const result = await this.hbDevice.setCharacteristicsByTypes(filterIfOff(message.payload));
|
|
54
54
|
results.push(result.values);
|
|
55
55
|
} catch (error) {
|
|
56
|
-
console.log(error)
|
|
57
56
|
this.error(`Failed to set value for "${JSON.stringify(message.payload)}": ${error.message}`);
|
|
58
57
|
results.push({ 'Error': `Error: ${error.message}` });
|
|
59
58
|
fill = 'red';
|