ring-client-api 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 +2 -1
- 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/package.json +26 -23
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
|
@@ -45,6 +45,7 @@ Option | Default | Explanation
|
|
|
45
45
|
`ffmpegPath` | Uses `ffmpeg-for-homebridge` | A custom path to the `ffmpeg` executable. By default, the static binaries built in [ffmpeg-for-homebridge](https://github.com/oznu/ffmpeg-for-homebridg) will be used. If you prefer to use your own version of ffmpeg, you can pass a complete path, or simply `"ffmpeg"` to use ffmpeg from your `PATH`.
|
|
46
46
|
`controlCenterDisplayName` | 'ring-client-api' | This allows you to change the displayed name for the Authorized Device within Control Center in the Ring app
|
|
47
47
|
`avoidSnapshotBatteryDrain` | false | Causes snapshots for battery cameras to be fetched at a minimum 10 minute interval to avoid draining the battery.
|
|
48
|
+
`treatKnockAsDing` | false | Will cause "knock" (`door_activity`) dings to be emitted from `onDoorbellPressed`
|
|
48
49
|
|
|
49
50
|
## Locations
|
|
50
51
|
```typescript
|
|
@@ -108,7 +109,7 @@ Camera also includes the following observables:
|
|
|
108
109
|
* `onDoorbellPressed`: emits a ding every time the doorbell is pressed
|
|
109
110
|
* `onMotionDetected`: `true` or `false` based on `onActiveDings` containing a motion ding
|
|
110
111
|
|
|
111
|
-
Some other useful
|
|
112
|
+
Some other useful properties
|
|
112
113
|
* `id`
|
|
113
114
|
* `name`: same as `description` from `data`
|
|
114
115
|
* `hasLight`: does this camera have a light
|
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);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ring-client-api",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.24.0",
|
|
4
4
|
"description": "Unofficial API for Ring doorbells, cameras, security alarm system and smart lighting",
|
|
5
5
|
"main": "lib/api/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -57,41 +57,41 @@
|
|
|
57
57
|
"@homebridge/plugin-ui-utils": "0.0.19",
|
|
58
58
|
"@types/socket.io-client": "1.4.36",
|
|
59
59
|
"colors": "1.4.0",
|
|
60
|
-
"debug": "4.3.
|
|
61
|
-
"got": "11.8.
|
|
62
|
-
"rxjs": "7.
|
|
60
|
+
"debug": "4.3.3",
|
|
61
|
+
"got": "11.8.3",
|
|
62
|
+
"rxjs": "7.5.2",
|
|
63
63
|
"sdp": "3.0.3",
|
|
64
64
|
"socket.io-client": "2.4.0",
|
|
65
65
|
"stun": "2.1.0",
|
|
66
|
-
"systeminformation": "5.
|
|
66
|
+
"systeminformation": "5.10.7",
|
|
67
67
|
"uuid": "8.3.2"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@types/debug": "4.1.7",
|
|
71
|
-
"@types/jest": "27.0
|
|
72
|
-
"@types/node": "
|
|
73
|
-
"@types/uuid": "8.3.
|
|
74
|
-
"@typescript-eslint/eslint-plugin": "
|
|
75
|
-
"@typescript-eslint/parser": "
|
|
76
|
-
"concurrently": "^
|
|
71
|
+
"@types/jest": "27.4.0",
|
|
72
|
+
"@types/node": "17.0.10",
|
|
73
|
+
"@types/uuid": "8.3.4",
|
|
74
|
+
"@typescript-eslint/eslint-plugin": "5.10.0",
|
|
75
|
+
"@typescript-eslint/parser": "5.10.0",
|
|
76
|
+
"concurrently": "^7.0.0",
|
|
77
77
|
"conventional-github-releaser": "3.1.5",
|
|
78
|
-
"dotenv": "
|
|
79
|
-
"eslint": "7.
|
|
78
|
+
"dotenv": "14.2.0",
|
|
79
|
+
"eslint": "8.7.0",
|
|
80
80
|
"eslint-config-prettier": "8.3.0",
|
|
81
|
-
"eslint-plugin-jest": "
|
|
82
|
-
"eslint-plugin-prettier": "
|
|
83
|
-
"express": "4.17.
|
|
84
|
-
"homebridge": "1.
|
|
85
|
-
"jest": "27.
|
|
86
|
-
"prettier": "2.
|
|
81
|
+
"eslint-plugin-jest": "25.7.0",
|
|
82
|
+
"eslint-plugin-prettier": "4.0.0",
|
|
83
|
+
"express": "4.17.2",
|
|
84
|
+
"homebridge": "1.4.0",
|
|
85
|
+
"jest": "27.4.7",
|
|
86
|
+
"prettier": "2.5.1",
|
|
87
87
|
"reflect-metadata": "0.1.13",
|
|
88
88
|
"rimraf": "3.0.2",
|
|
89
|
-
"standard-version": "9.3.
|
|
90
|
-
"ts-jest": "27.
|
|
91
|
-
"typescript": "4.
|
|
89
|
+
"standard-version": "9.3.2",
|
|
90
|
+
"ts-jest": "27.1.3",
|
|
91
|
+
"typescript": "4.5.5"
|
|
92
92
|
},
|
|
93
93
|
"engines": {
|
|
94
|
-
"node": "^10 || ^12.20 || ^14",
|
|
94
|
+
"node": "^10 || ^12.20 || ^14 || ^16",
|
|
95
95
|
"homebridge": ">=1.0.0"
|
|
96
96
|
},
|
|
97
97
|
"bugs": {
|
|
@@ -107,5 +107,8 @@
|
|
|
107
107
|
"type": "github",
|
|
108
108
|
"url": "https://github.com/sponsors/dgreif"
|
|
109
109
|
}
|
|
110
|
+
],
|
|
111
|
+
"workspaces": [
|
|
112
|
+
"homebridge-ui"
|
|
110
113
|
]
|
|
111
114
|
}
|