ring-client-api 11.5.2 → 11.7.0-beta.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/README.md CHANGED
@@ -115,7 +115,9 @@ camera.getSnapshot() // returns a Promise<Buffer> of the latest snapshot from th
115
115
 
116
116
  Camera also includes the following observables:
117
117
 
118
- - `onNewDing`: this will include the sip info and ding information every time a new ding is created
118
+ - `onNewNotification`: this is triggered any time a new push notification is received
119
+ - `onActiveNotifications`: notifications received within the last minute
120
+ - `onDoorbellPressed`: this will include the sip info and ding information every time a new ding is created
119
121
  - `onActiveDings`: dings created within the last 65 seconds
120
122
  - `onDoorbellPressed`: emits a ding every time the doorbell is pressed
121
123
  - `onMotionDetected`: `true` or `false` based on `onActiveDings` containing a motion ding
package/lib/api.d.ts CHANGED
@@ -33,7 +33,7 @@ export declare class RingApi extends Subscribed {
33
33
  beamBridges: BeamBridge[];
34
34
  onvifCameras: OnvifCameraData[];
35
35
  thirdPartyGarageDoorOpeners: ThirdPartyGarageDoorOpener[];
36
- intercomHandsets: IntercomHandsetAudioData[];
36
+ intercoms: IntercomHandsetAudioData[];
37
37
  unknownDevices: UnknownDevice[];
38
38
  }>;
39
39
  private listenForDeviceUpdates;
package/lib/api.js CHANGED
@@ -15,6 +15,7 @@ const util_1 = require("./util");
15
15
  const ffmpeg_1 = require("./ffmpeg");
16
16
  const subscribed_1 = require("./subscribed");
17
17
  const push_receiver_1 = __importDefault(require("@eneris/push-receiver"));
18
+ const ring_intercom_1 = require("./ring-intercom");
18
19
  class RingApi extends subscribed_1.Subscribed {
19
20
  constructor(options) {
20
21
  super();
@@ -34,14 +35,14 @@ class RingApi extends subscribed_1.Subscribed {
34
35
  }
35
36
  }
36
37
  async fetchRingDevices() {
37
- const { doorbots, chimes, authorized_doorbots: authorizedDoorbots, stickup_cams: stickupCams, base_stations: baseStations, beams_bridges: beamBridges, other: otherDevices, } = await this.restClient.request({ url: (0, rest_client_1.clientApi)('ring_devices') }), onvifCameras = [], intercomHandsets = [], thirdPartyGarageDoorOpeners = [], unknownDevices = [];
38
+ const { doorbots, chimes, authorized_doorbots: authorizedDoorbots, stickup_cams: stickupCams, base_stations: baseStations, beams_bridges: beamBridges, other: otherDevices, } = await this.restClient.request({ url: (0, rest_client_1.clientApi)('ring_devices') }), onvifCameras = [], intercoms = [], thirdPartyGarageDoorOpeners = [], unknownDevices = [];
38
39
  otherDevices.forEach((device) => {
39
40
  switch (device.kind) {
40
41
  case ring_types_1.RingDeviceType.OnvifCamera:
41
42
  onvifCameras.push(device);
42
43
  break;
43
44
  case ring_types_1.RingDeviceType.IntercomHandsetAudio:
44
- intercomHandsets.push(device);
45
+ intercoms.push(device);
45
46
  break;
46
47
  case ring_types_1.RingDeviceType.ThirdPartyGarageDoorOpener:
47
48
  thirdPartyGarageDoorOpeners.push(device);
@@ -66,16 +67,16 @@ class RingApi extends subscribed_1.Subscribed {
66
67
  beamBridges,
67
68
  onvifCameras,
68
69
  thirdPartyGarageDoorOpeners,
69
- intercomHandsets,
70
+ intercoms,
70
71
  unknownDevices,
71
72
  };
72
73
  }
73
- listenForDeviceUpdates(cameras, chimes) {
74
+ listenForDeviceUpdates(cameras, chimes, intercoms) {
74
75
  const { cameraStatusPollingSeconds } = this.options;
75
76
  if (!cameraStatusPollingSeconds) {
76
77
  return;
77
78
  }
78
- const onCamerasRequestUpdate = (0, rxjs_1.merge)(...cameras.map((camera) => camera.onRequestUpdate)), onChimesRequestUpdate = (0, rxjs_1.merge)(...chimes.map((chime) => chime.onRequestUpdate)), onUpdateReceived = new rxjs_1.Subject(), onPollForStatusUpdate = cameraStatusPollingSeconds
79
+ const devices = [...cameras, ...chimes, ...intercoms], onDeviceRequestUpdate = (0, rxjs_1.merge)(...devices.map((device) => device.onRequestUpdate)), onUpdateReceived = new rxjs_1.Subject(), onPollForStatusUpdate = cameraStatusPollingSeconds
79
80
  ? onUpdateReceived.pipe((0, operators_1.debounceTime)(cameraStatusPollingSeconds * 1000))
80
81
  : rxjs_1.EMPTY, camerasById = cameras.reduce((byId, camera) => {
81
82
  byId[camera.id] = camera;
@@ -83,11 +84,14 @@ class RingApi extends subscribed_1.Subscribed {
83
84
  }, {}), chimesById = chimes.reduce((byId, chime) => {
84
85
  byId[chime.id] = chime;
85
86
  return byId;
87
+ }, {}), intercomsById = intercoms.reduce((byId, intercom) => {
88
+ byId[intercom.id] = intercom;
89
+ return byId;
86
90
  }, {});
87
91
  if (!cameras.length && !chimes.length) {
88
92
  return;
89
93
  }
90
- this.addSubscriptions((0, rxjs_1.merge)(onCamerasRequestUpdate, onChimesRequestUpdate, onPollForStatusUpdate)
94
+ this.addSubscriptions((0, rxjs_1.merge)(onDeviceRequestUpdate, onPollForStatusUpdate)
91
95
  .pipe((0, operators_1.throttleTime)(500), (0, operators_1.switchMap)(() => this.fetchRingDevices().catch(() => null)))
92
96
  .subscribe((response) => {
93
97
  onUpdateReceived.next(null);
@@ -106,6 +110,12 @@ class RingApi extends subscribed_1.Subscribed {
106
110
  chime.updateData(data);
107
111
  }
108
112
  });
113
+ response.intercoms.forEach((data) => {
114
+ const intercom = intercomsById[data.id];
115
+ if (intercom) {
116
+ intercom.updateData(data);
117
+ }
118
+ });
109
119
  }));
110
120
  if (cameraStatusPollingSeconds) {
111
121
  onUpdateReceived.next(null); // kick off polling
@@ -175,19 +185,19 @@ class RingApi extends subscribed_1.Subscribed {
175
185
  });
176
186
  }
177
187
  async fetchAndBuildLocations() {
178
- const rawLocations = await this.fetchRawLocations(), { authorizedDoorbots, chimes, doorbots, allCameras, baseStations, beamBridges, } = await this.fetchRingDevices(), locationIdsWithHubs = [...baseStations, ...beamBridges].map((x) => x.location_id), cameras = allCameras.map((data) => new ring_camera_1.RingCamera(data, doorbots.includes(data) ||
188
+ const rawLocations = await this.fetchRawLocations(), { authorizedDoorbots, chimes, doorbots, allCameras, baseStations, beamBridges, intercoms, } = await this.fetchRingDevices(), locationIdsWithHubs = [...baseStations, ...beamBridges].map((x) => x.location_id), cameras = allCameras.map((data) => new ring_camera_1.RingCamera(data, doorbots.includes(data) ||
179
189
  authorizedDoorbots.includes(data) ||
180
- data.kind.startsWith('doorbell'), this.restClient, this.options.avoidSnapshotBatteryDrain || false)), ringChimes = chimes.map((data) => new ring_chime_1.RingChime(data, this.restClient)), locations = rawLocations
190
+ data.kind.startsWith('doorbell'), this.restClient, this.options.avoidSnapshotBatteryDrain || false)), ringChimes = chimes.map((data) => new ring_chime_1.RingChime(data, this.restClient)), ringIntercoms = intercoms.map((data) => new ring_intercom_1.RingIntercom(data, this.restClient)), locations = rawLocations
181
191
  .filter((location) => {
182
192
  return (!Array.isArray(this.options.locationIds) ||
183
193
  this.options.locationIds.includes(location.location_id));
184
194
  })
185
- .map((location) => new location_1.Location(location, cameras.filter((x) => x.data.location_id === location.location_id), ringChimes.filter((x) => x.data.location_id === location.location_id), {
195
+ .map((location) => new location_1.Location(location, cameras.filter((x) => x.data.location_id === location.location_id), ringChimes.filter((x) => x.data.location_id === location.location_id), ringIntercoms.filter((x) => x.data.location_id === location.location_id), {
186
196
  hasHubs: locationIdsWithHubs.includes(location.location_id),
187
197
  hasAlarmBaseStation: baseStations.some((station) => station.location_id === location.location_id),
188
198
  locationModePollingSeconds: this.options.locationModePollingSeconds,
189
199
  }, this.restClient));
190
- this.listenForDeviceUpdates(cameras, ringChimes);
200
+ this.listenForDeviceUpdates(cameras, ringChimes, ringIntercoms);
191
201
  this.registerPushReceiver(cameras).catch((e) => {
192
202
  (0, util_1.logError)(e);
193
203
  });
package/lib/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export * from './location';
3
3
  export * from './ring-camera';
4
4
  export * from './ring-chime';
5
5
  export * from './ring-device';
6
+ export * from './ring-intercom';
6
7
  export * from './ring-types';
package/lib/index.js CHANGED
@@ -19,4 +19,5 @@ __exportStar(require("./location"), exports);
19
19
  __exportStar(require("./ring-camera"), exports);
20
20
  __exportStar(require("./ring-chime"), exports);
21
21
  __exportStar(require("./ring-device"), exports);
22
+ __exportStar(require("./ring-intercom"), exports);
22
23
  __exportStar(require("./ring-types"), exports);
package/lib/location.d.ts CHANGED
@@ -5,11 +5,13 @@ import { RingRestClient } from './rest-client';
5
5
  import { RingCamera } from './ring-camera';
6
6
  import { RingChime } from './ring-chime';
7
7
  import { RingDevice } from './ring-device';
8
+ import { RingIntercom } from './ring-intercom';
8
9
  import { Subscribed } from './subscribed';
9
10
  export declare class Location extends Subscribed {
10
11
  readonly locationDetails: UserLocation;
11
12
  readonly cameras: RingCamera[];
12
13
  readonly chimes: RingChime[];
14
+ readonly intercoms: RingIntercom[];
13
15
  readonly options: {
14
16
  hasHubs: boolean;
15
17
  hasAlarmBaseStation: boolean;
@@ -35,7 +37,7 @@ export declare class Location extends Subscribed {
35
37
  offlineAssets: string[];
36
38
  hasHubs: boolean;
37
39
  hasAlarmBaseStation: boolean;
38
- constructor(locationDetails: UserLocation, cameras: RingCamera[], chimes: RingChime[], options: {
40
+ constructor(locationDetails: UserLocation, cameras: RingCamera[], chimes: RingChime[], intercoms: RingIntercom[], options: {
39
41
  hasHubs: boolean;
40
42
  hasAlarmBaseStation: boolean;
41
43
  locationModePollingSeconds?: number;
package/lib/location.js CHANGED
@@ -15,11 +15,12 @@ function flattenDeviceData(data) {
15
15
  return Object.assign({}, data.general && data.general.v2, data.device && data.device.v1);
16
16
  }
17
17
  class Location extends subscribed_1.Subscribed {
18
- constructor(locationDetails, cameras, chimes, options, restClient) {
18
+ constructor(locationDetails, cameras, chimes, intercoms, options, restClient) {
19
19
  super();
20
20
  this.locationDetails = locationDetails;
21
21
  this.cameras = cameras;
22
22
  this.chimes = chimes;
23
+ this.intercoms = intercoms;
23
24
  this.options = options;
24
25
  this.restClient = restClient;
25
26
  this.seq = 1;
@@ -3,6 +3,7 @@ import { AuthTokenResponse, SessionResponse } from './ring-types';
3
3
  import { ReplaySubject } from 'rxjs';
4
4
  export declare function clientApi(path: string): string;
5
5
  export declare function deviceApi(path: string): string;
6
+ export declare function commandsApi(path: string): string;
6
7
  export declare function appApi(path: string): string;
7
8
  export interface ExtendedResponse {
8
9
  responseTimestamp: number;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.RingRestClient = exports.appApi = exports.deviceApi = exports.clientApi = void 0;
6
+ exports.RingRestClient = exports.appApi = exports.commandsApi = exports.deviceApi = exports.clientApi = void 0;
7
7
  const got_1 = __importDefault(require("got"));
8
8
  const util_1 = require("./util");
9
9
  const rxjs_1 = require("rxjs");
@@ -18,7 +18,7 @@ const defaultRequestOptions = {
18
18
  7061: 'ASSET_CELL_BACKUP',
19
19
  7062: 'UPDATING',
20
20
  7063: 'MAINTENANCE',
21
- }, clientApiBaseUrl = 'https://api.ring.com/clients_api/', deviceApiBaseUrl = 'https://api.ring.com/devices/v1/', appApiBaseUrl = 'https://app.ring.com/api/v1/', apiVersion = 11;
21
+ }, clientApiBaseUrl = 'https://api.ring.com/clients_api/', deviceApiBaseUrl = 'https://api.ring.com/devices/v1/', commandsApiBaseUrl = 'https://api.ring.com/commands/v1/', appApiBaseUrl = 'https://app.ring.com/api/v1/', apiVersion = 11;
22
22
  function clientApi(path) {
23
23
  return clientApiBaseUrl + path;
24
24
  }
@@ -27,6 +27,10 @@ function deviceApi(path) {
27
27
  return deviceApiBaseUrl + path;
28
28
  }
29
29
  exports.deviceApi = deviceApi;
30
+ function commandsApi(path) {
31
+ return commandsApiBaseUrl + path;
32
+ }
33
+ exports.commandsApi = commandsApi;
30
34
  function appApi(path) {
31
35
  return appApiBaseUrl + path;
32
36
  }
@@ -0,0 +1,20 @@
1
+ import { IntercomHandsetAudioData } from './ring-types';
2
+ import { RingRestClient } from './rest-client';
3
+ import { BehaviorSubject, Subject } from 'rxjs';
4
+ export declare class RingIntercom {
5
+ private initialData;
6
+ private restClient;
7
+ id: number;
8
+ deviceType: import("./ring-types").RingDeviceType.IntercomHandsetAudio;
9
+ onData: BehaviorSubject<IntercomHandsetAudioData>;
10
+ onRequestUpdate: Subject<unknown>;
11
+ onBatteryLevel: import("rxjs").Observable<number | null>;
12
+ constructor(initialData: IntercomHandsetAudioData, restClient: RingRestClient);
13
+ updateData(update: IntercomHandsetAudioData): void;
14
+ requestUpdate(): void;
15
+ get data(): IntercomHandsetAudioData;
16
+ get name(): string;
17
+ get isOffline(): boolean;
18
+ get batteryLevel(): number | null;
19
+ unlock(): Promise<import("./rest-client").ExtendedResponse>;
20
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RingIntercom = void 0;
4
+ const rest_client_1 = require("./rest-client");
5
+ const rxjs_1 = require("rxjs");
6
+ const operators_1 = require("rxjs/operators");
7
+ const ring_camera_1 = require("./ring-camera");
8
+ class RingIntercom {
9
+ constructor(initialData, restClient) {
10
+ this.initialData = initialData;
11
+ this.restClient = restClient;
12
+ this.onRequestUpdate = new rxjs_1.Subject();
13
+ this.id = this.initialData.id;
14
+ this.deviceType = this.initialData.kind;
15
+ this.onData = new rxjs_1.BehaviorSubject(this.initialData);
16
+ this.onBatteryLevel = this.onData.pipe((0, operators_1.map)((data) => (0, ring_camera_1.getBatteryLevel)(data)), (0, operators_1.distinctUntilChanged)());
17
+ }
18
+ updateData(update) {
19
+ this.onData.next(update);
20
+ }
21
+ requestUpdate() {
22
+ this.onRequestUpdate.next(null);
23
+ }
24
+ get data() {
25
+ return this.onData.getValue();
26
+ }
27
+ get name() {
28
+ return this.data.description;
29
+ }
30
+ get isOffline() {
31
+ return this.data.alerts.connection === 'offline';
32
+ }
33
+ get batteryLevel() {
34
+ return (0, ring_camera_1.getBatteryLevel)(this.data);
35
+ }
36
+ unlock() {
37
+ return this.restClient.request({
38
+ method: 'PUT',
39
+ url: (0, rest_client_1.commandsApi)(`devices/${this.id}/device_rpc`),
40
+ json: {
41
+ command_name: 'device_rpc',
42
+ request: {
43
+ jsonrpc: '2.0',
44
+ method: 'unlock_door',
45
+ params: {
46
+ door_id: this.id,
47
+ user_id: 0,
48
+ },
49
+ },
50
+ },
51
+ });
52
+ }
53
+ }
54
+ exports.RingIntercom = RingIntercom;
@@ -80,6 +80,7 @@ export declare enum RingCameraKind {
80
80
  stickup_cam = "stickup_cam",
81
81
  stickup_cam_v3 = "stickup_cam_v3",
82
82
  stickup_cam_elite = "stickup_cam_elite",
83
+ stickup_cam_longfin = "stickup_cam_longfin",
83
84
  stickup_cam_lunar = "stickup_cam_lunar",
84
85
  spotlightw_v2 = "spotlightw_v2",
85
86
  hp_cam_v1 = "hp_cam_v1",
package/lib/ring-types.js CHANGED
@@ -88,6 +88,7 @@ var RingCameraKind;
88
88
  RingCameraKind["stickup_cam"] = "stickup_cam";
89
89
  RingCameraKind["stickup_cam_v3"] = "stickup_cam_v3";
90
90
  RingCameraKind["stickup_cam_elite"] = "stickup_cam_elite";
91
+ RingCameraKind["stickup_cam_longfin"] = "stickup_cam_longfin";
91
92
  RingCameraKind["stickup_cam_lunar"] = "stickup_cam_lunar";
92
93
  RingCameraKind["spotlightw_v2"] = "spotlightw_v2";
93
94
  RingCameraKind["hp_cam_v1"] = "hp_cam_v1";
@@ -119,6 +120,7 @@ exports.RingCameraModel = {
119
120
  stickup_cam: 'Stick Up Cam',
120
121
  stickup_cam_v3: 'Stick Up Cam',
121
122
  stickup_cam_elite: 'Stick Up Cam',
123
+ stickup_cam_longfin: 'Spotlight Cam Pro',
122
124
  stickup_cam_lunar: 'Stick Up Cam',
123
125
  spotlightw_v2: 'Spotlight Cam',
124
126
  hp_cam_v1: 'Floodlight Cam',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ring-client-api",
3
- "version": "11.5.2",
3
+ "version": "11.7.0-beta.0",
4
4
  "description": "Unofficial API for Ring doorbells, cameras, security alarm system and smart lighting",
5
5
  "main": "lib/index.js",
6
6
  "exports": {