iobroker.zendure-solarflow 5.2.0 → 5.2.1

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 CHANGED
@@ -124,22 +124,14 @@ This adapter will use the Cloud Authorization Code for authentication on the off
124
124
  -->
125
125
 
126
126
  ## Changelog
127
- ### 5.2.0 (2026-08-29)
127
+ ### 5.2.1 (2026-08-30)
128
128
 
129
+ - **BREAKING CHANGE**: `setDeviceAutomationInOutLimit` on Hyper 2000 uses simulated HEMS now and requires `hemsState = 1` and `autoModel = 0` to control the device (automatically set by the adapter). Please check your control parameters (e.g. inverseMaxPower) after updating if you use setDeviceAutomationInOutLimit.
129
130
  - Add support for Solarflow 3000/4000 Mix AC+ and 4000 Mix Pro via mDNS auto-discovery
130
131
  - Add support for Smart Meter 3CT and Smart Meter D0 (read-only zenSDK accessories, with proper power state names/units and no control or packData states)
131
132
  - Correct a device's IP via mDNS if it no longer matches the (stale or wrong) IP from the cloud device list
132
133
  - Process zenSDK measurements reported directly on the response instead of nested under "properties" (affects Smart Meter 3CT/D0)
133
- - Enable "mDNS discovery" by default, including for existing instances that never had this setting saved - you must disable this option in settings if not desired
134
-
135
-
136
- ### 5.2.0-alpha.3 (2026-08-28)
137
-
138
- - Added a mDNS listener to detect Solarflow Devices with zenSDK. In cloud mode this will check for missing or wrong IP addresses. In local only mode this will add the device(s) with the serial number.
139
- - First test to support SF 3000/4000 Mix devices via zenSDK and mDNS discovery
140
- - This version changes the function 'setDeviceAutomationInOutLimit' of Hyper 2000 to use 'hemsEP' function instead of 'deviceAutomation'. Big thanks to **FireSon** from the team of the Home Assistant Integration for Zendure for clarification and details!
141
- - Fix setting of 0-values to battery states
142
- - Fix 'Cannot write file deviceList.json: zendure-solarflow.admin is not an object of type "meta"'
134
+ - Enable "mDNS discovery" by default, including for existing instances that never had this setting saved - you must disable this option in settings if not desired
143
135
 
144
136
  ### 5.1.0 (2026-08-20)
145
137
 
@@ -153,7 +145,12 @@ This adapter will use the Cloud Authorization Code for authentication on the off
153
145
 
154
146
  ### 5.0.3 (2026-08-18)
155
147
 
156
- - 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
148
+ - 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
149
+
150
+
151
+ ### 5.0.2 (2026-08-18)
152
+
153
+ - Fix Wifistate type/value mismatch
157
154
 
158
155
  For older changes see [CHANGELOG_OLD.md](CHANGELOG_OLD.md).
159
156
 
@@ -592,15 +592,19 @@ class ZenIobDevice {
592
592
  this.messageId += 1;
593
593
  const timestamp = /* @__PURE__ */ new Date();
594
594
  timestamp.setMilliseconds(0);
595
+ const inverseMaxPowerState = await this.adapter.getStateAsync(
596
+ `${this.productKey}.${this.deviceKey}.inverseMaxPower`
597
+ );
598
+ const inverseMaxPower = (inverseMaxPowerState == null ? void 0 : inverseMaxPowerState.val) ? Number(inverseMaxPowerState.val) : 0;
599
+ if (limit > inverseMaxPower) {
600
+ this.adapter.log.error(
601
+ `[sendHemsEpSetpoint] Requested output limit (${limit}W) exceeds inverseMaxPower (${inverseMaxPower}W) - actual output will be ignored by the device!`
602
+ );
603
+ }
595
604
  let minSoc;
596
- let inverseMaxPower;
597
605
  if (isFirstPayload) {
598
606
  const minSocState = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.minSoc`);
599
607
  minSoc = ((minSocState == null ? void 0 : minSocState.val) ? Number(minSocState.val) : 1) * 10;
600
- const inverseMaxPowerState = await this.adapter.getStateAsync(
601
- `${this.productKey}.${this.deviceKey}.inverseMaxPower`
602
- );
603
- inverseMaxPower = (inverseMaxPowerState == null ? void 0 : inverseMaxPowerState.val) ? Number(inverseMaxPowerState.val) : 800;
604
608
  }
605
609
  const _arguments = limit < 0 ? { outputPower: 0, chargePower: -limit, freq: 0, mode: 9, chargeMode: 3 } : {
606
610
  outputPower: limit,
@@ -1051,24 +1055,25 @@ class ZenIobDevice {
1051
1055
  }
1052
1056
  };
1053
1057
  async checkVoltage(voltage) {
1054
- var _a, _b, _c, _d;
1058
+ var _a, _b, _c, _d, _e;
1055
1059
  if (voltage < 46.1) {
1056
1060
  if (this.adapter.config.useCalculation) {
1057
1061
  this.setSocToZero();
1058
1062
  }
1059
1063
  if (this.adapter.config.useLowVoltageBlock) {
1060
1064
  await ((_a = this.adapter) == null ? void 0 : _a.setState(`${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`, true, true));
1061
- const autoModel = (_b = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.autoModel`)) == null ? void 0 : _b.val;
1062
- if (autoModel == 8) {
1065
+ const outputLimit = (_b = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.outputLimit`)) == null ? void 0 : _b.val;
1066
+ const deviceAutomationInOutLimit = (_c = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.control.setDeviceAutomationInOutLimit`)) == null ? void 0 : _c.val;
1067
+ if (deviceAutomationInOutLimit != 0) {
1063
1068
  this.setDeviceAutomationInOutLimit(0);
1064
- } else {
1069
+ } else if (outputLimit != 0) {
1065
1070
  this.setOutputLimit(0);
1066
1071
  }
1067
1072
  if (this.adapter.config.forceShutdownOnLowVoltage) {
1068
1073
  const currentSoc = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.electricLevel`);
1069
1074
  if (currentSoc && Number(currentSoc.val) > 50) {
1070
1075
  if (this.adapter.config.fullChargeIfNeeded) {
1071
- await ((_c = this.adapter) == null ? void 0 : _c.setState(`${this.productKey}.${this.deviceKey}.control.fullChargeNeeded`, true, true));
1076
+ await ((_d = this.adapter) == null ? void 0 : _d.setState(`${this.productKey}.${this.deviceKey}.control.fullChargeNeeded`, true, true));
1072
1077
  }
1073
1078
  } else {
1074
1079
  if (currentSoc && currentSoc.val) {
@@ -1088,7 +1093,7 @@ class ZenIobDevice {
1088
1093
  `${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`
1089
1094
  );
1090
1095
  if (lowVoltageBlock && lowVoltageBlock.val == true) {
1091
- await ((_d = this.adapter) == null ? void 0 : _d.setState(`${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`, false, true));
1096
+ await ((_e = this.adapter) == null ? void 0 : _e.setState(`${this.productKey}.${this.deviceKey}.control.lowVoltageBlock`, false, true));
1092
1097
  if (this.adapter.config.useLowVoltageBlock && this.adapter.config.forceShutdownOnLowVoltage) {
1093
1098
  this.setDischargeLimit(this.adapter.config.dischargeLimit ? this.adapter.config.dischargeLimit : 5);
1094
1099
  }
@@ -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 { IHemsEpPayload } from \"../IDeviceAutomationPayload\";\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 /** Whether this device reports battery packData (false for read-only devices like the Smart Meter 3CT/D0). */\n public hasPackData: boolean = true;\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 if (this.hasPackData) {\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\n if (this.controlStates.length > 0) {\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\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 // Some devices (e.g. Smart Meter 3CT/D0) report their measurements directly on the\n // top-level response instead of nesting them under 'properties'\n const {\n properties,\n packData,\n timestamp,\n messageId,\n deviceId,\n sn,\n success,\n output,\n isHA,\n ...directProperties\n } = data;\n\n const propertiesToProcess = { ...(properties ?? {}), ...directProperties };\n\n if (Object.keys(propertiesToProcess).length > 0) {\n processDeviceProperties(this, propertiesToProcess, 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 (packData) {\n this.addOrUpdatePackData(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.warn(\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.warn(`[getZenSdkProperties] IP address is not defined for device ${this.deviceKey}!`);\n\n return Promise.resolve(false);\n }\n\n /**\n * Called by mdnsHelper when this device was discovered locally via mDNS. Fills in the\n * ipAddress if it is not yet known, or corrects it if it no longer matches the\n * mDNS-discovered address (e.g. a stale/wrong IP from the cloud device list), then\n * switches the device to a zenSDK connection (instead of Cloud/MQTT) if zenSDK is\n * supported and enabled.\n *\n * @param ipAddress the IP address the device was discovered at\n * @param serviceName the mDNS service name the device was discovered with (for logging)\n * @param serviceHost the mDNS service host the device was discovered with (for logging)\n */\n public connectViaMdns(ipAddress: string, serviceName?: string, serviceHost?: string): void {\n if (this.ipAddress !== ipAddress) {\n if (this.ipAddress) {\n this.adapter.log.info(\n `[connectViaMdns] Correcting stale IP for device ${this.deviceKey}: ${this.ipAddress} -> ${ipAddress} (mDNS service: ${serviceName})!`,\n );\n }\n this.ipAddress = ipAddress;\n this.updateSolarFlowState(\"ip\", ipAddress);\n }\n\n if (\n !this.adapter.config.useZenSDK ||\n !this.isZenSdkSupported ||\n this.deviceConnectionMode == DeviceConnectionMode.zenSDK\n ) {\n this.adapter.log.warn(\n `[connectViaMdns] Skipping zenSDK connect for device ${this.deviceKey} (useZenSDK=${this.adapter.config.useZenSDK}, isZenSdkSupported=${this.isZenSdkSupported}, deviceConnectionMode=${this.deviceConnectionMode})!`,\n );\n return;\n }\n\n this.getZenSdkProperties()\n .then((success) => {\n if (success) {\n this.deviceConnectionMode = DeviceConnectionMode.zenSDK;\n\n this.updateSolarFlowState(\"connectionMode\", \"zenSDK\");\n this.updateSolarFlowState(\"wifiState\", 1);\n\n // zenSDK and MQTT are mutually exclusive - if we previously fell back to MQTT, drop that subscription now\n this.unsubscribeMqttTopics();\n\n this.adapter.log.info(\n `[connectViaMdns] Switched device ${this.deviceKey} to zenSDK connection via mDNS-discovered IP ${ipAddress} (service: ${serviceName}, host: ${serviceHost})!`,\n );\n }\n })\n .catch(() => {\n // zenSDK not reachable yet via the discovered IP, keep existing connection mode\n });\n }\n\n private unsubscribeMqttTopics(): void {\n const reportTopic = `/${this.productKey}/${this.deviceKey}/#`;\n const iotSubscribeTopic = `iot/${this.productKey}/${this.deviceKey}/#`;\n\n if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter.log.debug(\n `[unsubscribeMqttTopics] Unsubscribing from MQTT Topics for device ${this.deviceKey} (Cloud)`,\n );\n this.adapter.cloudMqttService.mqttClient.unsubscribe(reportTopic);\n this.adapter.cloudMqttService.mqttClient.unsubscribe(iotSubscribeTopic);\n }\n\n if (this.adapter?.localMqttService?.mqttClient) {\n this.adapter.log.debug(\n `[unsubscribeMqttTopics] Unsubscribing from MQTT Topics for device ${this.deviceKey} (Local)`,\n );\n this.adapter.localMqttService.mqttClient.unsubscribe(reportTopic);\n this.adapter.localMqttService.mqttClient.unsubscribe(iotSubscribeTopic);\n }\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.warn(`[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.warn(`[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 /**\n * Hands control of the device to the HEMS via `hemsState` (properties/write).\n *\n * @param hemsState true to hand control to the HEMS, false to release it\n */\n public setHemsState(hemsState: boolean): void {\n if (this.productKey && this.deviceKey) {\n this.adapter.log.debug(`[setHemsState] Setting hemsState to ${hemsState ? 1 : 0} for device ${this.deviceKey}!`);\n this.writeMqttProperties(JSON.stringify({ properties: { hemsState: hemsState ? 1 : 0 } }));\n }\n }\n\n /**\n * Sending a device limit trought HEMS imitation. This function acts like the HEMS from Zendure cloud.\n *\n * @param limit desired power in W; negative charges, positive (including 0) discharges/idles\n */\n private releaseHemsControlTimeout?: ioBroker.Timeout;\n\n protected async sendHemsEpSetpoint(limit: number): Promise<void> {\n if (this.releaseHemsControlTimeout) {\n this.adapter.clearTimeout(this.releaseHemsControlTimeout);\n this.releaseHemsControlTimeout = undefined;\n }\n\n const hemsStateActive = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.hemsState`);\n const isFirstPayload = !hemsStateActive || !hemsStateActive.val;\n if (isFirstPayload) {\n const autoModel = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.autoModel`))?.val;\n if (autoModel != 0) {\n this.adapter.log.warn(\n `[sendHemsEpSetpoint] autoModel is not set to '0' (current value: ${autoModel}), setting it to '0' before sending the HEMS setpoint!`,\n );\n this.setAutoModel(0);\n }\n\n const acMode = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.acMode`))?.val;\n if (acMode != 0) {\n this.adapter.log.warn(\n `[sendHemsEpSetpoint] acMode is not set to '0' (current value: ${acMode}), setting it to '0' before sending the HEMS setpoint!`,\n );\n this.setAcMode(0);\n }\n\n this.setHemsState(true);\n // Device needs ~3s to process the hemsState handshake before it accepts hemsEP setpoints\n await new Promise<void>((resolve) => this.adapter.setTimeout(resolve, 3000));\n }\n\n this.messageId += 1;\n\n const timestamp = new Date();\n timestamp.setMilliseconds(0);\n\n let minSoc: number | undefined;\n let inverseMaxPower: number | undefined;\n if (isFirstPayload) {\n const minSocState = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.minSoc`);\n minSoc = (minSocState?.val ? Number(minSocState.val) : 1) * 10;\n\n const inverseMaxPowerState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.inverseMaxPower`,\n );\n inverseMaxPower = inverseMaxPowerState?.val ? Number(inverseMaxPowerState.val) : 800;\n }\n\n const _arguments: IHemsEpPayload =\n limit < 0\n ? { outputPower: 0, chargePower: -limit, freq: 0, mode: 9, chargeMode: 3 }\n : {\n outputPower: limit,\n chargePower: 0,\n freq: 0,\n mode: 9,\n ...(isFirstPayload ? { minSoc, inverseMaxPower } : {}),\n };\n\n const hemsEP = {\n arguments: _arguments,\n function: \"hemsEP\",\n messageId: this.messageId,\n deviceKey: this.deviceKey,\n timestamp: timestamp.getTime() / 1000,\n };\n this.invokeMqttFunction(JSON.stringify(hemsEP));\n\n if (limit === 0) {\n // Release HEMS control 3s after idling at 0, unless a new setpoint arrives first (see cancellation above)\n this.releaseHemsControlTimeout = this.adapter.setTimeout(() => {\n this.releaseHemsControlTimeout = undefined;\n this.setHemsState(false);\n }, 3000);\n }\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 setGridOffMode(gridOffMode: number): void {\n if (this.productKey && this.deviceKey) {\n if (gridOffMode >= 0 && gridOffMode <= 2) {\n this.updateProperty(\"gridOffMode\", gridOffMode);\n } else {\n this.adapter.log.debug(`[setGridOffMode] Grid off mode value ${gridOffMode} 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 public setInverseMaxPower(inverseMaxPower: number): void {\n if (this.productKey && this.deviceKey) {\n if (inverseMaxPower < 0) {\n this.adapter.log.debug(\n `[setInverseMaxPower] inverseMaxPower ${inverseMaxPower} is negative, converting to positive!`,\n );\n inverseMaxPower = Math.abs(inverseMaxPower);\n }\n this.updateProperty(\"inverseMaxPower\", Math.round(inverseMaxPower));\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 != null) {\n packStatesToSet.set(\"socLevel\", x.socLevel);\n }\n\n if (x.maxTemp != null) {\n const maxTempCelsius = x.maxTemp / 10 - 273.15;\n await touchLastUpdate(\"maxTemp\", maxTempCelsius);\n packStatesToSet.set(\"maxTemp\", maxTempCelsius);\n }\n\n if (x.minVol != null) {\n const minVol = x.minVol / 100;\n await touchLastUpdate(\"minVol\", minVol);\n packStatesToSet.set(\"minVol\", minVol);\n }\n\n if (x.batcur != null) {\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 = x.batcur;\n\n if (batcur > 32767) {\n batcur -= 65536;\n }\n packStatesToSet.set(\"batcur\", batcur / 10);\n }\n\n if (x.maxVol != null) {\n const maxVol = x.maxVol / 100;\n await touchLastUpdate(\"maxVol\", maxVol);\n packStatesToSet.set(\"maxVol\", maxVol);\n }\n\n if (x.totalVol != null) {\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 != null) {\n packStatesToSet.set(\"soh\", x.soh / 10);\n }\n if (x.power != null) {\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 { IHemsEpPayload } from \"../IDeviceAutomationPayload\";\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 /** Whether this device reports battery packData (false for read-only devices like the Smart Meter 3CT/D0). */\n public hasPackData: boolean = true;\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 if (this.hasPackData) {\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\n if (this.controlStates.length > 0) {\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\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 // Some devices (e.g. Smart Meter 3CT/D0) report their measurements directly on the\n // top-level response instead of nesting them under 'properties'\n const {\n properties,\n packData,\n timestamp,\n messageId,\n deviceId,\n sn,\n success,\n output,\n isHA,\n ...directProperties\n } = data;\n\n const propertiesToProcess = { ...(properties ?? {}), ...directProperties };\n\n if (Object.keys(propertiesToProcess).length > 0) {\n processDeviceProperties(this, propertiesToProcess, 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 (packData) {\n this.addOrUpdatePackData(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.warn(\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.warn(`[getZenSdkProperties] IP address is not defined for device ${this.deviceKey}!`);\n\n return Promise.resolve(false);\n }\n\n /**\n * Called by mdnsHelper when this device was discovered locally via mDNS. Fills in the\n * ipAddress if it is not yet known, or corrects it if it no longer matches the\n * mDNS-discovered address (e.g. a stale/wrong IP from the cloud device list), then\n * switches the device to a zenSDK connection (instead of Cloud/MQTT) if zenSDK is\n * supported and enabled.\n *\n * @param ipAddress the IP address the device was discovered at\n * @param serviceName the mDNS service name the device was discovered with (for logging)\n * @param serviceHost the mDNS service host the device was discovered with (for logging)\n */\n public connectViaMdns(ipAddress: string, serviceName?: string, serviceHost?: string): void {\n if (this.ipAddress !== ipAddress) {\n if (this.ipAddress) {\n this.adapter.log.info(\n `[connectViaMdns] Correcting stale IP for device ${this.deviceKey}: ${this.ipAddress} -> ${ipAddress} (mDNS service: ${serviceName})!`,\n );\n }\n this.ipAddress = ipAddress;\n this.updateSolarFlowState(\"ip\", ipAddress);\n }\n\n if (\n !this.adapter.config.useZenSDK ||\n !this.isZenSdkSupported ||\n this.deviceConnectionMode == DeviceConnectionMode.zenSDK\n ) {\n this.adapter.log.warn(\n `[connectViaMdns] Skipping zenSDK connect for device ${this.deviceKey} (useZenSDK=${this.adapter.config.useZenSDK}, isZenSdkSupported=${this.isZenSdkSupported}, deviceConnectionMode=${this.deviceConnectionMode})!`,\n );\n return;\n }\n\n this.getZenSdkProperties()\n .then((success) => {\n if (success) {\n this.deviceConnectionMode = DeviceConnectionMode.zenSDK;\n\n this.updateSolarFlowState(\"connectionMode\", \"zenSDK\");\n this.updateSolarFlowState(\"wifiState\", 1);\n\n // zenSDK and MQTT are mutually exclusive - if we previously fell back to MQTT, drop that subscription now\n this.unsubscribeMqttTopics();\n\n this.adapter.log.info(\n `[connectViaMdns] Switched device ${this.deviceKey} to zenSDK connection via mDNS-discovered IP ${ipAddress} (service: ${serviceName}, host: ${serviceHost})!`,\n );\n }\n })\n .catch(() => {\n // zenSDK not reachable yet via the discovered IP, keep existing connection mode\n });\n }\n\n private unsubscribeMqttTopics(): void {\n const reportTopic = `/${this.productKey}/${this.deviceKey}/#`;\n const iotSubscribeTopic = `iot/${this.productKey}/${this.deviceKey}/#`;\n\n if (this.adapter?.cloudMqttService?.mqttClient) {\n this.adapter.log.debug(\n `[unsubscribeMqttTopics] Unsubscribing from MQTT Topics for device ${this.deviceKey} (Cloud)`,\n );\n this.adapter.cloudMqttService.mqttClient.unsubscribe(reportTopic);\n this.adapter.cloudMqttService.mqttClient.unsubscribe(iotSubscribeTopic);\n }\n\n if (this.adapter?.localMqttService?.mqttClient) {\n this.adapter.log.debug(\n `[unsubscribeMqttTopics] Unsubscribing from MQTT Topics for device ${this.deviceKey} (Local)`,\n );\n this.adapter.localMqttService.mqttClient.unsubscribe(reportTopic);\n this.adapter.localMqttService.mqttClient.unsubscribe(iotSubscribeTopic);\n }\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.warn(`[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.warn(`[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 /**\n * Hands control of the device to the HEMS via `hemsState` (properties/write).\n *\n * @param hemsState true to hand control to the HEMS, false to release it\n */\n public setHemsState(hemsState: boolean): void {\n if (this.productKey && this.deviceKey) {\n this.adapter.log.debug(`[setHemsState] Setting hemsState to ${hemsState ? 1 : 0} for device ${this.deviceKey}!`);\n this.writeMqttProperties(JSON.stringify({ properties: { hemsState: hemsState ? 1 : 0 } }));\n }\n }\n\n /**\n * Sending a device limit trought HEMS imitation. This function acts like the HEMS from Zendure cloud.\n *\n * @param limit desired power in W; negative charges, positive (including 0) discharges/idles\n */\n private releaseHemsControlTimeout?: ioBroker.Timeout;\n\n protected async sendHemsEpSetpoint(limit: number): Promise<void> {\n if (this.releaseHemsControlTimeout) {\n this.adapter.clearTimeout(this.releaseHemsControlTimeout);\n this.releaseHemsControlTimeout = undefined;\n }\n\n const hemsStateActive = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.hemsState`);\n const isFirstPayload = !hemsStateActive || !hemsStateActive.val;\n if (isFirstPayload) {\n const autoModel = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.autoModel`))?.val;\n if (autoModel != 0) {\n this.adapter.log.warn(\n `[sendHemsEpSetpoint] autoModel is not set to '0' (current value: ${autoModel}), setting it to '0' before sending the HEMS setpoint!`,\n );\n this.setAutoModel(0);\n }\n\n const acMode = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.acMode`))?.val;\n if (acMode != 0) {\n this.adapter.log.warn(\n `[sendHemsEpSetpoint] acMode is not set to '0' (current value: ${acMode}), setting it to '0' before sending the HEMS setpoint!`,\n );\n this.setAcMode(0);\n }\n\n this.setHemsState(true);\n // Device needs ~3s to process the hemsState handshake before it accepts hemsEP setpoints\n await new Promise<void>((resolve) => this.adapter.setTimeout(resolve, 3000));\n }\n\n this.messageId += 1;\n\n const timestamp = new Date();\n timestamp.setMilliseconds(0);\n\n const inverseMaxPowerState = await this.adapter.getStateAsync(\n `${this.productKey}.${this.deviceKey}.inverseMaxPower`,\n );\n const inverseMaxPower = inverseMaxPowerState?.val ? Number(inverseMaxPowerState.val) : 0;\n\n if (limit > inverseMaxPower) {\n this.adapter.log.error(\n `[sendHemsEpSetpoint] Requested output limit (${limit}W) exceeds inverseMaxPower (${inverseMaxPower}W) - actual output will be ignored by the device!`,\n );\n }\n\n let minSoc: number | undefined;\n if (isFirstPayload) {\n const minSocState = await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.minSoc`);\n minSoc = (minSocState?.val ? Number(minSocState.val) : 1) * 10;\n }\n\n const _arguments: IHemsEpPayload =\n limit < 0\n ? { outputPower: 0, chargePower: -limit, freq: 0, mode: 9, chargeMode: 3 }\n : {\n outputPower: limit,\n chargePower: 0,\n freq: 0,\n mode: 9,\n ...(isFirstPayload ? { minSoc, inverseMaxPower } : {}),\n };\n\n const hemsEP = {\n arguments: _arguments,\n function: \"hemsEP\",\n messageId: this.messageId,\n deviceKey: this.deviceKey,\n timestamp: timestamp.getTime() / 1000,\n };\n this.invokeMqttFunction(JSON.stringify(hemsEP));\n\n if (limit === 0) {\n // Release HEMS control 3s after idling at 0, unless a new setpoint arrives first (see cancellation above)\n this.releaseHemsControlTimeout = this.adapter.setTimeout(() => {\n this.releaseHemsControlTimeout = undefined;\n this.setHemsState(false);\n }, 3000);\n }\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 setGridOffMode(gridOffMode: number): void {\n if (this.productKey && this.deviceKey) {\n if (gridOffMode >= 0 && gridOffMode <= 2) {\n this.updateProperty(\"gridOffMode\", gridOffMode);\n } else {\n this.adapter.log.debug(`[setGridOffMode] Grid off mode value ${gridOffMode} 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 public setInverseMaxPower(inverseMaxPower: number): void {\n if (this.productKey && this.deviceKey) {\n if (inverseMaxPower < 0) {\n this.adapter.log.debug(\n `[setInverseMaxPower] inverseMaxPower ${inverseMaxPower} is negative, converting to positive!`,\n );\n inverseMaxPower = Math.abs(inverseMaxPower);\n }\n this.updateProperty(\"inverseMaxPower\", Math.round(inverseMaxPower));\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 != null) {\n packStatesToSet.set(\"socLevel\", x.socLevel);\n }\n\n if (x.maxTemp != null) {\n const maxTempCelsius = x.maxTemp / 10 - 273.15;\n await touchLastUpdate(\"maxTemp\", maxTempCelsius);\n packStatesToSet.set(\"maxTemp\", maxTempCelsius);\n }\n\n if (x.minVol != null) {\n const minVol = x.minVol / 100;\n await touchLastUpdate(\"minVol\", minVol);\n packStatesToSet.set(\"minVol\", minVol);\n }\n\n if (x.batcur != null) {\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 = x.batcur;\n\n if (batcur > 32767) {\n batcur -= 65536;\n }\n packStatesToSet.set(\"batcur\", batcur / 10);\n }\n\n if (x.maxVol != null) {\n const maxVol = x.maxVol / 100;\n await touchLastUpdate(\"maxVol\", maxVol);\n packStatesToSet.set(\"maxVol\", maxVol);\n }\n\n if (x.totalVol != null) {\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 != null) {\n packStatesToSet.set(\"soh\", x.soh / 10);\n }\n if (x.power != null) {\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 outputLimit = (await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.outputLimit`))?.val;\n const deviceAutomationInOutLimit = (\n await this.adapter.getStateAsync(`${this.productKey}.${this.deviceKey}.control.setDeviceAutomationInOutLimit`)\n )?.val;\n\n if (deviceAutomationInOutLimit != 0) {\n this.setDeviceAutomationInOutLimit(0);\n } else if (outputLimit != 0) {\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,98 +1,72 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zendure-solarflow",
4
- "version": "5.2.0",
4
+ "version": "5.2.1",
5
5
  "news": {
6
- "5.2.0": {
7
- "en": "Add support for Solarflow 3000/4000 Mix AC+ and 4000 Mix Pro via mDNS auto-discovery\nAdd support for Smart Meter 3CT and Smart Meter D0 (read-only zenSDK accessories, with proper power state names/units and no control or packData states)\nCorrect a device's IP via mDNS if it no longer matches the (stale or wrong) IP from the cloud device list\nProcess zenSDK measurements reported directly on the response instead of nested under \"properties\" (affects Smart Meter 3CT/D0)\nEnable \"mDNS discovery\" by default, including for existing instances that never had this setting saved - you must disable this option in settings if not desired",
8
- "de": "Unterstützung für Solarflow 3000/4000 Mix AC+ und 4000 Mix Pro über mDNS-Autoerkennung hinzufügen\nUnterstützung für Smart Meter 3CT und Smart Meter D0 hinzufügen (schreibgeschützte zenSDK-Zubehörteile mit korrekten Leistungszustandsnamen/-einheiten und ohne Steuerungs- oder Packdatenzustände)\nKorrigieren Sie die IP-Adresse eines Geräts über mDNS, falls diese nicht mehr mit der (veralteten oder falschen) IP-Adresse aus der Cloud-Geräteliste übereinstimmt.\nDie Messwerte des Process zenSDK werden direkt in der Antwort anstatt unter „Eigenschaften“ verschachtelt angezeigt (betrifft Smart Meter 3CT/D0).\nAktivieren Sie die „mDNS-Erkennung“ standardmäßig, auch für bestehende Instanzen, bei denen diese Einstellung nie gespeichert wurde. Sie müssen diese Option in den Einstellungen deaktivieren, wenn Sie dies nicht wünschen.",
9
- "ru": "Добавлена поддержка Solarflow 3000/4000 Mix AC+ и 4000 Mix Pro через автоматическое обнаружение mDNS.\nДобавлена поддержка интеллектуальных счетчиков Smart Meter 3CT и Smart Meter D0 (аксессуары zenSDK только для чтения, с корректными именами/единицами измерения состояния питания и без состояний control или packData).\nИсправьте IP-адрес устройства через mDNS, если он больше не совпадает с (устаревшим или неверным) IP-адресом из списка устройств в облаке.\nОбработка измерений zenSDK осуществляется непосредственно в ответе, а не вложенным образом в раздел «свойства» (это затрагивает интеллектуальные счетчики 3CT/D0).\nФункция \"обнаружение mDNS\" должна быть включена по умолчанию, в том числе для существующих экземпляров, для которых этот параметр никогда не был сохранен — при желании эту опцию необходимо отключить в настройках.",
10
- "pt": "Adicionar suporte para Solarflow 3000/4000 Mix AC+ e 4000 Mix Pro via descoberta automática de mDNS.\nAdicionar suporte para Smart Meter 3CT e Smart Meter D0 (acessórios zenSDK somente leitura, com nomes/unidades de estado de energia adequados e sem estados de controle ou packData).\nCorrija o endereço IP de um dispositivo via mDNS se ele não corresponder mais ao endereço IP (desatualizado ou incorreto) da lista de dispositivos na nuvem.\nProcessar medições do zenSDK relatadas diretamente na resposta em vez de aninhadas em \"propriedades\" (afeta o Smart Meter 3CT/D0)\nAtive a \"descoberta mDNS\" por padrão, inclusive para instâncias existentes que nunca tiveram essa configuração salva. Você deve desativar essa opção nas configurações, caso não a deseje.",
11
- "nl": "Voeg ondersteuning toe voor Solarflow 3000/4000 Mix AC+ en 4000 Mix Pro via mDNS-automatische detectie.\nVoeg ondersteuning toe voor Smart Meter 3CT en Smart Meter D0 (alleen-lezen zenSDK-accessoires, met de juiste namen/eenheden voor de stroomstatus en zonder controle- of packData-statussen).\nCorrigeer het IP-adres van een apparaat via mDNS als dit niet langer overeenkomt met het (verouderde of onjuiste) IP-adres uit de apparatenlijst in de cloud.\nVerwerk de zenSDK-metingen die direct in het antwoord worden gerapporteerd in plaats van genest onder \"eigenschappen\" (dit heeft gevolgen voor slimme meter 3CT/D0).\nSchakel 'mDNS-detectie' standaard in, ook voor bestaande instanties waar deze instelling nog nooit is opgeslagen. U moet deze optie in de instellingen uitschakelen als u dit niet wilt.",
12
- "fr": "Ajout de la prise en charge des systèmes Solarflow 3000/4000 Mix AC+ et 4000 Mix Pro via la découverte automatique mDNS\nAjout de la prise en charge des compteurs intelligents Smart Meter 3CT et Smart Meter D0 (accessoires zenSDK en lecture seule, avec des noms/unités d'état de puissance appropriés et sans états de contrôle ou de packData)\nCorrigez l'adresse IP d'un appareil via mDNS si elle ne correspond plus à l'adresse IP (obsolète ou erronée) de la liste des appareils dans le cloud.\nLes mesures du zenSDK sont désormais rapportées directement dans la réponse au lieu d'être imbriquées sous « propriétés » (affecte le compteur intelligent 3CT/D0).\nActiver la « découverte mDNS » par défaut, y compris pour les instances existantes pour lesquelles ce paramètre n'a jamais été enregistré. Vous devez désactiver cette option dans les paramètres si vous ne le souhaitez pas.",
13
- "it": "Aggiunto il supporto per Solarflow 3000/4000 Mix AC+ e 4000 Mix Pro tramite rilevamento automatico mDNS\nAggiunto il supporto per Smart Meter 3CT e Smart Meter D0 (accessori zenSDK di sola lettura, con nomi/unità di misura dello stato di alimentazione corretti e senza stati di controllo o dati di pacchetto).\nCorreggi l'indirizzo IP di un dispositivo tramite mDNS se non corrisponde più all'indirizzo IP (obsoleto o errato) presente nell'elenco dei dispositivi cloud.\nLe misurazioni di zenSDK vengono riportate direttamente nella risposta anziché essere annidate nella sezione \"proprietà\" (questo problema riguarda il contatore intelligente 3CT/D0).\nAbilita la \"rilevazione mDNS\" per impostazione predefinita, anche per le istanze esistenti che non hanno mai avuto questa impostazione salvata; devi disabilitare questa opzione nelle impostazioni se non la desideri",
14
- "es": "Agregar compatibilidad con Solarflow 3000/4000 Mix AC+ y 4000 Mix Pro mediante detección automática mDNS.\nAgregar compatibilidad con Smart Meter 3CT y Smart Meter D0 (accesorios zenSDK de solo lectura, con nombres/unidades de estado de energía adecuados y sin estados de control o packData).\nCorrige la IP de un dispositivo a través de mDNS si ya no coincide con la IP (obsoleta o incorrecta) de la lista de dispositivos en la nube.\nLas mediciones de zenSDK procesadas se informan directamente en la respuesta en lugar de estar anidadas en \"propiedades\" (afecta al medidor inteligente 3CT/D0).\nHabilitar la \"detección de mDNS\" de forma predeterminada, incluso para las instancias existentes que nunca hayan guardado esta configuración; debe desactivar esta opción en la configuración si no la desea.",
15
- "pl": "Dodano obsługę Solarflow 3000/4000 Mix AC+ i 4000 Mix Pro za pomocą automatycznego wykrywania mDNS\nDodano obsługę liczników Smart Meter 3CT i Smart Meter D0 (akcesoria zenSDK tylko do odczytu, z poprawnymi nazwami/jednostkami stanu zasilania i bez stanów sterowania lub packData)\nPopraw adres IP urządzenia za pomocą mDNS, jeśli nie jest już zgodny z (nieaktualnym lub błędnym) adresem IP z listy urządzeń w chmurze\nPrzetwarzaj pomiary zenSDK raportowane bezpośrednio w odpowiedzi, zamiast zagnieżdżać je w „właściwościach” (dotyczy licznika Smart Meter 3CT/D0)\nWłącz domyślnie „wykrywanie mDNS”, także w przypadku istniejących instancji, w których to ustawienie nigdy nie zostało zapisane — w razie potrzeby należy wyłączyć tę opcję w ustawieniach",
16
- "uk": "Додано підтримку для Solarflow 3000/4000 Mix AC+ та 4000 Mix Pro через автоматичне виявлення mDNS\nДодано підтримку для Smart Meter 3CT та Smart Meter D0 (аксесуари zenSDK лише для читання, з відповідними назвами/одиницями вимірювання станів живлення та без станів керування або packData)\nВиправити IP-адресу пристрою через mDNS, якщо вона більше не відповідає (застарілій або неправильній) IP-адресі зі списку хмарних пристроїв\nОбробляти вимірювання zenSDK, що відображаються безпосередньо у відповіді, а не вкладені у \"властивості\" (стосується Smart Meter 3CT/D0)\nУвімкнути «виявлення mDNS» за замовчуванням, зокрема для існуючих екземплярів, для яких цей параметр ніколи не зберігався. Якщо ви цього не хочете, ви повинні вимкнути цю опцію в налаштуваннях.",
17
- "zh-cn": "通过 mDNS 自动发现功能,增加对 Solarflow 3000/4000 Mix AC+ 和 4000 Mix Pro 的支持\n添加对 Smart Meter 3CT 和 Smart Meter D0 的支持(只读 zenSDK 配件,具有正确的电源状态名称/单位,但没有控制或包数据状态)\n如果设备的 IP 地址与云设备列表中的(过时或错误的)IP 地址不再匹配,请通过 mDNS 更正设备的 IP 地址。\n将 zenSDK 测量结果直接报告在响应中,而不是嵌套在“属性”下(影响智能电表 3CT/D0)\n默认启用“mDNS 发现”,包括从未保存过此设置的现有实例——如果不需要,必须在设置中禁用此选项。"
18
- },
19
- "5.2.0-alpha.8": {
20
- "en": "Compare full SN number instead of suffix only",
21
- "de": "Vergleiche die vollständige Seriennummer anstatt nur das Suffix.",
22
- "ru": "Сравнивайте полный серийный номер, а не только суффикс.",
23
- "pt": "Compare o número de série completo em vez de apenas o sufixo.",
24
- "nl": "Vergelijk het volledige serienummer in plaats van alleen het achtervoegsel.",
25
- "fr": "Comparez le numéro de série complet et non seulement le suffixe.",
26
- "it": "Confronta il numero SN completo anziché solo il suffisso",
27
- "es": "Comparar el número SN completo en lugar de solo el sufijo.",
28
- "pl": "Porównaj pełny numer SN zamiast tylko sufiksu",
29
- "uk": "Порівняйте повний серійний номер, а не лише суфікс",
30
- "zh-cn": "请比较完整的序列号,而不仅仅是后缀。"
6
+ "5.2.1": {
7
+ "en": "**BREAKING CHANGE**: `setDeviceAutomationInOutLimit` on Hyper 2000 uses simulated HEMS now and requires `hemsState = 1` and `autoModel = 0` to control the device (automatically set by the adapter). Please check your control parameters (e.g. inverseMaxPower) after updating if you use setDeviceAutomationInOutLimit.\nAdd support for Solarflow 3000/4000 Mix AC+ and 4000 Mix Pro via mDNS auto-discovery\nAdd support for Smart Meter 3CT and Smart Meter D0 (read-only zenSDK accessories, with proper power state names/units and no control or packData states)\nCorrect a device's IP via mDNS if it no longer matches the (stale or wrong) IP from the cloud device list\nProcess zenSDK measurements reported directly on the response instead of nested under \"properties\" (affects Smart Meter 3CT/D0)\nEnable \"mDNS discovery\" by default, including for existing instances that never had this setting saved - you must disable this option in settings if not desired",
8
+ "de": "**WICHTIGE ÄNDERUNG**: Die Funktion `setDeviceAutomationInOutLimit` auf Hyper 2000 verwendet nun simuliertes HEMS und erfordert `hemsState = 1` und `autoModel = 0` zur Gerätesteuerung (automatisch vom Adapter eingestellt). Bitte überprüfen Sie nach dem Update Ihre Steuerungsparameter (z. B. inverseMaxPower), falls Sie `setDeviceAutomationInOutLimit` verwenden.\nUnterstützung für Solarflow 3000/4000 Mix AC+ und 4000 Mix Pro über mDNS-Autoerkennung hinzufügen\nUnterstützung für Smart Meter 3CT und Smart Meter D0 hinzufügen (schreibgeschützte zenSDK-Zubehörteile mit korrekten Leistungszustandsnamen/-einheiten und ohne Steuerungs- oder Packdatenzustände)\nKorrigieren Sie die IP-Adresse eines Geräts über mDNS, falls diese nicht mehr mit der (veralteten oder falschen) IP-Adresse aus der Cloud-Geräteliste übereinstimmt.\nDie Messwerte des Process zenSDK werden direkt in der Antwort anstatt unter „Eigenschaften“ verschachtelt angezeigt (betrifft Smart Meter 3CT/D0).\nAktivieren Sie die „mDNS-Erkennung“ standardmäßig, auch für bestehende Instanzen, bei denen diese Einstellung nie gespeichert wurde. Sie müssen diese Option in den Einstellungen deaktivieren, wenn Sie dies nicht wünschen.",
9
+ "ru": "**КРИТИЧЕСКИ ВАЖНОЕ ИЗМЕНЕНИЕ**: В Hyper 2000 функция `setDeviceAutomationInOutLimit` теперь использует симулированную HEMS и требует `hemsState = 1` и `autoModel = 0` для управления устройством (автоматически устанавливается адаптером). Пожалуйста, проверьте параметры управления (например, inverseMaxPower) после обновления, если вы используете `setDeviceAutomationInOutLimit`.\nДобавлена поддержка Solarflow 3000/4000 Mix AC+ и 4000 Mix Pro через автоматическое обнаружение mDNS.\nДобавлена поддержка интеллектуальных счетчиков Smart Meter 3CT и Smart Meter D0 (аксессуары zenSDK только для чтения, с корректными именами/единицами измерения состояния питания и без состояний control или packData).\nИсправьте IP-адрес устройства через mDNS, если он больше не совпадает с (устаревшим или неверным) IP-адресом из списка устройств в облаке.\nОбработка измерений zenSDK осуществляется непосредственно в ответе, а не вложенным образом в раздел «свойства» (это затрагивает интеллектуальные счетчики 3CT/D0).\nФункция \"обнаружение mDNS\" должна быть включена по умолчанию, в том числе для существующих экземпляров, для которых этот параметр никогда не был сохранен — при желании эту опцию необходимо отключить в настройках.",
10
+ "pt": "**ALTERAÇÃO IMPORTANTE**: O comando `setDeviceAutomationInOutLimit` no Hyper 2000 agora utiliza HEMS simulado e requer `hemsState = 1` e `autoModel = 0` para controlar o dispositivo (definidos automaticamente pelo adaptador). Verifique seus parâmetros de controle (por exemplo, inverseMaxPower) após a atualização se você utiliza o comando `setDeviceAutomationInOutLimit`.\nAdicionar suporte para Solarflow 3000/4000 Mix AC+ e 4000 Mix Pro via descoberta automática de mDNS.\nAdicionar suporte para Smart Meter 3CT e Smart Meter D0 (acessórios zenSDK somente leitura, com nomes/unidades de estado de energia adequados e sem estados de controle ou packData).\nCorrija o endereço IP de um dispositivo via mDNS se ele não corresponder mais ao endereço IP (desatualizado ou incorreto) da lista de dispositivos na nuvem.\nProcessar medições do zenSDK relatadas diretamente na resposta em vez de aninhadas em \"propriedades\" (afeta o Smart Meter 3CT/D0)\nAtive a \"descoberta mDNS\" por padrão, inclusive para instâncias existentes que nunca tiveram essa configuração salva. Você deve desativar essa opção nas configurações, caso não a deseje.",
11
+ "nl": "**BELANGRIJKE WIJZIGING**: `setDeviceAutomationInOutLimit` op Hyper 2000 gebruikt nu gesimuleerde HEMS en vereist `hemsState = 1` en `autoModel = 0` om het apparaat te besturen (automatisch ingesteld door de adapter). Controleer uw besturingsparameters (bijv. inverseMaxPower) na de update als u `setDeviceAutomationInOutLimit` gebruikt.\nVoeg ondersteuning toe voor Solarflow 3000/4000 Mix AC+ en 4000 Mix Pro via mDNS-automatische detectie.\nVoeg ondersteuning toe voor Smart Meter 3CT en Smart Meter D0 (alleen-lezen zenSDK-accessoires, met de juiste namen/eenheden voor de stroomstatus en zonder controle- of packData-statussen).\nCorrigeer het IP-adres van een apparaat via mDNS als dit niet langer overeenkomt met het (verouderde of onjuiste) IP-adres uit de apparatenlijst in de cloud.\nVerwerk de zenSDK-metingen die direct in de respons worden gerapporteerd in plaats van genest onder \"eigenschappen\" (dit heeft gevolgen voor slimme meter 3CT/D0).\nSchakel 'mDNS-detectie' standaard in, ook voor bestaande instanties waar deze instelling nog nooit is opgeslagen. U moet deze optie in de instellingen uitschakelen als u dit niet wilt.",
12
+ "fr": "**CHANGEMENT IMPORTANT** : La fonction `setDeviceAutomationInOutLimit` sur Hyper 2000 utilise désormais un système HEMS simulé et requiert `hemsState = 1` et `autoModel = 0` pour contrôler l'appareil (paramètres définis automatiquement par l'adaptateur). Veuillez vérifier vos paramètres de contrôle (par exemple, `inverseMaxPower`) après la mise à jour si vous utilisez `setDeviceAutomationInOutLimit`.\nAjout de la prise en charge des systèmes Solarflow 3000/4000 Mix AC+ et 4000 Mix Pro via la découverte automatique mDNS\nAjout de la prise en charge des compteurs intelligents Smart Meter 3CT et Smart Meter D0 (accessoires zenSDK en lecture seule, avec des noms/unités d'état de puissance appropriés et sans états de contrôle ou de packData)\nCorrigez l'adresse IP d'un appareil via mDNS si elle ne correspond plus à l'adresse IP (obsolète ou erronée) de la liste des appareils dans le cloud.\nLes mesures du zenSDK sont désormais rapportées directement dans la réponse au lieu d'être imbriquées sous « propriétés » (affecte le compteur intelligent 3CT/D0).\nActiver la « découverte mDNS » par défaut, y compris pour les instances existantes pour lesquelles ce paramètre n'a jamais été enregistré. Vous devez désactiver cette option dans les paramètres si vous ne le souhaitez pas.",
13
+ "it": "**MODIFICA IMPORTANTE**: `setDeviceAutomationInOutLimit` su Hyper 2000 ora utilizza HEMS simulato e richiede `hemsState = 1` e `autoModel = 0` per controllare il dispositivo (impostati automaticamente dall'adattatore). Si prega di verificare i parametri di controllo (ad esempio inverseMaxPower) dopo l'aggiornamento se si utilizza setDeviceAutomationInOutLimit.\nAggiunto il supporto per Solarflow 3000/4000 Mix AC+ e 4000 Mix Pro tramite rilevamento automatico mDNS\nAggiunto il supporto per Smart Meter 3CT e Smart Meter D0 (accessori zenSDK di sola lettura, con nomi/unità di misura dello stato di alimentazione corretti e senza stati di controllo o dati di pacchetto).\nCorreggi l'indirizzo IP di un dispositivo tramite mDNS se non corrisponde più all'indirizzo IP (obsoleto o errato) presente nell'elenco dei dispositivi cloud.\nLe misurazioni di zenSDK vengono riportate direttamente nella risposta anziché essere annidate nella sezione \"proprietà\" (questo problema riguarda il contatore intelligente 3CT/D0).\nAbilita la \"rilevazione mDNS\" per impostazione predefinita, anche per le istanze esistenti che non hanno mai avuto questa impostazione salvata; devi disabilitare questa opzione nelle impostazioni se non la desideri",
14
+ "es": "**CAMBIO IMPORTANTE**: La función `setDeviceAutomationInOutLimit` en Hyper 2000 ahora utiliza HEMS simulado y requiere `hemsState = 1` y `autoModel = 0` para controlar el dispositivo (configurado automáticamente por el adaptador). Si utiliza `setDeviceAutomationInOutLimit`, revise sus parámetros de control (por ejemplo, inverseMaxPower) después de la actualización.\nAgregar compatibilidad con Solarflow 3000/4000 Mix AC+ y 4000 Mix Pro mediante detección automática mDNS.\nAgregar compatibilidad con Smart Meter 3CT y Smart Meter D0 (accesorios zenSDK de solo lectura, con nombres/unidades de estado de energía adecuados y sin estados de control o packData).\nCorrige la IP de un dispositivo a través de mDNS si ya no coincide con la IP (obsoleta o incorrecta) de la lista de dispositivos en la nube.\nLas mediciones de zenSDK procesadas se informan directamente en la respuesta en lugar de estar anidadas en \"propiedades\" (afecta al medidor inteligente 3CT/D0).\nHabilitar la \"detección de mDNS\" de forma predeterminada, incluso para las instancias existentes que nunca hayan guardado esta configuración; debe desactivar esta opción en la configuración si no la desea.",
15
+ "pl": "**WAŻNA ZMIANA**: `setDeviceAutomationInOutLimit` w Hyper 2000 korzysta teraz z symulowanego HEMS i wymaga `hemsState = 1` i `autoModel = 0` do sterowania urządzeniem (ustawiane automatycznie przez adapter). Sprawdź parametry sterowania (np. inverseMaxPower) po aktualizacji, jeśli używasz setDeviceAutomationInOutLimit.\nDodano obsługę Solarflow 3000/4000 Mix AC+ i 4000 Mix Pro za pomocą automatycznego wykrywania mDNS\nDodano obsługę liczników Smart Meter 3CT i Smart Meter D0 (akcesoria zenSDK tylko do odczytu, z poprawnymi nazwami/jednostkami stanu zasilania i bez stanów sterowania lub packData)\nPopraw adres IP urządzenia za pomocą mDNS, jeśli nie jest już zgodny z (nieaktualnym lub błędnym) adresem IP z listy urządzeń w chmurze\nPrzetwarzaj pomiary zenSDK raportowane bezpośrednio w odpowiedzi, zamiast zagnieżdżać je w „właściwościach” (dotyczy licznika Smart Meter 3CT/D0)\nWłącz domyślnie „wykrywanie mDNS”, także w przypadku istniejących instancji, w których to ustawienie nigdy nie zostało zapisane — w razie potrzeby należy wyłączyć tę opcję w ustawieniach",
16
+ "uk": "**ВАЖЛИВА ЗМІНА**: `setDeviceAutomationInOutLimit` на Hyper 2000 тепер використовує імітацію HEMS та вимагає `hemsState = 1` та `autoModel = 0` для керування пристроєм (автоматично встановлюється адаптером). Будь ласка, перевірте параметри керування (наприклад, inverseMaxPower) після оновлення, якщо ви використовуєте setDeviceAutomationInOutLimit.\nДодано підтримку для Solarflow 3000/4000 Mix AC+ та 4000 Mix Pro через автоматичне виявлення mDNS\nДодано підтримку для Smart Meter 3CT та Smart Meter D0 (аксесуари zenSDK лише для читання, з відповідними назвами/одиницями вимірювання станів живлення та без станів керування або packData)\nВиправити IP-адресу пристрою через mDNS, якщо вона більше не відповідає (застарілій або неправильній) IP-адресі зі списку хмарних пристроїв\nОбробляти вимірювання zenSDK, що відображаються безпосередньо у відповіді, а не вкладені у \"властивості\" (стосується Smart Meter 3CT/D0)\nУвімкнути «виявлення mDNS» за замовчуванням, зокрема для існуючих екземплярів, для яких цей параметр ніколи не зберігався. Якщо ви цього не хочете, ви повинні вимкнути цю опцію в налаштуваннях.",
17
+ "zh-cn": "**重大变更**:Hyper 2000 上的 `setDeviceAutomationInOutLimit` 现在使用模拟 HEMS,并且需要 `hemsState = 1` 和 `autoModel = 0` 才能控制设备(由适配器自动设置)。如果您使用 `setDeviceAutomationInOutLimit`,请在更新后检查您的控制参数(例如 inverseMaxPower)。\n通过 mDNS 自动发现功能,增加对 Solarflow 3000/4000 Mix AC+ 和 4000 Mix Pro 的支持\n添加对 Smart Meter 3CT 和 Smart Meter D0 的支持(只读 zenSDK 配件,具有正确的电源状态名称/单位,没有控制或包数据状态)\n如果设备的 IP 地址与云设备列表中的(过时或错误的)IP 地址不再匹配,请通过 mDNS 更正设备的 IP 地址。\n将 zenSDK 测量结果直接报告在响应中,而不是嵌套在“属性”下(影响智能电表 3CT/D0)\n默认启用“mDNS 发现”,包括从未保存过此设置的现有实例——如果不需要,必须在设置中禁用此选项。"
31
18
  },
32
- "5.2.0-alpha.7": {
33
- "en": "Correct IP of device if it is not correctly in cloud device list and detected by mDNS",
34
- "de": "Korrekte IP-Adresse des Geräts, falls es nicht korrekt in der Cloud-Geräteliste eingetragen und von mDNS erkannt wurde.",
35
- "ru": "Если устройство некорректно отображается в списке облачных устройств и не определяется mDNS, укажите правильный IP-адрес.",
36
- "pt": "Corrija o endereço IP do dispositivo caso ele não esteja corretamente listado na nuvem e não seja detectado pelo mDNS.",
37
- "nl": "Corrigeer het IP-adres van het apparaat als het niet correct in de lijst met cloudapparaten staat en niet door mDNS wordt gedetecteerd.",
38
- "fr": "Corrigez l'adresse IP de l'appareil si elle ne figure pas correctement dans la liste des appareils cloud et n'est pas détectée par mDNS.",
39
- "it": "Indirizzo IP corretto del dispositivo se non è presente correttamente nell'elenco dei dispositivi cloud e non viene rilevato da mDNS.",
40
- "es": "Corrija la dirección IP del dispositivo si no aparece correctamente en la lista de dispositivos en la nube y no es detectada por mDNS.",
41
- "pl": "Popraw adres IP urządzenia, jeśli nie znajduje się ono prawidłowo na liście urządzeń w chmurze i nie zostało wykryte przez mDNS",
42
- "uk": "Виправте IP-адресу пристрою, якщо він неправильно відображається у списку хмарних пристроїв та не виявлений mDNS",
43
- "zh-cn": "如果设备未正确列入云设备列表且未被 mDNS 检测到,请更正设备的 IP 地址。"
44
- },
45
- "5.2.0-alpha.6": {
46
- "en": "Process direct properties of smart meters which are not nested under \"properties\"",
47
- "de": "Verarbeiten Sie direkte Eigenschaften von Smart Metern, die nicht unter „Eigenschaften“ verschachtelt sind.",
48
- "ru": "Обрабатывайте непосредственные свойства интеллектуальных счетчиков, которые не вложены в раздел «Свойства».",
49
- "pt": "Processar propriedades diretas de medidores inteligentes que não estejam aninhadas em \"propriedades\".",
50
- "nl": "Verwerk directe eigenschappen van slimme meters die niet onder \"eigenschappen\" zijn genest.",
51
- "fr": "Traiter directement les propriétés des compteurs intelligents qui ne sont pas imbriquées sous « propriétés »",
52
- "it": "Elabora direttamente le proprietà dei contatori intelligenti che non sono annidate sotto \"proprietà\"",
53
- "es": "Procesar propiedades directas de contadores inteligentes que no estén anidadas bajo \"propiedades\".",
54
- "pl": "Przetwarzaj bezpośrednio właściwości inteligentnych liczników, które nie są zagnieżdżone w „właściwościach”",
55
- "uk": "Обробляти прямі властивості інтелектуальних лічильників, які не вкладені у \"властивості\"",
56
- "zh-cn": "处理智能电表未嵌套在“属性”下的直接属性"
19
+ "5.2.0": {
20
+ "en": "**BREAKING CHANGE**: 'setDeviceAutomationInOutLimit' on Hyper 2000 uses simulated HEMS now and requires 'hemsState = 1' and 'autoModel = 0' to control the device (automatically set by the adapter). Please check your control parameters (e.g. inverseMaxPower) after updating if you use setDeviceAutomationInOutLimit.\nAdd support for Solarflow 3000/4000 Mix AC+ and 4000 Mix Pro via mDNS auto-discovery\nAdd support for Smart Meter 3CT and Smart Meter D0 (read-only zenSDK accessories, with proper power state names/units and no control or packData states)\nCorrect a device's IP via mDNS if it no longer matches the (stale or wrong) IP from the cloud device list\nProcess zenSDK measurements reported directly on the response instead of nested under \"properties\" (affects Smart Meter 3CT/D0)\nEnable \"mDNS discovery\" by default, including for existing instances that never had this setting saved - you must disable this option in settings if not desired",
21
+ "de": "**BREAKING CHANGE**: 'setDeviceAutomationInOutLimit' verwendet beim Hyper 2000 jetzt simuliertes HEMS und erfordert 'hemsState = 1' und 'autoModel = 0', um das Gerät zu steuern (wird automatisch vom Adapter gesetzt). Bitte überprüfen Sie nach dem Update Ihre Steuerungsparameter (z. B. inverseMaxPower), wenn Sie setDeviceAutomationInOutLimit verwenden.\nUnterstützung für Solarflow 3000/4000 Mix AC+ und 4000 Mix Pro über mDNS-Autoerkennung hinzufügen\nUnterstützung für Smart Meter 3CT und Smart Meter D0 hinzufügen (schreibgeschützte zenSDK-Zubehörteile mit korrekten Leistungszustandsnamen/-einheiten und ohne Steuerungs- oder Packdatenzustände)\nKorrigieren Sie die IP-Adresse eines Geräts über mDNS, falls diese nicht mehr mit der (veralteten oder falschen) IP-Adresse aus der Cloud-Geräteliste übereinstimmt.\nDie Messwerte des Process zenSDK werden direkt in der Antwort anstatt unter „Eigenschaften“ verschachtelt angezeigt (betrifft Smart Meter 3CT/D0).\nAktivieren Sie die „mDNS-Erkennung“ standardmäßig, auch für bestehende Instanzen, bei denen diese Einstellung nie gespeichert wurde. Sie müssen diese Option in den Einstellungen deaktivieren, wenn Sie dies nicht wünschen.",
22
+ "ru": "**ВАЖНОЕ ИЗМЕНЕНИЕ**: Функция 'setDeviceAutomationInOutLimit' на Hyper 2000 теперь использует симулированный HEMS и требует 'hemsState = 1' и 'autoModel = 0' для управления устройством (устанавливается адаптером автоматически). Пожалуйста, проверьте свои параметры управления (например, inverseMaxPower) после обновления, если вы используете setDeviceAutomationInOutLimit.\nДобавлена поддержка Solarflow 3000/4000 Mix AC+ и 4000 Mix Pro через автоматическое обнаружение mDNS.\nДобавлена поддержка интеллектуальных счетчиков Smart Meter 3CT и Smart Meter D0 (аксессуары zenSDK только для чтения, с корректными именами/единицами измерения состояния питания и без состояний control или packData).\nИсправьте IP-адрес устройства через mDNS, если он больше не совпадает с (устаревшим или неверным) IP-адресом из списка устройств в облаке.\nОбработка измерений zenSDK осуществляется непосредственно в ответе, а не вложенным образом в раздел «свойства» (это затрагивает интеллектуальные счетчики 3CT/D0).\nФункция \"обнаружение mDNS\" должна быть включена по умолчанию, в том числе для существующих экземпляров, для которых этот параметр никогда не был сохранен — при желании эту опцию необходимо отключить в настройках.",
23
+ "pt": "**ALTERAÇÃO SIGNIFICATIVA**: A função 'setDeviceAutomationInOutLimit' no Hyper 2000 agora usa HEMS simulado e requer 'hemsState = 1' e 'autoModel = 0' para controlar o dispositivo (definido automaticamente pelo adaptador). Verifique seus parâmetros de controle (por exemplo, inverseMaxPower) após a atualização, caso utilize setDeviceAutomationInOutLimit.\nAdicionar suporte para Solarflow 3000/4000 Mix AC+ e 4000 Mix Pro via descoberta automática de mDNS.\nAdicionar suporte para Smart Meter 3CT e Smart Meter D0 (acessórios zenSDK somente leitura, com nomes/unidades de estado de energia adequados e sem estados de controle ou packData).\nCorrija o endereço IP de um dispositivo via mDNS se ele não corresponder mais ao endereço IP (desatualizado ou incorreto) da lista de dispositivos na nuvem.\nProcessar medições do zenSDK relatadas diretamente na resposta em vez de aninhadas em \"propriedades\" (afeta o Smart Meter 3CT/D0)\nAtive a \"descoberta mDNS\" por padrão, inclusive para instâncias existentes que nunca tiveram essa configuração salva. Você deve desativar essa opção nas configurações, caso não a deseje.",
24
+ "nl": "**BREAKING CHANGE**: 'setDeviceAutomationInOutLimit' gebruikt bij de Hyper 2000 nu gesimuleerde HEMS en vereist 'hemsState = 1' en 'autoModel = 0' om het apparaat te besturen (wordt automatisch door de adapter ingesteld). Controleer na de update uw besturingsparameters (bijv. inverseMaxPower) als u setDeviceAutomationInOutLimit gebruikt.\nVoeg ondersteuning toe voor Solarflow 3000/4000 Mix AC+ en 4000 Mix Pro via mDNS-automatische detectie.\nVoeg ondersteuning toe voor Smart Meter 3CT en Smart Meter D0 (alleen-lezen zenSDK-accessoires, met de juiste namen/eenheden voor de stroomstatus en zonder controle- of packData-statussen).\nCorrigeer het IP-adres van een apparaat via mDNS als dit niet langer overeenkomt met het (verouderde of onjuiste) IP-adres uit de apparatenlijst in de cloud.\nVerwerk de zenSDK-metingen die direct in het antwoord worden gerapporteerd in plaats van genest onder \"eigenschappen\" (dit heeft gevolgen voor slimme meter 3CT/D0).\nSchakel 'mDNS-detectie' standaard in, ook voor bestaande instanties waar deze instelling nog nooit is opgeslagen. U moet deze optie in de instellingen uitschakelen als u dit niet wilt.",
25
+ "fr": "**CHANGEMENT MAJEUR** : 'setDeviceAutomationInOutLimit' sur le Hyper 2000 utilise désormais un HEMS simulé et nécessite 'hemsState = 1' et 'autoModel = 0' pour contrôler l'appareil (automatiquement défini par l'adaptateur). Veuillez vérifier vos paramètres de contrôle (par exemple inverseMaxPower) après la mise à jour si vous utilisez setDeviceAutomationInOutLimit.\nAjout de la prise en charge des systèmes Solarflow 3000/4000 Mix AC+ et 4000 Mix Pro via la découverte automatique mDNS\nAjout de la prise en charge des compteurs intelligents Smart Meter 3CT et Smart Meter D0 (accessoires zenSDK en lecture seule, avec des noms/unités d'état de puissance appropriés et sans états de contrôle ou de packData)\nCorrigez l'adresse IP d'un appareil via mDNS si elle ne correspond plus à l'adresse IP (obsolète ou erronée) de la liste des appareils dans le cloud.\nLes mesures du zenSDK sont désormais rapportées directement dans la réponse au lieu d'être imbriquées sous « propriétés » (affecte le compteur intelligent 3CT/D0).\nActiver la « découverte mDNS » par défaut, y compris pour les instances existantes pour lesquelles ce paramètre n'a jamais été enregistré. Vous devez désactiver cette option dans les paramètres si vous ne le souhaitez pas.",
26
+ "it": "**MODIFICA SOSTANZIALE**: 'setDeviceAutomationInOutLimit' su Hyper 2000 ora utilizza HEMS simulato e richiede 'hemsState = 1' e 'autoModel = 0' per controllare il dispositivo (impostato automaticamente dall'adattatore). Dopo l'aggiornamento, controlla i tuoi parametri di controllo (ad es. inverseMaxPower) se utilizzi setDeviceAutomationInOutLimit.\nAggiunto il supporto per Solarflow 3000/4000 Mix AC+ e 4000 Mix Pro tramite rilevamento automatico mDNS\nAggiunto il supporto per Smart Meter 3CT e Smart Meter D0 (accessori zenSDK di sola lettura, con nomi/unità di misura dello stato di alimentazione corretti e senza stati di controllo o dati di pacchetto).\nCorreggi l'indirizzo IP di un dispositivo tramite mDNS se non corrisponde più all'indirizzo IP (obsoleto o errato) presente nell'elenco dei dispositivi cloud.\nLe misurazioni di zenSDK vengono riportate direttamente nella risposta anziché essere annidate nella sezione \"proprietà\" (questo problema riguarda il contatore intelligente 3CT/D0).\nAbilita la \"rilevazione mDNS\" per impostazione predefinita, anche per le istanze esistenti che non hanno mai avuto questa impostazione salvata; devi disabilitare questa opzione nelle impostazioni se non la desideri",
27
+ "es": "**CAMBIO IMPORTANTE**: 'setDeviceAutomationInOutLimit' en el Hyper 2000 ahora usa HEMS simulado y requiere 'hemsState = 1' y 'autoModel = 0' para controlar el dispositivo (configurado automáticamente por el adaptador). Verifique sus parámetros de control (por ejemplo, inverseMaxPower) después de la actualización si utiliza setDeviceAutomationInOutLimit.\nAgregar compatibilidad con Solarflow 3000/4000 Mix AC+ y 4000 Mix Pro mediante detección automática mDNS.\nAgregar compatibilidad con Smart Meter 3CT y Smart Meter D0 (accesorios zenSDK de solo lectura, con nombres/unidades de estado de energía adecuados y sin estados de control o packData).\nCorrige la IP de un dispositivo a través de mDNS si ya no coincide con la IP (obsoleta o incorrecta) de la lista de dispositivos en la nube.\nLas mediciones de zenSDK procesadas se informan directamente en la respuesta en lugar de estar anidadas en \"propiedades\" (afecta al medidor inteligente 3CT/D0).\nHabilitar la \"detección de mDNS\" de forma predeterminada, incluso para las instancias existentes que nunca hayan guardado esta configuración; debe desactivar esta opción en la configuración si no la desea.",
28
+ "pl": "**WAŻNA ZMIANA**: Funkcja 'setDeviceAutomationInOutLimit' w Hyper 2000 używa teraz symulowanego HEMS i wymaga 'hemsState = 1' oraz 'autoModel = 0', aby sterować urządzeniem (ustawiane automatycznie przez adapter). Po aktualizacji sprawdź swoje parametry sterowania (np. inverseMaxPower), jeśli korzystasz z setDeviceAutomationInOutLimit.\nDodano obsługę Solarflow 3000/4000 Mix AC+ i 4000 Mix Pro za pomocą automatycznego wykrywania mDNS\nDodano obsługę liczników Smart Meter 3CT i Smart Meter D0 (akcesoria zenSDK tylko do odczytu, z poprawnymi nazwami/jednostkami stanu zasilania i bez stanów sterowania lub packData)\nPopraw adres IP urządzenia za pomocą mDNS, jeśli nie jest już zgodny z (nieaktualnym lub błędnym) adresem IP z listy urządzeń w chmurze\nPrzetwarzaj pomiary zenSDK raportowane bezpośrednio w odpowiedzi, zamiast zagnieżdżać je w „właściwościach” (dotyczy licznika Smart Meter 3CT/D0)\nWłącz domyślnie „wykrywanie mDNS”, także w przypadku istniejących instancji, w których to ustawienie nigdy nie zostało zapisane — w razie potrzeby należy wyłączyć tę opcję w ustawieniach",
29
+ "uk": "**ВАЖЛИВА ЗМІНА**: Функція 'setDeviceAutomationInOutLimit' на Hyper 2000 тепер використовує симульований HEMS і вимагає 'hemsState = 1' та 'autoModel = 0' для керування пристроєм (встановлюється адаптером автоматично). Будь ласка, перевірте свої параметри керування (наприклад, inverseMaxPower) після оновлення, якщо ви використовуєте setDeviceAutomationInOutLimit.\nДодано підтримку для Solarflow 3000/4000 Mix AC+ та 4000 Mix Pro через автоматичне виявлення mDNS\nДодано підтримку для Smart Meter 3CT та Smart Meter D0 (аксесуари zenSDK лише для читання, з відповідними назвами/одиницями вимірювання станів живлення та без станів керування або packData)\nВиправити IP-адресу пристрою через mDNS, якщо вона більше не відповідає (застарілій або неправильній) IP-адресі зі списку хмарних пристроїв\nОбробляти вимірювання zenSDK, що відображаються безпосередньо у відповіді, а не вкладені у \"властивості\" (стосується Smart Meter 3CT/D0)\nУвімкнути «виявлення mDNS» за замовчуванням, зокрема для існуючих екземплярів, для яких цей параметр ніколи не зберігався. Якщо ви цього не хочете, ви повинні вимкнути цю опцію в налаштуваннях.",
30
+ "zh-cn": "**重大变更**:Hyper 2000 上的 'setDeviceAutomationInOutLimit' 现在使用模拟 HEMS,需要 'hemsState = 1' 和 'autoModel = 0' 才能控制设备(由适配器自动设置)。如果您使用 setDeviceAutomationInOutLimit,请在更新后检查您的控制参数(例如 inverseMaxPower)。\n通过 mDNS 自动发现功能,增加对 Solarflow 3000/4000 Mix AC+ 和 4000 Mix Pro 的支持\n添加对 Smart Meter 3CT 和 Smart Meter D0 的支持(只读 zenSDK 配件,具有正确的电源状态名称/单位,但没有控制或包数据状态)\n如果设备的 IP 地址与云设备列表中的(过时或错误的)IP 地址不再匹配,请通过 mDNS 更正设备的 IP 地址。\n将 zenSDK 测量结果直接报告在响应中,而不是嵌套在“属性”下(影响智能电表 3CT/D0)\n默认启用“mDNS 发现”,包括从未保存过此设置的现有实例——如果不需要,必须在设置中禁用此选项。"
57
31
  },
58
- "5.2.0-alpha.5": {
59
- "en": "Add more logging for zenSDK process in mDNS discovery",
60
- "de": "Füge zusätzliche Protokollierung für den zenSDK-Prozess bei der mDNS-Erkennung hinzu.",
61
- "ru": "Добавить больше логов для процесса zenSDK в обнаружении mDNS.",
62
- "pt": "Adicionar mais registros para o processo zenSDK na descoberta de mDNS",
63
- "nl": "Voeg meer logboekregistratie toe voor het zenSDK-proces in mDNS-ontdekking.",
64
- "fr": "Ajouter davantage de journaux pour le processus zenSDK dans la découverte mDNS",
65
- "it": "Aggiungere ulteriori informazioni di log per il processo zenSDK nella scoperta mDNS",
66
- "es": "Agregar más registros para el proceso zenSDK en el descubrimiento de mDNS",
67
- "pl": "Dodaj więcej rejestrowania dla procesu zenSDK w odkryciu mDNS",
68
- "uk": "Додано більше логування для процесу zenSDK у виявленні mDNS",
69
- "zh-cn": "在 mDNS 发现过程中,为 zenSDK 进程添加更多日志记录"
32
+ "5.1.0": {
33
+ "en": "Fix batCur Reading\nAdd control state for inverseMaxPower and gridOffMode (Control AC outlet on 'Plus' Devices)",
34
+ "de": "Fehler beim Auslesen von batCur behoben\nSteuerungszustand für inverseMaxPower und gridOffMode hinzugefügt (Steuerung der Wechselstromsteckdose bei 'Plus'-Geräten)",
35
+ "ru": "Исправлено чтение batCur\nДобавлено состояние управления для inverseMaxPower и gridOffMode (управление розеткой переменного тока на устройствах 'Plus')",
36
+ "pt": "Correção da leitura de batCur\nAdicionado estado de controle para inverseMaxPower e gridOffMode (Controle da tomada CA em dispositivos 'Plus')",
37
+ "nl": "batCur-uitlezing gecorrigeerd\nBesturingsstatus toegevoegd voor inverseMaxPower en gridOffMode (Bediening van het AC-stopcontact op 'Plus'-apparaten)",
38
+ "fr": "Correction de la lecture de batCur\nAjout d'un état de contrôle pour inverseMaxPower et gridOffMode (contrôle de la prise secteur sur les appareils 'Plus')",
39
+ "it": "Corretta la lettura di batCur\nAggiunto lo stato di controllo per inverseMaxPower e gridOffMode (controllo della presa CA sui dispositivi 'Plus')",
40
+ "es": "Corregida la lectura de batCur\nAgregado estado de control para inverseMaxPower y gridOffMode (control de la toma de CA en dispositivos 'Plus')",
41
+ "pl": "Naprawiono odczyt batCur\nDodano stan sterowania dla inverseMaxPower i gridOffMode (sterowanie gniazdem AC w urządzeniach 'Plus')",
42
+ "uk": "Виправлено зчитування batCur\nДодано стан керування для inverseMaxPower та gridOffMode (керування розеткою змінного струму на пристроях 'Plus')",
43
+ "zh-cn": "修复 batCur 读取问题\n为 inverseMaxPower 和 gridOffMode 添加控制状态(控制“Plus”设备上的交流插座)"
70
44
  },
71
- "5.2.0-alpha.4": {
72
- "en": "Fix zenSDK support for Smart Meter 3CT and Smart Meter D0",
73
- "de": "Behebung der zenSDK-Unterstützung für Smart Meter 3CT und Smart Meter D0",
74
- "ru": "Исправлена поддержка zenSDK для интеллектуальных счетчиков Smart Meter 3CT и Smart Meter D0.",
75
- "pt": "Correção do suporte do zenSDK para Smart Meter 3CT e Smart Meter D0.",
76
- "nl": "Verbeter de zenSDK-ondersteuning voor slimme meters 3CT en slimme meters D0.",
77
- "fr": "Correction de la prise en charge zenSDK pour les compteurs intelligents 3CT et D0",
78
- "it": "Correzione del supporto zenSDK per Smart Meter 3CT e Smart Meter D0",
79
- "es": "Corregir la compatibilidad de zenSDK con los contadores inteligentes 3CT y D0.",
80
- "pl": "Napraw obsługę zenSDK dla liczników Smart Meter 3CT i Smart Meter D0",
81
- "uk": "Виправлено підтримку zenSDK для Smart Meter 3CT та Smart Meter D0",
82
- "zh-cn": "修复 zenSDK 对 Smart Meter 3CT 和 Smart Meter D0 的支持"
45
+ "5.0.4": {
46
+ "en": "Fix flickering Save button in Settings.\nAdd function to detect zenSDK devices with mDNS and fill missing IP-address if found.",
47
+ "de": "Flackernden Speichern-Button in den Einstellungen behoben.\nFunktion hinzugefügt, um zenSDK-Geräte per mDNS zu erkennen und fehlende IP-Adressen auszufüllen, falls gefunden.",
48
+ "ru": "Исправлено мерцание кнопки «Сохранить» в настройках.\nДобавлена функция обнаружения устройств zenSDK через mDNS и заполнения отсутствующего IP-адреса, если он найден.",
49
+ "pt": "Corrigido o piscar do botão Salvar nas Configurações.\nAdicionada função para detectar dispositivos zenSDK via mDNS e preencher o endereço IP ausente, se encontrado.",
50
+ "nl": "Knipperende Opslaan-knop in Instellingen gecorrigeerd.\nFunctie toegevoegd om zenSDK-apparaten via mDNS te detecteren en het ontbrekende IP-adres in te vullen indien gevonden.",
51
+ "fr": "Correction du clignotement du bouton Enregistrer dans les paramètres.\nAjout d'une fonction pour détecter les appareils zenSDK via mDNS et renseigner l'adresse IP manquante si elle est trouvée.",
52
+ "it": "Risolto il problema dello sfarfallio del pulsante Salva nelle impostazioni.\nAggiunta la funzione per rilevare i dispositivi zenSDK tramite mDNS e compilare l'indirizzo IP mancante se trovato.",
53
+ "es": "Corregido el parpadeo del botón Guardar en Configuración.\nAgregada función para detectar dispositivos zenSDK mediante mDNS y completar la dirección IP faltante si se encuentra.",
54
+ "pl": "Naprawiono migający przycisk Zapisz w Ustawieniach.\nDodano funkcję wykrywania urządzeń zenSDK za pomocą mDNS i uzupełniania brakującego adresu IP, jeśli zostanie znaleziony.",
55
+ "uk": "Виправлено блимання кнопки «Зберегти» в налаштуваннях.\nДодано функцію виявлення пристроїв zenSDK за допомогою mDNS та заповнення відсутньої IP-адреси, якщо її знайдено.",
56
+ "zh-cn": "修复设置中“保存”按钮闪烁的问题。\n添加通过 mDNS 检测 zenSDK 设备并在找到时填充缺失 IP 地址的功能。"
83
57
  },
84
- "5.2.0-alpha.3": {
85
- "en": "Added a mDNS listener to detect Solarflow Devices with zenSDK. In cloud mode this will check for missing or wrong IP addresses. In local only mode this will add the device(s) with the serial number.\nFirst test to support SF 3000/4000 Mix devices via zenSDK and mDNS discovery\nThis version changes the function 'setDeviceAutomationInOutLimit' of Hyper 2000 to use 'hemsEP' function instead of 'deviceAutomation'. Big thanks to **FireSon** from the team of the Home Assistant Integration for Zendure for clarification and details!\nFix setting of 0-values to battery states\nFix 'Cannot write file deviceList.json: zendure-solarflow.admin is not an object of type \"meta\"'",
86
- "de": "Ein mDNS-Listener wurde hinzugefügt, um Solarflow-Geräte mit zenSDK zu erkennen. Im Cloud-Modus prüft dieser auf fehlende oder falsche IP-Adressen. Im lokalen Modus werden die Geräte anhand ihrer Seriennummer hinzugefügt.\nErster Test zur Unterstützung von SF 3000/4000 Mix-Geräten über zenSDK und mDNS-Erkennung\nDiese Version ändert die Funktion „setDeviceAutomationInOutLimit“ von Hyper 2000, sodass sie die Funktion „hemsEP“ anstelle von „deviceAutomation“ verwendet. Ein großes Dankeschön an **FireSon** vom Team der Home Assistant Integration für Zendure für die Erläuterungen und Details!\nKorrektur der Einstellung von 0-Werten für Batteriezustände\nBehebt den Fehler „Datei deviceList.json kann nicht geschrieben werden: zendure-solarflow.admin ist kein Objekt vom Typ \"meta\"“.",
87
- "ru": "Добавлен mDNS-прослушиватель для обнаружения устройств Solarflow с помощью zenSDK. В облачном режиме он будет проверять наличие отсутствующих или неверных IP-адресов. В локальном режиме он будет добавлять устройство(а) с серийным номером.\nПервое тестирование поддержки устройств SF 3000/4000 Mix через zenSDK и обнаружение mDNS.\nВ этой версии функция 'setDeviceAutomationInOutLimit' в Hyper 2000 использует функцию 'hemsEP' вместо 'deviceAutomation'. Огромное спасибо **FireSon** из команды интеграции Home Assistant с Zendure за разъяснения и подробности!\nИсправлена ошибка, из-за которой нулевое значение присваивалось состоянию батареи.\nИсправлена ошибка 'Cannot write file deviceList.json: zendure-solarflow.admin is not an object of type \"meta\"'",
88
- "pt": "Adicionamos um ouvinte mDNS para detectar dispositivos Solarflow com o zenSDK. No modo nuvem, ele verificará endereços IP ausentes ou incorretos. No modo somente local, ele adicionará o(s) dispositivo(s) com o número de série.\nPrimeiro teste de suporte para dispositivos SF 3000/4000 Mix via zenSDK e descoberta mDNS.\nEsta versão altera a função 'setDeviceAutomationInOutLimit' do Hyper 2000 para usar a função 'hemsEP' em vez de 'deviceAutomation'. Um grande agradecimento a **FireSon** da equipe de integração do Home Assistant para Zendure pelos esclarecimentos e detalhes!\nCorrigir a configuração de valores 0 para os estados da bateria.\nCorrigir o erro \"Não foi possível gravar o arquivo deviceList.json: zendure-solarflow.admin não é um objeto do tipo \"meta\"\".",
89
- "nl": "Er is een mDNS-listener toegevoegd om Solarflow-apparaten met zenSDK te detecteren. In de cloudmodus controleert deze op ontbrekende of onjuiste IP-adressen. In de lokale modus voegt deze de apparaten toe met het bijbehorende serienummer.\nEerste test ter ondersteuning van SF 3000/4000 Mix-apparaten via zenSDK en mDNS-ontdekking.\nDeze versie wijzigt de functie 'setDeviceAutomationInOutLimit' van Hyper 2000 zodat deze de functie 'hemsEP' gebruikt in plaats van 'deviceAutomation'. Hartelijk dank aan **FireSon** van het Home Assistant Integration-team voor Zendure voor de verduidelijking en details!\nHet instellen van 0-waarden voor batterijstatussen is gecorrigeerd.\nLos de foutmelding 'Kan bestand deviceList.json niet schrijven: zendure-solarflow.admin is geen object van het type \"meta\"' op.",
90
- "fr": "Ajout d'un écouteur mDNS pour détecter les appareils Solarflow avec zenSDK. En mode cloud, il vérifie les adresses IP manquantes ou incorrectes. En mode local uniquement, il ajoute le ou les appareils à partir de leur numéro de série.\nPremier test de prise en charge des périphériques SF 3000/4000 Mix via zenSDK et la découverte mDNS\nCette version remplace la fonction « setDeviceAutomationInOutLimit » d'Hyper 2000 par la fonction « hemsEP » au lieu de « deviceAutomation ». Un grand merci à **FireSon** de l'équipe d'intégration Home Assistant pour Zendure pour ses éclaircissements et précisions !\nCorrection de l'attribution de valeurs nulles aux états de la batterie\nCorrection de l'erreur « Impossible d'écrire dans le fichier deviceList.json : zendure-solarflow.admin n'est pas un objet de type \"meta\" »",
91
- "it": "È stato aggiunto un listener mDNS per rilevare i dispositivi Solarflow con zenSDK. In modalità cloud, questo controllerà la presenza di indirizzi IP mancanti o errati. In modalità locale, aggiungerà il/i dispositivo/i con il relativo numero di serie.\nPrimo test per supportare i dispositivi SF 3000/4000 Mix tramite zenSDK e rilevamento mDNS\nQuesta versione modifica la funzione 'setDeviceAutomationInOutLimit' di Hyper 2000 per utilizzare la funzione 'hemsEP' invece di 'deviceAutomation'. Un grande ringraziamento a **FireSon** del team di integrazione di Home Assistant per Zendure per i chiarimenti e i dettagli!\nCorreggere l'impostazione dei valori 0 per gli stati della batteria\nCorrezione dell'errore \"Impossibile scrivere il file deviceList.json: zendure-solarflow.admin non è un oggetto di tipo \"meta\"\".",
92
- "es": "Se agregó un oyente mDNS para detectar dispositivos Solarflow con zenSDK. En modo nube, verificará si faltan direcciones IP o si son incorrectas. En modo local, agregará el o los dispositivos con su número de serie.\nPrimera prueba para dar soporte a los dispositivos SF 3000/4000 Mix mediante zenSDK y descubrimiento mDNS.\nEsta versión modifica la función 'setDeviceAutomationInOutLimit' de Hyper 2000 para que utilice la función 'hemsEP' en lugar de 'deviceAutomation'. ¡Muchas gracias a **FireSon** del equipo de integración de Home Assistant para Zendure por sus aclaraciones y detalles!\nCorregir la configuración de valores 0 para los estados de la batería\nSolucionar el error 'No se puede escribir el archivo deviceList.json: zendure-solarflow.admin no es un objeto de tipo \"meta\"'",
93
- "pl": "Dodano nasłuchiwacz mDNS do wykrywania urządzeń Solarflow za pomocą zenSDK. W trybie chmurowym sprawdza on brakujące lub nieprawidłowe adresy IP. W trybie lokalnym doda urządzenie(a) z numerem seryjnym.\nPierwszy test obsługi urządzeń SF 3000/4000 Mix za pośrednictwem zenSDK i wykrywania mDNS\nTa wersja zmienia funkcję „setDeviceAutomationInOutLimit” w Hyper 2000, aby zamiast „deviceAutomation” używać funkcji „hemsEP”. Wielkie podziękowania dla **FireSon** z zespołu ds. integracji Home Assistant dla Zendure za wyjaśnienia i szczegóły!\nNapraw ustawienie wartości 0 dla stanów baterii\nNapraw błąd „Nie można zapisać pliku deviceList.json: zendure-solarflow.admin nie jest obiektem typu „meta””",
94
- "uk": "Додано mDNS-слухач для виявлення пристроїв Solarflow за допомогою zenSDK. У хмарному режимі це перевірятиме наявність відсутніх або неправильних IP-адрес. У локальному режимі це додаватиме пристрій(и) із серійним номером.\nПерше тестування підтримки пристроїв SF 3000/4000 Mix через zenSDK та mDNS discovery\nУ цій версії функція «setDeviceAutomationInOutLimit» Hyper 2000 змінюється на «hemsEP» замість «deviceAutomation». Велика подяка **FireSon** з команди Home Assistant Integration для Zendure за роз'яснення та деталі!\nВиправлено встановлення 0-значень для станів батареї\nВиправлено помилку «Неможливо записати файл deviceList.json: zendure-solarflow.admin не є об'єктом типу «meta»»",
95
- "zh-cn": "添加了 mDNS 监听器,用于检测使用 zenSDK 的 Solarflow 设备。在云模式下,它会检查 IP 地址是否缺失或错误。在本地模式下,它会根据序列号添加设备。\n首次测试通过 zenSDK 和 mDNS 发现功能支持 SF 3000/4000 Mix 设备\n此版本将 Hyper 2000 的“setDeviceAutomationInOutLimit”函数更改为使用“hemsEP”函数而不是“deviceAutomation”函数。非常感谢 Zendure Home Assistant 集成团队的 **FireSon** 提供的澄清和详细信息!\n修复电池状态的 0 值设置问题\n修复“无法写入文件 deviceList.json:zendure-solarflow.admin 不是类型为“meta”的对象”的错误"
58
+ "5.0.3": {
59
+ "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",
60
+ "de": "Fehler behoben, durch den wifiState bei Geräten mit lokalem zenSDK-Polling (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus) nicht korrekt erstellt/aktualisiert wurde, da deren lokale Statusnutzlast keine wifiState-Eigenschaft meldet",
61
+ "ru": "Исправлена ошибка, из-за которой wifiState некорректно создавался/обновлялся для устройств, использующих локальный опрос zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), поскольку их локальный пакет состояния не сообщает свойство wifiState",
62
+ "pt": "Corrigido o wifiState não sendo criado/atualizado corretamente para dispositivos que usam sondagem local do zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), pois seu payload de status local não relata a propriedade wifiState",
63
+ "nl": "wifiState wordt niet correct aangemaakt/bijgewerkt voor apparaten die gebruikmaken van lokale zenSDK-polling (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus) gecorrigeerd, aangezien hun lokale statuspayload geen wifiState-eigenschap rapporteert",
64
+ "fr": "Correction du wifiState qui n'était pas créé/mis à jour correctement pour les appareils utilisant l'interrogation locale zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), car leur charge utile d'état locale ne signale pas de propriété wifiState",
65
+ "it": "Corretto il wifiState che non veniva creato/aggiornato correttamente per i dispositivi che utilizzano il polling locale zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), poiché il loro payload di stato locale non riporta una proprietà wifiState",
66
+ "es": "Corregido que wifiState no se creara/actualizara correctamente en dispositivos que usan sondeo local de zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), ya que su payload de estado local no informa una propiedad wifiState",
67
+ "pl": "Naprawiono nieprawidłowe tworzenie/aktualizowanie wifiState dla urządzeń korzystających z lokalnego odpytywania zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), ponieważ ich lokalny ładunek statusu nie zgłasza właściwości wifiState",
68
+ "uk": "Виправлено неправильне створення/оновлення wifiState для пристроїв, що використовують локальне опитування zenSDK (Solarflow 2400 AC/AC Plus/Pro, 1600 AC Plus), оскільки їхній локальний пакет стану не повідомляє властивість wifiState",
69
+ "zh-cn": "修复使用本地 zenSDK 轮询的设备(Solarflow 2400 AC/AC Plus/Pro、1600 AC Plus)无法正确创建/更新 wifiState 的问题,因为其本地状态负载不会报告 wifiState 属性"
96
70
  }
97
71
  },
98
72
  "titleLang": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zendure-solarflow",
3
- "version": "5.2.0",
3
+ "version": "5.2.1",
4
4
  "description": "zendure-solarflow",
5
5
  "author": {
6
6
  "name": "Peter",