iobroker.zendure-solarflow 5.0.2 → 5.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 +4 -5
- package/build/helpers/processDeviceProperties.js +2 -0
- package/build/helpers/processDeviceProperties.js.map +2 -2
- package/build/models/deviceModels/ZenIobDevice.js +4 -8
- package/build/models/deviceModels/ZenIobDevice.js.map +2 -2
- package/io-package.json +14 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,6 +101,10 @@ This adapter will use the Cloud Authorization Code for authentication on the off
|
|
|
101
101
|
-->
|
|
102
102
|
|
|
103
103
|
## Changelog
|
|
104
|
+
### 5.0.3 (2026-08-18)
|
|
105
|
+
|
|
106
|
+
- Fix `wifiState` not being created/updated correctly for devices using local zenSDK polling (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), as their local status payload does not report a `wifiState` property
|
|
107
|
+
|
|
104
108
|
### 5.0.2 (2026-08-18)
|
|
105
109
|
|
|
106
110
|
- Fix Wifistate type/value mismatch
|
|
@@ -121,11 +125,6 @@ This adapter will use the Cloud Authorization Code for authentication on the off
|
|
|
121
125
|
- Add missing translations
|
|
122
126
|
- Add dependencies
|
|
123
127
|
|
|
124
|
-
### 4.1.1 (2026-07-14)
|
|
125
|
-
|
|
126
|
-
- Send MQTT commands with QOS=1
|
|
127
|
-
- If zenSDK device is not reachable, stop polling device after 5 retries. Try again after 10 minutes.
|
|
128
|
-
|
|
129
128
|
For older changes see [CHANGELOG_OLD.md](CHANGELOG_OLD.md).
|
|
130
129
|
|
|
131
130
|
## License
|
|
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var processDeviceProperties_exports = {};
|
|
20
20
|
__export(processDeviceProperties_exports, {
|
|
21
|
+
ensureState: () => ensureState,
|
|
21
22
|
processDeviceProperties: () => processDeviceProperties
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(processDeviceProperties_exports);
|
|
@@ -354,6 +355,7 @@ const processDeviceProperties = async (device, properties, isSolarFlow) => {
|
|
|
354
355
|
};
|
|
355
356
|
// Annotate the CommonJS export names for ESM import in node:
|
|
356
357
|
0 && (module.exports = {
|
|
358
|
+
ensureState,
|
|
357
359
|
processDeviceProperties
|
|
358
360
|
});
|
|
359
361
|
//# sourceMappingURL=processDeviceProperties.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/helpers/processDeviceProperties.ts"],
|
|
4
|
-
"sourcesContent": ["import { allStates } from \"../constants/sensorStates/allStates\";\nimport type { ZenIobDevice } from \"../models/deviceModels/ZenIobDevice\";\nimport type { ISolarFlowMqttProperties } from \"../models/ISolarFlowMqttProperties\";\n\n// Cache of states already created per device in this session (avoids redundant extendObject calls)\nconst createdStateCache = new Map<string, Set<string>>();\n\n// All MQTT property keys that have explicit handlers in processDeviceProperties\nconst handledMqttKeys = new Set<string>([\n \"autoModel\",\n \"heatState\",\n \"electricLevel\",\n \"packData\",\n \"packState\",\n \"passMode\",\n \"pass\",\n \"autoRecover\",\n \"outputHomePower\",\n \"energyPower\",\n \"outputLimit\",\n \"smartMode\",\n \"buzzerSwitch\",\n \"outputPackPower\",\n \"packInputPower\",\n \"solarInputPower\",\n \"pvPower1\",\n \"pvPower2\",\n \"solarPower1\",\n \"solarPower2\",\n \"solarPower3\",\n \"solarPower4\",\n \"remainOutTime\",\n \"remainInputTime\",\n \"socSet\",\n \"minSoc\",\n \"inputLimit\",\n \"gridInputPower\",\n \"acMode\",\n \"hyperTmp\",\n \"acOutputPower\",\n \"gridPower\",\n \"acSwitch\",\n \"dcSwitch\",\n \"dcOutputPower\",\n \"pvBrand\",\n \"inverseMaxPower\",\n \"wifiState\",\n \"packNum\",\n \"hubState\",\n \"batteryElectric\",\n \"gridReverse\",\n]);\n\n// MQTT property keys that are known noise and should never become states\nconst ignoredMqttKeys = new Set<string>([\"0\", \"getAll\"]);\n\nconst ensureState = async (\n device: ZenIobDevice,\n stateTitle: string,\n rawValue?: number | string | boolean,\n): Promise<void> => {\n const deviceId = `${device.productKey}.${device.deviceKey}`;\n if (createdStateCache.get(deviceId)?.has(stateTitle)) {\n return;\n }\n\n const stateDef = allStates[stateTitle];\n const productKey = device.productKey.replace(device.adapter.FORBIDDEN_CHARS, \"\");\n const deviceKey = device.deviceKey.replace(device.adapter.FORBIDDEN_CHARS, \"\");\n const stateId = `${productKey}.${deviceKey}.${stateTitle}`;\n\n let type: ioBroker.CommonType;\n let role: string;\n let nameDe: string;\n let nameEn: string;\n\n if (stateDef) {\n type = stateDef.type;\n role = stateDef.role;\n nameDe = stateDef.nameDe;\n nameEn = stateDef.nameEn;\n } else if (rawValue !== undefined) {\n const t = typeof rawValue;\n type = t === \"number\" ? \"number\" : t === \"boolean\" ? \"boolean\" : \"string\";\n role = \"value\";\n nameDe = stateTitle;\n nameEn = stateTitle;\n } else {\n return;\n }\n\n // Self-heal objects left over from older adapter versions where this state had a different type\n // (e.g. wifiState used to be a string enum and was later changed to a number).\n const existingObj = await device.adapter.getObjectAsync(stateId);\n if (existingObj?.common?.type && existingObj.common.type !== type) {\n await device.adapter.delObjectAsync(stateId);\n }\n\n await device.adapter.extendObject(stateId, {\n type: \"state\",\n common: {\n name: { de: nameDe, en: nameEn },\n type,\n desc: stateTitle,\n role,\n read: true,\n write: false,\n unit: stateDef?.unit,\n states: stateDef?.states,\n },\n native: {},\n });\n\n if (!createdStateCache.has(deviceId)) {\n createdStateCache.set(deviceId, new Set());\n }\n createdStateCache.get(deviceId)!.add(stateTitle);\n};\n\nconst coerceToStateType = (stateTitle: string, value: number | string | boolean): number | string | boolean => {\n const stateDef = allStates[stateTitle];\n if (!stateDef) {\n return value;\n }\n\n if (stateDef.type === \"boolean\" && typeof value !== \"boolean\") {\n return value == 0 ? false : true;\n }\n if (stateDef.type === \"string\" && typeof value !== \"string\") {\n return String(value);\n }\n if (stateDef.type === \"number\" && typeof value !== \"number\") {\n return Number(value);\n }\n return value;\n};\n\nexport const processDeviceProperties = async (\n device: ZenIobDevice,\n properties: ISolarFlowMqttProperties,\n isSolarFlow: boolean,\n): Promise<void> => {\n // Phase 1: collect all transformed state values and control state values.\n // Side effects (setEnergyWhMax, setSocToZero, etc.) are triggered here.\n const statesToSet = new Map<string, number | string | boolean>();\n const controlStatesToSet = new Map<string, number | string | boolean>();\n\n if (properties?.autoModel != null) {\n statesToSet.set(\"autoModel\", properties.autoModel);\n controlStatesToSet.set(\"autoModel\", properties.autoModel);\n }\n\n if (properties?.heatState != null) {\n statesToSet.set(\"heatState\", properties.heatState == 0 ? 0 : 1);\n }\n\n if (properties?.electricLevel != null) {\n statesToSet.set(\"electricLevel\", properties.electricLevel);\n\n if (device.adapter?.config.useCalculation && properties.electricLevel == 100 && isSolarFlow) {\n device.setEnergyWhMax();\n }\n\n if (properties.electricLevel == 100) {\n const fullChargeNeeded = await device.adapter.getStateAsync(\n `${device.productKey}.${device.deviceKey}.control.fullChargeNeeded`,\n );\n if (fullChargeNeeded?.val == true) {\n await device.adapter.setState(`${device.productKey}.${device.deviceKey}.control.fullChargeNeeded`, false, true);\n }\n }\n\n const minSoc = await device.adapter.getStateAsync(`${device.productKey}.${device.deviceKey}.minSoc`);\n if (\n device.adapter?.config.useCalculation &&\n minSoc?.val &&\n properties.electricLevel == Number(minSoc.val) &&\n isSolarFlow\n ) {\n device.setSocToZero();\n }\n }\n\n if (properties?.packState != null) {\n statesToSet.set(\n \"packState\",\n properties.packState == 0\n ? \"Idle\"\n : properties.packState == 1\n ? \"Charging\"\n : properties.packState == 2\n ? \"Discharging\"\n : \"Unknown\",\n );\n }\n\n if (properties?.passMode != null) {\n statesToSet.set(\n \"passMode\",\n properties.passMode == 0\n ? \"Automatic\"\n : properties.passMode == 1\n ? \"Always off\"\n : properties.passMode == 2\n ? \"Always on\"\n : \"Unknown\",\n );\n controlStatesToSet.set(\"passMode\", properties.passMode);\n }\n\n if (properties?.pass != null) {\n statesToSet.set(\"pass\", properties.pass == 0 ? 0 : 1);\n }\n\n if (properties?.autoRecover != null) {\n const value = properties.autoRecover == 0 ? 0 : 1;\n statesToSet.set(\"autoRecover\", value);\n controlStatesToSet.set(\"autoRecover\", value == 1);\n }\n\n if (properties?.outputHomePower != null) {\n statesToSet.set(\"outputHomePower\", properties.outputHomePower);\n }\n\n if (properties?.energyPower != null) {\n statesToSet.set(\"energyPower\", properties.energyPower);\n }\n\n if (properties?.outputLimit != null) {\n statesToSet.set(\"outputLimit\", properties.outputLimit);\n controlStatesToSet.set(\"setOutputLimit\", properties.outputLimit);\n }\n\n if (properties?.smartMode != null) {\n const value = properties.smartMode == 0 ? 0 : 1;\n statesToSet.set(\"smartMode\", value);\n controlStatesToSet.set(\"smartMode\", value == 1);\n }\n\n if (properties?.buzzerSwitch != null) {\n const value = properties.buzzerSwitch == 0 ? 0 : 1;\n statesToSet.set(\"buzzerSwitch\", value);\n controlStatesToSet.set(\"buzzerSwitch\", value == 1);\n }\n\n if (properties?.outputPackPower != null) {\n statesToSet.set(\"outputPackPower\", properties.outputPackPower);\n if (properties.outputPackPower > 0) {\n statesToSet.set(\"packInputPower\", 0);\n }\n }\n\n if (properties?.packInputPower != null) {\n statesToSet.set(\"packInputPower\", properties.packInputPower);\n if (properties.packInputPower > 0) {\n statesToSet.set(\"outputPackPower\", 0);\n }\n }\n\n if (properties?.solarInputPower != null) {\n statesToSet.set(\"solarInputPower\", properties.solarInputPower);\n }\n\n // pvPower1/2 are reversed to align with the official app\n if (properties?.pvPower1 != null) {\n statesToSet.set(\"pvPower2\", properties.pvPower1);\n }\n if (properties?.pvPower2 != null) {\n statesToSet.set(\"pvPower1\", properties.pvPower2);\n }\n\n if (properties?.solarPower1 != null) {\n statesToSet.set(\"pvPower1\", properties.solarPower1);\n }\n if (properties?.solarPower2 != null) {\n statesToSet.set(\"pvPower2\", properties.solarPower2);\n }\n if (properties?.solarPower3 != null) {\n statesToSet.set(\"pvPower3\", properties.solarPower3);\n }\n if (properties?.solarPower4 != null) {\n statesToSet.set(\"pvPower4\", properties.solarPower4);\n }\n\n if (properties?.remainOutTime != null) {\n statesToSet.set(\"remainOutTime\", properties.remainOutTime);\n }\n if (properties?.remainInputTime != null) {\n statesToSet.set(\"remainInputTime\", properties.remainInputTime);\n }\n\n if (properties?.socSet != null) {\n statesToSet.set(\"socSet\", Number(properties.socSet) / 10);\n controlStatesToSet.set(\"chargeLimit\", Number(properties.socSet) / 10);\n }\n\n if (properties?.minSoc != null) {\n statesToSet.set(\"minSoc\", Number(properties.minSoc) / 10);\n controlStatesToSet.set(\"dischargeLimit\", Number(properties.minSoc) / 10);\n }\n\n if (properties?.inputLimit != null) {\n statesToSet.set(\"inputLimit\", properties.inputLimit);\n controlStatesToSet.set(\"setInputLimit\", properties.inputLimit);\n }\n\n if (properties?.gridInputPower != null) {\n statesToSet.set(\"gridInputPower\", properties.gridInputPower);\n }\n\n if (properties?.acMode != null) {\n statesToSet.set(\"acMode\", properties.acMode);\n controlStatesToSet.set(\"acMode\", properties.acMode);\n }\n\n if (properties?.hyperTmp != null) {\n statesToSet.set(\"hyperTmp\", properties.hyperTmp / 10 - 273.15);\n }\n if (properties?.acOutputPower != null) {\n statesToSet.set(\"acOutputPower\", properties.acOutputPower);\n }\n if (properties?.gridPower != null) {\n statesToSet.set(\"gridInputPower\", properties.gridPower);\n }\n\n if (properties?.acSwitch != null) {\n const value = properties.acSwitch == 0 ? 0 : 1;\n statesToSet.set(\"acSwitch\", value);\n controlStatesToSet.set(\"acSwitch\", value == 1);\n }\n\n if (properties?.dcSwitch != null) {\n const value = properties.dcSwitch == 0 ? 0 : 1;\n statesToSet.set(\"dcSwitch\", value);\n controlStatesToSet.set(\"dcSwitch\", value == 1);\n }\n\n if (properties?.dcOutputPower != null) {\n statesToSet.set(\"dcOutputPower\", properties.dcOutputPower);\n }\n\n if (properties?.pvBrand != null) {\n statesToSet.set(\n \"pvBrand\",\n properties.pvBrand == 0\n ? \"Others\"\n : properties.pvBrand == 1\n ? \"Hoymiles\"\n : properties.pvBrand == 2\n ? \"Enphase\"\n : properties.pvBrand == 3\n ? \"APSystems\"\n : properties.pvBrand == 4\n ? \"Anker\"\n : properties.pvBrand == 5\n ? \"Deye\"\n : properties.pvBrand == 6\n ? \"Bosswerk\"\n : \"Unknown\",\n );\n }\n\n if (properties?.inverseMaxPower != null) {\n statesToSet.set(\"inverseMaxPower\", properties.inverseMaxPower);\n }\n\n if (properties?.wifiState != null) {\n statesToSet.set(\"wifiState\", properties.wifiState);\n }\n\n if (properties?.packNum != null) {\n statesToSet.set(\"packNum\", properties.packNum);\n }\n\n if (properties?.hubState != null) {\n statesToSet.set(\"hubState\", properties.hubState);\n controlStatesToSet.set(\"hubState\", properties.hubState);\n }\n\n if (properties?.batteryElectric != null) {\n statesToSet.set(\"batteryElectric\", properties.batteryElectric);\n }\n\n if (properties?.gridReverse != null) {\n statesToSet.set(\"gridReverse\", properties.gridReverse);\n controlStatesToSet.set(\"gridReverse\", properties.gridReverse);\n }\n\n if (properties?.packData != null) {\n await device.addOrUpdatePackData(properties.packData, isSolarFlow);\n }\n\n // Derive packPower from outputPackPower and packInputPower\n if (statesToSet.has(\"outputPackPower\") || statesToSet.has(\"packInputPower\")) {\n let outputPower = (statesToSet.get(\"outputPackPower\") as number | undefined) ?? 0;\n let inputPower = (statesToSet.get(\"packInputPower\") as number | undefined) ?? 0;\n\n if (!statesToSet.has(\"outputPackPower\")) {\n const s = await device.adapter.getStateAsync(`${device.productKey}.${device.deviceKey}.outputPackPower`);\n outputPower = (s?.val as number) || 0;\n }\n if (!statesToSet.has(\"packInputPower\")) {\n const s = await device.adapter.getStateAsync(`${device.productKey}.${device.deviceKey}.packInputPower`);\n inputPower = (s?.val as number) || 0;\n }\n statesToSet.set(\"packPower\", outputPower - inputPower);\n }\n\n // Phase 2: ensure states exist and set all collected values\n for (const [key, value] of statesToSet) {\n await ensureState(device, key, value);\n device.updateSolarFlowState(key, value);\n }\n\n // Phase 3: apply control state updates\n for (const [key, value] of controlStatesToSet) {\n device.updateSolarFlowControlState(key, value);\n }\n\n // Fallback: for any MQTT property not explicitly handled above, create a state and store the raw value\n for (const [key, value] of Object.entries(properties)) {\n if (handledMqttKeys.has(key) || ignoredMqttKeys.has(key)) {\n continue;\n }\n if (value == null || typeof value === \"object\") {\n continue;\n }\n\n const rawValue = value as number | string | boolean;\n const coercedValue = coerceToStateType(key, rawValue);\n await ensureState(device, key, coercedValue);\n device.updateSolarFlowState(key, coercedValue);\n\n if (device.adapter.log.level == \"debug\") {\n device.adapter.log.debug(\n `[onMessage] ${device.deviceKey}: ${key} = ${JSON.stringify(coercedValue)} stored via fallback handler`,\n );\n }\n }\n};\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAA0B;AAK1B,MAAM,oBAAoB,oBAAI,IAAyB;AAGvD,MAAM,kBAAkB,oBAAI,IAAY;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGD,MAAM,kBAAkB,oBAAI,IAAY,CAAC,KAAK,QAAQ,CAAC;
|
|
4
|
+
"sourcesContent": ["import { allStates } from \"../constants/sensorStates/allStates\";\nimport type { ZenIobDevice } from \"../models/deviceModels/ZenIobDevice\";\nimport type { ISolarFlowMqttProperties } from \"../models/ISolarFlowMqttProperties\";\n\n// Cache of states already created per device in this session (avoids redundant extendObject calls)\nconst createdStateCache = new Map<string, Set<string>>();\n\n// All MQTT property keys that have explicit handlers in processDeviceProperties\nconst handledMqttKeys = new Set<string>([\n \"autoModel\",\n \"heatState\",\n \"electricLevel\",\n \"packData\",\n \"packState\",\n \"passMode\",\n \"pass\",\n \"autoRecover\",\n \"outputHomePower\",\n \"energyPower\",\n \"outputLimit\",\n \"smartMode\",\n \"buzzerSwitch\",\n \"outputPackPower\",\n \"packInputPower\",\n \"solarInputPower\",\n \"pvPower1\",\n \"pvPower2\",\n \"solarPower1\",\n \"solarPower2\",\n \"solarPower3\",\n \"solarPower4\",\n \"remainOutTime\",\n \"remainInputTime\",\n \"socSet\",\n \"minSoc\",\n \"inputLimit\",\n \"gridInputPower\",\n \"acMode\",\n \"hyperTmp\",\n \"acOutputPower\",\n \"gridPower\",\n \"acSwitch\",\n \"dcSwitch\",\n \"dcOutputPower\",\n \"pvBrand\",\n \"inverseMaxPower\",\n \"wifiState\",\n \"packNum\",\n \"hubState\",\n \"batteryElectric\",\n \"gridReverse\",\n]);\n\n// MQTT property keys that are known noise and should never become states\nconst ignoredMqttKeys = new Set<string>([\"0\", \"getAll\"]);\n\nexport const ensureState = async (\n device: ZenIobDevice,\n stateTitle: string,\n rawValue?: number | string | boolean,\n): Promise<void> => {\n const deviceId = `${device.productKey}.${device.deviceKey}`;\n if (createdStateCache.get(deviceId)?.has(stateTitle)) {\n return;\n }\n\n const stateDef = allStates[stateTitle];\n const productKey = device.productKey.replace(device.adapter.FORBIDDEN_CHARS, \"\");\n const deviceKey = device.deviceKey.replace(device.adapter.FORBIDDEN_CHARS, \"\");\n const stateId = `${productKey}.${deviceKey}.${stateTitle}`;\n\n let type: ioBroker.CommonType;\n let role: string;\n let nameDe: string;\n let nameEn: string;\n\n if (stateDef) {\n type = stateDef.type;\n role = stateDef.role;\n nameDe = stateDef.nameDe;\n nameEn = stateDef.nameEn;\n } else if (rawValue !== undefined) {\n const t = typeof rawValue;\n type = t === \"number\" ? \"number\" : t === \"boolean\" ? \"boolean\" : \"string\";\n role = \"value\";\n nameDe = stateTitle;\n nameEn = stateTitle;\n } else {\n return;\n }\n\n // Self-heal objects left over from older adapter versions where this state had a different type\n // (e.g. wifiState used to be a string enum and was later changed to a number).\n const existingObj = await device.adapter.getObjectAsync(stateId);\n if (existingObj?.common?.type && existingObj.common.type !== type) {\n await device.adapter.delObjectAsync(stateId);\n }\n\n await device.adapter.extendObject(stateId, {\n type: \"state\",\n common: {\n name: { de: nameDe, en: nameEn },\n type,\n desc: stateTitle,\n role,\n read: true,\n write: false,\n unit: stateDef?.unit,\n states: stateDef?.states,\n },\n native: {},\n });\n\n if (!createdStateCache.has(deviceId)) {\n createdStateCache.set(deviceId, new Set());\n }\n createdStateCache.get(deviceId)!.add(stateTitle);\n};\n\nconst coerceToStateType = (stateTitle: string, value: number | string | boolean): number | string | boolean => {\n const stateDef = allStates[stateTitle];\n if (!stateDef) {\n return value;\n }\n\n if (stateDef.type === \"boolean\" && typeof value !== \"boolean\") {\n return value == 0 ? false : true;\n }\n if (stateDef.type === \"string\" && typeof value !== \"string\") {\n return String(value);\n }\n if (stateDef.type === \"number\" && typeof value !== \"number\") {\n return Number(value);\n }\n return value;\n};\n\nexport const processDeviceProperties = async (\n device: ZenIobDevice,\n properties: ISolarFlowMqttProperties,\n isSolarFlow: boolean,\n): Promise<void> => {\n // Phase 1: collect all transformed state values and control state values.\n // Side effects (setEnergyWhMax, setSocToZero, etc.) are triggered here.\n const statesToSet = new Map<string, number | string | boolean>();\n const controlStatesToSet = new Map<string, number | string | boolean>();\n\n if (properties?.autoModel != null) {\n statesToSet.set(\"autoModel\", properties.autoModel);\n controlStatesToSet.set(\"autoModel\", properties.autoModel);\n }\n\n if (properties?.heatState != null) {\n statesToSet.set(\"heatState\", properties.heatState == 0 ? 0 : 1);\n }\n\n if (properties?.electricLevel != null) {\n statesToSet.set(\"electricLevel\", properties.electricLevel);\n\n if (device.adapter?.config.useCalculation && properties.electricLevel == 100 && isSolarFlow) {\n device.setEnergyWhMax();\n }\n\n if (properties.electricLevel == 100) {\n const fullChargeNeeded = await device.adapter.getStateAsync(\n `${device.productKey}.${device.deviceKey}.control.fullChargeNeeded`,\n );\n if (fullChargeNeeded?.val == true) {\n await device.adapter.setState(`${device.productKey}.${device.deviceKey}.control.fullChargeNeeded`, false, true);\n }\n }\n\n const minSoc = await device.adapter.getStateAsync(`${device.productKey}.${device.deviceKey}.minSoc`);\n if (\n device.adapter?.config.useCalculation &&\n minSoc?.val &&\n properties.electricLevel == Number(minSoc.val) &&\n isSolarFlow\n ) {\n device.setSocToZero();\n }\n }\n\n if (properties?.packState != null) {\n statesToSet.set(\n \"packState\",\n properties.packState == 0\n ? \"Idle\"\n : properties.packState == 1\n ? \"Charging\"\n : properties.packState == 2\n ? \"Discharging\"\n : \"Unknown\",\n );\n }\n\n if (properties?.passMode != null) {\n statesToSet.set(\n \"passMode\",\n properties.passMode == 0\n ? \"Automatic\"\n : properties.passMode == 1\n ? \"Always off\"\n : properties.passMode == 2\n ? \"Always on\"\n : \"Unknown\",\n );\n controlStatesToSet.set(\"passMode\", properties.passMode);\n }\n\n if (properties?.pass != null) {\n statesToSet.set(\"pass\", properties.pass == 0 ? 0 : 1);\n }\n\n if (properties?.autoRecover != null) {\n const value = properties.autoRecover == 0 ? 0 : 1;\n statesToSet.set(\"autoRecover\", value);\n controlStatesToSet.set(\"autoRecover\", value == 1);\n }\n\n if (properties?.outputHomePower != null) {\n statesToSet.set(\"outputHomePower\", properties.outputHomePower);\n }\n\n if (properties?.energyPower != null) {\n statesToSet.set(\"energyPower\", properties.energyPower);\n }\n\n if (properties?.outputLimit != null) {\n statesToSet.set(\"outputLimit\", properties.outputLimit);\n controlStatesToSet.set(\"setOutputLimit\", properties.outputLimit);\n }\n\n if (properties?.smartMode != null) {\n const value = properties.smartMode == 0 ? 0 : 1;\n statesToSet.set(\"smartMode\", value);\n controlStatesToSet.set(\"smartMode\", value == 1);\n }\n\n if (properties?.buzzerSwitch != null) {\n const value = properties.buzzerSwitch == 0 ? 0 : 1;\n statesToSet.set(\"buzzerSwitch\", value);\n controlStatesToSet.set(\"buzzerSwitch\", value == 1);\n }\n\n if (properties?.outputPackPower != null) {\n statesToSet.set(\"outputPackPower\", properties.outputPackPower);\n if (properties.outputPackPower > 0) {\n statesToSet.set(\"packInputPower\", 0);\n }\n }\n\n if (properties?.packInputPower != null) {\n statesToSet.set(\"packInputPower\", properties.packInputPower);\n if (properties.packInputPower > 0) {\n statesToSet.set(\"outputPackPower\", 0);\n }\n }\n\n if (properties?.solarInputPower != null) {\n statesToSet.set(\"solarInputPower\", properties.solarInputPower);\n }\n\n // pvPower1/2 are reversed to align with the official app\n if (properties?.pvPower1 != null) {\n statesToSet.set(\"pvPower2\", properties.pvPower1);\n }\n if (properties?.pvPower2 != null) {\n statesToSet.set(\"pvPower1\", properties.pvPower2);\n }\n\n if (properties?.solarPower1 != null) {\n statesToSet.set(\"pvPower1\", properties.solarPower1);\n }\n if (properties?.solarPower2 != null) {\n statesToSet.set(\"pvPower2\", properties.solarPower2);\n }\n if (properties?.solarPower3 != null) {\n statesToSet.set(\"pvPower3\", properties.solarPower3);\n }\n if (properties?.solarPower4 != null) {\n statesToSet.set(\"pvPower4\", properties.solarPower4);\n }\n\n if (properties?.remainOutTime != null) {\n statesToSet.set(\"remainOutTime\", properties.remainOutTime);\n }\n if (properties?.remainInputTime != null) {\n statesToSet.set(\"remainInputTime\", properties.remainInputTime);\n }\n\n if (properties?.socSet != null) {\n statesToSet.set(\"socSet\", Number(properties.socSet) / 10);\n controlStatesToSet.set(\"chargeLimit\", Number(properties.socSet) / 10);\n }\n\n if (properties?.minSoc != null) {\n statesToSet.set(\"minSoc\", Number(properties.minSoc) / 10);\n controlStatesToSet.set(\"dischargeLimit\", Number(properties.minSoc) / 10);\n }\n\n if (properties?.inputLimit != null) {\n statesToSet.set(\"inputLimit\", properties.inputLimit);\n controlStatesToSet.set(\"setInputLimit\", properties.inputLimit);\n }\n\n if (properties?.gridInputPower != null) {\n statesToSet.set(\"gridInputPower\", properties.gridInputPower);\n }\n\n if (properties?.acMode != null) {\n statesToSet.set(\"acMode\", properties.acMode);\n controlStatesToSet.set(\"acMode\", properties.acMode);\n }\n\n if (properties?.hyperTmp != null) {\n statesToSet.set(\"hyperTmp\", properties.hyperTmp / 10 - 273.15);\n }\n if (properties?.acOutputPower != null) {\n statesToSet.set(\"acOutputPower\", properties.acOutputPower);\n }\n if (properties?.gridPower != null) {\n statesToSet.set(\"gridInputPower\", properties.gridPower);\n }\n\n if (properties?.acSwitch != null) {\n const value = properties.acSwitch == 0 ? 0 : 1;\n statesToSet.set(\"acSwitch\", value);\n controlStatesToSet.set(\"acSwitch\", value == 1);\n }\n\n if (properties?.dcSwitch != null) {\n const value = properties.dcSwitch == 0 ? 0 : 1;\n statesToSet.set(\"dcSwitch\", value);\n controlStatesToSet.set(\"dcSwitch\", value == 1);\n }\n\n if (properties?.dcOutputPower != null) {\n statesToSet.set(\"dcOutputPower\", properties.dcOutputPower);\n }\n\n if (properties?.pvBrand != null) {\n statesToSet.set(\n \"pvBrand\",\n properties.pvBrand == 0\n ? \"Others\"\n : properties.pvBrand == 1\n ? \"Hoymiles\"\n : properties.pvBrand == 2\n ? \"Enphase\"\n : properties.pvBrand == 3\n ? \"APSystems\"\n : properties.pvBrand == 4\n ? \"Anker\"\n : properties.pvBrand == 5\n ? \"Deye\"\n : properties.pvBrand == 6\n ? \"Bosswerk\"\n : \"Unknown\",\n );\n }\n\n if (properties?.inverseMaxPower != null) {\n statesToSet.set(\"inverseMaxPower\", properties.inverseMaxPower);\n }\n\n if (properties?.wifiState != null) {\n statesToSet.set(\"wifiState\", properties.wifiState);\n }\n\n if (properties?.packNum != null) {\n statesToSet.set(\"packNum\", properties.packNum);\n }\n\n if (properties?.hubState != null) {\n statesToSet.set(\"hubState\", properties.hubState);\n controlStatesToSet.set(\"hubState\", properties.hubState);\n }\n\n if (properties?.batteryElectric != null) {\n statesToSet.set(\"batteryElectric\", properties.batteryElectric);\n }\n\n if (properties?.gridReverse != null) {\n statesToSet.set(\"gridReverse\", properties.gridReverse);\n controlStatesToSet.set(\"gridReverse\", properties.gridReverse);\n }\n\n if (properties?.packData != null) {\n await device.addOrUpdatePackData(properties.packData, isSolarFlow);\n }\n\n // Derive packPower from outputPackPower and packInputPower\n if (statesToSet.has(\"outputPackPower\") || statesToSet.has(\"packInputPower\")) {\n let outputPower = (statesToSet.get(\"outputPackPower\") as number | undefined) ?? 0;\n let inputPower = (statesToSet.get(\"packInputPower\") as number | undefined) ?? 0;\n\n if (!statesToSet.has(\"outputPackPower\")) {\n const s = await device.adapter.getStateAsync(`${device.productKey}.${device.deviceKey}.outputPackPower`);\n outputPower = (s?.val as number) || 0;\n }\n if (!statesToSet.has(\"packInputPower\")) {\n const s = await device.adapter.getStateAsync(`${device.productKey}.${device.deviceKey}.packInputPower`);\n inputPower = (s?.val as number) || 0;\n }\n statesToSet.set(\"packPower\", outputPower - inputPower);\n }\n\n // Phase 2: ensure states exist and set all collected values\n for (const [key, value] of statesToSet) {\n await ensureState(device, key, value);\n device.updateSolarFlowState(key, value);\n }\n\n // Phase 3: apply control state updates\n for (const [key, value] of controlStatesToSet) {\n device.updateSolarFlowControlState(key, value);\n }\n\n // Fallback: for any MQTT property not explicitly handled above, create a state and store the raw value\n for (const [key, value] of Object.entries(properties)) {\n if (handledMqttKeys.has(key) || ignoredMqttKeys.has(key)) {\n continue;\n }\n if (value == null || typeof value === \"object\") {\n continue;\n }\n\n const rawValue = value as number | string | boolean;\n const coercedValue = coerceToStateType(key, rawValue);\n await ensureState(device, key, coercedValue);\n device.updateSolarFlowState(key, coercedValue);\n\n if (device.adapter.log.level == \"debug\") {\n device.adapter.log.debug(\n `[onMessage] ${device.deviceKey}: ${key} = ${JSON.stringify(coercedValue)} stored via fallback handler`,\n );\n }\n }\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -699,17 +699,13 @@ class ZenIobDevice {
|
|
|
699
699
|
}
|
|
700
700
|
}
|
|
701
701
|
async updateSolarFlowState(state, val) {
|
|
702
|
-
var _a, _b
|
|
702
|
+
var _a, _b;
|
|
703
703
|
const stateId = `${this.productKey}.${this.deviceKey}.${state}`;
|
|
704
|
-
|
|
705
|
-
if (!obj) {
|
|
706
|
-
this.adapter.log.debug(`[updateSolarFlowState] state ${stateId} not found, skipping update`);
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
704
|
+
await (0, import_processDeviceProperties.ensureState)(this, state, val);
|
|
709
705
|
const currentValue = await this.adapter.getStateAsync(stateId);
|
|
710
|
-
await ((
|
|
706
|
+
await ((_a = this.adapter) == null ? void 0 : _a.setState(stateId, val, true));
|
|
711
707
|
if ((currentValue == null ? void 0 : currentValue.val) != val && state != "wifiState") {
|
|
712
|
-
await ((
|
|
708
|
+
await ((_b = this.adapter) == null ? void 0 : _b.setState(`${this.productKey}.${this.deviceKey}.lastUpdate`, (/* @__PURE__ */ new Date()).getTime(), true));
|
|
713
709
|
const currentWifiState = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.wifiState`);
|
|
714
710
|
if (currentWifiState && currentWifiState.val == 0) {
|
|
715
711
|
this.updateSolarFlowState("wifiState", 1);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/models/deviceModels/ZenIobDevice.ts"],
|
|
4
|
-
"sourcesContent": ["import { createHash } from \"node:crypto\";\nimport { calculationStateKeys } from \"../../constants/sensorStates/constants\";\nimport { createCalculationStates } from \"../../helpers/createCalculationStates\";\nimport { toHoursAndMinutes } from \"../../helpers/timeHelper\";\nimport type { ZendureSolarflow } from \"../../main\";\nimport {\n knownPackDataProperties,\n onSubscribeIotTopic,\n onSubscribeReportTopic,\n} from \"../../services/mqtt/mqttSharedService\";\nimport type { IDevicePack } from \"../IDevicePack\";\nimport type { IPackData } from \"../IPackData\";\nimport type { ISolarflowState } from \"../ISolarflowState\";\nimport type { IZenIobDeviceDetails } from \"../IZenIobDeviceDetails\";\nimport { DeviceConnectionMode } from \"../../helpers/enums\";\nimport axios from \"axios\";\nimport { processDeviceProperties } from \"../../helpers/processDeviceProperties\";\nimport { allStates } from \"../../constants/sensorStates/allStates\";\n\nexport class ZenIobDevice {\n public zenIobDeviceDetails?: IZenIobDeviceDetails;\n public adapter: ZendureSolarflow;\n public deviceConnectionMode: DeviceConnectionMode | undefined = undefined;\n\n public productKey: string;\n public deviceKey: string;\n public snNumber: string | undefined = undefined;\n public productName: string;\n public deviceName: string;\n public ipAddress: string | undefined = undefined;\n public messageId: number = 0;\n public batteries: IDevicePack[] = [];\n\n public iotTopic: string | undefined = undefined;\n public functionTopic: string | undefined = undefined;\n public password: string = \"\";\n\n public isZenSdkSupported!: boolean; // No initializer - let derived classes set this\n public maxInputLimit: number = 0;\n public maxOutputLimit: number = 0;\n\n public controlStates: ISolarflowState[] = [];\n\n private zenSdkErrorCount: number = 0;\n private zenSdkPausedUntil: number = 0;\n private static readonly ZEN_SDK_MAX_ERROR_LOGS = 5;\n private static readonly ZEN_SDK_PAUSE_DURATION_MS = 10 * 60 * 1000;\n\n public constructor(\n _adapter: ZendureSolarflow,\n _productKey: string,\n _deviceKey: string,\n _productName: string,\n _deviceName: string,\n isZenSdkSupported: boolean,\n _zenIobDeviceDetails?: IZenIobDeviceDetails,\n ) {\n this.zenIobDeviceDetails = _zenIobDeviceDetails;\n\n this.adapter = _adapter;\n this.productKey = _productKey;\n this.deviceKey = _deviceKey;\n\n this.deviceName = _deviceName;\n this.productName = _productName;\n\n this.isZenSdkSupported = isZenSdkSupported;\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 // Update states from device details\n if (_zenIobDeviceDetails) {\n this.updateSolarFlowStatesFromDeviceDetails(_zenIobDeviceDetails);\n }\n\n // Calculate device password\n this.password = createHash(\"md5\").update(_deviceKey, \"utf8\").digest(\"hex\").toUpperCase().substring(8, 24);\n\n this.adapter.log.debug(\n `[ZenIobDevice] useZenSDK for device ${this.deviceKey}: Supported=${this.isZenSdkSupported} Config=${this.adapter.config.useZenSDK}`,\n );\n\n if (this.adapter.config.useZenSDK && this.isZenSdkSupported) {\n // Try to get data from device via zenSDK\n this.getZenSdkProperties()\n .then((success) => {\n if (success) {\n // Device is reachable, so set connection mode to zenSDK\n this.deviceConnectionMode = DeviceConnectionMode.zenSDK;\n\n this.updateSolarFlowState(\"connectionMode\", \"zenSDK\");\n this.updateSolarFlowState(\"wifiState\", 1);\n } else {\n this.updateSolarFlowState(\"wifiState\", 0);\n }\n })\n .catch(() => {\n this.updateSolarFlowState(\"wifiState\", 0);\n // After zenSDK failure, setup MQTT fallback\n this.setupMqttConnection();\n });\n } else {\n // zenSDK not enabled/supported, use MQTT directly\n this.setupMqttConnection();\n }\n }\n\n private setupMqttConnection(): void {\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\n private async updateSolarFlowStatesFromDeviceDetails(zenIobDeviceDetails: IZenIobDeviceDetails): Promise<void> {\n if (zenIobDeviceDetails?.online) {\n this.updateSolarFlowState(\"wifiState\", 1);\n } else if (zenIobDeviceDetails?.online == false) {\n this.updateSolarFlowState(\"wifiState\", 0);\n }\n\n if (zenIobDeviceDetails.productModel) {\n this.updateSolarFlowState(\"productName\", zenIobDeviceDetails.productModel);\n }\n\n if (zenIobDeviceDetails.ip) {\n this.ipAddress = zenIobDeviceDetails.ip;\n this.updateSolarFlowState(\"ip\", zenIobDeviceDetails.ip);\n }\n\n if (zenIobDeviceDetails.snNumber) {\n this.snNumber = zenIobDeviceDetails.snNumber;\n this.updateSolarFlowState(\"snNumber\", zenIobDeviceDetails.snNumber);\n }\n\n if (zenIobDeviceDetails.deviceName) {\n this.updateSolarFlowState(\"name\", zenIobDeviceDetails.deviceName);\n }\n\n if (zenIobDeviceDetails.protocol == \"mqtt\" && zenIobDeviceDetails.server && zenIobDeviceDetails.port) {\n await this.adapter?.extendObject(`${this.productKey}.${this.deviceKey}.mqttServer`, {\n type: \"state\",\n common: {\n name: {\n de: \"MQTT Server\",\n en: \"MQTT Server\",\n },\n type: \"string\",\n desc: \"MQTT Server\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"\",\n states: {},\n },\n native: {},\n });\n this.updateSolarFlowState(\"mqttServer\", `${zenIobDeviceDetails.server}:${zenIobDeviceDetails.port}`);\n }\n }\n\n private async createSolarFlowStates(): Promise<void> {\n const productKey = this.productKey.replace(this.adapter.FORBIDDEN_CHARS, \"\");\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 lastUpdate state manually, as it is never published via\n // /properties/report or MQTT and would otherwise never be created\n const lastUpdateState = allStates.lastUpdate;\n await this.adapter?.extendObject(`${productKey}.${deviceKey}.lastUpdate`, {\n type: \"state\",\n common: {\n name: {\n de: lastUpdateState.nameDe,\n en: lastUpdateState.nameEn,\n },\n type: lastUpdateState.type,\n desc: lastUpdateState.title,\n role: lastUpdateState.role,\n read: true,\n write: false,\n unit: lastUpdateState.unit,\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 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 const stateId = `${productKey}.${deviceKey}.control.${state.title}`;\n\n await this.adapter?.extendObject(stateId, {\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 def: state.def,\n },\n native: {},\n });\n\n if (state.def !== undefined) {\n const current = await this.adapter?.getStateAsync(stateId);\n if (!current || current.val === null || current.val === undefined) {\n await this.adapter?.setState(stateId, state.def, true);\n }\n }\n\n // Subscribe to states to respond to changes\n this.adapter?.subscribeStates(`${productKey}.${deviceKey}.control.${state.title}`);\n });\n\n if (this.adapter.config.useCalculation) {\n // Create calculations folder\n await this.adapter?.extendObject(`${productKey}.${deviceKey}.calculations`, {\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 await createCalculationStates(this.adapter, productKey, deviceKey);\n }\n }\n\n public getZenSdkProperties(): Promise<boolean> {\n if (Date.now() < this.zenSdkPausedUntil) {\n this.adapter.log.debug(\n `[getZenSdkProperties] Skipping poll for device ${this.deviceKey}, paused until ${new Date(\n this.zenSdkPausedUntil,\n ).toString()} after repeated errors!`,\n );\n\n return Promise.resolve(false);\n }\n\n this.adapter.log.debug(`[getZenSdkProperties] Getting properties with zenSDK for device ${this.deviceKey}!`);\n\n if (this.ipAddress) {\n const headers = {\n \"Content-Type\": \"application/json\",\n };\n\n const config = {\n headers: headers,\n timeout: 4000,\n };\n\n return axios\n .get(`http://${this.ipAddress}/properties/report`, config)\n .then(async (response) => {\n const data = await response.data;\n\n // Device is online, so set error count to 0!\n this.zenSdkErrorCount = 0;\n\n this.adapter.log.debug(\n `[getZenSdkProperties] Successfully got properties for device ${this.deviceKey} with zenSDK!}`,\n );\n\n // Process properties if they exist in the message\n if (data.properties) {\n processDeviceProperties(this, data.properties, true);\n\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.lastUpdate`, new Date().getTime(), true);\n\n this.updateSolarFlowState(\"wifiState\", 1);\n }\n\n // Process packData if it exists in the message\n if (data.packData) {\n this.addOrUpdatePackData(data.packData, true);\n }\n\n return true;\n })\n .catch((error) => {\n this.zenSdkErrorCount++;\n\n if (this.zenSdkErrorCount <= ZenIobDevice.ZEN_SDK_MAX_ERROR_LOGS) {\n this.adapter.log.error(\n `[getZenSdkProperties] Error getting properties for device ${this.deviceKey} with zenSDK: ${error}`,\n );\n }\n\n if (this.zenSdkErrorCount >= ZenIobDevice.ZEN_SDK_MAX_ERROR_LOGS) {\n this.adapter.log.warn(\n `[getZenSdkProperties] Reached ${ZenIobDevice.ZEN_SDK_MAX_ERROR_LOGS} consecutive errors for device ${this.deviceKey}, pausing zenSDK polling for ${\n ZenIobDevice.ZEN_SDK_PAUSE_DURATION_MS / 60000\n } minutes!`,\n );\n\n this.zenSdkPausedUntil = Date.now() + ZenIobDevice.ZEN_SDK_PAUSE_DURATION_MS;\n this.zenSdkErrorCount = 0;\n }\n\n this.updateSolarFlowState(\"wifiState\", 0);\n return false;\n });\n }\n this.adapter.log.error(`[getZenSdkProperties] IP address is not defined for device ${this.deviceKey}!`);\n\n return Promise.resolve(false);\n }\n\n private async axiosPostWithRetry(url: string, data: any, config: any, maxRetries: number = 3): Promise<any> {\n let lastError: any;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await axios.post(url, data, config);\n } catch (error) {\n lastError = error;\n\n if (attempt < maxRetries) {\n this.adapter.log.warn(\n `[retryAxiosPost] Request failed (attempt ${attempt}/${maxRetries}), retrying... Error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n throw lastError;\n }\n\n public writeZenSdkProperties(properties: string): Promise<boolean> {\n this.adapter.log.debug(\n `[writeZenSdkProperties] Writing properties with zenSDK for device ${this.deviceKey}: ${properties}`,\n );\n\n if (this.ipAddress) {\n const headers = {\n \"Content-Type\": \"application/json\",\n };\n\n const config = {\n headers: headers,\n timeout: 4000,\n };\n\n return this.axiosPostWithRetry(\n `http://${this.ipAddress}/properties/write`,\n {\n sn: this.snNumber, // Required\n properties: JSON.parse(properties),\n },\n config,\n )\n .then((response) => {\n this.adapter.log.debug(\n `[writeZenSdkProperties] Successfully wrote properties for device ${this.deviceKey} with zenSDK: ${properties} / status: ${response.status}`,\n );\n return true;\n })\n .catch((error) => {\n this.adapter.log.error(\n `[writeZenSdkProperties] Error writing properties with zenSDK for device ${this.deviceKey}: ${error}`,\n );\n return false;\n });\n }\n this.adapter.log.error(`[writeZenSdkProperties] IP address is not defined for device ${this.deviceKey}!`);\n return Promise.resolve(false);\n }\n\n public writeMqttProperties(properties: string): boolean {\n if (!this.iotTopic) {\n this.adapter.log.error(`[writeMqttProperties] IoT topic is not defined for device ${this.deviceKey}!`);\n return false;\n }\n if (this.productKey && this.deviceKey) {\n this.messageId += 1;\n // if local MQTT is enabled, prefer local MQTT client for setting properties, otherwise use cloud MQTT client\n if (\n this.adapter?.localMqttService?.mqttClient &&\n (this.deviceConnectionMode == DeviceConnectionMode.LocalMqtt ||\n this.deviceConnectionMode == DeviceConnectionMode.LocalMqttWithCloudRelay)\n ) {\n this.adapter?.localMqttService?.mqttClient?.publish(this.iotTopic, properties, { qos: 1 });\n } else if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter?.cloudMqttService?.mqttClient?.publish(this.iotTopic, properties, { qos: 1 });\n }\n }\n return true;\n }\n\n public invokeMqttFunction(properties: string): void {\n if (!this.functionTopic) {\n this.adapter.log.error(`[invokeMqttFunction] Function topic is not defined for device ${this.deviceKey}!`);\n return;\n }\n\n if (this.productKey && this.deviceKey) {\n // if local MQTT is enabled, prefer local MQTT client for invoking functions, otherwise use cloud MQTT client\n if (\n this.adapter?.localMqttService?.mqttClient &&\n (this.deviceConnectionMode == DeviceConnectionMode.LocalMqtt ||\n this.deviceConnectionMode == DeviceConnectionMode.LocalMqttWithCloudRelay)\n ) {\n this.adapter?.localMqttService?.mqttClient?.publish(this.functionTopic, properties, { qos: 1 });\n } else if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter?.cloudMqttService?.mqttClient?.publish(this.functionTopic, properties, { qos: 1 });\n }\n }\n }\n\n public subscribeReportTopic(): void {\n const reportTopic = `/${this.productKey}/${this.deviceKey}/#`; // Use wildcard topic to get ALL messages from device\n\n if (this.adapter) {\n // Subscribe to report topic with both MQTT clients, if available. This is necessary because we don't know which MQTT client the device will report to (cloud or local), so we have to subscribe with both to make sure we receive the reports.\n if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter.log.debug(`[subscribeReportTopic] Subscribing to MQTT Topic: ${reportTopic} (Cloud)`);\n this.adapter?.cloudMqttService?.mqttClient?.subscribe(reportTopic, onSubscribeReportTopic);\n }\n\n if (this.adapter?.localMqttService?.mqttClient) {\n this.adapter.log.debug(`[subscribeReportTopic] Subscribing to MQTT Topic: ${reportTopic} (Local)`);\n this.adapter?.localMqttService?.mqttClient?.subscribe(reportTopic, onSubscribeReportTopic);\n }\n\n this.adapter.log.debug(\n `[subscribeReportTopic] Setting connectionMode for device ${this.deviceKey}, relayMqttToCloud=${this.adapter.config.relayMqttToCloud}!`,\n );\n\n if (this && this.adapter?.localMqttService?.mqttClient && this.adapter.config.relayMqttToCloud) {\n this.deviceConnectionMode = DeviceConnectionMode.LocalMqttWithCloudRelay;\n\n this.updateSolarFlowState(\"connectionMode\", \"Local MQTT with Cloud Relay\");\n\n this.adapter?.log.debug(\n `[subscribeReportTopic] Set connectionMode to 'Local MQTT with Cloud Relay' for device ${this.deviceKey}`,\n );\n } else if (this && this.adapter?.localMqttService?.mqttClient) {\n if (this && this.deviceConnectionMode == undefined) {\n this.deviceConnectionMode = DeviceConnectionMode.LocalMqtt;\n\n this.updateSolarFlowState(\"connectionMode\", \"Local MQTT\");\n\n this.adapter?.log.debug(\n `[subscribeReportTopic] Set connectionMode to 'Local MQTT' for device ${this.deviceKey}`,\n );\n }\n } else if (this && this.adapter?.cloudMqttService?.mqttClient) {\n this.deviceConnectionMode = DeviceConnectionMode.CloudMqtt;\n\n this.updateSolarFlowState(\"connectionMode\", \"Cloud MQTT\");\n\n this.adapter?.log.debug(\n `[subscribeReportTopic] Set connectionMode to 'Cloud MQTT' for device ${this.deviceKey}`,\n );\n }\n }\n }\n\n private subscribeIotTopic(): void {\n const iotTopic = `iot/${this.productKey}/${this.deviceKey}/#`; // Use wildcard topic to get all messages from device\n\n if (this.adapter) {\n if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter?.log.debug(`[subscribeIotTopic] Subscribing to MQTT Topic: '${iotTopic}' (Cloud)`);\n this.adapter?.cloudMqttService?.mqttClient.subscribe(iotTopic, (error) => {\n onSubscribeIotTopic(error, this.productKey, this.deviceKey);\n });\n }\n\n if (this.adapter?.localMqttService?.mqttClient) {\n this.adapter?.log.debug(`[subscribeIotTopic] Subscribing to MQTT Topic: '${iotTopic}' (Local)`);\n this.adapter?.localMqttService?.mqttClient.subscribe(iotTopic, (error) => {\n onSubscribeIotTopic(error, this.productKey, this.deviceKey);\n });\n }\n }\n }\n\n public async updateProperty(property: string, value: number): Promise<boolean> {\n if (this.isZenSdkSupported && this.adapter.config.useZenSDK) {\n const setPropertyContent = { [property]: value };\n this.adapter.log.debug(\n `[updateProperty] Updating property ${property} with value ${value} for device ${this.deviceKey} using zenSDK!`,\n );\n return await this.writeZenSdkProperties(JSON.stringify(setPropertyContent));\n }\n const setPropertyContent = { properties: { [property]: value } };\n this.adapter.log.debug(\n `[updateProperty] Updating property ${property} with value ${value} for device ${this.deviceKey} using MQTT!`,\n );\n return this.writeMqttProperties(JSON.stringify(setPropertyContent));\n }\n\n public setDeviceAutomationInOutLimit(limit: number): void {\n this.adapter?.log.error(\n `[setDeviceAutomationInOutLimit] 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(`[setAcMode] Method setAcMode (set to ${acMode}) not defined in base class!`);\n return;\n }\n\n public setDcSwitch(dcSwitch: boolean): void {\n this.adapter?.log.error(`[setDcSwitch] Method setDcSwitch (set to ${dcSwitch}) not defined in base class!`);\n return;\n }\n\n public setAcSwitch(acSwitch: boolean): void {\n this.adapter?.log.error(`[setAcSwitch] Method setAcSwitch (set to ${acSwitch}) not defined in base class!`);\n return;\n }\n\n public setHubState(hubState: number): void {\n if (this.productKey && this.deviceKey) {\n if (hubState == 0 || hubState == 1) {\n this.updateProperty(\"hubState\", hubState);\n } else {\n this.adapter.log.debug(`[setHubState] Hub state is not 0 or 1!`);\n }\n }\n }\n\n public setGridReverse(gridReverse: number): void {\n if (this.productKey && this.deviceKey) {\n if (gridReverse >= 0 && gridReverse <= 2) {\n this.updateProperty(\"gridReverse\", gridReverse);\n } else {\n this.adapter.log.debug(`[setGridReverse] Grid reverse value ${gridReverse} is not 0, 1 or 2!`);\n }\n }\n }\n\n public setPassMode(passMode: number): void {\n if (this.productKey && this.deviceKey) {\n this.updateProperty(\"passMode\", passMode);\n }\n }\n\n public setAutoRecover(autoRecover: boolean): void {\n if (this.productKey && this.deviceKey) {\n this.updateProperty(\"autoRecover\", autoRecover ? 1 : 0);\n }\n }\n\n /**\n * Will set the discharge limit (minSoc)\n *\n * @param socSet the desired minimum soc\n * @param minSoc\n * @returns void\n */\n public setDischargeLimit(minSoc: number): void {\n if (this.productKey && this.deviceKey) {\n if (minSoc >= 0 && minSoc <= 50) {\n this.updateProperty(\"minSoc\", minSoc * 10);\n } else {\n this.adapter.log.debug(`[setDischargeLimit] Discharge limit is not in range 0<>50!`);\n }\n }\n }\n\n /**\n * Will set the maximum charge limit\n *\n * @param socSet the desired max SOC\n * @returns void\n */\n public setChargeLimit(socSet: number): void {\n if (this.productKey && this.deviceKey) {\n if (socSet >= 40 && socSet <= 100) {\n this.updateProperty(\"socSet\", socSet * 10);\n } else {\n this.adapter.log.debug(`[setChargeLimit] Charge limit is not in range 40<>100!`);\n }\n }\n }\n\n /**\n * Will set the 'energy plan'\n *\n * @param autoModel autoModel value, like 8 for smart matching\n * @returns void\n */\n public setAutoModel(autoModel: number): void {\n if (this.isZenSdkSupported && this.adapter.config.useZenSDK) {\n if (autoModel != 0) {\n this.adapter.log.warn(`[setAutoModel] Can't set autoModel to a value other than 0 when using zenSDK!`);\n }\n\n this.updateProperty(\"autoModel\", 0);\n return;\n }\n\n if (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(`[setAutoModel] Setting autoModel for device key ${this.deviceKey} to ${autoModel}!`);\n this.writeMqttProperties(JSON.stringify(setAutoModelContent));\n }\n }\n\n public async setOutputLimit(limit: number): Promise<void> {\n if (this.productKey && this.deviceKey) {\n // Check if autoModel is set to 0 (Nothing) or 8 (Smart Matching)\n const autoModel = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.autoModel`))?.val;\n\n if (autoModel != 0) {\n this.adapter.log.warn(\"Operation mode (autoModel) is not set to '0', we can't set the output limit!\");\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 (lowVoltageBlockState && lowVoltageBlockState.val && lowVoltageBlockState.val == true) {\n limit = 0;\n }\n\n const fullChargeNeeded = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.control.fullChargeNeeded`,\n );\n\n if (fullChargeNeeded && fullChargeNeeded.val && fullChargeNeeded.val == true) {\n limit = 0;\n }\n }\n\n const currentLimit = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.outputLimit`))?.val;\n\n if (currentLimit != null && currentLimit != undefined) {\n if (currentLimit != limit) {\n const timestamp = new Date();\n timestamp.setMilliseconds(0);\n\n this.updateProperty(\"outputLimit\", limit);\n }\n }\n }\n }\n\n public setInputLimit(limit: number): void {\n if (this.productKey && this.deviceKey) {\n // Limit has always to be positive!\n if (limit < 0) {\n this.adapter.log.debug(`[setInputLimit] limit ${limit} is negative, converting to positive!`);\n limit = Math.abs(limit);\n }\n\n if (limit) {\n limit = Math.round(limit);\n } else {\n limit = 0;\n }\n\n if (limit < 0) {\n limit = 0;\n } else if (limit > 0 && limit <= 30) {\n limit = 30;\n } else if (limit > this.maxInputLimit) {\n limit = this.maxInputLimit;\n }\n\n if (this.productKey.includes(\"8bm93h\")) {\n // Das Limit kann beim ACE nur in 100er Schritten gesetzt werden\n limit = Math.ceil(limit / 100) * 100;\n }\n\n this.updateProperty(\"inputLimit\", limit);\n }\n }\n\n public setSmartMode(smartModeOn: boolean): void {\n if (this.productKey && this.deviceKey) {\n this.updateProperty(\"smartMode\", smartModeOn ? 1 : 0);\n }\n }\n\n public setBuzzerSwitch(buzzerOn: boolean): void {\n if (this.productKey && this.deviceKey) {\n this.updateProperty(\"buzzerSwitch\", buzzerOn ? 1 : 0);\n }\n }\n\n public triggerFullTelemetryUpdate(): void {\n if (this.isZenSdkSupported && this.adapter.config.useZenSDK) {\n this.getZenSdkProperties();\n return;\n }\n\n if (this.productKey && this.deviceKey) {\n const getAllContent = { properties: [\"getAll\"] };\n this.adapter.log.debug(\n `[triggerFullTelemetryUpdate] Triggering full telemetry update for device key ${this.deviceKey}!`,\n );\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/read`;\n\n this.messageId += 1;\n // if local MQTT is enabled, prefer local MQTT client for setting properties, otherwise use cloud MQTT client\n if (this.adapter?.localMqttService?.mqttClient) {\n this.adapter?.localMqttService?.mqttClient?.publish(topic, JSON.stringify(getAllContent), { qos: 1 });\n } else if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter?.cloudMqttService?.mqttClient?.publish(topic, JSON.stringify(getAllContent), { qos: 1 });\n }\n }\n }\n\n public async updateSolarFlowState(state: string, val: number | string | boolean): Promise<void> {\n const stateId = `${this.productKey}.${this.deviceKey}.${state}`;\n\n // skip if state does not exist\n const obj = await this.adapter?.getObjectAsync(stateId);\n if (!obj) {\n this.adapter.log.debug(`[updateSolarFlowState] state ${stateId} not found, skipping update`);\n return;\n }\n\n const currentValue = await this.adapter.getStateAsync(stateId);\n\n await this.adapter?.setState(stateId, val, true);\n\n if (currentValue?.val != val && state != \"wifiState\") {\n // Set lastUpdate for deviceKey if a value was changed!\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.lastUpdate`, new Date().getTime(), true);\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.wifiState`);\n\n if (currentWifiState && currentWifiState.val == 0) {\n this.updateSolarFlowState(\"wifiState\", 1);\n }\n }\n }\n\n public async updateSolarFlowControlState(state: string, val: number | string | boolean): Promise<void> {\n // First check if state exist\n const stateExist = await this.adapter?.objectExists(`${this.productKey}.${this.deviceKey}.control.${state}`);\n\n // Update the control state\n if (stateExist) {\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.control.${state}`, val, true);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await -- kept async, caller in processDeviceProperties.ts awaits this method\n addOrUpdatePackData = async (packData: IPackData[], isSolarFlow: boolean): Promise<void> => {\n if (this.adapter && this.productKey && this.deviceKey) {\n packData.forEach(async (x) => {\n if (x.sn && this.adapter) {\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[1] === \"O\" && x.sn[2] === \"4\") {\n batType = \"I1920\";\n }\n if (x.sn[3] == \"F\") {\n batType = \"AB2000S\";\n } else if (x.sn[3] == \"E\") {\n batType = \"AB2000X\";\n } else {\n batType = \"AB2000\";\n }\n } else if (x.sn.startsWith(\"F\")) {\n batType = \"AB3000X\";\n } else if (x.sn.startsWith(\"G\")) {\n batType = \"AB3000L\";\n } else if (x.sn.startsWith(\"J\")) {\n batType = \"I2400\";\n }\n\n if (!this.batteries.some((y) => y.packSn == x.sn)) {\n this.batteries.push({ packSn: x.sn, type: batType });\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 const key = `${this.productKey}.${this.deviceKey}.packData.${x.sn}`.replace(this.adapter.FORBIDDEN_CHARS, \"\");\n\n await this.adapter?.extendObject(key, {\n type: \"channel\",\n common: { name: { de: batType, en: batType } },\n native: {},\n });\n\n const createPackState = async (fieldName: string): Promise<void> => {\n const def = allStates[fieldName];\n if (!def) {\n return;\n }\n await this.adapter?.extendObject(`${key}.${fieldName}`, {\n type: \"state\",\n common: {\n name: { de: def.nameDe, en: def.nameEn },\n type: def.type,\n desc: def.title,\n role: def.role,\n read: true,\n write: false,\n unit: def.unit,\n },\n native: {},\n });\n };\n\n const touchLastUpdate = async (fieldName: string, newValue: number): Promise<void> => {\n const current = await this.adapter?.getStateAsync(`${key}.${fieldName}`);\n if (current?.val && newValue != current.val) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true,\n );\n const wifiState = await this.adapter?.getStateAsync(`${this.productKey}.${this.deviceKey}.wifiState`);\n if (wifiState?.val == 0) {\n this.updateSolarFlowState(\"wifiState\", 1);\n }\n }\n };\n\n // Phase 1: collect transformed values; side effects happen here\n const packStatesToSet = new Map<string, number | string>();\n\n packStatesToSet.set(\"model\", batType);\n packStatesToSet.set(\"sn\", x.sn);\n\n if (x.socLevel) {\n packStatesToSet.set(\"socLevel\", x.socLevel);\n }\n\n if (x.maxTemp) {\n const maxTempCelsius = x.maxTemp / 10 - 273.15;\n await touchLastUpdate(\"maxTemp\", maxTempCelsius);\n packStatesToSet.set(\"maxTemp\", maxTempCelsius);\n }\n\n if (x.minVol) {\n const minVol = x.minVol / 100;\n await touchLastUpdate(\"minVol\", minVol);\n packStatesToSet.set(\"minVol\", minVol);\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 let batcur = 0;\n\n if (x.batcur > 32767) {\n batcur -= 65536;\n }\n packStatesToSet.set(\"batcur\", batcur / 10);\n }\n\n if (x.maxVol) {\n const maxVol = x.maxVol / 100;\n await touchLastUpdate(\"maxVol\", maxVol);\n packStatesToSet.set(\"maxVol\", maxVol);\n }\n\n if (x.totalVol) {\n const totalVol = x.totalVol / 100;\n await touchLastUpdate(\"totalVol\", totalVol);\n packStatesToSet.set(\"totalVol\", totalVol);\n if (isSolarFlow) {\n this.checkVoltage(totalVol);\n }\n }\n\n if (x.soh) {\n packStatesToSet.set(\"soh\", x.soh / 10);\n }\n if (x.power) {\n packStatesToSet.set(\"power\", x.power);\n }\n\n // Phase 2: create states and set all collected values\n for (const [fieldName, value] of packStatesToSet) {\n await createPackState(fieldName);\n await this.adapter?.setState(`${key}.${fieldName}`, value, true);\n }\n\n // Debug unknown properties\n let found = false;\n Object.entries(x).forEach(([k, value]) => {\n knownPackDataProperties.forEach((property: string) => {\n if (property == k) {\n found = true;\n }\n });\n if (!found) {\n this.adapter?.log.debug(\n `[addOrUpdatePackData] ${k} 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(`${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`, true, true);\n\n // Low Voltage Block activated, stop power input immediately\n const autoModel = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.autoModel`))?.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(`${this.productKey}.${this.deviceKey}.electricLevel`);\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(`${this.productKey}.${this.deviceKey}.control.fullChargeNeeded`, true, true);\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(`${this.productKey}.${this.deviceKey}.hubState`);\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(`${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`, false, true);\n\n if (this.adapter.config.useLowVoltageBlock && this.adapter.config.forceShutdownOnLowVoltage) {\n this.setDischargeLimit(this.adapter.config.dischargeLimit ? this.adapter.config.dischargeLimit : 5);\n }\n }\n }\n }\n\n /**\n * Calculates the energy for all items in 'calculationStateKeys'.\n *\n * @returns Promise<void>\n * @beta\n */\n public calculateEnergy(): void {\n calculationStateKeys.forEach(async (stateKey) => {\n let stateNameEnergyWh = \"\";\n let stateNameEnergykWh = \"\";\n let stateNamePower = \"\";\n\n switch (stateKey) {\n case \"pvPower1\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower1`;\n break;\n case \"pvPower2\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower2`;\n break;\n case \"pvPower3\":\n if (await this.adapter.getObjectAsync(`${this.productKey}.${this.deviceKey}.pvPower3`)) {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower3`;\n }\n break;\n case \"pvPower4\":\n if (await this.adapter.getObjectAsync(`${this.productKey}.${this.deviceKey}.pvPower4`)) {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower4`;\n }\n break;\n default:\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.${stateKey}Power`;\n break;\n }\n\n if (stateNamePower != \"\") {\n // If stateNamePower found, proceed with calculation, otherwise skip this stateKey\n this.adapter.log.debug(`[calculateEnergy] No stateNamePower found for ${stateKey}!`);\n const currentPowerState = await this.adapter?.getStateAsync(stateNamePower);\n\n const currentEnergyState = await this.adapter?.getStateAsync(stateNameEnergyWh);\n\n if (!currentEnergyState?.val || currentEnergyState?.val == 0) {\n // Workaround, set Val to very low value to avoid Jump in data...\n await this.adapter?.setState(stateNameEnergyWh, 0.000001, true);\n } else if (\n currentEnergyState &&\n currentEnergyState.lc &&\n currentPowerState &&\n currentPowerState.val != undefined &&\n currentPowerState.val != null\n ) {\n // Timeframe = 30000ms, Job runs every 30 seconds...\n const timeFrame = 30000;\n\n // Calculate Energy value (Wh) from current power in the timeframe from last run...\n const addEnergyValue = (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(stateNameEnergykWh, Number((newEnergyValue / 1000).toFixed(2)), true);\n\n // SOC and energy in batteries\n if ((stateKey == \"outputPack\" || stateKey == \"packInput\") && addEnergyValue > 0) {\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(`${this.productKey}.${this.deviceKey}.calculations.remainOutTime`, \"\", true);\n }\n }\n } else if (currentPowerState && currentEnergyState) {\n await this.adapter?.setState(stateNameEnergyWh, 0, true);\n await this.adapter?.setState(stateNameEnergykWh, 0, true);\n }\n }\n });\n }\n\n public calculateSocAndEnergy = async (stateKey: string, value: number): 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 = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.minSoc`))?.val;\n const currentSoc = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.electricLevel`))?.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(currentEnergyMaxState ? currentEnergyMaxState.val : 0);\n\n let currentEnergyWh = currentEnergyState?.val ? Number(currentEnergyState?.val) : 0;\n\n if (currentEnergyWh == null || currentEnergyWh == undefined || currentEnergyWh <= 0) {\n currentEnergyWh = 0;\n }\n\n if (this.productKey == \"yWF7hV\") {\n // The device is an AIO 2400, so set maximum Wh to 2400!\n energyWhMax = 2400;\n } else {\n // Iterate over all batteries!\n for (let i = 0; i < this.batteries.length; i++) {\n if (this.batteries[i].type.includes(\"AB1000\")) {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 960;\n } else if (this.batteries[i].type.includes(\"AB2000\")) {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 1920;\n } else if (this.batteries[i].type.includes(\"AB3000\")) {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 2880;\n } else if (this.batteries[i].type.includes(\"I2400\")) {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 2400;\n } else if (this.batteries[i].type.includes(\"I1920\")) {\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 = stateKey == \"outputPack\" ? currentEnergyWh + value : currentEnergyWh - value;\n\n // If greater than Max of batteries, set it to this value.\n if (stateKey == \"outputPack\" && energyWhMax != undefined && newEnergyWh > energyWhMax) {\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(`${this.productKey}.${this.deviceKey}.calculations.energyWh`, newEnergyWh, true);\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 (stateKey == \"outputPack\" && currentOutputPackPower?.val != null && currentOutputPackPower != undefined) {\n // Charging, calculate remaining charging time\n const toCharge = currentMaxValue - newEnergyWh;\n\n const remainHoursAsDecimal = toCharge / Number(currentOutputPackPower.val);\n\n if (remainHoursAsDecimal < 48.0) {\n const remainFormatted = toHoursAndMinutes(Math.round(remainHoursAsDecimal * 60));\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(`${this.productKey}.${this.deviceKey}.calculations.remainInputTime`, \"\", true);\n }\n } else if (stateKey == \"packInput\" && currentPackInputPower != null && currentPackInputPower != undefined) {\n // Discharging, calculate remaining discharge time\n const remainHoursAsDecimal = newEnergyWh / Number(currentPackInputPower.val);\n const remainFormatted = toHoursAndMinutes(Math.round(remainHoursAsDecimal * 60));\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(`${this.productKey}.${this.deviceKey}.calculations.remainOutTime`, \"\", true);\n }\n }\n }\n } else if (newEnergyWh <= 0 && stateKey == \"outputPack\") {\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.calculations.remainInputTime`, \"\", true);\n } else if (newEnergyWh <= 0 && stateKey == \"packInput\") {\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.calculations.remainOutTime`, \"\", true);\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(`${this.productKey}.${this.deviceKey}.calculations.soc`, 0, true);\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(`${this.productKey}.${this.deviceKey}.calculations.energyWhMax`, newMax, true);\n\n // Set Energy in Battery to 0\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.calculations.energyWh`, 0, true);\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 switch (stateKey) {\n case \"pvPower1\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodaykWh`;\n break;\n case \"pvPower2\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodaykWh`;\n break;\n case \"pvPower3\":\n if (await this.adapter.getObjectAsync(`${this.productKey}.${this.deviceKey}.pvPower3`)) {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodaykWh`;\n } else {\n return;\n }\n break;\n case \"pvPower4\":\n if (await this.adapter.getObjectAsync(`${this.productKey}.${this.deviceKey}.pvPower4`)) {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodaykWh`;\n } else {\n return;\n }\n break;\n default:\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\n break;\n }\n\n if (stateNameEnergyWh != \"\" && stateNameEnergykWh != \"\") {\n await this.adapter?.setState(stateNameEnergyWh, 0, true);\n await this.adapter?.setState(stateNameEnergykWh, 0, true);\n }\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { createHash } from \"node:crypto\";\nimport { calculationStateKeys } from \"../../constants/sensorStates/constants\";\nimport { createCalculationStates } from \"../../helpers/createCalculationStates\";\nimport { toHoursAndMinutes } from \"../../helpers/timeHelper\";\nimport type { ZendureSolarflow } from \"../../main\";\nimport {\n knownPackDataProperties,\n onSubscribeIotTopic,\n onSubscribeReportTopic,\n} from \"../../services/mqtt/mqttSharedService\";\nimport type { IDevicePack } from \"../IDevicePack\";\nimport type { IPackData } from \"../IPackData\";\nimport type { ISolarflowState } from \"../ISolarflowState\";\nimport type { IZenIobDeviceDetails } from \"../IZenIobDeviceDetails\";\nimport { DeviceConnectionMode } from \"../../helpers/enums\";\nimport axios from \"axios\";\nimport { ensureState, processDeviceProperties } from \"../../helpers/processDeviceProperties\";\nimport { allStates } from \"../../constants/sensorStates/allStates\";\n\nexport class ZenIobDevice {\n public zenIobDeviceDetails?: IZenIobDeviceDetails;\n public adapter: ZendureSolarflow;\n public deviceConnectionMode: DeviceConnectionMode | undefined = undefined;\n\n public productKey: string;\n public deviceKey: string;\n public snNumber: string | undefined = undefined;\n public productName: string;\n public deviceName: string;\n public ipAddress: string | undefined = undefined;\n public messageId: number = 0;\n public batteries: IDevicePack[] = [];\n\n public iotTopic: string | undefined = undefined;\n public functionTopic: string | undefined = undefined;\n public password: string = \"\";\n\n public isZenSdkSupported!: boolean; // No initializer - let derived classes set this\n public maxInputLimit: number = 0;\n public maxOutputLimit: number = 0;\n\n public controlStates: ISolarflowState[] = [];\n\n private zenSdkErrorCount: number = 0;\n private zenSdkPausedUntil: number = 0;\n private static readonly ZEN_SDK_MAX_ERROR_LOGS = 5;\n private static readonly ZEN_SDK_PAUSE_DURATION_MS = 10 * 60 * 1000;\n\n public constructor(\n _adapter: ZendureSolarflow,\n _productKey: string,\n _deviceKey: string,\n _productName: string,\n _deviceName: string,\n isZenSdkSupported: boolean,\n _zenIobDeviceDetails?: IZenIobDeviceDetails,\n ) {\n this.zenIobDeviceDetails = _zenIobDeviceDetails;\n\n this.adapter = _adapter;\n this.productKey = _productKey;\n this.deviceKey = _deviceKey;\n\n this.deviceName = _deviceName;\n this.productName = _productName;\n\n this.isZenSdkSupported = isZenSdkSupported;\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 // Update states from device details\n if (_zenIobDeviceDetails) {\n this.updateSolarFlowStatesFromDeviceDetails(_zenIobDeviceDetails);\n }\n\n // Calculate device password\n this.password = createHash(\"md5\").update(_deviceKey, \"utf8\").digest(\"hex\").toUpperCase().substring(8, 24);\n\n this.adapter.log.debug(\n `[ZenIobDevice] useZenSDK for device ${this.deviceKey}: Supported=${this.isZenSdkSupported} Config=${this.adapter.config.useZenSDK}`,\n );\n\n if (this.adapter.config.useZenSDK && this.isZenSdkSupported) {\n // Try to get data from device via zenSDK\n this.getZenSdkProperties()\n .then((success) => {\n if (success) {\n // Device is reachable, so set connection mode to zenSDK\n this.deviceConnectionMode = DeviceConnectionMode.zenSDK;\n\n this.updateSolarFlowState(\"connectionMode\", \"zenSDK\");\n this.updateSolarFlowState(\"wifiState\", 1);\n } else {\n this.updateSolarFlowState(\"wifiState\", 0);\n }\n })\n .catch(() => {\n this.updateSolarFlowState(\"wifiState\", 0);\n // After zenSDK failure, setup MQTT fallback\n this.setupMqttConnection();\n });\n } else {\n // zenSDK not enabled/supported, use MQTT directly\n this.setupMqttConnection();\n }\n }\n\n private setupMqttConnection(): void {\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\n private async updateSolarFlowStatesFromDeviceDetails(zenIobDeviceDetails: IZenIobDeviceDetails): Promise<void> {\n if (zenIobDeviceDetails?.online) {\n this.updateSolarFlowState(\"wifiState\", 1);\n } else if (zenIobDeviceDetails?.online == false) {\n this.updateSolarFlowState(\"wifiState\", 0);\n }\n\n if (zenIobDeviceDetails.productModel) {\n this.updateSolarFlowState(\"productName\", zenIobDeviceDetails.productModel);\n }\n\n if (zenIobDeviceDetails.ip) {\n this.ipAddress = zenIobDeviceDetails.ip;\n this.updateSolarFlowState(\"ip\", zenIobDeviceDetails.ip);\n }\n\n if (zenIobDeviceDetails.snNumber) {\n this.snNumber = zenIobDeviceDetails.snNumber;\n this.updateSolarFlowState(\"snNumber\", zenIobDeviceDetails.snNumber);\n }\n\n if (zenIobDeviceDetails.deviceName) {\n this.updateSolarFlowState(\"name\", zenIobDeviceDetails.deviceName);\n }\n\n if (zenIobDeviceDetails.protocol == \"mqtt\" && zenIobDeviceDetails.server && zenIobDeviceDetails.port) {\n await this.adapter?.extendObject(`${this.productKey}.${this.deviceKey}.mqttServer`, {\n type: \"state\",\n common: {\n name: {\n de: \"MQTT Server\",\n en: \"MQTT Server\",\n },\n type: \"string\",\n desc: \"MQTT Server\",\n role: \"value\",\n read: true,\n write: false,\n unit: \"\",\n states: {},\n },\n native: {},\n });\n this.updateSolarFlowState(\"mqttServer\", `${zenIobDeviceDetails.server}:${zenIobDeviceDetails.port}`);\n }\n }\n\n private async createSolarFlowStates(): Promise<void> {\n const productKey = this.productKey.replace(this.adapter.FORBIDDEN_CHARS, \"\");\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 lastUpdate state manually, as it is never published via\n // /properties/report or MQTT and would otherwise never be created\n const lastUpdateState = allStates.lastUpdate;\n await this.adapter?.extendObject(`${productKey}.${deviceKey}.lastUpdate`, {\n type: \"state\",\n common: {\n name: {\n de: lastUpdateState.nameDe,\n en: lastUpdateState.nameEn,\n },\n type: lastUpdateState.type,\n desc: lastUpdateState.title,\n role: lastUpdateState.role,\n read: true,\n write: false,\n unit: lastUpdateState.unit,\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 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 const stateId = `${productKey}.${deviceKey}.control.${state.title}`;\n\n await this.adapter?.extendObject(stateId, {\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 def: state.def,\n },\n native: {},\n });\n\n if (state.def !== undefined) {\n const current = await this.adapter?.getStateAsync(stateId);\n if (!current || current.val === null || current.val === undefined) {\n await this.adapter?.setState(stateId, state.def, true);\n }\n }\n\n // Subscribe to states to respond to changes\n this.adapter?.subscribeStates(`${productKey}.${deviceKey}.control.${state.title}`);\n });\n\n if (this.adapter.config.useCalculation) {\n // Create calculations folder\n await this.adapter?.extendObject(`${productKey}.${deviceKey}.calculations`, {\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 await createCalculationStates(this.adapter, productKey, deviceKey);\n }\n }\n\n public getZenSdkProperties(): Promise<boolean> {\n if (Date.now() < this.zenSdkPausedUntil) {\n this.adapter.log.debug(\n `[getZenSdkProperties] Skipping poll for device ${this.deviceKey}, paused until ${new Date(\n this.zenSdkPausedUntil,\n ).toString()} after repeated errors!`,\n );\n\n return Promise.resolve(false);\n }\n\n this.adapter.log.debug(`[getZenSdkProperties] Getting properties with zenSDK for device ${this.deviceKey}!`);\n\n if (this.ipAddress) {\n const headers = {\n \"Content-Type\": \"application/json\",\n };\n\n const config = {\n headers: headers,\n timeout: 4000,\n };\n\n return axios\n .get(`http://${this.ipAddress}/properties/report`, config)\n .then(async (response) => {\n const data = await response.data;\n\n // Device is online, so set error count to 0!\n this.zenSdkErrorCount = 0;\n\n this.adapter.log.debug(\n `[getZenSdkProperties] Successfully got properties for device ${this.deviceKey} with zenSDK!}`,\n );\n\n // Process properties if they exist in the message\n if (data.properties) {\n processDeviceProperties(this, data.properties, true);\n\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.lastUpdate`, new Date().getTime(), true);\n\n this.updateSolarFlowState(\"wifiState\", 1);\n }\n\n // Process packData if it exists in the message\n if (data.packData) {\n this.addOrUpdatePackData(data.packData, true);\n }\n\n return true;\n })\n .catch((error) => {\n this.zenSdkErrorCount++;\n\n if (this.zenSdkErrorCount <= ZenIobDevice.ZEN_SDK_MAX_ERROR_LOGS) {\n this.adapter.log.error(\n `[getZenSdkProperties] Error getting properties for device ${this.deviceKey} with zenSDK: ${error}`,\n );\n }\n\n if (this.zenSdkErrorCount >= ZenIobDevice.ZEN_SDK_MAX_ERROR_LOGS) {\n this.adapter.log.warn(\n `[getZenSdkProperties] Reached ${ZenIobDevice.ZEN_SDK_MAX_ERROR_LOGS} consecutive errors for device ${this.deviceKey}, pausing zenSDK polling for ${\n ZenIobDevice.ZEN_SDK_PAUSE_DURATION_MS / 60000\n } minutes!`,\n );\n\n this.zenSdkPausedUntil = Date.now() + ZenIobDevice.ZEN_SDK_PAUSE_DURATION_MS;\n this.zenSdkErrorCount = 0;\n }\n\n this.updateSolarFlowState(\"wifiState\", 0);\n return false;\n });\n }\n this.adapter.log.error(`[getZenSdkProperties] IP address is not defined for device ${this.deviceKey}!`);\n\n return Promise.resolve(false);\n }\n\n private async axiosPostWithRetry(url: string, data: any, config: any, maxRetries: number = 3): Promise<any> {\n let lastError: any;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await axios.post(url, data, config);\n } catch (error) {\n lastError = error;\n\n if (attempt < maxRetries) {\n this.adapter.log.warn(\n `[retryAxiosPost] Request failed (attempt ${attempt}/${maxRetries}), retrying... Error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n throw lastError;\n }\n\n public writeZenSdkProperties(properties: string): Promise<boolean> {\n this.adapter.log.debug(\n `[writeZenSdkProperties] Writing properties with zenSDK for device ${this.deviceKey}: ${properties}`,\n );\n\n if (this.ipAddress) {\n const headers = {\n \"Content-Type\": \"application/json\",\n };\n\n const config = {\n headers: headers,\n timeout: 4000,\n };\n\n return this.axiosPostWithRetry(\n `http://${this.ipAddress}/properties/write`,\n {\n sn: this.snNumber, // Required\n properties: JSON.parse(properties),\n },\n config,\n )\n .then((response) => {\n this.adapter.log.debug(\n `[writeZenSdkProperties] Successfully wrote properties for device ${this.deviceKey} with zenSDK: ${properties} / status: ${response.status}`,\n );\n return true;\n })\n .catch((error) => {\n this.adapter.log.error(\n `[writeZenSdkProperties] Error writing properties with zenSDK for device ${this.deviceKey}: ${error}`,\n );\n return false;\n });\n }\n this.adapter.log.error(`[writeZenSdkProperties] IP address is not defined for device ${this.deviceKey}!`);\n return Promise.resolve(false);\n }\n\n public writeMqttProperties(properties: string): boolean {\n if (!this.iotTopic) {\n this.adapter.log.error(`[writeMqttProperties] IoT topic is not defined for device ${this.deviceKey}!`);\n return false;\n }\n if (this.productKey && this.deviceKey) {\n this.messageId += 1;\n // if local MQTT is enabled, prefer local MQTT client for setting properties, otherwise use cloud MQTT client\n if (\n this.adapter?.localMqttService?.mqttClient &&\n (this.deviceConnectionMode == DeviceConnectionMode.LocalMqtt ||\n this.deviceConnectionMode == DeviceConnectionMode.LocalMqttWithCloudRelay)\n ) {\n this.adapter?.localMqttService?.mqttClient?.publish(this.iotTopic, properties, { qos: 1 });\n } else if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter?.cloudMqttService?.mqttClient?.publish(this.iotTopic, properties, { qos: 1 });\n }\n }\n return true;\n }\n\n public invokeMqttFunction(properties: string): void {\n if (!this.functionTopic) {\n this.adapter.log.error(`[invokeMqttFunction] Function topic is not defined for device ${this.deviceKey}!`);\n return;\n }\n\n if (this.productKey && this.deviceKey) {\n // if local MQTT is enabled, prefer local MQTT client for invoking functions, otherwise use cloud MQTT client\n if (\n this.adapter?.localMqttService?.mqttClient &&\n (this.deviceConnectionMode == DeviceConnectionMode.LocalMqtt ||\n this.deviceConnectionMode == DeviceConnectionMode.LocalMqttWithCloudRelay)\n ) {\n this.adapter?.localMqttService?.mqttClient?.publish(this.functionTopic, properties, { qos: 1 });\n } else if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter?.cloudMqttService?.mqttClient?.publish(this.functionTopic, properties, { qos: 1 });\n }\n }\n }\n\n public subscribeReportTopic(): void {\n const reportTopic = `/${this.productKey}/${this.deviceKey}/#`; // Use wildcard topic to get ALL messages from device\n\n if (this.adapter) {\n // Subscribe to report topic with both MQTT clients, if available. This is necessary because we don't know which MQTT client the device will report to (cloud or local), so we have to subscribe with both to make sure we receive the reports.\n if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter.log.debug(`[subscribeReportTopic] Subscribing to MQTT Topic: ${reportTopic} (Cloud)`);\n this.adapter?.cloudMqttService?.mqttClient?.subscribe(reportTopic, onSubscribeReportTopic);\n }\n\n if (this.adapter?.localMqttService?.mqttClient) {\n this.adapter.log.debug(`[subscribeReportTopic] Subscribing to MQTT Topic: ${reportTopic} (Local)`);\n this.adapter?.localMqttService?.mqttClient?.subscribe(reportTopic, onSubscribeReportTopic);\n }\n\n this.adapter.log.debug(\n `[subscribeReportTopic] Setting connectionMode for device ${this.deviceKey}, relayMqttToCloud=${this.adapter.config.relayMqttToCloud}!`,\n );\n\n if (this && this.adapter?.localMqttService?.mqttClient && this.adapter.config.relayMqttToCloud) {\n this.deviceConnectionMode = DeviceConnectionMode.LocalMqttWithCloudRelay;\n\n this.updateSolarFlowState(\"connectionMode\", \"Local MQTT with Cloud Relay\");\n\n this.adapter?.log.debug(\n `[subscribeReportTopic] Set connectionMode to 'Local MQTT with Cloud Relay' for device ${this.deviceKey}`,\n );\n } else if (this && this.adapter?.localMqttService?.mqttClient) {\n if (this && this.deviceConnectionMode == undefined) {\n this.deviceConnectionMode = DeviceConnectionMode.LocalMqtt;\n\n this.updateSolarFlowState(\"connectionMode\", \"Local MQTT\");\n\n this.adapter?.log.debug(\n `[subscribeReportTopic] Set connectionMode to 'Local MQTT' for device ${this.deviceKey}`,\n );\n }\n } else if (this && this.adapter?.cloudMqttService?.mqttClient) {\n this.deviceConnectionMode = DeviceConnectionMode.CloudMqtt;\n\n this.updateSolarFlowState(\"connectionMode\", \"Cloud MQTT\");\n\n this.adapter?.log.debug(\n `[subscribeReportTopic] Set connectionMode to 'Cloud MQTT' for device ${this.deviceKey}`,\n );\n }\n }\n }\n\n private subscribeIotTopic(): void {\n const iotTopic = `iot/${this.productKey}/${this.deviceKey}/#`; // Use wildcard topic to get all messages from device\n\n if (this.adapter) {\n if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter?.log.debug(`[subscribeIotTopic] Subscribing to MQTT Topic: '${iotTopic}' (Cloud)`);\n this.adapter?.cloudMqttService?.mqttClient.subscribe(iotTopic, (error) => {\n onSubscribeIotTopic(error, this.productKey, this.deviceKey);\n });\n }\n\n if (this.adapter?.localMqttService?.mqttClient) {\n this.adapter?.log.debug(`[subscribeIotTopic] Subscribing to MQTT Topic: '${iotTopic}' (Local)`);\n this.adapter?.localMqttService?.mqttClient.subscribe(iotTopic, (error) => {\n onSubscribeIotTopic(error, this.productKey, this.deviceKey);\n });\n }\n }\n }\n\n public async updateProperty(property: string, value: number): Promise<boolean> {\n if (this.isZenSdkSupported && this.adapter.config.useZenSDK) {\n const setPropertyContent = { [property]: value };\n this.adapter.log.debug(\n `[updateProperty] Updating property ${property} with value ${value} for device ${this.deviceKey} using zenSDK!`,\n );\n return await this.writeZenSdkProperties(JSON.stringify(setPropertyContent));\n }\n const setPropertyContent = { properties: { [property]: value } };\n this.adapter.log.debug(\n `[updateProperty] Updating property ${property} with value ${value} for device ${this.deviceKey} using MQTT!`,\n );\n return this.writeMqttProperties(JSON.stringify(setPropertyContent));\n }\n\n public setDeviceAutomationInOutLimit(limit: number): void {\n this.adapter?.log.error(\n `[setDeviceAutomationInOutLimit] 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(`[setAcMode] Method setAcMode (set to ${acMode}) not defined in base class!`);\n return;\n }\n\n public setDcSwitch(dcSwitch: boolean): void {\n this.adapter?.log.error(`[setDcSwitch] Method setDcSwitch (set to ${dcSwitch}) not defined in base class!`);\n return;\n }\n\n public setAcSwitch(acSwitch: boolean): void {\n this.adapter?.log.error(`[setAcSwitch] Method setAcSwitch (set to ${acSwitch}) not defined in base class!`);\n return;\n }\n\n public setHubState(hubState: number): void {\n if (this.productKey && this.deviceKey) {\n if (hubState == 0 || hubState == 1) {\n this.updateProperty(\"hubState\", hubState);\n } else {\n this.adapter.log.debug(`[setHubState] Hub state is not 0 or 1!`);\n }\n }\n }\n\n public setGridReverse(gridReverse: number): void {\n if (this.productKey && this.deviceKey) {\n if (gridReverse >= 0 && gridReverse <= 2) {\n this.updateProperty(\"gridReverse\", gridReverse);\n } else {\n this.adapter.log.debug(`[setGridReverse] Grid reverse value ${gridReverse} is not 0, 1 or 2!`);\n }\n }\n }\n\n public setPassMode(passMode: number): void {\n if (this.productKey && this.deviceKey) {\n this.updateProperty(\"passMode\", passMode);\n }\n }\n\n public setAutoRecover(autoRecover: boolean): void {\n if (this.productKey && this.deviceKey) {\n this.updateProperty(\"autoRecover\", autoRecover ? 1 : 0);\n }\n }\n\n /**\n * Will set the discharge limit (minSoc)\n *\n * @param socSet the desired minimum soc\n * @param minSoc\n * @returns void\n */\n public setDischargeLimit(minSoc: number): void {\n if (this.productKey && this.deviceKey) {\n if (minSoc >= 0 && minSoc <= 50) {\n this.updateProperty(\"minSoc\", minSoc * 10);\n } else {\n this.adapter.log.debug(`[setDischargeLimit] Discharge limit is not in range 0<>50!`);\n }\n }\n }\n\n /**\n * Will set the maximum charge limit\n *\n * @param socSet the desired max SOC\n * @returns void\n */\n public setChargeLimit(socSet: number): void {\n if (this.productKey && this.deviceKey) {\n if (socSet >= 40 && socSet <= 100) {\n this.updateProperty(\"socSet\", socSet * 10);\n } else {\n this.adapter.log.debug(`[setChargeLimit] Charge limit is not in range 40<>100!`);\n }\n }\n }\n\n /**\n * Will set the 'energy plan'\n *\n * @param autoModel autoModel value, like 8 for smart matching\n * @returns void\n */\n public setAutoModel(autoModel: number): void {\n if (this.isZenSdkSupported && this.adapter.config.useZenSDK) {\n if (autoModel != 0) {\n this.adapter.log.warn(`[setAutoModel] Can't set autoModel to a value other than 0 when using zenSDK!`);\n }\n\n this.updateProperty(\"autoModel\", 0);\n return;\n }\n\n if (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(`[setAutoModel] Setting autoModel for device key ${this.deviceKey} to ${autoModel}!`);\n this.writeMqttProperties(JSON.stringify(setAutoModelContent));\n }\n }\n\n public async setOutputLimit(limit: number): Promise<void> {\n if (this.productKey && this.deviceKey) {\n // Check if autoModel is set to 0 (Nothing) or 8 (Smart Matching)\n const autoModel = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.autoModel`))?.val;\n\n if (autoModel != 0) {\n this.adapter.log.warn(\"Operation mode (autoModel) is not set to '0', we can't set the output limit!\");\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 (lowVoltageBlockState && lowVoltageBlockState.val && lowVoltageBlockState.val == true) {\n limit = 0;\n }\n\n const fullChargeNeeded = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.control.fullChargeNeeded`,\n );\n\n if (fullChargeNeeded && fullChargeNeeded.val && fullChargeNeeded.val == true) {\n limit = 0;\n }\n }\n\n const currentLimit = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.outputLimit`))?.val;\n\n if (currentLimit != null && currentLimit != undefined) {\n if (currentLimit != limit) {\n const timestamp = new Date();\n timestamp.setMilliseconds(0);\n\n this.updateProperty(\"outputLimit\", limit);\n }\n }\n }\n }\n\n public setInputLimit(limit: number): void {\n if (this.productKey && this.deviceKey) {\n // Limit has always to be positive!\n if (limit < 0) {\n this.adapter.log.debug(`[setInputLimit] limit ${limit} is negative, converting to positive!`);\n limit = Math.abs(limit);\n }\n\n if (limit) {\n limit = Math.round(limit);\n } else {\n limit = 0;\n }\n\n if (limit < 0) {\n limit = 0;\n } else if (limit > 0 && limit <= 30) {\n limit = 30;\n } else if (limit > this.maxInputLimit) {\n limit = this.maxInputLimit;\n }\n\n if (this.productKey.includes(\"8bm93h\")) {\n // Das Limit kann beim ACE nur in 100er Schritten gesetzt werden\n limit = Math.ceil(limit / 100) * 100;\n }\n\n this.updateProperty(\"inputLimit\", limit);\n }\n }\n\n public setSmartMode(smartModeOn: boolean): void {\n if (this.productKey && this.deviceKey) {\n this.updateProperty(\"smartMode\", smartModeOn ? 1 : 0);\n }\n }\n\n public setBuzzerSwitch(buzzerOn: boolean): void {\n if (this.productKey && this.deviceKey) {\n this.updateProperty(\"buzzerSwitch\", buzzerOn ? 1 : 0);\n }\n }\n\n public triggerFullTelemetryUpdate(): void {\n if (this.isZenSdkSupported && this.adapter.config.useZenSDK) {\n this.getZenSdkProperties();\n return;\n }\n\n if (this.productKey && this.deviceKey) {\n const getAllContent = { properties: [\"getAll\"] };\n this.adapter.log.debug(\n `[triggerFullTelemetryUpdate] Triggering full telemetry update for device key ${this.deviceKey}!`,\n );\n const topic = `iot/${this.productKey}/${this.deviceKey}/properties/read`;\n\n this.messageId += 1;\n // if local MQTT is enabled, prefer local MQTT client for setting properties, otherwise use cloud MQTT client\n if (this.adapter?.localMqttService?.mqttClient) {\n this.adapter?.localMqttService?.mqttClient?.publish(topic, JSON.stringify(getAllContent), { qos: 1 });\n } else if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter?.cloudMqttService?.mqttClient?.publish(topic, JSON.stringify(getAllContent), { qos: 1 });\n }\n }\n }\n\n public async updateSolarFlowState(state: string, val: number | string | boolean): Promise<void> {\n const stateId = `${this.productKey}.${this.deviceKey}.${state}`;\n\n // Create the state if it does not exist yet, or self-heal it if its persisted type\n // no longer matches allStates (e.g. left over from an older adapter version).\n await ensureState(this, state, val);\n\n const currentValue = await this.adapter.getStateAsync(stateId);\n\n await this.adapter?.setState(stateId, val, true);\n\n if (currentValue?.val != val && state != \"wifiState\") {\n // Set lastUpdate for deviceKey if a value was changed!\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.lastUpdate`, new Date().getTime(), true);\n\n // Check current wifiState, if Disconnected set it to Connected!\n const currentWifiState = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.wifiState`);\n\n if (currentWifiState && currentWifiState.val == 0) {\n this.updateSolarFlowState(\"wifiState\", 1);\n }\n }\n }\n\n public async updateSolarFlowControlState(state: string, val: number | string | boolean): Promise<void> {\n // First check if state exist\n const stateExist = await this.adapter?.objectExists(`${this.productKey}.${this.deviceKey}.control.${state}`);\n\n // Update the control state\n if (stateExist) {\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.control.${state}`, val, true);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await -- kept async, caller in processDeviceProperties.ts awaits this method\n addOrUpdatePackData = async (packData: IPackData[], isSolarFlow: boolean): Promise<void> => {\n if (this.adapter && this.productKey && this.deviceKey) {\n packData.forEach(async (x) => {\n if (x.sn && this.adapter) {\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[1] === \"O\" && x.sn[2] === \"4\") {\n batType = \"I1920\";\n }\n if (x.sn[3] == \"F\") {\n batType = \"AB2000S\";\n } else if (x.sn[3] == \"E\") {\n batType = \"AB2000X\";\n } else {\n batType = \"AB2000\";\n }\n } else if (x.sn.startsWith(\"F\")) {\n batType = \"AB3000X\";\n } else if (x.sn.startsWith(\"G\")) {\n batType = \"AB3000L\";\n } else if (x.sn.startsWith(\"J\")) {\n batType = \"I2400\";\n }\n\n if (!this.batteries.some((y) => y.packSn == x.sn)) {\n this.batteries.push({ packSn: x.sn, type: batType });\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 const key = `${this.productKey}.${this.deviceKey}.packData.${x.sn}`.replace(this.adapter.FORBIDDEN_CHARS, \"\");\n\n await this.adapter?.extendObject(key, {\n type: \"channel\",\n common: { name: { de: batType, en: batType } },\n native: {},\n });\n\n const createPackState = async (fieldName: string): Promise<void> => {\n const def = allStates[fieldName];\n if (!def) {\n return;\n }\n await this.adapter?.extendObject(`${key}.${fieldName}`, {\n type: \"state\",\n common: {\n name: { de: def.nameDe, en: def.nameEn },\n type: def.type,\n desc: def.title,\n role: def.role,\n read: true,\n write: false,\n unit: def.unit,\n },\n native: {},\n });\n };\n\n const touchLastUpdate = async (fieldName: string, newValue: number): Promise<void> => {\n const current = await this.adapter?.getStateAsync(`${key}.${fieldName}`);\n if (current?.val && newValue != current.val) {\n await this.adapter?.setState(\n `${this.productKey}.${this.deviceKey}.lastUpdate`,\n new Date().getTime(),\n true,\n );\n const wifiState = await this.adapter?.getStateAsync(`${this.productKey}.${this.deviceKey}.wifiState`);\n if (wifiState?.val == 0) {\n this.updateSolarFlowState(\"wifiState\", 1);\n }\n }\n };\n\n // Phase 1: collect transformed values; side effects happen here\n const packStatesToSet = new Map<string, number | string>();\n\n packStatesToSet.set(\"model\", batType);\n packStatesToSet.set(\"sn\", x.sn);\n\n if (x.socLevel) {\n packStatesToSet.set(\"socLevel\", x.socLevel);\n }\n\n if (x.maxTemp) {\n const maxTempCelsius = x.maxTemp / 10 - 273.15;\n await touchLastUpdate(\"maxTemp\", maxTempCelsius);\n packStatesToSet.set(\"maxTemp\", maxTempCelsius);\n }\n\n if (x.minVol) {\n const minVol = x.minVol / 100;\n await touchLastUpdate(\"minVol\", minVol);\n packStatesToSet.set(\"minVol\", minVol);\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 let batcur = 0;\n\n if (x.batcur > 32767) {\n batcur -= 65536;\n }\n packStatesToSet.set(\"batcur\", batcur / 10);\n }\n\n if (x.maxVol) {\n const maxVol = x.maxVol / 100;\n await touchLastUpdate(\"maxVol\", maxVol);\n packStatesToSet.set(\"maxVol\", maxVol);\n }\n\n if (x.totalVol) {\n const totalVol = x.totalVol / 100;\n await touchLastUpdate(\"totalVol\", totalVol);\n packStatesToSet.set(\"totalVol\", totalVol);\n if (isSolarFlow) {\n this.checkVoltage(totalVol);\n }\n }\n\n if (x.soh) {\n packStatesToSet.set(\"soh\", x.soh / 10);\n }\n if (x.power) {\n packStatesToSet.set(\"power\", x.power);\n }\n\n // Phase 2: create states and set all collected values\n for (const [fieldName, value] of packStatesToSet) {\n await createPackState(fieldName);\n await this.adapter?.setState(`${key}.${fieldName}`, value, true);\n }\n\n // Debug unknown properties\n let found = false;\n Object.entries(x).forEach(([k, value]) => {\n knownPackDataProperties.forEach((property: string) => {\n if (property == k) {\n found = true;\n }\n });\n if (!found) {\n this.adapter?.log.debug(\n `[addOrUpdatePackData] ${k} 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(`${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`, true, true);\n\n // Low Voltage Block activated, stop power input immediately\n const autoModel = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.autoModel`))?.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(`${this.productKey}.${this.deviceKey}.electricLevel`);\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(`${this.productKey}.${this.deviceKey}.control.fullChargeNeeded`, true, true);\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(`${this.productKey}.${this.deviceKey}.hubState`);\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(`${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`, false, true);\n\n if (this.adapter.config.useLowVoltageBlock && this.adapter.config.forceShutdownOnLowVoltage) {\n this.setDischargeLimit(this.adapter.config.dischargeLimit ? this.adapter.config.dischargeLimit : 5);\n }\n }\n }\n }\n\n /**\n * Calculates the energy for all items in 'calculationStateKeys'.\n *\n * @returns Promise<void>\n * @beta\n */\n public calculateEnergy(): void {\n calculationStateKeys.forEach(async (stateKey) => {\n let stateNameEnergyWh = \"\";\n let stateNameEnergykWh = \"\";\n let stateNamePower = \"\";\n\n switch (stateKey) {\n case \"pvPower1\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower1`;\n break;\n case \"pvPower2\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower2`;\n break;\n case \"pvPower3\":\n if (await this.adapter.getObjectAsync(`${this.productKey}.${this.deviceKey}.pvPower3`)) {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower3`;\n }\n break;\n case \"pvPower4\":\n if (await this.adapter.getObjectAsync(`${this.productKey}.${this.deviceKey}.pvPower4`)) {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.pvPower4`;\n }\n break;\n default:\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\n stateNamePower = `${this.productKey}.${this.deviceKey}.${stateKey}Power`;\n break;\n }\n\n if (stateNamePower != \"\") {\n // If stateNamePower found, proceed with calculation, otherwise skip this stateKey\n this.adapter.log.debug(`[calculateEnergy] No stateNamePower found for ${stateKey}!`);\n const currentPowerState = await this.adapter?.getStateAsync(stateNamePower);\n\n const currentEnergyState = await this.adapter?.getStateAsync(stateNameEnergyWh);\n\n if (!currentEnergyState?.val || currentEnergyState?.val == 0) {\n // Workaround, set Val to very low value to avoid Jump in data...\n await this.adapter?.setState(stateNameEnergyWh, 0.000001, true);\n } else if (\n currentEnergyState &&\n currentEnergyState.lc &&\n currentPowerState &&\n currentPowerState.val != undefined &&\n currentPowerState.val != null\n ) {\n // Timeframe = 30000ms, Job runs every 30 seconds...\n const timeFrame = 30000;\n\n // Calculate Energy value (Wh) from current power in the timeframe from last run...\n const addEnergyValue = (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(stateNameEnergykWh, Number((newEnergyValue / 1000).toFixed(2)), true);\n\n // SOC and energy in batteries\n if ((stateKey == \"outputPack\" || stateKey == \"packInput\") && addEnergyValue > 0) {\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(`${this.productKey}.${this.deviceKey}.calculations.remainOutTime`, \"\", true);\n }\n }\n } else if (currentPowerState && currentEnergyState) {\n await this.adapter?.setState(stateNameEnergyWh, 0, true);\n await this.adapter?.setState(stateNameEnergykWh, 0, true);\n }\n }\n });\n }\n\n public calculateSocAndEnergy = async (stateKey: string, value: number): 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 = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.minSoc`))?.val;\n const currentSoc = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.electricLevel`))?.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(currentEnergyMaxState ? currentEnergyMaxState.val : 0);\n\n let currentEnergyWh = currentEnergyState?.val ? Number(currentEnergyState?.val) : 0;\n\n if (currentEnergyWh == null || currentEnergyWh == undefined || currentEnergyWh <= 0) {\n currentEnergyWh = 0;\n }\n\n if (this.productKey == \"yWF7hV\") {\n // The device is an AIO 2400, so set maximum Wh to 2400!\n energyWhMax = 2400;\n } else {\n // Iterate over all batteries!\n for (let i = 0; i < this.batteries.length; i++) {\n if (this.batteries[i].type.includes(\"AB1000\")) {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 960;\n } else if (this.batteries[i].type.includes(\"AB2000\")) {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 1920;\n } else if (this.batteries[i].type.includes(\"AB3000\")) {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 2880;\n } else if (this.batteries[i].type.includes(\"I2400\")) {\n energyWhMax = (energyWhMax ? energyWhMax : 0) + 2400;\n } else if (this.batteries[i].type.includes(\"I1920\")) {\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 = stateKey == \"outputPack\" ? currentEnergyWh + value : currentEnergyWh - value;\n\n // If greater than Max of batteries, set it to this value.\n if (stateKey == \"outputPack\" && energyWhMax != undefined && newEnergyWh > energyWhMax) {\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(`${this.productKey}.${this.deviceKey}.calculations.energyWh`, newEnergyWh, true);\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 (stateKey == \"outputPack\" && currentOutputPackPower?.val != null && currentOutputPackPower != undefined) {\n // Charging, calculate remaining charging time\n const toCharge = currentMaxValue - newEnergyWh;\n\n const remainHoursAsDecimal = toCharge / Number(currentOutputPackPower.val);\n\n if (remainHoursAsDecimal < 48.0) {\n const remainFormatted = toHoursAndMinutes(Math.round(remainHoursAsDecimal * 60));\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(`${this.productKey}.${this.deviceKey}.calculations.remainInputTime`, \"\", true);\n }\n } else if (stateKey == \"packInput\" && currentPackInputPower != null && currentPackInputPower != undefined) {\n // Discharging, calculate remaining discharge time\n const remainHoursAsDecimal = newEnergyWh / Number(currentPackInputPower.val);\n const remainFormatted = toHoursAndMinutes(Math.round(remainHoursAsDecimal * 60));\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(`${this.productKey}.${this.deviceKey}.calculations.remainOutTime`, \"\", true);\n }\n }\n }\n } else if (newEnergyWh <= 0 && stateKey == \"outputPack\") {\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.calculations.remainInputTime`, \"\", true);\n } else if (newEnergyWh <= 0 && stateKey == \"packInput\") {\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.calculations.remainOutTime`, \"\", true);\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(`${this.productKey}.${this.deviceKey}.calculations.soc`, 0, true);\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(`${this.productKey}.${this.deviceKey}.calculations.energyWhMax`, newMax, true);\n\n // Set Energy in Battery to 0\n await this.adapter?.setState(`${this.productKey}.${this.deviceKey}.calculations.energyWh`, 0, true);\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 switch (stateKey) {\n case \"pvPower1\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv1EnergyTodaykWh`;\n break;\n case \"pvPower2\":\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv2EnergyTodaykWh`;\n break;\n case \"pvPower3\":\n if (await this.adapter.getObjectAsync(`${this.productKey}.${this.deviceKey}.pvPower3`)) {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv3EnergyTodaykWh`;\n } else {\n return;\n }\n break;\n case \"pvPower4\":\n if (await this.adapter.getObjectAsync(`${this.productKey}.${this.deviceKey}.pvPower4`)) {\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.solarInputPv4EnergyTodaykWh`;\n } else {\n return;\n }\n break;\n default:\n stateNameEnergyWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\n stateNameEnergykWh = `${this.productKey}.${this.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\n break;\n }\n\n if (stateNameEnergyWh != \"\" && stateNameEnergykWh != \"\") {\n await this.adapter?.setState(stateNameEnergyWh, 0, true);\n await this.adapter?.setState(stateNameEnergykWh, 0, true);\n }\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["_a", "_b", "_c", "_d", "axios", "setPropertyContent"]
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "zendure-solarflow",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.3",
|
|
5
5
|
"news": {
|
|
6
|
+
"5.0.3": {
|
|
7
|
+
"en": "Fix `wifiState` not being created/updated correctly for devices using local zenSDK polling (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), as their local status payload does not report a `wifiState` property",
|
|
8
|
+
"de": "Behebung des Problems, dass `wifiState` für Geräte mit lokaler zenSDK-Abfrage (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus) nicht korrekt erstellt/aktualisiert wird, da deren lokale Statusnutzlast keine `wifiState`-Eigenschaft meldet.",
|
|
9
|
+
"ru": "Исправлена ошибка, из-за которой свойство `wifiState` некорректно создавалось/обновлялось для устройств, использующих локальный опрос zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), поскольку их локальная полезная нагрузка состояния не сообщает о свойстве `wifiState`.",
|
|
10
|
+
"pt": "Corrigido o problema em que o `wifiState` não era criado/atualizado corretamente para dispositivos que usam polling local do zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), pois o payload de status local desses dispositivos não reporta uma propriedade `wifiState`.",
|
|
11
|
+
"nl": "Los het probleem op dat `wifiState` niet correct wordt aangemaakt/bijgewerkt voor apparaten die gebruikmaken van lokale zenSDK-polling (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), omdat hun lokale statuspayload geen `wifiState`-eigenschap rapporteert.",
|
|
12
|
+
"fr": "Correction d'un problème où `wifiState` n'était pas créé/mis à jour correctement pour les appareils utilisant l'interrogation locale du zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), car leur charge utile d'état local ne signale pas de propriété `wifiState`.",
|
|
13
|
+
"it": "Risolto il problema per cui `wifiState` non veniva creato/aggiornato correttamente per i dispositivi che utilizzano il polling locale di zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), poiché il loro payload di stato locale non riporta una proprietà `wifiState`",
|
|
14
|
+
"es": "Solucionar el problema por el que `wifiState` no se crea ni se actualiza correctamente en los dispositivos que utilizan el sondeo local de zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), ya que su carga útil de estado local no informa de una propiedad `wifiState`.",
|
|
15
|
+
"pl": "Naprawiono problem z poprawnym tworzeniem/aktualizacją właściwości `wifiState` w przypadku urządzeń korzystających z lokalnego sondowania zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), ponieważ ich lokalny ładunek stanu nie raportuje właściwości `wifiState`",
|
|
16
|
+
"uk": "Виправлено помилку, через яку `wifiState` не створювався/оновлювався коректно для пристроїв, що використовують локальне опитування zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), оскільки їхнє локальне корисне навантаження стану не повідомляє про властивість `wifiState`.",
|
|
17
|
+
"zh-cn": "修复了使用本地 zenSDK 轮询的设备(Solarflow 2400 AC/AC Plus/Pro、1600 AC Plus)的 `wifiState` 属性无法正确创建/更新的问题,因为它们的本地状态负载未报告 `wifiState` 属性。"
|
|
18
|
+
},
|
|
6
19
|
"5.0.2": {
|
|
7
20
|
"en": "Fix Wifistate type/value mismatch",
|
|
8
21
|
"de": "Behebung des WLAN-Status-Typ-/Wertkonflikts",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "Zezwól na połączenie lokalnego serwera TLS MQTT na porcie 8883 (z powodu nowego oprogramowania sprzętowego urządzenia) w ustawieniach\nNapraw obliczenia Batcura",
|
|
81
94
|
"uk": "Дозволити підключення локального сервера TLS MQTT на порту 8883 (через нову прошивку пристрою) у налаштуваннях\nВиправити розрахунок Batcur",
|
|
82
95
|
"zh-cn": "允许本地 TLS MQTT 服务器连接到端口 8883(由于设备固件更新),请在设置中进行启用。\n修复 batcur 计算"
|
|
83
|
-
},
|
|
84
|
-
"4.0.7-alpha.0": {
|
|
85
|
-
"en": "Allow local SSL MQTT Server on port 8883\nFix batcur calculation",
|
|
86
|
-
"de": "Lokalen SSL-MQTT-Server auf Port 8883 erlauben\nBatcur-Berechnung korrigiert",
|
|
87
|
-
"ru": "Разрешить локальный SSL MQTT сервер на порту 8883\nИсправлен расчёт batcur",
|
|
88
|
-
"pt": "Permitir servidor MQTT SSL local na porta 8883\nCorrecção do cálculo batcur",
|
|
89
|
-
"nl": "Lokale SSL MQTT-server op poort 8883 toestaan\nBatcur-berekening gecorrigeerd",
|
|
90
|
-
"fr": "Autoriser le serveur MQTT SSL local sur le port 8883\nCorrection du calcul batcur",
|
|
91
|
-
"it": "Consentire il server MQTT SSL locale sulla porta 8883\nCorrezione del calcolo batcur",
|
|
92
|
-
"es": "Permitir servidor MQTT SSL local en el puerto 8883\nCorreción del cálculo batcur",
|
|
93
|
-
"pl": "Zezwól na lokalny serwer SSL MQTT na porcie 8883\nNaprawiono obliczenie batcur",
|
|
94
|
-
"uk": "Дозволити локальний SSL MQTT сервер на порту 8883\nВиправлено розрахунок batcur",
|
|
95
|
-
"zh-cn": "允许本地SSL MQTT服务器使用8883端口\n修复batcur计算"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|