iobroker.zendure-solarflow 1.1.11 → 1.1.13
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 +7 -0
- package/admin/build/index.js +9 -9
- package/admin/build/index.js.map +2 -2
- package/build/helpers/createCalculationStates.js +275 -0
- package/build/helpers/createCalculationStates.js.map +7 -0
- package/build/helpers/createControlStates.js +111 -0
- package/build/helpers/createControlStates.js.map +7 -0
- package/build/helpers/createSolarFlowStates.js +296 -0
- package/build/helpers/createSolarFlowStates.js.map +7 -0
- package/build/helpers/deleteCalculationStates.js +51 -0
- package/build/helpers/deleteCalculationStates.js.map +7 -0
- package/build/main.js +49 -31
- package/build/main.js.map +3 -3
- package/build/services/adapterService.js +0 -728
- package/build/services/adapterService.js.map +2 -2
- package/build/services/calculationService.js +98 -0
- package/build/services/calculationService.js.map +7 -0
- package/build/services/jobSchedule.js +90 -0
- package/build/services/jobSchedule.js.map +7 -0
- package/build/services/mqttService.js +156 -40
- package/build/services/mqttService.js.map +2 -2
- package/build/services/webService.js +1 -1
- package/build/services/webService.js.map +2 -2
- package/io-package.json +27 -27
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/services/mqttService.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\r\nimport { MqttClient } from \"mqtt\";\r\nimport * as mqtt from \"mqtt\";\r\nimport { ZendureSolarflow } from \"../main\";\r\nimport { ISolarFlowDeviceDetails } from \"../models/ISolarFlowDeviceDetails\";\r\nimport {\r\n addOrUpdatePackData,\r\n createSolarFlowStates,\r\n updateSolarFlowState,\r\n} from \"./adapterService\";\r\nimport { toHoursAndMinutes } from \"../helpers/timeHelper\";\r\n\r\nlet client: MqttClient | undefined = undefined;\r\nlet adapter: ZendureSolarflow | undefined = undefined;\r\n\r\nconst onConnected = (): void => {\r\n adapter?.log.info(\"Connected with MQTT!\");\r\n};\r\n\r\nconst onError = (error: any): void => {\r\n adapter?.log.error(\"Connection to MQTT failed! Error: \" + error);\r\n};\r\n\r\nconst onSubscribe: any = (error: Error | null) => {\r\n if (error) {\r\n adapter?.log.error(\"Subscription to MQTT failed! Error: \" + error);\r\n } else {\r\n adapter?.log.debug(\"Subscription successful!\");\r\n }\r\n};\r\n\r\nconst onMessage = async (topic: string, message: Buffer): Promise<void> => {\r\n //adapter?.log.info(message.toString())\r\n if (adapter) {\r\n const splitted = topic.split(\"/\");\r\n const productKey = splitted[1];\r\n const deviceKey = splitted[2];\r\n\r\n const obj = JSON.parse(message.toString());\r\n\r\n // lastUpdate f\u00FCr den deviceKey setzen\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"lastUpdate\",\r\n new Date().getTime(),\r\n );\r\n\r\n if (\r\n obj.properties?.electricLevel != null &&\r\n obj.properties?.electricLevel != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"electricLevel\",\r\n obj.properties.electricLevel,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.outputHomePower != null &&\r\n obj.properties?.outputHomePower != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"outputHomePower\",\r\n obj.properties.outputHomePower,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.outputLimit != null &&\r\n obj.properties?.outputLimit != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"outputLimit\",\r\n obj.properties.outputLimit,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.outputPackPower != null &&\r\n obj.properties?.outputPackPower != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"outputPackPower\",\r\n obj.properties.outputPackPower,\r\n );\r\n\r\n // if outPutPackPower set packInputPower to 0\r\n updateSolarFlowState(adapter, productKey, deviceKey, \"packInputPower\", 0);\r\n }\r\n\r\n if (\r\n obj.properties?.packInputPower != null &&\r\n obj.properties?.packInputPower != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"packInputPower\",\r\n obj.properties.packInputPower,\r\n );\r\n\r\n // if packInputPower set outputPackPower to 0\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"outputPackPower\",\r\n 0,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.solarInputPower != null &&\r\n obj.properties?.solarInputPower != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"solarInputPower\",\r\n obj.properties.solarInputPower,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.pvPower1 != null &&\r\n obj.properties?.pvPower1 != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"pvPower2\", // Reversed to adjust like offical app\r\n obj.properties.pvPower1,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.pvPower2 != null &&\r\n obj.properties?.pvPower2 != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"pvPower1\", // Reversed to adjust like offical app\r\n obj.properties.pvPower2,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.solarPower1 != null &&\r\n obj.properties?.solarPower1 != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"pvPower1\",\r\n obj.properties.solarPower1,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.solarPower2 != null &&\r\n obj.properties?.solarPower2 != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"pvPower2\",\r\n obj.properties.solarPower2,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.remainOutTime != null &&\r\n obj.properties?.remainOutTime != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"remainOutTime\",\r\n obj.properties.remainOutTime,\r\n );\r\n\r\n // Zendure use the same state for input und output values, if charging set remainInputTime, else remainOutTime\r\n const packInputPower = Number(\r\n (\r\n await adapter.getStateAsync(\r\n productKey + \".\" + deviceKey + \".packInputPower\",\r\n )\r\n )?.val,\r\n );\r\n const outputPackPower = Number(\r\n (\r\n await adapter.getStateAsync(\r\n productKey + \".\" + deviceKey + \".outputPackPower\",\r\n )\r\n )?.val,\r\n );\r\n\r\n if (packInputPower && packInputPower > 0) {\r\n // Calculate minutes to format hh:mm\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"calculations.remainOutTime\",\r\n obj.properties.remainOutTime < 59940\r\n ? toHoursAndMinutes(obj.properties.remainOutTime)\r\n : \"\",\r\n );\r\n\r\n // Set remainInputTime to blank\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"calculations.remainInputTime\",\r\n \"\",\r\n );\r\n } else if (outputPackPower && outputPackPower > 0) {\r\n // Calculate minutes to format hh:mm\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"calculations.remainInputTime\",\r\n obj.properties.remainInputTime < 59940\r\n ? toHoursAndMinutes(obj.properties.remainInputTime)\r\n : \"\",\r\n );\r\n\r\n // Set remainOutTime to blank\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"calculations.remainOutTime\",\r\n \"\",\r\n );\r\n }\r\n }\r\n\r\n if (obj.properties?.socSet != null && obj.properties?.socSet != undefined) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"socSet\",\r\n Number(obj.properties.socSet) / 10,\r\n );\r\n }\r\n\r\n if (obj.properties?.minSoc != null && obj.properties?.minSoc != undefined) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"minSoc\",\r\n Number(obj.properties.minSoc) / 10,\r\n );\r\n }\r\n\r\n if (obj.packData) {\r\n addOrUpdatePackData(adapter, productKey, deviceKey, obj.packData);\r\n }\r\n }\r\n\r\n if (client) {\r\n //client.end();\r\n }\r\n};\r\n\r\nexport const setChargeLimit = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n socSet: number,\r\n): Promise<void> => {\r\n if (client && productKey && deviceKey) {\r\n if (socSet > 40 && socSet <= 100) {\r\n const topic = `iot/${productKey}/${deviceKey}/properties/write`;\r\n\r\n const socSetLimit = { properties: { socSet: socSet * 10 } };\r\n adapter.log.debug(\r\n `Setting ChargeLimit for device key ${deviceKey} to ${socSet}!`,\r\n );\r\n client?.publish(topic, JSON.stringify(socSetLimit));\r\n } else {\r\n adapter.log.debug(`Charge limit is not in range 40<>100!`);\r\n }\r\n }\r\n};\r\n\r\nexport const setDischargeLimit = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n minSoc: number,\r\n): Promise<void> => {\r\n if (client && productKey && deviceKey) {\r\n if (minSoc > 0 && minSoc < 90) {\r\n const topic = `iot/${productKey}/${deviceKey}/properties/write`;\r\n\r\n const socSetLimit = { properties: { minSoc: minSoc * 10 } };\r\n adapter.log.debug(\r\n `Setting Discharge Limit for device key ${deviceKey} to ${minSoc}!`,\r\n );\r\n client?.publish(topic, JSON.stringify(socSetLimit));\r\n } else {\r\n adapter.log.debug(`Discharge limit is not in range 0<>90!`);\r\n }\r\n }\r\n};\r\n\r\nexport const setOutputLimit = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n limit: number,\r\n): Promise<void> => {\r\n if (client && productKey && deviceKey) {\r\n // Das Limit kann unter 100 nur in 30er Schritten gesetzt werden, dH. 30/60/90/100, wir rechnen das also um\r\n const currentLimit = (\r\n await adapter.getStateAsync(productKey + \".\" + deviceKey + \".outputLimit\")\r\n )?.val;\r\n\r\n if (currentLimit != null && currentLimit != undefined) {\r\n if (currentLimit != limit) {\r\n if (\r\n limit < 100 &&\r\n limit != 90 &&\r\n limit != 60 &&\r\n limit != 30 &&\r\n limit != 0\r\n ) {\r\n if (limit < 100 && limit > 90) {\r\n limit = 90;\r\n } else if (limit < 90 && limit > 60) {\r\n limit = 60;\r\n } else if (limit < 60 && limit > 30) {\r\n limit = 30;\r\n } else if (limit < 30) {\r\n limit = 30;\r\n }\r\n }\r\n\r\n // 'iot/{auth.productKey}/{auth.deviceKey}/properties/write' == Topic? Oder productKey,deviceKey aus Device Details?\r\n const topic = `iot/${productKey}/${deviceKey}/properties/write`;\r\n\r\n const outputlimit = { properties: { outputLimit: limit } };\r\n adapter.log.debug(\r\n `Setting Output Limit for device key ${deviceKey} to ${limit}!`,\r\n );\r\n client?.publish(topic, JSON.stringify(outputlimit));\r\n } else {\r\n adapter.log.debug(\r\n `Output Limit for device key ${deviceKey} is already at ${limit}!`,\r\n );\r\n }\r\n }\r\n }\r\n};\r\n\r\nexport const connectMqttClient = (_adapter: ZendureSolarflow): void => {\r\n adapter = _adapter;\r\n\r\n const options: mqtt.IClientOptions = {\r\n clientId: adapter.accessToken,\r\n username: \"zenApp\",\r\n password: \"oK#PCgy6OZxd\",\r\n clean: true,\r\n protocolVersion: 5,\r\n };\r\n\r\n if (mqtt && adapter && adapter.paths) {\r\n client = mqtt.connect(\r\n \"mqtt://\" + adapter.paths.mqttUrl + \":\" + adapter.paths.mqttPort,\r\n options,\r\n ); // create a client\r\n\r\n if (client && adapter) {\r\n client.on(\"connect\", onConnected);\r\n client.on(\"error\", onError);\r\n\r\n // Subscribe to Topic (appkey von Zendure)\r\n adapter.deviceList.forEach((device: ISolarFlowDeviceDetails) => {\r\n // States erstellen\r\n if (adapter) {\r\n createSolarFlowStates(adapter, device.productKey, device.deviceKey);\r\n\r\n // Set electricLevel (soc) from device details.\r\n updateSolarFlowState(\r\n adapter,\r\n device.productKey,\r\n device.deviceKey,\r\n \"electricLevel\",\r\n device.electricity,\r\n );\r\n\r\n const reportTopic = `/${device.productKey}/${device.deviceKey}/properties/report`;\r\n const iotTopic = `iot/${device.productKey}/${device.deviceKey}/#`;\r\n\r\n adapter.log.debug(`Subscribing to MQTT Topic: ${reportTopic}`);\r\n client?.subscribe(reportTopic, onSubscribe);\r\n adapter.log.debug(`Subscribing to MQTT Topic: ${iotTopic}`);\r\n client?.subscribe(iotTopic, onSubscribe);\r\n }\r\n });\r\n\r\n client.on(\"message\", onMessage);\r\n }\r\n }\r\n};\r\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,WAAsB;AAGtB,
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\r\nimport { MqttClient } from \"mqtt\";\r\nimport * as mqtt from \"mqtt\";\r\nimport { ZendureSolarflow } from \"../main\";\r\nimport { ISolarFlowDeviceDetails } from \"../models/ISolarFlowDeviceDetails\";\r\nimport { updateSolarFlowState } from \"./adapterService\";\r\nimport { toHoursAndMinutes } from \"../helpers/timeHelper\";\r\nimport { createSolarFlowStates } from \"../helpers/createSolarFlowStates\";\r\nimport { IPackData } from \"../models/IPackData\";\r\n\r\nlet client: MqttClient | undefined = undefined;\r\nlet adapter: ZendureSolarflow | undefined = undefined;\r\n\r\nconst onConnected = (): void => {\r\n adapter?.log.info(\"Connected with MQTT!\");\r\n};\r\n\r\nconst onError = (error: any): void => {\r\n adapter?.log.error(\"Connection to MQTT failed! Error: \" + error);\r\n};\r\n\r\nconst onSubscribe: any = (error: Error | null) => {\r\n if (error) {\r\n adapter?.log.error(\"Subscription to MQTT failed! Error: \" + error);\r\n } else {\r\n adapter?.log.debug(\"Subscription successful!\");\r\n }\r\n};\r\n\r\nexport const addOrUpdatePackData = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n packData: IPackData[],\r\n): Promise<void> => {\r\n await packData.forEach(async (x) => {\r\n // Process data only with a serial id!\r\n if (x.sn) {\r\n // create a state for the serial id\r\n const key = (productKey + \".\" + deviceKey + \".packData.\" + x.sn).replace(\r\n adapter.FORBIDDEN_CHARS,\r\n \"\",\r\n );\r\n\r\n await adapter?.extendObjectAsync(key + \".sn\", {\r\n type: \"state\",\r\n common: {\r\n name: {\r\n de: \"Seriennummer\",\r\n en: \"Serial id\",\r\n },\r\n type: \"string\",\r\n desc: \"Serial ID\",\r\n role: \"value\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n\r\n await adapter?.setStateAsync(key + \".sn\", x.sn, true);\r\n\r\n if (x.socLevel) {\r\n // State f\u00FCr socLevel\r\n await adapter?.extendObjectAsync(key + \".socLevel\", {\r\n type: \"state\",\r\n common: {\r\n name: {\r\n de: \"SOC der Batterie\",\r\n en: \"soc of battery\",\r\n },\r\n type: \"number\",\r\n desc: \"SOC Level\",\r\n role: \"value\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n\r\n await adapter?.setStateAsync(key + \".socLevel\", x.socLevel, true);\r\n }\r\n\r\n if (x.maxTemp) {\r\n // State f\u00FCr maxTemp\r\n await adapter?.extendObjectAsync(key + \".maxTemp\", {\r\n type: \"state\",\r\n common: {\r\n name: {\r\n de: \"Max. Temperatur der Batterie\",\r\n en: \"max temp. of battery\",\r\n },\r\n type: \"number\",\r\n desc: \"Max. Temp\",\r\n role: \"value\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n\r\n // Convert Kelvin to Celsius\r\n await adapter?.setStateAsync(\r\n key + \".maxTemp\",\r\n x.maxTemp / 10 - 273.15,\r\n true,\r\n );\r\n }\r\n\r\n if (x.minVol) {\r\n await adapter?.extendObjectAsync(key + \".minVol\", {\r\n type: \"state\",\r\n common: {\r\n name: \"minVol\",\r\n type: \"number\",\r\n desc: \"minVol\",\r\n role: \"value\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n\r\n await adapter?.setStateAsync(key + \".minVol\", x.minVol / 100, true);\r\n }\r\n\r\n if (x.maxVol) {\r\n await adapter?.extendObjectAsync(key + \".maxVol\", {\r\n type: \"state\",\r\n common: {\r\n name: \"maxVol\",\r\n type: \"number\",\r\n desc: \"maxVol\",\r\n role: \"value\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n\r\n await adapter?.setStateAsync(key + \".maxVol\", x.maxVol / 100, true);\r\n }\r\n\r\n if (x.totalVol) {\r\n await adapter?.extendObjectAsync(key + \".totalVol\", {\r\n type: \"state\",\r\n common: {\r\n name: \"totalVol\",\r\n type: \"number\",\r\n desc: \"totalVol\",\r\n role: \"value\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n\r\n await adapter?.setStateAsync(key + \".totalVol\", x.totalVol / 100, true);\r\n }\r\n }\r\n });\r\n};\r\n\r\nconst onMessage = async (topic: string, message: Buffer): Promise<void> => {\r\n //adapter?.log.info(message.toString())\r\n if (adapter) {\r\n const splitted = topic.split(\"/\");\r\n const productKey = splitted[1];\r\n const deviceKey = splitted[2];\r\n\r\n const obj = JSON.parse(message.toString());\r\n\r\n // lastUpdate f\u00FCr den deviceKey setzen\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"lastUpdate\",\r\n new Date().getTime(),\r\n );\r\n\r\n if (\r\n obj.properties?.electricLevel != null &&\r\n obj.properties?.electricLevel != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"electricLevel\",\r\n obj.properties.electricLevel,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.outputHomePower != null &&\r\n obj.properties?.outputHomePower != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"outputHomePower\",\r\n obj.properties.outputHomePower,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.outputLimit != null &&\r\n obj.properties?.outputLimit != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"outputLimit\",\r\n obj.properties.outputLimit,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.outputPackPower != null &&\r\n obj.properties?.outputPackPower != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"outputPackPower\",\r\n obj.properties.outputPackPower,\r\n );\r\n\r\n // if outPutPackPower set packInputPower to 0\r\n updateSolarFlowState(adapter, productKey, deviceKey, \"packInputPower\", 0);\r\n }\r\n\r\n if (\r\n obj.properties?.packInputPower != null &&\r\n obj.properties?.packInputPower != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"packInputPower\",\r\n obj.properties.packInputPower,\r\n );\r\n\r\n // if packInputPower set outputPackPower to 0\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"outputPackPower\",\r\n 0,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.solarInputPower != null &&\r\n obj.properties?.solarInputPower != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"solarInputPower\",\r\n obj.properties.solarInputPower,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.pvPower1 != null &&\r\n obj.properties?.pvPower1 != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"pvPower2\", // Reversed to adjust like offical app\r\n obj.properties.pvPower1,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.pvPower2 != null &&\r\n obj.properties?.pvPower2 != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"pvPower1\", // Reversed to adjust like offical app\r\n obj.properties.pvPower2,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.solarPower1 != null &&\r\n obj.properties?.solarPower1 != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"pvPower1\",\r\n obj.properties.solarPower1,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.solarPower2 != null &&\r\n obj.properties?.solarPower2 != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"pvPower2\",\r\n obj.properties.solarPower2,\r\n );\r\n }\r\n\r\n if (\r\n obj.properties?.remainOutTime != null &&\r\n obj.properties?.remainOutTime != undefined\r\n ) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"remainOutTime\",\r\n obj.properties.remainOutTime,\r\n );\r\n\r\n // If Adapter calucation is used, calculate in and outtime\r\n if (adapter.config.useCalculation) {\r\n // Zendure use the same state for input und output values, if charging set remainInputTime, else remainOutTime\r\n const packInputPower = Number(\r\n (\r\n await adapter.getStateAsync(\r\n productKey + \".\" + deviceKey + \".packInputPower\",\r\n )\r\n )?.val,\r\n );\r\n const outputPackPower = Number(\r\n (\r\n await adapter.getStateAsync(\r\n productKey + \".\" + deviceKey + \".outputPackPower\",\r\n )\r\n )?.val,\r\n );\r\n\r\n if (packInputPower && packInputPower > 0) {\r\n // Calculate minutes to format hh:mm\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"calculations.remainOutTime\",\r\n obj.properties.remainOutTime < 59940\r\n ? toHoursAndMinutes(obj.properties.remainOutTime)\r\n : \"\",\r\n );\r\n\r\n // Set remainInputTime to blank\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"calculations.remainInputTime\",\r\n \"\",\r\n );\r\n } else if (outputPackPower && outputPackPower > 0) {\r\n // Calculate minutes to format hh:mm\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"calculations.remainInputTime\",\r\n obj.properties.remainInputTime < 59940\r\n ? toHoursAndMinutes(obj.properties.remainInputTime)\r\n : \"\",\r\n );\r\n\r\n // Set remainOutTime to blank\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"calculations.remainOutTime\",\r\n \"\",\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (obj.properties?.socSet != null && obj.properties?.socSet != undefined) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"socSet\",\r\n Number(obj.properties.socSet) / 10,\r\n );\r\n }\r\n\r\n if (obj.properties?.minSoc != null && obj.properties?.minSoc != undefined) {\r\n updateSolarFlowState(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n \"minSoc\",\r\n Number(obj.properties.minSoc) / 10,\r\n );\r\n }\r\n\r\n if (obj.packData) {\r\n addOrUpdatePackData(adapter, productKey, deviceKey, obj.packData);\r\n }\r\n }\r\n\r\n if (client) {\r\n //client.end();\r\n }\r\n};\r\n\r\nexport const setChargeLimit = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n socSet: number,\r\n): Promise<void> => {\r\n if (client && productKey && deviceKey) {\r\n if (socSet > 40 && socSet <= 100) {\r\n const topic = `iot/${productKey}/${deviceKey}/properties/write`;\r\n\r\n const socSetLimit = { properties: { socSet: socSet * 10 } };\r\n adapter.log.debug(\r\n `Setting ChargeLimit for device key ${deviceKey} to ${socSet}!`,\r\n );\r\n client?.publish(topic, JSON.stringify(socSetLimit));\r\n } else {\r\n adapter.log.debug(`Charge limit is not in range 40<>100!`);\r\n }\r\n }\r\n};\r\n\r\nexport const setDischargeLimit = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n minSoc: number,\r\n): Promise<void> => {\r\n if (client && productKey && deviceKey) {\r\n if (minSoc > 0 && minSoc < 90) {\r\n const topic = `iot/${productKey}/${deviceKey}/properties/write`;\r\n\r\n const socSetLimit = { properties: { minSoc: minSoc * 10 } };\r\n adapter.log.debug(\r\n `Setting Discharge Limit for device key ${deviceKey} to ${minSoc}!`,\r\n );\r\n client?.publish(topic, JSON.stringify(socSetLimit));\r\n } else {\r\n adapter.log.debug(`Discharge limit is not in range 0<>90!`);\r\n }\r\n }\r\n};\r\n\r\nexport const setOutputLimit = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n limit: number,\r\n): Promise<void> => {\r\n if (client && productKey && deviceKey) {\r\n // Das Limit kann unter 100 nur in 30er Schritten gesetzt werden, dH. 30/60/90/100, wir rechnen das also um\r\n const currentLimit = (\r\n await adapter.getStateAsync(productKey + \".\" + deviceKey + \".outputLimit\")\r\n )?.val;\r\n\r\n if (currentLimit != null && currentLimit != undefined) {\r\n if (currentLimit != limit) {\r\n if (\r\n limit < 100 &&\r\n limit != 90 &&\r\n limit != 60 &&\r\n limit != 30 &&\r\n limit != 0\r\n ) {\r\n if (limit < 100 && limit > 90) {\r\n limit = 90;\r\n } else if (limit < 90 && limit > 60) {\r\n limit = 60;\r\n } else if (limit < 60 && limit > 30) {\r\n limit = 30;\r\n } else if (limit < 30) {\r\n limit = 30;\r\n }\r\n }\r\n\r\n // 'iot/{auth.productKey}/{auth.deviceKey}/properties/write' == Topic? Oder productKey,deviceKey aus Device Details?\r\n const topic = `iot/${productKey}/${deviceKey}/properties/write`;\r\n\r\n const outputlimit = { properties: { outputLimit: limit } };\r\n adapter.log.debug(\r\n `Setting Output Limit for device key ${deviceKey} to ${limit}!`,\r\n );\r\n client?.publish(topic, JSON.stringify(outputlimit));\r\n } else {\r\n adapter.log.debug(\r\n `Output Limit for device key ${deviceKey} is already at ${limit}!`,\r\n );\r\n }\r\n }\r\n }\r\n};\r\n\r\nexport const connectMqttClient = (_adapter: ZendureSolarflow): void => {\r\n adapter = _adapter;\r\n\r\n const options: mqtt.IClientOptions = {\r\n clientId: adapter.accessToken,\r\n username: \"zenApp\",\r\n password: \"oK#PCgy6OZxd\",\r\n clean: true,\r\n protocolVersion: 5,\r\n };\r\n\r\n if (mqtt && adapter && adapter.paths) {\r\n client = mqtt.connect(\r\n \"mqtt://\" + adapter.paths.mqttUrl + \":\" + adapter.paths.mqttPort,\r\n options,\r\n ); // create a client\r\n\r\n if (client && adapter) {\r\n client.on(\"connect\", onConnected);\r\n client.on(\"error\", onError);\r\n\r\n // Subscribe to Topic (appkey von Zendure)\r\n adapter.deviceList.forEach((device: ISolarFlowDeviceDetails) => {\r\n // States erstellen\r\n if (adapter) {\r\n createSolarFlowStates(adapter, device.productKey, device.deviceKey);\r\n\r\n // Set electricLevel (soc) from device details.\r\n updateSolarFlowState(\r\n adapter,\r\n device.productKey,\r\n device.deviceKey,\r\n \"electricLevel\",\r\n device.electricity,\r\n );\r\n\r\n const reportTopic = `/${device.productKey}/${device.deviceKey}/properties/report`;\r\n const iotTopic = `iot/${device.productKey}/${device.deviceKey}/#`;\r\n\r\n adapter.log.debug(`Subscribing to MQTT Topic: ${reportTopic}`);\r\n client?.subscribe(reportTopic, onSubscribe);\r\n adapter.log.debug(`Subscribing to MQTT Topic: ${iotTopic}`);\r\n client?.subscribe(iotTopic, onSubscribe);\r\n }\r\n });\r\n\r\n client.on(\"message\", onMessage);\r\n }\r\n }\r\n};\r\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,WAAsB;AAGtB,4BAAqC;AACrC,wBAAkC;AAClC,mCAAsC;AAGtC,IAAI,SAAiC;AACrC,IAAI,UAAwC;AAE5C,MAAM,cAAc,MAAY;AAC9B,qCAAS,IAAI,KAAK;AACpB;AAEA,MAAM,UAAU,CAAC,UAAqB;AACpC,qCAAS,IAAI,MAAM,uCAAuC;AAC5D;AAEA,MAAM,cAAmB,CAAC,UAAwB;AAChD,MAAI,OAAO;AACT,uCAAS,IAAI,MAAM,yCAAyC;AAAA,EAC9D,OAAO;AACL,uCAAS,IAAI,MAAM;AAAA,EACrB;AACF;AAEO,MAAM,sBAAsB,OACjCA,UACA,YACA,WACA,aACkB;AAClB,QAAM,SAAS,QAAQ,OAAO,MAAM;AAElC,QAAI,EAAE,IAAI;AAER,YAAM,OAAO,aAAa,MAAM,YAAY,eAAe,EAAE,IAAI;AAAA,QAC/DA,SAAQ;AAAA,QACR;AAAA,MACF;AAEA,aAAMA,YAAA,gBAAAA,SAAS,kBAAkB,MAAM,OAAO;AAAA,QAC5C,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,MAAM;AAAA,YACJ,IAAI;AAAA,YACJ,IAAI;AAAA,UACN;AAAA,UACA,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,QACA,QAAQ,CAAC;AAAA,MACX;AAEA,aAAMA,YAAA,gBAAAA,SAAS,cAAc,MAAM,OAAO,EAAE,IAAI;AAEhD,UAAI,EAAE,UAAU;AAEd,eAAMA,YAAA,gBAAAA,SAAS,kBAAkB,MAAM,aAAa;AAAA,UAClD,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,IAAI;AAAA,YACN;AAAA,YACA,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,UACA,QAAQ,CAAC;AAAA,QACX;AAEA,eAAMA,YAAA,gBAAAA,SAAS,cAAc,MAAM,aAAa,EAAE,UAAU;AAAA,MAC9D;AAEA,UAAI,EAAE,SAAS;AAEb,eAAMA,YAAA,gBAAAA,SAAS,kBAAkB,MAAM,YAAY;AAAA,UACjD,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,IAAI;AAAA,YACN;AAAA,YACA,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,UACA,QAAQ,CAAC;AAAA,QACX;AAGA,eAAMA,YAAA,gBAAAA,SAAS;AAAA,UACb,MAAM;AAAA,UACN,EAAE,UAAU,KAAK;AAAA,UACjB;AAAA;AAAA,MAEJ;AAEA,UAAI,EAAE,QAAQ;AACZ,eAAMA,YAAA,gBAAAA,SAAS,kBAAkB,MAAM,WAAW;AAAA,UAChD,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,UACA,QAAQ,CAAC;AAAA,QACX;AAEA,eAAMA,YAAA,gBAAAA,SAAS,cAAc,MAAM,WAAW,EAAE,SAAS,KAAK;AAAA,MAChE;AAEA,UAAI,EAAE,QAAQ;AACZ,eAAMA,YAAA,gBAAAA,SAAS,kBAAkB,MAAM,WAAW;AAAA,UAChD,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,UACA,QAAQ,CAAC;AAAA,QACX;AAEA,eAAMA,YAAA,gBAAAA,SAAS,cAAc,MAAM,WAAW,EAAE,SAAS,KAAK;AAAA,MAChE;AAEA,UAAI,EAAE,UAAU;AACd,eAAMA,YAAA,gBAAAA,SAAS,kBAAkB,MAAM,aAAa;AAAA,UAClD,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,UACA,QAAQ,CAAC;AAAA,QACX;AAEA,eAAMA,YAAA,gBAAAA,SAAS,cAAc,MAAM,aAAa,EAAE,WAAW,KAAK;AAAA,MACpE;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,MAAM,YAAY,OAAO,OAAe,YAAmC;AAnK3E;AAqKE,MAAI,SAAS;AACX,UAAM,WAAW,MAAM,MAAM,GAAG;AAChC,UAAM,aAAa,SAAS,CAAC;AAC7B,UAAM,YAAY,SAAS,CAAC;AAE5B,UAAM,MAAM,KAAK,MAAM,QAAQ,SAAS,CAAC;AAGzC;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,OACA,oBAAI,KAAK,GAAE,QAAQ;AAAA,IACrB;AAEA,UACE,SAAI,eAAJ,mBAAgB,kBAAiB,UACjC,SAAI,eAAJ,mBAAgB,kBAAiB,QACjC;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,oBAAmB,UACnC,SAAI,eAAJ,mBAAgB,oBAAmB,QACnC;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,gBAAe,UAC/B,SAAI,eAAJ,mBAAgB,gBAAe,QAC/B;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,oBAAmB,UACnC,SAAI,eAAJ,mBAAgB,oBAAmB,QACnC;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAGA,sDAAqB,SAAS,YAAY,WAAW,kBAAkB,CAAC;AAAA,IAC1E;AAEA,UACE,SAAI,eAAJ,mBAAgB,mBAAkB,UAClC,SAAI,eAAJ,mBAAgB,mBAAkB,QAClC;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAGA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,oBAAmB,UACnC,SAAI,eAAJ,mBAAgB,oBAAmB,QACnC;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,aAAY,UAC5B,SAAI,eAAJ,mBAAgB,aAAY,QAC5B;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,aAAY,UAC5B,SAAI,eAAJ,mBAAgB,aAAY,QAC5B;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,gBAAe,UAC/B,SAAI,eAAJ,mBAAgB,gBAAe,QAC/B;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,gBAAe,UAC/B,SAAI,eAAJ,mBAAgB,gBAAe,QAC/B;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAAA,IACF;AAEA,UACE,SAAI,eAAJ,mBAAgB,kBAAiB,UACjC,SAAI,eAAJ,mBAAgB,kBAAiB,QACjC;AACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI,WAAW;AAAA,MACjB;AAGA,UAAI,QAAQ,OAAO,gBAAgB;AAEjC,cAAM,iBAAiB;AAAA,WAEnB,WAAM,QAAQ;AAAA,YACZ,aAAa,MAAM,YAAY;AAAA,UACjC,MAFA,mBAGC;AAAA,QACL;AACA,cAAM,kBAAkB;AAAA,WAEpB,WAAM,QAAQ;AAAA,YACZ,aAAa,MAAM,YAAY;AAAA,UACjC,MAFA,mBAGC;AAAA,QACL;AAEA,YAAI,kBAAkB,iBAAiB,GAAG;AAExC;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,IAAI,WAAW,gBAAgB,YAC3B,qCAAkB,IAAI,WAAW,aAAa,IAC9C;AAAA,UACN;AAGA;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,WAAW,mBAAmB,kBAAkB,GAAG;AAEjD;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,IAAI,WAAW,kBAAkB,YAC7B,qCAAkB,IAAI,WAAW,eAAe,IAChD;AAAA,UACN;AAGA;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAI,SAAI,eAAJ,mBAAgB,WAAU,UAAQ,SAAI,eAAJ,mBAAgB,WAAU,QAAW;AACzE;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,IAAI,WAAW,MAAM,IAAI;AAAA,MAClC;AAAA,IACF;AAEA,UAAI,SAAI,eAAJ,mBAAgB,WAAU,UAAQ,SAAI,eAAJ,mBAAgB,WAAU,QAAW;AACzE;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,IAAI,WAAW,MAAM,IAAI;AAAA,MAClC;AAAA,IACF;AAEA,QAAI,IAAI,UAAU;AAChB,0BAAoB,SAAS,YAAY,WAAW,IAAI,QAAQ;AAAA,IAClE;AAAA,EACF;AAEA,MAAI,QAAQ;AAAA,EAEZ;AACF;AAEO,MAAM,iBAAiB,OAC5BA,UACA,YACA,WACA,WACkB;AAClB,MAAI,UAAU,cAAc,WAAW;AACrC,QAAI,SAAS,MAAM,UAAU,KAAK;AAChC,YAAM,QAAQ,OAAO,UAAU,IAAI,SAAS;AAE5C,YAAM,cAAc,EAAE,YAAY,EAAE,QAAQ,SAAS,GAAG,EAAE;AAC1D,MAAAA,SAAQ,IAAI;AAAA,QACV,sCAAsC,SAAS,OAAO,MAAM;AAAA,MAC9D;AACA,uCAAQ,QAAQ,OAAO,KAAK,UAAU,WAAW;AAAA,IACnD,OAAO;AACL,MAAAA,SAAQ,IAAI,MAAM,uCAAuC;AAAA,IAC3D;AAAA,EACF;AACF;AAEO,MAAM,oBAAoB,OAC/BA,UACA,YACA,WACA,WACkB;AAClB,MAAI,UAAU,cAAc,WAAW;AACrC,QAAI,SAAS,KAAK,SAAS,IAAI;AAC7B,YAAM,QAAQ,OAAO,UAAU,IAAI,SAAS;AAE5C,YAAM,cAAc,EAAE,YAAY,EAAE,QAAQ,SAAS,GAAG,EAAE;AAC1D,MAAAA,SAAQ,IAAI;AAAA,QACV,0CAA0C,SAAS,OAAO,MAAM;AAAA,MAClE;AACA,uCAAQ,QAAQ,OAAO,KAAK,UAAU,WAAW;AAAA,IACnD,OAAO;AACL,MAAAA,SAAQ,IAAI,MAAM,wCAAwC;AAAA,IAC5D;AAAA,EACF;AACF;AAEO,MAAM,iBAAiB,OAC5BA,UACA,YACA,WACA,UACkB;AA1dpB;AA2dE,MAAI,UAAU,cAAc,WAAW;AAErC,UAAM,gBACJ,WAAMA,SAAQ,cAAc,aAAa,MAAM,YAAY,cAAc,MAAzE,mBACC;AAEH,QAAI,gBAAgB,QAAQ,gBAAgB,QAAW;AACrD,UAAI,gBAAgB,OAAO;AACzB,YACE,QAAQ,OACR,SAAS,MACT,SAAS,MACT,SAAS,MACT,SAAS,GACT;AACA,cAAI,QAAQ,OAAO,QAAQ,IAAI;AAC7B,oBAAQ;AAAA,UACV,WAAW,QAAQ,MAAM,QAAQ,IAAI;AACnC,oBAAQ;AAAA,UACV,WAAW,QAAQ,MAAM,QAAQ,IAAI;AACnC,oBAAQ;AAAA,UACV,WAAW,QAAQ,IAAI;AACrB,oBAAQ;AAAA,UACV;AAAA,QACF;AAGA,cAAM,QAAQ,OAAO,UAAU,IAAI,SAAS;AAE5C,cAAM,cAAc,EAAE,YAAY,EAAE,aAAa,MAAM,EAAE;AACzD,QAAAA,SAAQ,IAAI;AAAA,UACV,uCAAuC,SAAS,OAAO,KAAK;AAAA,QAC9D;AACA,yCAAQ,QAAQ,OAAO,KAAK,UAAU,WAAW;AAAA,MACnD,OAAO;AACL,QAAAA,SAAQ,IAAI;AAAA,UACV,+BAA+B,SAAS,kBAAkB,KAAK;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,oBAAoB,CAAC,aAAqC;AACrE,YAAU;AAEV,QAAM,UAA+B;AAAA,IACnC,UAAU,QAAQ;AAAA,IAClB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,IACP,iBAAiB;AAAA,EACnB;AAEA,MAAI,QAAQ,WAAW,QAAQ,OAAO;AACpC,aAAS,KAAK;AAAA,MACZ,YAAY,QAAQ,MAAM,UAAU,MAAM,QAAQ,MAAM;AAAA,MACxD;AAAA,IACF;AAEA,QAAI,UAAU,SAAS;AACrB,aAAO,GAAG,WAAW,WAAW;AAChC,aAAO,GAAG,SAAS,OAAO;AAG1B,cAAQ,WAAW,QAAQ,CAAC,WAAoC;AAE9D,YAAI,SAAS;AACX,kEAAsB,SAAS,OAAO,YAAY,OAAO,SAAS;AAGlE;AAAA,YACE;AAAA,YACA,OAAO;AAAA,YACP,OAAO;AAAA,YACP;AAAA,YACA,OAAO;AAAA,UACT;AAEA,gBAAM,cAAc,IAAI,OAAO,UAAU,IAAI,OAAO,SAAS;AAC7D,gBAAM,WAAW,OAAO,OAAO,UAAU,IAAI,OAAO,SAAS;AAE7D,kBAAQ,IAAI,MAAM,8BAA8B,WAAW,EAAE;AAC7D,2CAAQ,UAAU,aAAa;AAC/B,kBAAQ,IAAI,MAAM,8BAA8B,QAAQ,EAAE;AAC1D,2CAAQ,UAAU,UAAU;AAAA,QAC9B;AAAA,MACF,CAAC;AAED,aAAO,GAAG,WAAW,SAAS;AAAA,IAChC;AAAA,EACF;AACF;",
|
|
6
6
|
"names": ["adapter"]
|
|
7
7
|
}
|
|
@@ -73,7 +73,7 @@ const login = (adapter) => {
|
|
|
73
73
|
return import_axios.default.post(adapter.paths.solarFlowTokenUrl, authBody, config).then(function(response) {
|
|
74
74
|
var _a, _b;
|
|
75
75
|
if (response.data.success) {
|
|
76
|
-
adapter.log.info("Login to Rest API successful!");
|
|
76
|
+
adapter.log.info("Login to Zendure Rest API successful!");
|
|
77
77
|
if ((_b = (_a = response.data) == null ? void 0 : _a.data) == null ? void 0 : _b.accessToken) {
|
|
78
78
|
return response.data.data.accessToken;
|
|
79
79
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/services/webService.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\r\nimport { pathsEu, pathsGlobal } from \"../constants/paths\";\r\nimport { ZendureSolarflow } from \"../main\";\r\nimport axios, { AxiosRequestConfig } from \"axios\";\r\nimport { ISolarFlowDeviceDetails } from \"../models/ISolarFlowDeviceDetails\";\r\n\r\nconst config: AxiosRequestConfig = {\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"Accept-Language\": \"de-DE\",\r\n appVersion: \"4.3.1\",\r\n \"User-Agent\": \"Zendure/4.3.1 (iPhone; iOS 14.4.2; Scale/3.00)\",\r\n Accept: \"*/*\",\r\n Authorization: \"Basic Q29uc3VtZXJBcHA6NX4qUmRuTnJATWg0WjEyMw==\",\r\n \"Blade-Auth\": \"bearer (null)\",\r\n },\r\n timeout: 10000,\r\n};\r\n\r\n/* eslint-disable @typescript-eslint/indent */\r\nexport const login = (adapter: ZendureSolarflow): Promise<string> => {\r\n if (adapter.accessToken) {\r\n return new Promise((resolve) => {\r\n if (adapter.accessToken) {\r\n resolve(adapter.accessToken);\r\n }\r\n });\r\n }\r\n\r\n const auth = Buffer.from(\r\n `${adapter.config.userName}:${adapter.config.password}`,\r\n ).toString(\"base64\");\r\n\r\n if (!config || !config.headers) {\r\n return Promise.reject(\"No axios config!\");\r\n }\r\n\r\n config.headers.Authorization = \"Basic \" + auth;\r\n\r\n const authBody = {\r\n password: adapter.config.password,\r\n account: adapter.config.userName,\r\n appId: \"121c83f761305d6cf7b\",\r\n appType: \"iOS\",\r\n grantType: \"password\",\r\n tenantId: \"\",\r\n };\r\n\r\n if (adapter.paths && adapter.paths.solarFlowTokenUrl) {\r\n return axios\r\n .post(adapter.paths.solarFlowTokenUrl, authBody, config)\r\n .then(function (response) {\r\n if (response.data.success) {\r\n adapter.log.info(\"Login to Rest API successful!\");\r\n\r\n if (response.data?.data?.accessToken) {\r\n return response.data.data.accessToken;\r\n }\r\n }\r\n })\r\n .catch(function (error) {\r\n adapter.log.error(error);\r\n return Promise.reject(\"Failed to login to Zendure REST API!\");\r\n });\r\n } else return Promise.reject(\"Path error!\");\r\n};\r\n\r\nexport const getDeviceList = (\r\n adapter: ZendureSolarflow,\r\n): Promise<ISolarFlowDeviceDetails[]> => {\r\n //adapter.setState(\"errorMessage\", \"no_error\");\r\n adapter.log.debug(\"Getting device list from Zendure Rest API!\");\r\n\r\n if (adapter.accessToken && config && config.headers) {\r\n config.headers[\"Blade-Auth\"] = \"bearer \" + adapter.accessToken;\r\n\r\n const body = {};\r\n\r\n let paths = undefined;\r\n\r\n if (adapter.config.server == \"eu\") {\r\n paths = pathsEu;\r\n } else {\r\n paths = pathsGlobal;\r\n }\r\n\r\n return axios\r\n .post(paths.solarFlowQueryDeviceListUrl, JSON.stringify(body), config)\r\n .then(function (response) {\r\n if (response.data.data && response.data.data.length > 0) {\r\n return response.data.data as ISolarFlowDeviceDetails[];\r\n } else {\r\n return [];\r\n }\r\n });\r\n } else {\r\n adapter.log.error(\"No Access Token found!\");\r\n return Promise.reject(\"No Access Token found!\");\r\n }\r\n};\r\n\r\n/* export const createDeveloperAccount = (adapter: ZendureSolarflow) => {\r\n adapter.log.info(\"Function createDeveloperAccount\");\r\n\r\n adapter.setState(\"errorMessage\", \"\");\r\n\r\n const body = {\r\n snNumber: adapter.snNumber,\r\n account: adapter.config.userName,\r\n };\r\n\r\n let paths = undefined;\r\n\r\n if (adapter.config.server == \"eu\") {\r\n paths = pathsEu;\r\n } else {\r\n paths = pathsGlobal;\r\n }\r\n\r\n return axios\r\n .post(paths.solarFlowDevRegisterUrl, JSON.stringify(body), config)\r\n .then(function (response) {\r\n adapter.log.info(\"Successfully created Developer Account!\");\r\n\r\n if (response.data && response.data.success == true) {\r\n return response.data.data;\r\n } else {\r\n console.warn(\"No Response Data!\");\r\n return undefined;\r\n }\r\n })\r\n .catch(function (error) {\r\n adapter.setObjectNotExists(\"errorMessage\", {\r\n type: \"state\",\r\n common: {\r\n name: \"errorMessage\",\r\n type: \"string\",\r\n role: \"indicator\",\r\n read: true,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n adapter.setState(\r\n \"errorMessage\",\r\n error.response?.data?.code + \" - \" + error.response.data.msg,\r\n );\r\n\r\n if (error.response?.data?.code && error.response?.data?.msg) {\r\n // The request was made and the server responded with a status code\r\n // that falls out of the range of 2xx\r\n adapter.log.error(\r\n \"Failed to created Zendure Developer Account: \" +\r\n error.response?.data?.code +\r\n \" - \" +\r\n error.response.data.msg,\r\n );\r\n }\r\n\r\n return Promise.reject(\"Failed to created Zendure Developer Account!\");\r\n });\r\n};*/\r\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAqC;AAErC,mBAA0C;AAG1C,MAAM,SAA6B;AAAA,EACjC,SAAS;AAAA,IACP,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,cAAc;AAAA,EAChB;AAAA,EACA,SAAS;AACX;AAGO,MAAM,QAAQ,CAAC,YAA+C;AACnE,MAAI,QAAQ,aAAa;AACvB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAI,QAAQ,aAAa;AACvB,gBAAQ,QAAQ,WAAW;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,OAAO;AAAA,IAClB,GAAG,QAAQ,OAAO,QAAQ,IAAI,QAAQ,OAAO,QAAQ;AAAA,EACvD,EAAE,SAAS,QAAQ;AAEnB,MAAI,CAAC,UAAU,CAAC,OAAO,SAAS;AAC9B,WAAO,QAAQ,OAAO,kBAAkB;AAAA,EAC1C;AAEA,SAAO,QAAQ,gBAAgB,WAAW;AAE1C,QAAM,WAAW;AAAA,IACf,UAAU,QAAQ,OAAO;AAAA,IACzB,SAAS,QAAQ,OAAO;AAAA,IACxB,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAEA,MAAI,QAAQ,SAAS,QAAQ,MAAM,mBAAmB;AACpD,WAAO,aAAAA,QACJ,KAAK,QAAQ,MAAM,mBAAmB,UAAU,MAAM,EACtD,KAAK,SAAU,UAAU;AAnDhC;AAoDQ,UAAI,SAAS,KAAK,SAAS;AACzB,gBAAQ,IAAI,KAAK
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\r\nimport { pathsEu, pathsGlobal } from \"../constants/paths\";\r\nimport { ZendureSolarflow } from \"../main\";\r\nimport axios, { AxiosRequestConfig } from \"axios\";\r\nimport { ISolarFlowDeviceDetails } from \"../models/ISolarFlowDeviceDetails\";\r\n\r\nconst config: AxiosRequestConfig = {\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"Accept-Language\": \"de-DE\",\r\n appVersion: \"4.3.1\",\r\n \"User-Agent\": \"Zendure/4.3.1 (iPhone; iOS 14.4.2; Scale/3.00)\",\r\n Accept: \"*/*\",\r\n Authorization: \"Basic Q29uc3VtZXJBcHA6NX4qUmRuTnJATWg0WjEyMw==\",\r\n \"Blade-Auth\": \"bearer (null)\",\r\n },\r\n timeout: 10000,\r\n};\r\n\r\n/* eslint-disable @typescript-eslint/indent */\r\nexport const login = (adapter: ZendureSolarflow): Promise<string> => {\r\n if (adapter.accessToken) {\r\n return new Promise((resolve) => {\r\n if (adapter.accessToken) {\r\n resolve(adapter.accessToken);\r\n }\r\n });\r\n }\r\n\r\n const auth = Buffer.from(\r\n `${adapter.config.userName}:${adapter.config.password}`,\r\n ).toString(\"base64\");\r\n\r\n if (!config || !config.headers) {\r\n return Promise.reject(\"No axios config!\");\r\n }\r\n\r\n config.headers.Authorization = \"Basic \" + auth;\r\n\r\n const authBody = {\r\n password: adapter.config.password,\r\n account: adapter.config.userName,\r\n appId: \"121c83f761305d6cf7b\",\r\n appType: \"iOS\",\r\n grantType: \"password\",\r\n tenantId: \"\",\r\n };\r\n\r\n if (adapter.paths && adapter.paths.solarFlowTokenUrl) {\r\n return axios\r\n .post(adapter.paths.solarFlowTokenUrl, authBody, config)\r\n .then(function (response) {\r\n if (response.data.success) {\r\n adapter.log.info(\"Login to Zendure Rest API successful!\");\r\n\r\n if (response.data?.data?.accessToken) {\r\n return response.data.data.accessToken;\r\n }\r\n }\r\n })\r\n .catch(function (error) {\r\n adapter.log.error(error);\r\n return Promise.reject(\"Failed to login to Zendure REST API!\");\r\n });\r\n } else return Promise.reject(\"Path error!\");\r\n};\r\n\r\nexport const getDeviceList = (\r\n adapter: ZendureSolarflow,\r\n): Promise<ISolarFlowDeviceDetails[]> => {\r\n //adapter.setState(\"errorMessage\", \"no_error\");\r\n adapter.log.debug(\"Getting device list from Zendure Rest API!\");\r\n\r\n if (adapter.accessToken && config && config.headers) {\r\n config.headers[\"Blade-Auth\"] = \"bearer \" + adapter.accessToken;\r\n\r\n const body = {};\r\n\r\n let paths = undefined;\r\n\r\n if (adapter.config.server == \"eu\") {\r\n paths = pathsEu;\r\n } else {\r\n paths = pathsGlobal;\r\n }\r\n\r\n return axios\r\n .post(paths.solarFlowQueryDeviceListUrl, JSON.stringify(body), config)\r\n .then(function (response) {\r\n if (response.data.data && response.data.data.length > 0) {\r\n return response.data.data as ISolarFlowDeviceDetails[];\r\n } else {\r\n return [];\r\n }\r\n });\r\n } else {\r\n adapter.log.error(\"No Access Token found!\");\r\n return Promise.reject(\"No Access Token found!\");\r\n }\r\n};\r\n\r\n/* export const createDeveloperAccount = (adapter: ZendureSolarflow) => {\r\n adapter.log.info(\"Function createDeveloperAccount\");\r\n\r\n adapter.setState(\"errorMessage\", \"\");\r\n\r\n const body = {\r\n snNumber: adapter.snNumber,\r\n account: adapter.config.userName,\r\n };\r\n\r\n let paths = undefined;\r\n\r\n if (adapter.config.server == \"eu\") {\r\n paths = pathsEu;\r\n } else {\r\n paths = pathsGlobal;\r\n }\r\n\r\n return axios\r\n .post(paths.solarFlowDevRegisterUrl, JSON.stringify(body), config)\r\n .then(function (response) {\r\n adapter.log.info(\"Successfully created Developer Account!\");\r\n\r\n if (response.data && response.data.success == true) {\r\n return response.data.data;\r\n } else {\r\n console.warn(\"No Response Data!\");\r\n return undefined;\r\n }\r\n })\r\n .catch(function (error) {\r\n adapter.setObjectNotExists(\"errorMessage\", {\r\n type: \"state\",\r\n common: {\r\n name: \"errorMessage\",\r\n type: \"string\",\r\n role: \"indicator\",\r\n read: true,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n adapter.setState(\r\n \"errorMessage\",\r\n error.response?.data?.code + \" - \" + error.response.data.msg,\r\n );\r\n\r\n if (error.response?.data?.code && error.response?.data?.msg) {\r\n // The request was made and the server responded with a status code\r\n // that falls out of the range of 2xx\r\n adapter.log.error(\r\n \"Failed to created Zendure Developer Account: \" +\r\n error.response?.data?.code +\r\n \" - \" +\r\n error.response.data.msg,\r\n );\r\n }\r\n\r\n return Promise.reject(\"Failed to created Zendure Developer Account!\");\r\n });\r\n};*/\r\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAqC;AAErC,mBAA0C;AAG1C,MAAM,SAA6B;AAAA,EACjC,SAAS;AAAA,IACP,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,cAAc;AAAA,EAChB;AAAA,EACA,SAAS;AACX;AAGO,MAAM,QAAQ,CAAC,YAA+C;AACnE,MAAI,QAAQ,aAAa;AACvB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAI,QAAQ,aAAa;AACvB,gBAAQ,QAAQ,WAAW;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,OAAO;AAAA,IAClB,GAAG,QAAQ,OAAO,QAAQ,IAAI,QAAQ,OAAO,QAAQ;AAAA,EACvD,EAAE,SAAS,QAAQ;AAEnB,MAAI,CAAC,UAAU,CAAC,OAAO,SAAS;AAC9B,WAAO,QAAQ,OAAO,kBAAkB;AAAA,EAC1C;AAEA,SAAO,QAAQ,gBAAgB,WAAW;AAE1C,QAAM,WAAW;AAAA,IACf,UAAU,QAAQ,OAAO;AAAA,IACzB,SAAS,QAAQ,OAAO;AAAA,IACxB,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAEA,MAAI,QAAQ,SAAS,QAAQ,MAAM,mBAAmB;AACpD,WAAO,aAAAA,QACJ,KAAK,QAAQ,MAAM,mBAAmB,UAAU,MAAM,EACtD,KAAK,SAAU,UAAU;AAnDhC;AAoDQ,UAAI,SAAS,KAAK,SAAS;AACzB,gBAAQ,IAAI,KAAK,uCAAuC;AAExD,aAAI,oBAAS,SAAT,mBAAe,SAAf,mBAAqB,aAAa;AACpC,iBAAO,SAAS,KAAK,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,CAAC,EACA,MAAM,SAAU,OAAO;AACtB,cAAQ,IAAI,MAAM,KAAK;AACvB,aAAO,QAAQ,OAAO,sCAAsC;AAAA,IAC9D,CAAC;AAAA,EACL;AAAO,WAAO,QAAQ,OAAO,aAAa;AAC5C;AAEO,MAAM,gBAAgB,CAC3B,YACuC;AAEvC,UAAQ,IAAI,MAAM,4CAA4C;AAE9D,MAAI,QAAQ,eAAe,UAAU,OAAO,SAAS;AACnD,WAAO,QAAQ,YAAY,IAAI,YAAY,QAAQ;AAEnD,UAAM,OAAO,CAAC;AAEd,QAAI,QAAQ;AAEZ,QAAI,QAAQ,OAAO,UAAU,MAAM;AACjC,cAAQ;AAAA,IACV,OAAO;AACL,cAAQ;AAAA,IACV;AAEA,WAAO,aAAAA,QACJ,KAAK,MAAM,6BAA6B,KAAK,UAAU,IAAI,GAAG,MAAM,EACpE,KAAK,SAAU,UAAU;AACxB,UAAI,SAAS,KAAK,QAAQ,SAAS,KAAK,KAAK,SAAS,GAAG;AACvD,eAAO,SAAS,KAAK;AAAA,MACvB,OAAO;AACL,eAAO,CAAC;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACL,OAAO;AACL,YAAQ,IAAI,MAAM,wBAAwB;AAC1C,WAAO,QAAQ,OAAO,wBAAwB;AAAA,EAChD;AACF;",
|
|
6
6
|
"names": ["axios"]
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "zendure-solarflow",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.13",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.1.13": {
|
|
7
|
+
"en": "Reorganize Code\nCalculations are now optional and have to be enabled in settings\nCalculation of SOC from voltage and energy go in and out of batteries\nStop energy feed if voltage drops under limit",
|
|
8
|
+
"de": "Reorganisieren Code\nBerechnungen sind nun optional und müssen in Einstellungen aktiviert werden\nBerechnung von SOC aus Spannung und Energie gehen in und aus Batterien\nStoppen Sie die Energiezufuhr, wenn die Spannung unter Grenzwert sinkt",
|
|
9
|
+
"ru": "Реорганизовать код\nРасчеты теперь необязательны и должны быть включены в настройки\nРасчет SOC от напряжения и энергии идет в и из батарей\nОстановить источник энергии, если напряжение падает под лимит",
|
|
10
|
+
"pt": "Reorganizar código\nCálculos agora são opcionais e têm de ser ativados em configurações\nCálculo de SOC de tensão e energia entrar e sair de baterias\nPare a alimentação de energia se a tensão cair sob limite",
|
|
11
|
+
"nl": "Code herschikken\nBerekeningen zijn nu optioneel en moeten worden ingeschakeld in instellingen\nBerekening van SOC uit spanning en energie gaan in en uit batterijen\nStop energietoevoer als de spanning onder de limiet daalt",
|
|
12
|
+
"fr": "Réorganiser le code\nLes calculs sont désormais optionnels et doivent être activés dans les paramètres\nCalcul du COS à partir de la tension et de l'énergie entrent et sortent des batteries\nArrêt de l'alimentation en énergie si la tension tombe sous la limite",
|
|
13
|
+
"it": "Riorganizzare il Codice\nI calcoli sono ora facoltativi e devono essere abilitati nelle impostazioni\nCalcolo di SOC da tensione ed energia vanno dentro e fuori dalle batterie\nSmettere di alimentazione di energia se la tensione scende sotto limite",
|
|
14
|
+
"es": "Reorganizar el Código\nLas cálculos son ahora opcionales y tienen que ser habilitados en la configuración\nCálculo de SOC a partir del voltaje y la energía entran y salen de las baterías\nStop energy feed if tension drops under limit",
|
|
15
|
+
"pl": "Kod reorganizacji\nObliczenia są teraz opcjonalne i muszą być włączone w ustawieniach\nObliczanie SOC z napięcia i energii wchodzi i wychodzi z baterii\nZatrzymać zasilanie energetyczne, jeśli napięcie spada w granicach",
|
|
16
|
+
"uk": "Код реорганізації\nРозрахунок тепер необов'язково і потрібно ввімкнути в налаштуваннях\nРозрахунок SOC від напруги і енергії йти і з батарей\nЗупинити живлення енергії, якщо краплі напруги під лімітом",
|
|
17
|
+
"zh-cn": "重组代码\n现在计算是可选的,必须在设置中启用\n从电压和能量中计算出电池的SOC\n如果电压下降, 停止能量喂养"
|
|
18
|
+
},
|
|
19
|
+
"1.1.12": {
|
|
20
|
+
"en": "Reorganize Code\nCalculations are now optional and have to be enabled in settings\nCalculation of SOC from voltage and energy go in and out of batteries\nStop energy feed if voltage drops under limit",
|
|
21
|
+
"de": "Reorganisieren Code\nBerechnungen sind nun optional und müssen in Einstellungen aktiviert werden\nBerechnung von SOC aus Spannung und Energie gehen in und aus Batterien\nStoppen Sie die Energiezufuhr, wenn die Spannung unter Grenzwert sinkt",
|
|
22
|
+
"ru": "Реорганизовать код\nРасчеты теперь необязательны и должны быть включены в настройки\nРасчет SOC от напряжения и энергии идет в и из батарей\nОстановить источник энергии, если напряжение падает под лимит",
|
|
23
|
+
"pt": "Reorganizar código\nCálculos agora são opcionais e têm de ser ativados em configurações\nCálculo de SOC de tensão e energia entrar e sair de baterias\nPare a alimentação de energia se a tensão cair sob limite",
|
|
24
|
+
"nl": "Code herschikken\nBerekeningen zijn nu optioneel en moeten worden ingeschakeld in instellingen\nBerekening van SOC uit spanning en energie gaan in en uit batterijen\nStop energietoevoer als de spanning onder de limiet daalt",
|
|
25
|
+
"fr": "Réorganiser le code\nLes calculs sont désormais optionnels et doivent être activés dans les paramètres\nCalcul du COS à partir de la tension et de l'énergie entrent et sortent des batteries\nArrêt de l'alimentation en énergie si la tension tombe sous la limite",
|
|
26
|
+
"it": "Riorganizzare il Codice\nI calcoli sono ora facoltativi e devono essere abilitati nelle impostazioni\nCalcolo di SOC da tensione ed energia vanno dentro e fuori dalle batterie\nSmettere di alimentazione di energia se la tensione scende sotto limite",
|
|
27
|
+
"es": "Reorganizar el Código\nLas cálculos son ahora opcionales y tienen que ser habilitados en la configuración\nCálculo de SOC a partir del voltaje y la energía entran y salen de las baterías\nStop energy feed if tension drops under limit",
|
|
28
|
+
"pl": "Kod reorganizacji\nObliczenia są teraz opcjonalne i muszą być włączone w ustawieniach\nObliczanie SOC z napięcia i energii wchodzi i wychodzi z baterii\nZatrzymać zasilanie energetyczne, jeśli napięcie spada w granicach",
|
|
29
|
+
"uk": "Код реорганізації\nРозрахунок тепер необов'язково і потрібно ввімкнути в налаштуваннях\nРозрахунок SOC від напруги і енергії йти і з батарей\nЗупинити живлення енергії, якщо краплі напруги під лімітом",
|
|
30
|
+
"zh-cn": "重组代码\n现在计算是可选的,必须在设置中启用\n从电压和能量中计算出电池的SOC\n如果电压下降, 停止能量喂养"
|
|
31
|
+
},
|
|
6
32
|
"1.1.11": {
|
|
7
33
|
"en": "Fix Solar Input 1 and 2 from the new Zendure firmware\nFix remaining charging time\nFix calculations overwritten when data with 0 value comes in.",
|
|
8
34
|
"de": "Fix Solar Input 1 und 2 von der neuen Zendure Firmware\nVerbleibende Ladezeit\nFix Berechnungen überschrieben, wenn Daten mit 0 Wert kommen.",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "Dodaj obliczenia energii na dziś '\nNapraw błąd wyświetlania minut dla pozostałego czasu ładowania i rozładowania",
|
|
68
94
|
"uk": "Додавання енергорозрахунків за добу Р\nВиправлення хвилин відображення помилок для решти часу заряду та розряду",
|
|
69
95
|
"zh-cn": "为今天添加能量计算 '\n为剩余充电和放电时间修正分钟显示错误"
|
|
70
|
-
},
|
|
71
|
-
"1.1.6": {
|
|
72
|
-
"en": "Add energy calculations for 'today'\nFix minutes display bug for remaining charge and discharge time",
|
|
73
|
-
"de": "Energieberechnungen für heute hinzufügen '\nFehler der Minutenanzeige für die verbleibende Lade- und Entladezeit",
|
|
74
|
-
"ru": "Добавить расчеты энергии для \"сегодня\" \"\n6 минут дисплей клоп для оставшегося заряда и времени выгрузки",
|
|
75
|
-
"pt": "Adicionar cálculos de energia para 'hoje '\nCorrigir minutos exibir bug para o tempo restante de carga e descarga",
|
|
76
|
-
"nl": "Energieberekeningen toevoegen voor 'vandaag' '\nFix minuten weergave bug voor resterende lading en ontladingstijd",
|
|
77
|
-
"fr": "Ajouter le calcul de l'énergie pour «aujourd'hui» '\nCorrection minutes affichage bug pour la charge restante et le temps de décharge",
|
|
78
|
-
"it": "Aggiungere calcoli energetici per 'oggi '\nFissare il bug di visualizzazione dei minuti per il tempo di carica e di scarico rimanenti",
|
|
79
|
-
"es": "Añadir cálculos energéticos para 'hoy '\nError de visualización de minutos fijo para el tiempo de carga y descarga restante",
|
|
80
|
-
"pl": "Dodaj obliczenia energii na dziś '\nNapraw błąd wyświetlania minut dla pozostałego czasu ładowania i rozładowania",
|
|
81
|
-
"uk": "Додавання енергорозрахунків за добу Р\nВиправлення хвилин відображення помилок для решти часу заряду та розряду",
|
|
82
|
-
"zh-cn": "为今天添加能量计算 '\n为剩余充电和放电时间修正分钟显示错误"
|
|
83
|
-
},
|
|
84
|
-
"1.1.5": {
|
|
85
|
-
"en": "Add energy calculations for 'today'\nFix minutes display bug for remaining charge and discharge time",
|
|
86
|
-
"de": "Energieberechnungen für heute hinzufügen '\nFehler der Minutenanzeige für die verbleibende Lade- und Entladezeit",
|
|
87
|
-
"ru": "Добавить расчеты энергии для \"сегодня\" \"\n6 минут дисплей клоп для оставшегося заряда и времени выгрузки",
|
|
88
|
-
"pt": "Adicionar cálculos de energia para 'hoje '\nCorrigir minutos exibir bug para o tempo restante de carga e descarga",
|
|
89
|
-
"nl": "Energieberekeningen toevoegen voor 'vandaag' '\nFix minuten weergave bug voor resterende lading en ontladingstijd",
|
|
90
|
-
"fr": "Ajouter le calcul de l'énergie pour «aujourd'hui» '\nCorrection minutes affichage bug pour la charge restante et le temps de décharge",
|
|
91
|
-
"it": "Aggiungere calcoli energetici per 'oggi '\nFissare il bug di visualizzazione dei minuti per il tempo di carica e di scarico rimanenti",
|
|
92
|
-
"es": "Añadir cálculos energéticos para 'hoy '\nError de visualización de minutos fijo para el tiempo de carga y descarga restante",
|
|
93
|
-
"pl": "Dodaj obliczenia energii na dziś '\nNapraw błąd wyświetlania minut dla pozostałego czasu ładowania i rozładowania",
|
|
94
|
-
"uk": "Додавання енергорозрахунків за добу Р\nВиправлення хвилин відображення помилок для решти часу заряду та розряду",
|
|
95
|
-
"zh-cn": "为今天添加能量计算 '\n为剩余充电和放电时间修正分钟显示错误"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"title": "Zendure Solarflow",
|