homebridge-face-location/src/locationAccessory.ts
2020-12-11 13:39:30 -05:00

119 lines
3.3 KiB
TypeScript

import {
Service,
CharacteristicGetCallback,
PlatformAccessory,
} from "homebridge";
import { Monitor, IStateChangeEventArgs } from "./monitor/monitor";
import { HomeLocationPlatform } from "./homeLocationPlatform";
import { IRoom } from "./config";
const defaultDetectionTimeout = 180000;
interface IMotionDetectionService {
service: Service;
detectionTimeout: NodeJS.Timeout | null;
}
/**
* Platform Accessory
* An instance of this class is created for each accessory your platform registers
* Each accessory may expose multiple services of different service types.
*/
export class LocationAccessory {
private _services: Array<IMotionDetectionService>;
constructor(
private readonly _platform: HomeLocationPlatform,
private readonly _accessory: PlatformAccessory,
private _monitor: Monitor,
private _room: IRoom
) {
this._services = [];
// set accessory information
this._accessory
.getService(this._platform.Service.AccessoryInformation)!
.setCharacteristic(
this._platform.Characteristic.Manufacturer,
"Brandon Watson"
)
.setCharacteristic(
this._platform.Characteristic.Model,
"Person Location Sensor"
)
.setCharacteristic(
this._platform.Characteristic.SerialNumber,
"123-456-789"
);
//Init motion services
for (const label of this._monitor.labels) {
const newService =
this._accessory.getService(label) ||
this._accessory.addService(
this._platform.Service.MotionSensor,
label,
this._room + label
);
newService
.getCharacteristic(this._platform.Characteristic.MotionDetected)
.on("get", (callback: CharacteristicGetCallback) =>
this.onMotionDetectedGet(label, callback)
);
this._services.push({
service: newService,
detectionTimeout: null,
});
}
//Register monitor state change events
this._monitor.stateChangedEvent.push(this.onMonitorStateChange.bind(this));
}
private onMotionDetectedGet = (
label: string,
callback: CharacteristicGetCallback
) => {
this._platform.log.debug("Triggered GET MotionDetected");
// set this to a valid value for MotionDetected
const currentValue =
this._monitor.getState(label) === this._room.name ? 1 : 0;
callback(null, currentValue);
};
private onMonitorStateChange = (
sender: Monitor,
args: IStateChangeEventArgs
) => {
const motionService = this._services.find(
(motionService) => motionService.service.displayName == args.label
);
if (motionService) {
//Set accessory state
motionService.service.setCharacteristic(
this._platform.Characteristic.MotionDetected,
args.new === this._room.name
);
//Reset detectionTimeout
clearTimeout(motionService.detectionTimeout!);
motionService.detectionTimeout = setTimeout(
() => this.onDetectionTimeout(motionService),
this._platform.config.detectionTimeout ?? defaultDetectionTimeout
);
}
};
private onDetectionTimeout = (motionService: IMotionDetectionService) => {
//Set accessory state
motionService.service.setCharacteristic(
this._platform.Characteristic.MotionDetected,
0
);
this._monitor.resetState(motionService.service.displayName);
};
}