diff --git a/.changeset/slimy-lizards-divide.md b/.changeset/slimy-lizards-divide.md new file mode 100644 index 00000000..20819c4d --- /dev/null +++ b/.changeset/slimy-lizards-divide.md @@ -0,0 +1,6 @@ +--- +'homebridge-ring': minor +'ring-client-api': minor +--- + +Updated build target from ES2021 to ES2022. ES2022 is fully supported by Node 18, which is the current minimum supported version. diff --git a/packages/homebridge-ring/beam.ts b/packages/homebridge-ring/beam.ts index 39a4b4bb..d0ab912c 100644 --- a/packages/homebridge-ring/beam.ts +++ b/packages/homebridge-ring/beam.ts @@ -6,9 +6,8 @@ import { PlatformAccessory } from 'homebridge' import { logInfo } from 'ring-client-api/util' export class Beam extends BaseDeviceAccessory { - isLightGroup = - this.device.data.deviceType === RingDeviceType.BeamsLightGroupSwitch - groupId = this.device.data.groupId + private isLightGroup + private groupId constructor( public readonly device: RingDevice, @@ -17,6 +16,10 @@ export class Beam extends BaseDeviceAccessory { ) { super() + this.isLightGroup = + this.device.data.deviceType === RingDeviceType.BeamsLightGroupSwitch + this.groupId = this.device.data.groupId + const { Characteristic, Service } = hap, { MotionSensor } = Service, { diff --git a/packages/homebridge-ring/camera-source.ts b/packages/homebridge-ring/camera-source.ts index 8f00ed2b..140ef565 100644 --- a/packages/homebridge-ring/camera-source.ts +++ b/packages/homebridge-ring/camera-source.ts @@ -35,7 +35,7 @@ import { SrtpSession, SrtcpSession, } from 'werift' -import type { StreamingSession } from 'ring-client-api/lib/streaming/streaming-session' +import type { StreamingSession } from 'ring-client-api/streaming/streaming-session' import { OpusRepacketizer } from './opus-repacketizer' const readFileAsync = promisify(readFile), @@ -389,61 +389,63 @@ class StreamingSessionWrapper { } export class CameraSource implements CameraStreamingDelegate { - public controller = new hap.CameraController({ - cameraStreamCount: 10, - delegate: this, - streamingOptions: { - supportedCryptoSuites: [SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80], - video: { - resolutions: [ - [1280, 720, 30], - [1024, 768, 30], - [640, 480, 30], - [640, 360, 30], - [480, 360, 30], - [480, 270, 30], - [320, 240, 30], - [320, 240, 15], // Apple Watch requires this configuration - [320, 180, 30], - ], - codec: { - profiles: [H264Profile.BASELINE], - levels: [H264Level.LEVEL3_1], - }, - }, - audio: { - codecs: this.useOpus - ? [ - { - type: AudioStreamingCodecType.OPUS, - // required by watch - samplerate: AudioStreamingSamplerate.KHZ_8, - }, - { - type: AudioStreamingCodecType.OPUS, - samplerate: AudioStreamingSamplerate.KHZ_16, - }, - { - type: AudioStreamingCodecType.OPUS, - samplerate: AudioStreamingSamplerate.KHZ_24, - }, - ] - : [ - { - type: AudioStreamingCodecType.AAC_ELD, - samplerate: AudioStreamingSamplerate.KHZ_16, - }, - ], - }, - }, - }) + public controller private sessions: { [sessionKey: string]: StreamingSessionWrapper } = {} private cachedSnapshot?: Buffer constructor( private ringCamera: RingCamera, private useOpus = false, - ) {} + ) { + this.controller = new hap.CameraController({ + cameraStreamCount: 10, + delegate: this, + streamingOptions: { + supportedCryptoSuites: [SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80], + video: { + resolutions: [ + [1280, 720, 30], + [1024, 768, 30], + [640, 480, 30], + [640, 360, 30], + [480, 360, 30], + [480, 270, 30], + [320, 240, 30], + [320, 240, 15], // Apple Watch requires this configuration + [320, 180, 30], + ], + codec: { + profiles: [H264Profile.BASELINE], + levels: [H264Level.LEVEL3_1], + }, + }, + audio: { + codecs: this.useOpus + ? [ + { + type: AudioStreamingCodecType.OPUS, + // required by watch + samplerate: AudioStreamingSamplerate.KHZ_8, + }, + { + type: AudioStreamingCodecType.OPUS, + samplerate: AudioStreamingSamplerate.KHZ_16, + }, + { + type: AudioStreamingCodecType.OPUS, + samplerate: AudioStreamingSamplerate.KHZ_24, + }, + ] + : [ + { + type: AudioStreamingCodecType.AAC_ELD, + samplerate: AudioStreamingSamplerate.KHZ_16, + }, + ], + }, + }, + }) + } private previousLoadSnapshotPromise?: Promise async loadSnapshot(imageUuid?: string) { diff --git a/packages/homebridge-ring/camera.ts b/packages/homebridge-ring/camera.ts index 2a776f13..a2e9dbdd 100644 --- a/packages/homebridge-ring/camera.ts +++ b/packages/homebridge-ring/camera.ts @@ -11,10 +11,7 @@ import { firstValueFrom } from 'rxjs' export class Camera extends BaseDataAccessory { private inHomeDoorbellStatus: boolean | undefined - private cameraSource = new CameraSource( - this.device, - this.config.unbridgeCameras, - ) + private cameraSource constructor( public readonly device: RingCamera, @@ -23,6 +20,11 @@ export class Camera extends BaseDataAccessory { ) { super() + this.cameraSource = new CameraSource( + this.device, + this.config.unbridgeCameras, + ) + if (!hap.CameraController) { const error = 'HAP CameraController not found. Please make sure you are on homebridge version 1.0.0 or newer' diff --git a/packages/homebridge-ring/location-mode-switch.ts b/packages/homebridge-ring/location-mode-switch.ts index 498e3e08..277377aa 100644 --- a/packages/homebridge-ring/location-mode-switch.ts +++ b/packages/homebridge-ring/location-mode-switch.ts @@ -32,7 +32,7 @@ function getStateFromMode(mode: LocationMode) { export class LocationModeSwitch extends BaseAccessory { private targetState: any - public device = this.location // for use in BaseAccessory + public device constructor( private readonly location: Location, @@ -40,6 +40,8 @@ export class LocationModeSwitch extends BaseAccessory { public readonly config: RingPlatformConfig, ) { super() + this.device = location // for use in BaseAccessory + const { Characteristic, Service: { SecuritySystem, AccessoryInformation }, diff --git a/packages/homebridge-ring/security-panel.ts b/packages/homebridge-ring/security-panel.ts index b34b4e32..3ce3208f 100644 --- a/packages/homebridge-ring/security-panel.ts +++ b/packages/homebridge-ring/security-panel.ts @@ -17,9 +17,7 @@ function isValidNightModeBypass(mode?: AlarmMode) { } export class SecurityPanel extends BaseDeviceAccessory { - private alarmStates: AlarmState[] = this.config.alarmOnEntryDelay - ? allAlarmStates - : allAlarmStates.filter((x) => x !== 'entry-delay') + private alarmStates: AlarmState[] constructor( public readonly device: RingDevice, @@ -28,6 +26,10 @@ export class SecurityPanel extends BaseDeviceAccessory { ) { super() + this.alarmStates = this.config.alarmOnEntryDelay + ? allAlarmStates + : allAlarmStates.filter((x) => x !== 'entry-delay') + const { Characteristic, Service } = hap, validValues = [ Characteristic.SecuritySystemTargetState.AWAY_ARM, diff --git a/packages/ring-client-api/package.json b/packages/ring-client-api/package.json index 53b0415b..d0d6ddec 100644 --- a/packages/ring-client-api/package.json +++ b/packages/ring-client-api/package.json @@ -7,7 +7,8 @@ ".": "./lib/index.js", "./ffmpeg": "./lib/ffmpeg.js", "./util": "./lib/util.js", - "./rest-client": "./lib/rest-client.js" + "./rest-client": "./lib/rest-client.js", + "./streaming/streaming-session": "./lib/streaming/streaming-session.js" }, "scripts": { "build": "rm -rf lib && tsc --declaration && chmod +x ./lib/ring-*-cli.js", diff --git a/packages/ring-client-api/rest-client.ts b/packages/ring-client-api/rest-client.ts index 3e233383..797301a3 100644 --- a/packages/ring-client-api/rest-client.ts +++ b/packages/ring-client-api/rest-client.ts @@ -214,13 +214,9 @@ function parseAuthConfig(rawRefreshToken?: string): AuthConfig | undefined { } export class RingRestClient { - public refreshToken = - 'refreshToken' in this.authOptions - ? this.authOptions.refreshToken - : undefined - private authConfig = parseAuthConfig(this.refreshToken) - private hardwareIdPromise = - this.authConfig?.hid || getHardwareId(this.authOptions.systemId) + public refreshToken + private authConfig + private hardwareIdPromise private _authPromise: Promise | undefined private timeouts: ReturnType[] = [] private clearPreviousAuth() { @@ -259,15 +255,21 @@ export class RingRestClient { newRefreshToken: string }>(1) public onSession = new ReplaySubject(1) - public readonly baseSessionMetadata = { - api_version: apiVersion, - device_model: - this.authOptions.controlCenterDisplayName ?? 'ring-client-api', - } + public readonly baseSessionMetadata constructor( private authOptions: (EmailAuth | RefreshTokenAuth) & SessionOptions, - ) {} + ) { + this.refreshToken = + 'refreshToken' in authOptions ? authOptions.refreshToken : undefined + this.authConfig = parseAuthConfig(this.refreshToken) + this.hardwareIdPromise = + this.authConfig?.hid || getHardwareId(authOptions.systemId) + this.baseSessionMetadata = { + api_version: apiVersion, + device_model: authOptions.controlCenterDisplayName ?? 'ring-client-api', + } + } private getGrantData(twoFactorAuthCode?: string) { if (this.authConfig?.rt && !twoFactorAuthCode) { diff --git a/packages/tsconfig/tsconfig.json b/packages/tsconfig/tsconfig.json index cdef3235..ea04aa69 100644 --- a/packages/tsconfig/tsconfig.json +++ b/packages/tsconfig/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { - "target": "ES2021", - "lib": ["ES2021", "dom"], - "module": "commonjs", + "target": "ES2022", + "lib": ["ES2023", "DOM"], + "module": "node16", "esModuleInterop": true, "allowJs": true, "strict": true,