ring-client-api 11.7.0 → 11.7.2
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/lib/api.js +1 -1
- package/lib/device-data.js +1 -0
- package/lib/rest-client.js +16 -16
- package/lib/ring-camera.d.ts +1 -1
- package/lib/ring-types.d.ts +18 -18
- package/lib/streaming/peer-connection.d.ts +1 -1
- package/lib/streaming/peer-connection.js +4 -0
- package/lib/streaming/ring-edge-connection.d.ts +1 -1
- package/lib/streaming/streaming-connection-base.d.ts +1 -0
- package/lib/streaming/streaming-connection-base.js +12 -1
- package/lib/streaming/streaming-session.d.ts +1 -1
- package/lib/streaming/streaming-session.js +3 -1
- package/lib/test/ring-camera.spec.d.ts +1 -0
- package/lib/test/ring-camera.spec.js +25 -0
- package/lib/util.d.ts +1 -1
- package/package.json +13 -13
package/lib/api.js
CHANGED
|
@@ -88,7 +88,7 @@ class RingApi extends subscribed_1.Subscribed {
|
|
|
88
88
|
byId[intercom.id] = intercom;
|
|
89
89
|
return byId;
|
|
90
90
|
}, {});
|
|
91
|
-
if (!cameras.length && !chimes.length) {
|
|
91
|
+
if (!cameras.length && !chimes.length && !intercoms.length) {
|
|
92
92
|
return;
|
|
93
93
|
}
|
|
94
94
|
this.addSubscriptions((0, rxjs_1.merge)(onDeviceRequestUpdate, onPollForStatusUpdate)
|
package/lib/device-data.js
CHANGED
|
@@ -61,6 +61,7 @@ async function logDeviceData() {
|
|
|
61
61
|
name: location.name,
|
|
62
62
|
cameras: location.cameras.map((camera) => camera.data),
|
|
63
63
|
chimes: location.chimes.map((chime) => chime.data),
|
|
64
|
+
intercoms: location.intercoms.map((intercom) => intercom.data),
|
|
64
65
|
devices: devices.map((device) => device.data),
|
|
65
66
|
};
|
|
66
67
|
}), results = {
|
package/lib/rest-client.js
CHANGED
|
@@ -65,22 +65,6 @@ async function requestWithRetry(requestOptions) {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
class RingRestClient {
|
|
68
|
-
constructor(authOptions) {
|
|
69
|
-
this.authOptions = authOptions;
|
|
70
|
-
this.timeouts = [];
|
|
71
|
-
this.sessionPromise = undefined;
|
|
72
|
-
this.using2fa = false;
|
|
73
|
-
this.onRefreshTokenUpdated = new rxjs_1.ReplaySubject(1);
|
|
74
|
-
this.baseSessionMetadata = {
|
|
75
|
-
api_version: apiVersion,
|
|
76
|
-
device_model: this.authOptions.controlCenterDisplayName ?? 'ring-client-api',
|
|
77
|
-
};
|
|
78
|
-
this.refreshToken =
|
|
79
|
-
'refreshToken' in this.authOptions
|
|
80
|
-
? this.authOptions.refreshToken
|
|
81
|
-
: undefined;
|
|
82
|
-
this.hardwareIdPromise = (0, util_1.getHardwareId)(this.authOptions.systemId);
|
|
83
|
-
}
|
|
84
68
|
clearPreviousAuth() {
|
|
85
69
|
this._authPromise = undefined;
|
|
86
70
|
}
|
|
@@ -104,6 +88,22 @@ class RingRestClient {
|
|
|
104
88
|
}
|
|
105
89
|
return this._authPromise;
|
|
106
90
|
}
|
|
91
|
+
constructor(authOptions) {
|
|
92
|
+
this.authOptions = authOptions;
|
|
93
|
+
this.timeouts = [];
|
|
94
|
+
this.sessionPromise = undefined;
|
|
95
|
+
this.using2fa = false;
|
|
96
|
+
this.onRefreshTokenUpdated = new rxjs_1.ReplaySubject(1);
|
|
97
|
+
this.baseSessionMetadata = {
|
|
98
|
+
api_version: apiVersion,
|
|
99
|
+
device_model: this.authOptions.controlCenterDisplayName ?? 'ring-client-api',
|
|
100
|
+
};
|
|
101
|
+
this.refreshToken =
|
|
102
|
+
'refreshToken' in this.authOptions
|
|
103
|
+
? this.authOptions.refreshToken
|
|
104
|
+
: undefined;
|
|
105
|
+
this.hardwareIdPromise = (0, util_1.getHardwareId)(this.authOptions.systemId);
|
|
106
|
+
}
|
|
107
107
|
getGrantData(twoFactorAuthCode) {
|
|
108
108
|
if (this.refreshToken && !twoFactorAuthCode) {
|
|
109
109
|
return {
|
package/lib/ring-camera.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Subscribed } from './subscribed';
|
|
|
7
7
|
import { FfmpegOptions, StreamingSession } from './streaming/streaming-session';
|
|
8
8
|
import { StreamingConnectionOptions } from './streaming/streaming-connection-base';
|
|
9
9
|
import { SimpleWebRtcSession } from './streaming/simple-webrtc-session';
|
|
10
|
-
export
|
|
10
|
+
export type AnyCameraData = CameraData | OnvifCameraData;
|
|
11
11
|
export declare function getBatteryLevel(data: Pick<CameraData, 'battery_life' | 'battery_life_2'> & {
|
|
12
12
|
health?: Partial<CameraData['health']>;
|
|
13
13
|
}): number | null;
|
package/lib/ring-types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
type Firmware = string | 'Up To Date';
|
|
2
2
|
export declare enum RingDeviceType {
|
|
3
3
|
BaseStation = "hub.redsky",
|
|
4
4
|
BaseStationPro = "hub.kili",
|
|
@@ -98,17 +98,17 @@ export declare enum RingCameraKind {
|
|
|
98
98
|
export declare const RingCameraModel: {
|
|
99
99
|
readonly [P in RingCameraKind]: string;
|
|
100
100
|
};
|
|
101
|
-
export
|
|
102
|
-
export
|
|
103
|
-
export
|
|
104
|
-
export
|
|
101
|
+
export type AlarmMode = 'all' | 'some' | 'none';
|
|
102
|
+
export type ThermostatMode = 'heat' | 'cool' | 'off' | 'aux';
|
|
103
|
+
export type MessageType = 'RoomGetList' | 'SessionInfo' | 'DeviceInfoDocGetList' | 'DeviceInfoSet';
|
|
104
|
+
export type MessageDataType = 'RoomListV2Type' | 'SessionInfoType' | 'DeviceInfoDocType' | 'DeviceInfoSetType' | 'HubDisconnectionEventType';
|
|
105
105
|
export interface SocketIoMessage {
|
|
106
106
|
msg: MessageType;
|
|
107
107
|
datatype: MessageDataType;
|
|
108
108
|
src: string;
|
|
109
109
|
body: any[];
|
|
110
110
|
}
|
|
111
|
-
export
|
|
111
|
+
export type AssetKind = 'base_station_v1' | 'beams_bridge_v1' | 'floodlight_v2' | string;
|
|
112
112
|
export interface AssetSession {
|
|
113
113
|
assetUuid: string;
|
|
114
114
|
connectionStatus: 'unknown' | 'cell-backup' | 'online';
|
|
@@ -116,7 +116,7 @@ export interface AssetSession {
|
|
|
116
116
|
kind: AssetKind;
|
|
117
117
|
sessionId: number;
|
|
118
118
|
}
|
|
119
|
-
export
|
|
119
|
+
export type AlarmState = 'burglar-alarm' | 'entry-delay' | 'fire-alarm' | 'co-alarm' | 'panic' | 'user-verified-burglar-alarm' | 'user-verified-co-or-fire-alarm' | 'burglar-accelerated-alarm' | 'fire-accelerated-alarm';
|
|
120
120
|
export declare const allAlarmStates: AlarmState[];
|
|
121
121
|
export interface RingDeviceData {
|
|
122
122
|
zid: string;
|
|
@@ -226,7 +226,7 @@ export interface BeamBridge {
|
|
|
226
226
|
role: string;
|
|
227
227
|
updated_at: string;
|
|
228
228
|
}
|
|
229
|
-
export
|
|
229
|
+
export type ChimeKind = 'chime' | 'chime_pro' | 'chime_v2' | 'chime_pro_v2';
|
|
230
230
|
export declare const ChimeModel: {
|
|
231
231
|
readonly [P in ChimeKind]: string;
|
|
232
232
|
};
|
|
@@ -268,7 +268,7 @@ export interface ChimeData {
|
|
|
268
268
|
email: string;
|
|
269
269
|
};
|
|
270
270
|
}
|
|
271
|
-
export
|
|
271
|
+
export type ChimeSoundKind = 'motion' | 'ding';
|
|
272
272
|
export interface ChimeUpdate {
|
|
273
273
|
description?: string;
|
|
274
274
|
latitude?: number;
|
|
@@ -749,7 +749,7 @@ export interface CameraDeviceSettingsData {
|
|
|
749
749
|
mode?: string;
|
|
750
750
|
};
|
|
751
751
|
}
|
|
752
|
-
|
|
752
|
+
type HealthCategory = 'very_poor' | 'poor' | 'good' | 'very_good' | 'unknown' | 'NA' | string | null;
|
|
753
753
|
export interface ChimeHealth {
|
|
754
754
|
id: number;
|
|
755
755
|
wifi_name: string;
|
|
@@ -772,7 +772,7 @@ export interface CameraHealth extends ChimeHealth {
|
|
|
772
772
|
transformer_voltage_category?: 'good';
|
|
773
773
|
ext_power_state?: number;
|
|
774
774
|
}
|
|
775
|
-
export
|
|
775
|
+
export type DingKind = 'motion' | 'ding' | 'on_demand' | 'alarm' | 'on_demand_link' | 'door_activity' | 'key_access' | 'DELETED_FOOTAGE' | 'OFFLINE_FOOTAGE' | 'OFFLINE_MOTION';
|
|
776
776
|
export interface CameraEvent {
|
|
777
777
|
created_at: string;
|
|
778
778
|
cv_properties: {
|
|
@@ -853,7 +853,7 @@ export interface RingDeviceHistoryEvent {
|
|
|
853
853
|
datatype: MessageDataType;
|
|
854
854
|
body: any;
|
|
855
855
|
}
|
|
856
|
-
export
|
|
856
|
+
export type DingState = 'ringing' | 'connected' | 'timed_out' | 'completed';
|
|
857
857
|
export declare enum NotificationDetectionType {
|
|
858
858
|
Human = "human",
|
|
859
859
|
Loitering = "loitering",
|
|
@@ -918,7 +918,7 @@ export interface PushNotificationLowBattery {
|
|
|
918
918
|
};
|
|
919
919
|
action: PushNotificationAction.LowBattery;
|
|
920
920
|
}
|
|
921
|
-
export
|
|
921
|
+
export type PushNotification = PushNotificationDing | PushNotificationAlarm | PushNotificationLowBattery;
|
|
922
922
|
export interface LiveCallResponse {
|
|
923
923
|
ding_id: string;
|
|
924
924
|
ding_kind: DingKind;
|
|
@@ -941,8 +941,8 @@ export interface AuthTokenResponse {
|
|
|
941
941
|
scope: 'client';
|
|
942
942
|
token_type: 'Bearer';
|
|
943
943
|
}
|
|
944
|
-
export
|
|
945
|
-
export
|
|
944
|
+
export type TwoStageVerificationState = 'sms' | 'email' | 'totp';
|
|
945
|
+
export type Auth2faResponse = {
|
|
946
946
|
error?: string | unknown;
|
|
947
947
|
error_description?: string;
|
|
948
948
|
} | {
|
|
@@ -1001,8 +1001,8 @@ export declare enum DispatchSignalType {
|
|
|
1001
1001
|
Burglar = "user-verified-burglar-xa",
|
|
1002
1002
|
Fire = "user-verified-fire-xa"
|
|
1003
1003
|
}
|
|
1004
|
-
export
|
|
1005
|
-
export
|
|
1004
|
+
export type LocationModeInput = 'home' | 'away' | 'disarmed';
|
|
1005
|
+
export type LocationMode = LocationModeInput | 'disabled' | 'unset';
|
|
1006
1006
|
export declare const disabledLocationModes: LocationMode[];
|
|
1007
1007
|
export interface LocationModeResponse {
|
|
1008
1008
|
mode: LocationMode;
|
|
@@ -1018,7 +1018,7 @@ export interface LocationModeResponse {
|
|
|
1018
1018
|
deviceIdType: 'doorbot' | string;
|
|
1019
1019
|
}[];
|
|
1020
1020
|
}
|
|
1021
|
-
export
|
|
1021
|
+
export type LocationModeAction = 'disableMotionDetection' | 'enableMotionDetection' | 'blockLiveViewLocally' | 'allowLiveViewLocally';
|
|
1022
1022
|
export interface LocationModeSetting {
|
|
1023
1023
|
deviceId: string;
|
|
1024
1024
|
deviceIdType: 'doorbot' | string;
|
|
@@ -26,7 +26,7 @@ export declare class WeriftPeerConnection extends Subscribed implements BasicPee
|
|
|
26
26
|
onVideoRtp: Subject<RtpPacket>;
|
|
27
27
|
onVideoRtcp: Subject<RtcpPacket>;
|
|
28
28
|
onIceCandidate: Subject<RTCIceCandidate>;
|
|
29
|
-
onConnectionState: ReplaySubject<"
|
|
29
|
+
onConnectionState: ReplaySubject<"connected" | "closed" | "failed" | "disconnected" | "new" | "connecting">;
|
|
30
30
|
returnAudioTrack: MediaStreamTrack;
|
|
31
31
|
private onRequestKeyFrame;
|
|
32
32
|
constructor();
|
|
@@ -55,6 +55,10 @@ class WeriftPeerConnection extends subscribed_1.Subscribed {
|
|
|
55
55
|
],
|
|
56
56
|
parameters: 'packetization-mode=1;profile-level-id=640029;level-asymmetry-allowed=1',
|
|
57
57
|
}),
|
|
58
|
+
new werift_1.RTCRtpCodecParameters({
|
|
59
|
+
mimeType: 'video/rtx',
|
|
60
|
+
clockRate: 90000,
|
|
61
|
+
}),
|
|
58
62
|
],
|
|
59
63
|
},
|
|
60
64
|
iceServers: ringIceServers.map((server) => ({ urls: server })),
|
|
@@ -51,7 +51,7 @@ interface CloseMessage {
|
|
|
51
51
|
};
|
|
52
52
|
} & SessionBody;
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
type IncomingMessage = AnswerMessage | IceCandidateMessage | SessionCreatedMessage | SessionStartedMessage | PongMessage | CloseMessage | NotificationMessage;
|
|
55
55
|
export declare class RingEdgeConnection extends StreamingConnectionBase {
|
|
56
56
|
private camera;
|
|
57
57
|
private readonly onSessionId;
|
|
@@ -11,6 +11,7 @@ export declare abstract class StreamingConnectionBase extends Subscribed {
|
|
|
11
11
|
protected options: StreamingConnectionOptions;
|
|
12
12
|
readonly onCallAnswered: ReplaySubject<string>;
|
|
13
13
|
readonly onCallEnded: ReplaySubject<void>;
|
|
14
|
+
readonly onError: ReplaySubject<void>;
|
|
14
15
|
readonly onMessage: ReplaySubject<{
|
|
15
16
|
method: string;
|
|
16
17
|
}>;
|
|
@@ -13,6 +13,7 @@ class StreamingConnectionBase extends subscribed_1.Subscribed {
|
|
|
13
13
|
this.options = options;
|
|
14
14
|
this.onCallAnswered = new rxjs_1.ReplaySubject(1);
|
|
15
15
|
this.onCallEnded = new rxjs_1.ReplaySubject(1);
|
|
16
|
+
this.onError = new rxjs_1.ReplaySubject(1);
|
|
16
17
|
this.onMessage = new rxjs_1.ReplaySubject();
|
|
17
18
|
this.hasEnded = false;
|
|
18
19
|
if (options.createPeerConnection) {
|
|
@@ -35,7 +36,14 @@ class StreamingConnectionBase extends subscribed_1.Subscribed {
|
|
|
35
36
|
.pipe((0, operators_1.concatMap)((event) => {
|
|
36
37
|
const message = JSON.parse(event.data);
|
|
37
38
|
this.onMessage.next(message);
|
|
38
|
-
return this.handleMessage(message)
|
|
39
|
+
return this.handleMessage(message).catch((e) => {
|
|
40
|
+
if (e instanceof Error &&
|
|
41
|
+
e.message.includes('negotiate codecs failed')) {
|
|
42
|
+
e = new Error('Failed to negotiate codecs. This is a known issue with Ring cameras. Please see https://github.com/dgreif/ring/wiki/Streaming-Legacy-Mode');
|
|
43
|
+
}
|
|
44
|
+
this.onError.next(e);
|
|
45
|
+
throw e;
|
|
46
|
+
});
|
|
39
47
|
}))
|
|
40
48
|
.subscribe(), onError.subscribe((e) => {
|
|
41
49
|
(0, util_1.logError)(e);
|
|
@@ -51,6 +59,9 @@ class StreamingConnectionBase extends subscribed_1.Subscribed {
|
|
|
51
59
|
(0, util_1.logDebug)('Stream connection closed');
|
|
52
60
|
this.callEnded();
|
|
53
61
|
}
|
|
62
|
+
}), this.onError.subscribe((e) => {
|
|
63
|
+
(0, util_1.logError)(e);
|
|
64
|
+
this.callEnded();
|
|
54
65
|
}));
|
|
55
66
|
}
|
|
56
67
|
activate() {
|
|
@@ -4,7 +4,7 @@ import { RingEdgeConnection } from './ring-edge-connection';
|
|
|
4
4
|
import { WebrtcConnection } from './webrtc-connection';
|
|
5
5
|
import { RingCamera } from '../ring-camera';
|
|
6
6
|
import { Subscribed } from '../subscribed';
|
|
7
|
-
|
|
7
|
+
type SpawnInput = string | number;
|
|
8
8
|
export interface FfmpegOptions {
|
|
9
9
|
input?: SpawnInput[];
|
|
10
10
|
video?: SpawnInput[] | false;
|
|
@@ -56,7 +56,9 @@ class StreamingSession extends subscribed_1.Subscribed {
|
|
|
56
56
|
return ports[0];
|
|
57
57
|
}
|
|
58
58
|
get isUsingOpus() {
|
|
59
|
-
return (0, rxjs_1.firstValueFrom)(this.onUsingOpus)
|
|
59
|
+
return (0, rxjs_1.firstValueFrom)(this.onUsingOpus.pipe((0, operators_1.mergeWith)(this.connection.onError.pipe((0, operators_1.map)((e) => {
|
|
60
|
+
throw e;
|
|
61
|
+
})))));
|
|
60
62
|
}
|
|
61
63
|
async startTranscoding(ffmpegOptions) {
|
|
62
64
|
if (this.hasEnded) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_1 = require("../index");
|
|
4
|
+
describe('Ring Camera', () => {
|
|
5
|
+
describe('battery level', () => {
|
|
6
|
+
it('should handle string battery life', () => {
|
|
7
|
+
expect((0, index_1.getBatteryLevel)({
|
|
8
|
+
battery_life: '49',
|
|
9
|
+
})).toEqual(49);
|
|
10
|
+
});
|
|
11
|
+
it('should handle null battery life', () => {
|
|
12
|
+
expect((0, index_1.getBatteryLevel)({ battery_life: null })).toEqual(null);
|
|
13
|
+
});
|
|
14
|
+
it('should handle right battery only', () => {
|
|
15
|
+
expect((0, index_1.getBatteryLevel)({ battery_life: null, battery_life_2: 24 })).toEqual(24);
|
|
16
|
+
});
|
|
17
|
+
it('should handle left battery only', () => {
|
|
18
|
+
expect((0, index_1.getBatteryLevel)({ battery_life: 76, battery_life_2: null })).toEqual(76);
|
|
19
|
+
});
|
|
20
|
+
it('should handle dual batteries', () => {
|
|
21
|
+
expect((0, index_1.getBatteryLevel)({ battery_life: '92', battery_life_2: 84 })).toEqual(84);
|
|
22
|
+
expect((0, index_1.getBatteryLevel)({ battery_life: '92', battery_life_2: 100 })).toEqual(92);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
package/lib/util.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare function stringify(data: any): string;
|
|
|
15
15
|
export declare function mapAsync<T, U>(records: T[], asyncMapper: (record: T) => Promise<U>): Promise<U[]>;
|
|
16
16
|
export declare function randomInteger(): number;
|
|
17
17
|
export declare function randomString(length: number): string;
|
|
18
|
-
export
|
|
18
|
+
export type DeepPartial<T> = {
|
|
19
19
|
[K in keyof T]?: T[K] extends Array<infer U> ? Array<DeepPartial<U>> : T[K] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[K]>;
|
|
20
20
|
};
|
|
21
21
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ring-client-api",
|
|
3
|
-
"version": "11.7.
|
|
3
|
+
"version": "11.7.2",
|
|
4
4
|
"description": "Unofficial API for Ring doorbells, cameras, security alarm system and smart lighting",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -17,30 +17,30 @@
|
|
|
17
17
|
"test:watch": "jest --watch"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@eneris/push-receiver": "^3.1.
|
|
20
|
+
"@eneris/push-receiver": "^3.1.4",
|
|
21
21
|
"@homebridge/camera-utils": "^2.2.0",
|
|
22
|
-
"werift": "0.
|
|
22
|
+
"werift": "0.18.1",
|
|
23
23
|
"@types/socket.io-client": "1.4.36",
|
|
24
24
|
"colors": "1.4.0",
|
|
25
25
|
"debug": "^4.3.4",
|
|
26
26
|
"got": "^11.8.5",
|
|
27
|
-
"rxjs": "^7.
|
|
27
|
+
"rxjs": "^7.8.0",
|
|
28
28
|
"socket.io-client": "^2.5.0",
|
|
29
|
-
"systeminformation": "^5.
|
|
29
|
+
"systeminformation": "^5.17.10",
|
|
30
30
|
"uuid": "^9.0.0",
|
|
31
|
-
"ws": "^8.
|
|
31
|
+
"ws": "^8.12.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/debug": "4.1.7",
|
|
35
|
-
"@types/jest": "29.
|
|
36
|
-
"@types/node": "18.
|
|
37
|
-
"@types/uuid": "
|
|
38
|
-
"@types/ws": "^8.5.
|
|
35
|
+
"@types/jest": "29.4.0",
|
|
36
|
+
"@types/node": "18.14.1",
|
|
37
|
+
"@types/uuid": "9.0.1",
|
|
38
|
+
"@types/ws": "^8.5.4",
|
|
39
39
|
"eslint-config-shared": "0.0.0",
|
|
40
|
-
"jest": "29.3
|
|
41
|
-
"ts-jest": "29.0.
|
|
40
|
+
"jest": "29.4.3",
|
|
41
|
+
"ts-jest": "29.0.5",
|
|
42
42
|
"tsconfig": "0.0.0",
|
|
43
|
-
"typescript": "4.
|
|
43
|
+
"typescript": "4.9.5"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": "^16 || ^18"
|