iobroker.zendure-solarflow 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/admin/build/index.css +1 -1
- package/admin/build/index.css.map +3 -3
- package/admin/build/index.js +811 -410
- package/admin/build/index.js.map +4 -4
- package/build/helpers/createCalculationStates.js +38 -0
- package/build/helpers/createCalculationStates.js.map +2 -2
- package/build/helpers/helpers.js +1 -1
- package/build/helpers/helpers.js.map +1 -1
- package/build/helpers/timeHelper.js.map +2 -2
- package/build/models/deviceModels/Hyper2000.js +12 -10
- package/build/models/deviceModels/Hyper2000.js.map +2 -2
- package/build/models/deviceModels/Sf2400Ac.js +11 -9
- package/build/models/deviceModels/Sf2400Ac.js.map +2 -2
- package/build/models/deviceModels/Sf800.js +11 -9
- package/build/models/deviceModels/Sf800.js.map +2 -2
- package/build/models/deviceModels/Sf800Pro.js +11 -9
- package/build/models/deviceModels/Sf800Pro.js.map +2 -2
- package/build/models/deviceModels/SfHub1200.js +12 -10
- package/build/models/deviceModels/SfHub1200.js.map +2 -2
- package/build/models/deviceModels/SfHub2000.js +12 -10
- package/build/models/deviceModels/SfHub2000.js.map +2 -2
- package/build/models/deviceModels/ZenHaDevice.js +36 -14
- package/build/models/deviceModels/ZenHaDevice.js.map +2 -2
- package/build/services/jobSchedule.js +6 -4
- package/build/services/jobSchedule.js.map +2 -2
- package/build/services/zenWebService.js +0 -1
- package/build/services/zenWebService.js.map +2 -2
- package/io-package.json +27 -27
- package/package.json +11 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/models/deviceModels/ZenHaDevice.ts"],
|
|
4
|
-
"sourcesContent": ["import { calculationStateKeys } from \"../../constants/constants\";\nimport { createCalculationStates } from \"../../helpers/createCalculationStates\";\nimport { toHoursAndMinutes } from \"../../helpers/timeHelper\";\nimport { ZendureSolarflow } from \"../../main\";\nimport {\n knownPackDataProperties,\n onSubscribeIotTopic,\n onSubscribeReportTopic,\n} from \"../../services/mqttSharedService\";\nimport { IDevicePack } from \"../IDevicePack\";\nimport { IPackData } from \"../IPackData\";\nimport { ISolarflowState } from \"../ISolarflowState\";\nimport { IZenHaDeviceDetails } from \"../IZenHaDeviceDetails\";\n\nexport class ZenHaDevice {\n public zenHaDeviceDetails?: IZenHaDeviceDetails;\n public adapter: ZendureSolarflow;\n\n public productKey: string;\n public deviceKey: string;\n public productName: string;\n public deviceName: string;\n public batteries: IDevicePack[] = [];\n\n public iotTopic: string = \"\";\n public functionTopic = \"\";\n\n public maxInputLimit: number = 0;\n public maxOutputLimit: number = 0;\n\n public states: ISolarflowState[] = [];\n public controlStates: ISolarflowState[] = [];\n\n public constructor(\n _adapter: ZendureSolarflow,\n _productKey: string,\n _deviceKey: string,\n _productName: string,\n _deviceName: string,\n _zenHaDeviceDetails?: IZenHaDeviceDetails\n ) {\n this.zenHaDeviceDetails = _zenHaDeviceDetails;\n this.adapter = _adapter;\n this.productKey = _productKey;\n this.deviceKey = _deviceKey;\n\n this.deviceName = _deviceName;\n this.productName = _productName;\n\n this.iotTopic = `iot/${_productKey}/${_deviceKey}/properties/write`;\n this.functionTopic = `iot/${_productKey}/${_deviceKey}/function/invoke`;\n\n // Create or update states\n this.createSolarFlowStates();\n\n // Subscribe to report topic (get telemetry)\n this.subscribeReportTopic();\n\n // Subscribe to Iot topic (push control values)\n this.subscribeIotTopic();\n\n // Get complete data from device after a timeout\n this.adapter.setTimeout(() => {\n this.triggerFullTelemetryUpdate();\n }, 5000);\n\n if (this.zenHaDeviceDetails?.online) {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n } else if (this.zenHaDeviceDetails?.online == false) {\n this.updateSolarFlowState(\"wifiState\", \"Disconnected\");\n }\n }\n\n private async createSolarFlowStates(): Promise<void> {\n const productKey = this.productKey.replace(\n this.adapter.FORBIDDEN_CHARS,\n \"\"\n );\n const deviceKey = this.deviceKey.replace(this.adapter.FORBIDDEN_CHARS, \"\");\n\n this.adapter.log.debug(\n `[createSolarFlowStates] Creating or updating SolarFlow states for ${this.productName} (${productKey}/${deviceKey}) and name '${this.deviceName}'.`\n );\n\n // Create device (e.g. the product type -> SolarFlow)\n await this.adapter?.extendObject(productKey, {\n type: \"device\",\n common: {\n name: {\n de: `${this.productName} (${productKey})`,\n en: `${this.productName} (${productKey})`,\n },\n },\n native: {},\n });\n\n // Create channel (e.g. the device specific key)\n await this.adapter?.extendObject(productKey + \".\" + deviceKey, {\n type: \"channel\",\n common: {\n name: {\n de: `${this.deviceName} (${deviceKey})`,\n en: `${this.deviceName} (${deviceKey})`,\n },\n },\n native: {},\n });\n\n // Create pack data folder\n await this.adapter?.extendObject(`${productKey}.${deviceKey}.packData`, {\n type: \"channel\",\n common: {\n name: {\n de: \"Batterie Packs\",\n en: \"Battery packs\",\n },\n },\n native: {},\n });\n\n // Create report states\n this.states.forEach(async (state: ISolarflowState) => {\n await this.adapter?.extendObject(\n `${productKey}.${deviceKey}.${state.title}`,\n {\n type: \"state\",\n common: {\n name: {\n de: state.nameDe,\n en: state.nameEn,\n },\n type: state.type,\n desc: state.title,\n role: state.role,\n read: true,\n write: false,\n unit: state.unit,\n states: state.states,\n },\n native: {},\n }\n );\n });\n\n // Create control folder\n await this.adapter?.extendObject(`${productKey}.${deviceKey}.control`, {\n type: \"channel\",\n common: {\n name: {\n de: \"Steuerung f\u00FCr Ger\u00E4t \" + deviceKey,\n en: \"Control for device \" + deviceKey,\n },\n },\n native: {},\n });\n\n this.controlStates.forEach(async (state: ISolarflowState) => {\n await this.adapter?.extendObject(\n `${productKey}.${deviceKey}.control.${state.title}`,\n {\n type: \"state\",\n common: {\n name: {\n de: state.nameDe,\n en: state.nameEn,\n },\n type: state.type,\n desc: state.title,\n role: state.role,\n read: true,\n write: true,\n unit: state.unit,\n states: state.states,\n },\n native: {},\n }\n );\n\n // Subscribe to states to respond to changes\n this.adapter?.subscribeStates(\n `${productKey}.${deviceKey}.control.${state.title}`\n );\n });\n\n if (this.adapter.config.useCalculation) {\n // Create calculations folder\n await this.adapter?.extendObject(\n `${productKey}.${deviceKey}.calculations`,\n {\n type: \"channel\",\n common: {\n name: {\n de: \"Berechnungen f\u00FCr Ger\u00E4t \" + deviceKey,\n en: \"Calculations for Device \" + deviceKey,\n },\n },\n native: {},\n }\n );\n\n await createCalculationStates(this.adapter, productKey, deviceKey);\n }\n }\n\n public subscribeReportTopic(): void {\n const reportTopic = `/${this.productKey}/${this.deviceKey}/#`;\n\n if (this.adapter) {\n this.adapter.log.debug(\n `[subscribeReportTopic] Subscribing to MQTT Topic: ${reportTopic}`\n );\n this.adapter.mqttClient?.subscribe(reportTopic, onSubscribeReportTopic);\n }\n }\n\n private subscribeIotTopic(): void {\n const iotTopic = `iot/${this.productKey}/${this.deviceKey}/#`;\n\n this.adapter?.log.debug(\n `[subscribeIotTopic] Subscribing to MQTT Topic: ${iotTopic}`\n );\n this.adapter?.mqttClient?.subscribe(iotTopic, (error) => {\n onSubscribeIotTopic(error, this.productKey, this.deviceKey);\n });\n }\n\n public setDeviceAutomationInOutLimit(limit: number): void {\n this.adapter?.log.error(\n `[setAcMode] Method setDeviceAutomationInOutLimit (set to ${limit}) not defined in base class!`\n );\n return;\n }\n\n public setAcMode(acMode: number): void {\n this.adapter?.log.error(\n `[setAcMode] Method setAcMode (set to ${acMode}) not defined in base class!`\n );\n return;\n }\n\n public setDcSwitch(dcSwitch: boolean): void {\n this.adapter?.log.error(\n `[setAcMode] Method setDcSwitch (set to ${dcSwitch}) not defined in base class!`\n );\n return;\n }\n\n public setAcSwitch(acSwitch: boolean): void {\n this.adapter?.log.error(\n `[setAcMode] Method setAcSwitch (set to ${acSwitch}) not defined in base class!`\n );\n return;\n }\n\n public setHubState(hubState: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n if (hubState == 0 || hubState == 1) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/write`;\n\n const socSetLimit = { properties: { hubState: hubState } };\n this.adapter.log.debug(\n `[setHubState] Setting Hub State for deviceKey ${this.deviceKey} to ${hubState}!`\n );\n this.adapter.mqttClient?.publish(topic, JSON.stringify(socSetLimit));\n } else {\n this.adapter.log.debug(`[setHubState] Hub state is not 0 or 1!`);\n }\n }\n }\n\n public setPassMode(passMode: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/write`;\n\n const setPassModeContent = { properties: { passMode: passMode } };\n this.adapter.log.debug(\n `[setPassMode] Set passMode for deviceKey ${this.deviceKey} to ${passMode}!`\n );\n this.adapter.mqttClient?.publish(\n topic,\n JSON.stringify(setPassModeContent)\n );\n }\n }\n\n public setAutoRecover(autoRecover: boolean): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/write`;\n\n const setAutoRecoverContent = {\n properties: { autoRecover: autoRecover ? 1 : 0 },\n };\n this.adapter.log.debug(\n `[setAutoRecover] Set autoRecover for deviceKey ${this.deviceKey} to ${autoRecover}!`\n );\n this.adapter.mqttClient?.publish(\n topic,\n JSON.stringify(setAutoRecoverContent)\n );\n }\n }\n\n /**\n * Will set the discharge limit (minSoc)\n * @param socSet the desired minimum soc\n * @returns void\n */\n public setDischargeLimit(minSoc: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n if (minSoc >= 0 && minSoc <= 50) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/write`;\n\n const socSetLimit = { properties: { minSoc: minSoc * 10 } };\n this.adapter.log.debug(\n `[setDischargeLimit] Setting Discharge Limit for device key ${this.deviceKey} to ${minSoc}!`\n );\n this.adapter.mqttClient?.publish(topic, JSON.stringify(socSetLimit));\n } else {\n this.adapter.log.debug(\n `[setDischargeLimit] Discharge limit is not in range 0<>50!`\n );\n }\n }\n }\n\n /**\n * Will set the maximum charge limit\n * @param socSet the desired max SOC\n * @returns void\n */\n public setChargeLimit(socSet: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n if (socSet >= 40 && socSet <= 100) {\n const socSetLimit = { properties: { socSet: socSet * 10 } };\n this.adapter.log.debug(\n `[setChargeLimit] Setting ChargeLimit for device key ${this.deviceKey} to ${socSet}!`\n );\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(socSetLimit)\n );\n } else {\n this.adapter.log.debug(\n `[setChargeLimit] Charge limit is not in range 40<>100!`\n );\n }\n }\n }\n\n /**\n * Will set the 'energy plan'\n * @param autoModel autoModel value, like 8 for smart matching\n * @returns void\n */\n public setAutoModel(autoModel: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n let setAutoModelContent: any = { properties: { autoModel: autoModel } };\n\n switch (autoModel) {\n case 8: {\n // Smart Matching Modus\n setAutoModelContent = {\n properties: {\n autoModelProgram: 1,\n autoModelValue: {\n chargingType: 0,\n chargingPower: 0,\n outPower: 0,\n },\n msgType: 1,\n autoModel: 8,\n },\n };\n break;\n }\n case 9: // Smart CT Modus\n setAutoModelContent = {\n properties: {\n autoModelProgram: 2,\n autoModelValue: {\n chargingType: 3,\n chargingPower: 0,\n outPower: 0,\n },\n msgType: 1,\n autoModel: 9,\n },\n };\n break;\n }\n\n this.adapter.log.debug(\n `[setAutoModel] Setting autoModel for device key ${this.deviceKey} to ${autoModel}!`\n );\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(setAutoModelContent)\n );\n }\n }\n\n public async setOutputLimit(limit: number): Promise<void> {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n // Check if autoModel is set to 0 (Nothing) or 8 (Smart Matching)\n const autoModel = (\n await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".autoModel\"\n )\n )?.val;\n\n if (autoModel != 0) {\n this.adapter.log.warn(\n \"Operation mode (autoModel) is not set to '0', we can't set the output limit!\"\n );\n return;\n }\n\n if (limit) {\n limit = Math.round(limit);\n } else {\n limit = 0;\n }\n\n // Limit to the device max limit\n if (limit > this.maxOutputLimit) {\n limit = this.maxOutputLimit;\n }\n\n if (\n limit < 100 &&\n limit != 90 &&\n limit != 60 &&\n limit != 30 &&\n limit != 0 &&\n (this.productKey == \"73bktv\" || this.productKey == \"a8yh63\")\n ) {\n // NUR Solarflow HUB: Das Limit kann unter 100 nur in 30er Schritten gesetzt werden, dH. 30/60/90/100, wir rechnen das also um\n if (limit < 100 && limit > 90) {\n limit = 90;\n } else if (limit > 60 && limit < 90) {\n limit = 60;\n } else if (limit > 30 && limit < 60) {\n limit = 30;\n } else if (limit < 30) {\n limit = 30;\n }\n }\n\n if (this.adapter.config.useLowVoltageBlock) {\n const lowVoltageBlockState = await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".control.lowVoltageBlock\"\n );\n if (\n lowVoltageBlockState &&\n lowVoltageBlockState.val &&\n lowVoltageBlockState.val == true\n ) {\n limit = 0;\n }\n\n const fullChargeNeeded = await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".control.fullChargeNeeded\"\n );\n\n if (\n fullChargeNeeded &&\n fullChargeNeeded.val &&\n fullChargeNeeded.val == true\n ) {\n limit = 0;\n }\n }\n\n const currentLimit = (\n await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".outputLimit\"\n )\n )?.val;\n\n if (currentLimit != null && currentLimit != undefined) {\n if (currentLimit != limit) {\n const outputlimit = { properties: { outputLimit: limit } };\n\n this.adapter.msgCounter += 1;\n\n const timestamp = new Date();\n timestamp.setMilliseconds(0);\n\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(outputlimit)\n );\n }\n }\n }\n }\n\n public setInputLimit(limit: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n // Limit has always to be positive!\n limit = Math.abs(limit);\n\n if (limit) {\n limit = Math.round(limit);\n } else {\n limit = 0;\n }\n\n if (limit < 0) {\n limit = 0;\n } else if (limit > 0 && limit <= 30) {\n limit = 30;\n } else if (limit > this.maxInputLimit) {\n limit = this.maxInputLimit;\n }\n\n if (this.productKey.includes(\"8bm93h\")) {\n // Das Limit kann beim ACE nur in 100er Schritten gesetzt werden\n limit = Math.ceil(limit / 100) * 100;\n }\n\n const inputLimitContent = { properties: { inputLimit: limit } };\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(inputLimitContent)\n );\n }\n }\n\n public setSmartMode(smartModeOn: boolean): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const setSmartModeContent = {\n properties: { smartMode: smartModeOn ? 1 : 0 },\n };\n\n this.adapter.log.debug(\n `[setBuzzer] Setting Smart Mode for device key ${this.deviceKey} to ${smartModeOn}!`\n );\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(setSmartModeContent)\n );\n }\n }\n\n public setBuzzerSwitch(buzzerOn: boolean): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const setBuzzerSwitchContent = {\n properties: { buzzerSwitch: buzzerOn ? 1 : 0 },\n };\n this.adapter.log.debug(\n `[setBuzzer] Setting Buzzer for device key ${this.deviceKey} to ${buzzerOn}!`\n );\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(setBuzzerSwitchContent)\n );\n }\n }\n\n public triggerFullTelemetryUpdate(): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/read`;\n\n const getAllContent = { properties: [\"getAll\"] };\n this.adapter.log.debug(\n `[triggerFullTelemetryUpdate] Triggering full telemetry update for device key ${this.deviceKey}!`\n );\n this.adapter.mqttClient?.publish(topic, JSON.stringify(getAllContent));\n }\n }\n\n public async updateSolarFlowState(\n state: string,\n val: number | string | boolean\n ): Promise<void> {\n const currentValue = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.${state}`\n );\n\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.${state}`,\n val,\n true\n );\n\n if (currentValue?.val != val && state != \"wifiState\") {\n // Set lastUpdate for deviceKey if a value was changed!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n }\n\n public async updateSolarFlowControlState(\n state: string,\n val: number | string | boolean\n ): Promise<void> {\n // First check if state exist\n const stateExist = await this.adapter?.objectExists(\n `${this.productKey}.${this.deviceKey}.control.${state}`\n );\n\n // Update the control state\n if (stateExist) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.control.${state}`,\n val,\n true\n );\n }\n }\n\n addOrUpdatePackData = async (\n packData: IPackData[],\n isSolarFlow: boolean\n ): Promise<void> => {\n if (this.adapter && this.productKey && this.deviceKey) {\n await packData.forEach(async (x) => {\n // Process data only with a serial id!\n if (x.sn && this.adapter) {\n // Create channel (e.g. the device specific key)\n // We can determine the type of the battery by the SN number.\n let batType = \"\";\n if (this.productKey == \"yWF7hV\") {\n batType = \"AIO2400\";\n } else if (x.sn.startsWith(\"A\")) {\n batType = \"AB1000\";\n } else if (x.sn.startsWith(\"B\")) {\n batType = \"AB1000S\";\n } else if (x.sn.startsWith(\"C\")) {\n if (x.sn[3] == \"F\") {\n batType = \"AB2000S\";\n } else {\n batType = \"AB2000\";\n }\n } else if (x.sn.startsWith(\"F\")) {\n batType = \"AB3000X\";\n }\n\n // Check if is in Pack2device list\n if (!this.batteries.some((y) => y.packSn == x.sn)) {\n this.batteries.push({\n packSn: x.sn,\n type: batType,\n });\n\n this.adapter.log.debug(\n `[addOrUpdatePackData] Added battery ${batType} with SN ${x.sn} on deviceKey ${this.deviceKey} to batteries array!`\n );\n }\n\n // create a state for the serial id\n const key = (\n this.productKey +\n \".\" +\n this.deviceKey +\n \".packData.\" +\n x.sn\n ).replace(this.adapter.FORBIDDEN_CHARS, \"\");\n\n await this.adapter?.extendObject(key, {\n type: \"channel\",\n common: {\n name: {\n de: batType,\n en: batType,\n },\n },\n native: {},\n });\n\n await this.adapter?.extendObject(key + \".model\", {\n type: \"state\",\n common: {\n name: {\n de: \"Batterietyp\",\n en: \"Battery type\",\n },\n type: \"string\",\n desc: \"model\",\n role: \"value\",\n read: true,\n write: false,\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".model\", batType, true);\n\n await this.adapter?.extendObject(key + \".sn\", {\n type: \"state\",\n common: {\n name: {\n de: \"Seriennummer\",\n en: \"Serial id\",\n },\n type: \"string\",\n desc: \"Serial ID\",\n role: \"value\",\n read: true,\n write: false,\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".sn\", x.sn, true);\n\n if (x.socLevel) {\n // State f\u00FCr socLevel\n await this.adapter?.extendObject(key + \".socLevel\", {\n type: \"state\",\n common: {\n name: {\n de: \"SOC der Batterie\",\n en: \"soc of battery\",\n },\n type: \"number\",\n desc: \"SOC Level\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"%\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".socLevel\", x.socLevel, true);\n }\n\n if (x.maxTemp) {\n const maxTempCelsius = x.maxTemp / 10 - 273.15;\n const maxTempState = await this.adapter?.getStateAsync(\n key + \".maxTemp\"\n );\n\n // Check if Value exist and changed, if so update lastUpdate!\n if (\n maxTempState &&\n maxTempState.val &&\n maxTempCelsius != maxTempState.val\n ) {\n // Value exist and value changed, update last update!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n\n // State f\u00FCr maxTemp\n await this.adapter?.extendObject(key + \".maxTemp\", {\n type: \"state\",\n common: {\n name: {\n de: \"Max. Temperatur der Batterie\",\n en: \"max temp. of battery\",\n },\n type: \"number\",\n desc: \"Max. Temp\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"\u00B0C\",\n },\n native: {},\n });\n\n // Convert Kelvin to Celsius\n await this.adapter?.setState(\n key + \".maxTemp\",\n maxTempCelsius,\n true\n );\n }\n\n if (x.minVol) {\n const minVol = x.minVol / 100;\n const minVolState = await this.adapter?.getStateAsync(\n key + \".minVol\"\n );\n\n // Check if Value exist and changed, if so update lastUpdate!\n if (minVolState && minVolState.val && minVol != minVolState.val) {\n // Value exist and value changed, update last update!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n\n await this.adapter?.extendObject(key + \".minVol\", {\n type: \"state\",\n common: {\n name: \"minVol\",\n type: \"number\",\n desc: \"minVol\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"V\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".minVol\", minVol, true);\n }\n\n if (x.batcur) {\n await this.adapter?.extendObject(key + \".batcur\", {\n type: \"state\",\n common: {\n name: \"batcur\",\n type: \"number\",\n desc: \"batcur\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"A\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".batcur\", x.batcur / 10, true);\n }\n\n // Check if Value exist and changed, if so update lastUpdate!\n if (x.maxVol) {\n const maxVol = x.maxVol / 100;\n const maxVolState = await this.adapter?.getStateAsync(\n key + \".maxVol\"\n );\n\n if (maxVolState && maxVolState.val && maxVol != maxVolState.val) {\n // Value exist and value changed, update last update!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n\n await this.adapter?.extendObject(key + \".maxVol\", {\n type: \"state\",\n common: {\n name: \"maxVol\",\n type: \"number\",\n desc: \"maxVol\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"V\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".maxVol\", maxVol, true);\n }\n\n // Check if Value exist and changed, if so update lastUpdate!\n if (x.totalVol) {\n const totalVol = x.totalVol / 100;\n\n const totalVolState = await this.adapter?.getStateAsync(\n key + \".totalVol\"\n );\n\n if (\n totalVolState &&\n totalVolState.val &&\n totalVol != totalVolState.val\n ) {\n // Value exist and value changed, update last update!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n\n await this.adapter?.extendObject(key + \".totalVol\", {\n type: \"state\",\n common: {\n name: \"totalVol\",\n type: \"number\",\n desc: \"totalVol\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"V\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".totalVol\", totalVol, true);\n\n // Send Voltage to checkVoltage Method (only if is Solarflow device)\n if (isSolarFlow) {\n this.checkVoltage(totalVol);\n }\n }\n\n if (x.soh) {\n await this.adapter?.extendObject(key + \".soh\", {\n type: \"state\",\n common: {\n name: {\n de: \"Gesundheitszustand\",\n en: \"State of Health\",\n },\n type: \"number\",\n desc: \"State of Health\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"%\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".soh\", x.soh / 10, true);\n }\n\n if (x.power) {\n await this.adapter?.extendObject(key + \".power\", {\n type: \"state\",\n common: {\n name: {\n de: \"Energie\",\n en: \"Power\",\n },\n type: \"number\",\n desc: \"Power\",\n read: true,\n write: false,\n role: \"value.power\",\n unit: \"W\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".power\", x.power, true);\n }\n\n // Debug, send message if property is unknown!\n let found = false;\n\n Object.entries(x).forEach(([key, value]) => {\n knownPackDataProperties.forEach((property: string) => {\n if (property == key) {\n found = true;\n }\n });\n\n if (found) {\n //console.log(\n // `${productName?.val}: ${key} with value ${value} is a KNOWN Mqtt Prop!`\n //);\n } else {\n this.adapter?.log.debug(\n `[addOrUpdatePackData] ${key} with value ${value} is a UNKNOWN PackData Mqtt Property!`\n );\n }\n });\n }\n });\n }\n };\n\n public async checkVoltage(voltage: number): Promise<void> {\n if (voltage < 46.1) {\n if (this.adapter.config.useCalculation) {\n this.setSocToZero();\n }\n\n if (this.adapter.config.useLowVoltageBlock) {\n // Activate Low Voltage Block\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`,\n true,\n true\n );\n\n // Low Voltage Block activated, stop power input immediately\n const autoModel = (\n await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".autoModel\"\n )\n )?.val;\n if (autoModel == 8) {\n this.setDeviceAutomationInOutLimit(0);\n } else {\n this.setOutputLimit(0);\n }\n\n if (this.adapter.config.forceShutdownOnLowVoltage) {\n const currentSoc = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.electricLevel`\n );\n\n if (currentSoc && Number(currentSoc.val) > 50) {\n // We can't shut down the device. Full charge needed!\n if (this.adapter.config.fullChargeIfNeeded) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.control.fullChargeNeeded`,\n true,\n true\n );\n }\n } else {\n if (currentSoc && currentSoc.val) {\n this.setDischargeLimit(Number(currentSoc.val));\n }\n\n // Check if device setting is correct\n const hubState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.hubState`\n );\n\n if (!hubState || Number(hubState.val) != 1) {\n this.adapter.log.warn(\n `[checkVoltage] hubState is not set to 'Stop output and shut down', device will NOT go offline!`\n );\n }\n }\n }\n }\n } else if (voltage >= 47.5) {\n // Deactivate Low Voltage Block\n const lowVoltageBlock = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`\n );\n\n if (lowVoltageBlock && lowVoltageBlock.val == true) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`,\n false,\n true\n );\n\n if (\n this.adapter.config.useLowVoltageBlock &&\n this.adapter.config.forceShutdownOnLowVoltage\n ) {\n this.setDischargeLimit(\n this.adapter.config.dischargeLimit\n ? this.adapter.config.dischargeLimit\n : 5\n );\n }\n }\n }\n }\n\n /**\n * Calculates the energy for all items in 'calculationStateKeys'.\n *\n * @returns Promise<void>\n *\n * @beta\n */\n public calculateEnergy(): void {\n calculationStateKeys.forEach(async (stateKey) => {\n let stateNameEnergyWh = \"\";\n let stateNameEnergykWh = \"\";\n let stateNamePower = \"\";\n\n if (stateKey == \"pvPower1\") {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower1`;\n } else if (stateKey == \"pvPower2\") {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower2`;\n } else {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.${stateKey}Power`;\n }\n\n const currentPowerState =\n await this.adapter?.getStateAsync(stateNamePower);\n\n const currentEnergyState =\n await this.adapter?.getStateAsync(stateNameEnergyWh);\n\n if (currentEnergyState?.val == 0) {\n // Workaround, set Val to very low value to avoid Jump in data...\n await this.adapter?.setState(stateNameEnergyWh, 0.000001, true);\n } else if (\n currentEnergyState &&\n currentEnergyState.lc &&\n currentPowerState &&\n currentPowerState.val != undefined &&\n currentPowerState.val != null\n ) {\n // Timeframe = 30000ms, Job runs every 30 seconds...\n const timeFrame = 30000;\n\n // Calculate Energy value (Wh) from current power in the timeframe from last run...\n const addEnergyValue =\n (Number(currentPowerState.val) * timeFrame) / 3600000; // Wh\n\n /* // Use efficiency factor (used the one from Youtube Channel VoltAmpereLux - thanks!)\n const chargingFactor = 0.96; // Efficiency 96%\n const dischargingFactor = 1.08 - addEnergyValue / 10000; // Efficiency 92% - 98% (92% + Energy / 10000 = 600W -> +6%)\n\n // Calculate energy from efficiency factor if value for charging or discharging\n addEnergyValue =\n stateKey == \"outputPack\" && addEnergyValue > 0\n ? addEnergyValue * chargingFactor\n : addEnergyValue;\n addEnergyValue =\n stateKey == \"packInput\" && addEnergyValue > 0\n ? addEnergyValue * dischargingFactor\n : addEnergyValue; */\n\n let newEnergyValue = Number(currentEnergyState.val) + addEnergyValue;\n\n // Fix negative value\n if (newEnergyValue < 0) {\n newEnergyValue = 0;\n }\n\n await this.adapter?.setState(stateNameEnergyWh, newEnergyValue, true);\n await this.adapter?.setState(\n stateNameEnergykWh,\n Number((newEnergyValue / 1000).toFixed(2)),\n true\n );\n\n // SOC and energy in batteries\n if (\n (stateKey == \"outputPack\" || stateKey == \"packInput\") &&\n addEnergyValue > 0\n ) {\n await this.calculateSocAndEnergy(stateKey, addEnergyValue);\n } else {\n if (stateKey == \"outputPack\") {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainInputTime`,\n \"\",\n true\n );\n } else if (stateKey == \"packInput\") {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainOutTime`,\n \"\",\n true\n );\n }\n }\n } else if (currentPowerState && currentEnergyState) {\n await this.adapter?.setState(stateNameEnergyWh, 0, true);\n await this.adapter?.setState(stateNameEnergykWh, 0, true);\n }\n });\n }\n\n public calculateSocAndEnergy = async (\n stateKey: string,\n value: number\n ): Promise<void> => {\n this.adapter.log.debug(\n `[calculateSocAndEnergy] Calculating for: ${this.productKey}.${this.deviceKey} and stateKey ${stateKey}!`\n );\n\n let energyWhMax: number | undefined = undefined;\n\n const minSoc = (\n await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.minSoc`\n )\n )?.val;\n const currentSoc = (\n await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.electricLevel`\n )\n )?.val;\n\n if (currentSoc && minSoc && Number(currentSoc) < Number(minSoc)) {\n // Don't calculate if current SOC is lower then minimum\n this.adapter.log.debug(\n `[calculateSocAndEnergy] Don't calculate, currentSoc (${Number(currentSoc)}) is lower than minSoc (${Number(minSoc)})!`\n );\n\n return;\n }\n\n const currentEnergyState = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".calculations.energyWh\"\n );\n\n const currentEnergyMaxState = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".calculations.energyWhMax\"\n );\n\n const lowVoltageBlock = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".control.lowVoltageBlock\"\n );\n\n const currentMaxValue = Number(\n currentEnergyMaxState ? currentEnergyMaxState.val : 0\n );\n\n let currentEnergyWh = currentEnergyState?.val\n ? Number(currentEnergyState?.val)\n : 0;\n\n if (\n currentEnergyWh == null ||\n currentEnergyWh == undefined ||\n currentEnergyWh <= 0\n ) {\n currentEnergyWh = 0;\n }\n\n if (this.productKey == \"yWF7hV\") {\n // The device is an AIO 2400, so set maximum Wh to 2400!\n energyWhMax = 2400;\n } else {\n // Iterate over all batteries!\n for (let i = 0; i < this.batteries.length; i++) {\n if (this.batteries[i].type == \"AB1000\") {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 960;\n } else if (this.batteries[i].type == \"AB2000\") {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 1920;\n }\n }\n }\n\n // newValue is the current available energy in the batteries. If outputPack (charging) add value, if packInput (discharging) subtract value.\n let newEnergyWh =\n stateKey == \"outputPack\"\n ? currentEnergyWh + value\n : currentEnergyWh - value;\n\n // If greater than Max of batteries, set it to this value.\n if (\n stateKey == \"outputPack\" &&\n energyWhMax != undefined &&\n newEnergyWh > energyWhMax\n ) {\n newEnergyWh = energyWhMax;\n\n this.adapter.log.debug(\n `[calculateSocAndEnergy] newEnergyWh (${newEnergyWh}) is greater than energyWhMax (${energyWhMax}), don't extend value!`\n );\n }\n\n if (newEnergyWh > 0) {\n this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWh`,\n newEnergyWh,\n true\n );\n\n this.adapter.log.debug(\n `[calculateSocAndEnergy] set '${this.productKey}.${this.deviceKey}.calculations.energyWh' to ${newEnergyWh}!`\n );\n\n if (currentEnergyMaxState) {\n const soc = Number(((newEnergyWh / currentMaxValue) * 100).toFixed(1));\n\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.soc`,\n soc > 100.0 ? 100 : soc,\n true\n );\n\n if (newEnergyWh > currentMaxValue && !lowVoltageBlock?.val) {\n // Extend maxVal\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`,\n newEnergyWh,\n true\n );\n }\n\n const currentOutputPackPower = await this.adapter?.getStateAsync(\n `${this.productKey}.${this.deviceKey}.outputPackPower`\n );\n\n const currentPackInputPower = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".packInputPower\"\n );\n\n if (\n stateKey == \"outputPack\" &&\n currentOutputPackPower?.val != null &&\n currentOutputPackPower != undefined\n ) {\n // Charging, calculate remaining charging time\n const toCharge = currentMaxValue - newEnergyWh;\n\n const remainHoursAsDecimal =\n toCharge / Number(currentOutputPackPower.val);\n\n if (remainHoursAsDecimal < 48.0) {\n const remainFormatted = toHoursAndMinutes(\n Math.round(remainHoursAsDecimal * 60)\n );\n\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainInputTime`,\n remainFormatted,\n true\n );\n } else {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainInputTime`,\n \"\",\n true\n );\n }\n } else if (\n stateKey == \"packInput\" &&\n currentPackInputPower != null &&\n currentPackInputPower != undefined\n ) {\n // Discharging, calculate remaining discharge time\n const remainHoursAsDecimal =\n newEnergyWh / Number(currentPackInputPower.val);\n const remainFormatted = toHoursAndMinutes(\n Math.round(remainHoursAsDecimal * 60)\n );\n\n if (remainHoursAsDecimal < 48.0) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainOutTime`,\n remainFormatted,\n true\n );\n } else {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainOutTime`,\n \"\",\n true\n );\n }\n }\n }\n } else if (newEnergyWh <= 0 && stateKey == \"outputPack\") {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainInputTime`,\n \"\",\n true\n );\n } else if (newEnergyWh <= 0 && stateKey == \"packInput\") {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainOutTime`,\n \"\",\n true\n );\n\n // TEST: if SOC == 0, add newValue as positive to energyWhMax\n const newEnergyWhPositive = Math.abs(newEnergyWh);\n\n if (energyWhMax && currentMaxValue + newEnergyWhPositive <= energyWhMax) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`,\n currentMaxValue + newEnergyWhPositive,\n true\n );\n }\n }\n };\n\n public async setSocToZero(): Promise<void> {\n // Set SOC to 0\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.soc`,\n 0,\n true\n );\n\n // Calculate new Wh Max Value\n const energyWhState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.calculations.energyWh`\n );\n const energyWhMaxState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`\n );\n\n const newMax = Number(energyWhMaxState?.val) - Number(energyWhState?.val);\n\n // Set Max Energy to value minus current energy\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`,\n newMax,\n true\n );\n\n // Set Energy in Battery to 0\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWh`,\n 0,\n true\n );\n }\n\n public async setEnergyWhMax(): Promise<void> {\n const currentEnergyState = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".calculations.energyWh\"\n );\n\n if (currentEnergyState) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`,\n currentEnergyState?.val,\n true\n );\n }\n }\n\n public resetValuesForDevice(): void {\n calculationStateKeys.forEach(async (stateKey: string) => {\n let stateNameEnergyWh = \"\";\n let stateNameEnergykWh = \"\";\n\n if (stateKey == \"pvPower1\") {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodaykWh`;\n } else if (stateKey == \"pvPower2\") {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodaykWh`;\n } else {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\n }\n\n await this.adapter?.setState(stateNameEnergyWh, 0, true);\n await this.adapter?.setState(stateNameEnergykWh, 0, true);\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { createHash } from \"crypto\";\nimport { calculationStateKeys } from \"../../constants/constants\";\nimport { createCalculationStates } from \"../../helpers/createCalculationStates\";\nimport { toHoursAndMinutes } from \"../../helpers/timeHelper\";\nimport { ZendureSolarflow } from \"../../main\";\nimport {\n knownPackDataProperties,\n onSubscribeIotTopic,\n onSubscribeReportTopic,\n} from \"../../services/mqttSharedService\";\nimport { IDevicePack } from \"../IDevicePack\";\nimport { IPackData } from \"../IPackData\";\nimport { ISolarflowState } from \"../ISolarflowState\";\nimport { IZenHaDeviceDetails } from \"../IZenHaDeviceDetails\";\n\nexport class ZenHaDevice {\n public zenHaDeviceDetails?: IZenHaDeviceDetails;\n public adapter: ZendureSolarflow;\n\n public productKey: string;\n public deviceKey: string;\n public productName: string;\n public deviceName: string;\n public batteries: IDevicePack[] = [];\n\n public iotTopic: string = \"\";\n public functionTopic = \"\";\n public password: string = \"\";\n\n public maxInputLimit: number = 0;\n public maxOutputLimit: number = 0;\n\n public states: ISolarflowState[] = [];\n public controlStates: ISolarflowState[] = [];\n\n public constructor(\n _adapter: ZendureSolarflow,\n _productKey: string,\n _deviceKey: string,\n _productName: string,\n _deviceName: string,\n _zenHaDeviceDetails?: IZenHaDeviceDetails\n ) {\n this.zenHaDeviceDetails = _zenHaDeviceDetails;\n this.adapter = _adapter;\n this.productKey = _productKey;\n this.deviceKey = _deviceKey;\n\n this.deviceName = _deviceName;\n this.productName = _productName;\n\n this.iotTopic = `iot/${_productKey}/${_deviceKey}/properties/write`;\n this.functionTopic = `iot/${_productKey}/${_deviceKey}/function/invoke`;\n\n // Calculate device password\n this.password = createHash(\"md5\")\n .update(_deviceKey, \"utf8\")\n .digest(\"hex\")\n .toUpperCase()\n .substring(8, 24);\n\n // Create or update states\n this.createSolarFlowStates();\n\n // Subscribe to report topic (get telemetry)\n this.subscribeReportTopic();\n\n // Subscribe to Iot topic (push control values)\n this.subscribeIotTopic();\n\n // Get complete data from device after a timeout\n this.adapter.setTimeout(() => {\n this.triggerFullTelemetryUpdate();\n }, 5000);\n\n if (this.zenHaDeviceDetails?.online) {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n } else if (this.zenHaDeviceDetails?.online == false) {\n this.updateSolarFlowState(\"wifiState\", \"Disconnected\");\n }\n }\n\n private async createSolarFlowStates(): Promise<void> {\n const productKey = this.productKey.replace(\n this.adapter.FORBIDDEN_CHARS,\n \"\"\n );\n const deviceKey = this.deviceKey.replace(this.adapter.FORBIDDEN_CHARS, \"\");\n\n this.adapter.log.debug(\n `[createSolarFlowStates] Creating or updating SolarFlow states for ${this.productName} (${productKey}/${deviceKey}) and name '${this.deviceName}'.`\n );\n\n // Create device (e.g. the product type -> SolarFlow)\n await this.adapter?.extendObject(productKey, {\n type: \"device\",\n common: {\n name: {\n de: `${this.productName} (${productKey})`,\n en: `${this.productName} (${productKey})`,\n },\n },\n native: {},\n });\n\n // Create channel (e.g. the device specific key)\n await this.adapter?.extendObject(productKey + \".\" + deviceKey, {\n type: \"channel\",\n common: {\n name: {\n de: `${this.deviceName} (${deviceKey})`,\n en: `${this.deviceName} (${deviceKey})`,\n },\n },\n native: {},\n });\n\n // Create pack data folder\n await this.adapter?.extendObject(`${productKey}.${deviceKey}.packData`, {\n type: \"channel\",\n common: {\n name: {\n de: \"Batterie Packs\",\n en: \"Battery packs\",\n },\n },\n native: {},\n });\n\n // Create report states\n this.states.forEach(async (state: ISolarflowState) => {\n await this.adapter?.extendObject(\n `${productKey}.${deviceKey}.${state.title}`,\n {\n type: \"state\",\n common: {\n name: {\n de: state.nameDe,\n en: state.nameEn,\n },\n type: state.type,\n desc: state.title,\n role: state.role,\n read: true,\n write: false,\n unit: state.unit,\n states: state.states,\n },\n native: {},\n }\n );\n });\n\n // Create control folder\n await this.adapter?.extendObject(`${productKey}.${deviceKey}.control`, {\n type: \"channel\",\n common: {\n name: {\n de: \"Steuerung f\u00FCr Ger\u00E4t \" + deviceKey,\n en: \"Control for device \" + deviceKey,\n },\n },\n native: {},\n });\n\n this.controlStates.forEach(async (state: ISolarflowState) => {\n await this.adapter?.extendObject(\n `${productKey}.${deviceKey}.control.${state.title}`,\n {\n type: \"state\",\n common: {\n name: {\n de: state.nameDe,\n en: state.nameEn,\n },\n type: state.type,\n desc: state.title,\n role: state.role,\n read: true,\n write: true,\n unit: state.unit,\n states: state.states,\n },\n native: {},\n }\n );\n\n // Subscribe to states to respond to changes\n this.adapter?.subscribeStates(\n `${productKey}.${deviceKey}.control.${state.title}`\n );\n });\n\n if (this.adapter.config.useCalculation) {\n // Create calculations folder\n await this.adapter?.extendObject(\n `${productKey}.${deviceKey}.calculations`,\n {\n type: \"channel\",\n common: {\n name: {\n de: \"Berechnungen f\u00FCr Ger\u00E4t \" + deviceKey,\n en: \"Calculations for Device \" + deviceKey,\n },\n },\n native: {},\n }\n );\n\n await createCalculationStates(this.adapter, productKey, deviceKey);\n }\n }\n\n public subscribeReportTopic(): void {\n const reportTopic = `/${this.productKey}/${this.deviceKey}/#`;\n\n if (this.adapter) {\n this.adapter.log.debug(\n `[subscribeReportTopic] Subscribing to MQTT Topic: ${reportTopic}`\n );\n this.adapter.mqttClient?.subscribe(reportTopic, onSubscribeReportTopic);\n }\n }\n\n private subscribeIotTopic(): void {\n const iotTopic = `iot/${this.productKey}/${this.deviceKey}/#`;\n\n this.adapter?.log.debug(\n `[subscribeIotTopic] Subscribing to MQTT Topic: ${iotTopic}`\n );\n this.adapter?.mqttClient?.subscribe(iotTopic, (error) => {\n onSubscribeIotTopic(error, this.productKey, this.deviceKey);\n });\n }\n\n public setDeviceAutomationInOutLimit(limit: number): void {\n this.adapter?.log.error(\n `[setAcMode] Method setDeviceAutomationInOutLimit (set to ${limit}) not defined in base class!`\n );\n return;\n }\n\n public setAcMode(acMode: number): void {\n this.adapter?.log.error(\n `[setAcMode] Method setAcMode (set to ${acMode}) not defined in base class!`\n );\n return;\n }\n\n public setDcSwitch(dcSwitch: boolean): void {\n this.adapter?.log.error(\n `[setAcMode] Method setDcSwitch (set to ${dcSwitch}) not defined in base class!`\n );\n return;\n }\n\n public setAcSwitch(acSwitch: boolean): void {\n this.adapter?.log.error(\n `[setAcMode] Method setAcSwitch (set to ${acSwitch}) not defined in base class!`\n );\n return;\n }\n\n public setHubState(hubState: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n if (hubState == 0 || hubState == 1) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/write`;\n\n const socSetLimit = { properties: { hubState: hubState } };\n this.adapter.log.debug(\n `[setHubState] Setting Hub State for deviceKey ${this.deviceKey} to ${hubState}!`\n );\n this.adapter.mqttClient?.publish(topic, JSON.stringify(socSetLimit));\n } else {\n this.adapter.log.debug(`[setHubState] Hub state is not 0 or 1!`);\n }\n }\n }\n\n public setPassMode(passMode: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/write`;\n\n const setPassModeContent = { properties: { passMode: passMode } };\n this.adapter.log.debug(\n `[setPassMode] Set passMode for deviceKey ${this.deviceKey} to ${passMode}!`\n );\n this.adapter.mqttClient?.publish(\n topic,\n JSON.stringify(setPassModeContent)\n );\n }\n }\n\n public setAutoRecover(autoRecover: boolean): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/write`;\n\n const setAutoRecoverContent = {\n properties: { autoRecover: autoRecover ? 1 : 0 },\n };\n this.adapter.log.debug(\n `[setAutoRecover] Set autoRecover for deviceKey ${this.deviceKey} to ${autoRecover}!`\n );\n this.adapter.mqttClient?.publish(\n topic,\n JSON.stringify(setAutoRecoverContent)\n );\n }\n }\n\n /**\n * Will set the discharge limit (minSoc)\n * @param socSet the desired minimum soc\n * @returns void\n */\n public setDischargeLimit(minSoc: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n if (minSoc >= 0 && minSoc <= 50) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/write`;\n\n const socSetLimit = { properties: { minSoc: minSoc * 10 } };\n this.adapter.log.debug(\n `[setDischargeLimit] Setting Discharge Limit for device key ${this.deviceKey} to ${minSoc}!`\n );\n this.adapter.mqttClient?.publish(topic, JSON.stringify(socSetLimit));\n } else {\n this.adapter.log.debug(\n `[setDischargeLimit] Discharge limit is not in range 0<>50!`\n );\n }\n }\n }\n\n /**\n * Will set the maximum charge limit\n * @param socSet the desired max SOC\n * @returns void\n */\n public setChargeLimit(socSet: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n if (socSet >= 40 && socSet <= 100) {\n const socSetLimit = { properties: { socSet: socSet * 10 } };\n this.adapter.log.debug(\n `[setChargeLimit] Setting ChargeLimit for device key ${this.deviceKey} to ${socSet}!`\n );\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(socSetLimit)\n );\n } else {\n this.adapter.log.debug(\n `[setChargeLimit] Charge limit is not in range 40<>100!`\n );\n }\n }\n }\n\n /**\n * Will set the 'energy plan'\n * @param autoModel autoModel value, like 8 for smart matching\n * @returns void\n */\n public setAutoModel(autoModel: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n let setAutoModelContent: any = { properties: { autoModel: autoModel } };\n\n switch (autoModel) {\n case 8: {\n // Smart Matching Modus\n setAutoModelContent = {\n properties: {\n autoModelProgram: 1,\n autoModelValue: {\n chargingType: 0,\n chargingPower: 0,\n outPower: 0,\n },\n msgType: 1,\n autoModel: 8,\n },\n };\n break;\n }\n case 9: // Smart CT Modus\n setAutoModelContent = {\n properties: {\n autoModelProgram: 2,\n autoModelValue: {\n chargingType: 3,\n chargingPower: 0,\n outPower: 0,\n },\n msgType: 1,\n autoModel: 9,\n },\n };\n break;\n }\n\n this.adapter.log.debug(\n `[setAutoModel] Setting autoModel for device key ${this.deviceKey} to ${autoModel}!`\n );\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(setAutoModelContent)\n );\n }\n }\n\n public async setOutputLimit(limit: number): Promise<void> {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n // Check if autoModel is set to 0 (Nothing) or 8 (Smart Matching)\n const autoModel = (\n await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".autoModel\"\n )\n )?.val;\n\n if (autoModel != 0) {\n this.adapter.log.warn(\n \"Operation mode (autoModel) is not set to '0', we can't set the output limit!\"\n );\n return;\n }\n\n if (limit) {\n limit = Math.round(limit);\n } else {\n limit = 0;\n }\n\n // Limit to the device max limit\n if (limit > this.maxOutputLimit) {\n limit = this.maxOutputLimit;\n }\n\n if (\n limit < 100 &&\n limit != 90 &&\n limit != 60 &&\n limit != 30 &&\n limit != 0 &&\n (this.productKey == \"73bktv\" || this.productKey == \"a8yh63\")\n ) {\n // NUR Solarflow HUB: Das Limit kann unter 100 nur in 30er Schritten gesetzt werden, dH. 30/60/90/100, wir rechnen das also um\n if (limit < 100 && limit > 90) {\n limit = 90;\n } else if (limit > 60 && limit < 90) {\n limit = 60;\n } else if (limit > 30 && limit < 60) {\n limit = 30;\n } else if (limit < 30) {\n limit = 30;\n }\n }\n\n if (this.adapter.config.useLowVoltageBlock) {\n const lowVoltageBlockState = await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".control.lowVoltageBlock\"\n );\n if (\n lowVoltageBlockState &&\n lowVoltageBlockState.val &&\n lowVoltageBlockState.val == true\n ) {\n limit = 0;\n }\n\n const fullChargeNeeded = await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".control.fullChargeNeeded\"\n );\n\n if (\n fullChargeNeeded &&\n fullChargeNeeded.val &&\n fullChargeNeeded.val == true\n ) {\n limit = 0;\n }\n }\n\n const currentLimit = (\n await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".outputLimit\"\n )\n )?.val;\n\n if (currentLimit != null && currentLimit != undefined) {\n if (currentLimit != limit) {\n const outputlimit = { properties: { outputLimit: limit } };\n\n this.adapter.msgCounter += 1;\n\n const timestamp = new Date();\n timestamp.setMilliseconds(0);\n\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(outputlimit)\n );\n }\n }\n }\n }\n\n public setInputLimit(limit: number): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n // Limit has always to be positive!\n if (limit < 0) {\n this.adapter.log.debug(\n `[setInputLimit] limit ${limit} is negative, converting to positive!`\n );\n limit = Math.abs(limit);\n }\n\n if (limit) {\n limit = Math.round(limit);\n } else {\n limit = 0;\n }\n\n if (limit < 0) {\n limit = 0;\n } else if (limit > 0 && limit <= 30) {\n limit = 30;\n } else if (limit > this.maxInputLimit) {\n limit = this.maxInputLimit;\n }\n\n if (this.productKey.includes(\"8bm93h\")) {\n // Das Limit kann beim ACE nur in 100er Schritten gesetzt werden\n limit = Math.ceil(limit / 100) * 100;\n }\n\n const inputLimitContent = { properties: { inputLimit: limit } };\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(inputLimitContent)\n );\n }\n }\n\n public setSmartMode(smartModeOn: boolean): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const setSmartModeContent = {\n properties: { smartMode: smartModeOn ? 1 : 0 },\n };\n\n this.adapter.log.debug(\n `[setBuzzer] Setting Smart Mode for device key ${this.deviceKey} to ${smartModeOn}!`\n );\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(setSmartModeContent)\n );\n }\n }\n\n public setBuzzerSwitch(buzzerOn: boolean): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const setBuzzerSwitchContent = {\n properties: { buzzerSwitch: buzzerOn ? 1 : 0 },\n };\n this.adapter.log.debug(\n `[setBuzzer] Setting Buzzer for device key ${this.deviceKey} to ${buzzerOn}!`\n );\n this.adapter.mqttClient?.publish(\n this.iotTopic,\n JSON.stringify(setBuzzerSwitchContent)\n );\n }\n }\n\n public triggerFullTelemetryUpdate(): void {\n if (this.adapter.mqttClient && this.productKey && this.deviceKey) {\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/read`;\n\n const getAllContent = { properties: [\"getAll\"] };\n this.adapter.log.debug(\n `[triggerFullTelemetryUpdate] Triggering full telemetry update for device key ${this.deviceKey}!`\n );\n this.adapter.mqttClient?.publish(topic, JSON.stringify(getAllContent));\n }\n }\n\n public async updateSolarFlowState(\n state: string,\n val: number | string | boolean\n ): Promise<void> {\n const currentValue = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.${state}`\n );\n\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.${state}`,\n val,\n true\n );\n\n if (currentValue?.val != val && state != \"wifiState\") {\n // Set lastUpdate for deviceKey if a value was changed!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n }\n\n public async updateSolarFlowControlState(\n state: string,\n val: number | string | boolean\n ): Promise<void> {\n // First check if state exist\n const stateExist = await this.adapter?.objectExists(\n `${this.productKey}.${this.deviceKey}.control.${state}`\n );\n\n // Update the control state\n if (stateExist) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.control.${state}`,\n val,\n true\n );\n }\n }\n\n addOrUpdatePackData = async (\n packData: IPackData[],\n isSolarFlow: boolean\n ): Promise<void> => {\n if (this.adapter && this.productKey && this.deviceKey) {\n await packData.forEach(async (x) => {\n // Process data only with a serial id!\n if (x.sn && this.adapter) {\n // Create channel (e.g. the device specific key)\n // We can determine the type of the battery by the SN number.\n let batType = \"\";\n if (this.productKey == \"yWF7hV\") {\n batType = \"AIO2400\";\n } else if (x.sn.startsWith(\"A\")) {\n batType = \"AB1000\";\n } else if (x.sn.startsWith(\"B\")) {\n batType = \"AB1000S\";\n } else if (x.sn.startsWith(\"C\")) {\n if (x.sn[3] == \"F\") {\n batType = \"AB2000S\";\n } else {\n batType = \"AB2000\";\n }\n } else if (x.sn.startsWith(\"F\")) {\n batType = \"AB3000X\";\n }\n\n // Check if is in Pack2device list\n if (!this.batteries.some((y) => y.packSn == x.sn)) {\n this.batteries.push({\n packSn: x.sn,\n type: batType,\n });\n\n this.adapter.log.debug(\n `[addOrUpdatePackData] Added battery ${batType} with SN ${x.sn} on deviceKey ${this.deviceKey} to batteries array!`\n );\n }\n\n // create a state for the serial id\n const key = (\n this.productKey +\n \".\" +\n this.deviceKey +\n \".packData.\" +\n x.sn\n ).replace(this.adapter.FORBIDDEN_CHARS, \"\");\n\n await this.adapter?.extendObject(key, {\n type: \"channel\",\n common: {\n name: {\n de: batType,\n en: batType,\n },\n },\n native: {},\n });\n\n await this.adapter?.extendObject(key + \".model\", {\n type: \"state\",\n common: {\n name: {\n de: \"Batterietyp\",\n en: \"Battery type\",\n },\n type: \"string\",\n desc: \"model\",\n role: \"value\",\n read: true,\n write: false,\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".model\", batType, true);\n\n await this.adapter?.extendObject(key + \".sn\", {\n type: \"state\",\n common: {\n name: {\n de: \"Seriennummer\",\n en: \"Serial id\",\n },\n type: \"string\",\n desc: \"Serial ID\",\n role: \"value\",\n read: true,\n write: false,\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".sn\", x.sn, true);\n\n if (x.socLevel) {\n // State f\u00FCr socLevel\n await this.adapter?.extendObject(key + \".socLevel\", {\n type: \"state\",\n common: {\n name: {\n de: \"SOC der Batterie\",\n en: \"soc of battery\",\n },\n type: \"number\",\n desc: \"SOC Level\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"%\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".socLevel\", x.socLevel, true);\n }\n\n if (x.maxTemp) {\n const maxTempCelsius = x.maxTemp / 10 - 273.15;\n const maxTempState = await this.adapter?.getStateAsync(\n key + \".maxTemp\"\n );\n\n // Check if Value exist and changed, if so update lastUpdate!\n if (\n maxTempState &&\n maxTempState.val &&\n maxTempCelsius != maxTempState.val\n ) {\n // Value exist and value changed, update last update!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n\n // State f\u00FCr maxTemp\n await this.adapter?.extendObject(key + \".maxTemp\", {\n type: \"state\",\n common: {\n name: {\n de: \"Max. Temperatur der Batterie\",\n en: \"max temp. of battery\",\n },\n type: \"number\",\n desc: \"Max. Temp\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"\u00B0C\",\n },\n native: {},\n });\n\n // Convert Kelvin to Celsius\n await this.adapter?.setState(\n key + \".maxTemp\",\n maxTempCelsius,\n true\n );\n }\n\n if (x.minVol) {\n const minVol = x.minVol / 100;\n const minVolState = await this.adapter?.getStateAsync(\n key + \".minVol\"\n );\n\n // Check if Value exist and changed, if so update lastUpdate!\n if (minVolState && minVolState.val && minVol != minVolState.val) {\n // Value exist and value changed, update last update!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n\n await this.adapter?.extendObject(key + \".minVol\", {\n type: \"state\",\n common: {\n name: \"minVol\",\n type: \"number\",\n desc: \"minVol\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"V\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".minVol\", minVol, true);\n }\n\n if (x.batcur) {\n await this.adapter?.extendObject(key + \".batcur\", {\n type: \"state\",\n common: {\n name: \"batcur\",\n type: \"number\",\n desc: \"batcur\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"A\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".batcur\", x.batcur / 10, true);\n }\n\n // Check if Value exist and changed, if so update lastUpdate!\n if (x.maxVol) {\n const maxVol = x.maxVol / 100;\n const maxVolState = await this.adapter?.getStateAsync(\n key + \".maxVol\"\n );\n\n if (maxVolState && maxVolState.val && maxVol != maxVolState.val) {\n // Value exist and value changed, update last update!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n\n await this.adapter?.extendObject(key + \".maxVol\", {\n type: \"state\",\n common: {\n name: \"maxVol\",\n type: \"number\",\n desc: \"maxVol\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"V\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".maxVol\", maxVol, true);\n }\n\n // Check if Value exist and changed, if so update lastUpdate!\n if (x.totalVol) {\n const totalVol = x.totalVol / 100;\n\n const totalVolState = await this.adapter?.getStateAsync(\n key + \".totalVol\"\n );\n\n if (\n totalVolState &&\n totalVolState.val &&\n totalVol != totalVolState.val\n ) {\n // Value exist and value changed, update last update!\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true\n );\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.wifiState`\n );\n\n if (currentWifiState && currentWifiState.val == \"Disconnected\") {\n this.updateSolarFlowState(\"wifiState\", \"Connected\");\n }\n }\n\n await this.adapter?.extendObject(key + \".totalVol\", {\n type: \"state\",\n common: {\n name: \"totalVol\",\n type: \"number\",\n desc: \"totalVol\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"V\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".totalVol\", totalVol, true);\n\n // Send Voltage to checkVoltage Method (only if is Solarflow device)\n if (isSolarFlow) {\n this.checkVoltage(totalVol);\n }\n }\n\n if (x.soh) {\n await this.adapter?.extendObject(key + \".soh\", {\n type: \"state\",\n common: {\n name: {\n de: \"Gesundheitszustand\",\n en: \"State of Health\",\n },\n type: \"number\",\n desc: \"State of Health\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"%\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".soh\", x.soh / 10, true);\n }\n\n if (x.power) {\n await this.adapter?.extendObject(key + \".power\", {\n type: \"state\",\n common: {\n name: {\n de: \"Energie\",\n en: \"Power\",\n },\n type: \"number\",\n desc: \"Power\",\n read: true,\n write: false,\n role: \"value.power\",\n unit: \"W\",\n },\n native: {},\n });\n\n await this.adapter?.setState(key + \".power\", x.power, true);\n }\n\n // Debug, send message if property is unknown!\n let found = false;\n\n Object.entries(x).forEach(([key, value]) => {\n knownPackDataProperties.forEach((property: string) => {\n if (property == key) {\n found = true;\n }\n });\n\n if (found) {\n //console.log(\n // `${productName?.val}: ${key} with value ${value} is a KNOWN Mqtt Prop!`\n //);\n } else {\n this.adapter?.log.debug(\n `[addOrUpdatePackData] ${key} with value ${value} is a UNKNOWN PackData Mqtt Property!`\n );\n }\n });\n }\n });\n }\n };\n\n public async checkVoltage(voltage: number): Promise<void> {\n if (voltage < 46.1) {\n if (this.adapter.config.useCalculation) {\n this.setSocToZero();\n }\n\n if (this.adapter.config.useLowVoltageBlock) {\n // Activate Low Voltage Block\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`,\n true,\n true\n );\n\n // Low Voltage Block activated, stop power input immediately\n const autoModel = (\n await this.adapter.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".autoModel\"\n )\n )?.val;\n if (autoModel == 8) {\n this.setDeviceAutomationInOutLimit(0);\n } else {\n this.setOutputLimit(0);\n }\n\n if (this.adapter.config.forceShutdownOnLowVoltage) {\n const currentSoc = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.electricLevel`\n );\n\n if (currentSoc && Number(currentSoc.val) > 50) {\n // We can't shut down the device. Full charge needed!\n if (this.adapter.config.fullChargeIfNeeded) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.control.fullChargeNeeded`,\n true,\n true\n );\n }\n } else {\n if (currentSoc && currentSoc.val) {\n this.setDischargeLimit(Number(currentSoc.val));\n }\n\n // Check if device setting is correct\n const hubState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.hubState`\n );\n\n if (!hubState || Number(hubState.val) != 1) {\n this.adapter.log.warn(\n `[checkVoltage] hubState is not set to 'Stop output and shut down', device will NOT go offline!`\n );\n }\n }\n }\n }\n } else if (voltage >= 47.5) {\n // Deactivate Low Voltage Block\n const lowVoltageBlock = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`\n );\n\n if (lowVoltageBlock && lowVoltageBlock.val == true) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`,\n false,\n true\n );\n\n if (\n this.adapter.config.useLowVoltageBlock &&\n this.adapter.config.forceShutdownOnLowVoltage\n ) {\n this.setDischargeLimit(\n this.adapter.config.dischargeLimit\n ? this.adapter.config.dischargeLimit\n : 5\n );\n }\n }\n }\n }\n\n /**\n * Calculates the energy for all items in 'calculationStateKeys'.\n *\n * @returns Promise<void>\n *\n * @beta\n */\n public calculateEnergy(): void {\n calculationStateKeys.forEach(async (stateKey) => {\n let stateNameEnergyWh = \"\";\n let stateNameEnergykWh = \"\";\n let stateNamePower = \"\";\n\n switch (stateKey) {\n case \"pvPower1\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower1`;\n break;\n case \"pvPower2\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower2`;\n break;\n case \"pvPower3\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower3`;\n break;\n case \"pvPower4\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower4`;\n break;\n default:\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.${stateKey}Power`;\n break;\n }\n\n const currentPowerState =\n await this.adapter?.getStateAsync(stateNamePower);\n\n const currentEnergyState =\n await this.adapter?.getStateAsync(stateNameEnergyWh);\n\n if (!currentEnergyState?.val || currentEnergyState?.val == 0) {\n // Workaround, set Val to very low value to avoid Jump in data...\n await this.adapter?.setState(stateNameEnergyWh, 0.000001, true);\n } else if (\n currentEnergyState &&\n currentEnergyState.lc &&\n currentPowerState &&\n currentPowerState.val != undefined &&\n currentPowerState.val != null\n ) {\n // Timeframe = 30000ms, Job runs every 30 seconds...\n const timeFrame = 30000;\n\n // Calculate Energy value (Wh) from current power in the timeframe from last run...\n const addEnergyValue =\n (Number(currentPowerState.val) * timeFrame) / 3600000; // Wh\n\n /* // Use efficiency factor (used the one from Youtube Channel VoltAmpereLux - thanks!)\n const chargingFactor = 0.96; // Efficiency 96%\n const dischargingFactor = 1.08 - addEnergyValue / 10000; // Efficiency 92% - 98% (92% + Energy / 10000 = 600W -> +6%)\n\n // Calculate energy from efficiency factor if value for charging or discharging\n addEnergyValue =\n stateKey == \"outputPack\" && addEnergyValue > 0\n ? addEnergyValue * chargingFactor\n : addEnergyValue;\n addEnergyValue =\n stateKey == \"packInput\" && addEnergyValue > 0\n ? addEnergyValue * dischargingFactor\n : addEnergyValue; */\n\n let newEnergyValue = Number(currentEnergyState.val) + addEnergyValue;\n\n // Fix negative value\n if (newEnergyValue < 0) {\n newEnergyValue = 0;\n }\n\n await this.adapter?.setState(stateNameEnergyWh, newEnergyValue, true);\n await this.adapter?.setState(\n stateNameEnergykWh,\n Number((newEnergyValue / 1000).toFixed(2)),\n true\n );\n\n // SOC and energy in batteries\n if (\n (stateKey == \"outputPack\" || stateKey == \"packInput\") &&\n addEnergyValue > 0\n ) {\n await this.calculateSocAndEnergy(stateKey, addEnergyValue);\n } else {\n if (stateKey == \"outputPack\") {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainInputTime`,\n \"\",\n true\n );\n } else if (stateKey == \"packInput\") {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainOutTime`,\n \"\",\n true\n );\n }\n }\n } else if (currentPowerState && currentEnergyState) {\n await this.adapter?.setState(stateNameEnergyWh, 0, true);\n await this.adapter?.setState(stateNameEnergykWh, 0, true);\n }\n });\n }\n\n public calculateSocAndEnergy = async (\n stateKey: string,\n value: number\n ): Promise<void> => {\n this.adapter.log.debug(\n `[calculateSocAndEnergy] Calculating for: ${this.productKey}.${this.deviceKey} and stateKey ${stateKey}!`\n );\n\n let energyWhMax: number | undefined = undefined;\n\n const minSoc = (\n await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.minSoc`\n )\n )?.val;\n const currentSoc = (\n await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.electricLevel`\n )\n )?.val;\n\n if (currentSoc && minSoc && Number(currentSoc) < Number(minSoc)) {\n // Don't calculate if current SOC is lower then minimum\n this.adapter.log.debug(\n `[calculateSocAndEnergy] Don't calculate, currentSoc (${Number(currentSoc)}) is lower than minSoc (${Number(minSoc)})!`\n );\n\n return;\n }\n\n const currentEnergyState = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".calculations.energyWh\"\n );\n\n const currentEnergyMaxState = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".calculations.energyWhMax\"\n );\n\n const lowVoltageBlock = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".control.lowVoltageBlock\"\n );\n\n const currentMaxValue = Number(\n currentEnergyMaxState ? currentEnergyMaxState.val : 0\n );\n\n let currentEnergyWh = currentEnergyState?.val\n ? Number(currentEnergyState?.val)\n : 0;\n\n if (\n currentEnergyWh == null ||\n currentEnergyWh == undefined ||\n currentEnergyWh <= 0\n ) {\n currentEnergyWh = 0;\n }\n\n if (this.productKey == \"yWF7hV\") {\n // The device is an AIO 2400, so set maximum Wh to 2400!\n energyWhMax = 2400;\n } else {\n // Iterate over all batteries!\n for (let i = 0; i < this.batteries.length; i++) {\n if (this.batteries[i].type == \"AB1000\") {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 960;\n } else if (this.batteries[i].type == \"AB2000\") {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 1920;\n }\n }\n }\n\n // newValue is the current available energy in the batteries. If outputPack (charging) add value, if packInput (discharging) subtract value.\n let newEnergyWh =\n stateKey == \"outputPack\"\n ? currentEnergyWh + value\n : currentEnergyWh - value;\n\n // If greater than Max of batteries, set it to this value.\n if (\n stateKey == \"outputPack\" &&\n energyWhMax != undefined &&\n newEnergyWh > energyWhMax\n ) {\n newEnergyWh = energyWhMax;\n\n this.adapter.log.debug(\n `[calculateSocAndEnergy] newEnergyWh (${newEnergyWh}) is greater than energyWhMax (${energyWhMax}), don't extend value!`\n );\n }\n\n if (newEnergyWh > 0) {\n this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWh`,\n newEnergyWh,\n true\n );\n\n this.adapter.log.debug(\n `[calculateSocAndEnergy] set '${this.productKey}.${this.deviceKey}.calculations.energyWh' to ${newEnergyWh}!`\n );\n\n if (currentEnergyMaxState) {\n const soc = Number(((newEnergyWh / currentMaxValue) * 100).toFixed(1));\n\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.soc`,\n soc > 100.0 ? 100 : soc,\n true\n );\n\n if (newEnergyWh > currentMaxValue && !lowVoltageBlock?.val) {\n // Extend maxVal\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`,\n newEnergyWh,\n true\n );\n }\n\n const currentOutputPackPower = await this.adapter?.getStateAsync(\n `${this.productKey}.${this.deviceKey}.outputPackPower`\n );\n\n const currentPackInputPower = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".packInputPower\"\n );\n\n if (\n stateKey == \"outputPack\" &&\n currentOutputPackPower?.val != null &&\n currentOutputPackPower != undefined\n ) {\n // Charging, calculate remaining charging time\n const toCharge = currentMaxValue - newEnergyWh;\n\n const remainHoursAsDecimal =\n toCharge / Number(currentOutputPackPower.val);\n\n if (remainHoursAsDecimal < 48.0) {\n const remainFormatted = toHoursAndMinutes(\n Math.round(remainHoursAsDecimal * 60)\n );\n\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainInputTime`,\n remainFormatted,\n true\n );\n } else {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainInputTime`,\n \"\",\n true\n );\n }\n } else if (\n stateKey == \"packInput\" &&\n currentPackInputPower != null &&\n currentPackInputPower != undefined\n ) {\n // Discharging, calculate remaining discharge time\n const remainHoursAsDecimal =\n newEnergyWh / Number(currentPackInputPower.val);\n const remainFormatted = toHoursAndMinutes(\n Math.round(remainHoursAsDecimal * 60)\n );\n\n if (remainHoursAsDecimal < 48.0) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainOutTime`,\n remainFormatted,\n true\n );\n } else {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainOutTime`,\n \"\",\n true\n );\n }\n }\n }\n } else if (newEnergyWh <= 0 && stateKey == \"outputPack\") {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainInputTime`,\n \"\",\n true\n );\n } else if (newEnergyWh <= 0 && stateKey == \"packInput\") {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.remainOutTime`,\n \"\",\n true\n );\n\n // TEST: if SOC == 0, add newValue as positive to energyWhMax\n const newEnergyWhPositive = Math.abs(newEnergyWh);\n\n if (energyWhMax && currentMaxValue + newEnergyWhPositive <= energyWhMax) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`,\n currentMaxValue + newEnergyWhPositive,\n true\n );\n }\n }\n };\n\n public async setSocToZero(): Promise<void> {\n // Set SOC to 0\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.soc`,\n 0,\n true\n );\n\n // Calculate new Wh Max Value\n const energyWhState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.calculations.energyWh`\n );\n const energyWhMaxState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`\n );\n\n const newMax = Number(energyWhMaxState?.val) - Number(energyWhState?.val);\n\n // Set Max Energy to value minus current energy\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`,\n newMax,\n true\n );\n\n // Set Energy in Battery to 0\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWh`,\n 0,\n true\n );\n }\n\n public async setEnergyWhMax(): Promise<void> {\n const currentEnergyState = await this.adapter?.getStateAsync(\n this.productKey + \".\" + this.deviceKey + \".calculations.energyWh\"\n );\n\n if (currentEnergyState) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.calculations.energyWhMax`,\n currentEnergyState?.val,\n true\n );\n }\n }\n\n public resetValuesForDevice(): void {\n calculationStateKeys.forEach(async (stateKey: string) => {\n let stateNameEnergyWh = \"\";\n let stateNameEnergykWh = \"\";\n\n if (stateKey == \"pvPower1\") {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodaykWh`;\n } else if (stateKey == \"pvPower2\") {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodaykWh`;\n } else {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\n }\n\n await this.adapter?.setState(stateNameEnergyWh, 0, true);\n await this.adapter?.setState(stateNameEnergykWh, 0, true);\n });\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA2B;AAC3B,uBAAqC;AACrC,qCAAwC;AACxC,wBAAkC;AAElC,+BAIO;AAMA,MAAM,YAAY;AAAA,EAoBhB,YACL,UACA,aACA,YACA,cACA,aACA,qBACA;AAnBF,SAAO,YAA2B,CAAC;AAEnC,SAAO,WAAmB;AAC1B,SAAO,gBAAgB;AACvB,SAAO,WAAmB;AAE1B,SAAO,gBAAwB;AAC/B,SAAO,iBAAyB;AAEhC,SAAO,SAA4B,CAAC;AACpC,SAAO,gBAAmC,CAAC;AA6lB3C,+BAAsB,OACpB,UACA,gBACkB;AAClB,UAAI,KAAK,WAAW,KAAK,cAAc,KAAK,WAAW;AACrD,cAAM,SAAS,QAAQ,OAAO,MAAM;AAnoB1C;AAqoBQ,cAAI,EAAE,MAAM,KAAK,SAAS;AAGxB,gBAAI,UAAU;AACd,gBAAI,KAAK,cAAc,UAAU;AAC/B,wBAAU;AAAA,YACZ,WAAW,EAAE,GAAG,WAAW,GAAG,GAAG;AAC/B,wBAAU;AAAA,YACZ,WAAW,EAAE,GAAG,WAAW,GAAG,GAAG;AAC/B,wBAAU;AAAA,YACZ,WAAW,EAAE,GAAG,WAAW,GAAG,GAAG;AAC/B,kBAAI,EAAE,GAAG,CAAC,KAAK,KAAK;AAClB,0BAAU;AAAA,cACZ,OAAO;AACL,0BAAU;AAAA,cACZ;AAAA,YACF,WAAW,EAAE,GAAG,WAAW,GAAG,GAAG;AAC/B,wBAAU;AAAA,YACZ;AAGA,gBAAI,CAAC,KAAK,UAAU,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG;AACjD,mBAAK,UAAU,KAAK;AAAA,gBAClB,QAAQ,EAAE;AAAA,gBACV,MAAM;AAAA,cACR,CAAC;AAED,mBAAK,QAAQ,IAAI;AAAA,gBACf,uCAAuC,OAAO,YAAY,EAAE,EAAE,iBAAiB,KAAK,SAAS;AAAA,cAC/F;AAAA,YACF;AAGA,kBAAM,OACJ,KAAK,aACL,MACA,KAAK,YACL,eACA,EAAE,IACF,QAAQ,KAAK,QAAQ,iBAAiB,EAAE;AAE1C,oBAAM,UAAK,YAAL,mBAAc,aAAa,KAAK;AAAA,cACpC,MAAM;AAAA,cACN,QAAQ;AAAA,gBACN,MAAM;AAAA,kBACJ,IAAI;AAAA,kBACJ,IAAI;AAAA,gBACN;AAAA,cACF;AAAA,cACA,QAAQ,CAAC;AAAA,YACX;AAEA,oBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,UAAU;AAAA,cAC/C,MAAM;AAAA,cACN,QAAQ;AAAA,gBACN,MAAM;AAAA,kBACJ,IAAI;AAAA,kBACJ,IAAI;AAAA,gBACN;AAAA,gBACA,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,OAAO;AAAA,cACT;AAAA,cACA,QAAQ,CAAC;AAAA,YACX;AAEA,oBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,UAAU,SAAS;AAEtD,oBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,OAAO;AAAA,cAC5C,MAAM;AAAA,cACN,QAAQ;AAAA,gBACN,MAAM;AAAA,kBACJ,IAAI;AAAA,kBACJ,IAAI;AAAA,gBACN;AAAA,gBACA,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,OAAO;AAAA,cACT;AAAA,cACA,QAAQ,CAAC;AAAA,YACX;AAEA,oBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,OAAO,EAAE,IAAI;AAEhD,gBAAI,EAAE,UAAU;AAEd,sBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,aAAa;AAAA,gBAClD,MAAM;AAAA,gBACN,QAAQ;AAAA,kBACN,MAAM;AAAA,oBACJ,IAAI;AAAA,oBACJ,IAAI;AAAA,kBACN;AAAA,kBACA,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,MAAM;AAAA,gBACR;AAAA,gBACA,QAAQ,CAAC;AAAA,cACX;AAEA,sBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,aAAa,EAAE,UAAU;AAAA,YAC9D;AAEA,gBAAI,EAAE,SAAS;AACb,oBAAM,iBAAiB,EAAE,UAAU,KAAK;AACxC,oBAAM,eAAe,QAAM,UAAK,YAAL,mBAAc;AAAA,gBACvC,MAAM;AAAA;AAIR,kBACE,gBACA,aAAa,OACb,kBAAkB,aAAa,KAC/B;AAEA,wBAAM,UAAK,YAAL,mBAAc;AAAA,kBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,mBACpC,oBAAI,KAAK,GAAE,QAAQ;AAAA,kBACnB;AAAA;AAIF,sBAAM,mBAAmB,MAAM,KAAK,QAAQ;AAAA,kBAC1C,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACtC;AAEA,oBAAI,oBAAoB,iBAAiB,OAAO,gBAAgB;AAC9D,uBAAK,qBAAqB,aAAa,WAAW;AAAA,gBACpD;AAAA,cACF;AAGA,sBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,YAAY;AAAA,gBACjD,MAAM;AAAA,gBACN,QAAQ;AAAA,kBACN,MAAM;AAAA,oBACJ,IAAI;AAAA,oBACJ,IAAI;AAAA,kBACN;AAAA,kBACA,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,MAAM;AAAA,gBACR;AAAA,gBACA,QAAQ,CAAC;AAAA,cACX;AAGA,sBAAM,UAAK,YAAL,mBAAc;AAAA,gBAClB,MAAM;AAAA,gBACN;AAAA,gBACA;AAAA;AAAA,YAEJ;AAEA,gBAAI,EAAE,QAAQ;AACZ,oBAAM,SAAS,EAAE,SAAS;AAC1B,oBAAM,cAAc,QAAM,UAAK,YAAL,mBAAc;AAAA,gBACtC,MAAM;AAAA;AAIR,kBAAI,eAAe,YAAY,OAAO,UAAU,YAAY,KAAK;AAE/D,wBAAM,UAAK,YAAL,mBAAc;AAAA,kBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,mBACpC,oBAAI,KAAK,GAAE,QAAQ;AAAA,kBACnB;AAAA;AAIF,sBAAM,mBAAmB,MAAM,KAAK,QAAQ;AAAA,kBAC1C,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACtC;AAEA,oBAAI,oBAAoB,iBAAiB,OAAO,gBAAgB;AAC9D,uBAAK,qBAAqB,aAAa,WAAW;AAAA,gBACpD;AAAA,cACF;AAEA,sBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,WAAW;AAAA,gBAChD,MAAM;AAAA,gBACN,QAAQ;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,MAAM;AAAA,gBACR;AAAA,gBACA,QAAQ,CAAC;AAAA,cACX;AAEA,sBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,WAAW,QAAQ;AAAA,YACxD;AAEA,gBAAI,EAAE,QAAQ;AACZ,sBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,WAAW;AAAA,gBAChD,MAAM;AAAA,gBACN,QAAQ;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,MAAM;AAAA,gBACR;AAAA,gBACA,QAAQ,CAAC;AAAA,cACX;AAEA,sBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,WAAW,EAAE,SAAS,IAAI;AAAA,YAC/D;AAGA,gBAAI,EAAE,QAAQ;AACZ,oBAAM,SAAS,EAAE,SAAS;AAC1B,oBAAM,cAAc,QAAM,UAAK,YAAL,mBAAc;AAAA,gBACtC,MAAM;AAAA;AAGR,kBAAI,eAAe,YAAY,OAAO,UAAU,YAAY,KAAK;AAE/D,wBAAM,UAAK,YAAL,mBAAc;AAAA,kBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,mBACpC,oBAAI,KAAK,GAAE,QAAQ;AAAA,kBACnB;AAAA;AAIF,sBAAM,mBAAmB,MAAM,KAAK,QAAQ;AAAA,kBAC1C,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACtC;AAEA,oBAAI,oBAAoB,iBAAiB,OAAO,gBAAgB;AAC9D,uBAAK,qBAAqB,aAAa,WAAW;AAAA,gBACpD;AAAA,cACF;AAEA,sBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,WAAW;AAAA,gBAChD,MAAM;AAAA,gBACN,QAAQ;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,MAAM;AAAA,gBACR;AAAA,gBACA,QAAQ,CAAC;AAAA,cACX;AAEA,sBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,WAAW,QAAQ;AAAA,YACxD;AAGA,gBAAI,EAAE,UAAU;AACd,oBAAM,WAAW,EAAE,WAAW;AAE9B,oBAAM,gBAAgB,QAAM,UAAK,YAAL,mBAAc;AAAA,gBACxC,MAAM;AAAA;AAGR,kBACE,iBACA,cAAc,OACd,YAAY,cAAc,KAC1B;AAEA,wBAAM,UAAK,YAAL,mBAAc;AAAA,kBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,mBACpC,oBAAI,KAAK,GAAE,QAAQ;AAAA,kBACnB;AAAA;AAIF,sBAAM,mBAAmB,MAAM,KAAK,QAAQ;AAAA,kBAC1C,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACtC;AAEA,oBAAI,oBAAoB,iBAAiB,OAAO,gBAAgB;AAC9D,uBAAK,qBAAqB,aAAa,WAAW;AAAA,gBACpD;AAAA,cACF;AAEA,sBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,aAAa;AAAA,gBAClD,MAAM;AAAA,gBACN,QAAQ;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,MAAM;AAAA,gBACR;AAAA,gBACA,QAAQ,CAAC;AAAA,cACX;AAEA,sBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,aAAa,UAAU;AAG1D,kBAAI,aAAa;AACf,qBAAK,aAAa,QAAQ;AAAA,cAC5B;AAAA,YACF;AAEA,gBAAI,EAAE,KAAK;AACT,sBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,QAAQ;AAAA,gBAC7C,MAAM;AAAA,gBACN,QAAQ;AAAA,kBACN,MAAM;AAAA,oBACJ,IAAI;AAAA,oBACJ,IAAI;AAAA,kBACN;AAAA,kBACA,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,MAAM;AAAA,gBACR;AAAA,gBACA,QAAQ,CAAC;AAAA,cACX;AAEA,sBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,QAAQ,EAAE,MAAM,IAAI;AAAA,YACzD;AAEA,gBAAI,EAAE,OAAO;AACX,sBAAM,UAAK,YAAL,mBAAc,aAAa,MAAM,UAAU;AAAA,gBAC/C,MAAM;AAAA,gBACN,QAAQ;AAAA,kBACN,MAAM;AAAA,oBACJ,IAAI;AAAA,oBACJ,IAAI;AAAA,kBACN;AAAA,kBACA,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,MAAM;AAAA,kBACN,MAAM;AAAA,gBACR;AAAA,gBACA,QAAQ,CAAC;AAAA,cACX;AAEA,sBAAM,UAAK,YAAL,mBAAc,SAAS,MAAM,UAAU,EAAE,OAAO;AAAA,YACxD;AAGA,gBAAI,QAAQ;AAEZ,mBAAO,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAACA,MAAK,KAAK,MAAM;AAj/BtD,kBAAAC;AAk/BY,+DAAwB,QAAQ,CAAC,aAAqB;AACpD,oBAAI,YAAYD,MAAK;AACnB,0BAAQ;AAAA,gBACV;AAAA,cACF,CAAC;AAED,kBAAI,OAAO;AAAA,cAIX,OAAO;AACL,iBAAAC,MAAA,KAAK,YAAL,gBAAAA,IAAc,IAAI;AAAA,kBAChB,yBAAyBD,IAAG,eAAe,KAAK;AAAA;AAAA,cAEpD;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AA+MA,SAAO,wBAAwB,OAC7B,UACA,UACkB;AAvtCtB;AAwtCI,WAAK,QAAQ,IAAI;AAAA,QACf,4CAA4C,KAAK,UAAU,IAAI,KAAK,SAAS,iBAAiB,QAAQ;AAAA,MACxG;AAEA,UAAI,cAAkC;AAEtC,YAAM,UACJ,WAAM,KAAK,QAAQ;AAAA,QACjB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACtC,MAFA,mBAGC;AACH,YAAM,cACJ,WAAM,KAAK,QAAQ;AAAA,QACjB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACtC,MAFA,mBAGC;AAEH,UAAI,cAAc,UAAU,OAAO,UAAU,IAAI,OAAO,MAAM,GAAG;AAE/D,aAAK,QAAQ,IAAI;AAAA,UACf,wDAAwD,OAAO,UAAU,CAAC,2BAA2B,OAAO,MAAM,CAAC;AAAA,QACrH;AAEA;AAAA,MACF;AAEA,YAAM,qBAAqB,QAAM,UAAK,YAAL,mBAAc;AAAA,QAC7C,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA;AAG3C,YAAM,wBAAwB,QAAM,UAAK,YAAL,mBAAc;AAAA,QAChD,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA;AAG3C,YAAM,kBAAkB,QAAM,UAAK,YAAL,mBAAc;AAAA,QAC1C,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA;AAG3C,YAAM,kBAAkB;AAAA,QACtB,wBAAwB,sBAAsB,MAAM;AAAA,MACtD;AAEA,UAAI,mBAAkB,yDAAoB,OACtC,OAAO,yDAAoB,GAAG,IAC9B;AAEJ,UACE,mBAAmB,QACnB,mBAAmB,UACnB,mBAAmB,GACnB;AACA,0BAAkB;AAAA,MACpB;AAEA,UAAI,KAAK,cAAc,UAAU;AAE/B,sBAAc;AAAA,MAChB,OAAO;AAEL,iBAAS,IAAI,GAAG,IAAI,KAAK,UAAU,QAAQ,KAAK;AAC9C,cAAI,KAAK,UAAU,CAAC,EAAE,QAAQ,UAAU;AACtC,2BAAe,cAAc,cAAc,KAAK;AAAA,UAClD,WAAW,KAAK,UAAU,CAAC,EAAE,QAAQ,UAAU;AAC7C,2BAAe,cAAc,cAAc,KAAK;AAAA,UAClD;AAAA,QACF;AAAA,MACF;AAGA,UAAI,cACF,YAAY,eACR,kBAAkB,QAClB,kBAAkB;AAGxB,UACE,YAAY,gBACZ,eAAe,UACf,cAAc,aACd;AACA,sBAAc;AAEd,aAAK,QAAQ,IAAI;AAAA,UACf,wCAAwC,WAAW,kCAAkC,WAAW;AAAA,QAClG;AAAA,MACF;AAEA,UAAI,cAAc,GAAG;AACnB,mBAAK,YAAL,mBAAc;AAAA,UACZ,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,UACpC;AAAA,UACA;AAAA;AAGF,aAAK,QAAQ,IAAI;AAAA,UACf,gCAAgC,KAAK,UAAU,IAAI,KAAK,SAAS,8BAA8B,WAAW;AAAA,QAC5G;AAEA,YAAI,uBAAuB;AACzB,gBAAM,MAAM,QAAS,cAAc,kBAAmB,KAAK,QAAQ,CAAC,CAAC;AAErE,kBAAM,UAAK,YAAL,mBAAc;AAAA,YAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,YACpC,MAAM,MAAQ,MAAM;AAAA,YACpB;AAAA;AAGF,cAAI,cAAc,mBAAmB,EAAC,mDAAiB,MAAK;AAE1D,oBAAM,UAAK,YAAL,mBAAc;AAAA,cAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,cACpC;AAAA,cACA;AAAA;AAAA,UAEJ;AAEA,gBAAM,yBAAyB,QAAM,UAAK,YAAL,mBAAc;AAAA,YACjD,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA;AAGtC,gBAAM,wBAAwB,QAAM,UAAK,YAAL,mBAAc;AAAA,YAChD,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA;AAG3C,cACE,YAAY,iBACZ,iEAAwB,QAAO,QAC/B,0BAA0B,QAC1B;AAEA,kBAAM,WAAW,kBAAkB;AAEnC,kBAAM,uBACJ,WAAW,OAAO,uBAAuB,GAAG;AAE9C,gBAAI,uBAAuB,IAAM;AAC/B,oBAAM,sBAAkB;AAAA,gBACtB,KAAK,MAAM,uBAAuB,EAAE;AAAA,cACtC;AAEA,sBAAM,UAAK,YAAL,mBAAc;AAAA,gBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACpC;AAAA,gBACA;AAAA;AAAA,YAEJ,OAAO;AACL,sBAAM,UAAK,YAAL,mBAAc;AAAA,gBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACpC;AAAA,gBACA;AAAA;AAAA,YAEJ;AAAA,UACF,WACE,YAAY,eACZ,yBAAyB,QACzB,yBAAyB,QACzB;AAEA,kBAAM,uBACJ,cAAc,OAAO,sBAAsB,GAAG;AAChD,kBAAM,sBAAkB;AAAA,cACtB,KAAK,MAAM,uBAAuB,EAAE;AAAA,YACtC;AAEA,gBAAI,uBAAuB,IAAM;AAC/B,sBAAM,UAAK,YAAL,mBAAc;AAAA,gBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACpC;AAAA,gBACA;AAAA;AAAA,YAEJ,OAAO;AACL,sBAAM,UAAK,YAAL,mBAAc;AAAA,gBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACpC;AAAA,gBACA;AAAA;AAAA,YAEJ;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,eAAe,KAAK,YAAY,cAAc;AACvD,gBAAM,UAAK,YAAL,mBAAc;AAAA,UAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,UACpC;AAAA,UACA;AAAA;AAAA,MAEJ,WAAW,eAAe,KAAK,YAAY,aAAa;AACtD,gBAAM,UAAK,YAAL,mBAAc;AAAA,UAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,UACpC;AAAA,UACA;AAAA;AAIF,cAAM,sBAAsB,KAAK,IAAI,WAAW;AAEhD,YAAI,eAAe,kBAAkB,uBAAuB,aAAa;AACvE,kBAAM,UAAK,YAAL,mBAAc;AAAA,YAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,YACpC,kBAAkB;AAAA,YAClB;AAAA;AAAA,QAEJ;AAAA,MACF;AAAA,IACF;AAn6CF;AA2CI,SAAK,qBAAqB;AAC1B,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,YAAY;AAEjB,SAAK,aAAa;AAClB,SAAK,cAAc;AAEnB,SAAK,WAAW,OAAO,WAAW,IAAI,UAAU;AAChD,SAAK,gBAAgB,OAAO,WAAW,IAAI,UAAU;AAGrD,SAAK,eAAW,0BAAW,KAAK,EAC7B,OAAO,YAAY,MAAM,EACzB,OAAO,KAAK,EACZ,YAAY,EACZ,UAAU,GAAG,EAAE;AAGlB,SAAK,sBAAsB;AAG3B,SAAK,qBAAqB;AAG1B,SAAK,kBAAkB;AAGvB,SAAK,QAAQ,WAAW,MAAM;AAC5B,WAAK,2BAA2B;AAAA,IAClC,GAAG,GAAI;AAEP,SAAI,UAAK,uBAAL,mBAAyB,QAAQ;AACnC,WAAK,qBAAqB,aAAa,WAAW;AAAA,IACpD,aAAW,UAAK,uBAAL,mBAAyB,WAAU,OAAO;AACnD,WAAK,qBAAqB,aAAa,cAAc;AAAA,IACvD;AAAA,EACF;AAAA,EAEA,MAAc,wBAAuC;AAlFvD;AAmFI,UAAM,aAAa,KAAK,WAAW;AAAA,MACjC,KAAK,QAAQ;AAAA,MACb;AAAA,IACF;AACA,UAAM,YAAY,KAAK,UAAU,QAAQ,KAAK,QAAQ,iBAAiB,EAAE;AAEzE,SAAK,QAAQ,IAAI;AAAA,MACf,qEAAqE,KAAK,WAAW,KAAK,UAAU,IAAI,SAAS,eAAe,KAAK,UAAU;AAAA,IACjJ;AAGA,YAAM,UAAK,YAAL,mBAAc,aAAa,YAAY;AAAA,MAC3C,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,IAAI,GAAG,KAAK,WAAW,KAAK,UAAU;AAAA,UACtC,IAAI,GAAG,KAAK,WAAW,KAAK,UAAU;AAAA,QACxC;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,IACX;AAGA,YAAM,UAAK,YAAL,mBAAc,aAAa,aAAa,MAAM,WAAW;AAAA,MAC7D,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,IAAI,GAAG,KAAK,UAAU,KAAK,SAAS;AAAA,UACpC,IAAI,GAAG,KAAK,UAAU,KAAK,SAAS;AAAA,QACtC;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,IACX;AAGA,YAAM,UAAK,YAAL,mBAAc,aAAa,GAAG,UAAU,IAAI,SAAS,aAAa;AAAA,MACtE,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,IAAI;AAAA,UACJ,IAAI;AAAA,QACN;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,IACX;AAGA,SAAK,OAAO,QAAQ,OAAO,UAA2B;AAlI1D,UAAAC;AAmIM,cAAMA,MAAA,KAAK,YAAL,gBAAAA,IAAc;AAAA,QAClB,GAAG,UAAU,IAAI,SAAS,IAAI,MAAM,KAAK;AAAA,QACzC;AAAA,UACE,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,cACJ,IAAI,MAAM;AAAA,cACV,IAAI,MAAM;AAAA,YACZ;AAAA,YACA,MAAM,MAAM;AAAA,YACZ,MAAM,MAAM;AAAA,YACZ,MAAM,MAAM;AAAA,YACZ,MAAM;AAAA,YACN,OAAO;AAAA,YACP,MAAM,MAAM;AAAA,YACZ,QAAQ,MAAM;AAAA,UAChB;AAAA,UACA,QAAQ,CAAC;AAAA,QACX;AAAA;AAAA,IAEJ,CAAC;AAGD,YAAM,UAAK,YAAL,mBAAc,aAAa,GAAG,UAAU,IAAI,SAAS,YAAY;AAAA,MACrE,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,IAAI,+BAAyB;AAAA,UAC7B,IAAI,wBAAwB;AAAA,QAC9B;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,IACX;AAEA,SAAK,cAAc,QAAQ,OAAO,UAA2B;AArKjE,UAAAA,KAAAC;AAsKM,cAAMD,MAAA,KAAK,YAAL,gBAAAA,IAAc;AAAA,QAClB,GAAG,UAAU,IAAI,SAAS,YAAY,MAAM,KAAK;AAAA,QACjD;AAAA,UACE,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,cACJ,IAAI,MAAM;AAAA,cACV,IAAI,MAAM;AAAA,YACZ;AAAA,YACA,MAAM,MAAM;AAAA,YACZ,MAAM,MAAM;AAAA,YACZ,MAAM,MAAM;AAAA,YACZ,MAAM;AAAA,YACN,OAAO;AAAA,YACP,MAAM,MAAM;AAAA,YACZ,QAAQ,MAAM;AAAA,UAChB;AAAA,UACA,QAAQ,CAAC;AAAA,QACX;AAAA;AAIF,OAAAC,MAAA,KAAK,YAAL,gBAAAA,IAAc;AAAA,QACZ,GAAG,UAAU,IAAI,SAAS,YAAY,MAAM,KAAK;AAAA;AAAA,IAErD,CAAC;AAED,QAAI,KAAK,QAAQ,OAAO,gBAAgB;AAEtC,cAAM,UAAK,YAAL,mBAAc;AAAA,QAClB,GAAG,UAAU,IAAI,SAAS;AAAA,QAC1B;AAAA,UACE,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,cACJ,IAAI,kCAA4B;AAAA,cAChC,IAAI,6BAA6B;AAAA,YACnC;AAAA,UACF;AAAA,UACA,QAAQ,CAAC;AAAA,QACX;AAAA;AAGF,gBAAM,wDAAwB,KAAK,SAAS,YAAY,SAAS;AAAA,IACnE;AAAA,EACF;AAAA,EAEO,uBAA6B;AArNtC;AAsNI,UAAM,cAAc,IAAI,KAAK,UAAU,IAAI,KAAK,SAAS;AAEzD,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,IAAI;AAAA,QACf,qDAAqD,WAAW;AAAA,MAClE;AACA,iBAAK,QAAQ,eAAb,mBAAyB,UAAU,aAAa;AAAA,IAClD;AAAA,EACF;AAAA,EAEQ,oBAA0B;AAhOpC;AAiOI,UAAM,WAAW,OAAO,KAAK,UAAU,IAAI,KAAK,SAAS;AAEzD,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,kDAAkD,QAAQ;AAAA;AAE5D,qBAAK,YAAL,mBAAc,eAAd,mBAA0B,UAAU,UAAU,CAAC,UAAU;AACvD,wDAAoB,OAAO,KAAK,YAAY,KAAK,SAAS;AAAA,IAC5D;AAAA,EACF;AAAA,EAEO,8BAA8B,OAAqB;AA3O5D;AA4OI,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,4DAA4D,KAAK;AAAA;AAEnE;AAAA,EACF;AAAA,EAEO,UAAU,QAAsB;AAlPzC;AAmPI,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,wCAAwC,MAAM;AAAA;AAEhD;AAAA,EACF;AAAA,EAEO,YAAY,UAAyB;AAzP9C;AA0PI,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,0CAA0C,QAAQ;AAAA;AAEpD;AAAA,EACF;AAAA,EAEO,YAAY,UAAyB;AAhQ9C;AAiQI,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,0CAA0C,QAAQ;AAAA;AAEpD;AAAA,EACF;AAAA,EAEO,YAAY,UAAwB;AAvQ7C;AAwQI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,UAAI,YAAY,KAAK,YAAY,GAAG;AAClC,cAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,KAAK,SAAS;AAEtD,cAAM,cAAc,EAAE,YAAY,EAAE,SAAmB,EAAE;AACzD,aAAK,QAAQ,IAAI;AAAA,UACf,iDAAiD,KAAK,SAAS,OAAO,QAAQ;AAAA,QAChF;AACA,mBAAK,QAAQ,eAAb,mBAAyB,QAAQ,OAAO,KAAK,UAAU,WAAW;AAAA,MACpE,OAAO;AACL,aAAK,QAAQ,IAAI,MAAM,wCAAwC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,YAAY,UAAwB;AAvR7C;AAwRI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,YAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,KAAK,SAAS;AAEtD,YAAM,qBAAqB,EAAE,YAAY,EAAE,SAAmB,EAAE;AAChE,WAAK,QAAQ,IAAI;AAAA,QACf,4CAA4C,KAAK,SAAS,OAAO,QAAQ;AAAA,MAC3E;AACA,iBAAK,QAAQ,eAAb,mBAAyB;AAAA,QACvB;AAAA,QACA,KAAK,UAAU,kBAAkB;AAAA;AAAA,IAErC;AAAA,EACF;AAAA,EAEO,eAAe,aAA4B;AAtSpD;AAuSI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,YAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,KAAK,SAAS;AAEtD,YAAM,wBAAwB;AAAA,QAC5B,YAAY,EAAE,aAAa,cAAc,IAAI,EAAE;AAAA,MACjD;AACA,WAAK,QAAQ,IAAI;AAAA,QACf,kDAAkD,KAAK,SAAS,OAAO,WAAW;AAAA,MACpF;AACA,iBAAK,QAAQ,eAAb,mBAAyB;AAAA,QACvB;AAAA,QACA,KAAK,UAAU,qBAAqB;AAAA;AAAA,IAExC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,kBAAkB,QAAsB;AA5TjD;AA6TI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,UAAI,UAAU,KAAK,UAAU,IAAI;AAC/B,cAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,KAAK,SAAS;AAEtD,cAAM,cAAc,EAAE,YAAY,EAAE,QAAQ,SAAS,GAAG,EAAE;AAC1D,aAAK,QAAQ,IAAI;AAAA,UACf,8DAA8D,KAAK,SAAS,OAAO,MAAM;AAAA,QAC3F;AACA,mBAAK,QAAQ,eAAb,mBAAyB,QAAQ,OAAO,KAAK,UAAU,WAAW;AAAA,MACpE,OAAO;AACL,aAAK,QAAQ,IAAI;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,eAAe,QAAsB;AAnV9C;AAoVI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,UAAI,UAAU,MAAM,UAAU,KAAK;AACjC,cAAM,cAAc,EAAE,YAAY,EAAE,QAAQ,SAAS,GAAG,EAAE;AAC1D,aAAK,QAAQ,IAAI;AAAA,UACf,uDAAuD,KAAK,SAAS,OAAO,MAAM;AAAA,QACpF;AACA,mBAAK,QAAQ,eAAb,mBAAyB;AAAA,UACvB,KAAK;AAAA,UACL,KAAK,UAAU,WAAW;AAAA;AAAA,MAE9B,OAAO;AACL,aAAK,QAAQ,IAAI;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,aAAa,WAAyB;AA3W/C;AA4WI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,UAAI,sBAA2B,EAAE,YAAY,EAAE,UAAqB,EAAE;AAEtE,cAAQ,WAAW;AAAA,QACjB,KAAK,GAAG;AAEN,gCAAsB;AAAA,YACpB,YAAY;AAAA,cACV,kBAAkB;AAAA,cAClB,gBAAgB;AAAA,gBACd,cAAc;AAAA,gBACd,eAAe;AAAA,gBACf,UAAU;AAAA,cACZ;AAAA,cACA,SAAS;AAAA,cACT,WAAW;AAAA,YACb;AAAA,UACF;AACA;AAAA,QACF;AAAA,QACA,KAAK;AACH,gCAAsB;AAAA,YACpB,YAAY;AAAA,cACV,kBAAkB;AAAA,cAClB,gBAAgB;AAAA,gBACd,cAAc;AAAA,gBACd,eAAe;AAAA,gBACf,UAAU;AAAA,cACZ;AAAA,cACA,SAAS;AAAA,cACT,WAAW;AAAA,YACb;AAAA,UACF;AACA;AAAA,MACJ;AAEA,WAAK,QAAQ,IAAI;AAAA,QACf,mDAAmD,KAAK,SAAS,OAAO,SAAS;AAAA,MACnF;AACA,iBAAK,QAAQ,eAAb,mBAAyB;AAAA,QACvB,KAAK;AAAA,QACL,KAAK,UAAU,mBAAmB;AAAA;AAAA,IAEtC;AAAA,EACF;AAAA,EAEA,MAAa,eAAe,OAA8B;AA1Z5D;AA2ZI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAEhE,YAAM,aACJ,WAAM,KAAK,QAAQ;AAAA,QACjB,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA,MAC3C,MAFA,mBAGC;AAEH,UAAI,aAAa,GAAG;AAClB,aAAK,QAAQ,IAAI;AAAA,UACf;AAAA,QACF;AACA;AAAA,MACF;AAEA,UAAI,OAAO;AACT,gBAAQ,KAAK,MAAM,KAAK;AAAA,MAC1B,OAAO;AACL,gBAAQ;AAAA,MACV;AAGA,UAAI,QAAQ,KAAK,gBAAgB;AAC/B,gBAAQ,KAAK;AAAA,MACf;AAEA,UACE,QAAQ,OACR,SAAS,MACT,SAAS,MACT,SAAS,MACT,SAAS,MACR,KAAK,cAAc,YAAY,KAAK,cAAc,WACnD;AAEA,YAAI,QAAQ,OAAO,QAAQ,IAAI;AAC7B,kBAAQ;AAAA,QACV,WAAW,QAAQ,MAAM,QAAQ,IAAI;AACnC,kBAAQ;AAAA,QACV,WAAW,QAAQ,MAAM,QAAQ,IAAI;AACnC,kBAAQ;AAAA,QACV,WAAW,QAAQ,IAAI;AACrB,kBAAQ;AAAA,QACV;AAAA,MACF;AAEA,UAAI,KAAK,QAAQ,OAAO,oBAAoB;AAC1C,cAAM,uBAAuB,MAAM,KAAK,QAAQ;AAAA,UAC9C,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA,QAC3C;AACA,YACE,wBACA,qBAAqB,OACrB,qBAAqB,OAAO,MAC5B;AACA,kBAAQ;AAAA,QACV;AAEA,cAAM,mBAAmB,MAAM,KAAK,QAAQ;AAAA,UAC1C,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA,QAC3C;AAEA,YACE,oBACA,iBAAiB,OACjB,iBAAiB,OAAO,MACxB;AACA,kBAAQ;AAAA,QACV;AAAA,MACF;AAEA,YAAM,gBACJ,WAAM,KAAK,QAAQ;AAAA,QACjB,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA,MAC3C,MAFA,mBAGC;AAEH,UAAI,gBAAgB,QAAQ,gBAAgB,QAAW;AACrD,YAAI,gBAAgB,OAAO;AACzB,gBAAM,cAAc,EAAE,YAAY,EAAE,aAAa,MAAM,EAAE;AAEzD,eAAK,QAAQ,cAAc;AAE3B,gBAAM,YAAY,oBAAI,KAAK;AAC3B,oBAAU,gBAAgB,CAAC;AAE3B,qBAAK,QAAQ,eAAb,mBAAyB;AAAA,YACvB,KAAK;AAAA,YACL,KAAK,UAAU,WAAW;AAAA;AAAA,QAE9B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEO,cAAc,OAAqB;AA1f5C;AA2fI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAEhE,UAAI,QAAQ,GAAG;AACb,aAAK,QAAQ,IAAI;AAAA,UACf,yBAAyB,KAAK;AAAA,QAChC;AACA,gBAAQ,KAAK,IAAI,KAAK;AAAA,MACxB;AAEA,UAAI,OAAO;AACT,gBAAQ,KAAK,MAAM,KAAK;AAAA,MAC1B,OAAO;AACL,gBAAQ;AAAA,MACV;AAEA,UAAI,QAAQ,GAAG;AACb,gBAAQ;AAAA,MACV,WAAW,QAAQ,KAAK,SAAS,IAAI;AACnC,gBAAQ;AAAA,MACV,WAAW,QAAQ,KAAK,eAAe;AACrC,gBAAQ,KAAK;AAAA,MACf;AAEA,UAAI,KAAK,WAAW,SAAS,QAAQ,GAAG;AAEtC,gBAAQ,KAAK,KAAK,QAAQ,GAAG,IAAI;AAAA,MACnC;AAEA,YAAM,oBAAoB,EAAE,YAAY,EAAE,YAAY,MAAM,EAAE;AAC9D,iBAAK,QAAQ,eAAb,mBAAyB;AAAA,QACvB,KAAK;AAAA,QACL,KAAK,UAAU,iBAAiB;AAAA;AAAA,IAEpC;AAAA,EACF;AAAA,EAEO,aAAa,aAA4B;AA/hBlD;AAgiBI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,YAAM,sBAAsB;AAAA,QAC1B,YAAY,EAAE,WAAW,cAAc,IAAI,EAAE;AAAA,MAC/C;AAEA,WAAK,QAAQ,IAAI;AAAA,QACf,iDAAiD,KAAK,SAAS,OAAO,WAAW;AAAA,MACnF;AACA,iBAAK,QAAQ,eAAb,mBAAyB;AAAA,QACvB,KAAK;AAAA,QACL,KAAK,UAAU,mBAAmB;AAAA;AAAA,IAEtC;AAAA,EACF;AAAA,EAEO,gBAAgB,UAAyB;AA/iBlD;AAgjBI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,YAAM,yBAAyB;AAAA,QAC7B,YAAY,EAAE,cAAc,WAAW,IAAI,EAAE;AAAA,MAC/C;AACA,WAAK,QAAQ,IAAI;AAAA,QACf,6CAA6C,KAAK,SAAS,OAAO,QAAQ;AAAA,MAC5E;AACA,iBAAK,QAAQ,eAAb,mBAAyB;AAAA,QACvB,KAAK;AAAA,QACL,KAAK,UAAU,sBAAsB;AAAA;AAAA,IAEzC;AAAA,EACF;AAAA,EAEO,6BAAmC;AA9jB5C;AA+jBI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,YAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,KAAK,SAAS;AAEtD,YAAM,gBAAgB,EAAE,YAAY,CAAC,QAAQ,EAAE;AAC/C,WAAK,QAAQ,IAAI;AAAA,QACf,gFAAgF,KAAK,SAAS;AAAA,MAChG;AACA,iBAAK,QAAQ,eAAb,mBAAyB,QAAQ,OAAO,KAAK,UAAU,aAAa;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,MAAa,qBACX,OACA,KACe;AA7kBnB;AA8kBI,UAAM,eAAe,MAAM,KAAK,QAAQ;AAAA,MACtC,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,IAAI,KAAK;AAAA,IAC/C;AAEA,YAAM,UAAK,YAAL,mBAAc;AAAA,MAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,IAAI,KAAK;AAAA,MAC7C;AAAA,MACA;AAAA;AAGF,SAAI,6CAAc,QAAO,OAAO,SAAS,aAAa;AAEpD,cAAM,UAAK,YAAL,mBAAc;AAAA,QAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,SACpC,oBAAI,KAAK,GAAE,QAAQ;AAAA,QACnB;AAAA;AAIF,YAAM,mBAAmB,MAAM,KAAK,QAAQ;AAAA,QAC1C,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACtC;AAEA,UAAI,oBAAoB,iBAAiB,OAAO,gBAAgB;AAC9D,aAAK,qBAAqB,aAAa,WAAW;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,4BACX,OACA,KACe;AA9mBnB;AAgnBI,UAAM,aAAa,QAAM,UAAK,YAAL,mBAAc;AAAA,MACrC,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,YAAY,KAAK;AAAA;AAIvD,QAAI,YAAY;AACd,cAAM,UAAK,YAAL,mBAAc;AAAA,QAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,YAAY,KAAK;AAAA,QACrD;AAAA,QACA;AAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EA2YA,MAAa,aAAa,SAAgC;AAvgC5D;AAwgCI,QAAI,UAAU,MAAM;AAClB,UAAI,KAAK,QAAQ,OAAO,gBAAgB;AACtC,aAAK,aAAa;AAAA,MACpB;AAEA,UAAI,KAAK,QAAQ,OAAO,oBAAoB;AAE1C,gBAAM,UAAK,YAAL,mBAAc;AAAA,UAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,UACpC;AAAA,UACA;AAAA;AAIF,cAAM,aACJ,WAAM,KAAK,QAAQ;AAAA,UACjB,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA,QAC3C,MAFA,mBAGC;AACH,YAAI,aAAa,GAAG;AAClB,eAAK,8BAA8B,CAAC;AAAA,QACtC,OAAO;AACL,eAAK,eAAe,CAAC;AAAA,QACvB;AAEA,YAAI,KAAK,QAAQ,OAAO,2BAA2B;AACjD,gBAAM,aAAa,MAAM,KAAK,QAAQ;AAAA,YACpC,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,UACtC;AAEA,cAAI,cAAc,OAAO,WAAW,GAAG,IAAI,IAAI;AAE7C,gBAAI,KAAK,QAAQ,OAAO,oBAAoB;AAC1C,sBAAM,UAAK,YAAL,mBAAc;AAAA,gBAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,gBACpC;AAAA,gBACA;AAAA;AAAA,YAEJ;AAAA,UACF,OAAO;AACL,gBAAI,cAAc,WAAW,KAAK;AAChC,mBAAK,kBAAkB,OAAO,WAAW,GAAG,CAAC;AAAA,YAC/C;AAGA,kBAAM,WAAW,MAAM,KAAK,QAAQ;AAAA,cAClC,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,YACtC;AAEA,gBAAI,CAAC,YAAY,OAAO,SAAS,GAAG,KAAK,GAAG;AAC1C,mBAAK,QAAQ,IAAI;AAAA,gBACf;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,WAAW,MAAM;AAE1B,YAAM,kBAAkB,MAAM,KAAK,QAAQ;AAAA,QACzC,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACtC;AAEA,UAAI,mBAAmB,gBAAgB,OAAO,MAAM;AAClD,gBAAM,UAAK,YAAL,mBAAc;AAAA,UAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,UACpC;AAAA,UACA;AAAA;AAGF,YACE,KAAK,QAAQ,OAAO,sBACpB,KAAK,QAAQ,OAAO,2BACpB;AACA,eAAK;AAAA,YACH,KAAK,QAAQ,OAAO,iBAChB,KAAK,QAAQ,OAAO,iBACpB;AAAA,UACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,kBAAwB;AAC7B,0CAAqB,QAAQ,OAAO,aAAa;AApmCrD;AAqmCM,UAAI,oBAAoB;AACxB,UAAI,qBAAqB;AACzB,UAAI,iBAAiB;AAErB,cAAQ,UAAU;AAAA,QAChB,KAAK;AACH,8BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACxD,+BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACzD,2BAAiB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACrD;AAAA,QACF,KAAK;AACH,8BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACxD,+BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACzD,2BAAiB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACrD;AAAA,QACF,KAAK;AACH,8BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACxD,+BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACzD,2BAAiB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACrD;AAAA,QACF,KAAK;AACH,8BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACxD,+BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACzD,2BAAiB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACrD;AAAA,QACF;AACE,8BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,iBAAiB,QAAQ;AACjF,+BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,iBAAiB,QAAQ;AAClF,2BAAiB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,IAAI,QAAQ;AACjE;AAAA,MACJ;AAEA,YAAM,oBACJ,QAAM,UAAK,YAAL,mBAAc,cAAc;AAEpC,YAAM,qBACJ,QAAM,UAAK,YAAL,mBAAc,cAAc;AAEpC,UAAI,EAAC,yDAAoB,SAAO,yDAAoB,QAAO,GAAG;AAE5D,gBAAM,UAAK,YAAL,mBAAc,SAAS,mBAAmB,MAAU;AAAA,MAC5D,WACE,sBACA,mBAAmB,MACnB,qBACA,kBAAkB,OAAO,UACzB,kBAAkB,OAAO,MACzB;AAEA,cAAM,YAAY;AAGlB,cAAM,iBACH,OAAO,kBAAkB,GAAG,IAAI,YAAa;AAgBhD,YAAI,iBAAiB,OAAO,mBAAmB,GAAG,IAAI;AAGtD,YAAI,iBAAiB,GAAG;AACtB,2BAAiB;AAAA,QACnB;AAEA,gBAAM,UAAK,YAAL,mBAAc,SAAS,mBAAmB,gBAAgB;AAChE,gBAAM,UAAK,YAAL,mBAAc;AAAA,UAClB;AAAA,UACA,QAAQ,iBAAiB,KAAM,QAAQ,CAAC,CAAC;AAAA,UACzC;AAAA;AAIF,aACG,YAAY,gBAAgB,YAAY,gBACzC,iBAAiB,GACjB;AACA,gBAAM,KAAK,sBAAsB,UAAU,cAAc;AAAA,QAC3D,OAAO;AACL,cAAI,YAAY,cAAc;AAC5B,oBAAM,UAAK,YAAL,mBAAc;AAAA,cAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,cACpC;AAAA,cACA;AAAA;AAAA,UAEJ,WAAW,YAAY,aAAa;AAClC,oBAAM,UAAK,YAAL,mBAAc;AAAA,cAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,cACpC;AAAA,cACA;AAAA;AAAA,UAEJ;AAAA,QACF;AAAA,MACF,WAAW,qBAAqB,oBAAoB;AAClD,gBAAM,UAAK,YAAL,mBAAc,SAAS,mBAAmB,GAAG;AACnD,gBAAM,UAAK,YAAL,mBAAc,SAAS,oBAAoB,GAAG;AAAA,MACtD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAmNA,MAAa,eAA8B;AAr6C7C;AAu6CI,YAAM,UAAK,YAAL,mBAAc;AAAA,MAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACpC;AAAA,MACA;AAAA;AAIF,UAAM,gBAAgB,MAAM,KAAK,QAAQ;AAAA,MACvC,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,IACtC;AACA,UAAM,mBAAmB,MAAM,KAAK,QAAQ;AAAA,MAC1C,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,IACtC;AAEA,UAAM,SAAS,OAAO,qDAAkB,GAAG,IAAI,OAAO,+CAAe,GAAG;AAGxE,YAAM,UAAK,YAAL,mBAAc;AAAA,MAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACpC;AAAA,MACA;AAAA;AAIF,YAAM,UAAK,YAAL,mBAAc;AAAA,MAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACpC;AAAA,MACA;AAAA;AAAA,EAEJ;AAAA,EAEA,MAAa,iBAAgC;AAt8C/C;AAu8CI,UAAM,qBAAqB,QAAM,UAAK,YAAL,mBAAc;AAAA,MAC7C,KAAK,aAAa,MAAM,KAAK,YAAY;AAAA;AAG3C,QAAI,oBAAoB;AACtB,cAAM,UAAK,YAAL,mBAAc;AAAA,QAClB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,QACpC,yDAAoB;AAAA,QACpB;AAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEO,uBAA6B;AAClC,0CAAqB,QAAQ,OAAO,aAAqB;AAr9C7D;AAs9CM,UAAI,oBAAoB;AACxB,UAAI,qBAAqB;AAEzB,UAAI,YAAY,YAAY;AAC1B,4BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACxD,6BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MAC3D,WAAW,YAAY,YAAY;AACjC,4BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACxD,6BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MAC3D,OAAO;AACL,4BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,iBAAiB,QAAQ;AACjF,6BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,iBAAiB,QAAQ;AAAA,MACpF;AAEA,cAAM,UAAK,YAAL,mBAAc,SAAS,mBAAmB,GAAG;AACnD,cAAM,UAAK,YAAL,mBAAc,SAAS,oBAAoB,GAAG;AAAA,IACtD,CAAC;AAAA,EACH;AACF;",
|
|
6
6
|
"names": ["key", "_a", "_b"]
|
|
7
7
|
}
|
|
@@ -60,6 +60,10 @@ const startCheckStatesAndConnectionJob = async (adapter) => {
|
|
|
60
60
|
"gridInputPower",
|
|
61
61
|
"packInputPower",
|
|
62
62
|
"solarInputPower",
|
|
63
|
+
"pvPower1",
|
|
64
|
+
"pvPower2",
|
|
65
|
+
"pvPower3",
|
|
66
|
+
"pvPower4",
|
|
63
67
|
"packPower"
|
|
64
68
|
];
|
|
65
69
|
let refreshAccessTokenNeeded = false;
|
|
@@ -80,13 +84,11 @@ const startCheckStatesAndConnectionJob = async (adapter) => {
|
|
|
80
84
|
const fiveMinutesAgo = (Date.now() / 1e3 - 5 * 60) * 1e3;
|
|
81
85
|
const tenMinutesAgo = (Date.now() / 1e3 - 10 * 60) * 1e3;
|
|
82
86
|
if (lastUpdate && lastUpdate.val && Number(lastUpdate.val) < tenMinutesAgo && (wifiState == null ? void 0 : wifiState.val) == "Connected" && adapter.config.connectionMode == "authKey") {
|
|
83
|
-
adapter.log.
|
|
87
|
+
adapter.log.debug(
|
|
84
88
|
`[checkStatesJob] Last update for deviceKey ${device.deviceKey} was at ${new Date(
|
|
85
89
|
Number(lastUpdate.val)
|
|
86
|
-
)}, device seems to be online - so maybe connection is broken
|
|
90
|
+
)}, device seems to be online - so maybe connection is broken!`
|
|
87
91
|
);
|
|
88
|
-
await adapter.delay(20 * 1e3);
|
|
89
|
-
adapter.restart();
|
|
90
92
|
refreshAccessTokenNeeded = true;
|
|
91
93
|
} else if (lastUpdate && lastUpdate.val && Number(lastUpdate.val) < tenMinutesAgo && (wifiState == null ? void 0 : wifiState.val) == "Connected" && adapter.config.connectionMode == "local") {
|
|
92
94
|
adapter.log.warn(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/services/jobSchedule.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\r\nimport { scheduleJob } from \"node-schedule\";\r\nimport { ZendureSolarflow } from \"../main\";\r\n\r\nexport const startRefreshAccessTokenTimerJob = async (\r\n adapter: ZendureSolarflow\r\n): Promise<void> => {\r\n // Restart adapter every 3 hours\r\n adapter.refreshAccessTokenInterval = adapter.setInterval(\r\n async () => {\r\n adapter.log.info(\r\n `Refresh Access Token - Adapter will restart in 20 seconds!`\r\n );\r\n\r\n await adapter.delay(20 * 1000);\r\n adapter.restart();\r\n },\r\n 3 * 60 * 60 * 1000\r\n );\r\n};\r\n\r\nexport const startResetValuesJob = async (\r\n adapter: ZendureSolarflow\r\n): Promise<void> => {\r\n adapter.resetValuesJob = scheduleJob(\"5 0 0 * * *\", () => {\r\n // Reset Values\r\n adapter.zenHaDeviceList.forEach((device) => {\r\n device.resetValuesForDevice();\r\n });\r\n });\r\n};\r\n\r\nexport const startCalculationJob = async (\r\n adapter: ZendureSolarflow\r\n): Promise<void> => {\r\n adapter.calculationJob = scheduleJob(\"*/30 * * * * *\", () => {\r\n adapter.zenHaDeviceList.forEach((device) => {\r\n if (device.productKey != \"s3Xk4x\") {\r\n device.calculateEnergy();\r\n }\r\n });\r\n });\r\n};\r\n\r\nexport const startCheckStatesAndConnectionJob = async (\r\n adapter: ZendureSolarflow\r\n): Promise<void> => {\r\n // Check for states that has no updates in the last 5 minutes and set them to 0\r\n const statesToReset: string[] = [\r\n \"outputHomePower\",\r\n \"outputPackPower\",\r\n \"gridInputPower\",\r\n \"packInputPower\",\r\n \"solarInputPower\",\r\n \"packPower\",\r\n ];\r\n\r\n let refreshAccessTokenNeeded = false;\r\n\r\n adapter.log.debug(\r\n `[checkStatesJob] Starting check of states and connection!`\r\n );\r\n\r\n adapter.checkStatesJob = scheduleJob(\"*/5 * * * *\", async () => {\r\n adapter.zenHaDeviceList.forEach(async (device) => {\r\n if (refreshAccessTokenNeeded) {\r\n return;\r\n }\r\n\r\n const lastUpdate = await adapter?.getStateAsync(\r\n device.productKey + \".\" + device.deviceKey + \".lastUpdate\"\r\n );\r\n\r\n const wifiState = await adapter?.getStateAsync(\r\n device.productKey + \".\" + device.deviceKey + \".wifiState\"\r\n );\r\n\r\n const fiveMinutesAgo = (Date.now() / 1000 - 5 * 60) * 1000; // Five minutes ago\r\n const tenMinutesAgo = (Date.now() / 1000 - 10 * 60) * 1000; // Thirty minutes ago\r\n\r\n if (\r\n lastUpdate &&\r\n lastUpdate.val &&\r\n Number(lastUpdate.val) < tenMinutesAgo &&\r\n wifiState?.val == \"Connected\" &&\r\n adapter.config.connectionMode == \"authKey\"\r\n ) {\r\n adapter.log.
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,2BAA4B;AAGrB,MAAM,kCAAkC,OAC7C,YACkB;AAElB,UAAQ,6BAA6B,QAAQ;AAAA,IAC3C,YAAY;AACV,cAAQ,IAAI;AAAA,QACV;AAAA,MACF;AAEA,YAAM,QAAQ,MAAM,KAAK,GAAI;AAC7B,cAAQ,QAAQ;AAAA,IAClB;AAAA,IACA,IAAI,KAAK,KAAK;AAAA,EAChB;AACF;AAEO,MAAM,sBAAsB,OACjC,YACkB;AAClB,UAAQ,qBAAiB,kCAAY,eAAe,MAAM;AAExD,YAAQ,gBAAgB,QAAQ,CAAC,WAAW;AAC1C,aAAO,qBAAqB;AAAA,IAC9B,CAAC;AAAA,EACH,CAAC;AACH;AAEO,MAAM,sBAAsB,OACjC,YACkB;AAClB,UAAQ,qBAAiB,kCAAY,kBAAkB,MAAM;AAC3D,YAAQ,gBAAgB,QAAQ,CAAC,WAAW;AAC1C,UAAI,OAAO,cAAc,UAAU;AACjC,eAAO,gBAAgB;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAEO,MAAM,mCAAmC,OAC9C,YACkB;AAElB,QAAM,gBAA0B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,2BAA2B;AAE/B,UAAQ,IAAI;AAAA,IACV;AAAA,EACF;AAEA,UAAQ,qBAAiB,kCAAY,eAAe,YAAY;AAC9D,YAAQ,gBAAgB,QAAQ,OAAO,WAAW;AAChD,UAAI,0BAA0B;AAC5B;AAAA,MACF;AAEA,YAAM,aAAa,OAAM,mCAAS;AAAA,QAChC,OAAO,aAAa,MAAM,OAAO,YAAY;AAAA;AAG/C,YAAM,YAAY,OAAM,mCAAS;AAAA,QAC/B,OAAO,aAAa,MAAM,OAAO,YAAY;AAAA;AAG/C,YAAM,kBAAkB,KAAK,IAAI,IAAI,MAAO,IAAI,MAAM;AACtD,YAAM,iBAAiB,KAAK,IAAI,IAAI,MAAO,KAAK,MAAM;AAEtD,UACE,cACA,WAAW,OACX,OAAO,WAAW,GAAG,IAAI,kBACzB,uCAAW,QAAO,eAClB,QAAQ,OAAO,kBAAkB,WACjC;AACA,gBAAQ,IAAI;AAAA,UACV,8CACE,OAAO,SACT,WAAW,IAAI;AAAA,YACb,OAAO,WAAW,GAAG;AAAA,UACvB,CAAC;AAAA,QACH;
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\r\nimport { scheduleJob } from \"node-schedule\";\r\nimport { ZendureSolarflow } from \"../main\";\r\n\r\nexport const startRefreshAccessTokenTimerJob = async (\r\n adapter: ZendureSolarflow\r\n): Promise<void> => {\r\n // Restart adapter every 3 hours\r\n adapter.refreshAccessTokenInterval = adapter.setInterval(\r\n async () => {\r\n adapter.log.info(\r\n `Refresh Access Token - Adapter will restart in 20 seconds!`\r\n );\r\n\r\n await adapter.delay(20 * 1000);\r\n adapter.restart();\r\n },\r\n 3 * 60 * 60 * 1000\r\n );\r\n};\r\n\r\nexport const startResetValuesJob = async (\r\n adapter: ZendureSolarflow\r\n): Promise<void> => {\r\n adapter.resetValuesJob = scheduleJob(\"5 0 0 * * *\", () => {\r\n // Reset Values\r\n adapter.zenHaDeviceList.forEach((device) => {\r\n device.resetValuesForDevice();\r\n });\r\n });\r\n};\r\n\r\nexport const startCalculationJob = async (\r\n adapter: ZendureSolarflow\r\n): Promise<void> => {\r\n adapter.calculationJob = scheduleJob(\"*/30 * * * * *\", () => {\r\n adapter.zenHaDeviceList.forEach((device) => {\r\n if (device.productKey != \"s3Xk4x\") {\r\n device.calculateEnergy();\r\n }\r\n });\r\n });\r\n};\r\n\r\nexport const startCheckStatesAndConnectionJob = async (\r\n adapter: ZendureSolarflow\r\n): Promise<void> => {\r\n // Check for states that has no updates in the last 5 minutes and set them to 0\r\n const statesToReset: string[] = [\r\n \"outputHomePower\",\r\n \"outputPackPower\",\r\n \"gridInputPower\",\r\n \"packInputPower\",\r\n \"solarInputPower\",\r\n \"pvPower1\",\r\n \"pvPower2\",\r\n \"pvPower3\",\r\n \"pvPower4\",\r\n \"packPower\",\r\n ];\r\n\r\n let refreshAccessTokenNeeded = false;\r\n\r\n adapter.log.debug(\r\n `[checkStatesJob] Starting check of states and connection!`\r\n );\r\n\r\n adapter.checkStatesJob = scheduleJob(\"*/5 * * * *\", async () => {\r\n adapter.zenHaDeviceList.forEach(async (device) => {\r\n if (refreshAccessTokenNeeded) {\r\n return;\r\n }\r\n\r\n const lastUpdate = await adapter?.getStateAsync(\r\n device.productKey + \".\" + device.deviceKey + \".lastUpdate\"\r\n );\r\n\r\n const wifiState = await adapter?.getStateAsync(\r\n device.productKey + \".\" + device.deviceKey + \".wifiState\"\r\n );\r\n\r\n const fiveMinutesAgo = (Date.now() / 1000 - 5 * 60) * 1000; // Five minutes ago\r\n const tenMinutesAgo = (Date.now() / 1000 - 10 * 60) * 1000; // Thirty minutes ago\r\n\r\n if (\r\n lastUpdate &&\r\n lastUpdate.val &&\r\n Number(lastUpdate.val) < tenMinutesAgo &&\r\n wifiState?.val == \"Connected\" &&\r\n adapter.config.connectionMode == \"authKey\"\r\n ) {\r\n adapter.log.debug(\r\n `[checkStatesJob] Last update for deviceKey ${\r\n device.deviceKey\r\n } was at ${new Date(\r\n Number(lastUpdate.val)\r\n )}, device seems to be online - so maybe connection is broken!`\r\n );\r\n\r\n //await adapter.delay(20 * 1000);\r\n //adapter.restart();\r\n\r\n // set marker, so we discontinue the forEach Loop because of reconnect!\r\n refreshAccessTokenNeeded = true;\r\n } else if (\r\n lastUpdate &&\r\n lastUpdate.val &&\r\n Number(lastUpdate.val) < tenMinutesAgo &&\r\n wifiState?.val == \"Connected\" &&\r\n adapter.config.connectionMode == \"local\"\r\n ) {\r\n adapter.log.warn(\r\n `[checkStatesJob] Last update for deviceKey ${\r\n device.deviceKey\r\n } was at ${new Date(\r\n Number(lastUpdate.val)\r\n )}, set Wifi state to Disconnected!`\r\n );\r\n\r\n device?.updateSolarFlowState(\"wifiState\", \"Disconnected\");\r\n }\r\n\r\n if (\r\n lastUpdate &&\r\n lastUpdate.val &&\r\n Number(lastUpdate.val) < fiveMinutesAgo &&\r\n !refreshAccessTokenNeeded\r\n ) {\r\n adapter.log.debug(\r\n `[checkStatesJob] Last update for deviceKey ${\r\n device.deviceKey\r\n } was at ${new Date(\r\n Number(lastUpdate.val)\r\n )}, checking for pseudo power values!`\r\n );\r\n // State was not updated in the last 5 minutes... set states to 0\r\n await statesToReset.forEach(async (stateName: string) => {\r\n await adapter?.setState(\r\n device.productKey + \".\" + device.deviceKey + \".\" + stateName,\r\n 0,\r\n true\r\n );\r\n });\r\n }\r\n });\r\n });\r\n};\r\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,2BAA4B;AAGrB,MAAM,kCAAkC,OAC7C,YACkB;AAElB,UAAQ,6BAA6B,QAAQ;AAAA,IAC3C,YAAY;AACV,cAAQ,IAAI;AAAA,QACV;AAAA,MACF;AAEA,YAAM,QAAQ,MAAM,KAAK,GAAI;AAC7B,cAAQ,QAAQ;AAAA,IAClB;AAAA,IACA,IAAI,KAAK,KAAK;AAAA,EAChB;AACF;AAEO,MAAM,sBAAsB,OACjC,YACkB;AAClB,UAAQ,qBAAiB,kCAAY,eAAe,MAAM;AAExD,YAAQ,gBAAgB,QAAQ,CAAC,WAAW;AAC1C,aAAO,qBAAqB;AAAA,IAC9B,CAAC;AAAA,EACH,CAAC;AACH;AAEO,MAAM,sBAAsB,OACjC,YACkB;AAClB,UAAQ,qBAAiB,kCAAY,kBAAkB,MAAM;AAC3D,YAAQ,gBAAgB,QAAQ,CAAC,WAAW;AAC1C,UAAI,OAAO,cAAc,UAAU;AACjC,eAAO,gBAAgB;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAEO,MAAM,mCAAmC,OAC9C,YACkB;AAElB,QAAM,gBAA0B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,2BAA2B;AAE/B,UAAQ,IAAI;AAAA,IACV;AAAA,EACF;AAEA,UAAQ,qBAAiB,kCAAY,eAAe,YAAY;AAC9D,YAAQ,gBAAgB,QAAQ,OAAO,WAAW;AAChD,UAAI,0BAA0B;AAC5B;AAAA,MACF;AAEA,YAAM,aAAa,OAAM,mCAAS;AAAA,QAChC,OAAO,aAAa,MAAM,OAAO,YAAY;AAAA;AAG/C,YAAM,YAAY,OAAM,mCAAS;AAAA,QAC/B,OAAO,aAAa,MAAM,OAAO,YAAY;AAAA;AAG/C,YAAM,kBAAkB,KAAK,IAAI,IAAI,MAAO,IAAI,MAAM;AACtD,YAAM,iBAAiB,KAAK,IAAI,IAAI,MAAO,KAAK,MAAM;AAEtD,UACE,cACA,WAAW,OACX,OAAO,WAAW,GAAG,IAAI,kBACzB,uCAAW,QAAO,eAClB,QAAQ,OAAO,kBAAkB,WACjC;AACA,gBAAQ,IAAI;AAAA,UACV,8CACE,OAAO,SACT,WAAW,IAAI;AAAA,YACb,OAAO,WAAW,GAAG;AAAA,UACvB,CAAC;AAAA,QACH;AAMA,mCAA2B;AAAA,MAC7B,WACE,cACA,WAAW,OACX,OAAO,WAAW,GAAG,IAAI,kBACzB,uCAAW,QAAO,eAClB,QAAQ,OAAO,kBAAkB,SACjC;AACA,gBAAQ,IAAI;AAAA,UACV,8CACE,OAAO,SACT,WAAW,IAAI;AAAA,YACb,OAAO,WAAW,GAAG;AAAA,UACvB,CAAC;AAAA,QACH;AAEA,yCAAQ,qBAAqB,aAAa;AAAA,MAC5C;AAEA,UACE,cACA,WAAW,OACX,OAAO,WAAW,GAAG,IAAI,kBACzB,CAAC,0BACD;AACA,gBAAQ,IAAI;AAAA,UACV,8CACE,OAAO,SACT,WAAW,IAAI;AAAA,YACb,OAAO,WAAW,GAAG;AAAA,UACvB,CAAC;AAAA,QACH;AAEA,cAAM,cAAc,QAAQ,OAAO,cAAsB;AACvD,iBAAM,mCAAS;AAAA,YACb,OAAO,aAAa,MAAM,OAAO,YAAY,MAAM;AAAA,YACnD;AAAA,YACA;AAAA;AAAA,QAEJ,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -72,7 +72,6 @@ const zenLogin = async (adapter) => {
|
|
|
72
72
|
};
|
|
73
73
|
return import_axios.default.post(`${apiUrl}/api/ha/deviceList`, JSON.stringify(body), config).then(async function(response) {
|
|
74
74
|
const data = await response.data;
|
|
75
|
-
adapter.log.error(data);
|
|
76
75
|
return data.data;
|
|
77
76
|
}).catch(async function(error) {
|
|
78
77
|
if (error.response) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/services/zenWebService.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\nimport axios, { AxiosRequestConfig } from \"axios\";\nimport { haKey } from \"../constants/constants\";\nimport { ZendureSolarflow } from \"../main\";\nimport * as crypto from \"crypto\";\nimport { IHaDeviceListData } from \"../models/IHaDeviceListData\";\n\nexport const zenLogin = async (\n adapter: ZendureSolarflow\n): Promise<string | IHaDeviceListData | undefined> => {\n const decodedAuthCloudKey = Buffer.from(\n adapter.config.authorizationCloudKey,\n \"base64\"\n ).toString(\"utf-8\");\n\n const lastDot = decodedAuthCloudKey.lastIndexOf(\".\");\n if (lastDot === -1) {\n // Invalid\n }\n\n const apiUrl = decodedAuthCloudKey.slice(0, lastDot);\n const appKey = decodedAuthCloudKey.slice(lastDot + 1);\n\n const body = {\n appKey: appKey,\n };\n\n // Timestamp und Nonce\n const timestamp = Math.floor(Date.now() / 1000);\n const nonce = (Math.floor(Math.random() * 90000) + 10000).toString();\n\n // Signatur-Parameter\n const signParams: Record<string, string | number> = {\n ...body,\n timestamp: timestamp,\n nonce: nonce,\n };\n\n // Signatur-String erstellen\n const bodyStr = Object.keys(signParams)\n .sort()\n .map((k) => `${k}${signParams[k]}`)\n .join(\"\");\n\n const signStr = `${haKey}${bodyStr}${haKey}`;\n\n // SHA1-Hash berechnen\n const sha1 = crypto.createHash(\"sha1\");\n sha1.update(signStr, \"utf8\");\n const sign = sha1.digest(\"hex\").toUpperCase();\n\n // Header bauen\n const headers = {\n \"Content-Type\": \"application/json\",\n timestamp: timestamp.toString(),\n nonce: nonce,\n clientid: \"zenHa\",\n sign: sign,\n };\n\n const config: AxiosRequestConfig = {\n headers: headers,\n timeout: 10000,\n };\n\n // Request\n return axios\n .post(`${apiUrl}/api/ha/deviceList`, JSON.stringify(body), config)\n .then(async function (response) {\n const data = await response.data;\n\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA0C;AAC1C,uBAAsB;AAEtB,aAAwB;AAGjB,MAAM,WAAW,OACtB,YACoD;AACpD,QAAM,sBAAsB,OAAO;AAAA,IACjC,QAAQ,OAAO;AAAA,IACf;AAAA,EACF,EAAE,SAAS,OAAO;AAElB,QAAM,UAAU,oBAAoB,YAAY,GAAG;AACnD,MAAI,YAAY,IAAI;AAAA,EAEpB;AAEA,QAAM,SAAS,oBAAoB,MAAM,GAAG,OAAO;AACnD,QAAM,SAAS,oBAAoB,MAAM,UAAU,CAAC;AAEpD,QAAM,OAAO;AAAA,IACX;AAAA,EACF;AAGA,QAAM,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC9C,QAAM,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,GAAK,IAAI,KAAO,SAAS;AAGnE,QAAM,aAA8C;AAAA,IAClD,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAGA,QAAM,UAAU,OAAO,KAAK,UAAU,EACnC,KAAK,EACL,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,EACjC,KAAK,EAAE;AAEV,QAAM,UAAU,GAAG,sBAAK,GAAG,OAAO,GAAG,sBAAK;AAG1C,QAAM,OAAO,OAAO,WAAW,MAAM;AACrC,OAAK,OAAO,SAAS,MAAM;AAC3B,QAAM,OAAO,KAAK,OAAO,KAAK,EAAE,YAAY;AAG5C,QAAM,UAAU;AAAA,IACd,gBAAgB;AAAA,IAChB,WAAW,UAAU,SAAS;AAAA,IAC9B;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACF;AAEA,QAAM,SAA6B;AAAA,IACjC;AAAA,IACA,SAAS;AAAA,EACX;AAGA,SAAO,aAAAA,QACJ,KAAK,GAAG,MAAM,sBAAsB,KAAK,UAAU,IAAI,GAAG,MAAM,EAChE,KAAK,eAAgB,UAAU;AAC9B,UAAM,OAAO,MAAM,SAAS;AAE5B,
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\nimport axios, { AxiosRequestConfig } from \"axios\";\nimport { haKey } from \"../constants/constants\";\nimport { ZendureSolarflow } from \"../main\";\nimport * as crypto from \"crypto\";\nimport { IHaDeviceListData } from \"../models/IHaDeviceListData\";\n\nexport const zenLogin = async (\n adapter: ZendureSolarflow\n): Promise<string | IHaDeviceListData | undefined> => {\n const decodedAuthCloudKey = Buffer.from(\n adapter.config.authorizationCloudKey,\n \"base64\"\n ).toString(\"utf-8\");\n\n const lastDot = decodedAuthCloudKey.lastIndexOf(\".\");\n if (lastDot === -1) {\n // Invalid\n }\n\n const apiUrl = decodedAuthCloudKey.slice(0, lastDot);\n const appKey = decodedAuthCloudKey.slice(lastDot + 1);\n\n const body = {\n appKey: appKey,\n };\n\n // Timestamp und Nonce\n const timestamp = Math.floor(Date.now() / 1000);\n const nonce = (Math.floor(Math.random() * 90000) + 10000).toString();\n\n // Signatur-Parameter\n const signParams: Record<string, string | number> = {\n ...body,\n timestamp: timestamp,\n nonce: nonce,\n };\n\n // Signatur-String erstellen\n const bodyStr = Object.keys(signParams)\n .sort()\n .map((k) => `${k}${signParams[k]}`)\n .join(\"\");\n\n const signStr = `${haKey}${bodyStr}${haKey}`;\n\n // SHA1-Hash berechnen\n const sha1 = crypto.createHash(\"sha1\");\n sha1.update(signStr, \"utf8\");\n const sign = sha1.digest(\"hex\").toUpperCase();\n\n // Header bauen\n const headers = {\n \"Content-Type\": \"application/json\",\n timestamp: timestamp.toString(),\n nonce: nonce,\n clientid: \"zenHa\",\n sign: sign,\n };\n\n const config: AxiosRequestConfig = {\n headers: headers,\n timeout: 10000,\n };\n\n // Request\n return axios\n .post(`${apiUrl}/api/ha/deviceList`, JSON.stringify(body), config)\n .then(async function (response) {\n const data = await response.data;\n\n return data.data;\n })\n .catch(async function (error) {\n if (error.response) {\n // The request was made and the server responded with a status code\n // that falls out of the range of 2xx\n adapter.log.error(error.response.data);\n adapter.log.error(error.response.status);\n adapter.log.error(error.response.headers);\n } else if (error.request) {\n // The request was made but no response was received\n // `error.request` is an instance of XMLHttpRequest in the browser and an instance of\n // http.ClientRequest in node.js\n adapter.log.error(error.request);\n } else {\n // Something happened in setting up the request that triggered an Error\n adapter.log.error(\"Error\" + error.message);\n }\n adapter.log.error(error.config);\n });\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA0C;AAC1C,uBAAsB;AAEtB,aAAwB;AAGjB,MAAM,WAAW,OACtB,YACoD;AACpD,QAAM,sBAAsB,OAAO;AAAA,IACjC,QAAQ,OAAO;AAAA,IACf;AAAA,EACF,EAAE,SAAS,OAAO;AAElB,QAAM,UAAU,oBAAoB,YAAY,GAAG;AACnD,MAAI,YAAY,IAAI;AAAA,EAEpB;AAEA,QAAM,SAAS,oBAAoB,MAAM,GAAG,OAAO;AACnD,QAAM,SAAS,oBAAoB,MAAM,UAAU,CAAC;AAEpD,QAAM,OAAO;AAAA,IACX;AAAA,EACF;AAGA,QAAM,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC9C,QAAM,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,GAAK,IAAI,KAAO,SAAS;AAGnE,QAAM,aAA8C;AAAA,IAClD,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAGA,QAAM,UAAU,OAAO,KAAK,UAAU,EACnC,KAAK,EACL,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,EACjC,KAAK,EAAE;AAEV,QAAM,UAAU,GAAG,sBAAK,GAAG,OAAO,GAAG,sBAAK;AAG1C,QAAM,OAAO,OAAO,WAAW,MAAM;AACrC,OAAK,OAAO,SAAS,MAAM;AAC3B,QAAM,OAAO,KAAK,OAAO,KAAK,EAAE,YAAY;AAG5C,QAAM,UAAU;AAAA,IACd,gBAAgB;AAAA,IAChB,WAAW,UAAU,SAAS;AAAA,IAC9B;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACF;AAEA,QAAM,SAA6B;AAAA,IACjC;AAAA,IACA,SAAS;AAAA,EACX;AAGA,SAAO,aAAAA,QACJ,KAAK,GAAG,MAAM,sBAAsB,KAAK,UAAU,IAAI,GAAG,MAAM,EAChE,KAAK,eAAgB,UAAU;AAC9B,UAAM,OAAO,MAAM,SAAS;AAE5B,WAAO,KAAK;AAAA,EACd,CAAC,EACA,MAAM,eAAgB,OAAO;AAC5B,QAAI,MAAM,UAAU;AAGlB,cAAQ,IAAI,MAAM,MAAM,SAAS,IAAI;AACrC,cAAQ,IAAI,MAAM,MAAM,SAAS,MAAM;AACvC,cAAQ,IAAI,MAAM,MAAM,SAAS,OAAO;AAAA,IAC1C,WAAW,MAAM,SAAS;AAIxB,cAAQ,IAAI,MAAM,MAAM,OAAO;AAAA,IACjC,OAAO;AAEL,cAAQ,IAAI,MAAM,UAAU,MAAM,OAAO;AAAA,IAC3C;AACA,YAAQ,IAAI,MAAM,MAAM,MAAM;AAAA,EAChC,CAAC;AACL;",
|
|
6
6
|
"names": ["axios"]
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "zendure-solarflow",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.2.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"3.2.0": {
|
|
7
|
+
"en": "Fix inputLimit on certain devices\nFix calculation of PV3 & 4 again (hopefully now 100%)\nAdd some more specific debug messages\nRemove misleading error message on adapter start\nReplace restart on checkStatesJob with a debug message (I think Zendure cloud is stable now)\nUpdate adapter to adapter-react-v5 (MUI v5)\nFix commandbar in settings",
|
|
8
|
+
"de": "EingabeLimit auf bestimmte Geräte fixieren\nFixe Berechnung von PV3 & 4 wieder (hoffentlich jetzt 100%)\nFügen Sie einige spezifische Debug-Nachrichten hinzu\nEntfernen irreführende Fehlermeldung auf Adapterstart\nWiederstart ersetzen StatesJob mit einer Debug-Nachricht (ich glaube, Zendure Cloud ist jetzt stabil)\nUpdate-Adapter auf Adapter-React-v5 (MUI v5)\nBefehlsleiste in Einstellungen festlegen",
|
|
9
|
+
"ru": "Исправьте входное ограничение на определенных устройствах\nИсправьте расчет PV3 и 4 снова (надеюсь, теперь 100%)\nДобавьте более конкретные сообщения отладки\nУдалить вводящее в заблуждение сообщение об ошибке при запуске адаптера\nЗаменить перезапуск на проверку StatesJob с сообщением отладки (я думаю, что облако Zendure теперь стабильно)\nАдаптер обновления для адаптера-реакции-v5 (MUI v5)\nFix Commandbar в настройках",
|
|
10
|
+
"pt": "Corrigir a entradaLimit em certos dispositivos\nCorrigir o cálculo de PV3 & 4 novamente (esperançosamente agora 100%)\nAdicionar algumas mensagens de depuração mais específicas\nRemover a mensagem de erro enganosa no início do adaptador\nSubstituir reiniciar na verificação StatesJob com uma mensagem de depuração (Eu acho que a nuvem Zendure está estável agora)\nAtualizar adaptador para adaptador-react-v5 (MUI v5)\nCorrigir a barra de comandos nas configurações",
|
|
11
|
+
"nl": "Repareren inputLimit op bepaalde apparaten\nFix berekening van PV3 & 4 weer (hopelijk nu 100%)\nMeer specifieke debug-berichten toevoegen\nVerwijder misleidende foutmelding bij het starten van de adapter\nHerstart vervangen bij controle StatesJob met een debug bericht (Ik denk dat Zendure cloud nu stabiel is)\nUpdate adapter naar adapter-react-v5 (MUI v5)\nCommandbar in instellingen herstellen",
|
|
12
|
+
"fr": "Correction de l'entréeLimit sur certains appareils\nFixer à nouveau le calcul de PV3 & 4 (avec espoir maintenant 100%)\nAjouter des messages de débogage plus spécifiques\nSupprimer le message d'erreur trompeuse lors du démarrage de l'adaptateur\nRemplacer le redémarrage lors de la vérification StatesJob avec un message de débogage (je pense que le nuage Zendure est stable maintenant)\nMettre à jour l'adaptateur pour adapter-réaction-v5 (MUI v5)\nCorrection de la barre de commande dans les paramètres",
|
|
13
|
+
"it": "Fissare inputLimit su determinati dispositivi\nFissare il calcolo di PV3 & 4 di nuovo (si spera ora 100%)\nAggiungi alcuni messaggi di debug più specifici\nRimuovere il messaggio di errore fuorviante sull'avvio dell'adattatore\nSostituisci il riavvio al controllo StateJob con un messaggio debug (Penso che il cloud Zendure sia stabile ora)\nAdattatore di aggiornamento per adattatore-react-v5 (MUI v5)\nFissare la barra di comando nelle impostazioni",
|
|
14
|
+
"es": "Fijar entradaLimitar en ciertos dispositivos\nFijar el cálculo de PV3 & 4 de nuevo (esperadamente ahora 100%)\nAgregar algunos mensajes de depuración más específicos\nEliminar el mensaje de error engañoso en el comienzo del adaptador\nReemplace reiniciar el cheque StatesJob con un mensaje de depuración (creo que la nube Zendure está estable ahora)\nAdaptador de actualización para adaptador-react-v5 (MUI v5)\nFijar barra de comandos en los ajustes",
|
|
15
|
+
"pl": "Fix inputLimit na niektórych urządzeniach\nPopraw obliczenia PV3 & 4 ponownie (miejmy nadzieję, że teraz 100%)\nDodaj kilka bardziej szczegółowych wiadomości debugowania\nUsuń mylący komunikat błędu przy uruchomieniu adaptera\nZastąp ponowne uruchomienie podczas kontroli States Job z komunikatem o debugowaniu (myślę, że chmura Zabb jest teraz stabilna)\nAktualizuj adapter do adaptacji- react- v5 (MUI v5)\nNapraw pasek poleceń w ustawieniach",
|
|
16
|
+
"uk": "Фіксувати вхідОблік на певних пристроях\nФіксований розрахунок ПВ3 та 4 знову (повно зараз 100%)\nДодати більше специфічних повідомлень\nВидаліть повідомлення про помилку в оману на адаптері\nЗамініть перезапуск на перевірку USAJob з повідомленням debug (Я думаю, що хмара Zendure стабільний зараз)\nОновлення адаптера до адаптера-реакт-v5 (MUI v5)\nВиправлення командного рядка в налаштуваннях",
|
|
17
|
+
"zh-cn": "在某些设备上固定输入范围\n再次修复光电3 & 4 的计算( 希望现在100%)\n添加一些更具体的调试消息\n删除适配器启动时的错误消息\n检查时替换重新启动 有调试消息的国家Job(我认为Zendure云已经稳定了)\n更新适配器到适配器-反应-v5(MUI v5)\n在设置中修正命令栏"
|
|
18
|
+
},
|
|
19
|
+
"3.1.1": {
|
|
20
|
+
"en": "Fix Uppercase 'a4ss5p' in helpers.ts",
|
|
21
|
+
"de": "Großbuchstaben 'a4ss5p' in helpers.ts",
|
|
22
|
+
"ru": "Исправьте Uppercase 'a4ss5p' в helpers.ts",
|
|
23
|
+
"pt": "Corrigir 'a4ss5p' em helpers.ts",
|
|
24
|
+
"nl": "Fix Uppercase 'a4ss5p' in helpers.ts",
|
|
25
|
+
"fr": "Correction de la case supérieure 'a4ss5p' dans aideurs.ts",
|
|
26
|
+
"it": "Fissare Uppercase 'a4ss5p' in helpers.ts",
|
|
27
|
+
"es": "Fijar maleta superior 'a4s5p' en helpers.ts",
|
|
28
|
+
"pl": "Fix Uppercase 'a4ss5p' in helpers.ts",
|
|
29
|
+
"uk": "Фіксація Верхній регістр 'a4ss5p' в помічниках.ts",
|
|
30
|
+
"zh-cn": "在助手.ts中修正大写“ a4ss5p ”"
|
|
31
|
+
},
|
|
6
32
|
"3.1.0": {
|
|
7
33
|
"en": "Fix setInputLimit (always use positive value!)\nAdd calculation states for PV3 & PV4 (used by SF 800 Pro)\nFix Uppercase 'a4ss5p' in helpers.ts",
|
|
8
34
|
"de": "Fix setInputLimit (verwendet immer positiven Wert!)\nBerechnungszustände für PV3 & PV4 (verwendet durch SF 800 Pro) hinzufügen\nGroßbuchstaben 'a4ss5p' in helpers.ts",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "Fix inputLimit wydania\nNaprawianie stanu Wifi nie aktualizuje się przy zmianie PackData",
|
|
68
94
|
"uk": "Виправлення вхідного номера\nВиправлення стану Wifi не оновлення при зміні пакетаData",
|
|
69
95
|
"zh-cn": "修正输入范围\nBackData 更改时不更新 Wifi 状态"
|
|
70
|
-
},
|
|
71
|
-
"3.0.3": {
|
|
72
|
-
"en": "Optimize setting of wifiMode in local mode\nOptimize Debug option",
|
|
73
|
-
"de": "Optimieren Sie die Einstellung von wifiMode im lokalen Modus\nOptimierung der Debug-Option",
|
|
74
|
-
"ru": "Оптимизируйте настройку WiFiMode в локальном режиме\nОптимизируйте опцию Debug",
|
|
75
|
-
"pt": "Otimizar a configuração do wifiMode no modo local\nOtimizar a opção de depuração",
|
|
76
|
-
"nl": "Optimaliseer de instelling van wifiMode in lokale modus\nOptimaliseer debug-optie",
|
|
77
|
-
"fr": "Optimiser le réglage du wifiMode en mode local\nOptimiser l'option de débogage",
|
|
78
|
-
"it": "Ottimizzare l'impostazione di wifiMode in modalità locale\nOttimizzare l'opzione Debug",
|
|
79
|
-
"es": "Optimize setting of wifiMode in local mode\nOpción Optimize Debug",
|
|
80
|
-
"pl": "Optymalizacja ustawień WifiMode w trybie lokalnym\nOptymalizacja opcji debugowania",
|
|
81
|
-
"uk": "Оптимізуйте налаштування wifiMode в локальному режимі\nОптимізуйте опцію Debug",
|
|
82
|
-
"zh-cn": "优化本地模式的 wifiMode 设置\n优化调试选项"
|
|
83
|
-
},
|
|
84
|
-
"3.0.2": {
|
|
85
|
-
"en": "Ignore 'wifiState' for last update value",
|
|
86
|
-
"de": "'wifiState' für den letzten Updatewert ignorieren",
|
|
87
|
-
"ru": "Игнорируйте значение «wifiState» для последнего обновления",
|
|
88
|
-
"pt": "Ignorar 'wifiState' para o valor da última atualização",
|
|
89
|
-
"nl": "'wifiState' negeren voor laatste updatewaarde",
|
|
90
|
-
"fr": "Ignorer 'wifiState' pour la dernière valeur de mise à jour",
|
|
91
|
-
"it": "Ignora 'wifiState' per l'ultimo valore di aggiornamento",
|
|
92
|
-
"es": "Ignora 'wifiState' por último valor de actualización",
|
|
93
|
-
"pl": "Ignoruj 'wifiState' dla ostatniej wartości aktualizacji",
|
|
94
|
-
"uk": "Ignore 'wifiState' для останнього оновлення значення",
|
|
95
|
-
"zh-cn": "忽略上次更新值的“ wifi State ”"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|