homebridge-logo-platform
Version:
This is a Siemens LOGO! Platform Plugin.
365 lines (300 loc) • 14.1 kB
text/typescript
/*
Homebridge Dev Device Pi 4:
Homebridge v1.6.1 (HAP v0.11.1)
NPM v9.2.0
NODE v18.13.0
HDMI Pi:
Homebridge v1.7.0 (HAP v0.11.1)
NPM v10.2.3
NODE v20.5.1 -> Homebridge requires Node.js version of ^18.15.0 || ^20.7.0 which does not satisfy the current Node.js version of v20.5.1. You may need to upgrade your installation of Node.js - see https://homebridge.io/w/JTKEF
*/
import { API, AccessoryPlugin, Service, Characteristic, StaticPlatformPlugin, Logging, PlatformConfig } from "homebridge";
import { ModBusLogo } from "./modbus-logo";
import { Snap7Logo } from "./snap7-logo";
import { InfluxDBLogger } from './influxDB';
import { Queue, QueueSendItem, QueueReceiveItem } from "./queue";
import { ErrorNumber } from "./error";
import { LoggerType, LoggerInterval } from "./logger";
import { LogoType, LogoInterface, LogoDefault, Accessory } from "./logo";
import { SwitchPlatformAccessory } from './accessories/switchPlatformAccessory';
import { LightbulbPlatformAccessory } from './accessories/lightbulbPlatformAccessory';
import { BlindPlatformAccessory } from './accessories/blindPlatformAccessory';
import { WindowPlatformAccessory } from './accessories/windowPlatformAccessory';
import { GaragedoorPlatformAccessory } from './accessories/garagedoorPlatformAccessory';
import { ThermostatPlatformAccessory } from './accessories/thermostatPlatformAccessory';
import { IrrigationSystemPlatformAccessory } from './accessories/irrigationSystemPlatformAccessory';
import { ValvePlatformAccessory } from './accessories/valvePlatformAccessory';
import { FanPlatformAccessory } from './accessories/fanPlatformAccessory';
import { FilterMaintenancePlatformAccessory } from './accessories/filterMaintenancePlatformAccessory';
import { OutletPlatformAccessory } from './accessories/outletPlatformAccessory';
import { OtherPlatformAccessory } from './accessories/otherPlatformAccessory';
import { LightSensorPlatformAccessory } from './sensors/lightSensorPlatformAccessory';
import { MotionSensorPlatformAccessory } from './sensors/motionSensorPlatformAccessory';
import { ContactSensorPlatformAccessory } from './sensors/contactSensorPlatformAccessory';
import { SmokeSensorPlatformAccessory } from './sensors/smokeSensorPlatformAccessory';
import { TemperatureSensorPlatformAccessory } from './sensors/temperatureSensorPlatformAccessory';
import { HumiditySensorPlatformAccessory } from './sensors/humiditySensorPlatformAccessory';
import { CarbonDioxideSensorPlatformAccessory } from './sensors/carbonDioxideSensorPlatformAccessory';
import { AirQualitySensorPlatformAccessory } from './sensors/airQualitySensorPlatformAccessory';
import { LeakSensorPlatformAccessory } from './sensors/leakSensorPlatformAccessory';
import { WatchdogPlatformAccessory } from './sensors/watchdogPlatformAccessory';
const pjson = require('../package.json');
declare const process: any;
export class LogoHomebridgePlatform implements StaticPlatformPlugin {
public readonly Service: typeof Service = this.api.hap.Service;
public readonly Characteristic: typeof Characteristic = this.api.hap.Characteristic;
public logo: any;
public ip: string;
public interface: string;
public port: number;
public logoType: string;
public local_TSAP: number;
public remote_TSAP: number;
public debugMsgLog: number;
public retryCount: number;
public queue: Queue;
public queueInterval: number;
public queueSize: number;
public queueMinSize: number;
public updateTimer: any;
public accessoriesArray: any[];
public manufacturer: string;
public model: string;
public firmwareRevision: string;
public pushButton: number;
public loggerType: string;
public loggerInterval: number;
public influxDB: InfluxDBLogger;
public FakeGatoHistoryService: any;
constructor(
public readonly log: Logging,
public readonly config: PlatformConfig,
public readonly api: API,
) {
// this.log.debug('Finished initializing platform:', this.config.name);
const transientNetErrors = ['ECONNRESET', 'ECONNREFUSED', 'ETIMEDOUT', 'EPIPE', 'EHOSTUNREACH', 'ENETUNREACH'];
process.on('uncaughtException', (err: any) => {
if (err && err.code && transientNetErrors.indexOf(err.code) !== -1) {
this.log.warn('Suppressed transient network error: ' + err.code + ' - ' + err.message);
return;
}
throw err;
});
this.ip = this.config.ip;
this.interface = this.config.interface || LogoInterface.Modbus;
this.port = this.config.port || LogoDefault.Port;
this.logoType = this.config.logoType || LogoType.T_0BA7;
this.local_TSAP = parseInt( this.config.localTSAP, 16 ) || LogoDefault.LocalTSAP;
this.remote_TSAP = parseInt( this.config.remoteTSAP, 16 ) || LogoDefault.RemoteTSAP;
this.debugMsgLog = this.config.debugMsgLog || LogoDefault.DebugMsgLog;
this.retryCount = this.config.retryCount || LogoDefault.RetryCount;
this.queueInterval = this.config.queueInterval || LogoDefault.QueueInterval;
this.queueSize = this.config.queueSize || LogoDefault.QueueSize;
this.queueMinSize = LogoDefault.QueueMinSize;
this.loggerType = this.config.loggerType || LoggerType.None;
this.loggerInterval = this.config.loggerInterval || LoggerInterval.T_5Min;
this.influxDB = new InfluxDBLogger(this, this.config);
this.FakeGatoHistoryService = require('fakegato-history')(this.api);
if (this.interface == LogoInterface.Modbus) {
this.logo = new ModBusLogo(this.ip, this.port, this.debugMsgLog, this.log, (this.retryCount + 1));
} else {
this.logo = new Snap7Logo(this.logoType, this.ip, this.local_TSAP, this.remote_TSAP, this.debugMsgLog, this.log, (this.retryCount + 1));
}
this.queue = new Queue(this.queueSize);
this.accessoriesArray = [];
this.manufacturer = pjson.author.name;
this.model = pjson.model;
this.firmwareRevision = pjson.version;
this.pushButton = (this.config.pushButton ? 1 : 0);
if (Array.isArray(this.config.devices)) {
const configDevices = this.config.devices;
for (const device of configDevices) {
if (this.config.debugMsgLog == true) {
this.log.info('Adding new accessory: ', device.name);
}
switch (device.type) {
case Accessory.Switch:
if (!(device.parentAccessory)){
this.accessoriesArray.push( new SwitchPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.Lightbulb:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new LightbulbPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 2;
break;
case Accessory.Blind:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new BlindPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 4;
break;
case Accessory.Window:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new WindowPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 4;
break;
case Accessory.Garagedoor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new GaragedoorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 3;
break;
case Accessory.Thermostat:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new ThermostatPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 4;
break;
case Accessory.IrrigationSystem:
this.accessoriesArray.push( new IrrigationSystemPlatformAccessory(this.api, this, device) );
this.queueMinSize += 5;
break;
case Accessory.Valve:
if (!(device.valveParentIrrigationSystem)){
this.accessoriesArray.push( new ValvePlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 5;
break;
case Accessory.Fan:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new FanPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 3;
break;
case Accessory.FilterMaintenance:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new FilterMaintenancePlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 2;
break;
case Accessory.Outlet:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new OutletPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.Other:
this.accessoriesArray.push( new OtherPlatformAccessory(this.api, this, device) );
this.queueMinSize += 1;
break;
case Accessory.LightSensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new LightSensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.MotionSensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new MotionSensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.ContactSensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new ContactSensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.SmokeSensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new SmokeSensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.TemperatureSensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new TemperatureSensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.HumiditySensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new HumiditySensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.CarbonDioxideSensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new CarbonDioxideSensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 3;
break;
case Accessory.AirQualitySensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new AirQualitySensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
case Accessory.LeakSensor:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new LeakSensorPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 2;
break;
case Accessory.Watchdog:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new WatchdogPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
default:
if (!(device.parentAccessory)) {
this.accessoriesArray.push( new SwitchPlatformAccessory(this.api, this, device) );
}
this.queueMinSize += 1;
break;
}
}
}
if (this.queueMinSize > this.queueSize) {
this.log.warn('Queue size is to small! Minimum size for all accessories and sensors is:', this.queueMinSize);
}
this.startUpdateTimer();
}
accessories(callback: (foundAccessories: AccessoryPlugin[]) => void): void {
callback(this.accessoriesArray);
}
sendQueueItems() {
if (this.queue.count() > 0) {
// for logging Queue Size: add in Platform Main Configuration Parameters "debugMsgLogQueueSize": 1
if (this.config.debugMsgLogQueueSize == true) {
this.log.info('Queue size: ', this.queue.count());
}
// ### Timer OFF ####
this.stopUpdateTimer();
// ##################
const item: any = this.queue.dequeue();
if (item instanceof QueueSendItem) {
if (item.pushButton == 1) {
this.logo.WriteLogo(item.address, 1);
const pbItem: QueueSendItem = new QueueSendItem(item.address, 0, 0);
this.queue.bequeue(pbItem);
} else {
this.logo.WriteLogo(item.address, item.value);
}
} else {
this.logo.ReadLogo(item.address, item.callBack);
}
// ### Timer ON ####
this.startUpdateTimer();
// #################
}
}
isAnalogLogoAddress(addr: string): boolean {
return this.logo.isAnalogLogoAddress(addr);
}
startUpdateTimer() {
this.updateTimer = setInterval(() => {
this.sendQueueItems();
}, this.queueInterval );
}
stopUpdateTimer() {
clearInterval(this.updateTimer);
this.updateTimer = 0;
}
}
// https://developers.homebridge.io/#/config-schema#enabling-support-for-your-plugin