node-red-contrib-homekit-bridged 2.0.0-dev.4 → 2.0.0-dev.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/build/lib/HAPHostNode.js +183 -141
  2. package/build/lib/HAPServiceNode.js +199 -172
  3. package/build/lib/HAPServiceNode2.js +207 -172
  4. package/build/lib/NRCHKBError.js +23 -2
  5. package/build/lib/PairingQRCode.js +62 -0
  6. package/build/lib/Storage.js +157 -92
  7. package/build/lib/api.js +654 -288
  8. package/build/lib/camera/CameraControl.js +125 -0
  9. package/build/lib/camera/CameraDelegate.js +507 -0
  10. package/build/lib/camera/MP4StreamingServer.js +159 -0
  11. package/build/lib/hap/HAPCharacteristic.js +25 -4
  12. package/build/lib/hap/HAPService.js +25 -4
  13. package/build/lib/hap/eve-app/EveCharacteristics.js +124 -81
  14. package/build/lib/hap/eve-app/EveServices.js +50 -17
  15. package/build/lib/hap/hap-nodejs.js +32 -0
  16. package/build/lib/migration/HomeKitService2Migration.js +34 -0
  17. package/build/lib/migration/NodeMigration.js +75 -0
  18. package/build/lib/types/AccessoryInformationType.js +15 -1
  19. package/build/lib/types/CameraConfigType.js +15 -1
  20. package/build/lib/types/CustomCharacteristicType.js +15 -1
  21. package/build/lib/types/HAPHostConfigType.js +15 -1
  22. package/build/lib/types/HAPHostNodeType.js +15 -1
  23. package/build/lib/types/HAPService2ConfigType.js +15 -1
  24. package/build/lib/types/HAPService2NodeType.js +15 -1
  25. package/build/lib/types/HAPServiceConfigType.js +15 -1
  26. package/build/lib/types/HAPServiceNodeType.js +15 -1
  27. package/build/lib/types/HAPStatusConfigType.js +15 -1
  28. package/build/lib/types/HAPStatusNodeType.js +15 -1
  29. package/build/lib/types/HostType.js +28 -7
  30. package/build/lib/types/NodeType.js +15 -1
  31. package/build/lib/types/PublishTimersType.js +15 -1
  32. package/build/lib/types/UniFiControllerConfigType.js +16 -0
  33. package/build/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.js +28 -7
  34. package/build/lib/types/hap-nodejs/HapCategories.js +64 -43
  35. package/build/lib/types/storage/SerializedHostType.js +15 -1
  36. package/build/lib/types/storage/StorageType.js +34 -10
  37. package/build/lib/unifi/ProtectDiscovery.js +80 -0
  38. package/build/lib/utils/AccessoryUtils.js +152 -110
  39. package/build/lib/utils/BridgeUtils.js +82 -39
  40. package/build/lib/utils/CharacteristicUtils.js +5 -49
  41. package/build/lib/utils/CharacteristicUtils2.js +5 -49
  42. package/build/lib/utils/CharacteristicUtilsBase.js +81 -0
  43. package/build/lib/utils/NodeStatusUtils.js +89 -40
  44. package/build/lib/utils/ServiceUtils.js +434 -373
  45. package/build/lib/utils/ServiceUtils2.js +514 -307
  46. package/build/lib/utils/index.js +10 -11
  47. package/build/nodes/bridge.html +184 -166
  48. package/build/nodes/bridge.js +27 -9
  49. package/build/nodes/locales/en-US/node-red-contrib-homekit-bridged.json +22 -0
  50. package/build/nodes/nrchkb.html +1601 -88
  51. package/build/nodes/nrchkb.js +66 -88
  52. package/build/nodes/plugin-instance.html +499 -0
  53. package/build/nodes/plugin-instance.js +46 -0
  54. package/build/nodes/service.html +517 -299
  55. package/build/nodes/service.js +5 -6
  56. package/build/nodes/service2.html +1683 -460
  57. package/build/nodes/service2.js +5 -8
  58. package/build/nodes/standalone.html +187 -174
  59. package/build/nodes/standalone.js +27 -9
  60. package/build/nodes/status.html +51 -18
  61. package/build/nodes/status.js +47 -40
  62. package/build/nodes/unifi-controller.html +92 -0
  63. package/build/nodes/unifi-controller.js +20 -0
  64. package/build/plugins/embedded/homebridge-camera-ffmpeg/index.js +479 -0
  65. package/build/plugins/embedded/homebridge-unifi-protect/index.js +521 -0
  66. package/build/plugins/embedded/index.js +58 -0
  67. package/build/plugins/nrchkb-homekit-plugins.js +17 -0
  68. package/build/plugins/registry/index.js +203 -0
  69. package/build/plugins/registry/types.js +16 -0
  70. package/build/scripts/migrate-homekit-service-flows.js +47 -0
  71. package/examples/demo/01 - ALL Demos single import.json +1885 -1885
  72. package/examples/demo/02 - Air Purifier.json +279 -279
  73. package/examples/demo/03 - Air Quality sensor with Battery.json +254 -254
  74. package/examples/demo/04 - Dimmable Bulb.json +172 -172
  75. package/examples/demo/05 - Color Bulb (HSV).json +195 -195
  76. package/examples/demo/06 - Fan (simple, 3 speeds).json +240 -240
  77. package/examples/demo/07 - Fan (with speed, oscillate, rotation direction).json +175 -175
  78. package/examples/demo/08 - CO2 detector.json +224 -224
  79. package/examples/demo/09 - CO (carbon monoxide) example.json +255 -255
  80. package/examples/demo/10 - Door window contact sensor.json +234 -234
  81. package/examples/demos (advanced)/01 - Television with inputs and speaker.json +541 -541
  82. package/examples/switch/01 - Plain Switch.json +178 -178
  83. package/package.json +95 -84
  84. package/build/lib/HAPHostNode.d.ts +0 -1
  85. package/build/lib/HAPServiceNode.d.ts +0 -1
  86. package/build/lib/HAPServiceNode2.d.ts +0 -1
  87. package/build/lib/NRCHKBError.d.ts +0 -3
  88. package/build/lib/Storage.d.ts +0 -30
  89. package/build/lib/api.d.ts +0 -1
  90. package/build/lib/hap/HAPCharacteristic.d.ts +0 -9
  91. package/build/lib/hap/HAPService.d.ts +0 -6
  92. package/build/lib/hap/eve-app/EveCharacteristics.d.ts +0 -20
  93. package/build/lib/hap/eve-app/EveServices.d.ts +0 -5
  94. package/build/lib/types/AccessoryInformationType.d.ts +0 -11
  95. package/build/lib/types/CameraConfigType.d.ts +0 -24
  96. package/build/lib/types/CustomCharacteristicType.d.ts +0 -6
  97. package/build/lib/types/HAPHostConfigType.d.ts +0 -22
  98. package/build/lib/types/HAPHostNodeType.d.ts +0 -14
  99. package/build/lib/types/HAPService2ConfigType.d.ts +0 -6
  100. package/build/lib/types/HAPService2NodeType.d.ts +0 -7
  101. package/build/lib/types/HAPServiceConfigType.d.ts +0 -26
  102. package/build/lib/types/HAPServiceNodeType.d.ts +0 -38
  103. package/build/lib/types/HAPStatusConfigType.d.ts +0 -5
  104. package/build/lib/types/HAPStatusNodeType.d.ts +0 -12
  105. package/build/lib/types/HostType.d.ts +0 -5
  106. package/build/lib/types/NodeType.d.ts +0 -3
  107. package/build/lib/types/PublishTimersType.d.ts +0 -4
  108. package/build/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.d.ts +0 -5
  109. package/build/lib/types/hap-nodejs/HapCategories.d.ts +0 -41
  110. package/build/lib/types/storage/SerializedHostType.d.ts +0 -5
  111. package/build/lib/types/storage/StorageType.d.ts +0 -8
  112. package/build/lib/utils/AccessoryUtils.d.ts +0 -1
  113. package/build/lib/utils/BridgeUtils.d.ts +0 -1
  114. package/build/lib/utils/CharacteristicUtils.d.ts +0 -1
  115. package/build/lib/utils/CharacteristicUtils2.d.ts +0 -1
  116. package/build/lib/utils/NodeStatusUtils.d.ts +0 -17
  117. package/build/lib/utils/ServiceUtils.d.ts +0 -1
  118. package/build/lib/utils/ServiceUtils2.d.ts +0 -1
  119. package/build/lib/utils/index.d.ts +0 -1
  120. package/build/nodes/bridge.d.ts +0 -1
  121. package/build/nodes/nrchkb.d.ts +0 -1
  122. package/build/nodes/service.d.ts +0 -1
  123. package/build/nodes/service2.d.ts +0 -1
  124. package/build/nodes/standalone.d.ts +0 -1
  125. package/build/nodes/status.d.ts +0 -1
@@ -1,386 +1,447 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+ var import_hap_nodejs = require("@homebridge/hap-nodejs");
25
+ var import_logger = require("@nrchkb/logger");
26
+ var import_CameraControl = require("../camera/CameraControl");
27
+ var import_NRCHKBError = __toESM(require("../NRCHKBError"));
28
+ const buildAdaptiveLightingOptions = (config) => ({
29
+ controllerMode: config.adaptiveLightingOptionsMode !== void 0 ? +config.adaptiveLightingOptionsMode : import_hap_nodejs.AdaptiveLightingControllerMode.AUTOMATIC,
30
+ customTemperatureAdjustment: config.adaptiveLightingOptionsCustomTemperatureAdjustment !== void 0 ? +config.adaptiveLightingOptionsCustomTemperatureAdjustment : void 0
17
31
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
32
+ const describeContext = (context) => {
33
+ if (context === null) {
34
+ return "null";
35
+ }
36
+ if (context === void 0) {
37
+ return "undefined";
38
+ }
39
+ const type = typeof context;
40
+ if (type !== "object") {
41
+ return String(context);
42
+ }
43
+ if (Array.isArray(context)) {
44
+ return `Array(${context.length})`;
45
+ }
46
+ const keys = Object.keys(context);
47
+ return keys.length > 0 ? `Object(${keys.slice(0, 5).join(",")}${keys.length > 5 ? ",..." : ""})` : "Object";
37
48
  };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- const util = __importStar(require("node:util"));
40
- const hap_nodejs_1 = require("@homebridge/hap-nodejs");
41
- const logger_1 = require("@nrchkb/logger");
42
- const NRCHKBError_1 = __importDefault(require("../NRCHKBError"));
43
- module.exports = (node) => {
44
- const log = (0, logger_1.logger)('NRCHKB', 'ServiceUtils', node.config.name, node);
45
- const HapNodeJS = require('@homebridge/hap-nodejs');
46
- const Service = HapNodeJS.Service;
47
- const Characteristic = HapNodeJS.Characteristic;
48
- const NO_RESPONSE_MSG = 'NO_RESPONSE';
49
- const prepareHapData = (context, connection) => {
50
- const hap = {};
51
- if (connection) {
52
- hap.session = {
53
- sessionID: connection.sessionID,
54
- username: connection.username,
55
- remoteAddress: connection.remoteAddress,
56
- localAddress: connection.localAddress,
57
- httpPort: connection.remotePort
58
- };
59
- hap.context = {};
60
- }
61
- if (context) {
62
- hap.context = context;
63
- }
64
- return hap;
65
- };
66
- const onCharacteristicGet = function (callback, context, connection) {
67
- var _a, _b;
68
- log.debug(`onCharacteristicGet with status: ${this.statusCode}, value: ${this.value}, reachability is ${((_a = node.parentNode) !== null && _a !== void 0 ? _a : node).reachable} with context ${util.inspect(context)} on connection ${connection === null || connection === void 0 ? void 0 : connection.sessionID}`);
69
- if (callback) {
70
- try {
71
- callback(((_b = node.parentNode) !== null && _b !== void 0 ? _b : node).reachable
72
- ? null
73
- : new hap_nodejs_1.HapStatusError(-70402), this.value);
74
- }
75
- catch (_) { }
76
- }
77
- };
78
- const onValueChange = function (allCharacteristics, outputNumber, { oldValue, newValue, context }, connection) {
79
- var _a, _b, _c, _d, _e;
80
- const topic = node.config.topic ? node.config.topic : node.topic_in;
81
- const msg = { payload: {}, hap: {}, name: node.name, topic: topic };
82
- const key = this.constructor.name;
83
- msg.payload[key] = newValue;
84
- msg.hap = prepareHapData(context, connection);
85
- msg.hap.allChars = allCharacteristics.reduce((allChars, singleChar) => {
86
- const cKey = singleChar.constructor.name;
87
- allChars[cKey] = singleChar.value;
88
- return allChars;
89
- }, {});
90
- if (oldValue !== undefined) {
91
- msg.hap.oldValue = oldValue;
92
- }
93
- msg.hap.reachable = (_a = node.reachable) !== null && _a !== void 0 ? _a : (_b = node.parentNode) === null || _b === void 0 ? void 0 : _b.reachable;
94
- if (msg.hap.reachable === false) {
95
- ;
96
- [node, ...((_c = node.childNodes) !== null && _c !== void 0 ? _c : [])].forEach((n) => {
97
- n.nodeStatusUtils.setStatus({
98
- fill: 'red',
99
- shape: 'ring',
100
- text: 'Not reachable',
101
- type: 'NO_RESPONSE'
102
- });
103
- });
104
- }
105
- else {
106
- msg.hap.newValue = newValue;
107
- node.nodeStatusUtils.setStatus({
108
- fill: 'yellow',
109
- shape: 'dot',
110
- text: `${key}: ${newValue}`
111
- }, 3000);
112
- (_d = node.childNodes) === null || _d === void 0 ? void 0 : _d.forEach((n) => {
113
- n.nodeStatusUtils.clearStatusByType('NO_RESPONSE');
114
- });
115
- (_e = node.parentNode) === null || _e === void 0 ? void 0 : _e.nodeStatusUtils.clearStatusByType('NO_RESPONSE');
116
- }
117
- log.debug(`${node.name} received ${key} : ${newValue}`);
118
- if (connection || context || node.hostNode.config.allowMessagePassthrough) {
119
- if (outputNumber === 0) {
120
- node.send(msg);
121
- }
122
- else if (outputNumber === 1) {
123
- node.send([null, msg]);
124
- }
125
- }
126
- };
127
- const onCharacteristicSet = (allCharacteristics) => function (newValue, callback, context, connection) {
128
- var _a, _b;
129
- log.debug(`onCharacteristicSet with status: ${this.statusCode}, value: ${this.value}, reachability is ${((_a = node.parentNode) !== null && _a !== void 0 ? _a : node).reachable}
130
- with context ${util.inspect(context)} on connection ${connection === null || connection === void 0 ? void 0 : connection.sessionID}`);
131
- try {
132
- if (callback) {
133
- callback(((_b = node.parentNode) !== null && _b !== void 0 ? _b : node).reachable
134
- ? null
135
- : new hap_nodejs_1.HapStatusError(-70402));
136
- }
137
- }
138
- catch (_) { }
139
- onValueChange.call(this, allCharacteristics, 1, {
140
- newValue,
141
- context
142
- }, connection);
143
- };
144
- const onCharacteristicChange = (allCharacteristics) => function (change) {
145
- var _a;
146
- const { oldValue, newValue, context, originator, reason } = change;
147
- log.debug(`onCharacteristicChange with reason: ${reason}, oldValue: ${oldValue}, newValue: ${newValue}, reachability is ${((_a = node.parentNode) !== null && _a !== void 0 ? _a : node).reachable}
148
- with context ${util.inspect(context)} on connection ${originator === null || originator === void 0 ? void 0 : originator.sessionID}`);
149
- if (oldValue !== newValue) {
150
- onValueChange.call(this, allCharacteristics, 0, {
151
- oldValue,
152
- newValue,
153
- context
154
- }, originator);
155
- }
156
- };
157
- const onInput = (msg) => {
158
- var _a, _b;
159
- if (msg.payload) {
160
- const type = typeof msg.payload;
161
- if (type !== 'object') {
162
- log.error(`Invalid payload type: ${type}`);
163
- return;
164
- }
165
- }
166
- else {
167
- log.error('Invalid message (payload missing)');
168
- return;
49
+ const describeSupported = (supported) => Array.from(supported).join("', '");
50
+ const buildServiceUtils = (node) => {
51
+ const log = (0, import_logger.logger)("NRCHKB", "ServiceUtils", node.config.name, node);
52
+ const { Service, Characteristic } = require("@homebridge/hap-nodejs");
53
+ const NO_RESPONSE_MSG = "NO_RESPONSE";
54
+ const prepareHapData = (context, connection) => {
55
+ const hap = {};
56
+ if (connection) {
57
+ hap.session = {
58
+ sessionID: connection.sessionID,
59
+ username: connection.username,
60
+ remoteAddress: connection.remoteAddress,
61
+ localAddress: connection.localAddress,
62
+ httpPort: connection.remotePort
63
+ };
64
+ hap.context = {};
65
+ }
66
+ if (context) {
67
+ hap.context = context;
68
+ }
69
+ return hap;
70
+ };
71
+ const onCharacteristicGet = function(callback, context, connection) {
72
+ const reachability = (node.parentNode ?? node).reachable;
73
+ log.debug(
74
+ `onCharacteristicGet with status: ${this.statusCode}, value: ${this.value}, reachability is ${reachability} with context ${describeContext(context)} on connection ${connection?.sessionID}`
75
+ );
76
+ if (callback) {
77
+ try {
78
+ callback(
79
+ (node.parentNode ?? node).reachable ? null : new import_hap_nodejs.HapStatusError(
80
+ import_hap_nodejs.HAPStatus.SERVICE_COMMUNICATION_FAILURE
81
+ ),
82
+ this.value
83
+ );
84
+ } catch (_) {
85
+ }
86
+ }
87
+ };
88
+ const onValueChange = function(allCharacteristics, outputNumber, { oldValue, newValue, context }, connection) {
89
+ const topic = node.config.topic ? node.config.topic : node.topic_in;
90
+ const msg = { payload: {}, hap: {}, name: node.name, topic };
91
+ const key = this.constructor.name;
92
+ msg.payload[key] = newValue;
93
+ msg.hap = prepareHapData(context, connection);
94
+ const allChars = {};
95
+ for (const singleChar of allCharacteristics) {
96
+ const cKey = singleChar.constructor.name;
97
+ allChars[cKey] = singleChar.value;
98
+ }
99
+ msg.hap.allChars = allChars;
100
+ if (oldValue !== void 0) {
101
+ msg.hap.oldValue = oldValue;
102
+ }
103
+ msg.hap.reachable = node.reachable ?? node.parentNode?.reachable;
104
+ if (msg.hap.reachable === false) {
105
+ ;
106
+ [node, ...node.childNodes ?? []].forEach((n) => {
107
+ n.nodeStatusUtils.setStatus({
108
+ fill: "red",
109
+ shape: "ring",
110
+ text: "Not reachable",
111
+ type: "NO_RESPONSE"
112
+ });
113
+ });
114
+ } else {
115
+ msg.hap.newValue = newValue;
116
+ node.nodeStatusUtils.setStatus(
117
+ {
118
+ fill: "yellow",
119
+ shape: "dot",
120
+ text: `${key}: ${newValue}`
121
+ },
122
+ 3e3
123
+ );
124
+ node.childNodes?.forEach((n) => {
125
+ n.nodeStatusUtils.clearStatusByType("NO_RESPONSE");
126
+ });
127
+ node.parentNode?.nodeStatusUtils.clearStatusByType("NO_RESPONSE");
128
+ }
129
+ log.debug(`${node.name} received ${key} : ${newValue}`);
130
+ if (connection || context || node.hostNode.config.allowMessagePassthrough) {
131
+ if (outputNumber === 0) {
132
+ node.send(msg);
133
+ } else if (outputNumber === 1) {
134
+ node.send([null, msg]);
135
+ }
136
+ }
137
+ };
138
+ const onCharacteristicSet = (allCharacteristics) => function(newValue, callback, context, connection) {
139
+ const reachability = (node.parentNode ?? node).reachable;
140
+ log.debug(
141
+ `onCharacteristicSet with status: ${this.statusCode}, value: ${this.value}, reachability is ${reachability} with context ${describeContext(context)} on connection ${connection?.sessionID}`
142
+ );
143
+ try {
144
+ if (callback) {
145
+ callback(
146
+ (node.parentNode ?? node).reachable ? null : new import_hap_nodejs.HapStatusError(
147
+ import_hap_nodejs.HAPStatus.SERVICE_COMMUNICATION_FAILURE
148
+ )
149
+ );
150
+ }
151
+ } catch (_) {
152
+ }
153
+ onValueChange.call(
154
+ this,
155
+ allCharacteristics,
156
+ 1,
157
+ {
158
+ newValue,
159
+ context
160
+ },
161
+ connection
162
+ );
163
+ };
164
+ const onCharacteristicChange = (allCharacteristics) => function(change) {
165
+ const { oldValue, newValue, context, originator, reason } = change;
166
+ log.debug(
167
+ `onCharacteristicChange with reason: ${reason}, oldValue: ${oldValue}, newValue: ${newValue}, reachability is ${(node.parentNode ?? node).reachable} with context ${describeContext(context)} on connection ${originator?.sessionID}`
168
+ );
169
+ if (oldValue !== newValue) {
170
+ onValueChange.call(
171
+ this,
172
+ allCharacteristics,
173
+ 0,
174
+ {
175
+ oldValue,
176
+ newValue,
177
+ context
178
+ },
179
+ originator
180
+ );
181
+ }
182
+ };
183
+ const onInput = (msg) => {
184
+ if (msg.payload) {
185
+ const type = typeof msg.payload;
186
+ if (type !== "object") {
187
+ log.error(`Invalid payload type: ${type}`);
188
+ return;
189
+ }
190
+ } else {
191
+ log.error("Invalid message (payload missing)");
192
+ return;
193
+ }
194
+ const topic = node.config.topic ?? node.name;
195
+ if (node.config.filter && msg.topic !== topic) {
196
+ log.debug(
197
+ "msg.topic doesn't match configured value and filter is enabled. Dropping message."
198
+ );
199
+ return;
200
+ }
201
+ let context = null;
202
+ if (msg.payload.Context) {
203
+ context = msg.payload.Context;
204
+ delete msg.payload.Context;
205
+ }
206
+ node.topic_in = msg.topic ?? "";
207
+ for (const key in msg.payload) {
208
+ if (!Object.hasOwn(msg.payload, key)) {
209
+ continue;
210
+ }
211
+ if (!node.supported.has(key)) {
212
+ if (key === "AdaptiveLightingController" && node.adaptiveLightingController) {
213
+ const value = msg.payload?.[key];
214
+ const event = value?.event;
215
+ if (event === "disable") {
216
+ node.adaptiveLightingController?.disableAdaptiveLighting();
217
+ }
218
+ } else {
219
+ log.error(
220
+ `Instead of '${key}' try one of these characteristics: '${describeSupported(node.supported)}'`
221
+ );
169
222
  }
170
- const topic = (_a = node.config.topic) !== null && _a !== void 0 ? _a : node.name;
171
- if (node.config.filter && msg.topic !== topic) {
172
- log.debug("msg.topic doesn't match configured value and filter is enabled. Dropping message.");
173
- return;
223
+ } else {
224
+ const value = msg.payload?.[key];
225
+ const normalizedValue = value === NO_RESPONSE_MSG ? false : value;
226
+ const parentNode = node.parentNode ?? node;
227
+ parentNode.reachable = value !== NO_RESPONSE_MSG;
228
+ const characteristic = node.service.getCharacteristic(
229
+ Characteristic[key]
230
+ );
231
+ if (context !== null) {
232
+ characteristic.setValue(normalizedValue, context);
233
+ } else {
234
+ characteristic.setValue(normalizedValue);
174
235
  }
175
- let context = null;
176
- if (msg.payload.Context) {
177
- context = msg.payload.Context;
178
- delete msg.payload.Context;
236
+ }
237
+ }
238
+ };
239
+ const onClose = (removed, done) => {
240
+ if (node.waitForParentTimer) {
241
+ clearTimeout(node.waitForParentTimer);
242
+ node.waitForParentTimer = void 0;
243
+ }
244
+ Object.values(node.publishTimers).forEach((timer) => {
245
+ clearTimeout(timer);
246
+ });
247
+ node.publishTimers = {};
248
+ const characteristics = node.service ? node.service.characteristics.concat(
249
+ node.service.optionalCharacteristics
250
+ ) : [];
251
+ characteristics.forEach((characteristic) => {
252
+ characteristic.removeListener("get", node.onCharacteristicGet);
253
+ characteristic.removeListener("set", node.onCharacteristicSet);
254
+ characteristic.removeListener("change", node.onCharacteristicChange);
255
+ });
256
+ if (node.config.isParent && node.accessory && node.onIdentify) {
257
+ node.accessory.removeListener("identify", node.onIdentify);
258
+ }
259
+ if (removed && node.accessory) {
260
+ if (node.config.isParent) {
261
+ node.hostNode.host.removeBridgedAccessories([node.accessory]);
262
+ node.accessory.destroy();
263
+ } else if (node.service && node.parentService) {
264
+ node.accessory.removeService(node.service);
265
+ node.parentService.removeLinkedService(node.service);
266
+ }
267
+ }
268
+ node.nodeStatusUtils.cleanup();
269
+ done();
270
+ };
271
+ const getOrCreate = (accessory, serviceInformation, parentService) => {
272
+ if (serviceInformation.serviceName === "CameraControl") {
273
+ let service2 = accessory.services.find(
274
+ (service3) => {
275
+ return service3.UUID === Service.CameraRTPStreamManagement.UUID;
179
276
  }
180
- node.topic_in = (_b = msg.topic) !== null && _b !== void 0 ? _b : '';
181
- Object.keys(msg.payload).forEach((key) => {
182
- var _a, _b, _c, _d;
183
- if (node.supported.indexOf(key) < 0) {
184
- if (key === 'AdaptiveLightingController' &&
185
- node.adaptiveLightingController) {
186
- const value = (_a = msg.payload) === null || _a === void 0 ? void 0 : _a[key];
187
- const event = value === null || value === void 0 ? void 0 : value.event;
188
- if (event === 'disable') {
189
- (_b = node.adaptiveLightingController) === null || _b === void 0 ? void 0 : _b.disableAdaptiveLighting();
190
- }
191
- }
192
- else {
193
- log.error(`Instead of '${key}' try one of these characteristics: '${node.supported.join("', '")}'`);
194
- }
195
- }
196
- else {
197
- const value = (_c = msg.payload) === null || _c === void 0 ? void 0 : _c[key];
198
- const parentNode = (_d = node.parentNode) !== null && _d !== void 0 ? _d : node;
199
- parentNode.reachable = value !== NO_RESPONSE_MSG;
200
- const characteristic = node.service.getCharacteristic(Characteristic[key]);
201
- if (context !== null) {
202
- characteristic.setValue(value, context);
203
- }
204
- else {
205
- characteristic.setValue(value);
206
- }
207
- }
208
- });
209
- };
210
- const onClose = (removed, done) => {
211
- const characteristics = node.service.characteristics.concat(node.service.optionalCharacteristics);
212
- characteristics.forEach((characteristic) => {
213
- characteristic.removeListener('get', node.onCharacteristicGet);
214
- characteristic.removeListener('set', node.onCharacteristicSet);
215
- characteristic.removeListener('change', node.onCharacteristicChange);
277
+ );
278
+ if (!service2) {
279
+ configureCameraSource(accessory, serviceInformation.config);
280
+ service2 = accessory.services.find((service3) => {
281
+ return service3.UUID === Service.CameraRTPStreamManagement.UUID;
216
282
  });
217
- if (node.config.isParent) {
218
- node.accessory.removeListener('identify', node.onIdentify);
283
+ }
284
+ if (!service2) {
285
+ throw new import_NRCHKBError.default(
286
+ "Failed to configure CameraControl service."
287
+ );
288
+ }
289
+ return service2;
290
+ }
291
+ const ServiceConstructor = Service[serviceInformation.serviceName];
292
+ if (typeof ServiceConstructor !== "function") {
293
+ throw new import_NRCHKBError.default(
294
+ `Unknown HomeKit service "${serviceInformation.serviceName}".`
295
+ );
296
+ }
297
+ const newService = new ServiceConstructor(
298
+ serviceInformation.name,
299
+ serviceInformation.UUID
300
+ );
301
+ log.debug(
302
+ `Looking for service with UUID ${serviceInformation.UUID} ...`
303
+ );
304
+ let service = accessory.services.find(
305
+ (service2) => {
306
+ return newService.subtype === service2.subtype;
307
+ }
308
+ );
309
+ if (service && newService.UUID !== service.UUID) {
310
+ log.debug("... service type changed! Removing the old service.");
311
+ accessory.removeService(service);
312
+ service = void 0;
313
+ }
314
+ if (!service) {
315
+ log.debug(
316
+ `... didn't find it. Adding new ${serviceInformation.serviceName} service.`
317
+ );
318
+ service = accessory.addService(newService);
319
+ } else {
320
+ log.debug("... found it! Updating it.");
321
+ service.getCharacteristic(Characteristic.Name).setValue(serviceInformation.name);
322
+ }
323
+ if (parentService) {
324
+ if (service) {
325
+ log.debug("... and linking service to parent.");
326
+ parentService.addLinkedService(service);
327
+ }
328
+ }
329
+ return service ?? newService;
330
+ };
331
+ const configureCameraSource = (accessory, config) => {
332
+ if (config.cameraConfigSource) {
333
+ log.debug("Configuring Camera Source");
334
+ if (!config.cameraConfigVideoProcessor) {
335
+ log.error(
336
+ "Missing configuration for CameraControl: videoProcessor cannot be empty!"
337
+ );
338
+ } else {
339
+ (0, import_CameraControl.configureCamera)(accessory, config);
340
+ }
341
+ } else {
342
+ log.error("Missing configuration for CameraControl.");
343
+ }
344
+ };
345
+ const waitForParent = () => {
346
+ log.debug("Waiting for Parent Service");
347
+ return new Promise((resolve) => {
348
+ node.nodeStatusUtils.setStatus({
349
+ fill: "blue",
350
+ shape: "dot",
351
+ text: "Waiting for Parent Service"
352
+ });
353
+ const checkAndWait = () => {
354
+ const parentNode = node.RED.nodes.getNode(
355
+ node.config.parentService
356
+ );
357
+ if (parentNode?.configured) {
358
+ node.waitForParentTimer = void 0;
359
+ resolve(parentNode);
360
+ } else {
361
+ node.waitForParentTimer = setTimeout(checkAndWait, 1e3);
219
362
  }
220
- if (removed) {
221
- if (node.config.isParent) {
222
- node.hostNode.host.removeBridgedAccessories([node.accessory]);
223
- node.accessory.destroy();
224
- }
225
- else {
226
- node.accessory.removeService(node.service);
227
- node.parentService.removeLinkedService(node.service);
363
+ };
364
+ checkAndWait();
365
+ }).catch((error) => {
366
+ log.error(`Waiting for Parent Service failed due to: ${error}`);
367
+ throw new import_NRCHKBError.default(error);
368
+ });
369
+ };
370
+ const handleWaitForSetup = (config, msg, resolve) => {
371
+ if (node.setupDone) {
372
+ return;
373
+ }
374
+ if (msg && Object.hasOwn(msg, "payload") && msg.payload && typeof msg.payload === "object" && Object.hasOwn(msg.payload, "nrchkb") && msg.payload.nrchkb && typeof msg.payload.nrchkb === "object" && Object.hasOwn(msg.payload.nrchkb, "setup")) {
375
+ node.setupDone = true;
376
+ const newConfig = {
377
+ ...config,
378
+ ...msg.payload.nrchkb.setup
379
+ };
380
+ node.removeListener("input", node.handleWaitForSetup);
381
+ resolve(newConfig);
382
+ } else {
383
+ node.removeListener("input", node.handleWaitForSetup);
384
+ log.error(
385
+ 'Invalid message (required {"payload":{"nrchkb":{"setup":{}}}})'
386
+ );
387
+ }
388
+ };
389
+ const configureAdaptiveLightning = () => {
390
+ if (node.service.UUID === Service.Lightbulb.UUID && node.config.adaptiveLightingOptionsEnable) {
391
+ try {
392
+ node.service.getCharacteristic(Characteristic.Brightness);
393
+ node.service.getCharacteristic(Characteristic.ColorTemperature);
394
+ const options = buildAdaptiveLightingOptions(node.config);
395
+ log.trace(`Configuring Adaptive Lighting with options:`);
396
+ log.trace(JSON.stringify(options));
397
+ const adaptiveLightingController = new import_hap_nodejs.AdaptiveLightingController(node.service, options);
398
+ adaptiveLightingController.on("update", () => {
399
+ const activeAdaptiveLightingTransition = {
400
+ transitionStartMillis: adaptiveLightingController.getAdaptiveLightingStartTimeOfTransition(),
401
+ timeMillisOffset: adaptiveLightingController.getAdaptiveLightingTimeOffset(),
402
+ transitionCurve: adaptiveLightingController.getAdaptiveLightingTransitionCurve(),
403
+ brightnessAdjustmentRange: adaptiveLightingController.getAdaptiveLightingBrightnessMultiplierRange(),
404
+ updateInterval: adaptiveLightingController.getAdaptiveLightingUpdateInterval(),
405
+ notifyIntervalThreshold: adaptiveLightingController.getAdaptiveLightingNotifyIntervalThreshold()
406
+ };
407
+ node.send({
408
+ payload: {
409
+ AdaptiveLightingController: {
410
+ event: "update",
411
+ data: activeAdaptiveLightingTransition
412
+ }
228
413
  }
229
- }
230
- done();
231
- };
232
- const getOrCreate = (accessory, serviceInformation, parentService) => {
233
- const newService = new Service[serviceInformation.serviceName](serviceInformation.name, serviceInformation.UUID);
234
- log.debug(`Looking for service with UUID ${serviceInformation.UUID} ...`);
235
- let service = accessory.services.find((service) => {
236
- return newService.subtype === service.subtype;
414
+ });
237
415
  });
238
- if (service && newService.UUID !== service.UUID) {
239
- log.debug('... service type changed! Removing the old service.');
240
- accessory.removeService(service);
241
- service = undefined;
242
- }
243
- if (!service) {
244
- log.debug(`... didn't find it. Adding new ${serviceInformation.serviceName} service.`);
245
- if (serviceInformation.serviceName === 'CameraControl') {
246
- configureCameraSource(accessory, newService, serviceInformation.config);
247
- service = newService;
248
- }
249
- else {
250
- service = accessory.addService(newService);
416
+ adaptiveLightingController.on("disable", () => {
417
+ node.send({
418
+ payload: {
419
+ AdaptiveLightingController: {
420
+ event: "disable"
421
+ }
251
422
  }
252
- }
253
- else {
254
- log.debug('... found it! Updating it.');
255
- service
256
- .getCharacteristic(Characteristic.Name)
257
- .setValue(serviceInformation.name);
258
- }
259
- if (parentService) {
260
- if (serviceInformation.serviceName === 'CameraControl') {
261
- log.debug('... and adding service to accessory.');
262
- }
263
- else if (service) {
264
- log.debug('... and linking service to parent.');
265
- parentService.addLinkedService(service);
266
- }
267
- }
268
- return service;
269
- };
270
- const configureCameraSource = (_accessory, _service, config) => {
271
- if (config.cameraConfigSource) {
272
- log.debug('Configuring Camera Source');
273
- if (!config.cameraConfigVideoProcessor) {
274
- log.error('Missing configuration for CameraControl: videoProcessor cannot be empty!');
275
- }
276
- else {
277
- }
278
- }
279
- else {
280
- log.error('Missing configuration for CameraControl.');
281
- }
282
- };
283
- const waitForParent = () => {
284
- log.debug('Waiting for Parent Service');
285
- return new Promise((resolve) => {
286
- node.nodeStatusUtils.setStatus({
287
- fill: 'blue',
288
- shape: 'dot',
289
- text: 'Waiting for Parent Service'
290
- });
291
- const checkAndWait = () => {
292
- const parentNode = node.RED.nodes.getNode(node.config.parentService);
293
- if (parentNode === null || parentNode === void 0 ? void 0 : parentNode.configured) {
294
- resolve(parentNode);
295
- }
296
- else {
297
- setTimeout(checkAndWait, 1000);
298
- }
299
- };
300
- checkAndWait();
301
- }).catch((error) => {
302
- log.error(`Waiting for Parent Service failed due to: ${error}`);
303
- throw new NRCHKBError_1.default(error);
423
+ });
304
424
  });
305
- };
306
- const handleWaitForSetup = (config, msg, resolve) => {
307
- if (node.setupDone) {
308
- return;
309
- }
310
- if (Object.hasOwn(msg, 'payload') &&
311
- Object.hasOwn(msg.payload, 'nrchkb') &&
312
- Object.hasOwn(msg.payload.nrchkb, 'setup')) {
313
- node.setupDone = true;
314
- const newConfig = Object.assign(Object.assign({}, config), msg.payload.nrchkb.setup);
315
- node.removeListener('input', node.handleWaitForSetup);
316
- resolve(newConfig);
317
- }
318
- else {
319
- log.error('Invalid message (required {"payload":{"nrchkb":{"setup":{}}}})');
320
- }
321
- };
322
- const configureAdaptiveLightning = () => {
323
- if (node.service.UUID === Service.Lightbulb.UUID &&
324
- node.config.adaptiveLightingOptionsEnable) {
325
- try {
326
- node.service.getCharacteristic(Characteristic.Brightness);
327
- node.service.getCharacteristic(Characteristic.ColorTemperature);
328
- const options = {
329
- controllerMode: node.config.adaptiveLightingOptionsMode
330
- ? +node.config.adaptiveLightingOptionsMode
331
- : 1,
332
- customTemperatureAdjustment: node.config
333
- .adaptiveLightingOptionsCustomTemperatureAdjustment
334
- ? +node.config.adaptiveLightingOptionsCustomTemperatureAdjustment
335
- : undefined
336
- };
337
- log.trace(`Configuring Adaptive Lighting with options:`);
338
- log.trace(JSON.stringify(options));
339
- const adaptiveLightingController = new hap_nodejs_1.AdaptiveLightingController(node.service, options);
340
- adaptiveLightingController.on('update', () => {
341
- const activeAdaptiveLightingTransition = {
342
- transitionStartMillis: adaptiveLightingController.getAdaptiveLightingStartTimeOfTransition(),
343
- timeMillisOffset: adaptiveLightingController.getAdaptiveLightingTimeOffset(),
344
- transitionCurve: adaptiveLightingController.getAdaptiveLightingTransitionCurve(),
345
- brightnessAdjustmentRange: adaptiveLightingController.getAdaptiveLightingBrightnessMultiplierRange(),
346
- updateInterval: adaptiveLightingController.getAdaptiveLightingUpdateInterval(),
347
- notifyIntervalThreshold: adaptiveLightingController.getAdaptiveLightingNotifyIntervalThreshold()
348
- };
349
- node.send({
350
- payload: {
351
- AdaptiveLightingController: {
352
- event: 'update',
353
- data: activeAdaptiveLightingTransition
354
- }
355
- }
356
- });
357
- });
358
- adaptiveLightingController.on('disable', () => {
359
- node.send({
360
- payload: {
361
- AdaptiveLightingController: {
362
- event: 'disable'
363
- }
364
- }
365
- });
366
- });
367
- node.accessory.configureController(adaptiveLightingController);
368
- node.adaptiveLightingController = adaptiveLightingController;
369
- }
370
- catch (error) {
371
- log.error(`Failed to configure Adaptive Lightning due to ${error}`);
372
- }
373
- }
374
- };
375
- return {
376
- getOrCreate,
377
- onCharacteristicGet,
378
- onCharacteristicSet,
379
- onCharacteristicChange,
380
- onInput,
381
- onClose,
382
- waitForParent,
383
- handleWaitForSetup,
384
- configureAdaptiveLightning
385
- };
425
+ node.accessory.configureController(adaptiveLightingController);
426
+ node.adaptiveLightingController = adaptiveLightingController;
427
+ } catch (error) {
428
+ log.error(
429
+ `Failed to configure Adaptive Lightning due to ${error}`
430
+ );
431
+ }
432
+ }
433
+ };
434
+ return {
435
+ getOrCreate,
436
+ onCharacteristicGet,
437
+ onCharacteristicSet,
438
+ onCharacteristicChange,
439
+ onInput,
440
+ onClose,
441
+ waitForParent,
442
+ handleWaitForSetup,
443
+ configureAdaptiveLightning
444
+ };
386
445
  };
446
+ buildServiceUtils.buildAdaptiveLightingOptions = buildAdaptiveLightingOptions;
447
+ module.exports = buildServiceUtils;