homebridge-eufy-security
Version:
Control Eufy Security from homebridge.
160 lines • 8.43 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoSyncStationAccessory = void 0;
const eufy_security_client_1 = require("eufy-security-client");
const StationAccessory_1 = require("./StationAccessory");
const utils_1 = require("../utils/utils");
/**
* Platform Auto Accessory
* An instance of this class is created for each accessory your platform registers
* Each accessory may expose multiple services of different service types.
*/
class AutoSyncStationAccessory {
accessory;
device;
static first = true;
static alarmFired = false;
static childs = [];
static first_station = {};
name;
guardModeChangeTimeout = { timeout: null, delay: 5000 };
static alarmFiredTimeout = { timeout: null, delay: 5000 };
constructor(platform, accessory, device) {
this.accessory = accessory;
this.device = device;
// Must be subsecond since station are initiated in //
let first = false;
if (AutoSyncStationAccessory.first) {
AutoSyncStationAccessory.first = false;
first = true;
}
this.name = this.device.getName();
// if it's the first we do create a full station accessory and then store it
// if not we need to fire event from Eufy to push to HK and vice versa
if (first) {
utils_1.log.debug(`${this.accessory.displayName} Constructed First Station`);
// Create the Station accessory
AutoSyncStationAccessory.first_station = new StationAccessory_1.StationAccessory(platform, accessory, device);
this.device.on('guard mode', this.changeModeToAllChilds.bind(this));
this.device.on('alarm event', this.fireAlarmToAllChilds.bind(this));
}
else {
utils_1.log.debug(`${this.accessory.displayName} Constructed Child Station`);
// Register to Eufy event of all childs
this.initChildEventRegister();
}
// Register child
AutoSyncStationAccessory.childs.push(this);
}
initChildEventRegister() {
const first_station = AutoSyncStationAccessory.first_station;
this.device.on('current mode', (station, currentMode) => {
utils_1.log.debug(`FWD ${this.name} 'current mode' TO clearTimeout (${currentMode})`);
if (this.guardModeChangeTimeout.timeout) {
// If there's an existing timeout, clear it
clearTimeout(this.guardModeChangeTimeout.timeout);
}
});
this.device.on('alarm arm delay event', (station, armDelay) => {
utils_1.log.debug(`FWD ${this.name} 'alarm arm delay event' TO ${first_station.name}`);
first_station.onStationAlarmDelayedEvent(station, armDelay);
});
this.device.on('alarm armed event', () => {
utils_1.log.debug(`FWD ${this.name} 'alarm armed event' TO ${first_station.name}`);
first_station.onStationAlarmArmedEvent();
});
this.device.on('alarm event', this.fireAlarmToAllChilds.bind(this));
}
/**
* Handle requests to set the 'Security System Target State' to all childs
*/
changeModeToAllChilds(station, guardMode) {
utils_1.log.info(`FWD ${this.name} 'guard mode (${eufy_security_client_1.GuardMode[guardMode]})' TO all the childs`);
AutoSyncStationAccessory.childs.forEach((child, index) => {
if (index === 0) {
return;
} // Already changed so do nothing for him
child.handleSecuritySystemTargetStateSet(guardMode);
});
}
/**
* Handle requests to synchronize alarm events to all child stations.
* @param station The station triggering the alarm event.
* @param alarmEvent The type of alarm event.
*/
fireAlarmToAllChilds(station, alarmEvent) {
const first_station = AutoSyncStationAccessory.first_station;
const manualAlarmSeconds = first_station.stationConfig.manualAlarmSeconds;
// Log the received alarm event
utils_1.log.debug(`RECEIVED ${this.name} 'alarm event' REASON ${eufy_security_client_1.AlarmEvent[alarmEvent]}`);
// Prevent looping with multiple received events
// Reinit after manualAlarmSeconds * 4 / 5
if (AutoSyncStationAccessory.alarmFired) {
return;
}
else {
AutoSyncStationAccessory.alarmFired = true;
utils_1.log.debug(`SET TIMEOUT ${this.name} 'alarm event' REASON ${eufy_security_client_1.AlarmEvent[alarmEvent]} FOR ${manualAlarmSeconds * 4 / 5}sec`);
AutoSyncStationAccessory.alarmFiredTimeout.timeout = setTimeout(() => {
AutoSyncStationAccessory.alarmFired = false;
utils_1.log.debug(`TIMEOUT ${this.name} 'alarm event' REASON ${eufy_security_client_1.AlarmEvent[alarmEvent]}`);
}, manualAlarmSeconds * 4 / 5 * 1000);
}
// List of alarm events fired to stop alarm
const pluginFiredAlarmStopEvents = [
eufy_security_client_1.AlarmEvent.HUB_STOP,
eufy_security_client_1.AlarmEvent.HUB_STOP_BY_APP,
eufy_security_client_1.AlarmEvent.HUB_STOP_BY_HAND,
eufy_security_client_1.AlarmEvent.HUB_STOP_BY_KEYPAD,
eufy_security_client_1.AlarmEvent.DEV_STOP
];
// Check if the alarm event is a plugin-fired alarm stop event
if (pluginFiredAlarmStopEvents.includes(alarmEvent)) {
return;
}
const characteristic = first_station.getService(utils_1.SERV.SecuritySystem)
.getCharacteristic(utils_1.CHAR.SecuritySystemCurrentState);
first_station.onStationAlarmEventPushNotification(characteristic, alarmEvent);
// Iterate over child stations to synchronize the alarm event
AutoSyncStationAccessory.childs.forEach(child => {
// Check if the alarm is already handled by the child itself
if (this.device.getSerial() === child.device.getSerial()) {
return; // Already fired by itself so do nothing for him
}
// Log the forwarded alarm event along with the reason and duration
utils_1.log.debug(`FWD ${this.name} 'alarm event' TO ${child.name} REASON ${eufy_security_client_1.AlarmEvent[alarmEvent]} FOR ${manualAlarmSeconds}sec`);
// Trigger the alarm sound on the child station with the specified duration
child.device.triggerStationAlarmSound(manualAlarmSeconds);
});
}
/**
* Handle requests to set the 'Security System Target State' characteristic
*/
handleSecuritySystemTargetStateSet(mode) {
try {
utils_1.log.debug(`${this.name} SET StationGuardMode Eufy: ${eufy_security_client_1.GuardMode[mode]}(${mode})`);
// Call the device's setGuardMode method to initiate the action
this.device.setGuardMode(mode);
// Set a new timeout
this.guardModeChangeTimeout.timeout = setTimeout(() => {
// This code is executed when the timeout elapses, indicating that the action may not have completed yet.
// You can include a message indicating that the action is being retried.
utils_1.log.warn(`${this.accessory.displayName} Changing guard mode to ${eufy_security_client_1.GuardMode[mode]} did not complete. Retry...'`);
// Call the device's setGuardMode method to initiate the action
this.device.setGuardMode(mode);
// Set a secondary timeout for retry, if needed
const retryTimeout = setTimeout(() => {
// This code is executed if the retry also times out, indicating a failure.
utils_1.log.error(`${this.accessory.displayName} Changing guard mode to ${eufy_security_client_1.GuardMode[mode]} timed out!`);
}, this.guardModeChangeTimeout.delay);
// Store the retry timeout as part of guardModeChangeTimeout
this.guardModeChangeTimeout.timeout = retryTimeout;
}, this.guardModeChangeTimeout.delay);
}
catch (error) {
utils_1.log.error(`${this.name} Error Setting security mode! ${error}`);
}
}
}
exports.AutoSyncStationAccessory = AutoSyncStationAccessory;
//# sourceMappingURL=AutoSyncStationAccessory.js.map
;