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 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)
@@ -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 = {
@@ -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 {
@@ -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 declare type AnyCameraData = CameraData | OnvifCameraData;
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;
@@ -1,4 +1,4 @@
1
- declare type Firmware = string | 'Up To Date';
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 declare type AlarmMode = 'all' | 'some' | 'none';
102
- export declare type ThermostatMode = 'heat' | 'cool' | 'off' | 'aux';
103
- export declare type MessageType = 'RoomGetList' | 'SessionInfo' | 'DeviceInfoDocGetList' | 'DeviceInfoSet';
104
- export declare type MessageDataType = 'RoomListV2Type' | 'SessionInfoType' | 'DeviceInfoDocType' | 'DeviceInfoSetType' | 'HubDisconnectionEventType';
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 declare type AssetKind = 'base_station_v1' | 'beams_bridge_v1' | 'floodlight_v2' | string;
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 declare 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';
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 declare type ChimeKind = 'chime' | 'chime_pro' | 'chime_v2' | 'chime_pro_v2';
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 declare type ChimeSoundKind = 'motion' | 'ding';
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
- declare type HealthCategory = 'very_poor' | 'poor' | 'good' | 'very_good' | 'unknown' | 'NA' | string | null;
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 declare type DingKind = 'motion' | 'ding' | 'on_demand' | 'alarm' | 'on_demand_link' | 'door_activity' | 'key_access' | 'DELETED_FOOTAGE' | 'OFFLINE_FOOTAGE' | 'OFFLINE_MOTION';
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 declare type DingState = 'ringing' | 'connected' | 'timed_out' | 'completed';
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 declare type PushNotification = PushNotificationDing | PushNotificationAlarm | PushNotificationLowBattery;
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 declare type TwoStageVerificationState = 'sms' | 'email' | 'totp';
945
- export declare type Auth2faResponse = {
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 declare type LocationModeInput = 'home' | 'away' | 'disarmed';
1005
- export declare type LocationMode = LocationModeInput | 'disabled' | 'unset';
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 declare type LocationModeAction = 'disableMotionDetection' | 'enableMotionDetection' | 'blockLiveViewLocally' | 'allowLiveViewLocally';
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<"failed" | "closed" | "connected" | "connecting" | "new" | "disconnected">;
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
- declare type IncomingMessage = AnswerMessage | IceCandidateMessage | SessionCreatedMessage | SessionStartedMessage | PongMessage | CloseMessage | NotificationMessage;
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
- declare type SpawnInput = string | number;
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 declare type DeepPartial<T> = {
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.0",
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.2",
20
+ "@eneris/push-receiver": "^3.1.4",
21
21
  "@homebridge/camera-utils": "^2.2.0",
22
- "werift": "0.17.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.5.7",
27
+ "rxjs": "^7.8.0",
28
28
  "socket.io-client": "^2.5.0",
29
- "systeminformation": "^5.12.14",
29
+ "systeminformation": "^5.17.10",
30
30
  "uuid": "^9.0.0",
31
- "ws": "^8.11.0"
31
+ "ws": "^8.12.1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/debug": "4.1.7",
35
- "@types/jest": "29.2.2",
36
- "@types/node": "18.11.9",
37
- "@types/uuid": "8.3.4",
38
- "@types/ws": "^8.5.3",
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.1",
41
- "ts-jest": "29.0.3",
40
+ "jest": "29.4.3",
41
+ "ts-jest": "29.0.5",
42
42
  "tsconfig": "0.0.0",
43
- "typescript": "4.8.4"
43
+ "typescript": "4.9.5"
44
44
  },
45
45
  "engines": {
46
46
  "node": "^16 || ^18"