-
Notifications
You must be signed in to change notification settings - Fork 15
/
get-devices-list.js
120 lines (98 loc) Β· 3.33 KB
/
get-devices-list.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
'use strict'
// ring's client api has strange names for things, replace them with more intuitive names
// for device types
// ojbect here maps client api names to our exposed name
const keyReplacements = {
doorbots: 'doorbells',
authorized_doorbots: 'authorisedDoorbells',
stickup_cams: 'cameras',
base_stations: 'baseStations',
chimes: 'chimes'
}
const emojis = {
chime: 'π',
hp_cam_v1: 'π·π‘',
hp_cam_v2: 'π·π‘',
lpd_v1: 'πͺ',
lpd_v2: 'πͺ'
}
module.exports = bottle => bottle.service( 'getDevicesList', getDevicesList,
'restClient',
'apiUrls',
'getLiveStream'
)
function getDevicesList( restClient, apiUrls, getLiveStream ) {
class DeviceHealth {
constructor( jsonFromResponse ) {
// a naieve copy like this could one day create a bug if Ring add property
// names to their client API that shaddow our OOP methods
Object.assign( this, jsonFromResponse )
this.updated_at = new Date( jsonFromResponse.updated_at )
}
}
class Device {
constructor( jsonFromResponse ) {
// a naieve copy like this could one day create a bug if Ring add property
// names to their client API that shaddow our OOP methods
Object.assign( this, jsonFromResponse )
}
toString() {
return `[${emojis[ this.kind ] || this.kind} ${this.description}]`
}
get apiUri() {
return apiUrls.doorbots().device( this )
}
async health() {
const healthResponse = await restClient.authenticatedRequest( 'GET', this.apiUri.health())
return new DeviceHealth( healthResponse.device_health )
}
}
class Chime extends Device {
get apiUri() {
return apiUrls.chimes().device( this )
}
}
const lightable = Base => class extends Base {
lightOn() {
return restClient.authenticatedRequest( 'PUT', this.apiUri.lightOn())
}
lightOff() {
return restClient.authenticatedRequest( 'PUT', this.apiUri.lightOff())
}
}
const streamable = Base => class extends Base {
get liveStream() {
return getLiveStream( this )
}
}
const Doorbell = streamable( Device )
const Camera = streamable( lightable( Device ))
const types = {
doorbells: Doorbell,
cameras: Camera,
chimes: Chime,
baseStations: Device,
authorisedDoorbells: Device
}
return async() => {
const rawDeviceList = await restClient.authenticatedRequest( 'GET', apiUrls.devices())
const listAsTypes = ( key, list ) => {
if ( types[ key ]) {
const Type = types[ key ]
return list.map( d => new Type( d ))
} else {
return list
}
}
const devices = Object.entries( rawDeviceList ).reduce(( acc, [ key, devicesList ]) => {
const newKey = keyReplacements[ key ] || key
return {
...acc,
[ newKey ]: listAsTypes( newKey, devicesList )
}
}, {})
// convenience property containing an array of all devices
devices.all = [ ...devices.doorbells, ...devices.cameras, ...devices.chimes ]
return devices
}
}