iobroker.sun2000 2.3.7 → 2.4.2

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
@@ -17,7 +17,6 @@
17
17
 
18
18
  **This adapter uses Sentry libraries to automatically report exceptions and code errors to the developers.**\
19
19
  For more details and for information how to disable the error reporting see [Sentry-Plugin Documentation](https://github.com/ioBroker/plugin-sentry#plugin-sentry)!\
20
- Sentry reporting is used starting with js-controller 3.0.
21
20
 
22
21
  ## sun2000 adapter for ioBroker
23
22
 
@@ -30,7 +29,7 @@ Feel free to follow the discussions in the german [iobroker forum](https://forum
30
29
  ## Requirements
31
30
  * Node.js 20 or higher
32
31
  * ioBroker host (js-controller) 6.0.11 or higher
33
- * ioBroker admin 7.6.17 or higher
32
+ * ioBroker admin 7.6.20 or higher
34
33
 
35
34
  ## Documentation
36
35
 
@@ -59,12 +58,32 @@ browse in the [wiki](https://github.com/bolliy/ioBroker.sun2000/wiki)
59
58
  * Huawei [`SmartLogger`](https://github.com/bolliy/ioBroker.sun2000/wiki/SmartLogger) integration: Monitors and manages the PV power system. The adapter saves the collected data in the same way as it does when read out the inverter directly.
60
59
  * Huawei [`Emma`](https://github.com/bolliy/ioBroker.sun2000/wiki/Emma) integration: The Modbus access, network connectivity (WiFi and Ethernet) and the DDSU/DTSU-666H smart meter functions are integrated in one unit - the use of the Sdongle becomes redundant. In addition Huawei EV chargers and load shedding/control (via selected Shelly devices) are supported and "intelligent" controlled.
61
60
  * Huawei [`Charger`](https://github.com/bolliy/ioBroker.sun2000/issues/171) via Emma integration: The chargers are automatically recognized and the data is saved in their own path.
61
+ * [`Statistics`](https://github.com/bolliy/ioBroker.sun2000/wiki/Statistk-(statistics)): Aggregates historical collected datapoints into time-based summaries (e.g. hourly, daily, monthly, yearly).
62
+ These statistics should be able to be visualized in ioBroker VIS using the flexcharts adapter to create interactive diagrams for inverter performance and energy production.
63
+ * [`Surplus Power Control`](https://github.com/bolliy/ioBroker.sun2000/wiki/%C3%9Cberschuss-(surplus))
64
+ The sun2000 adapter calculates how much of your self-generated solar energy is available to power devices in your home — instead of sending it to the grid.
65
+
62
66
 
63
67
  ## Changelog
64
68
  <!--
65
69
  Placeholder for the next version (at the beginning of the line):
66
70
  ### **WORK IN PROGRESS**
67
71
  -->
72
+ ### 2.4.2 (2026-04-04)
73
+ * fix test-and-release: deploy with 24.x
74
+
75
+ ### 2.4.1 (2026-04-04)
76
+ * statistics: flexcharts integration — built-in Apache ECharts configuration with bar and line chart support
77
+ * statistics: day-break visualization with alternating shaded areas for hourly charts
78
+ * statistics: per chart-type templates (`statistics.flexCharts.template.hourly` etc.) for full ECharts customization including functions
79
+ * statistics: data placeholders (`%%solarYield%%`, `%%gridExport%%` etc.) allow complete chart layout control via template states
80
+ * statistics: chart output states (`statistics.flexCharts.jsonOutput.hourly` etc.) updated automatically each hour
81
+
82
+ ### 2.4.0 (2026-03-14)
83
+ * fix: the order of bit assignment corrected of alarmsJSON
84
+ * new state `inverter.x.emma.activeAlarmSN` and `inverter.x.emma.HistoricalAlarmSN` : emma alarms [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)
85
+ * statistics: Aggregates historical collected datapoints into time-based summaries (e.g. hourly, daily, monthly, yearly). The data is stored in the path `statistics` as JSON.
86
+
68
87
  ### 2.3.7 (2026-02-01)
69
88
  * deleted deprecated state `collected.usableSurplusPower`
70
89
 
package/io-package.json CHANGED
@@ -1,8 +1,47 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "sun2000",
4
- "version": "2.3.7",
4
+ "version": "2.4.2",
5
5
  "news": {
6
+ "2.4.2": {
7
+ "en": "fix test-and-release: deploy with 24.x",
8
+ "de": "fix test-and-release: einsatz mit 24.x",
9
+ "ru": "исправление тест-и-релиз: развертывание с 24.x",
10
+ "pt": "corrigir teste e liberação: implantar com 24.x",
11
+ "nl": "fix test-and-release: inzet met 24.x",
12
+ "fr": "correction test-and-release: déployer avec 24.x",
13
+ "it": "fix test-and-release: implementare con 24.x",
14
+ "es": "fijar prueba y liberación: desplegar con 24.x",
15
+ "pl": "fix test- and- release: rozmieszczanie z 24.x",
16
+ "uk": "виправити тест-і-випуск: розгортання з 24.x",
17
+ "zh-cn": "固定测试和释放:部署24x"
18
+ },
19
+ "2.4.1": {
20
+ "en": "statistics: flexcharts integration — built-in Apache ECharts configuration with bar and line chart support\nstatistics: day-break visualization with alternating shaded areas for hourly charts\nstatistics: per chart-type templates (`statistics.flexCharts.template.hourly` etc.) for full ECharts customization including functions\nstatistics: data placeholders (`%%solarYield%%`, `%%gridExport%%` etc.) allow complete chart layout control via template states\nstatistics: chart output states (`statistics.flexCharts.jsonOutput.hourly` etc.) updated automatically each hour",
21
+ "de": "statistik: flexcharts integration — integrierte Apache ECharts-Konfiguration mit Bar- und Liniendiagrammunterstützung\nstatistik: tages-früh-visualisierung mit alternierenden schattierten bereichen für stundendiagramme\nstatistiken: pro Diagrammvorlagen (`statistics.flexCharts.template.hourly` etc.) für die vollständige ECharts Anpassung einschließlich Funktionen\nstatistik: Datenplatzhalter (`%%solar%%%%`, `%%gridExport%% ` etc.) ermöglichen vollständige Chart-Layout-Kontrolle über Template-Staaten\nstatistiken: Diagrammausgabezustände (`statistics.flexCharts.jsonOutput.hourly` etc.) automatisch jede Stunde aktualisiert",
22
+ "ru": "статистика: интеграция flexcharts — встроенная конфигурация Apache ECharts с поддержкой штрих- и линейных графиков\nстатистика: визуализация на рассвете с чередующимися затененными областями для часовых графиков\nстатистика: на шаблоны типа диаграммы («statistics.flexCharts.template.hourly» и т. д.) для полной настройки EChart, включая функции\nстатистика: держатели данных («%%solarYield%%», «%%gridExport%%» и т.д.) позволяют полностью контролировать макет диаграммы через шаблонные состояния\nстатистика: состояния выхода диаграммы (statistics.flexCharts.jsonOutput.hourly и т. д.) обновляются автоматически каждый час",
23
+ "pt": "estatísticas: integração de flexcharts — configuração integrada do Apache ECharts com suporte a barras e gráficos de linha\nestatísticas: visualização diurna com áreas de sombra alternadas para gráficos horários\nestatísticas: por modelos de tipo gráfico (`statistics.flexCharts.template.hourly` etc.) para personalização completa de ECharts, incluindo funções\nestatísticas: placeholders de dados (` %s olarYield%% `, `% gridExport%% ` etc.) permitem o controle completo do layout do gráfico através de estados de modelo\nestatísticas: estados de saída do gráfico (`statistics.flexCharts.jsonOutput.hourly` etc.) atualizados automaticamente a cada hora",
24
+ "nl": "statistics: flexcharts integration Ingebouwde Apache ECharts configuratie met ondersteuning voor bar en lijndiagram\nstatistieken: dagvakvisualisatie met afwisselende schaduwgebieden voor uurkaarten\nstatistieken: per grafiek-type sjablonen (\nstatistieken: data placeholders (\nstatistieken: grafiek output states (",
25
+ "fr": "statistiques: intégration des flexcharts — configuration Apache ECharts intégrée avec support de la barre et de la ligne\nstatistiques: visualisation de la pause-jour avec zones ombrées alternées pour les graphiques horaires\nstatistiques: par modèle type de graphique (`statistics.flexCharts.template.hourly` etc.) pour la personnalisation complète d'ECharts, y compris les fonctions\nstatistiques : les détenteurs de place de données (`%%solarYield%%`, `%gridExport%%%` etc.) permettent un contrôle complet de la disposition des graphiques via les états de gabarit\nstatistiques: états de sortie du graphique (`statistics.flexCharts.jsonOutput.hourly` etc.) mis à jour automatiquement chaque heure",
26
+ "it": "statistiche: integrazione di flexcharts — configurazione integrata di Apache ECharts con supporto grafico a barre e linea\nstatistiche: visualizzazione day-break con aree ombreggiate alternate per grafici orari\nstatistiche: per modelli di tipo grafico (`statistics.flexCharts.template.hourly` ecc.) per la personalizzazione completa di ECharts comprese le funzioni\nstatistiche: i segnaposto dei dati (%solarYield%%, `%gridExport%%` ecc.) permettono il controllo completo del layout del grafico tramite gli stati del modello\nstatistiche: stati di output grafico (`statistics.flexCharts.jsonOutput.hourly` ecc.) aggiornati automaticamente ogni ora",
27
+ "es": "estadística: integración de flexcharts — configuración integrada de Apache ECharts con soporte de barras y gráficos\nestadística: visualización del día con áreas alternadas sombreadas para gráficos por hora\nestadística: por plantillas tipo gráfico (`statistics.flexCharts.template.hourly` etc.) para la personalización completa de ECharts incluyendo funciones\nestadística: marcadores de datos ( \"%solarYield%%% \" , \"%gridExport%%% \" , etc.) permiten un control completo de la distribución de gráficos a través de estados de plantilla\nestadística: estados de salida del gráfico (`statistics.flexCharts.jsonOutput.hourly` etc.) actualizados automáticamente cada hora",
28
+ "pl": "statystyki: integracja flexcharts - built- w konfiguracji Apache ECharts z obsługą wykresu paska i linii\nstatystyki: wizualizacja z naprzemiennymi zacienionymi obszarami dla wykresów godzinowych\nstatystyki: na szablony typu chart- ('statistics.flexCharts.template.hourly' itp.) dla pełnej personalizacji ECharts, w tym funkcji\nstatystyki: Posiadacze danych ('% %s olarYeld%%', '%% gridExport%%' itd.) pozwalają na pełną kontrolę układu wykresu za pomocą szablonów stanów\nstatystyki: stany wyjściowe wykresu ('statistics.flexCharts.jsonOutput.hourly' itp.) aktualizowane automatycznie co godzinę",
29
+ "uk": "статистика: інтеграція флекса — вбудована конфігурація Apache ECharts з підтримкою діаграми бару та лінії\nстатистика: візуалізація денного розриву з чергуванням затінених зон на часових графіках\nстатистика: за шаблони діаграм типу (`statistics.flexCharts.template.hrly` і т.д.) для повної настройки ECharts, включаючи функції\nстатистика: Держателі (`%solarYield%%`, `%gridExport%%` і т.д.) дозволяють повністю контролювати макети за допомогою шаблонних станів\nстатистика: діаграми вихідних станів (`statistics.flexCharts.jsonOutput.hrly` і т.д.) оновлено автоматично за кожну годину",
30
+ "zh-cn": "统计:弹性图集成——内置的Apache ECharts配置,并有栏和行图支持\n统计:日间可视化,小时图表可交替显示阴影区域\n统计:每个图表类型的模板(`Statistics.flex Charts.template.hourly'等),用于包括功能在内的全部ECharts定制\n统计:数据占位符(`%%solarYield%%`,`%%gridExport%%`等)允许通过模板状态进行完整的图表布局控制\n统计:图表输出状态(`STATistics.flexCHarts.jsonOutput.hourly'等)"
31
+ },
32
+ "2.4.0": {
33
+ "en": "fix: the order of bit assignment corrected of alarmsJSON\nnew state `inverter.x.emma.activeAlarmSN` and `inverter.x.emma.HistoricalAlarmSN` : emma alarms [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nstatistics: Aggregates historical collected datapoints into time-based summaries (e.g. hourly, daily, monthly, yearly). The data is stored in the path `statistics` as JSON.",
34
+ "de": "fix: die Reihenfolge der Bitzuweisung korrigiert von Alarmen JSON\nneuer Zustand `inverter.x.emma.activeAlarmSN` und `inverter.x.emma.HistoricalAlarmSN`: Emma alarms [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nstatistik: Aggregate historische gesammelte Datenpunkte in zeitbasierte Zusammenfassungen (z.B. stündlich, täglich, monatlich, jährlich). Die Daten werden im Pfad `statistics` als JSON gespeichert.",
35
+ "ru": "исправление: порядок назначения битов исправлен сигнализацией Джон\nновое состояние 'inverter.x.emma.activeAlarmSN' и 'inverter.x.emma.HistoricalAlarmSN': emma alarms [#226] (https://github.com/bolliy/ioBroker.sun2000/issues/226)\nстатистика: Собирает исторические собранные точки данных в основанные на времени резюме (например, почасовые, ежедневные, ежемесячные, годовые). Данные хранятся в «статистике» пути JSON.",
36
+ "pt": "corrigir: a ordem de atribuição de bits corrigida dos alarmes JSON\nnovo estado `inverter.x.emma.activeAlarmSN` e `inverter.x.emma.HistoricAlarmSN` : alarmes emma [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nestatísticas: Agrega pontos de dados históricos recolhidos em resumos baseados no tempo (por exemplo, horários, diários, mensais, anuais). Os dados são armazenados no caminho `statistics` como JSON.",
37
+ "nl": "fix: de volgorde van bittoewijzing gecorrigeerd van alarmen JSON\nnieuwe staat \nstatistieken: Verzamelt historische verzamelde datapunten in tijdgebaseerde samenvattingen (bv. uur, dag, maand, jaar). De gegevens worden opgeslagen in het pad .",
38
+ "fr": "correction : l'ordre d'attribution des bits corrigé des alarmes JSON\nnouvel état `inverter.x.emma.activeAlarmSN` et `inverter.x.emma.HistoricalAlarmSN`: emma alarms [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nstatistiques : Agrége les points de données historiques collectés en résumés chronologiques (p. ex. horaires, quotidiens, mensuels, annuels). Les données sont stockées dans le chemin `statistique` comme JSON.",
39
+ "it": "fix: l'ordine di bit assegnazione corretto di allarmi JSON\nnuovo stato `inverter.x.emma.activeAlarmSN` e `inverter.x.emma.HistoricalAlarmSN` : allarme emma [#226](https://github.com/bolliy/ioBroker.sun2000/problems/226)\nstatistiche: Aggrega i datapoint storici raccolti in riassunti basati sul tempo (es. orario, giornaliero, mensile, annuale). I dati vengono memorizzati nel percorso `statistics` come JSON.",
40
+ "es": "fijación: el orden de asignación de bits corregido de alarmas JSON\nnuevo estado `inverter.x.emma.activeAlarmSN` e `inverter.x.emma.HistoricalAlarmSN` : emma alarms [#226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\nestadística: Aggregates historical collected datapoints into time-based summaries (e.g. hourly, daily, monthly, yearly). Los datos se almacenan en el camino 'estadística' como JSON.",
41
+ "pl": "fix: kolejność przypisywania bitów poprawionych alarmów JSON\nw języku angielskim:\nstatystyki: Zagregowane historyczne zbierane punkty danych w skróty czasowe (np. godzinowe, dzienne, miesięczne, roczne). Dane są przechowywane w ścieżce \"statystyki\" jako JSON.",
42
+ "uk": "фіксувати: порядок відведення біту виправлено тривоги Сонце\nновий стан `inverter.x.emma.activeAlarmSN` і `inverter.x.emma.HistoricalAlarmSN` : emma тривоги [#226](https://github.com/bolliy/ioBroker.sun2000/products/226)\nстатистика: Агрегати історичних зібраних точок даних на часові суми (наприклад, час, щоденно, щомісяця, рік). Дані зберігаються на шляху `statistics` як JSON.",
43
+ "zh-cn": "固定: 修改提醒的位任务顺序 贾森\n新状态`inverter.x.emma.active AlarmSN ' 和`inverter.x.emma. Historical AlarmSN ' : emma警报[# 226](https://github.com/bolliy/ioBroker.sun2000/issues/226)\n统计: 将历史收集的数据点汇总为时间摘要(如小时、每日、每月、每年)。 数据作为JSON储存在路径`统计'中."
44
+ },
6
45
  "2.3.7": {
7
46
  "en": "deleted deprecated state `collected.usableSurplusPower`",
8
47
  "de": "gelöschter deprecated state `collect.usableSurplusPower `",
@@ -54,45 +93,6 @@
54
93
  "pl": "aktualizacje zależności i konfiguracji\nnowy stan \"collected.dailyExternalYield\" Riemann sum of 'collected.externalPower'",
55
94
  "uk": "оновлення залежності та конфігурації\nновий стан `collected.dailyExternalYield` Сума Riemann `collected.externalPower й",
56
95
  "zh-cn": "依赖和配置更新\n新国家`收集.每日外部耶尔德' 收集的里曼总和。 `"
57
- },
58
- "2.3.3": {
59
- "en": "Improved verification of the adapter configuration\nnew state `inverter.x.derived.dailyActiveEnergy` Inverter daily active energy, which is determined via the Riemann sum of `inverter.x.activePower`\nstate `collected.dailyInputYield` was redisigned based on inverter.[0..n-1].derived.dailyActiveEnergy",
60
- "de": "Verbesserte Überprüfung der Adapterkonfiguration\n`inverter.x.derived.dailyActiveEnergy` Inverter tägliche aktive Energie, die über die Riemann Summe von `inverter.x.activePower bestimmt wird `\nstate `collected.dailyInputYield` wurde basierend auf Inverter zurückgeteilt. [0.n-1].derived.dailyActiveEnergy",
61
- "ru": "Улучшенная проверка конфигурации адаптера\nновое состояние «inverter.x.derived.dailyActiveEnergy» Инверторная ежедневная активная энергия, которая определяется через сумму Римана 'inverter.x.activePower пункт\nstate 'collected.dailyInputYield' была переопределена на основе инвертора. [0..n-1].derived.dailyActiveEnergy",
62
- "pt": "Verificação melhorada da configuração do adaptador\nnovo estado «inverter.x.derived.dailyActiveEnergy» Energia ativa diária do inversor, que é determinada através da soma Riemann de `inverter.x.activePower `\nestado `colleted.dailyInputYield` foi reassinado com base no inversor. [0..n-1].derivado.diárioAtividadeEnergia",
63
- "nl": "Verbeterde verificatie van de configuratie van de adapter\nnieuwe staat Inverter dagelijkse actieve energie, die wordt bepaald via de Riemann som van Wat\nstaat [0..n-1].afgeleid.dailyActiveEnergy",
64
- "fr": "Amélioration de la vérification de la configuration de l'adaptateur\nnouvel état `inverter.x.derived.dailyActiveEnergy` Inverter l'énergie active quotidienne, qui est déterminée par la somme Riemann de `inverter.x.activePower \"\nl'état `collected.dailyInputYield` a été résigné sur la base de l'onduleur. Énergie active",
65
- "it": "Verifica migliorata della configurazione dell'adattatore\nnuovo stato `inverter.x.derived.dailyActiveEnergy` Inverter energia attiva quotidiana, che è determinata tramite la somma Riemann di `inverter.x.activePower #\nstato `collect.dailyInputYield` è stato ridisegnato sulla base di inverter. [0.n-1]",
66
- "es": "Mejor verificación de la configuración del adaptador\nnuevo estado `inverter.x.derived.dailyActiveEnergy` Inverter energía activa diaria, que se determina a través de la suma Riemann de `inverter.x.activePower `\nestado `colected.dailyInputYield` fue redisigned basado en inverter. [0.n-1].derived.dailyActiveEnergy",
67
- "pl": "Ulepszona weryfikacja konfiguracji adaptera\nnowy stan 'inverter.x.derived.dailyActiveEnergy' Inwerter dzienna aktywna energia, która jest określana za pomocą sumy Riemann 'inverter.x.activePower'\nstan 'collected.dailyInputYield' został wycofany na podstawie inwertera. [0.. n-1] .derived.dailyActiveEnergy",
68
- "uk": "Покращена перевірка конфігурації адаптера\nновий стан `inverter.x.derived.dailyActiveEnergy` Інверторна щоденна активна енергія, яка визначається за рахунок `inverter.x.activePower й\n`collected.dailyInputYield` був перерахований на основі інвертора. [0..n-1].derived.dailyActiveEnergy",
69
- "zh-cn": "改进适配器配置的核查\n新州`反转器.x.衍生的每日能源 ' 每日反转活性能量,通过`反转器.x.activePower的Riemann总和确定 `\ndaily InputYield)根据反差重新签名。 [0.n-1]. 衍生的每日能源"
70
- },
71
- "2.3.2": {
72
- "en": "allows again `control.battery.chargeFromGridFunction` when using the Emma",
73
- "de": "erlaubt wieder `control.battery.chargeFromGridFunction` bei Verwendung der Emma",
74
- "ru": "позволяет снова «control.battery.chargeFromGridFunction» при использовании Emma",
75
- "pt": "permite novamente `control.battery.chargeFromGridFunction` ao usar a Emma",
76
- "nl": "maakt het mogelijk opnieuw te controleren.battery.chargeFromGridFunction",
77
- "fr": "permet de nouveau `control.battery.chargeFromGridFunction` lors de l'utilisation de l'Emma",
78
- "it": "permette di nuovo `control.battery.chargeFromGridFunction` quando si utilizza Emma",
79
- "es": "permite de nuevo 'control.battery.chargeDesdeGridFunction' al utilizar Emma",
80
- "pl": "pozwala ponownie 'control.battery.chargeFromGridFunction' podczas korzystania z Emmy",
81
- "uk": "дозволяє знову `control.battery.chargeЗ альбомуGridFunction` при використанні Емма",
82
- "zh-cn": "允许在使用 Emma 时再次使用 \" control.battery. charge from GridFunction \" "
83
- },
84
- "2.3.1": {
85
- "en": "fix: handle potential null values in set method of RegisterMap",
86
- "de": "fix: griff potenzielle Nullwerte in der eingestellten Methode des Registrierens Landkarte",
87
- "ru": "исправление: обработка потенциальных нулевых значений в установленном методе Регистра Карта",
88
- "pt": "corrigir: manusear valores nulos potenciais no método definido de Registro Mapa",
89
- "nl": "fix: handle potentiële nulwaarden in set methode van Register Kaart",
90
- "fr": "fix: gérer les valeurs null potentielles dans la méthode définie de Register Carte",
91
- "it": "fix: gestire potenziali valori null nel metodo impostato di Registrazione Mappa",
92
- "es": "fijación: manejar valores nulos potenciales en el método set de Registro Mapa",
93
- "pl": "fix: obsługi potencjalnych wartości null w ustawieniu metody rejestru Mapa",
94
- "uk": "виправити: обробляти потенціал null значення в встановленому методі Реєстру Мапа",
95
- "zh-cn": "固定值:在设定的登记方法中处理潜在的无效值 地图"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -129,6 +129,7 @@
129
129
  "modbus",
130
130
  "sun2000",
131
131
  "luna2000",
132
+ "emma",
132
133
  "inverter",
133
134
  "smartcharger",
134
135
  "sdongle"
@@ -150,6 +151,7 @@
150
151
  "compact": true,
151
152
  "connectionType": "local",
152
153
  "dataSource": "poll",
154
+ "messagebox": true,
153
155
  "adminUI": {
154
156
  "config": "json"
155
157
  },
@@ -221,7 +223,7 @@
221
223
  ],
222
224
  "globalDependencies": [
223
225
  {
224
- "admin": ">=7.6.17"
226
+ "admin": ">=7.6.20"
225
227
  }
226
228
  ],
227
229
  "plugins": {
@@ -247,6 +249,8 @@
247
249
  "ms_log": false,
248
250
  "sl_meterId": 11,
249
251
  "ds_bu": true,
252
+ "ds_bp": false,
253
+ "cb_tou": false,
250
254
  "integration": 0
251
255
  },
252
256
  "objects": [],
@@ -191,7 +191,7 @@ class DriverBase {
191
191
 
192
192
  /**
193
193
  * Read the device list for a given modbusId.
194
- * @param {ModbusClient} modbusClient - The modbus client to use.
194
+ * @param {object} modbusClient - The modbus client to use.
195
195
  * @param {number} [modbusId] - The modbus ID to query.
196
196
  * @returns {Promise<[number, { [key: string]: string }]>}
197
197
  * The first element of the array is the number of devices,
@@ -209,6 +209,7 @@ class DriverBase {
209
209
  throw new Error(`readDeviceList: No answer for OID=0x${objectId.toString(16).toUpperCase()}: ${e.message}`);
210
210
  }
211
211
  const numDevices = parseInt(JSON.stringify(allInfo['135'] || '').replace(/[^0-9]/g, ''));
212
+ // @ts-expect-error - we know that the value is a string, but the type definition is incorrect
212
213
  return [numDevices, allInfo];
213
214
  }
214
215
 
@@ -293,7 +294,7 @@ class DriverBase {
293
294
  * If the error is a connection error, it stops the update loop.
294
295
  * Finally, it calls the _runPostUpdateHooks function to run any post update hooks and stores the states.
295
296
  *
296
- * @param {ModbusClient} modbusClient - The Modbus client to use for communication.
297
+ * @param {object} modbusClient - The Modbus client to use for communication.
297
298
  * @param {dataRefreshRate} refreshRate - The refresh rate to use for updating the states.
298
299
  * @param {number} [duration] - The duration in milliseconds for which the states should be updated.
299
300
  * @returns {Promise<number>} - A promise that resolves to the number of registers read.
@@ -784,6 +784,22 @@ class Emma extends DriverBase {
784
784
  this.stateCache.set(`${path}emma.derived.systemTime`, fixTime(systemTime), { type: 'number' });
785
785
  },
786
786
  },
787
+ {
788
+ address: 65500,
789
+ length: 4,
790
+ info: 'Public Register Definitions',
791
+ refresh: dataRefreshRate.low,
792
+ states: [
793
+ {
794
+ state: { id: 'emma.activeAlarmSN', name: 'Active alarm SN', type: 'number', role: 'value', desc: 'reg:65500, len:2' },
795
+ register: { reg: 65500, type: dataType.uint32 },
796
+ },
797
+ {
798
+ state: { id: 'emma.HistoricalAlarmSN', name: 'Historical alarm SN', type: 'number', role: 'value', desc: 'reg:65502, len:2' },
799
+ register: { reg: 65502, type: dataType.uint32 },
800
+ },
801
+ ],
802
+ },
787
803
  ];
788
804
 
789
805
  this.registerFields.push.apply(this.registerFields, newFields);
@@ -1741,36 +1741,40 @@ class InverterSun2000 extends DriverBase {
1741
1741
  //overload
1742
1742
  get modbusAllowed() {
1743
1743
  //if the modbus-device offline we cannot read or write anythink!
1744
- let modbusAllowed = true;
1745
- if (this.deviceInfo.index > 0) {
1744
+ let allowModbus = true; //allowed = true;
1745
+ //if integration = sDongle and only a slave inverter has not a meter.
1746
+ if (this.adapter.settings.integration === 0 && !this.deviceInfo.meter) {
1746
1747
  //I am a slave inverter
1747
- if (this.adapter.devices[0].driverClass === driverClasses.inverter && this.adapter.devices[0].instance) {
1748
- modbusAllowed = this.adapter.devices[0].instance.modbusAllowed; //first ask the master
1748
+ //If the master inverter has a meter, ask the master if modbus is allowed.
1749
+ if (this.adapter.devices[0].instance && this.adapter.devices[0].instance !== this.deviceInfo.instance) {
1750
+ if (this.adapter.devices[0].driverClass === driverClasses.inverter && this.adapter.devices[0].meter) {
1751
+ allowModbus = this.adapter.devices[0].instance.modbusAllowed; //first ask the master
1752
+ }
1749
1753
  }
1750
1754
  }
1751
- if (modbusAllowed) {
1755
+ if (allowModbus) {
1752
1756
  //430 = SUN2000-8KTL-M2
1753
1757
  if (this.deviceStatus === 0x0002) {
1754
- if (this.deviceInfo.index > 0 && this._modelId < 430) modbusAllowed = false;
1758
+ if (this.deviceInfo.index > 0 && this._modelId < 430) allowModbus = false;
1755
1759
  } //standby
1756
1760
  if (this.deviceStatus >= 0x0300 && this.deviceStatus <= 0x0307) {
1757
- modbusAllowed = false;
1761
+ allowModbus = false;
1758
1762
  } //shutdown
1759
1763
  if (this._errorCount > 3) {
1760
- modbusAllowed = false;
1764
+ allowModbus = false;
1761
1765
  }
1762
1766
  }
1763
1767
 
1764
- if (!modbusAllowed && !this.log.quiet) {
1768
+ if (!allowModbus && !this.log.quiet) {
1765
1769
  this.log.info(`The inverter with modbus ID ${this._modbusId} is no longer accessible. That is why the logs are minimized.`);
1766
1770
  this.log.beQuiet(true);
1767
1771
  }
1768
- if (modbusAllowed && this.log.quiet) {
1772
+ if (allowModbus && this.log.quiet) {
1769
1773
  this.log.beQuiet(false);
1770
1774
  this.log.info(`The inverter with modbus ID ${this._modbusId} is accessible again.`);
1771
1775
  //this._errorCount = 0;
1772
1776
  }
1773
- this._modbusAllowed = modbusAllowed;
1777
+ this._modbusAllowed = allowModbus;
1774
1778
  return this._modbusAllowed;
1775
1779
  }
1776
1780
 
package/lib/register.js CHANGED
@@ -4,6 +4,7 @@ const { deviceType, driverClasses, dataRefreshRate } = require(`${__dirname}/typ
4
4
  const { RiemannSum, StateMap } = require(`${__dirname}/tools.js`);
5
5
  const getDriverHandler = require(`${__dirname}/drivers/index.js`);
6
6
  const tools = require(`${__dirname}/tools.js`);
7
+ const statistics = require(`${__dirname}/statistics.js`);
7
8
 
8
9
  class Registers {
9
10
  constructor(adapterInstance) {
@@ -11,6 +12,7 @@ class Registers {
11
12
  this.stateCache = new StateMap();
12
13
 
13
14
  this.externalSum = new RiemannSum();
15
+ this.statistics = new statistics(adapterInstance, this.stateCache);
14
16
 
15
17
  for (const device of this.adapter.devices) {
16
18
  //DriverInfo Instance or Sdongle
@@ -19,7 +21,8 @@ class Registers {
19
21
  device.instance = new handler(this, device);
20
22
  }
21
23
  }
22
- //deleted deprecated states
24
+
25
+ //Upgrade to v2.3.7 - deleted deprecated states
23
26
  if (
24
27
  tools.existsState(this.adapter, `collected.usableSurplusPower`, (err, exists) => {
25
28
  if (!err && exists) {
@@ -32,8 +35,8 @@ class Registers {
32
35
  })
33
36
  );
34
37
 
35
- this.postProcessHooks = [];
36
- this.inverterPostProcessHooks = [
38
+ //this.postProcessHooks = [];
39
+ this.postProcessHooks = [
37
40
  {
38
41
  refresh: dataRefreshRate.high,
39
42
  states: [
@@ -56,16 +59,6 @@ class Registers {
56
59
  unit: 'kW',
57
60
  role: 'value.power',
58
61
  },
59
- /*
60
- {
61
- id: 'collected.usableSurplusPower',
62
- name: 'usable surplus power',
63
- type: 'number',
64
- unit: 'kW',
65
- role: 'value.power',
66
- desc: 'depreciated: Please use collected.surplus.usablePower instead',
67
- },
68
- */
69
62
  {
70
63
  id: 'collected.surplus.power',
71
64
  name: 'surplus power',
@@ -190,18 +183,12 @@ class Registers {
190
183
  this.stateCache.set('collected.activePower', actPower, { type: 'number', renew: true });
191
184
  this.stateCache.set('collected.houseConsumption', houseConsum, { type: 'number' });
192
185
  this.stateCache.set('collected.chargeDischargePower', chargeDischarge, { type: 'number' });
193
- /*
194
- this.stateCache.set('collected.usableSurplusPower', surplusArray[1], {
195
- type: 'number',
196
- });
197
- */
198
186
  this.stateCache.set('collected.surplus.power', surplusArray[0], {
199
187
  type: 'number',
200
188
  });
201
189
  this.stateCache.set('collected.surplus.usablePower', surplusArray[1], {
202
190
  type: 'number',
203
191
  });
204
-
205
192
  this.stateCache.set('collected.externalPower', extPower, { type: 'number' });
206
193
  },
207
194
  },
@@ -329,7 +316,17 @@ class Registers {
329
316
  feedinEnergy = this.stateCache.get('meter.positiveActiveEnergy')?.value ?? 0;
330
317
  supplyFromGrid = this.stateCache.get('meter.reverseActiveEnergy')?.value ?? 0;
331
318
  }
332
- //stimmt leider nicht genau - bleibt aber erstmal bestehen
319
+ //NEU - Initialisierung
320
+ const gridExportStart = this.stateCache.get('collected.gridExportStart')?.value;
321
+ if (!gridExportStart && feedinEnergy !== 0) {
322
+ this.stateCache.set('collected.gridExportStart', feedinEnergy, { type: 'number' });
323
+ }
324
+ const gridImportStart = this.stateCache.get('collected.gridImportStart')?.value;
325
+ if (!gridImportStart && supplyFromGrid !== 0) {
326
+ this.stateCache.set('collected.gridImportStart', supplyFromGrid, { type: 'number' });
327
+ }
328
+
329
+ //stimmt wahrscheinlich nicht genau - bleibt aber erstmal bestehen
333
330
  const conSum = enYield + supplyFromGrid - feedinEnergy;
334
331
  this.stateCache.set('collected.consumptionSum', conSum, { type: 'number' });
335
332
  // compute export and import today
@@ -360,7 +357,9 @@ class Registers {
360
357
  ];
361
358
 
362
359
  //only Inverter
363
- this.postProcessHooks.push.apply(this.postProcessHooks, this.inverterPostProcessHooks);
360
+ //this.postProcessHooks.push.apply(this.postProcessHooks, this.inverterPostProcessHooks);
361
+ this.postProcessHooks.push.apply(this.postProcessHooks, this.statistics.processHooks);
362
+
364
363
  this._loadStates();
365
364
  }
366
365
 
@@ -376,10 +375,21 @@ class Registers {
376
375
  unit: state.unit,
377
376
  desc: state.desc,
378
377
  read: true,
379
- write: false,
378
+ write: state.write || false,
380
379
  },
381
380
  native: {},
382
381
  });
382
+
383
+ if (state.initVal) {
384
+ const ret = await this.adapter.getState(state.id);
385
+ if (!ret || ret.val === null) {
386
+ try {
387
+ await this.adapter.setState(state.id, { val: state.initVal, ack: true });
388
+ } catch (err) {
389
+ this.adapter.log.warn(`Error while initializing ${state.id}, val=${state.initVal} err=${err.message}`);
390
+ }
391
+ }
392
+ }
383
393
  }
384
394
 
385
395
  async storeStates() {
@@ -411,7 +421,7 @@ class Registers {
411
421
  * its states. Logs an error if no device instance has been initialized.
412
422
  *
413
423
  * @param {object} device - The device object containing the instance and driverClass.
414
- * @param {ModbusClient} modbusClient - The Modbus client used for communication.
424
+ * @param {object} modbusClient - The Modbus client used for communication.
415
425
  * @param {string} refreshRate - The rate at which data should be refreshed.
416
426
  * @param {number} duration - The duration for which the states should be updated.
417
427
  * @returns {Promise<number>} - Returns a promise that resolves to the number of states updated.
@@ -449,7 +459,7 @@ class Registers {
449
459
  }
450
460
  }
451
461
  hook.initState = true;
452
- hook.fn(this.adapter.devices);
462
+ hook.fn && hook.fn(this.adapter.devices);
453
463
  }
454
464
  }
455
465
  this.storeStates(); //fire and forget
@@ -459,6 +469,7 @@ class Registers {
459
469
  async _loadStates() {
460
470
  let state = await this.adapter.getState('collected.gridExportStart');
461
471
  this.stateCache.set('collected.gridExportStart', state?.val, { type: 'number', stored: true });
472
+ this.stateCache.set('collected.gridImportStart', state?.val, { type: 'number', stored: true });
462
473
  state = await this.adapter.getState('collected.gridImportStart');
463
474
  this.stateCache.set('collected.gridImportStart', state?.val, { type: 'number', stored: true });
464
475
  state = await this.adapter.getState('collected.consumptionStart');
@@ -525,6 +536,7 @@ class Registers {
525
536
  // one minute before midnight - perform housekeeping actions
526
537
  //state
527
538
  async mitnightProcess() {
539
+ this.statistics.mitNightProcess();
528
540
  // copy current export/import kWh - used to compute daily import/export in kWh
529
541
  const sign = this.stateCache.get('meter.derived.signConventionForPowerFeed-in')?.value ?? 1;
530
542
  if (sign === -1) {
@@ -543,7 +555,7 @@ class Registers {
543
555
  await device.instance.mitnightProcess();
544
556
  }
545
557
  }
546
- this.storeStates(); //fire and forget
558
+ this.storeStates();
547
559
  }
548
560
  }
549
561