UNPKG

homebridge-logo-platform

Version:
393 lines (267 loc) 12.1 kB
import { AccessoryPlugin, API, Service, CharacteristicValue } from 'homebridge'; import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; import { Accessory } from '../logo'; import { ValvePlatformAccessory } from './valvePlatformAccessory'; export class IrrigationSystemPlatformAccessory implements AccessoryPlugin { private model: string = "IrrigationSystem"; private api: API; public service: Service; private information: Service; private valveAccessories: any[]; public services: Service[]; private valveZones: number[]; private platform: any; private device: any; private pushButton: number; private logging: number; private irrigationSystemAutoUpdate: number; private updateActiveQueued: boolean; private updateProgramModeQueued: boolean; private updateInUseQueued: boolean; private updateWaterLevelQueued: boolean; private updateRemainingDurationQueued: boolean; private accStates = { Active: 0, ProgramMode: 0, InUse: 0, RemainingDuration: 0, WaterLevel: 0 }; name: string; constructor( api: API, platform: any, device: any ) { this.name = device.name; this.api = api; this.platform = platform; this.device = device; this.pushButton = this.device.pushButton || this.platform.pushButton; this.logging = this.device.logging || 0; this.irrigationSystemAutoUpdate = (this.device.irrigationSystemAutoUpdate ? 1 : 0); this.valveAccessories = []; this.services = []; this.valveZones = []; this.errorCheck(); this.service = new this.api.hap.Service.IrrigationSystem(this.device.name); this.service.getCharacteristic(this.platform.Characteristic.Active) .onSet(this.setActive.bind(this)) .onGet(this.getActive.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.ProgramMode) .onGet(this.getProgramMode.bind(this)); if (this.device.irrigationSystemGetWaterLevel) { this.service.getCharacteristic((this.platform.Characteristic.WaterLevel)) .onGet(this.getWaterLevel.bind(this)); } this.service.getCharacteristic(this.platform.Characteristic.InUse) .onGet(this.getInUse.bind(this)); if (this.device.irrigationSystemGetRemainingDuration) { this.service.getCharacteristic(this.platform.Characteristic.RemainingDuration) .onGet(this.getRemainingDuration.bind(this)); } if (this.device.irrigationSystemGetWaterLevel) { this.service.getCharacteristic((this.platform.Characteristic.WaterLevel)) .onGet(this.getWaterLevel.bind(this)); } this.information = new this.api.hap.Service.AccessoryInformation() .setCharacteristic(this.api.hap.Characteristic.Manufacturer, this.platform.manufacturer) .setCharacteristic(this.api.hap.Characteristic.Model, this.model + ' @ ' + this.platform.model) .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); this.services.push(this.service, this.information); const configDevices = this.platform.config.devices; for (const dev of configDevices) { if ((dev.type == Accessory.Valve) && (dev.valveParentIrrigationSystem == this.name)) { if (this.valveZones.includes(dev.valveZone)) { this.platform.log.error('[%s] zone number [%d] already used on [%s] irrigation system!', dev.name, dev.valveZone, this.name); } else { this.valveZones.push(dev.valveZone); } this.valveAccessories.push(new ValvePlatformAccessory(api, platform, dev, this)); } } this.updateActiveQueued = false; this.updateProgramModeQueued = false; this.updateInUseQueued = false; this.updateWaterLevelQueued = false; this.updateRemainingDurationQueued = false; if (this.platform.config.updateInterval) { setInterval(() => { this.updateActive(); this.updateProgramMode(); this.updateInUse(); this.updateWaterLevel(); this.updateRemainingDuration(); }, this.platform.config.updateInterval); } if (this.logging) { setInterval(() => { this.logAccessory(); }, this.platform.loggerInterval); } } errorCheck() { if (!(this.device.irrigationSystemGetActive || this.device.irrigationSystemAutoUpdate) || !this.device.irrigationSystemSetActiveOn || !this.device.irrigationSystemSetActiveOff || !this.device.irrigationSystemGetProgramMode || !(this.device.irrigationSystemGetInUse || this.device.irrigationSystemAutoUpdate)) { this.platform.log.error('[%s] One or more LOGO! Addresses are not correct!', this.device.name); } } getServices(): Service[] { return this.services; } async setActive(value: CharacteristicValue) { this.accStates.Active = value as number; if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { this.platform.log.info('[%s] Set Active <- %i', this.device.name, value); } let qItem: QueueSendItem; if (value) { qItem = new QueueSendItem(this.device.irrigationSystemSetActiveOn, value as number, this.pushButton); } else { qItem = new QueueSendItem(this.device.irrigationSystemSetActiveOff, value as number, this.pushButton); } this.platform.queue.bequeue(qItem); } async getActive(): Promise<CharacteristicValue> { const isActive = this.accStates.Active; this.updateActive(); return isActive; } async getProgramMode(): Promise<CharacteristicValue> { const isProgramMode = this.accStates.ProgramMode; this.updateProgramMode(); return isProgramMode; } async getInUse(): Promise<CharacteristicValue> { const isInUse = this.accStates.InUse; this.updateInUse(); return isInUse; } async getRemainingDuration(): Promise<CharacteristicValue> { const isRemainingDuration = this.accStates.RemainingDuration; this.updateRemainingDuration(); return isRemainingDuration; } async getWaterLevel(): Promise<CharacteristicValue> { const WaterLevel = this.accStates.WaterLevel; this.updateWaterLevel(); return WaterLevel; } updateActive() { if(this.irrigationSystemAutoUpdate) { let isActive: number = 0; for (const dev of this.valveAccessories) { isActive |= dev.getActive(); } this.accStates.Active = isActive; } else { if (this.updateActiveQueued) {return;} let qItem: QueueReceiveItem = new QueueReceiveItem(this.device.irrigationSystemGetActive, async (value: number) => { if (value != ErrorNumber.noData) { this.accStates.Active = value as number; if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { this.platform.log.info('[%s] Get Active -> %i', this.device.name, this.accStates.Active); } this.service.updateCharacteristic(this.api.hap.Characteristic.Active, this.accStates.Active); } this.updateActiveQueued = false; }); if (this.platform.queue.enqueue(qItem) === 1) { this.updateActiveQueued = true; }; }; } updateProgramMode() { if (this.updateProgramModeQueued) {return;} let qItem: QueueReceiveItem = new QueueReceiveItem(this.device.irrigationSystemGetProgramMode, async (value: number) => { if (value != ErrorNumber.noData) { this.accStates.ProgramMode = value as number; if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { this.platform.log.info('[%s] Get ProgramMode -> %i', this.device.name, this.accStates.ProgramMode); } this.service.updateCharacteristic(this.api.hap.Characteristic.ProgramMode, this.accStates.ProgramMode); } this.updateProgramModeQueued = false; }); if (this.platform.queue.enqueue(qItem) === 1) { this.updateProgramModeQueued = true; }; } updateInUse() { if(this.irrigationSystemAutoUpdate) { let isInUse: number = 0; for (const dev of this.valveAccessories) { isInUse |= dev.getInUse(); } this.accStates.InUse = isInUse; } else { if (this.updateInUseQueued) {return;} let qItem: QueueReceiveItem = new QueueReceiveItem(this.device.irrigationSystemGetInUse, async (value: number) => { if (value != ErrorNumber.noData) { this.accStates.InUse = value as number; if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { this.platform.log.info('[%s] Get InUse -> %i', this.device.name, this.accStates.InUse); } this.service.updateCharacteristic(this.api.hap.Characteristic.InUse, this.accStates.InUse); } this.updateInUseQueued = false; }); if (this.platform.queue.enqueue(qItem) === 1) { this.updateInUseQueued = true; }; }; } updateRemainingDuration() { if (this.device.irrigationSystemGetRemainingDuration) { if (this.updateRemainingDurationQueued){return;} let qItem: QueueReceiveItem = new QueueReceiveItem(this.device.irrigationSystemGetRemainingDuration, async (value: number) => { if (value != ErrorNumber.noData) { this.accStates.RemainingDuration = value as number; if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { this.platform.log.info('[%s] Get RemainingDuration -> %i', this.device.name, this.accStates.RemainingDuration); } this.service.updateCharacteristic(this.api.hap.Characteristic.RemainingDuration, this.accStates.RemainingDuration); } this.updateRemainingDurationQueued = false; }); if(this.platform.queue.enqueue(qItem) === 1) { this.updateRemainingDurationQueued = true; } } } updateWaterLevel() { if (this.device.irrigationSystemGetWaterLevel) { if (this.updateWaterLevelQueued) {return;} let qItem: QueueReceiveItem = new QueueReceiveItem(this.device.irrigationSystemGetWaterLevel, async (value: number) => { if (value != ErrorNumber.noData) { this.accStates.WaterLevel = value as number; if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { this.platform.log.info('[%s] Get WaterLevel -> %i', this.device.name, this.accStates.WaterLevel); } this.service.updateCharacteristic(this.api.hap.Characteristic.WaterLevel, this.accStates.WaterLevel); } this.updateWaterLevelQueued = false; }); if (this.platform.queue.enqueue(qItem) === 1) { this.updateWaterLevelQueued = true; }; } } logAccessory() { if ((this.platform.loggerType == LoggerType.InfluxDB) && this.platform.influxDB.isConfigured) { let logItems: InfluxDBLogItem[] = []; logItems.push(new InfluxDBLogItem("Active", this.accStates.Active, InfluxDBFild.Int)); logItems.push(new InfluxDBLogItem("ProgramMode", this.accStates.ProgramMode, InfluxDBFild.Int)); logItems.push(new InfluxDBLogItem("InUse", this.accStates.InUse, InfluxDBFild.Int)); logItems.push(new InfluxDBLogItem("RemainingDuration", this.accStates.RemainingDuration, InfluxDBFild.Int)); logItems.push(new InfluxDBLogItem("WaterLevel", this.accStates.WaterLevel, InfluxDBFild.Int)); this.platform.influxDB.logMultipleValues(this.device.name, logItems); } if (this.platform.loggerType == LoggerType.Fakegato) { // this.fakegatoService.addEntry({time: Math.round(new Date().valueOf() / 1000), temp: this.sensStates.CurrentTemperature}); } } }