homebridge-ring 9.22.0-beta.0 → 9.24.0
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 +43 -2
- package/README.md +9 -1
- package/config.schema.json +11 -0
- package/lib/api/api.d.ts +1 -0
- package/lib/api/api.js +4 -2
- package/lib/api/location.js +11 -7
- package/lib/api/rest-client.d.ts +2 -0
- package/lib/api/rest-client.js +11 -4
- package/lib/api/ring-camera.d.ts +3 -2
- package/lib/api/ring-camera.js +25 -19
- package/lib/api/ring-chime.d.ts +1 -1
- package/lib/api/ring-chime.js +1 -1
- package/lib/api/ring-device.js +2 -1
- package/lib/api/ring-types.d.ts +2 -1
- package/lib/api/ring-types.js +1 -0
- package/lib/api/rtp-utils.js +4 -2
- package/lib/api/sip-call.js +1 -1
- package/lib/api/sip-session.js +3 -3
- package/lib/api/sip.d.ts +1 -0
- package/lib/api/sip.js +1 -0
- package/lib/api/util.js +5 -2
- package/lib/homebridge/base-accessory.js +1 -1
- package/lib/homebridge/base-device-accessory.js +1 -3
- package/lib/homebridge/camera-source.d.ts +1 -1
- package/lib/homebridge/camera-source.js +44 -25
- package/lib/homebridge/camera.js +1 -1
- package/lib/homebridge/config.d.ts +1 -0
- package/lib/homebridge/homebridge-ui/public/asset-manifest.json +10 -10
- package/lib/homebridge/homebridge-ui/public/index.html +1 -1
- package/lib/homebridge/homebridge-ui/public/static/js/2.fe3feb44.chunk.js +3 -0
- package/lib/homebridge/homebridge-ui/public/static/js/{2.01174b6e.chunk.js.LICENSE.txt → 2.fe3feb44.chunk.js.LICENSE.txt} +0 -0
- package/lib/homebridge/homebridge-ui/public/static/js/2.fe3feb44.chunk.js.map +1 -0
- package/lib/homebridge/homebridge-ui/public/static/js/main.adeecae1.chunk.js +2 -0
- package/lib/homebridge/homebridge-ui/public/static/js/main.adeecae1.chunk.js.map +1 -0
- package/lib/homebridge/homebridge-ui/public/static/js/{runtime-main.a9f07fed.js → runtime-main.401a8c6e.js} +1 -1
- package/lib/homebridge/homebridge-ui/public/static/js/runtime-main.401a8c6e.js.map +1 -0
- package/lib/homebridge/location-mode-switch.js +1 -1
- package/lib/homebridge/ring-platform.js +10 -4
- package/package.json +25 -22
- package/lib/homebridge/homebridge-ui/public/static/js/2.01174b6e.chunk.js +0 -3
- package/lib/homebridge/homebridge-ui/public/static/js/2.01174b6e.chunk.js.map +0 -1
- package/lib/homebridge/homebridge-ui/public/static/js/main.5f123226.chunk.js +0 -2
- package/lib/homebridge/homebridge-ui/public/static/js/main.5f123226.chunk.js.map +0 -1
- package/lib/homebridge/homebridge-ui/public/static/js/runtime-main.a9f07fed.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,12 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
-
## [9.
|
|
5
|
+
## [9.24.0](https://github.com/dgreif/ring/compare/v9.23.0...v9.24.0) (2022-01-22)
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
### Features
|
|
9
9
|
|
|
10
|
-
* support
|
|
10
|
+
* support glassbreak sensor ([98271f9](https://github.com/dgreif/ring/commit/98271f91f13aaae051fccaab7165cd17f2a2377c))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* allow process to exit when RingApi.disconnect() is called ([#851](https://github.com/dgreif/ring/issues/851)) ([8ef25ac](https://github.com/dgreif/ring/commit/8ef25acca66c533873b7fd43c7c899e34b4a7617))
|
|
16
|
+
* avoid error when ring terminates video stream ([7717d5e](https://github.com/dgreif/ring/commit/7717d5eaa40afed3d34f0e8e6eea1402e21afef7)), closes [#853](https://github.com/dgreif/ring/issues/853)
|
|
17
|
+
* update dependencies ([c80d052](https://github.com/dgreif/ring/commit/c80d052f9eaf4c0a50a495166177daa40299ffa7))
|
|
18
|
+
|
|
19
|
+
## [9.23.0](https://github.com/dgreif/ring/compare/v9.22.1...v9.23.0) (2021-10-17)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* **homebridge:** config option to hide camera lights ([58be17c](https://github.com/dgreif/ring/commit/58be17cfee524bfb158566e59d60438e9b6f0f5d)), closes [#802](https://github.com/dgreif/ring/issues/802)
|
|
25
|
+
* **homebridge:** option to treat "knock" as a ding ([7ece8b2](https://github.com/dgreif/ring/commit/7ece8b25314ef403a6c2bab6a28476a3b7229507)), closes [#514](https://github.com/dgreif/ring/issues/514)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* update dependencies ([b685e27](https://github.com/dgreif/ring/commit/b685e27e952a94635a277848821ebfa640d50ee2))
|
|
31
|
+
|
|
32
|
+
### [9.22.1](https://github.com/dgreif/ring/compare/v9.22.0...v9.22.1) (2021-10-13)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* **homebridge:** prevent login attempt for null refresh tokens ([#791](https://github.com/dgreif/ring/issues/791)) ([bbc9db5](https://github.com/dgreif/ring/commit/bbc9db5578f9b3ed2af49256c8581fef5af8e134))
|
|
38
|
+
|
|
39
|
+
## [9.22.0](https://github.com/dgreif/ring/compare/v9.21.2...v9.22.0) (2021-10-02)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
|
|
44
|
+
* support unknown zwave switch ([9a0a0b9](https://github.com/dgreif/ring/commit/9a0a0b9a3518e2ab9ec732d61fc1102a4e3b9458)), closes [#775](https://github.com/dgreif/ring/issues/775)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Bug Fixes
|
|
48
|
+
|
|
49
|
+
* handle promise rejections ([2df5591](https://github.com/dgreif/ring/commit/2df559128fbaeda7de6a64fa7029c86a08b26633))
|
|
50
|
+
* **homebridge:** handle camera stream ending before it is active ([4a0edc0](https://github.com/dgreif/ring/commit/4a0edc031fa6093ec0fa873f04479efa98307bc1)), closes [#762](https://github.com/dgreif/ring/issues/762)
|
|
51
|
+
* update dependencies ([24d5fde](https://github.com/dgreif/ring/commit/24d5fde5f456fa9bb3191c0dc8fa2b483a7ee310))
|
|
11
52
|
|
|
12
53
|
### [9.21.2](https://github.com/dgreif/ring/compare/v9.21.1...v9.21.2) (2021-09-08)
|
|
13
54
|
|
package/README.md
CHANGED
|
@@ -57,6 +57,7 @@ Only include an optional parameter if you actually need it. Default behavior wi
|
|
|
57
57
|
"hideDeviceIds": ["477e4800-fcde-4493-969b-d1a06f683102", "5aaed7a7-06df-4f18-b3af-291c89854d60"],
|
|
58
58
|
"hideLightGroups": true,
|
|
59
59
|
"hideDoorbellSwitch": true,
|
|
60
|
+
"hideCameraLight": true,
|
|
60
61
|
"hideCameraMotionSensor": true,
|
|
61
62
|
"sendCameraMotionNotificationsToTv": true,
|
|
62
63
|
"sendDoorbellMotionNotificationsToTv": true,
|
|
@@ -65,6 +66,7 @@ Only include an optional parameter if you actually need it. Default behavior wi
|
|
|
65
66
|
"hideAlarmSirenSwitch": true,
|
|
66
67
|
"hideUnsupportedServices": true,
|
|
67
68
|
"avoidSnapshotBatteryDrain": true,
|
|
69
|
+
"treatKnockAsDing": true,
|
|
68
70
|
"cameraStatusPollingSeconds": 20,
|
|
69
71
|
"cameraDingsPollingSeconds": 2,
|
|
70
72
|
"locationModePollingSeconds": 20,
|
|
@@ -79,6 +81,7 @@ Option | Default | Explanation
|
|
|
79
81
|
`hideDeviceIds` | `[]` | Allows you to hide specific devices by an array of ids. The id for each device is logged when homebridge starts.
|
|
80
82
|
`hideLightGroups` | `false` | Ring smart lighting allows you to create lighting groups within the Ring app. These groups are convenient for detecting motion in an area of your yard and turning on/off all lights in the group. However, you may wish to group the lights differently in HomeKit and ignore the groups you have configured in Ring. If this option is `true`, your Ring groups (and their associated motion sensor) will be ignored and will not show up in HomeKit.
|
|
81
83
|
`hideDoorbellSwitch` | `false` | If you have a Ring video doorbell, you will see a Programmable Switch associated with it. This switch can be used to perform actions on when the doorbell is pressed using "Single Press" actions. If you do not care to perform actions when the doorbell is pressed, you can hide the Programmable Switch by setting this option to `true`. You will still be able to receive _notifications_ from the doorbell even if the Programmable Switch is hidden (notifications can be configured in the settings for the doorbell camera in the Home app)
|
|
84
|
+
`hideCameraLight` | `false` | If `true`, hides the light for Ring cameras in HomeKit.
|
|
82
85
|
`hideCameraMotionSensor` | `false` | If `true`, hides the motion sensor for Ring cameras in HomeKit.
|
|
83
86
|
`sendCameraMotionNotificationsToTv` | `false` | If `true`, creates a 'Doorbell' accessory triggered by non-doorbell camera motion alerts for tvOS 14 notification support.
|
|
84
87
|
`sendDoorbellMotionNotificationsToTv` | `false` | If `true`, motion events on doorbell cameras will trigger a doorbell press event for tvOS 14 notification support.
|
|
@@ -89,6 +92,7 @@ Option | Default | Explanation
|
|
|
89
92
|
`showPanicButtons` | `false` | Creates a new `Panic Buttons` device in HomeKit with `Burglar Alarm` and `Fire Alarm` switches. **Use these at your own risk. I do not guarantee functionality in case of emergency, nor do I take responsibility for any false alarms**. These function just like the SOS sliders in the Ring app.
|
|
90
93
|
`nightModeBypassFor` | no Night Mode | Allows you to use Night mode to "Bypass and Arm" a Ring Alarm. Can be set to `all` for Away or `some` for Home. If set and Night mode is activated from HomeKit, any open contact sensors will automatically be bypassed.
|
|
91
94
|
`avoidSnapshotBatteryDrain` | false | Causes snapshots for battery cameras to be fetched at a minimum 10 minute interval to avoid draining the battery.
|
|
95
|
+
`treatKnockAsDing` | false | When someone knocks on your door, it will be recognized as a doorbell press in HomeKit. Limited to select camera models (Peephole Cam).
|
|
92
96
|
`cameraStatusPollingSeconds` | `20` | How frequently to poll for updates to your cameras and chimes (in seconds). Information like light/siren/volume/snooze status do not update in real time and need to be requested periodically.
|
|
93
97
|
`cameraDingsPollingSeconds` | `2` | How frequently to poll for new events from your cameras. These include motion and doorbell presses.
|
|
94
98
|
`locationModePollingSeconds` | `20` | How frequently to poll for location mode updates (in seconds). This is only useful if you are using location modes to control camera settings and want to keep an up-to-date reference of the current mode for each location. Polling is automatically disabled for locations equipped with a Ring Alarm. Will hide Location Mode switch if set to `0`
|
|
@@ -161,6 +165,10 @@ If you are having issues with your cameras in the Home app, please see the [Came
|
|
|
161
165
|
* Detect water leak
|
|
162
166
|
* Tamper status
|
|
163
167
|
* Battery status
|
|
168
|
+
* Glassbreak Sensor (**untested**)
|
|
169
|
+
* Detect glass breaking
|
|
170
|
+
* Tamper status
|
|
171
|
+
* Battery status
|
|
164
172
|
* Ring Smart Lights (Motion Detector, Flood/Path/Step/Spot Lights, Bulbs, Transformer, Outdoor Smart Plug, Mailbox Sensor)
|
|
165
173
|
* On/Off
|
|
166
174
|
* Brightness Level
|
|
@@ -173,7 +181,7 @@ If you are having issues with your cameras in the Home app, please see the [Came
|
|
|
173
181
|
* Fans
|
|
174
182
|
* On/Off
|
|
175
183
|
* Speed
|
|
176
|
-
* Lights/Switches/Outlets
|
|
184
|
+
* Lights/Switches/Outlets/Unknown (some brands of blinds, etc.)
|
|
177
185
|
* On/Off
|
|
178
186
|
* Brightness Level (if applicable)
|
|
179
187
|
* Hue/Sat/Color Temp are _possible_, but currently not supported.
|
package/config.schema.json
CHANGED
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
"type": "boolean",
|
|
32
32
|
"description": "Hides the Programmable Switch for Ring doorbells. This switch is only useful for triggering an automation when the doorbell is pressed, so most users can safely hide it"
|
|
33
33
|
},
|
|
34
|
+
"hideCameraLight": {
|
|
35
|
+
"title": "Hide Camera Light",
|
|
36
|
+
"type": "boolean"
|
|
37
|
+
},
|
|
34
38
|
"hideCameraMotionSensor": {
|
|
35
39
|
"title": "Hide Camera Motion Sensors",
|
|
36
40
|
"type": "boolean"
|
|
@@ -82,6 +86,11 @@
|
|
|
82
86
|
"type": "boolean",
|
|
83
87
|
"description": "Causes snapshots for battery cameras to be fetched at a minimum 10 minute interval to avoid draining the battery. This is useful if have the Home app open constantly, causing frequent snapshot requests."
|
|
84
88
|
},
|
|
89
|
+
"treatKnockAsDing": {
|
|
90
|
+
"title": "Treat Knock as Ding",
|
|
91
|
+
"type": "boolean",
|
|
92
|
+
"description": "When someone knocks on your door, it will be recognized as a doorbell press in HomeKit. Limited to select camera models (Peephole Cam)"
|
|
93
|
+
},
|
|
85
94
|
"sendCameraMotionNotificationsToTv": {
|
|
86
95
|
"title": "Create a 'Doorbell' accessory triggered by non-doorbell camera motion alerts for tvOS 14 notification support",
|
|
87
96
|
"type": "boolean"
|
|
@@ -161,6 +170,7 @@
|
|
|
161
170
|
"alarmOnEntryDelay",
|
|
162
171
|
"hideLightGroups",
|
|
163
172
|
"hideDoorbellSwitch",
|
|
173
|
+
"hideCameraLight",
|
|
164
174
|
"hideCameraMotionSensor",
|
|
165
175
|
"hideCameraSirenSwitch",
|
|
166
176
|
"hideInHomeDoorbellSwitch",
|
|
@@ -169,6 +179,7 @@
|
|
|
169
179
|
"showPanicButtons",
|
|
170
180
|
"nightModeBypassFor",
|
|
171
181
|
"avoidSnapshotBatteryDrain",
|
|
182
|
+
"treatKnockAsDing",
|
|
172
183
|
"sendCameraMotionNotificationsToTv",
|
|
173
184
|
"sendDoorbellMotionNotificationsToTv",
|
|
174
185
|
"beamDurationSeconds",
|
package/lib/api/api.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface RingApiOptions extends SessionOptions {
|
|
|
9
9
|
cameraDingsPollingSeconds?: number;
|
|
10
10
|
locationModePollingSeconds?: number;
|
|
11
11
|
avoidSnapshotBatteryDrain?: boolean;
|
|
12
|
+
treatKnockAsDing?: boolean;
|
|
12
13
|
debug?: boolean;
|
|
13
14
|
ffmpegPath?: string;
|
|
14
15
|
externalPorts?: {
|
package/lib/api/api.js
CHANGED
|
@@ -24,7 +24,8 @@ class RingApi extends subscribed_1.Subscribed {
|
|
|
24
24
|
super();
|
|
25
25
|
this.options = options;
|
|
26
26
|
this.restClient = new rest_client_1.RingRestClient(this.options);
|
|
27
|
-
this.onRefreshTokenUpdated =
|
|
27
|
+
this.onRefreshTokenUpdated =
|
|
28
|
+
this.restClient.onRefreshTokenUpdated.asObservable();
|
|
28
29
|
if (options.debug) {
|
|
29
30
|
(0, util_1.enableDebug)();
|
|
30
31
|
}
|
|
@@ -128,7 +129,7 @@ class RingApi extends subscribed_1.Subscribed {
|
|
|
128
129
|
return __awaiter(this, void 0, void 0, function* () {
|
|
129
130
|
const rawLocations = yield this.fetchRawLocations(), { authorizedDoorbots, chimes, doorbots, allCameras, baseStations, beamBridges, } = yield this.fetchRingDevices(), locationIdsWithHubs = [...baseStations, ...beamBridges].map((x) => x.location_id), cameras = allCameras.map((data) => new ring_camera_1.RingCamera(data, doorbots.includes(data) ||
|
|
130
131
|
authorizedDoorbots.includes(data) ||
|
|
131
|
-
data.kind.startsWith('doorbell'), this.restClient, this.options.avoidSnapshotBatteryDrain || false)), ringChimes = chimes.map((data) => new ring_chime_1.RingChime(data, this.restClient)), locations = rawLocations
|
|
132
|
+
data.kind.startsWith('doorbell'), this.restClient, this.options.avoidSnapshotBatteryDrain || false, this.options.treatKnockAsDing || false)), ringChimes = chimes.map((data) => new ring_chime_1.RingChime(data, this.restClient)), locations = rawLocations
|
|
132
133
|
.filter((location) => {
|
|
133
134
|
return (!Array.isArray(this.options.locationIds) ||
|
|
134
135
|
this.options.locationIds.includes(location.location_id));
|
|
@@ -169,6 +170,7 @@ class RingApi extends subscribed_1.Subscribed {
|
|
|
169
170
|
.catch((e) => {
|
|
170
171
|
(0, util_1.logError)(e);
|
|
171
172
|
});
|
|
173
|
+
this.restClient.clearTimeouts();
|
|
172
174
|
}
|
|
173
175
|
}
|
|
174
176
|
exports.RingApi = RingApi;
|
package/lib/api/location.js
CHANGED
|
@@ -96,7 +96,7 @@ class Location extends subscribed_1.Subscribed {
|
|
|
96
96
|
this.addSubscriptions((0, rxjs_1.merge)(this.onLocationModeRequested, this.onLocationMode)
|
|
97
97
|
.pipe((0, operators_1.debounceTime)(options.locationModePollingSeconds * 1000))
|
|
98
98
|
.subscribe(() => this.getLocationMode()));
|
|
99
|
-
|
|
99
|
+
this.getLocationMode().catch(util_1.logError);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
get id() {
|
|
@@ -188,7 +188,7 @@ class Location extends subscribed_1.Subscribed {
|
|
|
188
188
|
}
|
|
189
189
|
setAlarmMode(alarmMode, bypassSensorZids) {
|
|
190
190
|
return __awaiter(this, void 0, void 0, function* () {
|
|
191
|
-
const securityPanel = yield this.getSecurityPanel(), updatedDataPromise = (0, rxjs_1.
|
|
191
|
+
const securityPanel = yield this.getSecurityPanel(), updatedDataPromise = (0, rxjs_1.firstValueFrom)(securityPanel.onData.pipe((0, operators_1.skip)(1)));
|
|
192
192
|
yield this.sendCommandToSecurityPanel('security-panel.switch-mode', {
|
|
193
193
|
mode: alarmMode,
|
|
194
194
|
bypass: bypassSensorZids,
|
|
@@ -224,7 +224,7 @@ class Location extends subscribed_1.Subscribed {
|
|
|
224
224
|
});
|
|
225
225
|
}
|
|
226
226
|
getNextMessageOfType(type, src) {
|
|
227
|
-
return (0, rxjs_1.
|
|
227
|
+
return (0, rxjs_1.firstValueFrom)(this.onMessage.pipe((0, operators_1.filter)((m) => m.msg === type && m.src === src), (0, operators_1.map)((m) => m.body)));
|
|
228
228
|
}
|
|
229
229
|
requestList(listType, assetId) {
|
|
230
230
|
return this.sendMessage({ msg: listType, dst: assetId });
|
|
@@ -243,7 +243,7 @@ class Location extends subscribed_1.Subscribed {
|
|
|
243
243
|
if (!this.connectionPromise) {
|
|
244
244
|
yield this.getConnection();
|
|
245
245
|
}
|
|
246
|
-
return (0, rxjs_1.
|
|
246
|
+
return (0, rxjs_1.firstValueFrom)(this.onDevices);
|
|
247
247
|
});
|
|
248
248
|
}
|
|
249
249
|
getRoomList(assetId) {
|
|
@@ -391,11 +391,15 @@ class Location extends subscribed_1.Subscribed {
|
|
|
391
391
|
this.disconnected = true;
|
|
392
392
|
this.unsubscribe();
|
|
393
393
|
this.cameras.forEach((camera) => camera.disconnect());
|
|
394
|
-
this.getDevices()
|
|
394
|
+
this.getDevices()
|
|
395
|
+
.then((devices) => {
|
|
395
396
|
devices.forEach((device) => device.disconnect());
|
|
396
|
-
})
|
|
397
|
+
})
|
|
398
|
+
.catch(util_1.logError);
|
|
397
399
|
if (this.connectionPromise) {
|
|
398
|
-
this.connectionPromise
|
|
400
|
+
this.connectionPromise
|
|
401
|
+
.then((connection) => connection.close())
|
|
402
|
+
.catch(util_1.logError);
|
|
399
403
|
}
|
|
400
404
|
}
|
|
401
405
|
}
|
package/lib/api/rest-client.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare class RingRestClient {
|
|
|
24
24
|
refreshToken: string | undefined;
|
|
25
25
|
private hardwareIdPromise;
|
|
26
26
|
private _authPromise;
|
|
27
|
+
private timeouts;
|
|
27
28
|
private clearPreviousAuth;
|
|
28
29
|
private get authPromise();
|
|
29
30
|
private sessionPromise?;
|
|
@@ -44,4 +45,5 @@ export declare class RingRestClient {
|
|
|
44
45
|
url: string;
|
|
45
46
|
}): Promise<T & ExtendedResponse>;
|
|
46
47
|
getCurrentAuth(): Promise<AuthTokenResponse>;
|
|
48
|
+
clearTimeouts(): void;
|
|
47
49
|
}
|
package/lib/api/rest-client.js
CHANGED
|
@@ -66,12 +66,15 @@ function requestWithRetry(requestOptions) {
|
|
|
66
66
|
class RingRestClient {
|
|
67
67
|
constructor(authOptions) {
|
|
68
68
|
this.authOptions = authOptions;
|
|
69
|
-
|
|
70
|
-
this.refreshToken = ('refreshToken' in this.authOptions ? this.authOptions.refreshToken : undefined);
|
|
71
|
-
this.hardwareIdPromise = (0, util_1.getHardwareId)(this.authOptions.systemId);
|
|
69
|
+
this.timeouts = [];
|
|
72
70
|
this.sessionPromise = undefined;
|
|
73
71
|
this.using2fa = false;
|
|
74
72
|
this.onRefreshTokenUpdated = new rxjs_1.ReplaySubject(1);
|
|
73
|
+
this.refreshToken =
|
|
74
|
+
'refreshToken' in this.authOptions
|
|
75
|
+
? this.authOptions.refreshToken
|
|
76
|
+
: undefined;
|
|
77
|
+
this.hardwareIdPromise = (0, util_1.getHardwareId)(this.authOptions.systemId);
|
|
75
78
|
}
|
|
76
79
|
clearPreviousAuth() {
|
|
77
80
|
this._authPromise = undefined;
|
|
@@ -83,11 +86,12 @@ class RingRestClient {
|
|
|
83
86
|
authPromise
|
|
84
87
|
.then(({ expires_in }) => {
|
|
85
88
|
// clear the existing auth promise 1 minute before it expires
|
|
86
|
-
setTimeout(() => {
|
|
89
|
+
const timeout = setTimeout(() => {
|
|
87
90
|
if (this._authPromise === authPromise) {
|
|
88
91
|
this.clearPreviousAuth();
|
|
89
92
|
}
|
|
90
93
|
}, ((expires_in || 3600) - 60) * 1000);
|
|
94
|
+
this.timeouts.push(timeout);
|
|
91
95
|
})
|
|
92
96
|
.catch(() => {
|
|
93
97
|
// ignore these errors here, they should be handled by the function making a rest request
|
|
@@ -288,5 +292,8 @@ class RingRestClient {
|
|
|
288
292
|
getCurrentAuth() {
|
|
289
293
|
return this.authPromise;
|
|
290
294
|
}
|
|
295
|
+
clearTimeouts() {
|
|
296
|
+
this.timeouts.forEach(clearTimeout);
|
|
297
|
+
}
|
|
291
298
|
}
|
|
292
299
|
exports.RingRestClient = RingRestClient;
|
package/lib/api/ring-camera.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class RingCamera extends Subscribed {
|
|
|
16
16
|
isDoorbot: boolean;
|
|
17
17
|
private restClient;
|
|
18
18
|
private avoidSnapshotBatteryDrain;
|
|
19
|
+
private treatKnockAsDing;
|
|
19
20
|
id: number;
|
|
20
21
|
deviceType: import("./ring-types").RingCameraKind;
|
|
21
22
|
model: string;
|
|
@@ -32,7 +33,7 @@ export declare class RingCamera extends Subscribed {
|
|
|
32
33
|
onMotionStarted: import("rxjs").Observable<null>;
|
|
33
34
|
onBatteryLevel: import("rxjs").Observable<number | null>;
|
|
34
35
|
onInHomeDoorbellStatus: import("rxjs").Observable<boolean>;
|
|
35
|
-
constructor(initialData: CameraData, isDoorbot: boolean, restClient: RingRestClient, avoidSnapshotBatteryDrain: boolean);
|
|
36
|
+
constructor(initialData: CameraData, isDoorbot: boolean, restClient: RingRestClient, avoidSnapshotBatteryDrain: boolean, treatKnockAsDing: boolean);
|
|
36
37
|
updateData(update: CameraData): void;
|
|
37
38
|
requestUpdate(): void;
|
|
38
39
|
get data(): CameraData;
|
|
@@ -85,7 +86,7 @@ export declare class RingCamera extends Subscribed {
|
|
|
85
86
|
private checkIfSnapshotsAreBlocked;
|
|
86
87
|
private requestSnapshotUpdate;
|
|
87
88
|
private refreshSnapshot;
|
|
88
|
-
getSnapshot(): Promise<Buffer>;
|
|
89
|
+
getSnapshot(): Promise<Buffer | undefined>;
|
|
89
90
|
getSipOptions(): Promise<SipOptions>;
|
|
90
91
|
getUpdatedSipOptions(expiredDingId: string): Promise<SipOptions>;
|
|
91
92
|
createSipSession(options?: {
|
package/lib/api/ring-camera.js
CHANGED
|
@@ -66,37 +66,40 @@ function getSearchQueryString(options) {
|
|
|
66
66
|
}
|
|
67
67
|
exports.getSearchQueryString = getSearchQueryString;
|
|
68
68
|
class RingCamera extends subscribed_1.Subscribed {
|
|
69
|
-
constructor(initialData, isDoorbot, restClient, avoidSnapshotBatteryDrain) {
|
|
69
|
+
constructor(initialData, isDoorbot, restClient, avoidSnapshotBatteryDrain, treatKnockAsDing) {
|
|
70
70
|
super();
|
|
71
71
|
this.initialData = initialData;
|
|
72
72
|
this.isDoorbot = isDoorbot;
|
|
73
73
|
this.restClient = restClient;
|
|
74
74
|
this.avoidSnapshotBatteryDrain = avoidSnapshotBatteryDrain;
|
|
75
|
-
this.
|
|
76
|
-
this.deviceType = this.initialData.kind;
|
|
77
|
-
this.model = ring_types_1.RingCameraModel[this.initialData.kind] || 'Unknown Model';
|
|
78
|
-
this.onData = new rxjs_1.BehaviorSubject(this.initialData);
|
|
79
|
-
this.hasLight = this.initialData.led_status !== undefined;
|
|
80
|
-
this.hasSiren = this.initialData.siren_status !== undefined;
|
|
81
|
-
this.hasBattery = (0, ring_types_1.isBatteryCameraKind)(this.deviceType) ||
|
|
82
|
-
(typeof this.initialData.battery_life === 'string' &&
|
|
83
|
-
this.batteryLevel !== null &&
|
|
84
|
-
this.batteryLevel < 100 &&
|
|
85
|
-
this.batteryLevel >= 0);
|
|
75
|
+
this.treatKnockAsDing = treatKnockAsDing;
|
|
86
76
|
this.onRequestUpdate = new rxjs_1.Subject();
|
|
87
77
|
this.onRequestActiveDings = new rxjs_1.Subject();
|
|
88
78
|
this.onNewDing = new rxjs_1.Subject();
|
|
89
79
|
this.onActiveDings = new rxjs_1.BehaviorSubject([]);
|
|
90
|
-
this.onDoorbellPressed = this.onNewDing.pipe((0, operators_1.filter)((ding) => ding.kind === 'ding'
|
|
80
|
+
this.onDoorbellPressed = this.onNewDing.pipe((0, operators_1.filter)((ding) => ding.kind === 'ding' ||
|
|
81
|
+
(this.treatKnockAsDing && ding.kind === 'door_activity')), (0, operators_1.share)());
|
|
91
82
|
this.onMotionDetected = this.onActiveDings.pipe((0, operators_1.map)((dings) => dings.some((ding) => ding.motion || ding.kind === 'motion')), (0, operators_1.distinctUntilChanged)(), (0, operators_1.publishReplay)(1), (0, operators_1.refCount)());
|
|
92
83
|
this.onMotionStarted = this.onMotionDetected.pipe((0, operators_1.filter)((currentlyDetected) => currentlyDetected), (0, operators_1.mapTo)(null), // no value needed, event is what matters
|
|
93
84
|
(0, operators_1.share)());
|
|
85
|
+
this.expiredDingIds = [];
|
|
86
|
+
this.lastSnapshotTimestampLocal = 0;
|
|
87
|
+
this.id = this.initialData.id;
|
|
88
|
+
this.deviceType = this.initialData.kind;
|
|
89
|
+
this.model = ring_types_1.RingCameraModel[this.initialData.kind] || 'Unknown Model';
|
|
90
|
+
this.onData = new rxjs_1.BehaviorSubject(this.initialData);
|
|
91
|
+
this.hasLight = this.initialData.led_status !== undefined;
|
|
92
|
+
this.hasSiren = this.initialData.siren_status !== undefined;
|
|
93
|
+
this.hasBattery =
|
|
94
|
+
(0, ring_types_1.isBatteryCameraKind)(this.deviceType) ||
|
|
95
|
+
(typeof this.initialData.battery_life === 'string' &&
|
|
96
|
+
this.batteryLevel !== null &&
|
|
97
|
+
this.batteryLevel < 100 &&
|
|
98
|
+
this.batteryLevel >= 0);
|
|
94
99
|
this.onBatteryLevel = this.onData.pipe((0, operators_1.map)(getBatteryLevel), (0, operators_1.distinctUntilChanged)());
|
|
95
100
|
this.onInHomeDoorbellStatus = this.onData.pipe((0, operators_1.map)(({ settings: { chime_settings } }) => {
|
|
96
101
|
return Boolean(chime_settings === null || chime_settings === void 0 ? void 0 : chime_settings.enable);
|
|
97
102
|
}), (0, operators_1.distinctUntilChanged)());
|
|
98
|
-
this.expiredDingIds = [];
|
|
99
|
-
this.lastSnapshotTimestampLocal = 0;
|
|
100
103
|
if (!initialData.subscribed) {
|
|
101
104
|
this.subscribeToDingEvents().catch((e) => {
|
|
102
105
|
(0, util_1.logError)('Failed to subscribe ' + initialData.description + ' to ding events');
|
|
@@ -250,7 +253,7 @@ class RingCamera extends subscribed_1.Subscribed {
|
|
|
250
253
|
}
|
|
251
254
|
getSipConnectionDetails() {
|
|
252
255
|
return __awaiter(this, void 0, void 0, function* () {
|
|
253
|
-
const vodPromise = (0, rxjs_1.
|
|
256
|
+
const vodPromise = (0, rxjs_1.firstValueFrom)(this.onNewDing), videoOnDemandDing = yield this.startVideoOnDemand();
|
|
254
257
|
if (videoOnDemandDing && 'sip_from' in videoOnDemandDing) {
|
|
255
258
|
// wired cams return a ding from live_view so we don't need to wait
|
|
256
259
|
return videoOnDemandDing;
|
|
@@ -407,10 +410,13 @@ class RingCamera extends subscribed_1.Subscribed {
|
|
|
407
410
|
url: (0, rest_client_1.clientApi)(`snapshots/image/${this.id}`),
|
|
408
411
|
responseType: 'buffer',
|
|
409
412
|
});
|
|
410
|
-
|
|
413
|
+
try {
|
|
414
|
+
yield this.lastSnapshotPromise;
|
|
415
|
+
}
|
|
416
|
+
catch (_) {
|
|
411
417
|
// snapshot request failed, don't use it again
|
|
412
418
|
this.lastSnapshotPromise = undefined;
|
|
413
|
-
}
|
|
419
|
+
}
|
|
414
420
|
return this.lastSnapshotPromise;
|
|
415
421
|
});
|
|
416
422
|
}
|
|
@@ -458,7 +464,7 @@ class RingCamera extends subscribed_1.Subscribed {
|
|
|
458
464
|
const sipSession = yield this.streamVideo({
|
|
459
465
|
output: ['-t', duration.toString(), outputPath],
|
|
460
466
|
});
|
|
461
|
-
yield (0, rxjs_1.
|
|
467
|
+
yield (0, rxjs_1.firstValueFrom)(sipSession.onCallEnded);
|
|
462
468
|
});
|
|
463
469
|
}
|
|
464
470
|
streamVideo(ffmpegOptions) {
|
package/lib/api/ring-chime.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare class RingChime {
|
|
|
5
5
|
private initialData;
|
|
6
6
|
private restClient;
|
|
7
7
|
id: number;
|
|
8
|
-
deviceType: "
|
|
8
|
+
deviceType: import("./ring-types").ChimeKind;
|
|
9
9
|
model: string;
|
|
10
10
|
onData: BehaviorSubject<ChimeData>;
|
|
11
11
|
onRequestUpdate: Subject<unknown>;
|
package/lib/api/ring-chime.js
CHANGED
|
@@ -23,11 +23,11 @@ class RingChime {
|
|
|
23
23
|
constructor(initialData, restClient) {
|
|
24
24
|
this.initialData = initialData;
|
|
25
25
|
this.restClient = restClient;
|
|
26
|
+
this.onRequestUpdate = new rxjs_1.Subject();
|
|
26
27
|
this.id = this.initialData.id;
|
|
27
28
|
this.deviceType = this.initialData.kind;
|
|
28
29
|
this.model = ring_types_1.ChimeModel[this.deviceType] || 'Chime';
|
|
29
30
|
this.onData = new rxjs_1.BehaviorSubject(this.initialData);
|
|
30
|
-
this.onRequestUpdate = new rxjs_1.Subject();
|
|
31
31
|
}
|
|
32
32
|
updateData(update) {
|
|
33
33
|
this.onData.next(update);
|
package/lib/api/ring-device.js
CHANGED
|
@@ -5,6 +5,7 @@ const rxjs_1 = require("rxjs");
|
|
|
5
5
|
const ring_types_1 = require("./ring-types");
|
|
6
6
|
const operators_1 = require("rxjs/operators");
|
|
7
7
|
const subscribed_1 = require("./subscribed");
|
|
8
|
+
const util_1 = require("./util");
|
|
8
9
|
class RingDevice extends subscribed_1.Subscribed {
|
|
9
10
|
constructor(initialData, location, assetId) {
|
|
10
11
|
super();
|
|
@@ -63,7 +64,7 @@ class RingDevice extends subscribed_1.Subscribed {
|
|
|
63
64
|
},
|
|
64
65
|
],
|
|
65
66
|
},
|
|
66
|
-
});
|
|
67
|
+
}).catch(util_1.logError);
|
|
67
68
|
}
|
|
68
69
|
toString() {
|
|
69
70
|
return this.toJSON();
|
package/lib/api/ring-types.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare enum RingDeviceType {
|
|
|
10
10
|
TemperatureSensor = "sensor.temperature",
|
|
11
11
|
WaterSensor = "sensor.water",
|
|
12
12
|
TiltSensor = "sensor.tilt",
|
|
13
|
+
GlassbreakSensor = "sensor.glassbreak",
|
|
13
14
|
RangeExtender = "range-extender.zwave",
|
|
14
15
|
ZigbeeAdapter = "adapter.zigbee",
|
|
15
16
|
AccessCodeVault = "access-code.vault",
|
|
@@ -214,7 +215,7 @@ export interface BeamBridge {
|
|
|
214
215
|
role: string;
|
|
215
216
|
updated_at: string;
|
|
216
217
|
}
|
|
217
|
-
declare type ChimeKind = 'chime' | 'chime_pro' | 'chime_v2' | 'chime_pro_v2';
|
|
218
|
+
export declare type ChimeKind = 'chime' | 'chime_pro' | 'chime_v2' | 'chime_pro_v2';
|
|
218
219
|
export declare const ChimeModel: {
|
|
219
220
|
readonly [P in ChimeKind]: string;
|
|
220
221
|
};
|
package/lib/api/ring-types.js
CHANGED
|
@@ -14,6 +14,7 @@ var RingDeviceType;
|
|
|
14
14
|
RingDeviceType["TemperatureSensor"] = "sensor.temperature";
|
|
15
15
|
RingDeviceType["WaterSensor"] = "sensor.water";
|
|
16
16
|
RingDeviceType["TiltSensor"] = "sensor.tilt";
|
|
17
|
+
RingDeviceType["GlassbreakSensor"] = "sensor.glassbreak";
|
|
17
18
|
RingDeviceType["RangeExtender"] = "range-extender.zwave";
|
|
18
19
|
RingDeviceType["ZigbeeAdapter"] = "adapter.zigbee";
|
|
19
20
|
RingDeviceType["AccessCodeVault"] = "access-code.vault";
|
package/lib/api/rtp-utils.js
CHANGED
|
@@ -28,8 +28,10 @@ function sendStunBindingRequest({ rtpDescription, rtpSplitter, rtcpSplitter, loc
|
|
|
28
28
|
else {
|
|
29
29
|
// ICE not supported. Fire and forget the stun request for RTP and RTCP
|
|
30
30
|
const encodedMessage = stun.encode(message);
|
|
31
|
-
rtpSplitter.send(encodedMessage, { address, port });
|
|
32
|
-
rtcpSplitter
|
|
31
|
+
rtpSplitter.send(encodedMessage, { address, port }).catch(util_1.logError);
|
|
32
|
+
rtcpSplitter
|
|
33
|
+
.send(encodedMessage, { address, port: rtcpPort })
|
|
34
|
+
.catch(util_1.logError);
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
exports.sendStunBindingRequest = sendStunBindingRequest;
|
package/lib/api/sip-call.js
CHANGED
|
@@ -166,7 +166,7 @@ class SipCall {
|
|
|
166
166
|
ackWithInfo(seq) {
|
|
167
167
|
return __awaiter(this, void 0, void 0, function* () {
|
|
168
168
|
// Don't wait for ack, it won't ever come back.
|
|
169
|
-
|
|
169
|
+
this.request({
|
|
170
170
|
method: 'ACK',
|
|
171
171
|
seq, // The ACK must have the original sequence number.
|
|
172
172
|
}).catch(rxjs_1.noop);
|
package/lib/api/sip-session.js
CHANGED
|
@@ -32,8 +32,8 @@ class SipSession extends subscribed_1.Subscribed {
|
|
|
32
32
|
this.hasStarted = false;
|
|
33
33
|
this.hasCallEnded = false;
|
|
34
34
|
this.onCallEndedSubject = new rxjs_1.ReplaySubject(1);
|
|
35
|
-
this.sipCall = this.createSipCall(this.sipOptions);
|
|
36
35
|
this.onCallEnded = this.onCallEndedSubject.asObservable();
|
|
36
|
+
this.sipCall = this.createSipCall(this.sipOptions);
|
|
37
37
|
}
|
|
38
38
|
createSipCall(sipOptions) {
|
|
39
39
|
if (this.sipCall) {
|
|
@@ -159,7 +159,7 @@ class SipSession extends subscribed_1.Subscribed {
|
|
|
159
159
|
return null;
|
|
160
160
|
}
|
|
161
161
|
if (!haveReceivedStreamPacket) {
|
|
162
|
-
|
|
162
|
+
this.sipCall.requestKeyFrame().catch(rxjs_1.noop);
|
|
163
163
|
haveReceivedStreamPacket = true;
|
|
164
164
|
}
|
|
165
165
|
return {
|
|
@@ -196,7 +196,7 @@ class SipSession extends subscribed_1.Subscribed {
|
|
|
196
196
|
}
|
|
197
197
|
this.hasCallEnded = true;
|
|
198
198
|
if (sendBye) {
|
|
199
|
-
this.sipCall.sendBye();
|
|
199
|
+
this.sipCall.sendBye().catch(util_1.logError);
|
|
200
200
|
}
|
|
201
201
|
// clean up
|
|
202
202
|
this.onCallEndedSubject.next(null);
|
package/lib/api/sip.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export function create(options: any, callback: any): {
|
|
|
19
19
|
isFlowUri: (uri: any) => boolean;
|
|
20
20
|
hostname: () => any;
|
|
21
21
|
destroy: () => void;
|
|
22
|
+
makeResponse: typeof makeResponse;
|
|
22
23
|
};
|
|
23
24
|
export function start(options: any, callback: any): void;
|
|
24
25
|
export function parseAOR(data: any): any;
|
package/lib/api/sip.js
CHANGED
package/lib/api/util.js
CHANGED
|
@@ -8,14 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.randomString = exports.randomInteger = exports.mapAsync = exports.stringify = exports.requestInput = exports.getHardwareId = exports.generateUuid = exports.enableDebug = exports.useLogger = exports.logError = exports.logInfo = exports.logDebug = exports.delay = void 0;
|
|
13
|
-
const
|
|
16
|
+
const debug_1 = __importDefault(require("debug"));
|
|
14
17
|
const colors_1 = require("colors");
|
|
15
18
|
const readline_1 = require("readline");
|
|
16
19
|
const uuid_1 = require("uuid");
|
|
17
20
|
const systeminformation_1 = require("systeminformation");
|
|
18
|
-
const debugLogger =
|
|
21
|
+
const debugLogger = (0, debug_1.default)('ring'), uuidNamespace = 'e53ffdc0-e91d-4ce1-bec2-df939d94739c';
|
|
19
22
|
let logger = {
|
|
20
23
|
logInfo(message) {
|
|
21
24
|
debugLogger(message);
|
|
@@ -56,7 +56,7 @@ class BaseAccessory {
|
|
|
56
56
|
// allow GET once a value is cached
|
|
57
57
|
characteristic.on("get" /* GET */, (callback) => __awaiter(this, void 0, void 0, function* () {
|
|
58
58
|
try {
|
|
59
|
-
const value = yield (0, rxjs_1.
|
|
59
|
+
const value = yield (0, rxjs_1.firstValueFrom)(onCachedValue);
|
|
60
60
|
callback(null, value);
|
|
61
61
|
requestUpdate();
|
|
62
62
|
}
|
|
@@ -68,9 +68,7 @@ class BaseDeviceAccessory extends base_data_accessory_1.BaseDataAccessory {
|
|
|
68
68
|
getValue: (data) => {
|
|
69
69
|
return data.volume ? data.volume * 100 : 0;
|
|
70
70
|
},
|
|
71
|
-
setValue: (volume) =>
|
|
72
|
-
device.setVolume(volume / 100);
|
|
73
|
-
},
|
|
71
|
+
setValue: (volume) => device.setVolume(volume / 100),
|
|
74
72
|
});
|
|
75
73
|
}
|
|
76
74
|
if (hasBatteryStatus(initialData)) {
|
|
@@ -7,7 +7,7 @@ export declare class CameraSource implements CameraStreamingDelegate {
|
|
|
7
7
|
private cachedSnapshot?;
|
|
8
8
|
constructor(ringCamera: RingCamera);
|
|
9
9
|
private previousLoadSnapshotPromise?;
|
|
10
|
-
loadSnapshot(): Promise<any
|
|
10
|
+
loadSnapshot(): Promise<any>;
|
|
11
11
|
private loadAndCacheSnapshot;
|
|
12
12
|
private getCurrentSnapshot;
|
|
13
13
|
handleSnapshotRequest(request: SnapshotRequest, callback: SnapshotRequestCallback): Promise<void>;
|