node-red-contrib-homekit-bridged 2.0.0-dev.0 → 2.0.0-dev.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/build/lib/HAPHostNode.js +185 -148
- package/build/lib/HAPServiceNode.js +200 -177
- package/build/lib/HAPServiceNode2.js +208 -177
- package/build/lib/NRCHKBError.js +23 -2
- package/build/lib/PairingQRCode.js +62 -0
- package/build/lib/Storage.js +152 -90
- package/build/lib/api.js +654 -291
- package/build/lib/camera/CameraControl.js +125 -0
- package/build/lib/camera/CameraDelegate.js +507 -0
- package/build/lib/camera/MP4StreamingServer.js +159 -0
- package/build/lib/hap/HAPCharacteristic.js +25 -4
- package/build/lib/hap/HAPService.js +25 -4
- package/build/lib/hap/eve-app/EveCharacteristics.js +124 -81
- package/build/lib/hap/eve-app/EveServices.js +50 -17
- package/build/lib/hap/hap-nodejs.js +32 -0
- package/build/lib/migration/HomeKitService2Migration.js +34 -0
- package/build/lib/migration/NodeMigration.js +75 -0
- package/build/lib/types/AccessoryInformationType.js +15 -1
- package/build/lib/types/CameraConfigType.js +15 -1
- package/build/lib/types/CustomCharacteristicType.js +15 -1
- package/build/lib/types/HAPHostConfigType.js +15 -1
- package/build/lib/types/HAPHostNodeType.js +15 -1
- package/build/lib/types/HAPService2ConfigType.js +15 -1
- package/build/lib/types/HAPService2NodeType.js +15 -1
- package/build/lib/types/HAPServiceConfigType.js +15 -1
- package/build/lib/types/HAPServiceNodeType.js +15 -1
- package/build/lib/types/HAPStatusConfigType.js +15 -1
- package/build/lib/types/HAPStatusNodeType.js +15 -1
- package/build/lib/types/HostType.js +28 -7
- package/build/lib/types/NodeType.js +15 -1
- package/build/lib/types/PublishTimersType.js +15 -1
- package/build/lib/types/UniFiControllerConfigType.js +16 -0
- package/build/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.js +28 -7
- package/build/lib/types/hap-nodejs/HapCategories.js +64 -43
- package/build/lib/types/storage/SerializedHostType.js +15 -1
- package/build/lib/types/storage/StorageType.js +34 -10
- package/build/lib/unifi/ProtectDiscovery.js +80 -0
- package/build/lib/utils/AccessoryUtils.js +152 -110
- package/build/lib/utils/BridgeUtils.js +95 -39
- package/build/lib/utils/CharacteristicUtils.js +5 -49
- package/build/lib/utils/CharacteristicUtils2.js +5 -49
- package/build/lib/utils/CharacteristicUtilsBase.js +81 -0
- package/build/lib/utils/NodeStatusUtils.js +89 -40
- package/build/lib/utils/ServiceUtils.js +433 -371
- package/build/lib/utils/ServiceUtils2.js +519 -305
- package/build/lib/utils/index.js +11 -12
- package/build/nodes/bridge.html +206 -168
- package/build/nodes/bridge.js +27 -9
- package/build/nodes/locales/en-US/node-red-contrib-homekit-bridged.json +22 -0
- package/build/nodes/nrchkb.html +1753 -117
- package/build/nodes/nrchkb.js +66 -88
- package/build/nodes/plugin-instance.html +509 -0
- package/build/nodes/plugin-instance.js +46 -0
- package/build/nodes/service.html +557 -306
- package/build/nodes/service.js +5 -6
- package/build/nodes/service2.html +1735 -455
- package/build/nodes/service2.js +5 -8
- package/build/nodes/standalone.html +208 -176
- package/build/nodes/standalone.js +27 -9
- package/build/nodes/status.html +51 -18
- package/build/nodes/status.js +47 -41
- package/build/nodes/unifi-controller.html +92 -0
- package/build/nodes/unifi-controller.js +20 -0
- package/build/plugins/embedded/homebridge-camera-ffmpeg/index.js +479 -0
- package/build/plugins/embedded/homebridge-unifi-protect/index.js +521 -0
- package/build/plugins/embedded/index.js +58 -0
- package/build/plugins/nrchkb-homekit-plugins.js +17 -0
- package/build/plugins/registry/index.js +203 -0
- package/build/plugins/registry/types.js +16 -0
- package/build/scripts/migrate-homekit-service-flows.js +47 -0
- package/examples/demo/01 - ALL Demos single import.json +1885 -2139
- package/examples/demo/02 - Air Purifier.json +12 -61
- package/examples/demo/03 - Air Quality sensor with Battery.json +8 -36
- package/examples/demo/04 - Dimmable Bulb.json +4 -21
- package/examples/demo/05 - Color Bulb (HSV).json +5 -26
- package/examples/demo/06 - Fan (simple, 3 speeds).json +6 -31
- package/examples/demo/07 - Fan (with speed, oscillate, rotation direction).json +4 -21
- package/examples/demo/08 - CO2 detector.json +8 -39
- package/examples/demo/09 - CO (carbon monoxide) example.json +9 -44
- package/examples/demo/10 - Door window contact sensor.json +8 -39
- package/examples/demos (advanced)/01 - Television with inputs and speaker.json +19 -85
- package/examples/switch/01 - Plain Switch.json +179 -199
- package/package.json +48 -34
- package/build/lib/HAPHostNode.d.ts +0 -1
- package/build/lib/HAPServiceNode.d.ts +0 -1
- package/build/lib/HAPServiceNode2.d.ts +0 -1
- package/build/lib/NRCHKBError.d.ts +0 -3
- package/build/lib/Storage.d.ts +0 -30
- package/build/lib/api.d.ts +0 -1
- package/build/lib/hap/HAPCharacteristic.d.ts +0 -9
- package/build/lib/hap/HAPService.d.ts +0 -6
- package/build/lib/hap/eve-app/EveCharacteristics.d.ts +0 -20
- package/build/lib/hap/eve-app/EveServices.d.ts +0 -5
- package/build/lib/types/AccessoryInformationType.d.ts +0 -11
- package/build/lib/types/CameraConfigType.d.ts +0 -24
- package/build/lib/types/CustomCharacteristicType.d.ts +0 -6
- package/build/lib/types/HAPHostConfigType.d.ts +0 -22
- package/build/lib/types/HAPHostNodeType.d.ts +0 -14
- package/build/lib/types/HAPService2ConfigType.d.ts +0 -6
- package/build/lib/types/HAPService2NodeType.d.ts +0 -7
- package/build/lib/types/HAPServiceConfigType.d.ts +0 -26
- package/build/lib/types/HAPServiceNodeType.d.ts +0 -38
- package/build/lib/types/HAPStatusConfigType.d.ts +0 -5
- package/build/lib/types/HAPStatusNodeType.d.ts +0 -12
- package/build/lib/types/HostType.d.ts +0 -5
- package/build/lib/types/NodeType.d.ts +0 -3
- package/build/lib/types/PublishTimersType.d.ts +0 -4
- package/build/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.d.ts +0 -5
- package/build/lib/types/hap-nodejs/HapCategories.d.ts +0 -41
- package/build/lib/types/storage/SerializedHostType.d.ts +0 -5
- package/build/lib/types/storage/StorageType.d.ts +0 -8
- package/build/lib/utils/AccessoryUtils.d.ts +0 -1
- package/build/lib/utils/BridgeUtils.d.ts +0 -1
- package/build/lib/utils/CharacteristicUtils.d.ts +0 -1
- package/build/lib/utils/CharacteristicUtils2.d.ts +0 -1
- package/build/lib/utils/NodeStatusUtils.d.ts +0 -17
- package/build/lib/utils/ServiceUtils.d.ts +0 -1
- package/build/lib/utils/ServiceUtils2.d.ts +0 -1
- package/build/lib/utils/index.d.ts +0 -1
- package/build/nodes/bridge.d.ts +0 -1
- package/build/nodes/nrchkb.d.ts +0 -1
- package/build/nodes/service.d.ts +0 -1
- package/build/nodes/service2.d.ts +0 -1
- package/build/nodes/standalone.d.ts +0 -1
- package/build/nodes/status.d.ts +0 -1
package/build/nodes/service.html
CHANGED
|
@@ -1,322 +1,330 @@
|
|
|
1
1
|
<!--suppress EqualityComparisonWithCoercionJS -->
|
|
2
2
|
<script data-template-name="homekit-service" type="text/x-red">
|
|
3
|
-
<div class="
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
<div class="nrchkb-editor">
|
|
4
|
+
<div class="alert alert-warning nrchkb-warning" role="alert">
|
|
5
|
+
<strong>Deprecated:</strong> homekit-service will be disabled soon. Migrate this node to homekit-service2 to keep it working in NRCHKB 2.x.
|
|
6
|
+
<div style="margin-top: 8px;">
|
|
7
|
+
<button type="button" class="red-ui-button" id="nrchkb-migrate-service2">
|
|
8
|
+
<i class="fa fa-exchange"></i> Migrate this node
|
|
9
|
+
</button>
|
|
10
|
+
</div>
|
|
11
|
+
<div id="nrchkb-migration-result" class="alert alert-info nrchkb-info" role="alert" style="display: none; margin-top: 8px;"></div>
|
|
12
|
+
</div>
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
<details class="nrchkb-section" open>
|
|
15
|
+
<summary><i class="fa fa-sliders"></i> Essentials</summary>
|
|
16
|
+
<div class="nrchkb-section-body">
|
|
17
|
+
<div class="form-row">
|
|
18
|
+
<label for="node-config-input-isParent"><i class="fa fa-sitemap"></i> Service Hierarchy</label>
|
|
19
|
+
<select id="node-config-input-isParent">
|
|
20
|
+
<option value="true" selected="selected">Parent</option>
|
|
21
|
+
<option value="false">Linked</option>
|
|
22
|
+
</select>
|
|
23
|
+
</div>
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
</div>
|
|
38
|
-
<div class="form-row">
|
|
39
|
-
<label for="node-input-manufacturer"><i class="fa fa-wrench"></i> Manufacturer</label>
|
|
40
|
-
<input type="text" id="node-input-manufacturer" placeholder="Manufacturer">
|
|
41
|
-
</div>
|
|
42
|
-
<div class="form-row">
|
|
43
|
-
<label for="node-input-serialNo"><i class="fa fa-wrench"></i> Serial Number</label>
|
|
44
|
-
<input type="text" id="node-input-serialNo" placeholder="Serial Number">
|
|
45
|
-
</div>
|
|
46
|
-
<div class="form-row">
|
|
47
|
-
<label for="node-input-model"><i class="fa fa-wrench"></i> Model</label>
|
|
48
|
-
<input type="text" id="node-input-model" placeholder="Model">
|
|
49
|
-
</div>
|
|
50
|
-
<div class="form-row">
|
|
51
|
-
<label for="node-input-firmwareRev"><i class="fa fa-wrench"></i> Firmware Revision</label>
|
|
52
|
-
<input type="text" id="node-input-firmwareRev" placeholder="Firmware Revision">
|
|
25
|
+
<div class="form-row">
|
|
26
|
+
<label for="node-input-serviceName">
|
|
27
|
+
<i class="fa fa-puzzle-piece"></i>
|
|
28
|
+
Service
|
|
29
|
+
</label>
|
|
30
|
+
<select id="node-input-serviceName">
|
|
31
|
+
<option value="">Choose...</option>
|
|
32
|
+
</select>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div class="form-row">
|
|
36
|
+
<label for="node-input-name">
|
|
37
|
+
<i class="fa fa-tag"></i>
|
|
38
|
+
Name
|
|
39
|
+
</label>
|
|
40
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
41
|
+
</div>
|
|
53
42
|
</div>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
</details>
|
|
44
|
+
|
|
45
|
+
<details class="nrchkb-section" open>
|
|
46
|
+
<summary><i class="fa fa-map-marker"></i> Placement</summary>
|
|
47
|
+
<div class="nrchkb-section-body">
|
|
48
|
+
<div id="isParent">
|
|
49
|
+
<div class="form-row">
|
|
50
|
+
<label for="node-config-input-hostType"><i class="fa fa-server"></i> Host Type</label>
|
|
51
|
+
<select id="node-config-input-hostType">
|
|
52
|
+
<option value="0" selected="selected">Bridge</option>
|
|
53
|
+
<option value="1">Accessory</option>
|
|
54
|
+
</select>
|
|
55
|
+
</div>
|
|
56
|
+
<div id="isOnBridge">
|
|
57
|
+
<div id="isBridgeInSubflow" class="alert alert-warning nrchkb-warning" role="alert">
|
|
58
|
+
Read more <b><a href="#" id="bridgeInSubflowNotice">here</a></b> about adding Bridge in a Subflow.
|
|
59
|
+
</div>
|
|
60
|
+
<div class="form-row">
|
|
61
|
+
<label for="node-input-bridge">
|
|
62
|
+
<i class="fa fa-link"></i>
|
|
63
|
+
Bridge
|
|
64
|
+
</label>
|
|
65
|
+
<input id="node-input-bridge">
|
|
66
|
+
</div>
|
|
67
|
+
<details class="nrchkb-section">
|
|
68
|
+
<summary><i class="fa fa-id-card-o"></i> Accessory Metadata</summary>
|
|
69
|
+
<div class="nrchkb-section-body">
|
|
70
|
+
<div class="form-row">
|
|
71
|
+
<label for="node-input-manufacturer"><i class="fa fa-industry"></i> Manufacturer</label>
|
|
72
|
+
<input type="text" id="node-input-manufacturer" placeholder="Manufacturer">
|
|
73
|
+
</div>
|
|
74
|
+
<div class="form-row">
|
|
75
|
+
<label for="node-input-serialNo"><i class="fa fa-barcode"></i> Serial Number</label>
|
|
76
|
+
<input type="text" id="node-input-serialNo" placeholder="Serial Number">
|
|
77
|
+
</div>
|
|
78
|
+
<div class="form-row">
|
|
79
|
+
<label for="node-input-model"><i class="fa fa-cube"></i> Model</label>
|
|
80
|
+
<input type="text" id="node-input-model" placeholder="Model">
|
|
81
|
+
</div>
|
|
82
|
+
<div class="form-row">
|
|
83
|
+
<label for="node-input-firmwareRev"><i class="fa fa-microchip"></i> Firmware Revision</label>
|
|
84
|
+
<input type="text" id="node-input-firmwareRev" placeholder="Firmware Revision">
|
|
85
|
+
</div>
|
|
86
|
+
<div class="form-row">
|
|
87
|
+
<label for="node-input-hardwareRev"><i class="fa fa-hdd-o"></i> Hardware Revision</label>
|
|
88
|
+
<input type="text" id="node-input-hardwareRev" placeholder="Hardware Revision">
|
|
89
|
+
</div>
|
|
90
|
+
<div class="form-row">
|
|
91
|
+
<label for="node-input-softwareRev"><i class="fa fa-code"></i> Software Revision</label>
|
|
92
|
+
<input type="text" id="node-input-softwareRev" placeholder="Software Revision">
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</details>
|
|
96
|
+
</div>
|
|
97
|
+
<div id="isAccessory">
|
|
98
|
+
<div class="form-row">
|
|
99
|
+
<label for="node-input-accessoryId">
|
|
100
|
+
<i class="fa fa-home"></i>
|
|
101
|
+
Accessory
|
|
102
|
+
</label>
|
|
103
|
+
<input id="node-input-accessoryId">
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<div id="isLinked" style="display: none;">
|
|
109
|
+
<div class="form-row">
|
|
110
|
+
<label for="node-input-parentService">
|
|
111
|
+
<i class="fa fa-level-up"></i>
|
|
112
|
+
Parent Service
|
|
113
|
+
</label>
|
|
114
|
+
<select id="node-input-parentService">
|
|
115
|
+
<option value="">Choose...</option>
|
|
116
|
+
</select>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
57
119
|
</div>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
120
|
+
</details>
|
|
121
|
+
|
|
122
|
+
<details class="nrchkb-section" open>
|
|
123
|
+
<summary><i class="fa fa-exchange"></i> Message Routing</summary>
|
|
124
|
+
<div class="nrchkb-section-body">
|
|
125
|
+
<div class="form-row">
|
|
126
|
+
<label for="node-input-topic"><i class="fa fa-comment-o"></i> Topic</label>
|
|
127
|
+
<input type="text" id="node-input-topic" placeholder="Topic">
|
|
128
|
+
</div>
|
|
129
|
+
<div class="form-row nrchkb-checkbox-row">
|
|
130
|
+
<label class="nrchkb-checkbox-label" for="node-input-filter">
|
|
131
|
+
<input type="checkbox" id="node-input-filter">
|
|
132
|
+
<span><i class="fa fa-filter"></i> Filter on Topic</span>
|
|
133
|
+
</label>
|
|
134
|
+
</div>
|
|
61
135
|
</div>
|
|
62
|
-
</
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
136
|
+
</details>
|
|
137
|
+
|
|
138
|
+
<details id="camera-configuration" class="nrchkb-section" open style="display: none;">
|
|
139
|
+
<summary><i class="fa fa-video-camera"></i> Camera Configuration</summary>
|
|
140
|
+
<div class="nrchkb-section-body">
|
|
141
|
+
<div class="form-row">
|
|
142
|
+
<label for="node-input-cameraConfigVideoProcessor"><i class="fa fa-terminal"></i> Video Processor</label>
|
|
143
|
+
<input type="text" id="node-input-cameraConfigVideoProcessor" placeholder="ffmpeg">
|
|
144
|
+
</div>
|
|
145
|
+
<div class="form-row">
|
|
146
|
+
<label for="node-input-cameraConfigSource"><i class="fa fa-sign-in"></i> Source</label>
|
|
147
|
+
<input type="text" id="node-input-cameraConfigSource" placeholder="">
|
|
148
|
+
</div>
|
|
149
|
+
<div class="form-row">
|
|
150
|
+
<label for="node-input-cameraConfigStillImageSource"><i class="fa fa-picture-o"></i> Still Image Source</label>
|
|
151
|
+
<input type="text" id="node-input-cameraConfigStillImageSource" placeholder="">
|
|
152
|
+
</div>
|
|
153
|
+
<div class="form-row">
|
|
154
|
+
<label for="node-input-cameraConfigMaxStreams"><i class="fa fa-random"></i> Max Streams</label>
|
|
155
|
+
<input type="text" id="node-input-cameraConfigMaxStreams" placeholder="">
|
|
156
|
+
</div>
|
|
157
|
+
<div class="form-row">
|
|
158
|
+
<label for="node-input-cameraConfigMaxWidth"><i class="fa fa-arrows-h"></i> Max Width</label>
|
|
159
|
+
<input type="text" id="node-input-cameraConfigMaxWidth" placeholder="">
|
|
160
|
+
</div>
|
|
161
|
+
<div class="form-row">
|
|
162
|
+
<label for="node-input-cameraConfigMaxHeight"><i class="fa fa-arrows-v"></i> Max Height</label>
|
|
163
|
+
<input type="text" id="node-input-cameraConfigMaxHeight" placeholder="">
|
|
164
|
+
</div>
|
|
165
|
+
<div class="form-row">
|
|
166
|
+
<label for="node-input-cameraConfigMaxFPS"><i class="fa fa-clock-o"></i> Max FPS</label>
|
|
167
|
+
<input type="text" id="node-input-cameraConfigMaxFPS" placeholder="">
|
|
168
|
+
</div>
|
|
169
|
+
<div class="form-row">
|
|
170
|
+
<label for="node-input-cameraConfigMaxBitrate"><i class="fa fa-tachometer"></i> Max Bitrate</label>
|
|
171
|
+
<input type="text" id="node-input-cameraConfigMaxBitrate" placeholder="">
|
|
172
|
+
</div>
|
|
173
|
+
<div class="form-row">
|
|
174
|
+
<label for="node-input-cameraConfigVideoCodec"><i class="fa fa-film"></i> Video Codec</label>
|
|
175
|
+
<input type="text" id="node-input-cameraConfigVideoCodec" placeholder="">
|
|
176
|
+
</div>
|
|
177
|
+
<div class="form-row">
|
|
178
|
+
<label for="node-input-cameraConfigAudioCodec"><i class="fa fa-volume-up"></i> Audio Codec</label>
|
|
179
|
+
<input type="text" id="node-input-cameraConfigAudioCodec" placeholder="">
|
|
180
|
+
</div>
|
|
181
|
+
<div class="form-row nrchkb-checkbox-row">
|
|
182
|
+
<label class="nrchkb-checkbox-label" for="node-input-cameraConfigAudio">
|
|
183
|
+
<input type="checkbox" id="node-input-cameraConfigAudio">
|
|
184
|
+
<span><i class="fa fa-headphones"></i> Audio</span>
|
|
185
|
+
</label>
|
|
186
|
+
</div>
|
|
187
|
+
<div class="form-row">
|
|
188
|
+
<label for="node-input-cameraConfigPacketSize"><i class="fa fa-archive"></i> Packet Size</label>
|
|
189
|
+
<input type="text" id="node-input-cameraConfigPacketSize" placeholder="">
|
|
190
|
+
</div>
|
|
191
|
+
<div class="form-row nrchkb-checkbox-row">
|
|
192
|
+
<label class="nrchkb-checkbox-label" for="node-input-cameraConfigVerticalFlip">
|
|
193
|
+
<input type="checkbox" id="node-input-cameraConfigVerticalFlip">
|
|
194
|
+
<span><i class="fa fa-arrows-v"></i> Vertical Flip</span>
|
|
195
|
+
</label>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="form-row nrchkb-checkbox-row">
|
|
198
|
+
<label class="nrchkb-checkbox-label" for="node-input-cameraConfigHorizontalFlip">
|
|
199
|
+
<input type="checkbox" id="node-input-cameraConfigHorizontalFlip">
|
|
200
|
+
<span><i class="fa fa-arrows-h"></i> Horizontal Flip</span>
|
|
201
|
+
</label>
|
|
202
|
+
</div>
|
|
203
|
+
<div class="form-row">
|
|
204
|
+
<label for="node-input-cameraConfigMapVideo"><i class="fa fa-film"></i> Map Video</label>
|
|
205
|
+
<input type="text" id="node-input-cameraConfigMapVideo" placeholder="">
|
|
206
|
+
</div>
|
|
207
|
+
<div class="form-row">
|
|
208
|
+
<label for="node-input-cameraConfigMapAudio"><i class="fa fa-volume-up"></i> Map Audio</label>
|
|
209
|
+
<input type="text" id="node-input-cameraConfigMapAudio" placeholder="">
|
|
210
|
+
</div>
|
|
211
|
+
<div class="form-row">
|
|
212
|
+
<label for="node-input-cameraConfigVideoFilter"><i class="fa fa-filter"></i> Video Filter</label>
|
|
213
|
+
<input type="text" id="node-input-cameraConfigVideoFilter" placeholder="">
|
|
214
|
+
</div>
|
|
215
|
+
<div class="form-row">
|
|
216
|
+
<label for="node-input-cameraConfigAdditionalCommandLine"><i class="fa fa-terminal"></i> Additional Command Line</label>
|
|
217
|
+
<input type="text" id="node-input-cameraConfigAdditionalCommandLine" placeholder="">
|
|
218
|
+
</div>
|
|
219
|
+
<div class="form-row nrchkb-checkbox-row">
|
|
220
|
+
<label class="nrchkb-checkbox-label" for="node-input-cameraConfigDebug">
|
|
221
|
+
<input type="checkbox" id="node-input-cameraConfigDebug">
|
|
222
|
+
<span><i class="fa fa-bug"></i> Debug</span>
|
|
223
|
+
</label>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<div class="form-row">
|
|
227
|
+
<label for="node-input-cameraConfigSnapshotOutput"><i class="fa fa-camera"></i> Snapshot output</label>
|
|
228
|
+
<select id="node-input-cameraConfigSnapshotOutput">
|
|
229
|
+
<option value="disabled" selected="selected">Disabled</option>
|
|
230
|
+
<option value="path">Path</option>
|
|
231
|
+
<option value="content">Content</option>
|
|
232
|
+
</select>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
<div class="form-row">
|
|
236
|
+
<label for="node-input-cameraConfigInterfaceName"><i class="fa fa-sitemap"></i> Interface Name</label>
|
|
237
|
+
<input type="text" id="node-input-cameraConfigInterfaceName" placeholder="">
|
|
238
|
+
</div>
|
|
69
239
|
</div>
|
|
70
|
-
</
|
|
71
|
-
</div>
|
|
240
|
+
</details>
|
|
72
241
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
242
|
+
<details id="adaptive-lightning-configuration" class="nrchkb-section" open style="display: none;">
|
|
243
|
+
<summary><i class="fa fa-sun-o"></i> Adaptive Lighting Configuration</summary>
|
|
244
|
+
<div class="nrchkb-section-body">
|
|
245
|
+
<div class="form-row nrchkb-checkbox-row">
|
|
246
|
+
<label class="nrchkb-checkbox-label" for="node-input-adaptiveLightingOptionsEnable">
|
|
247
|
+
<input type="checkbox" id="node-input-adaptiveLightingOptionsEnable">
|
|
248
|
+
<span><i class="fa fa-toggle-on"></i> Enable</span>
|
|
249
|
+
</label>
|
|
250
|
+
</div>
|
|
251
|
+
<div class="form-row">
|
|
252
|
+
<label for="node-input-adaptiveLightingOptionsMode"><i class="fa fa-magic"></i> Mode</label>
|
|
253
|
+
<select id="node-input-adaptiveLightingOptionsMode">
|
|
254
|
+
<option value="" selected hidden disabled>AUTOMATIC</option>
|
|
255
|
+
<option value="1">AUTOMATIC</option>
|
|
256
|
+
<option value="2">MANUAL</option>
|
|
257
|
+
</select>
|
|
258
|
+
</div>
|
|
259
|
+
<div class="form-row">
|
|
260
|
+
<label for="node-input-adaptiveLightingOptionsCustomTemperatureAdjustment"><i class="fa fa-thermometer-half"></i> Custom Temperature Adjustment</label>
|
|
261
|
+
<input type="number" id="node-input-adaptiveLightingOptionsCustomTemperatureAdjustment" placeholder="0">
|
|
262
|
+
</div>
|
|
263
|
+
</div>
|
|
264
|
+
</details>
|
|
83
265
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<input type="checkbox" id="node-input-filter" style="display: inline-block; width: auto; vertical-align: top;">
|
|
92
|
-
<label for="node-input-filter" style="width: 120px;"> <i class="fa fa-filter"></i> Filter on Topic</label>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
266
|
+
<details class="nrchkb-section">
|
|
267
|
+
<summary><i class="fa fa-sliders"></i> Advanced Behavior</summary>
|
|
268
|
+
<div class="nrchkb-section-body">
|
|
269
|
+
<div class="form-row">
|
|
270
|
+
<label for="node-input-characteristicProperties"><i class="fa fa-list-alt"></i> Characteristic Properties</label>
|
|
271
|
+
<input type="text" id="node-input-characteristicProperties">
|
|
272
|
+
</div>
|
|
95
273
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
274
|
+
<div class="form-row nrchkb-checkbox-row">
|
|
275
|
+
<label class="nrchkb-checkbox-label" for="node-input-waitForSetupMsg">
|
|
276
|
+
<input type="checkbox" id="node-input-waitForSetupMsg">
|
|
277
|
+
<span><i class="fa fa-hourglass-half"></i> Wait for Setup message</span>
|
|
278
|
+
</label>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
</details>
|
|
101
282
|
</div>
|
|
283
|
+
</script>
|
|
102
284
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<div class="form-row">
|
|
106
|
-
<label for="node-input-cameraConfigVideoProcessor"><i class="fa fa-cog"></i> Video Processor</label>
|
|
107
|
-
<input type="text" id="node-input-cameraConfigVideoProcessor" placeholder="ffmpeg">
|
|
108
|
-
</div>
|
|
109
|
-
<div class="form-row">
|
|
110
|
-
<label for="node-input-cameraConfigSource"><i class="fa fa-tint"></i> Source</label>
|
|
111
|
-
<input type="text" id="node-input-cameraConfigSource" placeholder="">
|
|
112
|
-
</div>
|
|
113
|
-
<div class="form-row">
|
|
114
|
-
<label for="node-input-cameraConfigStillImageSource"><i class="fa fa-picture-o"></i> Still Image Source</label>
|
|
115
|
-
<input type="text" id="node-input-cameraConfigStillImageSource" placeholder="">
|
|
116
|
-
</div>
|
|
117
|
-
<div class="form-row">
|
|
118
|
-
<label for="node-input-cameraConfigMaxStreams"><i class="fa fa-tint"></i> Max Streams</label>
|
|
119
|
-
<input type="text" id="node-input-cameraConfigMaxStreams" placeholder="">
|
|
120
|
-
</div>
|
|
121
|
-
<div class="form-row">
|
|
122
|
-
<label for="node-input-cameraConfigMaxWidth"><i class="fa fa-text-width"></i> Max Width</label>
|
|
123
|
-
<input type="text" id="node-input-cameraConfigMaxWidth" placeholder="">
|
|
124
|
-
</div>
|
|
125
|
-
<div class="form-row">
|
|
126
|
-
<label for="node-input-cameraConfigMaxHeight"><i class="fa fa-text-height"></i> Max Height</label>
|
|
127
|
-
<input type="text" id="node-input-cameraConfigMaxHeight" placeholder="">
|
|
128
|
-
</div>
|
|
129
|
-
<div class="form-row">
|
|
130
|
-
<label for="node-input-cameraConfigMaxFPS"><i class="fa fa-clock-o"></i> Max FPS</label>
|
|
131
|
-
<input type="text" id="node-input-cameraConfigMaxFPS" placeholder="">
|
|
132
|
-
</div>
|
|
133
|
-
<div class="form-row">
|
|
134
|
-
<label for="node-input-cameraConfigMaxBitrate"><i class="fa fa-clock-o"></i> Max Bitrate</label>
|
|
135
|
-
<input type="text" id="node-input-cameraConfigMaxBitrate" placeholder="">
|
|
136
|
-
</div>
|
|
137
|
-
<div class="form-row">
|
|
138
|
-
<label for="node-input-cameraConfigVideoCodec"><i class="fa fa-video-camera"></i> Video Codec</label>
|
|
139
|
-
<input type="text" id="node-input-cameraConfigVideoCodec" placeholder="">
|
|
140
|
-
</div>
|
|
141
|
-
<div class="form-row">
|
|
142
|
-
<label for="node-input-cameraConfigAudioCodec"><i class="fa fa-video-camera"></i> Audio Codec</label>
|
|
143
|
-
<input type="text" id="node-input-cameraConfigAudioCodec" placeholder="">
|
|
144
|
-
</div>
|
|
145
|
-
<div class="form-row">
|
|
146
|
-
<label for="node-input-cameraConfigAudio"><i class="fa fa-headphones"></i> Audio</label>
|
|
147
|
-
<input type="checkbox" id="node-input-cameraConfigAudio">
|
|
148
|
-
</div>
|
|
149
|
-
<div class="form-row">
|
|
150
|
-
<label for="node-input-cameraConfigPacketSize"><i class="fa fa-get-pocket"></i> Packet Size</label>
|
|
151
|
-
<input type="text" id="node-input-cameraConfigPacketSize" placeholder="">
|
|
152
|
-
</div>
|
|
153
|
-
<div class="form-row">
|
|
154
|
-
<label for="node-input-cameraConfigVerticalFlip"><i class="fa fa-undo"></i> Vertical Flip</label>
|
|
155
|
-
<input type="checkbox" id="node-input-cameraConfigVerticalFlip">
|
|
156
|
-
</div>
|
|
157
|
-
<div class="form-row">
|
|
158
|
-
<label for="node-input-cameraConfigHorizontalFlip"><i class="fa fa-undo"></i> Horizontal Flip</label>
|
|
159
|
-
<input type="checkbox" id="node-input-cameraConfigHorizontalFlip">
|
|
160
|
-
</div>
|
|
161
|
-
<div class="form-row">
|
|
162
|
-
<label for="node-input-cameraConfigMapVideo"><i class="fa fa-video-camera"></i> Map Video</label>
|
|
163
|
-
<input type="text" id="node-input-cameraConfigMapVideo" placeholder="">
|
|
164
|
-
</div>
|
|
165
|
-
<div class="form-row">
|
|
166
|
-
<label for="node-input-cameraConfigMapAudio"><i class="fa fa-headphones"></i> Map Audio</label>
|
|
167
|
-
<input type="text" id="node-input-cameraConfigMapAudio" placeholder="">
|
|
168
|
-
</div>
|
|
169
|
-
<div class="form-row">
|
|
170
|
-
<label for="node-input-cameraConfigVideoFilter"><i class="fa fa-filter"></i> Video Filter</label>
|
|
171
|
-
<input type="text" id="node-input-cameraConfigVideoFilter" placeholder="">
|
|
172
|
-
</div>
|
|
173
|
-
<div class="form-row">
|
|
174
|
-
<label for="node-input-cameraConfigAdditionalCommandLine"><i class="fa fa-plus"></i> Additional Command Line</label>
|
|
175
|
-
<input type="text" id="node-input-cameraConfigAdditionalCommandLine" placeholder="">
|
|
176
|
-
</div>
|
|
177
|
-
<div class="form-row">
|
|
178
|
-
<label for="node-input-cameraConfigDebug"><i class="fa fa-bug"></i> Debug</label>
|
|
179
|
-
<input type="checkbox" id="node-input-cameraConfigDebug">
|
|
180
|
-
</div>
|
|
285
|
+
<script data-help-name="homekit-service" type="text/markdown">
|
|
286
|
+
# HomeKit Service
|
|
181
287
|
|
|
182
|
-
|
|
183
|
-
<label for="node-input-cameraConfigSnapshotOutput"><i class="fa fa-picture-o"></i> Snapshot output</label>
|
|
184
|
-
<select id="node-input-cameraConfigSnapshotOutput">
|
|
185
|
-
<option value="disabled" selected="selected">Disabled</option>
|
|
186
|
-
<option value="path">Path</option>
|
|
187
|
-
<option value="content">Content</option>
|
|
188
|
-
</select>
|
|
189
|
-
</div>
|
|
288
|
+
Represents one legacy HomeKit service. It receives Node-RED messages to update HomeKit characteristics and emits messages when HomeKit changes those characteristics.
|
|
190
289
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
<input type="text" id="node-input-cameraConfigInterfaceName" placeholder="">
|
|
194
|
-
</div>
|
|
195
|
-
</div>
|
|
290
|
+
> [!WARNING]
|
|
291
|
+
> `homekit-service` is deprecated and kept for existing flows. Use `homekit-service2` for new work.
|
|
196
292
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
<div class="form-row">
|
|
200
|
-
<label for="node-input-adaptiveLightingOptionsEnable"><i class="fa fa-toggle-on"></i> Enable</label>
|
|
201
|
-
<input type="checkbox" id="node-input-adaptiveLightingOptionsEnable">
|
|
202
|
-
</div>
|
|
203
|
-
<div class="form-row">
|
|
204
|
-
<label for="node-input-adaptiveLightingOptionsMode"><i class="fa fa-hand-o-up"></i> Mode</label>
|
|
205
|
-
<select id="node-input-adaptiveLightingOptionsMode">
|
|
206
|
-
<option value="" selected hidden disabled>AUTOMATIC</option>
|
|
207
|
-
<option value="1">AUTOMATIC</option>
|
|
208
|
-
<option value="2">MANUAL</option>
|
|
209
|
-
</select>
|
|
210
|
-
</div>
|
|
211
|
-
<div class="form-row">
|
|
212
|
-
<label for="node-input-adaptiveLightingOptionsCustomTemperatureAdjustment"><i class="fa fa-thermometer-quarter"></i> Custom Temperature Adjustment</label>
|
|
213
|
-
<input type="number" id="node-input-adaptiveLightingOptionsCustomTemperatureAdjustment" placeholder="0">
|
|
214
|
-
</div>
|
|
215
|
-
</div>
|
|
293
|
+
> [!IMPORTANT]
|
|
294
|
+
> The migration button prepares an editor-side change. Click **Done** and then **Deploy** to commit the migration.
|
|
216
295
|
|
|
217
|
-
|
|
218
|
-
<label for="node-input-characteristicProperties"><i class="fa fa-wrench"></i> Characteristic Properties</label>
|
|
219
|
-
<input type="text" id="node-input-characteristicProperties" style="width: 70%">
|
|
220
|
-
</div>
|
|
296
|
+
## Message Format
|
|
221
297
|
|
|
222
|
-
|
|
223
|
-
<label for="node-input-waitForSetupMsg"><i class="fa fa-bug"></i> Wait for Setup message</label>
|
|
224
|
-
<input type="checkbox" id="node-input-waitForSetupMsg">
|
|
225
|
-
</div>
|
|
226
|
-
</script>
|
|
298
|
+
Send a `msg.payload` object whose keys are HomeKit characteristic names.
|
|
227
299
|
|
|
228
|
-
|
|
229
|
-
<h3 id="toc_5">Service</h3>
|
|
230
|
-
<p>The Service node represents the single device you want to control or query.</p>
|
|
231
|
-
<p>Every service node creates its own HAP accessory to keep things simple.</p>
|
|
232
|
-
<ul>
|
|
233
|
-
<li><strong>Service Hierarchy</strong>: Choose if this Service is Parent or Linked</li>
|
|
234
|
-
<ul>
|
|
235
|
-
<li>Parent has <strong>Bridge</strong> and <strong>Accessory Category</strong>: On what Bridge to host this Service and its Accessory and what kind of category is this Accessory, default <em>OTHER</em></li>
|
|
236
|
-
<li>Linked has <strong>Parent Service</strong>: On what Parent Service link this Service.</li>
|
|
237
|
-
</ul>
|
|
238
|
-
<li><strong>Topic</strong>: An optional property that can be configured in the node or, if left blank, can be set by <code>msg.topic</code>. If <em>Filter on Topic</em> is selected <code>msg.topic</code> of incoming messages must match the configured
|
|
239
|
-
value for the message to be accepted. If <em>Filter on Topic</em> is selected and no <em>Topic</em> is set on the node, then <code>msg.topic</code> must match the nodes <em>Name</em>
|
|
240
|
-
</li>
|
|
241
|
-
<li><strong>Manufacturer, Model, Serial Number</strong>: Can be anything you want.</li>
|
|
242
|
-
<li><strong>Firmware Revision</strong>: Should be a version number string in the form of <em>MAJOR.MINOR.REVISION</em> e.g. <em>1.2.0</em>. Other types of strings are ignored and won't be displayed.</li>
|
|
243
|
-
<li><strong>Hardware Revision</strong>: Should be a version number string in the form of <em>MAJOR.MINOR.REVISION</em> e.g. <em>1.2.0</em>. Other types of strings are ignored and won't be displayed.</li>
|
|
244
|
-
<li><strong>Software Revision</strong>: Should be a version number string in the form of <em>MAJOR.MINOR.REVISION</em> e.g. <em>1.2.0</em>. Other types of strings are ignored and won't be displayed.</li>
|
|
245
|
-
<li><strong>Service</strong>: Choose the type of Service from the list.</li>
|
|
246
|
-
<li><strong>Name</strong>: <em>optional</em></li>
|
|
247
|
-
<li><strong>Camera Configuration</strong>: Additional configuration for CameraControl service.</li>
|
|
248
|
-
<ul>
|
|
249
|
-
<li><strong>Video Processor</strong>: Video processor used for Camera. Default is <em>ffmpeg</em>.</li>
|
|
250
|
-
<li><strong>Source</strong>: Camera source used for video processor. Example for ffmpeg <em>-re -i rtsp://192.168.0.227:8554/unicast</em></li>
|
|
251
|
-
<li><strong>Still Image Source</strong>: Camera snapshot source used for video processor. Example for ffmpeg <em>-i http://faster_still_image_grab_url/this_is_optional.jpg</em></li>
|
|
252
|
-
<li><strong>Max Streams</strong>: Maximum number of streams that will be generated for this camera, default <em>2</em>.</li>
|
|
253
|
-
<li><strong>Max Width</strong>: Maximum width reported to HomeKit, default <em>1280</em>.</li>
|
|
254
|
-
<li><strong>Max Height</strong>: Maximum height reported to HomeKit, default <em>720</em>.</li>
|
|
255
|
-
<li><strong>Max FPS</strong>: Maximum frame rate of the stream, default <em>10</em>.</li>
|
|
256
|
-
<li><strong>Max Bitrate</strong>: Maximum bit rate of the stream in kbit/s, default <em>300</em>.</li>
|
|
257
|
-
<li><strong>Video Codec</strong>: If you're running on a RPi with the omx version of ffmpeg installed, you can change to the hardware accelerated video codec with this option, default <em>libx264</em>.</li>
|
|
258
|
-
<li><strong>Audio Codec</strong>: If you're running on a RPi with the omx version of ffmpeg installed, you can change to the hardware accelerated audio codec with this option, default <em>libfdk_aac</em>.</li>
|
|
259
|
-
<li><strong>Audio</strong>: Can be set to true to enable audio streaming from camera. To use audio ffmpeg must be compiled with --enable-libfdk-aac, default <em>false</em>.</li>
|
|
260
|
-
<li><strong>Packet Size</strong>: If audio or video is choppy try a smaller value, set to a multiple of 188, default <em>1316</em>.</li>
|
|
261
|
-
<li><strong>Vertical Flip</strong>: Flips the stream vertically, default <em>false</em>.</li>
|
|
262
|
-
<li><strong>Horizontal Flip</strong>: Flips the stream horizontally, default <em>false</em>.</li>
|
|
263
|
-
<li><strong>Map Video</strong>: Select the stream used for video, default <em>0:0</em>.</li>
|
|
264
|
-
<li><strong>Map Audio</strong>: Select the stream used for audio, default <em>0:1</em>.</li>
|
|
265
|
-
<li><strong>Video Filter</strong>: Allows a custom video filter to be passed to FFmpeg via -vf, defaults to <em>scale=1280:720</em> but is optional.</li>
|
|
266
|
-
<li><strong>Additional Command Line</strong>: Allows additional of extra command line options to FFmpeg, default <em>-tune zerolatency</em> but is optional.</li>
|
|
267
|
-
<li><strong>Debug</strong>: Show the output of ffmpeg in the log, default <em>false</em>.</li>
|
|
268
|
-
<li><strong>Snapshot output</strong>: Choose how to output camera snapshot</li>
|
|
269
|
-
<ul>
|
|
270
|
-
<li><strong>Disabled</strong>: there will be no output</li>
|
|
271
|
-
<li><strong>Path</strong>: file will be saved and path will be send to output, <em>msg.payload.cameraSnapshot</em> contains path value stored as a string.</li>
|
|
272
|
-
<li><strong>Content</strong>: file content will be send to output, <em>msg.payload.cameraSnapshot</em> contains Buffer object {"type":"Buffer","data":[]}.</li>
|
|
273
|
-
</ul>
|
|
274
|
-
<li><strong>Interface Name</strong>: Selects the IP address of a given network interface.</li>
|
|
275
|
-
</ul>
|
|
276
|
-
<li><strong>Characteristic Properties</strong>: Customize the properties of characteristics.</li>
|
|
277
|
-
<li><strong>Wait for Setup message</strong>: If yes then Service node will wait for a input message with appropriate payload.</li>
|
|
278
|
-
</ul>
|
|
279
|
-
<h2 id="toc_6">Input Messages</h2>
|
|
280
|
-
<p>Input messages can be used to update any <em>Characteristic</em> that the selected <em>Service</em> provides. Simply pass the values-to-update as <code>msg.payload</code> object. </p>
|
|
281
|
-
<p><strong>Example</strong>: to signal that an <em>Outlet</em> is turned on and in use, send the following payload</p>
|
|
282
|
-
<div>
|
|
283
|
-
<pre><code class="language-javascript">
|
|
284
|
-
{
|
|
285
|
-
"On": 1,
|
|
286
|
-
"OutletInUse": 1
|
|
287
|
-
}
|
|
288
|
-
</code></pre>
|
|
289
|
-
</div>
|
|
290
|
-
<p><strong>Hint</strong>: to find out what <em>Characteristics</em> you can address, just send <code>{"foo":"bar"}</code> and watch the debug tab ;)</p>
|
|
291
|
-
<h2 id="toc_7">Output Messages</h2>
|
|
292
|
-
<p>Output messages are in the same format as input messages. They are emitted from the node when it receives <em>Characteristics</em> updates from a paired iOS device.</p>
|
|
293
|
-
<h2 id="toc_8">Characteristic Properties</h2>
|
|
294
|
-
<p><strong>Example</strong>: allow temperatures below 0°C</p>
|
|
295
|
-
<div>
|
|
296
|
-
<pre><code class="language-json">
|
|
300
|
+
```json
|
|
297
301
|
{
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}
|
|
302
|
+
"On": true,
|
|
303
|
+
"OutletInUse": true
|
|
301
304
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
</div>
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Placement
|
|
308
|
+
|
|
309
|
+
- **Host Type**: Publish a parent service behind a shared **Bridge** or behind a standalone **Accessory**.
|
|
310
|
+
- **Bridge**: HomeKit bridge configuration that hosts this service.
|
|
311
|
+
- **Accessory**: Standalone accessory configuration that hosts this service.
|
|
312
|
+
- **Parent Service**: Parent service used by linked services.
|
|
313
|
+
|
|
314
|
+
## Advanced Behavior
|
|
313
315
|
|
|
316
|
+
> [!CAUTION]
|
|
317
|
+
> **Wait for Setup message** delays service setup until the node receives the required setup payload. The service will not be published until that message arrives.
|
|
318
|
+
|
|
319
|
+
- **Characteristic Properties**: JSON object that overrides HAP characteristic metadata such as `minValue`, `maxValue`, or `minStep`.
|
|
320
|
+
- **Camera Configuration**: Shown for camera services and describes FFmpeg streaming and snapshot settings.
|
|
314
321
|
</script>
|
|
315
322
|
|
|
316
323
|
<script type="text/javascript">
|
|
317
324
|
RED.nodes.registerType('homekit-service', {
|
|
318
325
|
category: "Apple HomeKit",
|
|
319
326
|
paletteLabel: 'service',
|
|
327
|
+
nrchkbPreventNewInstances: true,
|
|
320
328
|
defaults: {
|
|
321
329
|
isParent: {
|
|
322
330
|
value: 'false',
|
|
@@ -481,8 +489,7 @@
|
|
|
481
489
|
|
|
482
490
|
try {
|
|
483
491
|
JSON.parse(value)
|
|
484
|
-
} catch (
|
|
485
|
-
console.log(e, value)
|
|
492
|
+
} catch (_) {
|
|
486
493
|
return false
|
|
487
494
|
}
|
|
488
495
|
|
|
@@ -530,9 +537,31 @@
|
|
|
530
537
|
labelStyle: function () {
|
|
531
538
|
return this.name ? 'node_label_italic' : ''
|
|
532
539
|
},
|
|
540
|
+
onadd: function () {
|
|
541
|
+
applyDefaultNodeDocumentation(this, 'homekit-service')
|
|
542
|
+
},
|
|
533
543
|
oneditprepare: function () {
|
|
534
544
|
let node = this
|
|
535
545
|
let isParentToggle = $('#node-config-input-isParent')
|
|
546
|
+
const prefersReducedMotion = function () {
|
|
547
|
+
return window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
548
|
+
}
|
|
549
|
+
const showEditorSection = function (section) {
|
|
550
|
+
if (prefersReducedMotion()) {
|
|
551
|
+
section.stop(true, true).show()
|
|
552
|
+
return
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
section.stop(true, true).fadeIn('fast')
|
|
556
|
+
}
|
|
557
|
+
const hideEditorSection = function (section) {
|
|
558
|
+
if (prefersReducedMotion()) {
|
|
559
|
+
section.stop(true, true).hide()
|
|
560
|
+
return
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
section.stop(true, true).fadeOut('fast')
|
|
564
|
+
}
|
|
536
565
|
|
|
537
566
|
if (node.isParent === false) {
|
|
538
567
|
isParentToggle.val('false')
|
|
@@ -540,6 +569,151 @@
|
|
|
540
569
|
isParentToggle.val('true')
|
|
541
570
|
}
|
|
542
571
|
|
|
572
|
+
const toSerializableValue = function (value) {
|
|
573
|
+
if (value === undefined || value === null) {
|
|
574
|
+
return value
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (typeof value !== 'object') {
|
|
578
|
+
return value
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
try {
|
|
582
|
+
return JSON.parse(JSON.stringify(value))
|
|
583
|
+
} catch (_) {
|
|
584
|
+
return undefined
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const readCurrentNodeConfig = function () {
|
|
589
|
+
const config = {
|
|
590
|
+
id: node.id,
|
|
591
|
+
type: node.type,
|
|
592
|
+
z: node.z,
|
|
593
|
+
g: node.g,
|
|
594
|
+
wires: toSerializableValue(node.wires),
|
|
595
|
+
outputs: node.outputs
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
Object.keys((node._def && node._def.defaults) || {}).forEach(function (key) {
|
|
599
|
+
const value = toSerializableValue(node[key])
|
|
600
|
+
|
|
601
|
+
if (value !== undefined) {
|
|
602
|
+
config[key] = value
|
|
603
|
+
}
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
return $.extend(config, {
|
|
607
|
+
name: $('#node-input-name').val(),
|
|
608
|
+
serviceName:
|
|
609
|
+
$('#node-input-serviceName').val() ||
|
|
610
|
+
$('#node-input-serviceName option:selected').attr('value') ||
|
|
611
|
+
node.serviceName,
|
|
612
|
+
manufacturer: $('#node-input-manufacturer').val(),
|
|
613
|
+
model: $('#node-input-model').val(),
|
|
614
|
+
serialNo: $('#node-input-serialNo').val(),
|
|
615
|
+
firmwareRev: $('#node-input-firmwareRev').val(),
|
|
616
|
+
cameraConfigVideoProcessor: $('#node-input-cameraConfigVideoProcessor').val(),
|
|
617
|
+
cameraConfigSource: $('#node-input-cameraConfigSource').val(),
|
|
618
|
+
cameraConfigStillImageSource: $('#node-input-cameraConfigStillImageSource').val(),
|
|
619
|
+
cameraConfigMaxStreams: $('#node-input-cameraConfigMaxStreams').val(),
|
|
620
|
+
cameraConfigMaxWidth: $('#node-input-cameraConfigMaxWidth').val(),
|
|
621
|
+
cameraConfigMaxHeight: $('#node-input-cameraConfigMaxHeight').val(),
|
|
622
|
+
cameraConfigMaxFPS: $('#node-input-cameraConfigMaxFPS').val(),
|
|
623
|
+
cameraConfigMaxBitrate: $('#node-input-cameraConfigMaxBitrate').val(),
|
|
624
|
+
cameraConfigVideoCodec: $('#node-input-cameraConfigVideoCodec').val(),
|
|
625
|
+
cameraConfigAudio: $('#node-input-cameraConfigAudio').is(':checked'),
|
|
626
|
+
cameraConfigPacketSize: $('#node-input-cameraConfigPacketSize').val(),
|
|
627
|
+
cameraConfigMapVideo: $('#node-input-cameraConfigMapVideo').val(),
|
|
628
|
+
cameraConfigMapAudio: $('#node-input-cameraConfigMapAudio').val(),
|
|
629
|
+
cameraConfigVideoFilter: $('#node-input-cameraConfigVideoFilter').val(),
|
|
630
|
+
cameraConfigAdditionalCommandLine: $('#node-input-cameraConfigAdditionalCommandLine').val(),
|
|
631
|
+
cameraConfigDebug: $('#node-input-cameraConfigDebug').is(':checked')
|
|
632
|
+
})
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
const showMigrationPrepared = function (result) {
|
|
636
|
+
if (
|
|
637
|
+
result.node.serviceName &&
|
|
638
|
+
$('#node-input-serviceName option[value="' + result.node.serviceName + '"]').length === 0
|
|
639
|
+
) {
|
|
640
|
+
$('#node-input-serviceName').append(
|
|
641
|
+
$('<option></option>')
|
|
642
|
+
.val(result.node.serviceName)
|
|
643
|
+
.text(result.node.serviceName)
|
|
644
|
+
)
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (result.node.serviceName) {
|
|
648
|
+
$('#node-input-serviceName')
|
|
649
|
+
.val(result.node.serviceName)
|
|
650
|
+
.trigger('change')
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
$('#nrchkb-migration-result')
|
|
654
|
+
.html(
|
|
655
|
+
'<strong>Migration prepared.</strong> Service is now <code>' +
|
|
656
|
+
$('<div>').text(result.node.serviceName || '').html() +
|
|
657
|
+
'</code>. Click <strong>Done</strong> to commit this editor change, then <strong>Deploy</strong>.'
|
|
658
|
+
)
|
|
659
|
+
.show()
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
$('#nrchkb-migrate-service2').on('click', function () {
|
|
663
|
+
$('<div>')
|
|
664
|
+
.html('<p>This will prepare this node for conversion to <strong>homekit-service2</strong> in legacy output mode and preserve existing wires.</p><p>CameraControl nodes will become the new <strong>Camera</strong> service with the embedded Homebridge Camera FFmpeg plugin.</p><p>After migration is prepared, click <strong>Done</strong> in this node editor to commit the change, then <strong>Deploy</strong>.</p>')
|
|
665
|
+
.dialog({
|
|
666
|
+
modal: true,
|
|
667
|
+
resizable: false,
|
|
668
|
+
width: 420,
|
|
669
|
+
title: 'Migrate Service Node',
|
|
670
|
+
buttons: {
|
|
671
|
+
Migrate: function () {
|
|
672
|
+
const dialog = this
|
|
673
|
+
|
|
674
|
+
$.ajax({
|
|
675
|
+
url: 'nrchkb/migration/node',
|
|
676
|
+
type: 'POST',
|
|
677
|
+
contentType: 'application/json',
|
|
678
|
+
data: JSON.stringify(readCurrentNodeConfig())
|
|
679
|
+
}).done(function (result) {
|
|
680
|
+
if (!result || !result.migrated || !result.node) {
|
|
681
|
+
RED.notify('This node could not be migrated.', 'warning')
|
|
682
|
+
return
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
node._nrchkbPendingMigration = result.node
|
|
686
|
+
showMigrationPrepared(result)
|
|
687
|
+
|
|
688
|
+
RED.nodes.dirty(true)
|
|
689
|
+
|
|
690
|
+
if (RED.view && RED.view.redraw) {
|
|
691
|
+
RED.view.redraw(true)
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
RED.notify(
|
|
695
|
+
result.cameraMigrated
|
|
696
|
+
? 'Migration prepared: CameraControl will become homekit-service2 Camera. Click Done, then Deploy.'
|
|
697
|
+
: 'Migration prepared. Click Done, then Deploy.',
|
|
698
|
+
'success'
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
$(dialog).dialog('destroy')
|
|
702
|
+
$('.ui-dialog-content').dialog('close')
|
|
703
|
+
}).fail(function (xhr) {
|
|
704
|
+
const message = xhr.responseJSON && xhr.responseJSON.error
|
|
705
|
+
? xhr.responseJSON.error
|
|
706
|
+
: 'Migration failed.'
|
|
707
|
+
RED.notify(message, 'error')
|
|
708
|
+
})
|
|
709
|
+
},
|
|
710
|
+
Cancel: function () {
|
|
711
|
+
$(this).dialog('destroy')
|
|
712
|
+
},
|
|
713
|
+
},
|
|
714
|
+
})
|
|
715
|
+
})
|
|
716
|
+
|
|
543
717
|
let isLinkedDiv = $('#isLinked')
|
|
544
718
|
let isParentDiv = $('#isParent')
|
|
545
719
|
|
|
@@ -548,11 +722,11 @@
|
|
|
548
722
|
isParentToggle
|
|
549
723
|
.change(function () {
|
|
550
724
|
if (isParentToggle.val() === 'true') {
|
|
551
|
-
isLinkedDiv
|
|
552
|
-
isParentDiv
|
|
725
|
+
hideEditorSection(isLinkedDiv)
|
|
726
|
+
showEditorSection(isParentDiv)
|
|
553
727
|
} else {
|
|
554
|
-
isParentDiv
|
|
555
|
-
isLinkedDiv
|
|
728
|
+
hideEditorSection(isParentDiv)
|
|
729
|
+
showEditorSection(isLinkedDiv)
|
|
556
730
|
selectHostType.val("_ADD_")
|
|
557
731
|
}
|
|
558
732
|
})
|
|
@@ -622,10 +796,11 @@
|
|
|
622
796
|
selectServiceName
|
|
623
797
|
.change(function () {
|
|
624
798
|
if (this.value === 'CameraControl') {
|
|
625
|
-
cameraConfiguration.
|
|
799
|
+
cameraConfiguration.prop('open', true)
|
|
800
|
+
showEditorSection(cameraConfiguration)
|
|
626
801
|
node.outputs = 3
|
|
627
802
|
} else {
|
|
628
|
-
cameraConfiguration
|
|
803
|
+
hideEditorSection(cameraConfiguration)
|
|
629
804
|
node.outputs = 2
|
|
630
805
|
}
|
|
631
806
|
})
|
|
@@ -634,9 +809,10 @@
|
|
|
634
809
|
selectServiceName
|
|
635
810
|
.change(function () {
|
|
636
811
|
if (this.value === 'Lightbulb') {
|
|
637
|
-
adaptiveLightningConfiguration.
|
|
812
|
+
adaptiveLightningConfiguration.prop('open', true)
|
|
813
|
+
showEditorSection(adaptiveLightningConfiguration)
|
|
638
814
|
} else {
|
|
639
|
-
adaptiveLightningConfiguration
|
|
815
|
+
hideEditorSection(adaptiveLightningConfiguration)
|
|
640
816
|
}
|
|
641
817
|
})
|
|
642
818
|
.change()
|
|
@@ -657,6 +833,8 @@
|
|
|
657
833
|
})
|
|
658
834
|
]
|
|
659
835
|
|
|
836
|
+
const parentServiceOptions = []
|
|
837
|
+
|
|
660
838
|
candidateNodes.forEach(function (n) {
|
|
661
839
|
if (!n.name || n.name.length < 1 || !n.isParent) {
|
|
662
840
|
return
|
|
@@ -689,14 +867,17 @@
|
|
|
689
867
|
const text = n.name + ' (' + sublabel + ')'
|
|
690
868
|
const hostType = n.hostType
|
|
691
869
|
|
|
692
|
-
|
|
693
|
-
|
|
870
|
+
parentServiceOptions.push({
|
|
871
|
+
text,
|
|
872
|
+
element: $('<option></option>')
|
|
694
873
|
.val(value)
|
|
695
874
|
.text(text)
|
|
696
|
-
.attr("hostType", hostType)
|
|
697
|
-
)
|
|
875
|
+
.attr("hostType", hostType)
|
|
876
|
+
})
|
|
698
877
|
})
|
|
699
878
|
|
|
879
|
+
sortSelectOptionsByLabel(selectParentService, parentServiceOptions)
|
|
880
|
+
|
|
700
881
|
selectParentService
|
|
701
882
|
.find('option')
|
|
702
883
|
.filter(function () {
|
|
@@ -753,9 +934,27 @@
|
|
|
753
934
|
})
|
|
754
935
|
})
|
|
755
936
|
},
|
|
937
|
+
oneditcancel: function () {
|
|
938
|
+
delete this._nrchkbPendingMigration
|
|
939
|
+
},
|
|
756
940
|
oneditsave: function () {
|
|
757
941
|
let node = this
|
|
758
942
|
|
|
943
|
+
if (node._nrchkbPendingMigration) {
|
|
944
|
+
const migratedNode = node._nrchkbPendingMigration
|
|
945
|
+
|
|
946
|
+
Object.keys(migratedNode).forEach(function (key) {
|
|
947
|
+
node[key] = migratedNode[key]
|
|
948
|
+
})
|
|
949
|
+
|
|
950
|
+
if (RED.nodes.getType(migratedNode.type)) {
|
|
951
|
+
node._def = RED.nodes.getType(migratedNode.type)
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
delete node._nrchkbPendingMigration
|
|
955
|
+
return true
|
|
956
|
+
}
|
|
957
|
+
|
|
759
958
|
node.isParent = $('#node-config-input-isParent').val() === 'true'
|
|
760
959
|
node.hostType = $('#node-config-input-hostType').val()
|
|
761
960
|
|
|
@@ -764,6 +963,20 @@
|
|
|
764
963
|
const selectedParentService = $('#node-input-parentService option:selected')
|
|
765
964
|
node.parentService = selectedParentService.val()
|
|
766
965
|
node.hostType = selectedParentService.attr("hostType")
|
|
966
|
+
node.bridge = ''
|
|
967
|
+
node.accessoryId = ''
|
|
968
|
+
$('#node-input-bridge').val('')
|
|
969
|
+
$('#node-input-accessoryId').val('')
|
|
970
|
+
} else if (node.hostType === '0') {
|
|
971
|
+
node.accessoryId = ''
|
|
972
|
+
node.parentService = ''
|
|
973
|
+
$('#node-input-accessoryId').val('')
|
|
974
|
+
$('#node-input-parentService').val('')
|
|
975
|
+
} else if (node.hostType === '1') {
|
|
976
|
+
node.bridge = ''
|
|
977
|
+
node.parentService = ''
|
|
978
|
+
$('#node-input-bridge').val('')
|
|
979
|
+
$('#node-input-parentService').val('')
|
|
767
980
|
}
|
|
768
981
|
|
|
769
982
|
node.serviceName = $(
|
|
@@ -771,5 +984,43 @@
|
|
|
771
984
|
).val()
|
|
772
985
|
},
|
|
773
986
|
})
|
|
774
|
-
</script>
|
|
775
987
|
|
|
988
|
+
;(function () {
|
|
989
|
+
const legacyServiceType = 'homekit-service'
|
|
990
|
+
const registry = RED.nodes.registry
|
|
991
|
+
const legacyServiceDefinition = RED.nodes.getType(legacyServiceType)
|
|
992
|
+
|
|
993
|
+
if (legacyServiceDefinition) {
|
|
994
|
+
legacyServiceDefinition.nrchkbPreventNewInstances = true
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
if (registry && !registry._nrchkbPreventNewInstancesPatch) {
|
|
998
|
+
const originalGetNodeTypes = registry.getNodeTypes
|
|
999
|
+
|
|
1000
|
+
registry.getNodeTypes = function () {
|
|
1001
|
+
return originalGetNodeTypes.call(registry).filter(function (type) {
|
|
1002
|
+
const definition = RED.nodes.getType(type)
|
|
1003
|
+
return !definition || definition.nrchkbPreventNewInstances !== true
|
|
1004
|
+
})
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
registry._nrchkbPreventNewInstancesPatch = true
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
const removeLegacyPaletteNode = function () {
|
|
1011
|
+
$('.red-ui-palette-node[data-palette-type="' + legacyServiceType + '"]').remove()
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
if (registry && RED.events && RED.events.on && !registry._nrchkbLegacyServicePaletteHandler) {
|
|
1015
|
+
RED.events.on('registry:node-type-added', function (type) {
|
|
1016
|
+
if (type === legacyServiceType) {
|
|
1017
|
+
removeLegacyPaletteNode()
|
|
1018
|
+
}
|
|
1019
|
+
})
|
|
1020
|
+
registry._nrchkbLegacyServicePaletteHandler = true
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
removeLegacyPaletteNode()
|
|
1024
|
+
setTimeout(removeLegacyPaletteNode, 0)
|
|
1025
|
+
})()
|
|
1026
|
+
</script>
|