iobroker.zendure-solarflow 3.0.2 → 3.0.3
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 +5 -0
- package/build/helpers/helpers.js.map +2 -2
- package/build/models/deviceModels/ZenHaDevice.js +6 -0
- package/build/models/deviceModels/ZenHaDevice.js.map +2 -2
- package/build/services/jobSchedule.js +3 -5
- package/build/services/jobSchedule.js.map +2 -2
- package/io-package.json +14 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,6 +59,11 @@ On a HUB 1200 / HUB 2000 / ACE 1500 combination you have to use '**setDeviceAuto
|
|
|
59
59
|
This adapter will now use the Cloud Authorization Code for authentication on the official mqtt servers, which you can generate in the Zendure app!
|
|
60
60
|
|
|
61
61
|
## Changelog
|
|
62
|
+
### 3.0.3 (2025-10-07)
|
|
63
|
+
|
|
64
|
+
- Optimize setting of wifiMode in local mode
|
|
65
|
+
- Optimize Debug option
|
|
66
|
+
|
|
62
67
|
### 3.0.2 (2025-10-06)
|
|
63
68
|
|
|
64
69
|
- Ignore 'wifiState' for last update value
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/helpers/helpers.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\n\nimport { ZendureSolarflow } from \"../main\";\nimport { Ace1500 } from \"../models/deviceModels/Ace1500\";\nimport { Aio2400 } from \"../models/deviceModels/Aio2400\";\nimport { Hyper2000 } from \"../models/deviceModels/Hyper2000\";\nimport { Sf2400Ac } from \"../models/deviceModels/Sf2400Ac\";\nimport { Sf800 } from \"../models/deviceModels/Sf800\";\nimport { SfHub1200 } from \"../models/deviceModels/SfHub1200\";\nimport { SfHub2000 } from \"../models/deviceModels/SfHub2000\";\n\nimport { IZenHaDeviceDetails } from \"../models/IZenHaDeviceDetails\";\n\nexport const createDeviceModel = (\n _adapter: ZendureSolarflow,\n _productKey: string,\n _deviceKey: string,\n _zenHaDeviceDetails?: IZenHaDeviceDetails\n)
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAwB;AACxB,qBAAwB;AACxB,uBAA0B;AAC1B,sBAAyB;AACzB,mBAAsB;AACtB,uBAA0B;AAC1B,uBAA0B;AAInB,MAAM,oBAAoB,CAC/B,UACA,aACA,YACA,
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\n\nimport { ZendureSolarflow } from \"../main\";\nimport { Ace1500 } from \"../models/deviceModels/Ace1500\";\nimport { Aio2400 } from \"../models/deviceModels/Aio2400\";\nimport { Hyper2000 } from \"../models/deviceModels/Hyper2000\";\nimport { Sf2400Ac } from \"../models/deviceModels/Sf2400Ac\";\nimport { Sf800 } from \"../models/deviceModels/Sf800\";\nimport { SfHub1200 } from \"../models/deviceModels/SfHub1200\";\nimport { SfHub2000 } from \"../models/deviceModels/SfHub2000\";\n\nimport { IZenHaDeviceDetails } from \"../models/IZenHaDeviceDetails\";\n\nexport const createDeviceModel = (\n _adapter: ZendureSolarflow,\n _productKey: string,\n _deviceKey: string,\n _zenHaDeviceDetails?: IZenHaDeviceDetails\n):\n | SfHub1200\n | SfHub2000\n | Ace1500\n | Hyper2000\n | Sf2400Ac\n | Sf800\n | undefined => {\n switch (_productKey.toLowerCase()) {\n case \"73bktv\":\n return new SfHub1200(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails ? _zenHaDeviceDetails.productModel : \"HUB 1200\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"HUB 1200\",\n _zenHaDeviceDetails\n );\n case \"a8yh63\":\n return new SfHub2000(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails ? _zenHaDeviceDetails.productModel : \"HUB 2000\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"HUB 2000\",\n _zenHaDeviceDetails\n );\n case \"ywf7hv\":\n return new Aio2400(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails ? _zenHaDeviceDetails.productModel : \"AIO 2400\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"AIO 2400\",\n _zenHaDeviceDetails\n );\n case \"ja72u0ha\":\n return new Hyper2000(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails ? _zenHaDeviceDetails.productModel : \"Hyper 2000\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"Hyper 2000\",\n _zenHaDeviceDetails\n );\n case \"gda3tb\":\n return new Hyper2000(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails ? _zenHaDeviceDetails.productModel : \"Hyper 2000\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"Hyper 2000\",\n _zenHaDeviceDetails\n );\n case \"b3dxda\":\n return new Hyper2000(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails ? _zenHaDeviceDetails.productModel : \"Hyper 2000\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"Hyper 2000\",\n _zenHaDeviceDetails\n );\n case \"8bm93h\":\n return new Ace1500(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails ? _zenHaDeviceDetails.productModel : \"Ace 1500\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"Ace 1500\",\n _zenHaDeviceDetails\n );\n case \"bc8b7f\":\n return new Sf2400Ac(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails\n ? _zenHaDeviceDetails.productModel\n : \"Solarflow 2400 AC\",\n _zenHaDeviceDetails\n ? _zenHaDeviceDetails.deviceName\n : \"Solarflow 2400 AC\",\n _zenHaDeviceDetails\n );\n case \"a4ss5P\":\n return new Sf800(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails\n ? _zenHaDeviceDetails.productModel\n : \"Solarflow 800\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"Solarflow 800\",\n _zenHaDeviceDetails\n );\n case \"b1nhmc\":\n return new Sf800(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails\n ? _zenHaDeviceDetails.productModel\n : \"Solarflow 800\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"Solarflow 800\",\n _zenHaDeviceDetails\n );\n case \"R3mn8U\":\n return new Sf800(\n _adapter,\n _productKey,\n _deviceKey,\n _zenHaDeviceDetails\n ? _zenHaDeviceDetails.productModel\n : \"Solarflow 800\",\n _zenHaDeviceDetails ? _zenHaDeviceDetails.deviceName : \"Solarflow 800\",\n _zenHaDeviceDetails\n );\n default:\n return undefined;\n }\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAwB;AACxB,qBAAwB;AACxB,uBAA0B;AAC1B,sBAAyB;AACzB,mBAAsB;AACtB,uBAA0B;AAC1B,uBAA0B;AAInB,MAAM,oBAAoB,CAC/B,UACA,aACA,YACA,wBAQe;AACf,UAAQ,YAAY,YAAY,GAAG;AAAA,IACjC,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,oBAAoB,eAAe;AAAA,QACzD,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,oBAAoB,eAAe;AAAA,QACzD,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,oBAAoB,eAAe;AAAA,QACzD,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,oBAAoB,eAAe;AAAA,QACzD,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,oBAAoB,eAAe;AAAA,QACzD,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,oBAAoB,eAAe;AAAA,QACzD,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,oBAAoB,eAAe;AAAA,QACzD,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBACI,oBAAoB,eACpB;AAAA,QACJ,sBACI,oBAAoB,aACpB;AAAA,QACJ;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBACI,oBAAoB,eACpB;AAAA,QACJ,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBACI,oBAAoB,eACpB;AAAA,QACJ,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBACI,oBAAoB,eACpB;AAAA,QACJ,sBAAsB,oBAAoB,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AACE,aAAO;AAAA,EACX;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -925,6 +925,12 @@ class ZenHaDevice {
|
|
|
925
925
|
(/* @__PURE__ */ new Date()).getTime(),
|
|
926
926
|
true
|
|
927
927
|
));
|
|
928
|
+
const currentWifiState = await this.adapter.getStateAsync(
|
|
929
|
+
`${this.productKey}.${this.deviceKey}.wifiState`
|
|
930
|
+
);
|
|
931
|
+
if (currentWifiState && currentWifiState.val == "Disconnected") {
|
|
932
|
+
this.updateSolarFlowState("wifiState", "Connected");
|
|
933
|
+
}
|
|
928
934
|
}
|
|
929
935
|
}
|
|
930
936
|
async updateSolarFlowControlState(state, val) {
|
|
@@ -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 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 }\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\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\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\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\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 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 {\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 const currentEnergyWh = currentEnergyState?.val\n ? Number(currentEnergyState?.val)\n : 0;\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 { 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 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\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\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\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\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 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 {\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 const currentEnergyWh = currentEnergyState?.val\n ? Number(currentEnergyState?.val)\n : 0;\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,uBAAqC;AACrC,qCAAwC;AACxC,wBAAkC;AAElC,+BAIO;AAMA,MAAM,YAAY;AAAA,EAmBhB,YACL,UACA,aACA,YACA,cACA,aACA,qBACA;AAlBF,SAAO,YAA2B,CAAC;AAEnC,SAAO,WAAmB;AAC1B,SAAO,gBAAgB;AAEvB,SAAO,gBAAwB;AAC/B,SAAO,iBAAyB;AAEhC,SAAO,SAA4B,CAAC;AACpC,SAAO,gBAAmC,CAAC;AA8kB3C,+BAAsB,OACpB,UACA,gBACkB;AAClB,UAAI,KAAK,WAAW,KAAK,cAAc,KAAK,WAAW;AACrD,cAAM,SAAS,QAAQ,OAAO,MAAM;AAlnB1C;AAonBQ,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;AAAA,cAEJ;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;AAAA,cAEJ;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;AAAA,cAEJ;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;AAAA,cAEJ;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;AA57BtD,kBAAAC;AA67BY,+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;AAgMA,SAAO,wBAAwB,OAC7B,UACA,UACkB;AAnpCtB;AAopCI,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,YAAM,mBAAkB,yDAAoB,OACxC,OAAO,yDAAoB,GAAG,IAC9B;AAEJ,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;AAv1CF;AAyCI,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,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;AAzEvD;AA0EI,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;AAzH1D,UAAAC;AA0HM,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;AA5JjE,UAAAA,KAAAC;AA6JM,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;AA5MtC;AA6MI,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;AAvNpC;AAwNI,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;AAlO5D;AAmOI,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,4DAA4D,KAAK;AAAA;AAEnE;AAAA,EACF;AAAA,EAEO,UAAU,QAAsB;AAzOzC;AA0OI,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,wCAAwC,MAAM;AAAA;AAEhD;AAAA,EACF;AAAA,EAEO,YAAY,UAAyB;AAhP9C;AAiPI,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,0CAA0C,QAAQ;AAAA;AAEpD;AAAA,EACF;AAAA,EAEO,YAAY,UAAyB;AAvP9C;AAwPI,eAAK,YAAL,mBAAc,IAAI;AAAA,MAChB,0CAA0C,QAAQ;AAAA;AAEpD;AAAA,EACF;AAAA,EAEO,YAAY,UAAwB;AA9P7C;AA+PI,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;AA9Q7C;AA+QI,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;AA7RpD;AA8RI,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;AAnTjD;AAoTI,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;AA1U9C;AA2UI,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;AAlW/C;AAmWI,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;AAjZ5D;AAkZI,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;AAjf5C;AAkfI,QAAI,KAAK,QAAQ,cAAc,KAAK,cAAc,KAAK,WAAW;AAChE,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,CAAC,KAAK,eAAe;AACtC,gBAAQ,CAAC,KAAK;AAAA,MAChB;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;AA9gBlD;AA+gBI,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;AA9hBlD;AA+hBI,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;AA7iB5C;AA8iBI,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;AA5jBnB;AA6jBI,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;AA7lBnB;AA+lBI,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,EAuWA,MAAa,aAAa,SAAgC;AAl9B5D;AAm9BI,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;AA/iCrD;AAgjCM,UAAI,oBAAoB;AACxB,UAAI,qBAAqB;AACzB,UAAI,iBAAiB;AAErB,UAAI,YAAY,YAAY;AAC1B,4BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACxD,6BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACzD,yBAAiB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACvD,WAAW,YAAY,YAAY;AACjC,4BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACxD,6BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AACzD,yBAAiB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS;AAAA,MACvD,OAAO;AACL,4BAAoB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,iBAAiB,QAAQ;AACjF,6BAAqB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,iBAAiB,QAAQ;AAClF,yBAAiB,GAAG,KAAK,UAAU,IAAI,KAAK,SAAS,IAAI,QAAQ;AAAA,MACnE;AAEA,YAAM,oBACJ,QAAM,UAAK,YAAL,mBAAc,cAAc;AACpC,YAAM,qBACJ,QAAM,UAAK,YAAL,mBAAc,cAAc;AAEpC,WAAI,yDAAoB,QAAO,GAAG;AAEhC,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,OAAO;AACL,gBAAM,UAAK,YAAL,mBAAc,SAAS,mBAAmB,GAAG;AACnD,gBAAM,UAAK,YAAL,mBAAc,SAAS,oBAAoB,GAAG;AAAA,MACtD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EA2MA,MAAa,eAA8B;AAz1C7C;AA21CI,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;AA13C/C;AA23CI,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;AAz4C7D;AA04CM,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
|
}
|
|
@@ -78,8 +78,8 @@ const startCheckStatesAndConnectionJob = async (adapter) => {
|
|
|
78
78
|
device.productKey + "." + device.deviceKey + ".wifiState"
|
|
79
79
|
));
|
|
80
80
|
const fiveMinutesAgo = (Date.now() / 1e3 - 5 * 60) * 1e3;
|
|
81
|
-
const
|
|
82
|
-
if (lastUpdate && lastUpdate.val && Number(lastUpdate.val) <
|
|
81
|
+
const tenMinutesAgo = (Date.now() / 1e3 - 10 * 60) * 1e3;
|
|
82
|
+
if (lastUpdate && lastUpdate.val && Number(lastUpdate.val) < tenMinutesAgo && (wifiState == null ? void 0 : wifiState.val) == "Connected" && adapter.config.connectionMode == "authKey") {
|
|
83
83
|
adapter.log.warn(
|
|
84
84
|
`[checkStatesJob] Last update for deviceKey ${device.deviceKey} was at ${new Date(
|
|
85
85
|
Number(lastUpdate.val)
|
|
@@ -88,15 +88,13 @@ const startCheckStatesAndConnectionJob = async (adapter) => {
|
|
|
88
88
|
await adapter.delay(20 * 1e3);
|
|
89
89
|
adapter.restart();
|
|
90
90
|
refreshAccessTokenNeeded = true;
|
|
91
|
-
} else if (lastUpdate && lastUpdate.val && Number(lastUpdate.val) <
|
|
91
|
+
} else if (lastUpdate && lastUpdate.val && Number(lastUpdate.val) < tenMinutesAgo && (wifiState == null ? void 0 : wifiState.val) == "Connected" && adapter.config.connectionMode == "local") {
|
|
92
92
|
adapter.log.warn(
|
|
93
93
|
`[checkStatesJob] Last update for deviceKey ${device.deviceKey} was at ${new Date(
|
|
94
94
|
Number(lastUpdate.val)
|
|
95
95
|
)}, set Wifi state to Disconnected!`
|
|
96
96
|
);
|
|
97
97
|
device == null ? void 0 : device.updateSolarFlowState("wifiState", "Disconnected");
|
|
98
|
-
} else {
|
|
99
|
-
device == null ? void 0 : device.updateSolarFlowState("wifiState", "Connected");
|
|
100
98
|
}
|
|
101
99
|
if (lastUpdate && lastUpdate.val && Number(lastUpdate.val) < fiveMinutesAgo && !refreshAccessTokenNeeded) {
|
|
102
100
|
adapter.log.debug(
|
|
@@ -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
|
|
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,
|
|
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.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 )}, device seems to be online - so maybe connection is broken - restart adapter in 20 seconds!`\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 10 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,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;AAEA,cAAM,QAAQ,MAAM,KAAK,GAAI;AAC7B,gBAAQ,QAAQ;AAGhB,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
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "zendure-solarflow",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.3",
|
|
5
5
|
"news": {
|
|
6
|
+
"3.0.3": {
|
|
7
|
+
"en": "Optimize setting of wifiMode in local mode\nOptimize Debug option",
|
|
8
|
+
"de": "Optimieren Sie die Einstellung von wifiMode im lokalen Modus\nOptimierung der Debug-Option",
|
|
9
|
+
"ru": "Оптимизируйте настройку WiFiMode в локальном режиме\nОптимизируйте опцию Debug",
|
|
10
|
+
"pt": "Otimizar a configuração do wifiMode no modo local\nOtimizar a opção de depuração",
|
|
11
|
+
"nl": "Optimaliseer de instelling van wifiMode in lokale modus\nOptimaliseer debug-optie",
|
|
12
|
+
"fr": "Optimiser le réglage du wifiMode en mode local\nOptimiser l'option de débogage",
|
|
13
|
+
"it": "Ottimizzare l'impostazione di wifiMode in modalità locale\nOttimizzare l'opzione Debug",
|
|
14
|
+
"es": "Optimize setting of wifiMode in local mode\nOpción Optimize Debug",
|
|
15
|
+
"pl": "Optymalizacja ustawień WifiMode w trybie lokalnym\nOptymalizacja opcji debugowania",
|
|
16
|
+
"uk": "Оптимізуйте налаштування wifiMode в локальному режимі\nОптимізуйте опцію Debug",
|
|
17
|
+
"zh-cn": "优化本地模式的 wifiMode 设置\n优化调试选项"
|
|
18
|
+
},
|
|
6
19
|
"3.0.2": {
|
|
7
20
|
"en": "Ignore 'wifiState' for last update value",
|
|
8
21
|
"de": "'wifiState' für den letzten Updatewert ignorieren",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "Usługa małej naprawy MQTT",
|
|
81
94
|
"uk": "Невелика фіксація MQTT сервіс",
|
|
82
95
|
"zh-cn": "小修补 MQTT 服务"
|
|
83
|
-
},
|
|
84
|
-
"2.0.0": {
|
|
85
|
-
"en": "Breaking Change: Add control parameter 'setDeviceAutomationInOutLimit' which emulates Zendure's Smart Matching mode. I recommend using this device automation instead of 'setInputLimit'/'setOutputLimit' from now on, as there were concerns that setting limits/modes would be stored in the flash memory. You can use negative values for charging and positive for feed in. On HUB 1200/2000 with ACE 1500 you can use \"smartMode\" to prevent switching AC mode trigger writing to the flash memory. Check you the readme for more details or participate in the ioBroker forum.",
|
|
86
|
-
"de": "Veränderung: Fügen Sie den Steuerparameter 'setDeviceAutomationInOutLimit' hinzu, der den Smart Matching-Modus von Zendure emuliert. Ich empfehle, diese Geräteautomatisierung anstelle von 'setInputLimit'/'setOutputLimit' von jetzt an zu verwenden, da es Bedenken gab, dass Einstelllimits/Mode im Flash-Speicher gespeichert würden. Sie können negative Werte für das Laden und positiv für das Einspeisen verwenden. Auf HUB 1200/2000 mit ACE 1500 können Sie \"smartMode\" verwenden, um zu verhindern, dass Wechselstrommodus das Schreiben an den Flash-Speicher auslöst. Überprüfen Sie das Readme für weitere Details oder nehmen Sie am ioBroker Forum teil.",
|
|
87
|
-
"ru": "Переломные изменения: Добавьте параметр управления «setDeviceAutomationInOutLimit», который эмулирует режим Smart Matching от Zendure. Отныне я рекомендую использовать автоматизацию этого устройства вместо «setInputLimit» / «setOutputLimit», поскольку были опасения, что установка ограничений / режимов будет храниться во флэш-памяти. Вы можете использовать отрицательные значения для зарядки и положительные для подачи. На HUB 1200/2000 с ACE 1500 можно использовать «smartMode», чтобы предотвратить переключение записи в режиме переменного тока на флэш-память. Проверьте Readme для получения более подробной информации или участвуйте в форуме ioBroker.",
|
|
88
|
-
"pt": "Quebrar a Mudança: Adicionar parâmetro de controle 'setDeviceAutomationInOutLimit' que emula o modo Smart Matching da Zendure. Eu recomendo usar esta automação de dispositivo em vez de 'setInputLimit'/'setOutputLimit' a partir de agora, como havia preocupações de que definir limites/modos seria armazenado na memória flash. Você pode usar valores negativos para carregar e positivos para alimentação. Em HUB 1200/2000 com ACE 1500 você pode usar \"smartMode\" para evitar a ativação do modo AC de comutação de gravação para a memória flash. Confira o readme para mais detalhes ou participe no fórum ioBroker.",
|
|
89
|
-
"nl": "Verandering doorbreken: Voeg controleparameter 'setDeviceAutomationInOutLimit' toe die Zendure's Smart Matching-modus emuleert. Ik adviseer deze apparaatautomatisering vanaf nu te gebruiken in plaats van 'setInputLimit'/'setOutputLimit', omdat er bezorgdheid bestond dat het instellen van limieten/modi in het flitsgeheugen zou worden opgeslagen. U kunt negatieve waarden gebruiken voor het opladen en positief voor voer in. Op HUB 1200/2000 met ACE 1500 kunt u \"smartMode\" gebruiken om te voorkomen dat het schakelen van de AC-modus trigger schrijven naar het flitsgeheugen. Bekijk de readme voor meer details of neem deel aan het ioBroker forum.",
|
|
90
|
-
"fr": "Briser le changement : Ajouter le paramètre de contrôle 'setDeviceAutomationInOutLimit' qui émule le mode Smart Matching de Zendure. Je recommande d'utiliser cette automatisation de périphérique au lieu de 'setInputLimit'/'setOutputLimit' à partir de maintenant, car il y avait des préoccupations que le réglage des limites/modes serait stocké dans la mémoire flash. Vous pouvez utiliser des valeurs négatives pour la charge et positives pour l'alimentation. Sur HUB 1200/2000 avec ACE 1500, vous pouvez utiliser \"smartMode\" pour empêcher le passage de l'écriture du déclencheur en mode AC à la mémoire flash. Vérifiez la lecture pour plus de détails ou participez au forum ioBroker.",
|
|
91
|
-
"it": "Cambiamento di rottura: Aggiungi il parametro di controllo 'setDeviceAutomationInOutLimit' che emula la modalità Smart Matching di Zendure. Raccomando di utilizzare questo dispositivo di automazione invece di 'setInputLimit'/'setOutputLimit' da ora in poi, in quanto vi erano preoccupazioni che la regolazione dei limiti/modi sarebbe memorizzata nella memoria flash. È possibile utilizzare valori negativi per la ricarica e positivo per il feed in. Su HUB 1200/2000 con ACE 1500 è possibile utilizzare \"smartMode\" per evitare di commutare la modalità AC di attivare la scrittura alla memoria flash. Controlla il readme per maggiori dettagli o partecipa al forum ioBroker.",
|
|
92
|
-
"es": "Cambio de ruptura: Añadir parámetro de control 'setDeviceAutomationInOutLimit' que emula el modo Smart Matching de Zendure. Recomiendo usar esta automatización de dispositivos en lugar de 'setInputLimit'/'setOutputLimit' a partir de ahora, ya que había preocupaciones de que fijar límites/modes se almacenarían en la memoria flash. Puede utilizar valores negativos para cargar y positivos para alimentarse. En HUB 1200/2000 con ACE 1500 se puede utilizar \"smartMode\" para evitar cambiar el modo AC activando la escritura a la memoria flash. Comprueba la lectura para más detalles o participa en el foro ioBroker.",
|
|
93
|
-
"pl": "Łamanie zmian: Dodaj parametr sterowania 'setDeviceAutomationInOutLimit', który emuluje tryb inteligentnego dopasowywania Zhamb. Zalecam stosowanie automatyzacji tego urządzenia zamiast 'setInputLimit' / 'setOutputLimit' od teraz, ponieważ istniały obawy, że ustawianie limitów / trybów będzie przechowywane w pamięci flash. Możesz użyć wartości ujemnych do ładowania i dodatnich do podawania. W HUB 1200 / 2000 z ACE 1500 można użyć \"smartMode\", aby zapobiec przełączaniu zapisu trybu AC do pamięci flash. Sprawdź czytaj więcej szczegółów lub uczestnicz w forum jOBroker.",
|
|
94
|
-
"uk": "Зміна несправностей: Додавання параметра керування «setDeviceAutomationInOutLimit», який визначає режим Smart Matching Zendure. Я рекомендую використовувати цей пристрій автоматизації замість 'setInputLimit'/'setOutputLimit' відтепер, оскільки є побоювання, що налаштування лімітів/модів буде зберігатися в флеш-пам'яті. Ви можете використовувати негативні значення для зарядки та позитиву для живлення. На HUB 1200/2000 з ACE 1500 ви можете використовувати \"smartMode\" для запобігання перемикання режиму змінного струму, що тривають на флеш-пам'ять. Перевірити читання для отримання більш детальної інформації або участі в форумі ioBroker.",
|
|
95
|
-
"zh-cn": "中断更改 : 添加模拟 Zendure 智能匹配模式的控制参数“ set DeviceAutomation InOutLimit ” 。 我建议从现在开始使用这个设备自动化, 而不是“ setInputLimit ” /“ setOutputLimit ” , 因为有人担心设定限制/ modes会存储在闪存中 。 可以使用负值充电,正值用于饲料输入. 在 HUB 1200/2000 与 ACE 1500 可以使用\"smartMode\"来防止将 AC 模式触发写入到闪存中. 请检查access-date=中的日期值 (帮助) 更多细节或参加ioBroker论坛."
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|