UNPKG

homebridge-enphase-envoy

Version:

Homebridge plugin for Photovoltaic Energy System manufactured by Enphase.

938 lines (861 loc) • 461 kB
import { promises as fsPromises } from 'fs'; import axios from 'axios'; import { Agent } from 'https'; import { XMLParser, XMLBuilder, XMLValidator } from 'fast-xml-parser'; import EventEmitter from 'events'; import RestFul from './restful.js'; import Mqtt from './mqtt.js'; import EnvoyToken from './envoytoken.js'; import DigestAuth from './digestauth.js'; import PasswdCalc from './passwdcalc.js'; import ImpulseGenerator from './impulsegenerator.js'; import { ApiUrls, PartNumbers, Authorization, ApiCodes, LedStatus } from './constants.js'; let Accessory, Characteristic, Service, Categories, AccessoryUUID; class EnvoyDevice extends EventEmitter { constructor(api, deviceName, host, displayType, envoyFirmware7xxTokenGenerationMode, envoyPasswd, envoyToken, envoyTokenInstaller, enlightenUser, enlightenPasswd, envoyIdFile, envoyTokenFile, device) { super(); Accessory = api.platformAccessory; Characteristic = api.hap.Characteristic; Service = api.hap.Service; Categories = api.hap.Categories; AccessoryUUID = api.hap.uuid; //device configuration this.name = deviceName; this.host = host; this.displayType = displayType; this.envoyFirmware7xxTokenGenerationMode = envoyFirmware7xxTokenGenerationMode; this.envoyPasswd = envoyPasswd; this.enlightenUser = enlightenUser; this.enlightenPassword = enlightenPasswd; this.envoyToken = envoyToken; this.envoyTokenInstaller = envoyTokenInstaller; this.productionStateControl = device.productionStateControl || {}; this.productionStateSensor = device.productionStateSensor || {}; this.plcLevelControl = device.plcLevelControl || {}; this.powerProductionSummary = device.powerProductionSummary || 1; this.powerProductionStateSensor = device.powerProductionStateSensor || {}; this.powerProductionLevelSensors = device.powerProductionLevelSensors || []; this.energyProductionStateSensor = device.energyProductionStateSensor || {}; this.energyProductionLevelSensors = device.energyProductionLevelSensors || []; this.energyProductionLifetimeOffset = device.energyProductionLifetimeOffset || 0; this.powerConsumptionTotalStateSensor = device.powerConsumptionTotalStateSensor || {}; this.powerConsumptionTotalLevelSensors = device.powerConsumptionTotalLevelSensors || []; this.energyConsumptionTotalStateSensor = device.energyConsumptionTotalStateSensor || {}; this.energyConsumptionTotalLevelSensors = device.energyConsumptionTotalLevelSensors || []; this.energyConsumptionTotalLifetimeOffset = device.energyConsumptionTotalLifetimeOffset || 0; this.powerConsumptionNetStateSensor = device.powerConsumptionNetStateSensor || {}; this.powerConsumptionNetLevelSensors = device.powerConsumptionNetLevelSensors || []; this.energyConsumptionNetStateSensor = device.energyConsumptionNetStateSensor || {}; this.energyConsumptionNetLevelSensors = device.energyConsumptionNetLevelSensors || []; this.energyConsumptionNetLifetimeOffset = device.energyConsumptionNetLifetimeOffset || 0; //qRelay this.qRelayStateSensor = device.qRelayStateSensor || {}; //ac battery this.acBatterieName = device.acBatterieName || 'AC Batterie'; this.acBatterieBackupLevelSummaryAccessory = device.acBatterieBackupLevelSummaryAccessory || {}; this.acBatterieBackupLevelAccessory = device.acBatterieBackupLevelAccessory || {}; //enpower this.enpowerDryContactsControl = envoyFirmware7xxTokenGenerationMode > 0 ? device.enpowerDryContactsControl || false : false; this.enpowerDryContactsSensor = envoyFirmware7xxTokenGenerationMode > 0 ? device.enpowerDryContactsSensor || false : false; this.enpowerGridStateControl = envoyFirmware7xxTokenGenerationMode > 0 ? device.enpowerGridStateControl || {} : {}; this.enpowerGridStateSensor = envoyFirmware7xxTokenGenerationMode > 0 ? device.enpowerGridStateSensor || {} : {}; this.enpowerGridModeSensors = envoyFirmware7xxTokenGenerationMode > 0 ? device.enpowerGridModeSensors || [] : []; //encharge this.enchargeName = device.enchargeName || 'Encharge'; this.enchargeBackupLevelSummaryAccessory = envoyFirmware7xxTokenGenerationMode > 0 ? device.enchargeBackupLevelSummaryAccessory || {} : {}; this.enchargeBackupLevelAccessory = envoyFirmware7xxTokenGenerationMode > 0 ? device.enchargeBackupLevelAccessory || {} : {}; this.enchargeStateSensor = envoyFirmware7xxTokenGenerationMode > 0 ? device.enchargeStateSensor || {} : {}; this.enchargeProfileControls = envoyFirmware7xxTokenGenerationMode > 0 ? device.enchargeProfileControls || [] : []; this.enchargeProfileSensors = envoyFirmware7xxTokenGenerationMode > 0 ? device.enchargeProfileSensors || [] : []; this.enchargeGridStateSensor = envoyFirmware7xxTokenGenerationMode > 0 ? device.enchargeGridStateSensor || {} : {}; this.enchargeGridModeSensors = envoyFirmware7xxTokenGenerationMode > 0 ? device.enchargeGridModeSensors || [] : []; this.enchargeBackupLevelSensors = envoyFirmware7xxTokenGenerationMode > 0 ? device.enchargeBackupLevelSensors || [] : []; //solar this.solarGridStateSensor = envoyFirmware7xxTokenGenerationMode > 0 ? device.solarGridStateSensor || {} : {}; this.solarGridModeSensors = envoyFirmware7xxTokenGenerationMode > 0 ? device.solarGridModeSensors || [] : []; //generator this.generatorStateControl = envoyFirmware7xxTokenGenerationMode > 0 ? device.generatorStateControl || {} : {}; this.generatorStateSensor = envoyFirmware7xxTokenGenerationMode > 0 ? device.generatorStateSensor || {} : {}; this.generatorModeContols = envoyFirmware7xxTokenGenerationMode > 0 ? device.generatorModeControls || [] : []; this.generatorModeSensors = envoyFirmware7xxTokenGenerationMode > 0 ? device.generatorModeSensors || [] : []; //data refresh this.dataRefreshControl = device.dataRefreshControl || {}; this.dataRefreshSensor = device.dataRefreshSensor || {}; this.metersDataRefreshTime = device.metersDataRefreshTime * 1000 || 5000; this.productionDataRefreshTime = device.productionDataRefreshTime * 1000 || 10000; this.liveDataRefreshTime = device.liveDataRefreshTime * 1000 || 3000; this.ensembleDataRefreshTime = device.ensembleDataRefreshTime * 1000 || 15000; //log this.enableDebugMode = device.enableDebugMode || false; this.disableLogInfo = device.disableLogInfo || false; this.disableLogDeviceInfo = device.disableLogDeviceInfo || false; //external integrations this.restFul = device.restFul ?? {}; this.restFulConnected = false; this.mqtt = device.mqtt ?? {}; this.mqttConnected = false; //system const systemAccessoryDisplayType = this.displayType ?? 0; if (systemAccessoryDisplayType > 0) { const tile = {}; tile.serviceType = ['', Service.Lightbulb, Service.Fan, Service.HumiditySensor, Service.CarbonMonoxideSensor][systemAccessoryDisplayType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.StatusActive, Characteristic.CarbonMonoxideDetected][systemAccessoryDisplayType]; tile.characteristicType1 = ['', Characteristic.Brightness, Characteristic.RotationSpeed, Characteristic.CurrentRelativeHumidity, Characteristic.CarbonMonoxideLevel][systemAccessoryDisplayType]; tile.state = false; tile.level = 0; this.systemAccessoryActive = tile; }; //production state control const productionStateControlDisplayType = this.productionStateControl.displayType ?? 0; if (productionStateControlDisplayType > 0) { const tile = {}; tile.name = this.productionStateControl.name || 'Production State Control'; tile.namePrefix = this.productionStateControl.namePrefix || false; tile.serviceType = ['', Service.Switch, Service.Outlet, Service.Lightbulb][productionStateControlDisplayType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.On][productionStateControlDisplayType]; tile.state = false; this.productionStateActiveControl = tile; }; //production state sensor const productionStateSensorDisplayType = this.productionStateSensor.displayType ?? 0; if (productionStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.productionStateSensor.name || 'Production State Sensor'; sensor.namePrefix = this.productionStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][productionStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][productionStateSensorDisplayType]; sensor.state = false; this.productionStateActiveSensor = sensor; }; //plc level control const plcLevelControlDisplayType = this.plcLevelControl.displayType ?? 0; if (plcLevelControlDisplayType > 0) { const tile = {}; tile.name = this.plcLevelControl.name || 'PLC Level Refresh Control'; tile.namePrefix = this.plcLevelControl.namePrefix || false; tile.serviceType = ['', Service.Switch, Service.Outlet, Service.Lightbulb][plcLevelControlDisplayType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.On][plcLevelControlDisplayType]; tile.state = false; this.plcLevelActiveControl = tile; } //data refresh control const dataRefreshControlDisplayType = this.dataRefreshControl.displayType ?? 0; if (dataRefreshControlDisplayType > 0) { const tile = {}; tile.name = this.dataRefreshControl.name || 'Data Refresh Control'; tile.namePrefix = this.dataRefreshControl.namePrefix || false; tile.serviceType = ['', Service.Switch, Service.Outlet, Service.Lightbulb][dataRefreshControlDisplayType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.On][dataRefreshControlDisplayType]; tile.state = false; this.dataRefreshActiveControl = tile; }; //data refresh sensor const dataRefreshSensorDisplayType = this.dataRefreshSensor.displayType ?? 0; if (dataRefreshSensorDisplayType > 0) { const sensor = {}; sensor.name = this.dataRefreshSensor.name || 'Data Refresh Sensor'; sensor.namePrefix = this.dataRefreshSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][dataRefreshSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][dataRefreshSensorDisplayType]; sensor.state = false; this.dataRefreshActiveSensor = sensor; }; //power production level sensors this.powerProductionLevelActiveSensors = []; for (const sensor of this.powerProductionLevelSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Power Production Level Sensor'; sensor.compareMode = sensor.compareMode ?? 0; sensor.powerLevel = sensor.powerLevel ?? 0; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.powerProductionLevelActiveSensors.push(sensor); } this.powerProductionLevelActiveSensorsCount = this.powerProductionLevelActiveSensors.length || 0; //power production state sensor const powerProductionStateSensorDisplayType = this.powerProductionStateSensor.displayType ?? 0; if (powerProductionStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.powerProductionStateSensor.name || 'Power Production State Sensor'; sensor.namePrefix = this.powerProductionStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][powerProductionStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][powerProductionStateSensorDisplayType]; sensor.state = false; this.powerProductionStateActiveSensor = sensor; }; //energy production state sensor const energyProductionStateSensorDisplayType = this.energyProductionStateSensor.displayType ?? 0; if (energyProductionStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.energyProductionStateSensor.name || 'Energy Production State Sensor'; sensor.namePrefix = this.energyProductionStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][energyProductionStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][energyProductionStateSensorDisplayType]; sensor.state = false; this.energyProductionStateActiveSensor = sensor; }; this.energyProductionLevelActiveSensors = []; for (const sensor of this.energyProductionLevelSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Energy Production Levele Sensor'; sensor.compareMode = sensor.compareMode ?? 0; sensor.energyLevel = sensor.energyLevel ?? 0; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.energyProductionLevelActiveSensors.push(sensor); } this.energyProductionLevelActiveSensorsCount = this.energyProductionLevelActiveSensors.length || 0; //power consumption total state sensor const powerConsumptionTotalStateSensorDisplayType = this.powerConsumptionTotalStateSensor.displayType ?? 0; if (powerConsumptionTotalStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.powerConsumptionTotalStateSensor.name || 'Power Consumption Total State Sensor'; sensor.namePrefix = this.powerConsumptionTotalStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][powerConsumptionTotalStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][powerConsumptionTotalStateSensorDisplayType]; sensor.state = false; this.powerConsumptionTotalStateActiveSensor = sensor; }; this.powerConsumptionTotalLevelActiveSensors = []; for (const sensor of this.powerConsumptionTotalLevelSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Power Consumption Total Level Sensor'; sensor.compareMode = sensor.compareMode ?? 0; sensor.powerLevel = sensor.powerLevel ?? 0; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.powerConsumptionTotalLevelActiveSensors.push(sensor); } this.powerConsumptionTotalLevelActiveSensorsCount = this.powerConsumptionTotalLevelActiveSensors.length || 0; //energy consumption total state sensor const energyConsumptionTotalStateSensorDisplayType = this.energyConsumptionTotalStateSensor.displayType ?? 0; if (energyConsumptionTotalStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.energyConsumptionTotalStateSensor.name || 'Energy Consumption Total State Sensor'; sensor.namePrefix = this.energyConsumptionTotalStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][energyConsumptionTotalStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][energyConsumptionTotalStateSensorDisplayType]; sensor.state = false; this.energyConsumptionTotalStateActiveSensor = sensor; }; this.energyConsumptionTotalLevelActiveSensors = []; for (const sensor of this.energyConsumptionTotalLevelSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Energy Consumption Total Level Sensor'; sensor.compareMode = sensor.compareMode ?? 0; sensor.energyLevel = sensor.energyLevel ?? 0; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.energyConsumptionTotalLevelActiveSensors.push(sensor); } this.energyConsumptionTotalLevelActiveSensorsCount = this.energyConsumptionTotalLevelActiveSensors.length || 0; //power consumption net state sensor const powerConsumptionNetStateSensorDisplayType = this.powerConsumptionNetStateSensor.displayType ?? 0; if (powerConsumptionNetStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.powerConsumptionNetStateSensor.name || 'Power Consumption Net State Sensor'; sensor.namePrefix = this.powerConsumptionNetStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][powerConsumptionNetStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][powerConsumptionNetStateSensorDisplayType]; sensor.state = false; this.powerConsumptionNetStateActiveSensor = sensor; }; this.powerConsumptionNetLevelActiveSensors = []; for (const sensor of this.powerConsumptionNetLevelSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Power Consumption Net Level Sensor'; sensor.compareMode = sensor.compareMode ?? 0; sensor.powerLevel = sensor.powerLevel ?? 0; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.powerConsumptionNetLevelActiveSensors.push(sensor); } this.powerConsumptionNetLevelActiveSensorsCount = this.powerConsumptionNetLevelActiveSensors.length || 0; //energy consumption net state sensor const energyConsumptionNetStateSensorDisplayType = this.energyConsumptionNetStateSensor.displayType ?? 0; if (energyConsumptionNetStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.energyConsumptionNetStateSensor.name || 'Energy Consumption Net State Sensor'; sensor.namePrefix = this.energyConsumptionNetStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][energyConsumptionNetStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][energyConsumptionNetStateSensorDisplayType]; sensor.state = false; this.energyConsumptionNetStateActiveSensor = sensor; }; this.energyConsumptionNetLevelActiveSensors = []; for (const sensor of this.energyConsumptionNetLevelSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; } sensor.name = sensor.name || 'Energy Consumption Net Level Sensor'; sensor.compareMode = sensor.compareMode ?? 0; sensor.energyLevel = sensor.energyLevel ?? 0; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.energyConsumptionNetLevelActiveSensors.push(sensor); } this.energyConsumptionNetLevelActiveSensorsCount = this.energyConsumptionNetLevelActiveSensors.length || 0; //qRelay const qRelayStateSensorDisplayType = this.qRelayStateSensor.displayType ?? 0; if (qRelayStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.qRelayStateSensor.name || 'State Sensor'; sensor.namePrefix = this.qRelayStateSensor.namePrefix || false; sensor.multiphase = this.qRelayStateSensor.multiphase || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][qRelayStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][qRelayStateSensorDisplayType]; sensor.state0 = false; sensor.state1 = false; sensor.state2 = false; sensor.state3 = false; this.qRelayStateActiveSensor = sensor; }; //ac battery const acBatterieBackupLevelSummaryAccessoryDisplayType = this.acBatterieBackupLevelSummaryAccessory.displayType ?? 0; if (acBatterieBackupLevelSummaryAccessoryDisplayType > 0) { const tile = {}; tile.namePrefix = this.acBatterieBackupLevelSummaryAccessory.namePrefix || false; tile.serviceType = ['', Service.Lightbulb, Service.Fan, Service.HumiditySensor, Service.CarbonMonoxideSensor, Service.Battery][acBatterieBackupLevelSummaryAccessoryDisplayType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.StatusActive, Characteristic.CarbonMonoxideDetected, Characteristic.StatusLowBattery][acBatterieBackupLevelSummaryAccessoryDisplayType]; tile.characteristicType1 = ['', Characteristic.Brightness, Characteristic.RotationSpeed, Characteristic.CurrentRelativeHumidity, Characteristic.CarbonMonoxideLevel, Characteristic.BatteryLevel][acBatterieBackupLevelSummaryAccessoryDisplayType]; tile.displayType = this.acBatterieBackupLevelSummaryAccessory.displayType; tile.minSoc = this.acBatterieBackupLevelSummaryAccessory.minSoc ?? 0; tile.state = false; tile.backupLevel = 0; this.acBatterieBackupLevelSummaryActiveAccessory = tile; }; const acBatterieBackupLevelAccessoryDisplayType = this.acBatterieBackupLevelAccessory.displayType ?? 0; if (acBatterieBackupLevelAccessoryDisplayType > 0) { const tile = {}; tile.namePrefix = this.acBatterieBackupLevelAccessory.namePrefix || false; tile.serviceType = ['', Service.Battery][acBatterieBackupLevelAccessoryDisplayType]; tile.characteristicType = ['', Characteristic.StatusLowBattery][acBatterieBackupLevelAccessoryDisplayType]; tile.characteristicType1 = ['', Characteristic.BatteryLevel][acBatterieBackupLevelAccessoryDisplayType]; tile.characteristicType2 = ['', Characteristic.ChargingState][acBatterieBackupLevelAccessoryDisplayType]; tile.displayType = this.acBatterieBackupLevelAccessory.displayType; tile.minSoc = this.acBatterieBackupLevelAccessory.minSoc ?? 0; this.acBatterieBackupLevelActiveAccessory = tile; }; //enpower const enpowerGridStateControlDisplaqyType = this.enpowerGridStateControl.displayType ?? 0; if (enpowerGridStateControlDisplaqyType > 0) { const tile = {}; tile.name = this.enpowerGridStateControl.name || 'Enpower Grid State Control'; tile.namePrefix = this.enpowerGridStateControl.namePrefix || false; tile.serviceType = ['', Service.Switch, Service.Outlet, Service.Lightbulb][enpowerGridStateControlDisplaqyType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.On][enpowerGridStateControlDisplaqyType]; tile.state = false; this.enpowerGridStateActiveControl = tile; }; const enpowerGridStateSensorDisplayType = this.enpowerGridStateSensor.displayType ?? 0; if (enpowerGridStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.enpowerGridStateSensor.name || 'Enpower Grid State Sensor'; sensor.namePrefix = this.enpowerGridStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][enpowerGridStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][enpowerGridStateSensorDisplayType]; sensor.state = false; this.enpowerGridStateActiveSensor = sensor; }; this.enpowerGridModeActiveSensors = []; for (const sensor of this.enpowerGridModeSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Enpower Grid Mode Sensor'; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.enpowerGridModeActiveSensors.push(sensor); } this.enpowerGridModeActiveSensorsCount = this.enpowerGridModeActiveSensors.length || 0; //encharge const enchargeBackupLevelSummaryAccessoryDisplayType = this.enchargeBackupLevelSummaryAccessory.displayType ?? 0; if (enchargeBackupLevelSummaryAccessoryDisplayType > 0) { const tile = {}; tile.namePrefix = this.enchargeBackupLevelSummaryAccessory.namePrefix || false; tile.serviceType = ['', Service.Lightbulb, Service.Fan, Service.HumiditySensor, Service.CarbonMonoxideSensor, Service.Battery][enchargeBackupLevelSummaryAccessoryDisplayType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.StatusActive, Characteristic.CarbonMonoxideDetected, Characteristic.StatusLowBattery][enchargeBackupLevelSummaryAccessoryDisplayType]; tile.characteristicType1 = ['', Characteristic.Brightness, Characteristic.RotationSpeed, Characteristic.CurrentRelativeHumidity, Characteristic.CarbonMonoxideLevel, Characteristic.BatteryLevel][enchargeBackupLevelSummaryAccessoryDisplayType]; tile.displayType = this.enchargeBackupLevelSummaryAccessory.displayType; tile.minSoc = this.enchargeBackupLevelSummaryAccessory.minSoc ?? 0; tile.state = false; tile.backupLevel = 0; this.enchargeBackupLevelSummaryActiveAccessory = tile; }; const enchargeBackupLevelAccessoryDisplayType = this.enchargeBackupLevelAccessory.displayType ?? 0; if (enchargeBackupLevelAccessoryDisplayType > 0) { const tile = {}; tile.namePrefix = this.enchargeBackupLevelAccessory.namePrefix || false; tile.serviceType = ['', Service.Battery][enchargeBackupLevelAccessoryDisplayType]; tile.characteristicType1 = ['', Characteristic.StatusLowBattery][enchargeBackupLevelAccessoryDisplayType]; tile.characteristicType = ['', Characteristic.BatteryLevel][enchargeBackupLevelAccessoryDisplayType]; tile.characteristicType2 = ['', Characteristic.ChargingState][enchargeBackupLevelAccessoryDisplayType]; tile.displayType = this.enchargeBackupLevelAccessory.displayType; tile.minSoc = this.enchargeBackupLevelAccessory.minSoc ?? 0; this.enchargeBackupLevelActiveAccessory = tile; }; const enchargeStateSensorDisplayType = this.enchargeStateSensor.displayType ?? 0; if (enchargeStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.enchargeStateSensor.name || 'State Sensor'; sensor.namePrefix = this.enchargeStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][enchargeStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][enchargeStateSensorDisplayType]; sensor.state = false; this.enchargeStateActiveSensor = sensor; }; this.enchargeProfileActiveControls = []; for (const tile of this.enchargeProfileControls) { const displayType = tile.displayType ?? 0; if (displayType === 0) { continue; } tile.name = tile.name || 'Echarge profile Control'; tile.serviceType = ['', Service.Lightbulb][displayType]; tile.characteristicType = ['', Characteristic.On][displayType]; tile.state = false; tile.previousState = null; this.enchargeProfileActiveControls.push(tile); } this.enchargeProfileActiveControlsCount = this.enchargeProfileActiveControls.length || 0; this.enchargeProfileActiveSensors = []; for (const sensor of this.enchargeProfileSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Profile Sensor'; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.enchargeProfileActiveSensors.push(sensor); } this.enchargeProfileActiveSensorsCount = this.enchargeProfileActiveSensors.length || 0; const enchargeGridStateSensorDisplayType = this.enchargeGridStateSensor.displayType ?? 0; if (enchargeGridStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.enchargeGridStateSensor.name || 'Grid State Sensor'; sensor.namePrefix = this.enchargeGridStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][enchargeGridStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][enchargeGridStateSensorDisplayType]; sensor.state = false; this.enchargeGridStateActiveSensor = sensor; }; this.enchargeGridModeActiveSensors = []; for (const sensor of this.enchargeGridModeSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Grid Mode Sensor'; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.enchargeGridModeActiveSensors.push(sensor); } this.enchargeGridModeActiveSensorsCount = this.enchargeGridModeActiveSensors.length || 0; this.enchargeBackupLevelActiveSensors = []; for (const sensor of this.enchargeBackupLevelSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; } sensor.name = sensor.name || 'Backup Level Sensor'; sensor.compareMode = sensor.compareMode ?? 0; sensor.backupLevel = sensor.backupLevel ?? 0; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.enchargeBackupLevelActiveSensors.push(sensor); } this.enchargeBackupLevelActiveSensorsCount = this.enchargeBackupLevelActiveSensors.length || 0; //solar const solarGridStateSensorDisplayType = this.solarGridStateSensor.displayType ?? 0; if (solarGridStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.solarGridStateSensor.name || 'Solar Grid State Sensor'; sensor.namePrefix = this.solarGridStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][solarGridStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][solarGridStateSensorDisplayType]; sensor.state = false; this.solarGridStateActiveSensor = sensor; }; this.solarGridModeActiveSensors = []; for (const sensor of this.solarGridModeSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Solar Grid Mode Sensor'; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.solarGridModeActiveSensors.push(sensor); } this.solarGridModeActiveSensorsCount = this.solarGridModeActiveSensors.length || 0; //generator const generatorStateControlDisplaqyType = this.generatorStateControl.displayType ?? 0; if (generatorStateControlDisplaqyType > 0) { const tile = {}; tile.name = this.generatorStateControl.name || 'Generator State Control'; tile.namePrefix = this.generatorStateControl.namePrefix || false; tile.serviceType = ['', Service.Switch, Service.Outlet, Service.Lightbulb][generatorStateControlDisplaqyType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.On][generatorStateControlDisplaqyType]; tile.state = false; this.generatorStateActiveControl = tile; }; const generatorStateSensorDisplayType = this.generatorStateSensor.displayType ?? 0; if (generatorStateSensorDisplayType > 0) { const sensor = {}; sensor.name = this.generatorStateSensor.name || 'Generator State Sensor'; sensor.namePrefix = this.generatorStateSensor.namePrefix || false; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][generatorStateSensorDisplayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][generatorStateSensorDisplayType]; sensor.state = false; this.generatorStateActiveSensor = sensor; }; this.generatorModeActiveControls = []; for (const tile of this.generatorModeContols) { const displayType = tile.displayType ?? 0; if (displayType === 0) { continue; }; tile.name = tile.name || 'Generator Mode Control'; tile.serviceType = ['', Service.Switch, Service.Outlet, Service.Lightbulb][displayType]; tile.characteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.On][displayType]; tile.state = false; tile.previousState = null; this.generatorModeActiveControls.push(tile); } this.generatorModeActiveControlsCount = this.generatorModeActiveControls.length || 0; this.generatorModeActiveSensors = []; for (const sensor of this.generatorModeSensors) { const displayType = sensor.displayType ?? 0; if (displayType === 0) { continue; }; sensor.name = sensor.name || 'Generator Mode Sensor'; sensor.serviceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType]; sensor.characteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType]; sensor.state = false; this.generatorModeActiveSensors.push(sensor); } this.generatorModeActiveSensorsCount = this.generatorModeActiveSensors.length || 0; //setup variables this.envoyIdFile = envoyIdFile; this.envoyTokenFile = envoyTokenFile; this.startPrepareAccessory = true; //url this.url = envoyFirmware7xxTokenGenerationMode > 0 ? `https://${this.host}` : `http://${this.host}`; //create axios instance this.axiosInstance = axios.create({ method: 'GET', baseURL: this.url, withCredentials: true, headers: { Accept: 'application/json' }, httpsAgent: new Agent({ keepAlive: false, rejectUnauthorized: false }), timeout: 25000 }); //supported functions this.feature = { info: { devId: '', envoyPasswd: '', installerPasswd: '', firmware: 500, firmware7xx: envoyFirmware7xxTokenGenerationMode > 0, jwtToken: { generation_time: 0, token: envoyToken, expires_at: 0, installer: this.envoyFirmware7xxTokenGenerationMode === 2 ? this.envoyTokenInstaller : false } }, home: { supported: false, networkInterfaces: { supported: false, installed: false, count: 0 }, wirelessConnections: { supported: false, installed: false, count: 0 }, }, inventory: { supported: false, pcus: { supported: false, installed: false, count: 0 }, qRelays: { supported: false, installed: false, count: 0 }, acBatteries: { supported: false, installed: false, count: 0 }, ensembles: { supported: false, installed: false, count: 0 } }, pcuStatus: { supported: false }, meters: { supported: false, installed: false, count: 0, production: { supported: false, enabled: false, voltageDivide: 1 }, consumption: { supported: false, enabled: false, voltageDivide: 1 }, acBatterie: { supported: false, enabled: false, voltageDivide: 1 } }, metersReading: { supported: false, installed: false, count: 0, channels: { supported: false, installed: false, count: 0 } }, production: { supported: false }, energy: { supported: false, production: { supported: false }, consumption: { supported: false } }, productionPdm: { supported: false }, energyPdm: { supported: false, production: { supported: false }, consumption: { supported: false } }, productionCt: { supported: false, production: { supported: false, pcu: { supported: false }, eim: { supported: false } }, consumption: { supported: false }, acBatterie: { supported: false } }, ensemble: { supported: false, installed: false, status: { supported: false } }, enpowers: { supported: false, installed: false, count: 0 }, encharges: { supported: false, installed: false, count: 0, settings: { supported: false, installed: false, } }, tariff: { supported: false }, dryContacts: { supported: false, installed: false, count: 0, settings: { supported: false, installed: false, count: 0 } }, generators: { supported: false, installed: false, count: 0, settings: { supported: false } }, liveData: { supported: false }, gridProfile: { supported: false }, plcLevel: { supported: false }, productionState: { supported: false }, backboneApp: { supported: false }, dataSampling: false, checkJwtTokenRunning: false, cookie: false, }; //pv object this.pv = { info: {}, home: {}, inventory: { pcus: [], qRelays: [], acBatteries: { devices: [] }, ensembles: [], }, meters: [], production: {}, energy: {}, productionPdm: {}, energyPdm: { production: {}, consumption: {} }, productionCt: { pcu: {}, production: {}, consumption: [], acBatterie: {} }, ensemble: { enpowers: { devices: [] }, encharges: { devices: [] }, counters: {}, secctrl: {}, relay: {}, tariff: {}, dryContacts: [], generator: {} }, liveData: {}, gridProfile: {}, productionState: false, plcLevelState: false, powerState: false, powerLevel: 0, productionPowerPeak: 0, consumptionTotalPowerPeak: 0, consumptionNetPowerPeak: 0 }; //create impulse generator this.impulseGenerator = new ImpulseGenerator(); this.impulseGenerator.on('updateHomeInventoryAndPcuStatus', async () => { try { const tokenValid = await this.checkJwtToken(); const updateHome = tokenValid && this.feature.home.supported ? await this.updateHome() : false; const updateInventory = tokenValid && this.feature.inventory.supported ? await this.updateInventory() : false; const updatePcuStatus = tokenValid && this.feature.pcuStatus.supported ? await this.updatePcuStatus() : false; } catch (error) { this.handleError(error); }; }).on('updateMeters', async () => { try { const tokenValid = await this.checkJwtToken(); const updateMeters = tokenValid && this.feature.meters.supported ? await this.updateMeters() : false; const updateMetersReading = tokenValid && this.feature.meters.installed && this.feature.metersReading.supported ? await this.updateMetersReading() : false; } catch (error) { this.handleError(error); }; }).on('updateProduction', async () => { try { const tokenValid = await this.checkJwtToken(); const updateProduction = tokenValid && this.feature.production.supported ? await this.updateProduction() : false; const updateProductionPdm = tokenValid && this.feature.productionPdm.supported ? await this.updateProductionPdm() : false; const updateEnergyPdm = tokenValid && this.feature.energyPdm.supported ? await this.updateEnergyPdm() : false; const updateProductionCt = (updateProduction || updateProductionPdm) && this.feature.productionCt.supported ? await this.updateProductionCt() : false; } catch (error) { this.handleError(error); }; }).on('updateEnsemble', async () => { try { const tokenValid = await this.checkJwtToken(); const updateEnsemble = tokenValid && this.feature.ensemble.supported ? await this.updateEnsembleInventory() : false; const updateEnsembleStatus = tokenValid && this.feature.ensemble.status.supported ? await this.updateEnsembleStatus() : false; const updateEnchargeSettings = tokenValid && this.feature.encharges.settings.supported ? await this.updateEnchargesSettings() : false; const updateTariffSettings = tokenValid && this.feature.tariff.supported ? await this.updateTariff() : false; const updateDryContacts = tokenValid && this.feature.dryContacts.supported ? await this.updateDryContacts() : false;