119 lines
3.3 KiB
TypeScript
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);
|
|
};
|
|
}
|