iobroker.sigenergy 2.2.7 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -153,6 +153,12 @@ Status and power readings for the DC charger.
153
153
 
154
154
  ## Changelog
155
155
 
156
+ ### 2.3.1 (2026-06-10)
157
+ - (ssbingo) feat: detect Modbus protocol level on startup by probing registers 30088/30200/30228/30286; read firmware version (30525); log result and store as info.protocolLevel state
158
+
159
+ ### 2.3.0 (2026-06-10)
160
+ - (ssbingo) feat: add common.states enum maps for emsWorkMode/runningState/remoteEmsMode/dcCharger.runningState; wire PSS/PID/AC Charger write registers (FC06/FC10) with subscribe and onStateChange handlers
161
+
156
162
  ### 2.2.7 (2026-06-10)
157
163
  - (ssbingo) fix: add missing native defaults enableSmartLoads/enableCumulativeEnergy/enableGridCode to io-package.json
158
164
  - (ssbingo) fix: update register 30003 desc with V2.7 EMS modes 5 (FullFeedIn) and 9 (Custom)
package/io-package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "sigenergy",
4
- "version": "2.2.7",
4
+ "version": "2.3.1",
5
5
  "news": {
6
- "2.2.7": {
7
- "en": "(ssbingo) fix: add missing native defaults enableSmartLoads/enableCumulativeEnergy/enableGridCode to io-package.json; update register 30003 desc with V2.7 EMS modes 5 (FullFeedIn) and 9 (Custom)",
8
- "de": "(ssbingo) fix: fehlende native-Defaults enableSmartLoads/enableCumulativeEnergy/enableGridCode in io-package.json ergänzt; Register 30003 Beschreibung um V2.7 EMS-Modi 5 (FullFeedIn) und 9 (Custom) erweitert",
9
- "ru": "(ssbingo) fix: добавлены отсутствующие native-дефолты enableSmartLoads/enableCumulativeEnergy/enableGridCode в io-package.json; обновлено описание регистра 30003 с режимами EMS V2.7: 5 (FullFeedIn) и 9 (Custom)",
10
- "pt": "(ssbingo) fix: defaults native enableSmartLoads/enableCumulativeEnergy/enableGridCode adicionados ao io-package.json; descrição do registo 30003 atualizada com modos EMS V2.7 5 (FullFeedIn) e 9 (Custom)",
11
- "nl": "(ssbingo) fix: ontbrekende native-standaarden enableSmartLoads/enableCumulativeEnergy/enableGridCode toegevoegd aan io-package.json; beschrijving register 30003 bijgewerkt met V2.7 EMS-modi 5 (FullFeedIn) en 9 (Custom)",
12
- "fr": "(ssbingo) fix: defaults native enableSmartLoads/enableCumulativeEnergy/enableGridCode ajoutés à io-package.json ; description registre 30003 mise à jour avec modes EMS V2.7 5 (FullFeedIn) et 9 (Custom)",
13
- "it": "(ssbingo) fix: default native enableSmartLoads/enableCumulativeEnergy/enableGridCode aggiunti a io-package.json; descrizione registro 30003 aggiornata con modalità EMS V2.7 5 (FullFeedIn) e 9 (Custom)",
14
- "es": "(ssbingo) fix: defaults native enableSmartLoads/enableCumulativeEnergy/enableGridCode añadidos a io-package.json; descripción del registro 30003 actualizada con modos EMS V2.7 5 (FullFeedIn) y 9 (Custom)",
15
- "pl": "(ssbingo) fix: brakujące domyślne native enableSmartLoads/enableCumulativeEnergy/enableGridCode dodane do io-package.json; opis rejestru 30003 zaktualizowany o tryby EMS V2.7 5 (FullFeedIn) i 9 (Custom)",
16
- "uk": "(ssbingo) fix: відсутні native-дефолти enableSmartLoads/enableCumulativeEnergy/enableGridCode додано до io-package.json; опис регістру 30003 оновлено з режимами EMS V2.7 5 (FullFeedIn) та 9 (Custom)",
17
- "zh-cn": "(ssbingo) fix: io-package.json 中添加缺失的 native 默认值 enableSmartLoads/enableCumulativeEnergy/enableGridCode;更新寄存器 30003 描述以包含 V2.7 EMS 模式 5(完全并网)和 9(自定义)"
6
+ "2.3.1": {
7
+ "en": "(ssbingo) feat: detect Modbus protocol level on startup by probing registers 30088/30200/30228/30286; read firmware version (30525); log result and store as info.protocolLevel state",
8
+ "de": "(ssbingo) feat: Modbus-Protokollebene beim Start durch Probe von Registern 30088/30200/30228/30286 erkennen; Firmware-Version (30525) lesen; Ergebnis loggen und als info.protocolLevel-State speichern",
9
+ "ru": "(ssbingo) feat: определение уровня протокола Modbus при запуске путём опроса регистров 30088/30200/30228/30286; чтение версии прошивки (30525); журналирование результата и сохранение в состояние info.protocolLevel",
10
+ "pt": "(ssbingo) feat: detectar nível do protocolo Modbus no arranque sondando registos 30088/30200/30228/30286; ler versão de firmware (30525); registar resultado e guardar como estado info.protocolLevel",
11
+ "nl": "(ssbingo) feat: Modbus-protocolniveau bij opstarten detecteren door registers 30088/30200/30228/30286 te sonderen; firmwareversie (30525) lezen; resultaat loggen en opslaan als info.protocolLevel-state",
12
+ "fr": "(ssbingo) feat: détection du niveau de protocole Modbus au démarrage en sondant les registres 30088/30200/30228/30286 ; lecture de la version firmware (30525) ; journalisation du résultat et stockage dans l'état info.protocolLevel",
13
+ "it": "(ssbingo) feat: rilevamento del livello del protocollo Modbus all'avvio sondando i registri 30088/30200/30228/30286; lettura della versione firmware (30525); registrazione del risultato e salvataggio come stato info.protocolLevel",
14
+ "es": "(ssbingo) feat: detectar nivel de protocolo Modbus en el arranque sondeando registros 30088/30200/30228/30286; leer versión de firmware (30525); registrar resultado y almacenar como estado info.protocolLevel",
15
+ "pl": "(ssbingo) feat: wykrywanie poziomu protokołu Modbus przy uruchomieniu przez próbkowanie rejestrów 30088/30200/30228/30286; odczyt wersji firmware (30525); logowanie wyniku i zapis jako stan info.protocolLevel",
16
+ "uk": "(ssbingo) feat: виявлення рівня протоколу Modbus при запуску шляхом зондування регістрів 30088/30200/30228/30286; зчитування версії прошивки (30525); журналювання результату та збереження як стан info.protocolLevel",
17
+ "zh-cn": "(ssbingo) feat: 启动时通过探测寄存器 30088/30200/30228/30286 检测 Modbus 协议级别;读取固件版本(30525);记录结果并存储为 info.protocolLevel 状态"
18
18
  }
19
19
  },
20
20
  "titleLang": {
@@ -178,6 +178,19 @@
178
178
  "def": "idle"
179
179
  },
180
180
  "native": {}
181
+ },
182
+ {
183
+ "_id": "info.protocolLevel",
184
+ "type": "state",
185
+ "common": {
186
+ "name": "Detected Modbus protocol level",
187
+ "type": "string",
188
+ "role": "text",
189
+ "read": true,
190
+ "write": false,
191
+ "def": ""
192
+ },
193
+ "native": {}
181
194
  }
182
195
  ]
183
196
  }
package/main.js CHANGED
@@ -20,11 +20,25 @@ const {
20
20
  PLANT_WRITE_REGISTERS,
21
21
  INVERTER_WRITE_REGISTERS,
22
22
  DC_CHARGER_WRITE_REGISTERS,
23
+ AC_CHARGER_WRITE_REGISTERS,
24
+ PSS_WRITE_REGISTERS,
25
+ PID_WRITE_REGISTERS,
26
+ RUNNING_STATES,
27
+ EMS_WORK_MODES,
28
+ REMOTE_EMS_MODES,
29
+ DC_CHARGER_RUNNING_STATES,
23
30
  } = require('./lib/registers');
24
31
  const SigenMicroScanner = require('./lib/scanner');
25
32
  const { getRegistersForDevice } = require('./lib/sigenMicroRegisters');
26
33
  const adapterVersion = require('./package.json').version;
27
34
 
35
+ const ENUM_STATES_MAP = {
36
+ 'plant.emsWorkMode': EMS_WORK_MODES,
37
+ 'plant.runningState': RUNNING_STATES,
38
+ 'dcCharger.runningState': DC_CHARGER_RUNNING_STATES,
39
+ 'plant.control.remoteEmsMode': REMOTE_EMS_MODES,
40
+ };
41
+
28
42
  class Sigenergy extends utils.Adapter {
29
43
  /**
30
44
  * @param {Partial<utils.AdapterOptions>} [options] - Adapter options
@@ -46,6 +60,7 @@ class Sigenergy extends utils.Adapter {
46
60
  // calling setStateAsync on a stopped adapter.
47
61
  this._stopped = false;
48
62
  this._controlRegistersRead = false;
63
+ this._protocolDetected = false;
49
64
  this._essPreheatingUnsupported = false;
50
65
 
51
66
  this.on('ready', this.onReady.bind(this));
@@ -233,6 +248,10 @@ class Sigenergy extends utils.Adapter {
233
248
  await this._readControlRegisters();
234
249
  this._controlRegistersRead = true;
235
250
  }
251
+ if (!this._protocolDetected) {
252
+ await this._detectProtocolLevel();
253
+ this._protocolDetected = true;
254
+ }
236
255
 
237
256
  const _t0 = Date.now();
238
257
  await this._readPlant();
@@ -487,6 +506,40 @@ class Sigenergy extends utils.Adapter {
487
506
  }
488
507
  }
489
508
 
509
+ async _detectProtocolLevel() {
510
+ const plantId = this.config.plantId || 247;
511
+ const inverterId = this.config.inverterId || 1;
512
+
513
+ const probes = [
514
+ { addr: 30088, level: 'V2.6' },
515
+ { addr: 30200, level: 'V2.7' },
516
+ { addr: 30228, level: 'V2.8' },
517
+ { addr: 30286, level: 'V2.9' },
518
+ ];
519
+
520
+ let detectedLevel = null;
521
+ for (const probe of probes) {
522
+ try {
523
+ await this.modbus.readInputRegisters(plantId, probe.addr, 1);
524
+ detectedLevel = probe.level;
525
+ } catch {
526
+ break;
527
+ }
528
+ }
529
+
530
+ let firmwareVersion = 'unknown';
531
+ try {
532
+ const raw = await this.modbus.readInputRegisters(inverterId, 30525, 15);
533
+ firmwareVersion = ModbusConnection.parseValue(raw, 'STRING', null) || 'unknown';
534
+ } catch {
535
+ // not critical
536
+ }
537
+
538
+ const levelStr = detectedLevel ? `>=${detectedLevel}` : 'unknown';
539
+ this.log.info(`Detected protocol level: ${levelStr} (firmware: ${firmwareVersion})`);
540
+ await this.setStateAsync('info.protocolLevel', { val: levelStr, ack: true });
541
+ }
542
+
490
543
  async _readControlRegisters() {
491
544
  const plantId = this.config.plantId || 247;
492
545
  const inverterId = this.config.inverterId || 1;
@@ -842,6 +895,14 @@ class Sigenergy extends utils.Adapter {
842
895
  }
843
896
  await this._createStateFromRegister(reg);
844
897
  }
898
+ await this._createChannel('acCharger.control', 'AC Charger Control');
899
+ for (const reg of AC_CHARGER_WRITE_REGISTERS) {
900
+ if (this._stopped) {
901
+ return;
902
+ }
903
+ await this._createWriteStateFromRegister(reg);
904
+ }
905
+ this.subscribeStates('acCharger.control.*');
845
906
  }
846
907
 
847
908
  if (this.config.hasDcCharger) {
@@ -882,17 +943,32 @@ class Sigenergy extends utils.Adapter {
882
943
  }
883
944
  await this._createStateFromRegister(reg);
884
945
  }
946
+ for (const reg of PSS_WRITE_REGISTERS) {
947
+ if (this._stopped) {
948
+ return;
949
+ }
950
+ await this._createWriteStateFromRegister(reg);
951
+ }
952
+ this.subscribeStates('pss.control.*');
885
953
  }
886
954
 
887
955
  if (this.config.enablePid) {
888
956
  this.log.debug('Creating PID objects');
889
957
  await this._createChannel('pid', 'PV Insulation Detection');
958
+ await this._createChannel('pid.control', 'PID Control');
890
959
  for (const reg of PID_READ_REGISTERS) {
891
960
  if (this._stopped) {
892
961
  return;
893
962
  }
894
963
  await this._createStateFromRegister(reg);
895
964
  }
965
+ for (const reg of PID_WRITE_REGISTERS) {
966
+ if (this._stopped) {
967
+ return;
968
+ }
969
+ await this._createWriteStateFromRegister(reg);
970
+ }
971
+ this.subscribeStates('pid.control.*');
896
972
  }
897
973
 
898
974
  if (this.config.enableEssPreheating) {
@@ -960,16 +1036,22 @@ class Sigenergy extends utils.Adapter {
960
1036
  type = 'number';
961
1037
  }
962
1038
 
1039
+ const common = {
1040
+ name: reg.desc,
1041
+ type,
1042
+ role,
1043
+ unit: reg.unit || '',
1044
+ read: true,
1045
+ write: false,
1046
+ };
1047
+ const states = ENUM_STATES_MAP[reg.name];
1048
+ if (states) {
1049
+ common.states = states;
1050
+ }
1051
+
963
1052
  await this.setObjectNotExistsAsync(reg.name, {
964
1053
  type: 'state',
965
- common: {
966
- name: reg.desc,
967
- type,
968
- role,
969
- unit: reg.unit || '',
970
- read: true,
971
- write: false,
972
- },
1054
+ common,
973
1055
  native: {
974
1056
  addr: reg.addr,
975
1057
  qty: reg.qty,
@@ -981,16 +1063,21 @@ class Sigenergy extends utils.Adapter {
981
1063
 
982
1064
  async _createWriteStateFromRegister(reg) {
983
1065
  const type = reg.type === 'STRING' ? 'string' : 'number';
1066
+ const common = {
1067
+ name: reg.desc,
1068
+ type,
1069
+ role: 'value',
1070
+ unit: reg.unit || '',
1071
+ read: reg.perm === 'RW',
1072
+ write: true,
1073
+ };
1074
+ const states = ENUM_STATES_MAP[reg.name];
1075
+ if (states) {
1076
+ common.states = states;
1077
+ }
984
1078
  await this.setObjectNotExistsAsync(reg.name, {
985
1079
  type: 'state',
986
- common: {
987
- name: reg.desc,
988
- type,
989
- role: 'value',
990
- unit: reg.unit || '',
991
- read: reg.perm === 'RW',
992
- write: true,
993
- },
1080
+ common,
994
1081
  native: {
995
1082
  addr: reg.addr,
996
1083
  qty: reg.qty,
@@ -1162,6 +1249,18 @@ class Sigenergy extends utils.Adapter {
1162
1249
  reg = DC_CHARGER_WRITE_REGISTERS.find(r => r.name === localId);
1163
1250
  slaveId = this.config.inverterId || 1;
1164
1251
  category = 'dcCharger';
1252
+ } else if (localId.startsWith('pss.control.')) {
1253
+ reg = PSS_WRITE_REGISTERS.find(r => r.name === localId);
1254
+ slaveId = this.config.pssSlaveId || 5;
1255
+ category = 'pss';
1256
+ } else if (localId.startsWith('pid.control.')) {
1257
+ reg = PID_WRITE_REGISTERS.find(r => r.name === localId);
1258
+ slaveId = this.config.pidSlaveId || 6;
1259
+ category = 'pid';
1260
+ } else if (localId.startsWith('acCharger.control.')) {
1261
+ reg = AC_CHARGER_WRITE_REGISTERS.find(r => r.name === localId);
1262
+ slaveId = this.config.acChargerId || 2;
1263
+ category = 'acCharger';
1165
1264
  }
1166
1265
 
1167
1266
  if (!reg) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.sigenergy",
3
- "version": "2.2.7",
3
+ "version": "2.3.1",
4
4
  "description": "ioBroker adapter for Sigenergy solar energy systems via Modbus TCP/RTU",
5
5
  "author": {
6
6
  "name": "ssbingo",