iobroker.zendure-solarflow 1.2.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,15 +38,12 @@ If you find the adapter useful for you and want to support my work, feel free to
38
38
  [![Donate](https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white)](https://www.paypal.com/paypalme/PeterFrommert)
39
39
 
40
40
  ## Changelog
41
- ### 1.2.7 (2024-03-22)
41
+ ### 1.3.0 (2024-03-26)
42
42
 
43
43
  - Fix calculation for outputPackEnergy and packInputEnergy
44
44
  - Trigger full telemetry update on adapter start
45
45
  - Add state and control for buzzer switch
46
- - Add state and control for bypass mode and automatic reset of bypass mode next day
47
-
48
- ### 1.2.6 (2024-03-20)
49
-
46
+ - Add state and control for bypass mode and automatic reset of bypass mode next day
50
47
  - Add states for pass (Bypass on/off), autoRecover (auto-mode for Bypass next day) and passMode (current bypass mode)
51
48
  - Add efficiency factor for calculations (96% charging, 92%-98%\* for discharging - based on measuring from VoltAmpereLux Youtube channel - THANKS!)
52
49
  - Changed calculations timeframe from 10secs to 30secs (performance related)
@@ -74,23 +74,45 @@ const calculateSocAndEnergy = async (adapter, productKey, deviceKey, stateKey, v
74
74
  true
75
75
  ));
76
76
  }
77
- if (stateKey == "outputPack") {
77
+ const currentOutputPackPower = await (adapter == null ? void 0 : adapter.getStateAsync(
78
+ `${productKey}.${deviceKey}.outputPackPower`
79
+ ));
80
+ const currentPackInputPower = await (adapter == null ? void 0 : adapter.getStateAsync(
81
+ productKey + "." + deviceKey + ".packInputPower"
82
+ ));
83
+ if (stateKey == "outputPack" && (currentOutputPackPower == null ? void 0 : currentOutputPackPower.val) != null && currentOutputPackPower != void 0) {
78
84
  const toCharge = Number(currentEnergyMaxState.val) - newValue;
79
- const remainHoursAsDecimal = toCharge / value;
80
- const remainFormatted = (0, import_timeHelper.toHoursAndMinutes)(remainHoursAsDecimal * 60);
81
- await (adapter == null ? void 0 : adapter.setStateAsync(
82
- `${productKey}.${deviceKey}.calculations.remainInputTime`,
83
- remainFormatted,
84
- true
85
- ));
86
- } else if (stateKey == "packInput") {
87
- const remainHoursAsDecimal = newValue / value;
88
- const remainFormatted = (0, import_timeHelper.toHoursAndMinutes)(remainHoursAsDecimal * 60);
89
- await (adapter == null ? void 0 : adapter.setStateAsync(
90
- `${productKey}.${deviceKey}.calculations.remainInputTime`,
91
- remainFormatted,
92
- true
93
- ));
85
+ const remainHoursAsDecimal = toCharge / Number(currentOutputPackPower.val);
86
+ if (remainHoursAsDecimal < 10) {
87
+ const remainFormatted = (0, import_timeHelper.toHoursAndMinutes)(Math.round(remainHoursAsDecimal * 60));
88
+ await (adapter == null ? void 0 : adapter.setStateAsync(
89
+ `${productKey}.${deviceKey}.calculations.remainInputTime`,
90
+ remainFormatted,
91
+ true
92
+ ));
93
+ } else {
94
+ await (adapter == null ? void 0 : adapter.setStateAsync(
95
+ `${productKey}.${deviceKey}.calculations.remainInputTime`,
96
+ "-",
97
+ true
98
+ ));
99
+ }
100
+ } else if (stateKey == "packInput" && currentPackInputPower != null && currentPackInputPower != void 0) {
101
+ const remainHoursAsDecimal = newValue / Number(currentPackInputPower.val);
102
+ const remainFormatted = (0, import_timeHelper.toHoursAndMinutes)(Math.round(remainHoursAsDecimal * 60));
103
+ if (remainHoursAsDecimal < 40) {
104
+ await (adapter == null ? void 0 : adapter.setStateAsync(
105
+ `${productKey}.${deviceKey}.calculations.remainOutTime`,
106
+ remainFormatted,
107
+ true
108
+ ));
109
+ } else {
110
+ await (adapter == null ? void 0 : adapter.setStateAsync(
111
+ `${productKey}.${deviceKey}.calculations.remainOutTime`,
112
+ "-",
113
+ true
114
+ ));
115
+ }
94
116
  }
95
117
  } else {
96
118
  await (adapter == null ? void 0 : adapter.setStateAsync(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/services/calculationService.ts"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\r\n\r\nimport { toHoursAndMinutes } from \"../helpers/timeHelper\";\r\nimport { ZendureSolarflow } from \"../main\";\r\nimport { ISolarFlowDeviceDetails } from \"../models/ISolarFlowDeviceDetails\";\r\n\r\nconst calculationStateKeys = [\r\n \"packInput\",\r\n \"outputHome\",\r\n \"outputPack\",\r\n \"solarInput\",\r\n];\r\n\r\nexport const setEnergyWhMax = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n): Promise<void> => {\r\n const currentEnergyState = await adapter?.getStateAsync(\r\n productKey + \".\" + deviceKey + \".calculations.energyWh\",\r\n );\r\n\r\n if (currentEnergyState) {\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.energyWhMax`,\r\n currentEnergyState?.val,\r\n true,\r\n );\r\n }\r\n};\r\n\r\nexport const calculateSocAndEnergy = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n stateKey: string,\r\n value: number,\r\n): Promise<void> => {\r\n const currentEnergyState = await adapter?.getStateAsync(\r\n productKey + \".\" + deviceKey + \".calculations.energyWh\",\r\n );\r\n\r\n const currentEnergyMaxState = await adapter?.getStateAsync(\r\n productKey + \".\" + deviceKey + \".calculations.energyWhMax\",\r\n );\r\n\r\n const currentValue = currentEnergyState?.val\r\n ? Number(currentEnergyState?.val)\r\n : 0;\r\n\r\n const newValue =\r\n stateKey == \"outputPack\" ? currentValue + value : currentValue - value;\r\n\r\n if (newValue > 0) {\r\n adapter?.setState(\r\n `${productKey}.${deviceKey}.calculations.energyWh`,\r\n newValue,\r\n true,\r\n );\r\n\r\n if (currentEnergyMaxState) {\r\n const soc = Number(\r\n ((newValue / Number(currentEnergyMaxState.val)) * 100).toFixed(1),\r\n );\r\n\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.soc`,\r\n soc > 100.0 ? 100 : soc,\r\n true,\r\n );\r\n\r\n if (newValue > Number(currentEnergyMaxState.val)) {\r\n // Extend maxVal\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.energyWhMax`,\r\n newValue,\r\n true,\r\n );\r\n }\r\n\r\n if (stateKey == \"outputPack\") {\r\n // Charging, calculate remaining charging time\r\n const toCharge = Number(currentEnergyMaxState.val) - newValue;\r\n\r\n const remainHoursAsDecimal = toCharge / value;\r\n const remainFormatted = toHoursAndMinutes(remainHoursAsDecimal * 60);\r\n\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.remainInputTime`,\r\n remainFormatted,\r\n true,\r\n );\r\n } else if (stateKey == \"packInput\") {\r\n // Discharging, calculate remaining discharge time\r\n const remainHoursAsDecimal = newValue / value;\r\n const remainFormatted = toHoursAndMinutes(remainHoursAsDecimal * 60);\r\n\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.remainInputTime`,\r\n remainFormatted,\r\n true,\r\n );\r\n }\r\n } else {\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.energyWhMax`,\r\n newValue,\r\n true,\r\n );\r\n }\r\n }\r\n};\r\n\r\nexport const calculateEnergy = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n): Promise<void> => {\r\n calculationStateKeys.forEach(async (stateKey) => {\r\n const stateNameEnergyWh = `${productKey}.${deviceKey}.calculations.${stateKey}EnergyTodayWh`;\r\n const stateNameEnergykWh = `${productKey}.${deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\r\n const stateNamePower = `${productKey}.${deviceKey}.${stateKey}Power`;\r\n\r\n const currentPowerState = await adapter?.getStateAsync(stateNamePower);\r\n const currentEnergyState = await adapter?.getStateAsync(stateNameEnergyWh);\r\n\r\n if (currentEnergyState?.val == 0) {\r\n // Workaround, set Val to very low value to avoid Jump in data...\r\n await adapter?.setStateAsync(stateNameEnergyWh, 0.000001, true);\r\n } else if (\r\n currentEnergyState &&\r\n currentEnergyState.lc &&\r\n currentPowerState &&\r\n currentPowerState.val != undefined &&\r\n currentPowerState.val != null\r\n ) {\r\n // Timeframe = 30000ms, Job runs every 30 seconds...\r\n const timeFrame = 30000;\r\n\r\n // Calculate Energy value (Wh) from current power in the timeframe from last run...\r\n let addEnergyValue =\r\n (Number(currentPowerState.val) * timeFrame) / 3600000; // Wh\r\n\r\n // Use efficiency factor (used the one from Youtube Channel VoltAmpereLux - thanks!)\r\n const chargingFactor = 0.96; // Efficiency 96%\r\n const dischargingFactor = 1.08 - addEnergyValue / 10000; // Efficiency 92% - 98% (92% + Energy / 10000 = 600W -> +6%)\r\n\r\n // Calculate energy from efficiency factor if value for charging or discharging\r\n addEnergyValue =\r\n stateKey == \"outputPack\" && addEnergyValue > 0\r\n ? addEnergyValue * chargingFactor\r\n : addEnergyValue;\r\n addEnergyValue =\r\n stateKey == \"packInput\" && addEnergyValue > 0\r\n ? addEnergyValue * dischargingFactor\r\n : addEnergyValue;\r\n\r\n let newEnergyValue = Number(currentEnergyState.val) + addEnergyValue;\r\n\r\n // Fix negative value\r\n if (newEnergyValue < 0) {\r\n newEnergyValue = 0;\r\n }\r\n\r\n await adapter?.setStateAsync(stateNameEnergyWh, newEnergyValue, true);\r\n await adapter?.setStateAsync(\r\n stateNameEnergykWh,\r\n Number((newEnergyValue / 1000).toFixed(2)),\r\n true,\r\n );\r\n\r\n // SOC and energy in batteries\r\n if (\r\n (stateKey == \"outputPack\" || stateKey == \"packInput\") &&\r\n addEnergyValue > 0\r\n ) {\r\n await calculateSocAndEnergy(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n stateKey,\r\n addEnergyValue,\r\n );\r\n }\r\n } else {\r\n await adapter?.setStateAsync(stateNameEnergyWh, 0, true);\r\n await adapter?.setStateAsync(stateNameEnergykWh, 0, true);\r\n }\r\n });\r\n};\r\n\r\nexport const resetTodaysValues = async (\r\n adapter: ZendureSolarflow,\r\n): Promise<void> => {\r\n adapter.deviceList.forEach((device: ISolarFlowDeviceDetails) => {\r\n calculationStateKeys.forEach(async (stateKey: string) => {\r\n const stateNameEnergyWh = `${device.productKey}.${device.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\r\n const stateNameEnergykWh = `${device.productKey}.${device.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\r\n\r\n await adapter?.setStateAsync(stateNameEnergyWh, 0, true);\r\n await adapter?.setStateAsync(stateNameEnergykWh, 0, true);\r\n });\r\n });\r\n};\r\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,wBAAkC;AAIlC,MAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,iBAAiB,OAC5B,SACA,YACA,cACkB;AAClB,QAAM,qBAAqB,OAAM,mCAAS;AAAA,IACxC,aAAa,MAAM,YAAY;AAAA;AAGjC,MAAI,oBAAoB;AACtB,WAAM,mCAAS;AAAA,MACb,GAAG,UAAU,IAAI,SAAS;AAAA,MAC1B,yDAAoB;AAAA,MACpB;AAAA;AAAA,EAEJ;AACF;AAEO,MAAM,wBAAwB,OACnC,SACA,YACA,WACA,UACA,UACkB;AAClB,QAAM,qBAAqB,OAAM,mCAAS;AAAA,IACxC,aAAa,MAAM,YAAY;AAAA;AAGjC,QAAM,wBAAwB,OAAM,mCAAS;AAAA,IAC3C,aAAa,MAAM,YAAY;AAAA;AAGjC,QAAM,gBAAe,yDAAoB,OACrC,OAAO,yDAAoB,GAAG,IAC9B;AAEJ,QAAM,WACJ,YAAY,eAAe,eAAe,QAAQ,eAAe;AAEnE,MAAI,WAAW,GAAG;AAChB,uCAAS;AAAA,MACP,GAAG,UAAU,IAAI,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA;AAGF,QAAI,uBAAuB;AACzB,YAAM,MAAM;AAAA,SACR,WAAW,OAAO,sBAAsB,GAAG,IAAK,KAAK,QAAQ,CAAC;AAAA,MAClE;AAEA,aAAM,mCAAS;AAAA,QACb,GAAG,UAAU,IAAI,SAAS;AAAA,QAC1B,MAAM,MAAQ,MAAM;AAAA,QACpB;AAAA;AAGF,UAAI,WAAW,OAAO,sBAAsB,GAAG,GAAG;AAEhD,eAAM,mCAAS;AAAA,UACb,GAAG,UAAU,IAAI,SAAS;AAAA,UAC1B;AAAA,UACA;AAAA;AAAA,MAEJ;AAEA,UAAI,YAAY,cAAc;AAE5B,cAAM,WAAW,OAAO,sBAAsB,GAAG,IAAI;AAErD,cAAM,uBAAuB,WAAW;AACxC,cAAM,sBAAkB,qCAAkB,uBAAuB,EAAE;AAEnE,eAAM,mCAAS;AAAA,UACb,GAAG,UAAU,IAAI,SAAS;AAAA,UAC1B;AAAA,UACA;AAAA;AAAA,MAEJ,WAAW,YAAY,aAAa;AAElC,cAAM,uBAAuB,WAAW;AACxC,cAAM,sBAAkB,qCAAkB,uBAAuB,EAAE;AAEnE,eAAM,mCAAS;AAAA,UACb,GAAG,UAAU,IAAI,SAAS;AAAA,UAC1B;AAAA,UACA;AAAA;AAAA,MAEJ;AAAA,IACF,OAAO;AACL,aAAM,mCAAS;AAAA,QACb,GAAG,UAAU,IAAI,SAAS;AAAA,QAC1B;AAAA,QACA;AAAA;AAAA,IAEJ;AAAA,EACF;AACF;AAEO,MAAM,kBAAkB,OAC7B,SACA,YACA,cACkB;AAClB,uBAAqB,QAAQ,OAAO,aAAa;AAC/C,UAAM,oBAAoB,GAAG,UAAU,IAAI,SAAS,iBAAiB,QAAQ;AAC7E,UAAM,qBAAqB,GAAG,UAAU,IAAI,SAAS,iBAAiB,QAAQ;AAC9E,UAAM,iBAAiB,GAAG,UAAU,IAAI,SAAS,IAAI,QAAQ;AAE7D,UAAM,oBAAoB,OAAM,mCAAS,cAAc;AACvD,UAAM,qBAAqB,OAAM,mCAAS,cAAc;AAExD,SAAI,yDAAoB,QAAO,GAAG;AAEhC,aAAM,mCAAS,cAAc,mBAAmB,MAAU;AAAA,IAC5D,WACE,sBACA,mBAAmB,MACnB,qBACA,kBAAkB,OAAO,UACzB,kBAAkB,OAAO,MACzB;AAEA,YAAM,YAAY;AAGlB,UAAI,iBACD,OAAO,kBAAkB,GAAG,IAAI,YAAa;AAGhD,YAAM,iBAAiB;AACvB,YAAM,oBAAoB,OAAO,iBAAiB;AAGlD,uBACE,YAAY,gBAAgB,iBAAiB,IACzC,iBAAiB,iBACjB;AACN,uBACE,YAAY,eAAe,iBAAiB,IACxC,iBAAiB,oBACjB;AAEN,UAAI,iBAAiB,OAAO,mBAAmB,GAAG,IAAI;AAGtD,UAAI,iBAAiB,GAAG;AACtB,yBAAiB;AAAA,MACnB;AAEA,aAAM,mCAAS,cAAc,mBAAmB,gBAAgB;AAChE,aAAM,mCAAS;AAAA,QACb;AAAA,QACA,QAAQ,iBAAiB,KAAM,QAAQ,CAAC,CAAC;AAAA,QACzC;AAAA;AAIF,WACG,YAAY,gBAAgB,YAAY,gBACzC,iBAAiB,GACjB;AACA,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAM,mCAAS,cAAc,mBAAmB,GAAG;AACnD,aAAM,mCAAS,cAAc,oBAAoB,GAAG;AAAA,IACtD;AAAA,EACF,CAAC;AACH;AAEO,MAAM,oBAAoB,OAC/B,YACkB;AAClB,UAAQ,WAAW,QAAQ,CAAC,WAAoC;AAC9D,yBAAqB,QAAQ,OAAO,aAAqB;AACvD,YAAM,oBAAoB,GAAG,OAAO,UAAU,IAAI,OAAO,SAAS,iBAAiB,QAAQ;AAC3F,YAAM,qBAAqB,GAAG,OAAO,UAAU,IAAI,OAAO,SAAS,iBAAiB,QAAQ;AAE5F,aAAM,mCAAS,cAAc,mBAAmB,GAAG;AACnD,aAAM,mCAAS,cAAc,oBAAoB,GAAG;AAAA,IACtD,CAAC;AAAA,EACH,CAAC;AACH;",
4
+ "sourcesContent": ["/* eslint-disable @typescript-eslint/indent */\r\n\r\nimport { toHoursAndMinutes } from \"../helpers/timeHelper\";\r\nimport { ZendureSolarflow } from \"../main\";\r\nimport { ISolarFlowDeviceDetails } from \"../models/ISolarFlowDeviceDetails\";\r\n\r\nconst calculationStateKeys = [\r\n \"packInput\",\r\n \"outputHome\",\r\n \"outputPack\",\r\n \"solarInput\",\r\n];\r\n\r\nexport const setEnergyWhMax = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n): Promise<void> => {\r\n const currentEnergyState = await adapter?.getStateAsync(\r\n productKey + \".\" + deviceKey + \".calculations.energyWh\",\r\n );\r\n\r\n if (currentEnergyState) {\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.energyWhMax`,\r\n currentEnergyState?.val,\r\n true,\r\n );\r\n }\r\n};\r\n\r\nexport const calculateSocAndEnergy = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n stateKey: string,\r\n value: number,\r\n): Promise<void> => {\r\n const currentEnergyState = await adapter?.getStateAsync(\r\n productKey + \".\" + deviceKey + \".calculations.energyWh\",\r\n );\r\n\r\n const currentEnergyMaxState = await adapter?.getStateAsync(\r\n productKey + \".\" + deviceKey + \".calculations.energyWhMax\",\r\n );\r\n\r\n const currentValue = currentEnergyState?.val\r\n ? Number(currentEnergyState?.val)\r\n : 0;\r\n\r\n const newValue =\r\n stateKey == \"outputPack\" ? currentValue + value : currentValue - value;\r\n\r\n if (newValue > 0) {\r\n adapter?.setState(\r\n `${productKey}.${deviceKey}.calculations.energyWh`,\r\n newValue,\r\n true,\r\n );\r\n\r\n if (currentEnergyMaxState) {\r\n const soc = Number(\r\n ((newValue / Number(currentEnergyMaxState.val)) * 100).toFixed(1),\r\n );\r\n\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.soc`,\r\n soc > 100.0 ? 100 : soc,\r\n true,\r\n );\r\n\r\n if (newValue > Number(currentEnergyMaxState.val)) {\r\n // Extend maxVal\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.energyWhMax`,\r\n newValue,\r\n true,\r\n );\r\n }\r\n\r\n const currentOutputPackPower = await adapter?.getStateAsync(\r\n `${productKey}.${deviceKey}.outputPackPower`,\r\n );\r\n\r\n const currentPackInputPower = await adapter?.getStateAsync(\r\n productKey + \".\" + deviceKey + \".packInputPower\",\r\n );\r\n\r\n if (stateKey == \"outputPack\" && currentOutputPackPower?.val != null && currentOutputPackPower != undefined) {\r\n // Charging, calculate remaining charging time\r\n const toCharge = Number(currentEnergyMaxState.val) - newValue;\r\n\r\n const remainHoursAsDecimal = toCharge / Number(currentOutputPackPower.val);\r\n\r\n if (remainHoursAsDecimal < 10.0) {\r\n const remainFormatted = toHoursAndMinutes(Math.round(remainHoursAsDecimal * 60));\r\n\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.remainInputTime`,\r\n remainFormatted,\r\n true,\r\n );\r\n }\r\n else {\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.remainInputTime`,\r\n \"-\",\r\n true,\r\n );\r\n }\r\n } else if (stateKey == \"packInput\" && currentPackInputPower != null && currentPackInputPower != undefined) {\r\n // Discharging, calculate remaining discharge time\r\n const remainHoursAsDecimal = newValue / Number(currentPackInputPower.val);\r\n const remainFormatted = toHoursAndMinutes(Math.round(remainHoursAsDecimal * 60));\r\n\r\n if (remainHoursAsDecimal < 40.0) {\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.remainOutTime`,\r\n remainFormatted,\r\n true,\r\n );\r\n }\r\n else {\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.remainOutTime`,\r\n \"-\",\r\n true,\r\n );\r\n }\r\n }\r\n } else {\r\n await adapter?.setStateAsync(\r\n `${productKey}.${deviceKey}.calculations.energyWhMax`,\r\n newValue,\r\n true,\r\n );\r\n }\r\n }\r\n};\r\n\r\nexport const calculateEnergy = async (\r\n adapter: ZendureSolarflow,\r\n productKey: string,\r\n deviceKey: string,\r\n): Promise<void> => {\r\n calculationStateKeys.forEach(async (stateKey) => {\r\n const stateNameEnergyWh = `${productKey}.${deviceKey}.calculations.${stateKey}EnergyTodayWh`;\r\n const stateNameEnergykWh = `${productKey}.${deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\r\n const stateNamePower = `${productKey}.${deviceKey}.${stateKey}Power`;\r\n\r\n const currentPowerState = await adapter?.getStateAsync(stateNamePower);\r\n const currentEnergyState = await adapter?.getStateAsync(stateNameEnergyWh);\r\n\r\n if (currentEnergyState?.val == 0) {\r\n // Workaround, set Val to very low value to avoid Jump in data...\r\n await adapter?.setStateAsync(stateNameEnergyWh, 0.000001, true);\r\n } else if (\r\n currentEnergyState &&\r\n currentEnergyState.lc &&\r\n currentPowerState &&\r\n currentPowerState.val != undefined &&\r\n currentPowerState.val != null\r\n ) {\r\n // Timeframe = 30000ms, Job runs every 30 seconds...\r\n const timeFrame = 30000;\r\n\r\n // Calculate Energy value (Wh) from current power in the timeframe from last run...\r\n let addEnergyValue =\r\n (Number(currentPowerState.val) * timeFrame) / 3600000; // Wh\r\n\r\n // Use efficiency factor (used the one from Youtube Channel VoltAmpereLux - thanks!)\r\n const chargingFactor = 0.96; // Efficiency 96%\r\n const dischargingFactor = 1.08 - addEnergyValue / 10000; // Efficiency 92% - 98% (92% + Energy / 10000 = 600W -> +6%)\r\n\r\n // Calculate energy from efficiency factor if value for charging or discharging\r\n addEnergyValue =\r\n stateKey == \"outputPack\" && addEnergyValue > 0\r\n ? addEnergyValue * chargingFactor\r\n : addEnergyValue;\r\n addEnergyValue =\r\n stateKey == \"packInput\" && addEnergyValue > 0\r\n ? addEnergyValue * dischargingFactor\r\n : addEnergyValue;\r\n\r\n let newEnergyValue = Number(currentEnergyState.val) + addEnergyValue;\r\n\r\n // Fix negative value\r\n if (newEnergyValue < 0) {\r\n newEnergyValue = 0;\r\n }\r\n\r\n await adapter?.setStateAsync(stateNameEnergyWh, newEnergyValue, true);\r\n await adapter?.setStateAsync(\r\n stateNameEnergykWh,\r\n Number((newEnergyValue / 1000).toFixed(2)),\r\n true,\r\n );\r\n\r\n // SOC and energy in batteries\r\n if (\r\n (stateKey == \"outputPack\" || stateKey == \"packInput\") &&\r\n addEnergyValue > 0\r\n ) {\r\n await calculateSocAndEnergy(\r\n adapter,\r\n productKey,\r\n deviceKey,\r\n stateKey,\r\n addEnergyValue,\r\n );\r\n }\r\n } else {\r\n await adapter?.setStateAsync(stateNameEnergyWh, 0, true);\r\n await adapter?.setStateAsync(stateNameEnergykWh, 0, true);\r\n }\r\n });\r\n};\r\n\r\nexport const resetTodaysValues = async (\r\n adapter: ZendureSolarflow,\r\n): Promise<void> => {\r\n adapter.deviceList.forEach((device: ISolarFlowDeviceDetails) => {\r\n calculationStateKeys.forEach(async (stateKey: string) => {\r\n const stateNameEnergyWh = `${device.productKey}.${device.deviceKey}.calculations.${stateKey}EnergyTodayWh`;\r\n const stateNameEnergykWh = `${device.productKey}.${device.deviceKey}.calculations.${stateKey}EnergyTodaykWh`;\r\n\r\n await adapter?.setStateAsync(stateNameEnergyWh, 0, true);\r\n await adapter?.setStateAsync(stateNameEnergykWh, 0, true);\r\n });\r\n });\r\n};\r\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,wBAAkC;AAIlC,MAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,iBAAiB,OAC5B,SACA,YACA,cACkB;AAClB,QAAM,qBAAqB,OAAM,mCAAS;AAAA,IACxC,aAAa,MAAM,YAAY;AAAA;AAGjC,MAAI,oBAAoB;AACtB,WAAM,mCAAS;AAAA,MACb,GAAG,UAAU,IAAI,SAAS;AAAA,MAC1B,yDAAoB;AAAA,MACpB;AAAA;AAAA,EAEJ;AACF;AAEO,MAAM,wBAAwB,OACnC,SACA,YACA,WACA,UACA,UACkB;AAClB,QAAM,qBAAqB,OAAM,mCAAS;AAAA,IACxC,aAAa,MAAM,YAAY;AAAA;AAGjC,QAAM,wBAAwB,OAAM,mCAAS;AAAA,IAC3C,aAAa,MAAM,YAAY;AAAA;AAGjC,QAAM,gBAAe,yDAAoB,OACrC,OAAO,yDAAoB,GAAG,IAC9B;AAEJ,QAAM,WACJ,YAAY,eAAe,eAAe,QAAQ,eAAe;AAEnE,MAAI,WAAW,GAAG;AAChB,uCAAS;AAAA,MACP,GAAG,UAAU,IAAI,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA;AAGF,QAAI,uBAAuB;AACzB,YAAM,MAAM;AAAA,SACR,WAAW,OAAO,sBAAsB,GAAG,IAAK,KAAK,QAAQ,CAAC;AAAA,MAClE;AAEA,aAAM,mCAAS;AAAA,QACb,GAAG,UAAU,IAAI,SAAS;AAAA,QAC1B,MAAM,MAAQ,MAAM;AAAA,QACpB;AAAA;AAGF,UAAI,WAAW,OAAO,sBAAsB,GAAG,GAAG;AAEhD,eAAM,mCAAS;AAAA,UACb,GAAG,UAAU,IAAI,SAAS;AAAA,UAC1B;AAAA,UACA;AAAA;AAAA,MAEJ;AAEA,YAAM,yBAAyB,OAAM,mCAAS;AAAA,QAC5C,GAAG,UAAU,IAAI,SAAS;AAAA;AAG5B,YAAM,wBAAwB,OAAM,mCAAS;AAAA,QAC3C,aAAa,MAAM,YAAY;AAAA;AAGjC,UAAI,YAAY,iBAAgB,iEAAwB,QAAO,QAAQ,0BAA0B,QAAW;AAE1G,cAAM,WAAW,OAAO,sBAAsB,GAAG,IAAI;AAErD,cAAM,uBAAuB,WAAW,OAAO,uBAAuB,GAAG;AAEzE,YAAI,uBAAuB,IAAM;AAC/B,gBAAM,sBAAkB,qCAAkB,KAAK,MAAM,uBAAuB,EAAE,CAAC;AAE/E,iBAAM,mCAAS;AAAA,YACb,GAAG,UAAU,IAAI,SAAS;AAAA,YAC1B;AAAA,YACA;AAAA;AAAA,QAEJ,OACK;AACH,iBAAM,mCAAS;AAAA,YACb,GAAG,UAAU,IAAI,SAAS;AAAA,YAC1B;AAAA,YACA;AAAA;AAAA,QAEJ;AAAA,MACF,WAAW,YAAY,eAAe,yBAAyB,QAAQ,yBAAyB,QAAW;AAEzG,cAAM,uBAAuB,WAAW,OAAO,sBAAsB,GAAG;AACxE,cAAM,sBAAkB,qCAAkB,KAAK,MAAM,uBAAuB,EAAE,CAAC;AAE/E,YAAI,uBAAuB,IAAM;AAC/B,iBAAM,mCAAS;AAAA,YACb,GAAG,UAAU,IAAI,SAAS;AAAA,YAC1B;AAAA,YACA;AAAA;AAAA,QAEJ,OACK;AACH,iBAAM,mCAAS;AAAA,YACb,GAAG,UAAU,IAAI,SAAS;AAAA,YAC1B;AAAA,YACA;AAAA;AAAA,QAEJ;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAM,mCAAS;AAAA,QACb,GAAG,UAAU,IAAI,SAAS;AAAA,QAC1B;AAAA,QACA;AAAA;AAAA,IAEJ;AAAA,EACF;AACF;AAEO,MAAM,kBAAkB,OAC7B,SACA,YACA,cACkB;AAClB,uBAAqB,QAAQ,OAAO,aAAa;AAC/C,UAAM,oBAAoB,GAAG,UAAU,IAAI,SAAS,iBAAiB,QAAQ;AAC7E,UAAM,qBAAqB,GAAG,UAAU,IAAI,SAAS,iBAAiB,QAAQ;AAC9E,UAAM,iBAAiB,GAAG,UAAU,IAAI,SAAS,IAAI,QAAQ;AAE7D,UAAM,oBAAoB,OAAM,mCAAS,cAAc;AACvD,UAAM,qBAAqB,OAAM,mCAAS,cAAc;AAExD,SAAI,yDAAoB,QAAO,GAAG;AAEhC,aAAM,mCAAS,cAAc,mBAAmB,MAAU;AAAA,IAC5D,WACE,sBACA,mBAAmB,MACnB,qBACA,kBAAkB,OAAO,UACzB,kBAAkB,OAAO,MACzB;AAEA,YAAM,YAAY;AAGlB,UAAI,iBACD,OAAO,kBAAkB,GAAG,IAAI,YAAa;AAGhD,YAAM,iBAAiB;AACvB,YAAM,oBAAoB,OAAO,iBAAiB;AAGlD,uBACE,YAAY,gBAAgB,iBAAiB,IACzC,iBAAiB,iBACjB;AACN,uBACE,YAAY,eAAe,iBAAiB,IACxC,iBAAiB,oBACjB;AAEN,UAAI,iBAAiB,OAAO,mBAAmB,GAAG,IAAI;AAGtD,UAAI,iBAAiB,GAAG;AACtB,yBAAiB;AAAA,MACnB;AAEA,aAAM,mCAAS,cAAc,mBAAmB,gBAAgB;AAChE,aAAM,mCAAS;AAAA,QACb;AAAA,QACA,QAAQ,iBAAiB,KAAM,QAAQ,CAAC,CAAC;AAAA,QACzC;AAAA;AAIF,WACG,YAAY,gBAAgB,YAAY,gBACzC,iBAAiB,GACjB;AACA,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAM,mCAAS,cAAc,mBAAmB,GAAG;AACnD,aAAM,mCAAS,cAAc,oBAAoB,GAAG;AAAA,IACtD;AAAA,EACF,CAAC;AACH;AAEO,MAAM,oBAAoB,OAC/B,YACkB;AAClB,UAAQ,WAAW,QAAQ,CAAC,WAAoC;AAC9D,yBAAqB,QAAQ,OAAO,aAAqB;AACvD,YAAM,oBAAoB,GAAG,OAAO,UAAU,IAAI,OAAO,SAAS,iBAAiB,QAAQ;AAC3F,YAAM,qBAAqB,GAAG,OAAO,UAAU,IAAI,OAAO,SAAS,iBAAiB,QAAQ;AAE5F,aAAM,mCAAS,cAAc,mBAAmB,GAAG;AACnD,aAAM,mCAAS,cAAc,oBAAoB,GAAG;AAAA,IACtD,CAAC;AAAA,EACH,CAAC;AACH;",
6
6
  "names": []
7
7
  }
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zendure-solarflow",
4
- "version": "1.2.7",
4
+ "version": "1.3.0",
5
5
  "news": {
6
+ "1.3.0": {
7
+ "en": "Fix calculation for outputPackEnergy and packInputEnergy\nTrigger full telemetry update on adapter start\nAdd state and control for buzzer switch\nAdd state and control for bypass mode and automatic reset of bypass mode next day\nAdd states for pass (Bypass on/off), autoRecover (auto-mode for Bypass next day) and passMode (current bypass mode)\nAdd efficiency factor for calculations (96% charging, 92%-98%\\* for discharging - based on measuring from VoltAmpereLux Youtube channel - THANKS!)\nChanged calculations timeframe from 10secs to 30secs (performance related)",
8
+ "de": "Fixberechnung für die Ausgabe PackEnergy und PackInputEnergy\nTrigger Full Telemetrie Update auf Adapterstart\nZustand und Steuerung für Summer Switch hinzufügen\nZustand und Steuerung für Bypass-Modus und automatische Rückstellung des Bypass-Modus am nächsten Tag hinzufügen\nFügen Sie Zustände für Pass (Bypass on/off), autoRecover (Auto-Modus für Bypass nächsten Tag) und passMode (current bypass mode) hinzu\nEffizienzfaktor für Berechnungen hinzufügen (96% Aufladung, 92%-98%\\* zur Entladung - basierend auf der Messung von VoltAmpere Lux Youtube Kanal - THANKS!)\nGeänderte Berechnungsdauer von 10 Sekunden auf 30 Sekunden (performance related)",
9
+ "ru": "Исчисление на основе исходных данных PackEnergy и packInputEnergy\nТреггер полного обновления телеметрии на запуске адаптера\nДобавить состояние и управление для выключателя\nДобавить состояние и управление для шунт-режима и автоматическая перезагрузка режима шунтирования на следующий день\nДобавить состояния для прохода (Bypass on/off), autoRecover (автомод для Bypass на следующий день) и passMode (текущий режим обхода)\nДобавить коэффициент эффективности для расчетов (96% зарядки, 92%-98%\\* для разрядки - на основе измерения от VoltAmpere Lux Youtube канал - THANKS!)\nИзменение сроков расчетов с 10секс до 30секс (связанные с производительностью)",
10
+ "pt": "Cálculo fixo para saída PackEnergy e packInputEnergy\nAtivar atualização de telemetria completa no início do adaptador\nAdicionar estado e controle para interruptor de buzzer\nAdicionar estado e controle para o modo bypass e reset automático do modo bypass no dia seguinte\nAdicionar estados para passe (Bypass on/off), autoRecover (automodo para Bypass no dia seguinte) e passMode (modo de bypass atual)\nAdicionar fator de eficiência para cálculos (carga de 96%, 92%-98%\\* para descarregamento - baseado na medição de VoltAmpere Canal Lux Youtube - THANKS!)\nPrazo de cálculos alterados de 10secs para 30secs (relacionado com o desempenho)",
11
+ "nl": "Fix berekening voor output PackEnergy en PackInputEnergy\nVolledige telemetrie-update van de adapter starten\nStatus en controle voor zoemerschakelaar toevoegen\nToevoegen status en controle voor bypass modus en automatische reset van bypass modus volgende dag\nToevoegen statussen voor pass (Bypass aan/uit), autoRecover (auto-modus voor Bypass volgende dag) en passMode (huidige bypass modus)\nToevoegen efficiëntiefactor voor berekeningen (96% opladen, 92%-98%\\* voor het lossen - op basis van metingen van VoltAmpere Lux Youtube kanaal - bedankt!)\nVeranderde berekeningsperiode van 10secs naar 30secs (prestatiegerelateerd)",
12
+ "fr": "Correction du calcul de la sortie PackÉnergie et packInputÉnergie\nMise à jour complète de la télémétrie sur le démarrage de l'adaptateur\nAjouter l'état et le contrôle pour interrupteur de buzzer\nAjouter l'état et la commande pour le mode de contournement et la remise automatique du mode de contournement le lendemain\nAjouter les états de passage (Bypass on/off), autoRecover (auto-mode pour Bypass le lendemain) et passMode (mode de contournement courant)\nAjouter le facteur d'efficacité pour les calculs (96% de charge, 92%-98%\\* de décharge - basé sur la mesure de VoltAmpere Chaîne Lux Youtube - MERCI!)\nTemps de calcul modifié de 10secs à 30secs (lié à la performance)",
13
+ "it": "Fissare il calcolo per l'output PackEnergy e packInputEnergia\nAggiornamento completo della telemetria del trigger all'avvio dell'adattatore\nAggiungi stato e controllo per interruttore buzzer\nAggiungi stato e controllo per la modalità bypass e reset automatico della modalità bypass il giorno successivo\nAggiungi stati per pass (Bypass on/off), autoRecover (mode automatico per Bypass il giorno successivo) e passMode (modalità bypass corrente)\nAggiungi fattore di efficienza per i calcoli (96% di carica, 92%-98%\\* per lo scarico - basato sulla misurazione da VoltAmpere Canale Lux Youtube - GRAZIE!)\nTempo di calcolo modificato da 10sec a 30secs (correlazione delle prestazioni)",
14
+ "es": "Cálculo fijo para la salida PackEnergía y paqueteInputEnergía\nTrigger actualización completa de telemetría en el comienzo del adaptador\nAñadir estado y control para interruptor de zumbido\nAgregar estado y control para modo bypass y reinicio automático del modo bypass al día siguiente\nAñadir estados para pasar (Bypass on/off), autoRecover (auto-mode for Bypass next day) y passMode (modo de bypass corriente)\nAñadir factor de eficiencia para cálculos (96% de carga, 92%-98%\\* para descarga - basado en la medición de VoltAmpere Canal de Lux Youtube - Gracias!)\nCambio de cálculos timeframe de 10 segundos a 30 segundos (con relación al desempeño)",
15
+ "pl": "Napraw obliczenie dla wyjścia PackEnergy and packInputEnergy\nPełna aktualizacja telemetrii podczas uruchamiania adaptera\nDodaj stan i sterowanie przełącznika brzęczyka\nDodaj stan i sterowanie dla trybu bajpasu i automatycznego resetowania trybu bajpasu następnego dnia\nDodaj stany dla pass (Bypass włączone / wyłączone), autoRecover (tryb auto- dla Bypass następnego dnia) i passMode (obecny tryb bypass)\nDodać współczynnik wydajności do obliczeń (96% doładowania, 92% -98%\\ * do rozładowania - w oparciu o pomiar z VoltaAmpere Lux YouTube kanał - Dzięki!)\nZmienione ramy czasowe obliczeń od 10 do 30 sekund (związane z wydajnością)",
16
+ "uk": "Фіксований розрахунок на виході ПакетЕнергія та пакетІнпутаціяЕнергія\nТригер повного оновлення телеметрії на старті адаптера\nДодати стан та контроль за комутатором\nДодати стан та контроль за режимом обходу та автоматичним скиданням режиму обходу наступного дня\nДодати стани для проходу (Вхід на / вихід), autoRecover (auto-mode for Bypass наступного дня) і passMode (поточний режим обходу)\nДодавання коефіцієнта ефективності розрахунку (96% зарядки, 92%-98%\\* для розвантаження - на основі вимірювання від VoltAmpere Lux Youtube канал - ДЯКУ!)\nЗмінено графіки розрахунку від 10secs до 30secs",
17
+ "zh-cn": "修正输出计算 包能源与包投入能源\n适配器启动时触发全遥测更新\n为铃声开关添加状态和控制\n第二天添加绕行模式和绕行模式自动重置的状态和控制\n添加通过状态( Bypass on/off), 自动恢复( Auto-mode for Bypass 第二天) 和通过模式( 当前绕行模式)\n增加计算效率系数(充电96%,放电92%-98%)——根据VoltAmpere的测量结果 Lux Youtube频道 - 谢谢\n计算时限从10秒改为30秒(业绩相关)"
18
+ },
6
19
  "1.2.7": {
7
20
  "en": "Fix calculation for outputPackEnergy and packInputEnergy\nTrigger full telemetry update on adapter start\nAdd state and control for buzzer switch\nAdd state and control for bypass mode and automatic reset of bypass mode next day",
8
21
  "de": "Fixberechnung für die Ausgabe PackEnergy und PackInputEnergy\nTrigger Full Telemetrie Update auf Adapterstart\nZustand und Steuerung für Summer Switch hinzufügen\nZustand und Steuerung für Bypass-Modus und automatische Rückstellung des Bypass-Modus am nächsten Tag hinzufügen",
@@ -80,19 +93,6 @@
80
93
  "pl": "Naprawiono problem, że nie można było znaleźć przemianowanych urządzeń.\nDodaj stany nazwy, nazwy produktu, seryjnego identyfikatora i skonfigurowanego serwera.\nDodać \"energyWhMax\" Stan zapisywalny, dzięki czemu można dostosować wartość max.\nWysłał ostrzeżenie, jeśli urządzenie jest skonfigurowane dla serwera, który nie jest używany.",
81
94
  "uk": "Виправлення проблеми, які не можуть бути знайдені пристрої.\nДодайте штати для імені, назви товару, послідовний ідентифікатор і налаштований сервер.\nЗробіть \"енергетикаWhMax\" Держава, тому ви можете регулювати максимальну вартість.\nУвімкніть попередження, якщо пристрій налаштовано на сервер не у використанні.",
82
95
  "zh-cn": "无法找到重命名的设备 .\n添加名称、产品名称、序列ID和配置服务器的状态 .\n让“ energyWhMax” 状态可写入, 这样您就可以调整最大值 .\n如果为服务器配置了设备, 则发送警告 ."
83
- },
84
- "1.2.1": {
85
- "en": "Fix calculation of soc: Set energyMaxWh to current energyWh if Zendures SOC is 100%\nRound SOC to max 1 digit after comma.",
86
- "de": "Berechnung von soc: Energie einstellenMaxWh zur aktuellen Energie Wh, wenn Zendures SOC 100%\nRunder SOC bis max 1 Ziffer nach Komma.",
87
- "ru": "Исправление расчета сока: Установка энергииMaxWh к текущей энергии В, если Зендурес SOC составляет 100%\nКруглый SOC до макс. 1 цифры после запятой.",
88
- "pt": "Cálculo fixo do soc: Definir energia MaxWh para energia atual Wh se Zendures SOC é 100%\nSOC redondo para max 1 dígito após vírgula.",
89
- "nl": "Fix calculation of soc: Energie instellenMaxWh op huidige energie Als Zendures SOC 100% is\nRonde SOC tot maximaal 1 cijfer na komma.",
90
- "fr": "Fixez le calcul du soc: Définir l'énergieMaxWh à l'énergie actuelle Whh si Zendures SOC est 100%\nRond SOC à 1 chiffre maximum après virgule.",
91
- "it": "Fissare il calcolo del soc: Impostare energia MaxWh a energia corrente Se Zendures SOC è 100%\nSOC tondo a max 1 cifra dopo virgola.",
92
- "es": "Fijar el cálculo del soc: Establecer energíaMaxWh a la energía actual Wh si Zendures SOC es 100%\nSOC redondo a máx 1 dígito después del coma.",
93
- "pl": "Fix obliczenia soc: Ustaw energyMaxWh na energię bieżącą Wh jeśli Zendures SOC wynosi 100%\nOkrągłe SOC do maksymalnie 1 cyfry po przecinku.",
94
- "uk": "Фіксований розрахунок СО: Настроювання енергіїMaxWh до поточної енергії Wh, якщо Zendures SOC 100%\nКруглий SOC до макс. 1 цифра після коми.",
95
- "zh-cn": "索克的固定计算 : 将能量MaxWh设定为当前能量 如果Zendures SOC是100%的话\n在逗号后将 SOC 转至最大 1 位数 ."
96
96
  }
97
97
  },
98
98
  "title": "Zendure Solarflow",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zendure-solarflow",
3
- "version": "1.2.7",
3
+ "version": "1.3.0",
4
4
  "description": "zendure-solarflow",
5
5
  "author": {
6
6
  "name": "Peter",