ring-client-api 11.6.0 → 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 +3 -1
- package/lib/api.d.ts +1 -1
- package/lib/api.js +20 -10
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/location.d.ts +3 -1
- package/lib/location.js +2 -1
- package/lib/rest-client.d.ts +1 -0
- package/lib/rest-client.js +6 -2
- package/lib/ring-intercom.d.ts +20 -0
- package/lib/ring-intercom.js +54 -0
- package/package.json +1 -1
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
|
-
- `
|
|
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
|
-
|
|
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 = [],
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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)(
|
|
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
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;
|
package/lib/rest-client.d.ts
CHANGED
|
@@ -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;
|
package/lib/rest-client.js
CHANGED
|
@@ -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;
|