forked from dgreif/ring
-
Notifications
You must be signed in to change notification settings - Fork 0
/
base-data-accessory.ts
136 lines (125 loc) · 3.51 KB
/
base-data-accessory.ts
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import {
BaseAccessory,
CharacteristicType,
ServiceType,
} from './base-accessory'
import { Observable, Subject } from 'rxjs'
import { RingCamera, RingChime, RingDevice } from '../api'
import { RingPlatformConfig } from './config'
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
import {
Logging,
PlatformAccessory,
CharacteristicValue,
CharacteristicSetCallback,
CharacteristicGetCallback,
CharacteristicEventTypes,
} from 'homebridge'
export abstract class BaseDataAccessory<
T extends RingDevice | RingCamera | RingChime
> extends BaseAccessory<T> {
abstract readonly device: T
abstract readonly accessory: PlatformAccessory
abstract readonly logger: Logging
abstract readonly config: RingPlatformConfig
registerCharacteristic({
characteristicType,
serviceType,
getValue,
setValue,
setValueDebounceTime = 0,
name,
requestUpdate,
serviceSubType,
}: {
characteristicType: CharacteristicType
serviceType: ServiceType
serviceSubType?: string
name?: string
getValue: (data: T['data']) => any
setValue?: (data: any) => any
setValueDebounceTime?: number
requestUpdate?: () => any
}) {
const service = this.getService(serviceType, name, serviceSubType),
characteristic = service.getCharacteristic(characteristicType),
{ device } = this
if (requestUpdate) {
// Only register for GET if an async request should be made to get an updated value
characteristic.on(
CharacteristicEventTypes.GET,
(callback: CharacteristicGetCallback) => {
try {
const value = getValue(device.data)
callback(null, value)
requestUpdate()
} catch (e) {
callback(e)
}
}
)
}
if (setValue && setValueDebounceTime) {
const onValueToSet = new Subject<any>()
characteristic.on(
CharacteristicEventTypes.SET,
(
newValue: CharacteristicValue,
callback: CharacteristicSetCallback
) => {
onValueToSet.next(newValue)
callback()
}
)
onValueToSet.pipe(debounceTime(setValueDebounceTime)).subscribe(setValue)
} else if (setValue) {
characteristic.on(
CharacteristicEventTypes.SET,
(
newValue: CharacteristicValue,
callback: CharacteristicSetCallback
) => {
Promise.resolve(setValue(newValue)).catch((e) => {
this.logger.error(e)
})
callback()
}
)
}
;(this.device.onData as Observable<T['data']>)
.pipe(map(getValue), distinctUntilChanged())
.subscribe((value) => characteristic.updateValue(value))
}
registerLevelCharacteristic({
characteristicType,
serviceType,
getValue,
setValue,
requestUpdate,
}: {
characteristicType: CharacteristicType
serviceType: ServiceType
getValue: (data: T['data']) => number
setValue: (data: any) => any
requestUpdate?: () => any
}) {
let targetLevel: number | undefined
this.registerCharacteristic({
characteristicType,
serviceType,
getValue: (data) => {
const newLevel = getValue(data)
if (newLevel === targetLevel) {
targetLevel = undefined
}
return targetLevel === undefined ? newLevel : targetLevel
},
setValue: (volume: number) => {
targetLevel = volume
setValue(volume)
},
setValueDebounceTime: 500,
requestUpdate,
})
}
}