homebridge-nest-accfactory 0.2.11 → 0.3.1
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/CHANGELOG.md +28 -0
- package/README.md +14 -7
- package/config.schema.json +118 -0
- package/dist/HomeKitDevice.js +203 -77
- package/dist/HomeKitHistory.js +1 -1
- package/dist/config.js +207 -0
- package/dist/devices.js +118 -0
- package/dist/index.js +2 -1
- package/dist/nexustalk.js +46 -48
- package/dist/{camera.js → plugins/camera.js} +216 -241
- package/dist/{doorbell.js → plugins/doorbell.js} +32 -30
- package/dist/plugins/floodlight.js +91 -0
- package/dist/plugins/heatlink.js +17 -0
- package/dist/{protect.js → plugins/protect.js} +26 -43
- package/dist/{tempsensor.js → plugins/tempsensor.js} +15 -19
- package/dist/{thermostat.js → plugins/thermostat.js} +426 -383
- package/dist/{weather.js → plugins/weather.js} +26 -60
- package/dist/protobuf/nest/services/apigateway.proto +31 -1
- package/dist/protobuf/nest/trait/firmware.proto +207 -89
- package/dist/protobuf/nest/trait/hvac.proto +1052 -312
- package/dist/protobuf/nest/trait/located.proto +51 -8
- package/dist/protobuf/nest/trait/network.proto +366 -36
- package/dist/protobuf/nest/trait/occupancy.proto +145 -17
- package/dist/protobuf/nest/trait/product/protect.proto +57 -43
- package/dist/protobuf/nest/trait/resourcedirectory.proto +8 -0
- package/dist/protobuf/nest/trait/sensor.proto +7 -1
- package/dist/protobuf/nest/trait/service.proto +3 -1
- package/dist/protobuf/nest/trait/structure.proto +60 -14
- package/dist/protobuf/nest/trait/ui.proto +41 -1
- package/dist/protobuf/nest/trait/user.proto +6 -1
- package/dist/protobuf/nest/trait/voiceassistant.proto +2 -1
- package/dist/protobuf/nestlabs/eventingapi/v1.proto +20 -1
- package/dist/protobuf/root.proto +1 -0
- package/dist/protobuf/wdl.proto +18 -2
- package/dist/protobuf/weave/common.proto +2 -1
- package/dist/protobuf/weave/trait/heartbeat.proto +41 -1
- package/dist/protobuf/weave/trait/power.proto +1 -0
- package/dist/protobuf/weave/trait/security.proto +10 -1
- package/dist/streamer.js +74 -78
- package/dist/system.js +1213 -1264
- package/dist/webrtc.js +39 -34
- package/package.json +11 -11
- package/dist/floodlight.js +0 -97
package/dist/webrtc.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// Handles connection and data from Google WebRTC systems
|
|
5
5
|
// Currently a "work in progress"
|
|
6
6
|
//
|
|
7
|
-
// Code version 2025
|
|
7
|
+
// Code version 2025.06.15
|
|
8
8
|
// Mark Hulskamp
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
@@ -26,17 +26,17 @@ import { fileURLToPath } from 'node:url';
|
|
|
26
26
|
import Streamer from './streamer.js';
|
|
27
27
|
|
|
28
28
|
// Define constants
|
|
29
|
-
const
|
|
29
|
+
const EXTEND_INTERVAL = 120000; // Send extend command to Google Home Foyer every this period for active streams
|
|
30
30
|
const RTP_PACKET_HEADER_SIZE = 12;
|
|
31
31
|
const RTP_VIDEO_PAYLOAD_TYPE = 102;
|
|
32
32
|
const RTP_AUDIO_PAYLOAD_TYPE = 111;
|
|
33
33
|
//const RTP_TALKBACK_PAYLOAD_TYPE = 110;
|
|
34
|
-
const
|
|
35
|
-
const
|
|
34
|
+
const USER_AGENT = 'Nest/5.78.0 (iOScom.nestlabs.jasper.release) os=18.0'; // User Agent string
|
|
35
|
+
const GOOGLE_HOME_FOYER_PREFIX = 'google.internal.home.foyer.v1.';
|
|
36
36
|
const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Make a defined for JS __dirname
|
|
37
37
|
|
|
38
38
|
// Blank audio in AAC format, mono channel @48000
|
|
39
|
-
const
|
|
39
|
+
const AAC_MONO_48000_BLANK = Buffer.from([
|
|
40
40
|
0xff, 0xf1, 0x4c, 0x40, 0x03, 0x9f, 0xfc, 0xde, 0x02, 0x00, 0x4c, 0x61, 0x76, 0x63, 0x35, 0x39, 0x2e, 0x31, 0x38, 0x2e, 0x31, 0x30, 0x30,
|
|
41
41
|
0x00, 0x02, 0x30, 0x40, 0x0e,
|
|
42
42
|
]);
|
|
@@ -51,13 +51,14 @@ export default class WebRTC extends Streamer {
|
|
|
51
51
|
extendTimer = undefined; // Stream extend timer
|
|
52
52
|
stalledTimer = undefined; // Timer object for no received data
|
|
53
53
|
pingTimer = undefined; // Google Hopme Foyer periodic ping
|
|
54
|
-
blankAudio =
|
|
54
|
+
blankAudio = AAC_MONO_48000_BLANK;
|
|
55
55
|
video = {}; // Video stream details once connected
|
|
56
56
|
audio = {}; // Audio stream details once connected
|
|
57
57
|
|
|
58
58
|
// Internal data only for this class
|
|
59
59
|
#protobufFoyer = undefined; // Protobuf for Google Home Foyer
|
|
60
60
|
#googleHomeFoyer = undefined; // HTTP/2 connection to Google Home Foyer APIs
|
|
61
|
+
#googleHomeFoyerAPIHost = 'https://googlehomefoyer-pa.googleapis.com'; // Default API endpoint for Google Home Foyer
|
|
61
62
|
#id = undefined; // Session ID
|
|
62
63
|
#googleHomeDeviceUUID = undefined; // Normal Nest/Google protobuf device ID translated to a Google Foyer device ID
|
|
63
64
|
#peerConnection = undefined;
|
|
@@ -78,6 +79,11 @@ export default class WebRTC extends Streamer {
|
|
|
78
79
|
this.token = deviceData?.apiAccess?.oauth2;
|
|
79
80
|
this.localAccess = deviceData?.localAccess === true;
|
|
80
81
|
|
|
82
|
+
// Update Google Home Foyer api host if using field test
|
|
83
|
+
if (deviceData?.apiAccess?.fieldTest === true) {
|
|
84
|
+
this.#googleHomeFoyerAPIHost = 'https://preprod-googlehomefoyer-pa.sandbox.googleapis.com';
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
// Set our streamer codec types
|
|
82
88
|
this.codecs = {
|
|
83
89
|
video: 'h264',
|
|
@@ -139,7 +145,7 @@ export default class WebRTC extends Streamer {
|
|
|
139
145
|
|
|
140
146
|
if (homeFoyerResponse.status !== 0) {
|
|
141
147
|
this.connected = undefined;
|
|
142
|
-
this?.log?.debug
|
|
148
|
+
this?.log?.debug?.('Request to start camera viewing was not accepted for uuid "%s"', this.uuid);
|
|
143
149
|
}
|
|
144
150
|
|
|
145
151
|
if (homeFoyerResponse.status === 0) {
|
|
@@ -194,7 +200,7 @@ export default class WebRTC extends Streamer {
|
|
|
194
200
|
let webRTCOffer = await this.#peerConnection.createOffer();
|
|
195
201
|
await this.#peerConnection.setLocalDescription(webRTCOffer);
|
|
196
202
|
|
|
197
|
-
this?.log?.debug
|
|
203
|
+
this?.log?.debug?.('Sending WebRTC offer for uuid "%s"', this.uuid);
|
|
198
204
|
|
|
199
205
|
homeFoyerResponse = await this.#googleHomeFoyerCommand('CameraService', 'JoinStream', {
|
|
200
206
|
command: 'offer',
|
|
@@ -207,7 +213,7 @@ export default class WebRTC extends Streamer {
|
|
|
207
213
|
|
|
208
214
|
if (homeFoyerResponse.status !== 0) {
|
|
209
215
|
this.connected = undefined;
|
|
210
|
-
this?.log?.debug
|
|
216
|
+
this?.log?.debug?.('WebRTC offer was not agreed with remote for uuid "%s"', this.uuid);
|
|
211
217
|
}
|
|
212
218
|
|
|
213
219
|
if (
|
|
@@ -215,7 +221,7 @@ export default class WebRTC extends Streamer {
|
|
|
215
221
|
homeFoyerResponse.data?.[0]?.responseType === 'answer' &&
|
|
216
222
|
homeFoyerResponse.data?.[0]?.streamId !== undefined
|
|
217
223
|
) {
|
|
218
|
-
this?.log?.debug
|
|
224
|
+
this?.log?.debug?.('WebRTC offer agreed with remote for uuid "%s"', this.uuid);
|
|
219
225
|
|
|
220
226
|
this.#audioTransceiver?.onTrack &&
|
|
221
227
|
this.#audioTransceiver.onTrack.subscribe((track) => {
|
|
@@ -249,7 +255,7 @@ export default class WebRTC extends Streamer {
|
|
|
249
255
|
sdp: homeFoyerResponse.data[0].sdp,
|
|
250
256
|
}));
|
|
251
257
|
|
|
252
|
-
this?.log?.debug
|
|
258
|
+
this?.log?.debug?.('Playback started from WebRTC for uuid "%s" with session ID "%s"', this.uuid, this.#id);
|
|
253
259
|
this.connected = true;
|
|
254
260
|
|
|
255
261
|
// Monitor connection status. If closed and there are still output streams, re-connect
|
|
@@ -257,7 +263,7 @@ export default class WebRTC extends Streamer {
|
|
|
257
263
|
this.#peerConnection &&
|
|
258
264
|
this.#peerConnection.connectionStateChange.subscribe((state) => {
|
|
259
265
|
if (state !== 'connected' && state !== 'connecting') {
|
|
260
|
-
this?.log?.debug
|
|
266
|
+
this?.log?.debug?.('Connection closed to WebRTC for uuid "%s"', this.uuid);
|
|
261
267
|
this.connected = undefined;
|
|
262
268
|
if (this.haveOutputs() === true) {
|
|
263
269
|
this.connect();
|
|
@@ -280,14 +286,14 @@ export default class WebRTC extends Streamer {
|
|
|
280
286
|
});
|
|
281
287
|
|
|
282
288
|
if (homeFoyerResponse?.data?.[0]?.streamExtensionStatus !== 'STATUS_STREAM_EXTENDED') {
|
|
283
|
-
this?.log?.debug
|
|
289
|
+
this?.log?.debug?.('Error occurred while requested stream extension for uuid "%s"', this.uuid);
|
|
284
290
|
|
|
285
291
|
if (typeof this.#peerConnection?.close === 'function') {
|
|
286
292
|
await this.#peerConnection.close();
|
|
287
293
|
}
|
|
288
294
|
}
|
|
289
295
|
}
|
|
290
|
-
},
|
|
296
|
+
}, EXTEND_INTERVAL);
|
|
291
297
|
}
|
|
292
298
|
}
|
|
293
299
|
}
|
|
@@ -307,7 +313,7 @@ export default class WebRTC extends Streamer {
|
|
|
307
313
|
});
|
|
308
314
|
}
|
|
309
315
|
|
|
310
|
-
this?.log?.debug
|
|
316
|
+
this?.log?.debug?.('Notifying remote about closing connection for uuid "%s"', this.uuid);
|
|
311
317
|
await this.#googleHomeFoyerCommand('CameraService', 'JoinStream', {
|
|
312
318
|
command: 'end',
|
|
313
319
|
deviceId: this.uuid,
|
|
@@ -375,11 +381,11 @@ export default class WebRTC extends Streamer {
|
|
|
375
381
|
|
|
376
382
|
if (homeFoyerResponse?.status !== 0) {
|
|
377
383
|
this.audio.talking = undefined;
|
|
378
|
-
this?.log?.debug
|
|
384
|
+
this?.log?.debug?.('Error occurred while requesting talkback to start for uuid "%s"', this.uuid);
|
|
379
385
|
}
|
|
380
386
|
if (homeFoyerResponse?.status === 0) {
|
|
381
387
|
this.audio.talking = true;
|
|
382
|
-
this?.log?.debug
|
|
388
|
+
this?.log?.debug?.('Talking start on uuid "%s"', this.uuid);
|
|
383
389
|
}
|
|
384
390
|
}
|
|
385
391
|
|
|
@@ -407,10 +413,10 @@ export default class WebRTC extends Streamer {
|
|
|
407
413
|
command: 'COMMAND_STOP',
|
|
408
414
|
});
|
|
409
415
|
if (homeFoyerResponse?.status !== 0) {
|
|
410
|
-
this?.log?.debug
|
|
416
|
+
this?.log?.debug?.('Error occurred while requesting talkback to stop for uuid "%s"', this.uuid);
|
|
411
417
|
}
|
|
412
418
|
if (homeFoyerResponse?.status === 0) {
|
|
413
|
-
this?.log?.debug
|
|
419
|
+
this?.log?.debug?.('Talking ended on uuid "%s"', this.uuid);
|
|
414
420
|
}
|
|
415
421
|
this.audio.talking = undefined;
|
|
416
422
|
}
|
|
@@ -453,12 +459,11 @@ export default class WebRTC extends Streamer {
|
|
|
453
459
|
// If its trigger, we'll attempt to restart the stream and/or connection
|
|
454
460
|
clearTimeout(this.stalledTimer);
|
|
455
461
|
this.stalledTimer = setTimeout(async () => {
|
|
456
|
-
this?.log?.debug
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
);
|
|
462
|
+
this?.log?.debug?.(
|
|
463
|
+
'We have not received any data from webrtc in the past "%s" seconds for uuid "%s". Attempting restart',
|
|
464
|
+
10,
|
|
465
|
+
this.uuid,
|
|
466
|
+
);
|
|
462
467
|
|
|
463
468
|
if (typeof this.#peerConnection?.close === 'function') {
|
|
464
469
|
await this.#peerConnection.close();
|
|
@@ -481,7 +486,7 @@ export default class WebRTC extends Streamer {
|
|
|
481
486
|
this.audio.opus = werift.OpusRtpPayload.deSerialize(weriftRtpPacket.payload);
|
|
482
487
|
if (this.audio.opus?.payload !== undefined) {
|
|
483
488
|
// Until work out audio, send blank aac
|
|
484
|
-
this.addToOutput('audio',
|
|
489
|
+
this.addToOutput('audio', AAC_MONO_48000_BLANK);
|
|
485
490
|
|
|
486
491
|
// Decode payload to opus??
|
|
487
492
|
//this.addToOutput('audio', this.audio.opus.payload);
|
|
@@ -498,8 +503,8 @@ export default class WebRTC extends Streamer {
|
|
|
498
503
|
}
|
|
499
504
|
|
|
500
505
|
// Attempt to retrieve both 'Request' and 'Reponse' traits for the associated service and command
|
|
501
|
-
let TraitMapRequest = this.#protobufFoyer.lookup(
|
|
502
|
-
let TraitMapResponse = this.#protobufFoyer.lookup(
|
|
506
|
+
let TraitMapRequest = this.#protobufFoyer.lookup(GOOGLE_HOME_FOYER_PREFIX + command + 'Request');
|
|
507
|
+
let TraitMapResponse = this.#protobufFoyer.lookup(GOOGLE_HOME_FOYER_PREFIX + command + 'Response');
|
|
503
508
|
let buffer = Buffer.alloc(0);
|
|
504
509
|
let commandResponse = {
|
|
505
510
|
status: undefined,
|
|
@@ -510,11 +515,11 @@ export default class WebRTC extends Streamer {
|
|
|
510
515
|
if (TraitMapRequest !== null && TraitMapResponse !== null && this.token !== undefined) {
|
|
511
516
|
if (this.#googleHomeFoyer === undefined || (this.#googleHomeFoyer?.connected === false && this.#googleHomeFoyer?.closed === true)) {
|
|
512
517
|
// No current HTTP/2 connection or current session is closed
|
|
513
|
-
this?.log?.debug
|
|
514
|
-
this.#googleHomeFoyer = http2.connect(
|
|
518
|
+
this?.log?.debug?.('Connection started to Google Home Foyer "%s"', this.#googleHomeFoyerAPIHost);
|
|
519
|
+
this.#googleHomeFoyer = http2.connect(this.#googleHomeFoyerAPIHost);
|
|
515
520
|
|
|
516
521
|
this.#googleHomeFoyer.on('connect', () => {
|
|
517
|
-
this?.log?.debug
|
|
522
|
+
this?.log?.debug?.('Connection established to Google Home Foyer "%s"', this.#googleHomeFoyerAPIHost);
|
|
518
523
|
|
|
519
524
|
clearInterval(this.pingTimer);
|
|
520
525
|
this.pingTimer = setInterval(() => {
|
|
@@ -542,16 +547,16 @@ export default class WebRTC extends Streamer {
|
|
|
542
547
|
clearInterval(this.pingTimer);
|
|
543
548
|
this.pingTimer = undefined;
|
|
544
549
|
this.#googleHomeFoyer = undefined;
|
|
545
|
-
this?.log?.debug
|
|
550
|
+
this?.log?.debug?.('Connection closed to Google Home Foyer "%s"', this.#googleHomeFoyerAPIHost);
|
|
546
551
|
});
|
|
547
552
|
}
|
|
548
553
|
|
|
549
554
|
let request = this.#googleHomeFoyer.request({
|
|
550
555
|
':method': 'post',
|
|
551
|
-
':path': '/' +
|
|
556
|
+
':path': '/' + GOOGLE_HOME_FOYER_PREFIX + service + '/' + command,
|
|
552
557
|
authorization: 'Bearer ' + this.token,
|
|
553
558
|
'content-type': 'application/grpc',
|
|
554
|
-
'user-agent':
|
|
559
|
+
'user-agent': USER_AGENT,
|
|
555
560
|
te: 'trailers',
|
|
556
561
|
'request-id': crypto.randomUUID(),
|
|
557
562
|
'grpc-timeout': '10S',
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "homebridge-nest-accfactory",
|
|
3
3
|
"displayName": "Nest Accfactory",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.3.1",
|
|
6
6
|
"description": "Homebridge support for Nest/Google devices including HomeKit Secure Video (HKSV) support for doorbells and cameras",
|
|
7
7
|
"author": "n0rt0nthec4t",
|
|
8
8
|
"license": "Apache-2.0",
|
|
@@ -46,25 +46,25 @@
|
|
|
46
46
|
"scripts": {
|
|
47
47
|
"clean": "rimraf ./dist*",
|
|
48
48
|
"format": "prettier --write src/*.js src/**/*.js src/**/*.mjs",
|
|
49
|
-
"lint": "eslint src/*.js src/**/*.js src/**/*.mjs --max-warnings=20",
|
|
50
|
-
"build": "npm run clean && copyfiles -u 1 src/*.js dist && copyfiles -u 2 src/HomeKitDevice/*.js dist && copyfiles -u 2 src/HomeKitHistory/*.js dist && copyfiles -u 1 src/res/*.h264 dist && copyfiles -u 1 src/res/*.jpg dist && copyfiles -u 1 'src/protobuf/**/*.proto' dist",
|
|
49
|
+
"lint": "eslint src/*.js src/**/*.js src/**/*.mjs --fix --max-warnings=20",
|
|
50
|
+
"build": "npm run clean && copyfiles -u 1 src/*.js dist && copyfiles -u 2 src/HomeKitDevice/*.js dist && copyfiles -u 2 src/HomeKitHistory/*.js dist && copyfiles -u 1 src/res/*.h264 dist && copyfiles -u 1 src/res/*.jpg dist && copyfiles -u 1 'src/protobuf/**/*.proto' dist && copyfiles -u 1 src/plugins/*.js dist",
|
|
51
51
|
"prepublishOnly": "npm run lint && npm run build"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@eslint/js": "^9.
|
|
55
|
-
"@stylistic/eslint-plugin": "^4.
|
|
56
|
-
"@types/node": "^
|
|
57
|
-
"@typescript-eslint/parser": "^8.
|
|
54
|
+
"@eslint/js": "^9.29.0",
|
|
55
|
+
"@stylistic/eslint-plugin": "^4.4.1",
|
|
56
|
+
"@types/node": "^24.0.1",
|
|
57
|
+
"@typescript-eslint/parser": "^8.34.0",
|
|
58
58
|
"copyfiles": "^2.4.1",
|
|
59
|
-
"eslint": "^9.
|
|
59
|
+
"eslint": "^9.29.0",
|
|
60
60
|
"homebridge": "^2.0.0-beta.0",
|
|
61
61
|
"prettier": "^3.5.3",
|
|
62
|
-
"prettier-eslint": "^16.
|
|
62
|
+
"prettier-eslint": "^16.4.2",
|
|
63
63
|
"rimraf": "^6.0.1"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"protobufjs": "^7.5.
|
|
66
|
+
"protobufjs": "^7.5.3",
|
|
67
67
|
"werift": "^0.22.1",
|
|
68
|
-
"ws": "^8.18.
|
|
68
|
+
"ws": "^8.18.2"
|
|
69
69
|
}
|
|
70
70
|
}
|
package/dist/floodlight.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// Nest Cam with Floodlight
|
|
2
|
-
// Part of homebridge-nest-accfactory
|
|
3
|
-
//
|
|
4
|
-
// Code version 27/9/2024
|
|
5
|
-
// Mark Hulskamp
|
|
6
|
-
'use strict';
|
|
7
|
-
|
|
8
|
-
// Define external module requirements
|
|
9
|
-
import NestCamera from './camera.js';
|
|
10
|
-
|
|
11
|
-
export default class NestFloodlight extends NestCamera {
|
|
12
|
-
lightService = undefined; // HomeKit light
|
|
13
|
-
|
|
14
|
-
constructor(accessory, api, log, eventEmitter, deviceData) {
|
|
15
|
-
super(accessory, api, log, eventEmitter, deviceData);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Class functions
|
|
19
|
-
addServices() {
|
|
20
|
-
// Call parent to setup the common camera things. Once we return, we can add in the specifics for our floodlight
|
|
21
|
-
let postSetupDetails = super.addServices();
|
|
22
|
-
|
|
23
|
-
this.lightService = this.accessory.getService(this.hap.Service.Switch);
|
|
24
|
-
if (this.deviceData.has_light === true) {
|
|
25
|
-
// Add service to for a light, including brightness control
|
|
26
|
-
if (this.lightService === undefined) {
|
|
27
|
-
this.lightService = this.accessory.addService(this.hap.Service.Lightbulb, '', 1);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (this.lightService.testCharacteristic(this.hap.Characteristic.Brightness) === false) {
|
|
31
|
-
this.lightService.addCharacteristic(this.hap.Characteristic.Brightness);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
this.lightService.getCharacteristic(this.hap.Characteristic.Brightness).setProps({
|
|
35
|
-
minStep: 10, // Light only goes in 10% increments
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
// Setup set callback for this light service
|
|
39
|
-
this.lightService.getCharacteristic(this.hap.Characteristic.On).onSet((value) => {
|
|
40
|
-
if (value !== this.deviceData.light_enabled) {
|
|
41
|
-
this.set({ uuid: this.deviceData.nest_google_uuid, light_enabled: value });
|
|
42
|
-
|
|
43
|
-
this?.log?.info && this.log.info('Floodlight on "%s" was turned', this.deviceData.description, value === true ? 'on' : 'off');
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
this.lightService.getCharacteristic(this.hap.Characteristic.Brightness).onSet((value) => {
|
|
48
|
-
if (value !== this.deviceData.light_brightness) {
|
|
49
|
-
this.set({ uuid: this.deviceData.nest_google_uuid, light_brightness: value });
|
|
50
|
-
|
|
51
|
-
this?.log?.info && this.log.info('Floodlight brightness on "%s" was set to "%s %"', this.deviceData.description, value);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
this.lightService.getCharacteristic(this.hap.Characteristic.On).onGet(() => {
|
|
56
|
-
return this.deviceData.light_enabled === true;
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
this.lightService.getCharacteristic(this.hap.Characteristic.Brightness).onGet(() => {
|
|
60
|
-
return this.deviceData.light_brightness;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
if (this.lightService !== undefined && this.deviceData.has_light !== true) {
|
|
64
|
-
// No longer required to have the light service
|
|
65
|
-
this.accessory.removeService(this.lightService);
|
|
66
|
-
this.lightService === undefined;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Create extra details for output
|
|
70
|
-
this.lightService !== undefined && postSetupDetails.push('Light support');
|
|
71
|
-
return postSetupDetails;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
removeServices() {
|
|
75
|
-
super.removeServices();
|
|
76
|
-
|
|
77
|
-
if (this.lightService !== undefined) {
|
|
78
|
-
this.accessory.removeService(this.lightService);
|
|
79
|
-
}
|
|
80
|
-
this.lightService = undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
updateServices(deviceData) {
|
|
84
|
-
if (typeof deviceData !== 'object' || this.controller === undefined) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Get the camera class todo all its updates first, then we'll handle the doorbell specific stuff
|
|
89
|
-
super.updateServices(deviceData);
|
|
90
|
-
|
|
91
|
-
if (this.lightService !== undefined) {
|
|
92
|
-
// Update status of light, including brightness
|
|
93
|
-
this.lightService.updateCharacteristic(this.hap.Characteristic.On, deviceData.light_enabled);
|
|
94
|
-
this.lightService.updateCharacteristic(this.hap.Characteristic.Brightness, deviceData.light_brightness);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|