Skip to content

Commit

Permalink
homekit: merge child lights into cameras (#659)
Browse files Browse the repository at this point in the history
  • Loading branch information
bjia56 authored Mar 26, 2023
1 parent 7e66d1a commit 3b7acc3
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 12 deletions.
13 changes: 11 additions & 2 deletions plugins/homekit/src/types/camera.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Deferred } from '@scrypted/common/src/deferred';
import sdk, { AudioSensor, Camera, Intercom, MotionSensor, ObjectsDetected, OnOff, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, VideoCamera, VideoCameraConfiguration } from '@scrypted/sdk';
import sdk, { AudioSensor, Camera, Intercom, MotionSensor, ObjectsDetected, OnOff, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, DeviceProvider, VideoCamera, VideoCameraConfiguration } from '@scrypted/sdk';
import { defaultObjectDetectionContactSensorTimeout } from '../camera-mixin';
import { addSupportedType, bindCharacteristic, DummyDevice } from '../common';
import { AudioRecordingCodec, AudioRecordingCodecType, AudioRecordingSamplerate, AudioStreamingCodec, AudioStreamingCodecType, AudioStreamingSamplerate, CameraController, CameraRecordingConfiguration, CameraRecordingDelegate, CameraRecordingOptions, CameraStreamingOptions, Characteristic, CharacteristicEventTypes, H264Level, H264Profile, MediaContainerType, OccupancySensor, RecordingPacket, Service, SRTPCryptoSuites, VideoCodecType, WithUUID } from '../hap';
import type { HomeKitPlugin } from '../main';
import { handleFragmentsRequests, iframeIntervalSeconds } from './camera/camera-recording';
import { createCameraStreamingDelegate } from './camera/camera-streaming';
import { FORCE_OPUS } from './camera/camera-utils';
import { makeAccessory } from './common';
import { makeAccessory, mergeOnOffDevicesByType } from './common';

const { deviceManager, systemManager } = sdk;

Expand Down Expand Up @@ -303,6 +303,15 @@ addSupportedType({
}
}

if (device.interfaces.includes(ScryptedInterface.DeviceProvider)) {
// merge in lights
const { devices } = mergeOnOffDevicesByType(device as ScryptedDevice as ScryptedDevice & DeviceProvider, accessory, ScryptedDeviceType.Light);

// ensure child devices are skipped by the rest of homekit by
// reporting that they've been merged
devices.map(device => homekitPlugin.mergedDevices.add(device.id));
}

return accessory;
}
});
17 changes: 9 additions & 8 deletions plugins/homekit/src/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,29 +167,30 @@ export function addFan(device: ScryptedDevice & Fan & OnOff, accessory: Accessor
}

/*
* addChildSirens looks for siren-type child devices of the given device provider
* and merges them as switches to the accessory represented by the device provider.
* mergeOnOffDevicesByType looks for the specified type of child devices under the
* given device provider and merges them as switches to the accessory represented
* by the device provider.
*
* Returns the services created as well as all of the child siren devices which have
* Returns the services created as well as all of the child OnOff devices which have
* been merged.
*/
export function addChildSirens(device: ScryptedDevice & DeviceProvider, accessory: Accessory): { services: Service[], devices: (ScryptedDevice & OnOff)[] } {
export function mergeOnOffDevicesByType(device: ScryptedDevice & DeviceProvider, accessory: Accessory, type: ScryptedDeviceType): { services: Service[], devices: (ScryptedDevice & OnOff)[] } {
if (!device.interfaces.includes(ScryptedInterface.DeviceProvider))
return undefined;

const children = getChildDevices(device);
const sirenDevices = [];
const mergedDevices = [];
const services = children.map((child: ScryptedDevice & OnOff) => {
if (child.type !== ScryptedDeviceType.Siren || !child.interfaces.includes(ScryptedInterface.OnOff))
if (child.type !== type || !child.interfaces.includes(ScryptedInterface.OnOff))
return undefined;

const onOffService = getOnOffService(child, accessory, Service.Switch)
sirenDevices.push(child);
mergedDevices.push(child);
return onOffService;
});

return {
services: services.filter(service => !!service),
devices: sirenDevices,
devices: mergedDevices,
};
}
5 changes: 3 additions & 2 deletions plugins/homekit/src/types/security.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SecuritySystem, SecuritySystemMode, SecuritySystemObstruction, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, DeviceProvider } from '@scrypted/sdk';
import { addSupportedType, bindCharacteristic, DummyDevice } from '../common';
import { Characteristic, CharacteristicEventTypes, CharacteristicSetCallback, CharacteristicValue, Service } from '../hap';
import { makeAccessory, addChildSirens } from './common';
import { makeAccessory, mergeOnOffDevicesByType } from './common';
import type { HomeKitPlugin } from "../main";

addSupportedType({
Expand Down Expand Up @@ -90,7 +90,8 @@ addSupportedType({
() => !!device.securitySystemState?.triggered);

if (device.interfaces.includes(ScryptedInterface.DeviceProvider)) {
const { devices } = addChildSirens(device as ScryptedDevice as ScryptedDevice & DeviceProvider, accessory);
// merge in sirens
const { devices } = mergeOnOffDevicesByType(device as ScryptedDevice as ScryptedDevice & DeviceProvider, accessory, ScryptedDeviceType.Siren);

// ensure child devices are skipped by the rest of homekit by
// reporting that they've been merged
Expand Down

0 comments on commit 3b7acc3

Please sign in to comment.