From 996a1d91e4fd50e4620fdced45755fb35ac00590 Mon Sep 17 00:00:00 2001 From: Matthias Bolte Date: Fri, 25 Oct 2024 14:59:09 +0200 Subject: [PATCH] meters-modbus-tcp: Add support for several Carlo Gavazzi meter types --- ...rlo Gavazzi EM270 Virtual Meter.uint8.enum | 4 + ...rlo Gavazzi EM280 Virtual Meter.uint8.enum | 4 + .../Carlo Gavazzi Phase.uint8.enum | 4 + .../Meter Modbus TCP Table ID.uint8.enum | 12 + .../meters_modbus_tcp/carlo_gavazzi.py | 2255 +++++++++++++++++ .../meters_modbus_tcp/meter_modbus_tcp.cpp | 223 +- .../meters_modbus_tcp/meter_modbus_tcp.h | 22 + .../meters_modbus_tcp/meters_modbus_tcp.cpp | 31 + .../src/modules/meters_modbus_tcp/prepare.py | 5 +- .../plugin_meters_config.tsx | 202 +- .../meters_modbus_tcp/translation_de.tsx | 19 + .../meters_modbus_tcp/translation_en.tsx | 19 + 12 files changed, 2796 insertions(+), 4 deletions(-) create mode 100644 software/src/modules/meters_modbus_tcp/Carlo Gavazzi EM270 Virtual Meter.uint8.enum create mode 100644 software/src/modules/meters_modbus_tcp/Carlo Gavazzi EM280 Virtual Meter.uint8.enum create mode 100644 software/src/modules/meters_modbus_tcp/Carlo Gavazzi Phase.uint8.enum create mode 100644 software/src/modules/meters_modbus_tcp/carlo_gavazzi.py diff --git a/software/src/modules/meters_modbus_tcp/Carlo Gavazzi EM270 Virtual Meter.uint8.enum b/software/src/modules/meters_modbus_tcp/Carlo Gavazzi EM270 Virtual Meter.uint8.enum new file mode 100644 index 000000000..7f3ea4ba1 --- /dev/null +++ b/software/src/modules/meters_modbus_tcp/Carlo Gavazzi EM270 Virtual Meter.uint8.enum @@ -0,0 +1,4 @@ +None +Meter +Current Transformer 1 +Current Transformer 2 diff --git a/software/src/modules/meters_modbus_tcp/Carlo Gavazzi EM280 Virtual Meter.uint8.enum b/software/src/modules/meters_modbus_tcp/Carlo Gavazzi EM280 Virtual Meter.uint8.enum new file mode 100644 index 000000000..7f3ea4ba1 --- /dev/null +++ b/software/src/modules/meters_modbus_tcp/Carlo Gavazzi EM280 Virtual Meter.uint8.enum @@ -0,0 +1,4 @@ +None +Meter +Current Transformer 1 +Current Transformer 2 diff --git a/software/src/modules/meters_modbus_tcp/Carlo Gavazzi Phase.uint8.enum b/software/src/modules/meters_modbus_tcp/Carlo Gavazzi Phase.uint8.enum new file mode 100644 index 000000000..242bf2bc9 --- /dev/null +++ b/software/src/modules/meters_modbus_tcp/Carlo Gavazzi Phase.uint8.enum @@ -0,0 +1,4 @@ +None +L1 +L2 +L3 diff --git a/software/src/modules/meters_modbus_tcp/Meter Modbus TCP Table ID.uint8.enum b/software/src/modules/meters_modbus_tcp/Meter Modbus TCP Table ID.uint8.enum index 7d7c875fd..2755e3e2e 100644 --- a/software/src/modules/meters_modbus_tcp/Meter Modbus TCP Table ID.uint8.enum +++ b/software/src/modules/meters_modbus_tcp/Meter Modbus TCP Table ID.uint8.enum @@ -19,3 +19,15 @@ Siemens PAC3200 Siemens PAC3220 Siemens PAC4200 Siemens PAC4220 +Carlo Gavazzi EM24 DIN +Carlo Gavazzi EM24 E1 +Carlo Gavazzi EM100 +Carlo Gavazzi ET100 +Carlo Gavazzi EM210 +Carlo Gavazzi EM270 +Carlo Gavazzi EM280 +Carlo Gavazzi EM300 +Carlo Gavazzi ET300 +Carlo Gavazzi EM510 +Carlo Gavazzi EM530 +Carlo Gavazzi EM540 diff --git a/software/src/modules/meters_modbus_tcp/carlo_gavazzi.py b/software/src/modules/meters_modbus_tcp/carlo_gavazzi.py new file mode 100644 index 000000000..ed44d3def --- /dev/null +++ b/software/src/modules/meters_modbus_tcp/carlo_gavazzi.py @@ -0,0 +1,2255 @@ +em100_and_et100_single_phase_values = [ + { + 'name': 'V L-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L1+L2+L3 [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', + 'start_address': 'START_ADDRESS_VIRTUAL', + }, + { + 'name': 'VA [0.1 VA]', + 'value_id': 'PowerApparentL1ImExDiff', # FIXME: direction? + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF [0.001]', + 'value_id': 'PowerFactorL1', + 'start_address': 0x0E, + 'value_type': 'S16', + 'drop_sign': True, # negative values correspond to capacitive load, positive value correspond to inductive load + 'scale_factor': 0.001, + }, + { + 'name': 'Hz [0.1 Hz]', + 'value_id': 'FrequencyL1', + 'start_address': 0x0F, + 'value_type': 'U16', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'L1+L2+L3 kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', + 'start_address': 'START_ADDRESS_VIRTUAL', + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveL1Inductive', # FIXME: direction? + 'start_address': 0x12, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveL1Export', # FIXME: direction? + 'start_address': 0x20, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'L1+L2+L3 kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumExport', + 'start_address': 'START_ADDRESS_VIRTUAL', + }, + { + 'name': 'kvarh(-) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveL1Capacitive', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, +] + +def make_em100_and_et100_single_phase_values(phase): + values = [] + + for value in em100_and_et100_single_phase_values: + new_value = dict(value) + new_value['value_id'] = new_value['value_id'].replace('L1', phase) + values.append(new_value) + + return values + +em510_single_phase_values = [ + { + 'name': 'V L-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L1+L2+L3 [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', + 'start_address': 'START_ADDRESS_VIRTUAL', + }, + { + 'name': 'VA [0.1 VA]', + 'value_id': 'PowerApparentL1ImExDiff', # FIXME: direction? + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF [0.001]', + 'value_id': 'PowerFactorL1Directional', + 'start_address': 0x0E, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'Hz [0.1 Hz]', + 'value_id': 'FrequencyL1', + 'start_address': 0x0F, + 'value_type': 'U16', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'L1+L2+L3 kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', + 'start_address': 'START_ADDRESS_VIRTUAL', + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveL1Inductive', # FIXME: direction? + 'start_address': 0x12, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveL1Export', # FIXME: direction? + 'start_address': 0x20, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'L1+L2+L3 kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumExport', + 'start_address': 'START_ADDRESS_VIRTUAL', + }, + { + 'name': 'kvarh(-) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveL1Capacitive', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kVAh Total [0.1 kVAh]', + 'value_id': 'EnergyApparentL1ImExSum', # FIXME: sum? + 'start_address': 0x28, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'THD A [0.01 %]', + 'value_id': 'CurrentTHDL1', + 'start_address': 0x32, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD V L-N [%]', + 'value_id': 'VoltageTHDL1N', + 'start_address': 0x34, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, +] + +def make_em510_single_phase_values(phase): + values = [] + + for value in em510_single_phase_values: + new_value = dict(value) + new_value['value_id'] = new_value['value_id'].replace('L1', phase) + values.append(new_value) + + return values + +specs = [ + { + 'name': 'Carlo Gavazzi EM24 DIN', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'V L1-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-N [0.1 V]', + 'value_id': 'VoltageL2N', + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-N [0.1 V]', + 'value_id': 'VoltageL3N', + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L1-L2 [0.1 V]', + 'value_id': 'VoltageL1L2', + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-L3 [0.1 V]', + 'value_id': 'VoltageL2L3', + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-L1 [0.1 V]', + 'value_id': 'VoltageL3L1', + 'start_address': 0x0A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x0C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x0E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W L1 [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x12, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L2 [0.1 W]', + 'value_id': 'PowerActiveL2ImExDiff', # FIXME: direction? + 'start_address': 0x14, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L3 [0.1 W]', + 'value_id': 'PowerActiveL3ImExDiff', # FIXME: direction? + 'start_address': 0x16, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L1 [0.1 VA]', + 'value_id': 'PowerApparentL1ImExDiff', # FIXME: direction? + 'start_address': 0x18, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L2 [0.1 VA]', + 'value_id': 'PowerApparentL2ImExDiff', # FIXME: direction? + 'start_address': 0x1A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L3 [0.1 VA]', + 'value_id': 'PowerApparentL3ImExDiff', # FIXME: direction? + 'start_address': 0x1C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L1 [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x1E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L2 [0.1 var]', + 'value_id': 'PowerReactiveL2IndCapDiff', # FIXME: direction? + 'start_address': 0x20, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L3 [0.1 var]', + 'value_id': 'PowerReactiveL3IndCapDiff', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-N Sum [0.1 V]', + 'value_id': 'VoltageLNAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x24, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-L Sum [0.1 V]', + 'value_id': 'VoltageLLAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x26, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x28, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x2A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x2C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF L1 [0.001]', + 'value_id': 'PowerFactorL1', + 'start_address': 0x32, + 'value_type': 'S16', + 'drop_sign': True, # negative values correspond to capacitive load, positive value correspond to inductive load + 'scale_factor': 0.001, + }, + { + 'name': 'PF L2 [0.001]', + 'value_id': 'PowerFactorL2', + 'start_address': 0x33, + 'value_type': 'S16', + 'drop_sign': True, # negative values correspond to capacitive load, positive value correspond to inductive load + 'scale_factor': 0.001, + }, + { + 'name': 'PF L3 [0.001]', + 'value_id': 'PowerFactorL3', + 'start_address': 0x34, + 'value_type': 'S16', + 'drop_sign': True, # negative values correspond to capacitive load, positive value correspond to inductive load + 'scale_factor': 0.001, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSum', # FIXME: negative values correspond to lead(C), positive value correspond to lag(L) + 'start_address': 0x35, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'Hz [0.1 Hz]', + 'value_id': 'FrequencyLAvg', + 'start_address': 0x37, + 'value_type': 'U16', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x3E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x40, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L1 [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x46, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L2 [0.1 kWh]', + 'value_id': 'EnergyActiveL2Import', # FIXME: direction? + 'start_address': 0x48, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L3 [0.1 kWh]', + 'value_id': 'EnergyActiveL3Import', # FIXME: direction? + 'start_address': 0x4A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumExport', # FIXME: direction? + 'start_address': 0x5C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(-) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumCapacitive', # FIXME: direction? + 'start_address': 0x5E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + ], + }, + { + 'name': 'Carlo Gavazzi EM24 E1', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'V L1-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-N [0.1 V]', + 'value_id': 'VoltageL2N', + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-N [0.1 V]', + 'value_id': 'VoltageL3N', + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L1-L2 [0.1 V]', + 'value_id': 'VoltageL1L2', + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-L3 [0.1 V]', + 'value_id': 'VoltageL2L3', + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-L1 [0.1 V]', + 'value_id': 'VoltageL3L1', + 'start_address': 0x0A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x0C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x0E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W L1 [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x12, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L2 [0.1 W]', + 'value_id': 'PowerActiveL2ImExDiff', # FIXME: direction? + 'start_address': 0x14, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L3 [0.1 W]', + 'value_id': 'PowerActiveL3ImExDiff', # FIXME: direction? + 'start_address': 0x16, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L1 [0.1 VA]', + 'value_id': 'PowerApparentL1ImExDiff', # FIXME: direction? + 'start_address': 0x18, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L2 [0.1 VA]', + 'value_id': 'PowerApparentL2ImExDiff', # FIXME: direction? + 'start_address': 0x1A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L3 [0.1 VA]', + 'value_id': 'PowerApparentL3ImExDiff', # FIXME: direction? + 'start_address': 0x1C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L1 [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x1E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L2 [0.1 var]', + 'value_id': 'PowerReactiveL2IndCapDiff', # FIXME: direction? + 'start_address': 0x20, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L3 [0.1 var]', + 'value_id': 'PowerReactiveL3IndCapDiff', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-N Sum [0.1 V]', + 'value_id': 'VoltageLNAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x24, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-L Sum [0.1 V]', + 'value_id': 'VoltageLLAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x26, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x28, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x2A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x2C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF L1 [0.001]', + 'value_id': 'PowerFactorL1', + 'start_address': 0x2E, + 'value_type': 'S16', + 'drop_sign': True, # negative values correspond to capacitive load, positive value correspond to inductive load + 'scale_factor': 0.001, + }, + { + 'name': 'PF L2 [0.001]', + 'value_id': 'PowerFactorL2', + 'start_address': 0x2F, + 'value_type': 'S16', + 'drop_sign': True, # negative values correspond to capacitive load, positive value correspond to inductive load + 'scale_factor': 0.001, + }, + { + 'name': 'PF L3 [0.001]', + 'value_id': 'PowerFactorL3', + 'start_address': 0x30, + 'value_type': 'S16', + 'drop_sign': True, # negative values correspond to capacitive load, positive value correspond to inductive load + 'scale_factor': 0.001, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSum', + 'start_address': 0x31, + 'value_type': 'S16', + 'drop_sign': True, # negative values correspond to capacitive load, positive value correspond to inductive load + 'scale_factor': 0.001, + }, + { + 'name': 'Hz [0.1 Hz]', + 'value_id': 'FrequencyLAvg', + 'start_address': 0x33, + 'value_type': 'U16', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x34, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x36, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L1 [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x40, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L2 [0.1 kWh]', + 'value_id': 'EnergyActiveL2Import', # FIXME: direction? + 'start_address': 0x42, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L3 [0.1 kWh]', + 'value_id': 'EnergyActiveL3Import', # FIXME: direction? + 'start_address': 0x44, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumExport', # FIXME: direction? + 'start_address': 0x4E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(-) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumCapacitive', # FIXME: direction? + 'start_address': 0x50, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + ], + }, + { + 'name': 'Carlo Gavazzi EM100 and ET100 At L1', + 'register_type': 'InputRegister', + 'values': make_em100_and_et100_single_phase_values('L1') + }, + { + 'name': 'Carlo Gavazzi EM100 and ET100 At L2', + 'register_type': 'InputRegister', + 'values': make_em100_and_et100_single_phase_values('L2') + }, + { + 'name': 'Carlo Gavazzi EM100 and ET100 At L3', + 'register_type': 'InputRegister', + 'values': make_em100_and_et100_single_phase_values('L3') + }, + { + 'name': 'Carlo Gavazzi EM210', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'V L1-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-N [0.1 V]', + 'value_id': 'VoltageL2N', + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-N [0.1 V]', + 'value_id': 'VoltageL3N', + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L1-L2 [0.1 V]', + 'value_id': 'VoltageL1L2', + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-L3 [0.1 V]', + 'value_id': 'VoltageL2L3', + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-L1 [0.1 V]', + 'value_id': 'VoltageL3L1', + 'start_address': 0x0A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x0C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x0E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W L1 [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x12, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L2 [0.1 W]', + 'value_id': 'PowerActiveL2ImExDiff', # FIXME: direction? + 'start_address': 0x14, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L3 [0.1 W]', + 'value_id': 'PowerActiveL3ImExDiff', # FIXME: direction? + 'start_address': 0x16, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L1 [0.1 VA]', + 'value_id': 'PowerApparentL1ImExDiff', # FIXME: direction? + 'start_address': 0x18, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L2 [0.1 VA]', + 'value_id': 'PowerApparentL2ImExDiff', # FIXME: direction? + 'start_address': 0x1A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L3 [0.1 VA]', + 'value_id': 'PowerApparentL3ImExDiff', # FIXME: direction? + 'start_address': 0x1C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L1 [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x1E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L2 [0.1 var]', + 'value_id': 'PowerReactiveL2IndCapDiff', # FIXME: direction? + 'start_address': 0x20, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L3 [0.1 var]', + 'value_id': 'PowerReactiveL3IndCapDiff', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-N Sum [0.1 V]', + 'value_id': 'VoltageLNAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x24, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-L Sum [0.1 V]', + 'value_id': 'VoltageLLAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x26, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x28, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x2A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x2C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF L1 [0.001]', + 'value_id': 'PowerFactorL1Directional', + 'start_address': 0x2E, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L2 [0.001]', + 'value_id': 'PowerFactorL2Directional', + 'start_address': 0x2F, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L3 [0.001]', + 'value_id': 'PowerFactorL3Directional', + 'start_address': 0x30, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSumDirectional', + 'start_address': 0x31, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'Hz [0.1 Hz]', + 'value_id': 'FrequencyLAvg', + 'start_address': 0x33, + 'value_type': 'U16', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x34, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x36, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumExport', # FIXME: direction? + 'start_address': 0x4E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + ], + }, + { + 'name': 'Carlo Gavazzi EM270 and EM280 Meter', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'V L1-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-N [0.1 V]', + 'value_id': 'VoltageL2N', + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-N [0.1 V]', + 'value_id': 'VoltageL3N', + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L1-L2 [0.1 V]', + 'value_id': 'VoltageL1L2', + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-L3 [0.1 V]', + 'value_id': 'VoltageL2L3', + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-L1 [0.1 V]', + 'value_id': 'VoltageL3L1', + 'start_address': 0x0A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x0C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x0E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x14, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x16, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x18, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x1A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSumDirectional', + 'start_address': 0x31, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + ], + }, + { + 'name': 'Carlo Gavazzi EM270 and EM280 Current Transformer 1', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x010C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x010E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x0110, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W L1 [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x0112, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L2 [0.1 W]', + 'value_id': 'PowerActiveL2ImExDiff', # FIXME: direction? + 'start_address': 0x0114, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L3 [0.1 W]', + 'value_id': 'PowerActiveL3ImExDiff', # FIXME: direction? + 'start_address': 0x0116, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x0118, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x011A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x011C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x011E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x0120, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L1 [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x012A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L2 [0.1 kWh]', + 'value_id': 'EnergyActiveL2Import', # FIXME: direction? + 'start_address': 0x012C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L3 [0.1 kWh]', + 'value_id': 'EnergyActiveL3Import', # FIXME: direction? + 'start_address': 0x012E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L1 [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x013C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L2 [0.1 var]', + 'value_id': 'PowerReactiveL2IndCapDiff', # FIXME: direction? + 'start_address': 0x013E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L3 [0.1 var]', + 'value_id': 'PowerReactiveL3IndCapDiff', # FIXME: direction? + 'start_address': 0x0140, + 'value_type': 'S32LE', + }, + { + 'name': 'PF L1 [0.001]', + 'value_id': 'PowerFactorL1Directional', + 'start_address': 0x0142, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L2 [0.001]', + 'value_id': 'PowerFactorL2Directional', + 'start_address': 0x0144, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L3 [0.001]', + 'value_id': 'PowerFactorL3Directional', + 'start_address': 0x0146, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSumDirectional', + 'start_address': 0x0148, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + ], + }, + { + 'name': 'Carlo Gavazzi EM270 and EM280 Current Transformer 2', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x020C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x020E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x0210, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W L1 [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x0212, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L2 [0.1 W]', + 'value_id': 'PowerActiveL2ImExDiff', # FIXME: direction? + 'start_address': 0x0214, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L3 [0.1 W]', + 'value_id': 'PowerActiveL3ImExDiff', # FIXME: direction? + 'start_address': 0x0216, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x0218, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x021A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x021C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x021E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x0220, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L1 [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x022A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L2 [0.1 kWh]', + 'value_id': 'EnergyActiveL2Import', # FIXME: direction? + 'start_address': 0x022C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L3 [0.1 kWh]', + 'value_id': 'EnergyActiveL3Import', # FIXME: direction? + 'start_address': 0x022E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L1 [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x023C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L2 [0.1 var]', + 'value_id': 'PowerReactiveL2IndCapDiff', # FIXME: direction? + 'start_address': 0x023E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L3 [0.1 var]', + 'value_id': 'PowerReactiveL3IndCapDiff', # FIXME: direction? + 'start_address': 0x0240, + 'value_type': 'S32LE', + }, + { + 'name': 'PF L1 [0.001]', + 'value_id': 'PowerFactorL1Directional', + 'start_address': 0x0242, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L2 [0.001]', + 'value_id': 'PowerFactorL2Directional', + 'start_address': 0x0244, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L3 [0.001]', + 'value_id': 'PowerFactorL3Directional', + 'start_address': 0x0246, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSumDirectional', + 'start_address': 0x0248, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + ], + }, + { + 'name': 'Carlo Gavazzi EM300', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'V L1-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-N [0.1 V]', + 'value_id': 'VoltageL2N', + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-N [0.1 V]', + 'value_id': 'VoltageL3N', + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L1-L2 [0.1 V]', + 'value_id': 'VoltageL1L2', + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-L3 [0.1 V]', + 'value_id': 'VoltageL2L3', + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-L1 [0.1 V]', + 'value_id': 'VoltageL3L1', + 'start_address': 0x0A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x0C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x0E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W L1 [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x12, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L2 [0.1 W]', + 'value_id': 'PowerActiveL2ImExDiff', # FIXME: direction? + 'start_address': 0x14, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L3 [0.1 W]', + 'value_id': 'PowerActiveL3ImExDiff', # FIXME: direction? + 'start_address': 0x16, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L1 [0.1 VA]', + 'value_id': 'PowerApparentL1ImExDiff', # FIXME: direction? + 'start_address': 0x18, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L2 [0.1 VA]', + 'value_id': 'PowerApparentL2ImExDiff', # FIXME: direction? + 'start_address': 0x1A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L3 [0.1 VA]', + 'value_id': 'PowerApparentL3ImExDiff', # FIXME: direction? + 'start_address': 0x1C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L1 [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x1E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L2 [0.1 var]', + 'value_id': 'PowerReactiveL2IndCapDiff', # FIXME: direction? + 'start_address': 0x20, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L3 [0.1 var]', + 'value_id': 'PowerReactiveL3IndCapDiff', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-N Sum [0.1 V]', + 'value_id': 'VoltageLNAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x24, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-L Sum [0.1 V]', + 'value_id': 'VoltageLLAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x26, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x28, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x2A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x2C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF L1 [0.001]', + 'value_id': 'PowerFactorL1Directional', + 'start_address': 0x2E, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L2 [0.001]', + 'value_id': 'PowerFactorL2Directional', + 'start_address': 0x2F, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L3 [0.001]', + 'value_id': 'PowerFactorL3Directional', + 'start_address': 0x30, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSumDirectional', + 'start_address': 0x31, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'Hz [0.1 Hz]', + 'value_id': 'FrequencyLAvg', + 'start_address': 0x33, + 'value_type': 'U16', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x34, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x36, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L1 [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x40, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L2 [0.1 kWh]', + 'value_id': 'EnergyActiveL2Import', # FIXME: direction? + 'start_address': 0x42, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L3 [0.1 kWh]', + 'value_id': 'EnergyActiveL3Import', # FIXME: direction? + 'start_address': 0x44, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumExport', # FIXME: direction? + 'start_address': 0x4E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(-) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumCapacitive', # FIXME: direction? + 'start_address': 0x50, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + ], + }, + { + 'name': 'Carlo Gavazzi ET300', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'V L1-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-N [0.1 V]', + 'value_id': 'VoltageL2N', + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-N [0.1 V]', + 'value_id': 'VoltageL3N', + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L1-L2 [0.1 V]', + 'value_id': 'VoltageL1L2', + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-L3 [0.1 V]', + 'value_id': 'VoltageL2L3', + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-L1 [0.1 V]', + 'value_id': 'VoltageL3L1', + 'start_address': 0x0A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x0C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x0E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W L1 [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x12, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L2 [0.1 W]', + 'value_id': 'PowerActiveL2ImExDiff', # FIXME: direction? + 'start_address': 0x14, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L3 [0.1 W]', + 'value_id': 'PowerActiveL3ImExDiff', # FIXME: direction? + 'start_address': 0x16, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L1 [0.1 VA]', + 'value_id': 'PowerApparentL1ImExDiff', # FIXME: direction? + 'start_address': 0x18, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L2 [0.1 VA]', + 'value_id': 'PowerApparentL2ImExDiff', # FIXME: direction? + 'start_address': 0x1A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L3 [0.1 VA]', + 'value_id': 'PowerApparentL3ImExDiff', # FIXME: direction? + 'start_address': 0x1C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L1 [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x1E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L2 [0.1 var]', + 'value_id': 'PowerReactiveL2IndCapDiff', # FIXME: direction? + 'start_address': 0x20, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L3 [0.1 var]', + 'value_id': 'PowerReactiveL3IndCapDiff', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-N Sum [0.1 V]', + 'value_id': 'VoltageLNAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x24, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-L Sum [0.1 V]', + 'value_id': 'VoltageLLAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x26, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x28, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x2A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x2C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF L1 [0.001]', + 'value_id': 'PowerFactorL1Directional', + 'start_address': 0x2E, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L2 [0.001]', + 'value_id': 'PowerFactorL2Directional', + 'start_address': 0x2F, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L3 [0.001]', + 'value_id': 'PowerFactorL3Directional', + 'start_address': 0x30, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSumDirectional', + 'start_address': 0x31, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'Hz [0.1 Hz]', + 'value_id': 'FrequencyLAvg', + 'start_address': 0x33, + 'value_type': 'U16', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x34, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x36, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L1 [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x40, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L2 [0.1 kWh]', + 'value_id': 'EnergyActiveL2Import', # FIXME: direction? + 'start_address': 0x42, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L3 [0.1 kWh]', + 'value_id': 'EnergyActiveL3Import', # FIXME: direction? + 'start_address': 0x44, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumExport', # FIXME: direction? + 'start_address': 0x4E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(-) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumCapacitive', # FIXME: direction? + 'start_address': 0x50, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) L1 [0.1 kWh]', + 'value_id': 'EnergyActiveL1Export', # FIXME: direction? + 'start_address': 0x60, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) L2 [0.1 kWh]', + 'value_id': 'EnergyActiveL2Export', # FIXME: direction? + 'start_address': 0x62, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) L3 [0.1 kWh]', + 'value_id': 'EnergyActiveL3Export', # FIXME: direction? + 'start_address': 0x64, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + ], + }, + { + 'name': 'Carlo Gavazzi EM510 at L1', + 'register_type': 'InputRegister', + 'values': make_em510_single_phase_values('L1') + }, + { + 'name': 'Carlo Gavazzi EM510 at L2', + 'register_type': 'InputRegister', + 'values': make_em510_single_phase_values('L2') + }, + { + 'name': 'Carlo Gavazzi EM510 at L3', + 'register_type': 'InputRegister', + 'values': make_em510_single_phase_values('L3') + }, + { + 'name': 'Carlo Gavazzi EM530 and EM540', + 'register_type': 'InputRegister', + 'values': [ + { + 'name': 'V L1-N [0.1 V]', + 'value_id': 'VoltageL1N', + 'start_address': 0x00, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-N [0.1 V]', + 'value_id': 'VoltageL2N', + 'start_address': 0x02, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-N [0.1 V]', + 'value_id': 'VoltageL3N', + 'start_address': 0x04, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L1-L2 [0.1 V]', + 'value_id': 'VoltageL1L2', + 'start_address': 0x06, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L2-L3 [0.1 V]', + 'value_id': 'VoltageL2L3', + 'start_address': 0x08, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L3-L1 [0.1 V]', + 'value_id': 'VoltageL3L1', + 'start_address': 0x0A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'A L1 [0.001 A]', + 'value_id': 'CurrentL1ImExDiff', # FIXME: direction? + 'start_address': 0x0C, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L2 [0.001 A]', + 'value_id': 'CurrentL2ImExDiff', # FIXME: direction? + 'start_address': 0x0E, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'A L3 [0.001 A]', + 'value_id': 'CurrentL3ImExDiff', # FIXME: direction? + 'start_address': 0x10, + 'value_type': 'S32LE', + 'scale_factor': 0.001, + }, + { + 'name': 'W L1 [0.1 W]', + 'value_id': 'PowerActiveL1ImExDiff', # FIXME: direction? + 'start_address': 0x12, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L2 [0.1 W]', + 'value_id': 'PowerActiveL2ImExDiff', # FIXME: direction? + 'start_address': 0x14, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W L3 [0.1 W]', + 'value_id': 'PowerActiveL3ImExDiff', # FIXME: direction? + 'start_address': 0x16, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L1 [0.1 VA]', + 'value_id': 'PowerApparentL1ImExDiff', # FIXME: direction? + 'start_address': 0x18, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L2 [0.1 VA]', + 'value_id': 'PowerApparentL2ImExDiff', # FIXME: direction? + 'start_address': 0x1A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA L3 [0.1 VA]', + 'value_id': 'PowerApparentL3ImExDiff', # FIXME: direction? + 'start_address': 0x1C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L1 [0.1 var]', + 'value_id': 'PowerReactiveL1IndCapDiff', # FIXME: direction? + 'start_address': 0x1E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L2 [0.1 var]', + 'value_id': 'PowerReactiveL2IndCapDiff', # FIXME: direction? + 'start_address': 0x20, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var L3 [0.1 var]', + 'value_id': 'PowerReactiveL3IndCapDiff', # FIXME: direction? + 'start_address': 0x22, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-N Sum [0.1 V]', + 'value_id': 'VoltageLNAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x24, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'V L-L Sum [0.1 V]', + 'value_id': 'VoltageLLAvg', # FIXME: datasheet says sum, but average would make more sense + 'start_address': 0x26, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'W Sum [0.1 W]', + 'value_id': 'PowerActiveLSumImExDiff', # FIXME: direction? + 'start_address': 0x28, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'VA Sum [0.1 VA]', + 'value_id': 'PowerApparentLSumImExDiff', # FIXME: direction? + 'start_address': 0x2A, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'var Sum [0.1 var]', + 'value_id': 'PowerReactiveLSumIndCapDiff', # FIXME: direction? + 'start_address': 0x2C, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'PF L1 [0.001]', + 'value_id': 'PowerFactorL1Directional', + 'start_address': 0x2E, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L2 [0.001]', + 'value_id': 'PowerFactorL2Directional', + 'start_address': 0x2F, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF L3 [0.001]', + 'value_id': 'PowerFactorL3Directional', + 'start_address': 0x30, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'PF Sum [0.001]', + 'value_id': 'PowerFactorLSumDirectional', + 'start_address': 0x31, + 'value_type': 'S16', + 'scale_factor': 0.001, + }, + { + 'name': 'Hz [0.1 Hz]', + 'value_id': 'FrequencyLAvg', + 'start_address': 0x33, + 'value_type': 'U16', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumImport', # FIXME: direction? + 'start_address': 0x34, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(+) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumInductive', # FIXME: direction? + 'start_address': 0x36, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L1 [0.1 kWh]', + 'value_id': 'EnergyActiveL1Import', # FIXME: direction? + 'start_address': 0x40, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L2 [0.1 kWh]', + 'value_id': 'EnergyActiveL2Import', # FIXME: direction? + 'start_address': 0x42, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(+) L3 [0.1 kWh]', + 'value_id': 'EnergyActiveL3Import', # FIXME: direction? + 'start_address': 0x44, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kWh(-) Total [0.1 kWh]', + 'value_id': 'EnergyActiveLSumExport', # FIXME: direction? + 'start_address': 0x4E, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kvarh(-) Total [0.1 kvarh]', + 'value_id': 'EnergyReactiveLSumCapacitive', # FIXME: direction? + 'start_address': 0x50, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'kVAh Total [0.1 kVAh]', + 'value_id': 'EnergyApparentLSumImExSum', # FIXME: sum? + 'start_address': 0x56, + 'value_type': 'S32LE', + 'scale_factor': 0.1, + }, + { + 'name': 'THD A L1 [0.01 %]', + 'value_id': 'CurrentTHDL1', + 'start_address': 0x82, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD A L2 [0.01 %]', + 'value_id': 'CurrentTHDL2', + 'start_address': 0x84, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD A L3 [0.01 %]', + 'value_id': 'CurrentTHDL3', + 'start_address': 0x86, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD V L1-N [%]', + 'value_id': 'VoltageTHDL1N', + 'start_address': 0x8A, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD V L2-N [%]', + 'value_id': 'VoltageTHDL2N', + 'start_address': 0x8C, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD V L3-N [%]', + 'value_id': 'VoltageTHDL3N', + 'start_address': 0x8E, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD V L1-L2 [%]', + 'value_id': 'VoltageTHDL1L2', + 'start_address': 0x92, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD V L2-L3 [%]', + 'value_id': 'VoltageTHDL2L3', + 'start_address': 0x94, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + { + 'name': 'THD V L3-L1 [%]', + 'value_id': 'VoltageTHDL3L1', + 'start_address': 0x96, + 'value_type': 'S32LE', + 'scale_factor': 0.01, + }, + ], + }, +] diff --git a/software/src/modules/meters_modbus_tcp/meter_modbus_tcp.cpp b/software/src/modules/meters_modbus_tcp/meter_modbus_tcp.cpp index 7e221989b..eeb0952d7 100644 --- a/software/src/modules/meters_modbus_tcp/meter_modbus_tcp.cpp +++ b/software/src/modules/meters_modbus_tcp/meter_modbus_tcp.cpp @@ -75,6 +75,13 @@ #define FRONIUS_GEN24_PLUS_HYBRID_INVERTER_CHASTATE_ADDRESS NUMBER_TO_ADDRESS(40352u) #define FRONIUS_GEN24_PLUS_HYBRID_INVERTER_CHASTATE_SF_ADDRESS NUMBER_TO_ADDRESS(40366u) +#define CARLO_GAVAZZI_EM100_OR_ET100_W 0x04 +#define CARLO_GAVAZZI_EM100_OR_ET100_KWH_PLUS_TOTAL 0x10 +#define CARLO_GAVAZZI_EM100_OR_ET100_KWH_MINUS_TOTAL 0x20 +#define CARLO_GAVAZZI_EM510_W 0x04 +#define CARLO_GAVAZZI_EM510_KWH_PLUS_TOTAL 0x10 +#define CARLO_GAVAZZI_EM510_KWH_MINUS_TOTAL 0x20 + #define MODBUS_VALUE_TYPE_TO_REGISTER_COUNT(x) (static_cast(x) & 0x07) #define MODBUS_VALUE_TYPE_TO_REGISTER_ORDER_LE(x) ((static_cast(x) >> 5) & 1) @@ -152,6 +159,7 @@ void MeterModbusTCP::setup(const Config &ephemeral_config) customs_specs[i].register_type = registers->get(i)->get("rtype")->asEnum(); customs_specs[i].start_address = registers->get(i)->get("addr")->asUint(); customs_specs[i].value_type = registers->get(i)->get("vtype")->asEnum(); + customs_specs[i].drop_sign = false; // FIXME: expose in API? customs_specs[i].offset = registers->get(i)->get("off")->asFloat(); customs_specs[i].scale_factor = registers->get(i)->get("scale")->asFloat(); @@ -708,6 +716,190 @@ void MeterModbusTCP::setup(const Config &ephemeral_config) table = &siemens_pac4220_table; break; + case MeterModbusTCPTableID::CarloGavazziEM24DIN: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 11)); + table = &carlo_gavazzi_em24_din_table; + break; + + case MeterModbusTCPTableID::CarloGavazziEM24E1: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + table = &carlo_gavazzi_em24_e1_table; + break; + + case MeterModbusTCPTableID::CarloGavazziEM100: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + carlo_gavazzi_em100_phase = ephemeral_config.get("table")->get()->get("phase")->asEnum(); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 50)); + + switch (carlo_gavazzi_em100_phase) { + case CarloGavazziPhase::None: + logger.printfln("No Carlo Gavazzi EM100 Phase selected"); + return; + + case CarloGavazziPhase::L1: + table = &carlo_gavazzi_em100_and_et100_at_l1_table; + break; + + case CarloGavazziPhase::L2: + table = &carlo_gavazzi_em100_and_et100_at_l2_table; + break; + + case CarloGavazziPhase::L3: + table = &carlo_gavazzi_em100_and_et100_at_l3_table; + break; + + default: + logger.printfln("Unknown Carlo Gavazzi EM100 Phase: %u", static_cast(carlo_gavazzi_em100_phase)); + return; + } + + break; + + case MeterModbusTCPTableID::CarloGavazziET100: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + carlo_gavazzi_et100_phase = ephemeral_config.get("table")->get()->get("phase")->asEnum(); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 50)); + + switch (carlo_gavazzi_et100_phase) { + case CarloGavazziPhase::None: + logger.printfln("No Carlo Gavazzi ET100 Phase selected"); + return; + + case CarloGavazziPhase::L1: + table = &carlo_gavazzi_em100_and_et100_at_l1_table; + break; + + case CarloGavazziPhase::L2: + table = &carlo_gavazzi_em100_and_et100_at_l2_table; + break; + + case CarloGavazziPhase::L3: + table = &carlo_gavazzi_em100_and_et100_at_l3_table; + break; + + default: + logger.printfln("Unknown Carlo Gavazzi ET100 Phase: %u", static_cast(carlo_gavazzi_et100_phase)); + return; + } + + break; + + case MeterModbusTCPTableID::CarloGavazziEM210: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 61)); + table = &carlo_gavazzi_em210_table; + break; + + case MeterModbusTCPTableID::CarloGavazziEM270: + carlo_gavazzi_em270_virtual_meter = ephemeral_config.get("table")->get()->get("virtual_meter")->asEnum(); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 18)); + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + + switch (carlo_gavazzi_em270_virtual_meter) { + case CarloGavazziEM270VirtualMeter::None: + logger.printfln("No Carlo Gavazzi EM270 Virtual Meter selected"); + return; + + case CarloGavazziEM270VirtualMeter::Meter: + table = &carlo_gavazzi_em270_and_em280_meter_table; + break; + + case CarloGavazziEM270VirtualMeter::CurrentTransformer1: + table = &carlo_gavazzi_em270_and_em280_current_transformer_1_table; + break; + + case CarloGavazziEM270VirtualMeter::CurrentTransformer2: + table = &carlo_gavazzi_em270_and_em280_current_transformer_2_table; + break; + + default: + logger.printfln("Unknown Carlo Gavazzi EM270 Virtual Meter: %u", static_cast(carlo_gavazzi_em270_virtual_meter)); + return; + } + + break; + + case MeterModbusTCPTableID::CarloGavazziEM280: + carlo_gavazzi_em280_virtual_meter = ephemeral_config.get("table")->get()->get("virtual_meter")->asEnum(); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 18)); + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + + switch (carlo_gavazzi_em280_virtual_meter) { + case CarloGavazziEM280VirtualMeter::None: + logger.printfln("No Carlo Gavazzi EM280 Virtual Meter selected"); + return; + + case CarloGavazziEM280VirtualMeter::Meter: + table = &carlo_gavazzi_em270_and_em280_meter_table; + break; + + case CarloGavazziEM280VirtualMeter::CurrentTransformer1: + table = &carlo_gavazzi_em270_and_em280_current_transformer_1_table; + break; + + case CarloGavazziEM280VirtualMeter::CurrentTransformer2: + table = &carlo_gavazzi_em270_and_em280_current_transformer_2_table; + break; + + default: + logger.printfln("Unknown Carlo Gavazzi EM280 Virtual Meter: %u", static_cast(carlo_gavazzi_em280_virtual_meter)); + return; + } + + break; + + case MeterModbusTCPTableID::CarloGavazziEM300: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 50)); + table = &carlo_gavazzi_em300_table; + break; + + case MeterModbusTCPTableID::CarloGavazziET300: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 50)); + table = &carlo_gavazzi_et300_table; + break; + + case MeterModbusTCPTableID::CarloGavazziEM510: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + carlo_gavazzi_em510_phase = ephemeral_config.get("table")->get()->get("phase")->asEnum(); + max_register_count = static_cast(std::min(METER_MODBUS_TCP_REGISTER_BUFFER_SIZE, 50)); + + switch (carlo_gavazzi_em510_phase) { + case CarloGavazziPhase::None: + logger.printfln("No Carlo Gavazzi EM510 Phase selected"); + return; + + case CarloGavazziPhase::L1: + table = &carlo_gavazzi_em510_at_l1_table; + break; + + case CarloGavazziPhase::L2: + table = &carlo_gavazzi_em510_at_l2_table; + break; + + case CarloGavazziPhase::L3: + table = &carlo_gavazzi_em510_at_l3_table; + break; + + default: + logger.printfln("Unknown Carlo Gavazzi EM510 Phase: %u", static_cast(carlo_gavazzi_em510_phase)); + return; + } + + break; + + case MeterModbusTCPTableID::CarloGavazziEM530: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + table = &carlo_gavazzi_em530_and_em540_table; + break; + + case MeterModbusTCPTableID::CarloGavazziEM540: + device_address = static_cast(ephemeral_config.get("table")->get()->get("device_address")->asUint()); + table = &carlo_gavazzi_em530_and_em540_table; + break; + default: logger.printfln("Unknown table: %u", static_cast(table_id)); return; @@ -800,7 +992,7 @@ void MeterModbusTCP::read_next() for (size_t i = read_index + 1; i < table->specs_length; ++i) { if (generic_read_request.register_type == table->specs[i].register_type && generic_read_request.start_address + generic_read_request.register_count == table->specs[i].start_address - && generic_read_request.register_count + MODBUS_VALUE_TYPE_TO_REGISTER_COUNT(table->specs[i].value_type) <= METER_MODBUS_TCP_REGISTER_BUFFER_SIZE) { + && generic_read_request.register_count + MODBUS_VALUE_TYPE_TO_REGISTER_COUNT(table->specs[i].value_type) <= max_register_count) { generic_read_request.register_count += MODBUS_VALUE_TYPE_TO_REGISTER_COUNT(table->specs[i].value_type); continue; } @@ -868,6 +1060,17 @@ bool MeterModbusTCP::is_fronius_gen24_plus_hybrid_inverter_battery_meter() const && fronius_gen24_plus_hybrid_inverter_virtual_meter == FroniusGEN24PlusHybridInverterVirtualMeter::Battery; } +bool MeterModbusTCP::is_carlo_gavazzi_em100_or_et100() const +{ + return table_id == MeterModbusTCPTableID::CarloGavazziEM100 + || table_id == MeterModbusTCPTableID::CarloGavazziET100; +} + +bool MeterModbusTCP::is_carlo_gavazzi_em510() const +{ + return table_id == MeterModbusTCPTableID::CarloGavazziEM510; +} + void MeterModbusTCP::read_done_callback() { if (generic_read_request.result != TFModbusTCPClientTransactionResult::Success) { @@ -1171,6 +1374,10 @@ void MeterModbusTCP::read_done_callback() break; } + if (table->specs[read_index].drop_sign) { + value = fabs(value); + } + value += table->specs[read_index].offset; #if defined(__GNUC__) @@ -1337,6 +1544,20 @@ void MeterModbusTCP::read_done_callback() meters.update_value(slot, table->index[read_index + 6], energy_discharge); } } + else if (is_carlo_gavazzi_em100_or_et100()) { + if (register_start_address == CARLO_GAVAZZI_EM100_OR_ET100_W + || register_start_address == CARLO_GAVAZZI_EM100_OR_ET100_KWH_PLUS_TOTAL + || register_start_address == CARLO_GAVAZZI_EM100_OR_ET100_KWH_MINUS_TOTAL) { + meters.update_value(slot, table->index[read_index + 1], value); + } + } + else if (is_carlo_gavazzi_em510()) { + if (register_start_address == CARLO_GAVAZZI_EM510_W + || register_start_address == CARLO_GAVAZZI_EM510_KWH_PLUS_TOTAL + || register_start_address == CARLO_GAVAZZI_EM510_KWH_MINUS_TOTAL) { + meters.update_value(slot, table->index[read_index + 1], value); + } + } if (table->index[read_index] != VALUE_INDEX_META && table->index[read_index] != VALUE_INDEX_DEBUG) { meters.update_value(slot, table->index[read_index], value); diff --git a/software/src/modules/meters_modbus_tcp/meter_modbus_tcp.h b/software/src/modules/meters_modbus_tcp/meter_modbus_tcp.h index d5c8b26c7..948454a51 100644 --- a/software/src/modules/meters_modbus_tcp/meter_modbus_tcp.h +++ b/software/src/modules/meters_modbus_tcp/meter_modbus_tcp.h @@ -44,6 +44,9 @@ #include "fronius_gen24_plus_hybrid_inverter_virtual_meter.enum.h" #include "hailei_hybrid_inverter_virtual_meter.enum.h" #include "fox_ess_h3_hybrid_inverter_virtual_meter.enum.h" +#include "carlo_gavazzi_phase.enum.h" +#include "carlo_gavazzi_em270_virtual_meter.enum.h" +#include "carlo_gavazzi_em280_virtual_meter.enum.h" #if defined(__GNUC__) #pragma GCC diagnostic push @@ -61,6 +64,7 @@ class MeterModbusTCP final : protected GenericModbusTCPClient, public IMeter ModbusRegisterType register_type; size_t start_address; ModbusValueType value_type; + bool drop_sign; float offset; float scale_factor; }; @@ -101,6 +105,8 @@ class MeterModbusTCP final : protected GenericModbusTCPClient, public IMeter bool is_deye_hybrid_inverter_battery_meter() const; bool is_shelly_pro_xem_monophase() const; bool is_fronius_gen24_plus_hybrid_inverter_battery_meter() const; + bool is_carlo_gavazzi_em100_or_et100() const; + bool is_carlo_gavazzi_em510() const; uint32_t slot; Config *state; @@ -112,6 +118,7 @@ class MeterModbusTCP final : protected GenericModbusTCPClient, public IMeter bool read_allowed = false; bool values_declared = false; size_t read_index = 0; + size_t max_register_count = METER_MODBUS_TCP_REGISTER_BUFFER_SIZE; uint16_t register_buffer[METER_MODBUS_TCP_REGISTER_BUFFER_SIZE]; size_t register_buffer_index = METER_MODBUS_TCP_REGISTER_BUFFER_SIZE; @@ -182,6 +189,21 @@ class MeterModbusTCP final : protected GenericModbusTCPClient, public IMeter // Fox ESS H3 FoxESSH3HybridInverterVirtualMeter fox_ess_h3_hybrid_inverter_virtual_meter; + + // Carlo Gavazzi EM100 + CarloGavazziPhase carlo_gavazzi_em100_phase; + + // Carlo Gavazzi ET100 + CarloGavazziPhase carlo_gavazzi_et100_phase; + + // Carlo Gavazzi EM270 + CarloGavazziEM270VirtualMeter carlo_gavazzi_em270_virtual_meter; + + // Carlo Gavazzi EM280 + CarloGavazziEM280VirtualMeter carlo_gavazzi_em280_virtual_meter; + + // Carlo Gavazzi EM510 + CarloGavazziPhase carlo_gavazzi_em510_phase; }; #if defined(__GNUC__) diff --git a/software/src/modules/meters_modbus_tcp/meters_modbus_tcp.cpp b/software/src/modules/meters_modbus_tcp/meters_modbus_tcp.cpp index d33a93d03..6b77e740e 100644 --- a/software/src/modules/meters_modbus_tcp/meters_modbus_tcp.cpp +++ b/software/src/modules/meters_modbus_tcp/meters_modbus_tcp.cpp @@ -131,6 +131,37 @@ void MetersModbusTCP::pre_setup() table_prototypes.push_back({MeterModbusTCPTableID::SiemensPAC4200, siemens}); table_prototypes.push_back({MeterModbusTCPTableID::SiemensPAC4220, siemens}); + Config carlo_gavazzi = Config::Object({ + {"device_address", Config::Uint(1, 1, 247)}, + }); + + Config carlo_gavazzi_single_phase = Config::Object({ + {"device_address", Config::Uint(1, 1, 247)}, + {"phase", Config::Uint8(static_cast(CarloGavazziPhase::None))}, + }); + + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM24DIN, carlo_gavazzi}); + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM24E1, carlo_gavazzi}); + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM100, carlo_gavazzi_single_phase}); + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziET100, carlo_gavazzi_single_phase}); + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM210, carlo_gavazzi}); + + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM270, Config::Object({ + {"virtual_meter", Config::Uint8(static_cast(CarloGavazziEM270VirtualMeter::None))}, + {"device_address", Config::Uint(1, 1, 247)}, + })}); + + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM280, Config::Object({ + {"virtual_meter", Config::Uint8(static_cast(CarloGavazziEM280VirtualMeter::None))}, + {"device_address", Config::Uint(1, 1, 247)}, + })}); + + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM300, carlo_gavazzi}); + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziET300, carlo_gavazzi}); + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM510, carlo_gavazzi_single_phase}); + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM530, carlo_gavazzi}); + table_prototypes.push_back({MeterModbusTCPTableID::CarloGavazziEM540, carlo_gavazzi}); + config_prototype = Config::Object({ {"display_name", Config::Str("", 0, 32)}, {"host", Config::Str("", 0, 64)}, diff --git a/software/src/modules/meters_modbus_tcp/prepare.py b/software/src/modules/meters_modbus_tcp/prepare.py index 9faaf68e7..02c330ac1 100644 --- a/software/src/modules/meters_modbus_tcp/prepare.py +++ b/software/src/modules/meters_modbus_tcp/prepare.py @@ -12,6 +12,7 @@ import hailei import fox_ess import siemens +import carlo_gavazzi tfutil.create_parent_module(__file__, 'software') @@ -48,7 +49,8 @@ def make_modbus_value_type(register_count, is_signed, is_float, register_order_i for item in modbus_value_types: f.write(f'{item[0]} = {item[1]}\n') -specs = sungrow.specs + solarmax.specs + victron_energy.specs + deye.specs + alpha_ess.specs + shelly.specs + goodwe.specs + solax.specs + fronius.specs + hailei.specs + fox_ess.specs + siemens.specs +specs = sungrow.specs + solarmax.specs + victron_energy.specs + deye.specs + alpha_ess.specs + shelly.specs + goodwe.specs \ + + solax.specs + fronius.specs + hailei.specs + fox_ess.specs + siemens.specs + carlo_gavazzi.specs spec_values = [] for spec in specs: @@ -82,6 +84,7 @@ def make_modbus_value_type(register_count, is_signed, is_float, register_order_i f' ModbusRegisterType::{value.get("register_type", spec["register_type"])},\n' f' {value["start_address"] - start_address_offset if value["start_address"] != "START_ADDRESS_VIRTUAL" else "START_ADDRESS_VIRTUAL"},\n' f' ModbusValueType::{value.get("value_type", "None")},\n' + f' {"true" if value.get("drop_sign", False) else "false"},\n' f' {value.get("offset", 0.0)}f,\n' f' {value.get("scale_factor", 1.0)}f,\n' ' },' diff --git a/software/web/src/modules/meters_modbus_tcp/plugin_meters_config.tsx b/software/web/src/modules/meters_modbus_tcp/plugin_meters_config.tsx index 7e762983e..1a75313b9 100644 --- a/software/web/src/modules/meters_modbus_tcp/plugin_meters_config.tsx +++ b/software/web/src/modules/meters_modbus_tcp/plugin_meters_config.tsx @@ -41,6 +41,9 @@ import { SolaxHybridInverterVirtualMeter } from "./solax_hybrid_inverter_virtual import { FroniusGEN24PlusHybridInverterVirtualMeter } from "./fronius_gen24_plus_hybrid_inverter_virtual_meter.enum"; import { HaileiHybridInverterVirtualMeter } from "./hailei_hybrid_inverter_virtual_meter.enum"; import { FoxESSH3HybridInverterVirtualMeter } from "./fox_ess_h3_hybrid_inverter_virtual_meter.enum"; +import { CarloGavazziPhase } from "./carlo_gavazzi_phase.enum"; +import { CarloGavazziEM270VirtualMeter } from "./carlo_gavazzi_em270_virtual_meter.enum"; +import { CarloGavazziEM280VirtualMeter } from "./carlo_gavazzi_em280_virtual_meter.enum"; import { InputText } from "../../ts/components/input_text"; import { InputNumber } from "../../ts/components/input_number"; import { InputAnyFloat } from "../../ts/components/input_any_float"; @@ -222,6 +225,95 @@ type TableConfigSiemensPAC4220 = [ }, ]; +type TableConfigCarloGavazziEM24DIN = [ + MeterModbusTCPTableID.CarloGavazziEM24DIN, + { + device_address: number; + }, +]; + +type TableConfigCarloGavazziEM24E1 = [ + MeterModbusTCPTableID.CarloGavazziEM24E1, + { + device_address: number; + }, +]; + +type TableConfigCarloGavazziEM100 = [ + MeterModbusTCPTableID.CarloGavazziEM100, + { + device_address: number; + phase: number; + }, +]; + +type TableConfigCarloGavazziET100 = [ + MeterModbusTCPTableID.CarloGavazziET100, + { + device_address: number; + phase: number; + }, +]; + +type TableConfigCarloGavazziEM210 = [ + MeterModbusTCPTableID.CarloGavazziEM210, + { + device_address: number; + }, +]; + +type TableConfigCarloGavazziEM270 = [ + MeterModbusTCPTableID.CarloGavazziEM270, + { + virtual_meter: number; + device_address: number; + }, +]; + +type TableConfigCarloGavazziEM280 = [ + MeterModbusTCPTableID.CarloGavazziEM280, + { + virtual_meter: number; + device_address: number; + }, +]; + +type TableConfigCarloGavazziEM300 = [ + MeterModbusTCPTableID.CarloGavazziEM300, + { + device_address: number; + }, +]; + +type TableConfigCarloGavazziET300 = [ + MeterModbusTCPTableID.CarloGavazziET300, + { + device_address: number; + }, +]; + +type TableConfigCarloGavazziEM510 = [ + MeterModbusTCPTableID.CarloGavazziEM510, + { + device_address: number; + phase: number; + }, +]; + +type TableConfigCarloGavazziEM530 = [ + MeterModbusTCPTableID.CarloGavazziEM530, + { + device_address: number; + }, +]; + +type TableConfigCarloGavazziEM540 = [ + MeterModbusTCPTableID.CarloGavazziEM540, + { + device_address: number; + }, +]; + type TableConfig = TableConfigNone | TableConfigCustom | TableConfigSungrowHybridInverter | @@ -242,7 +334,19 @@ type TableConfig = TableConfigNone | TableConfigSiemensPAC3200 | TableConfigSiemensPAC3220 | TableConfigSiemensPAC4200 | - TableConfigSiemensPAC4220; + TableConfigSiemensPAC4220 | + TableConfigCarloGavazziEM24DIN | + TableConfigCarloGavazziEM24E1 | + TableConfigCarloGavazziEM100 | + TableConfigCarloGavazziET100 | + TableConfigCarloGavazziEM210 | + TableConfigCarloGavazziEM270 | + TableConfigCarloGavazziEM280 | + TableConfigCarloGavazziEM300 | + TableConfigCarloGavazziET300 | + TableConfigCarloGavazziEM510 | + TableConfigCarloGavazziEM530 | + TableConfigCarloGavazziEM540; export type ModbusTCPMetersConfig = [ MeterClassID.ModbusTCP, @@ -316,6 +420,42 @@ function new_table_config(table: MeterModbusTCPTableID): TableConfig { case MeterModbusTCPTableID.SiemensPAC4220: return [MeterModbusTCPTableID.SiemensPAC4220, {device_address: 1}]; + case MeterModbusTCPTableID.CarloGavazziEM24DIN: + return [MeterModbusTCPTableID.CarloGavazziEM24DIN, {device_address: 1}]; + + case MeterModbusTCPTableID.CarloGavazziEM24E1: + return [MeterModbusTCPTableID.CarloGavazziEM24E1, {device_address: 1}]; + + case MeterModbusTCPTableID.CarloGavazziEM100: + return [MeterModbusTCPTableID.CarloGavazziEM100, {device_address: 1, phase: null}]; + + case MeterModbusTCPTableID.CarloGavazziET100: + return [MeterModbusTCPTableID.CarloGavazziET100, {device_address: 1, phase: null}]; + + case MeterModbusTCPTableID.CarloGavazziEM210: + return [MeterModbusTCPTableID.CarloGavazziEM210, {device_address: 1}]; + + case MeterModbusTCPTableID.CarloGavazziEM270: + return [MeterModbusTCPTableID.CarloGavazziEM270, {virtual_meter: null, device_address: 1}]; + + case MeterModbusTCPTableID.CarloGavazziEM280: + return [MeterModbusTCPTableID.CarloGavazziEM280, {virtual_meter: null, device_address: 1}]; + + case MeterModbusTCPTableID.CarloGavazziEM300: + return [MeterModbusTCPTableID.CarloGavazziEM300, {device_address: 1}]; + + case MeterModbusTCPTableID.CarloGavazziET300: + return [MeterModbusTCPTableID.CarloGavazziET300, {device_address: 1}]; + + case MeterModbusTCPTableID.CarloGavazziEM510: + return [MeterModbusTCPTableID.CarloGavazziEM510, {device_address: 1, phase: null}]; + + case MeterModbusTCPTableID.CarloGavazziEM530: + return [MeterModbusTCPTableID.CarloGavazziEM530, {device_address: 1}]; + + case MeterModbusTCPTableID.CarloGavazziEM540: + return [MeterModbusTCPTableID.CarloGavazziEM540, {device_address: 1}]; + default: return [MeterModbusTCPTableID.None, {}]; } @@ -527,6 +667,18 @@ export function init() { items={[ // Keep alphabetically sorted [MeterModbusTCPTableID.AlphaESSHybridInverter.toString(), __("meters_modbus_tcp.content.table_alpha_ess_hybrid_inverter")], + [MeterModbusTCPTableID.CarloGavazziEM24DIN.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em24_din")], + [MeterModbusTCPTableID.CarloGavazziEM24E1.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em24_e1")], + [MeterModbusTCPTableID.CarloGavazziEM100.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em100")], + [MeterModbusTCPTableID.CarloGavazziET100.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_et100")], + [MeterModbusTCPTableID.CarloGavazziEM210.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em210")], + [MeterModbusTCPTableID.CarloGavazziEM270.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em270")], + [MeterModbusTCPTableID.CarloGavazziEM280.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em280")], + [MeterModbusTCPTableID.CarloGavazziEM300.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em300")], + [MeterModbusTCPTableID.CarloGavazziET300.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_et300")], + [MeterModbusTCPTableID.CarloGavazziEM510.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em510")], + [MeterModbusTCPTableID.CarloGavazziEM530.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em530")], + [MeterModbusTCPTableID.CarloGavazziEM540.toString(), __("meters_modbus_tcp.content.table_carlo_gavazzi_em540")], [MeterModbusTCPTableID.DeyeHybridInverter.toString(), __("meters_modbus_tcp.content.table_deye_hybrid_inverter")], [MeterModbusTCPTableID.FoxESSH3HybridInverter.toString(), __("meters_modbus_tcp.content.table_fox_ess_h3_hybrid_inverter")], [MeterModbusTCPTableID.FroniusGEN24PlusHybridInverter.toString(), __("meters_modbus_tcp.content.table_fronius_gen24_plus_hybrid_inverter")], @@ -574,7 +726,19 @@ export function init() { || config[1].table[0] == MeterModbusTCPTableID.SiemensPAC3200 || config[1].table[0] == MeterModbusTCPTableID.SiemensPAC3220 || config[1].table[0] == MeterModbusTCPTableID.SiemensPAC4200 - || config[1].table[0] == MeterModbusTCPTableID.SiemensPAC4220)) { + || config[1].table[0] == MeterModbusTCPTableID.SiemensPAC4220 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM24DIN + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM24E1 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM100 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziET100 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM210 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM270 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM280 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM300 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziET300 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM510 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM530 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM540)) { let virtual_meter_items: [string, string][] = []; let device_address_default: number = 1; @@ -669,6 +833,20 @@ export function init() { device_address_default = 247; } + else if (config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM270) { + virtual_meter_items = [ + [CarloGavazziEM270VirtualMeter.Meter.toString(), __("meters_modbus_tcp.content.virtual_meter_meter")], + [CarloGavazziEM270VirtualMeter.CurrentTransformer1.toString(), __("meters_modbus_tcp.content.virtual_meter_current_transformer_1")], + [CarloGavazziEM270VirtualMeter.CurrentTransformer2.toString(), __("meters_modbus_tcp.content.virtual_meter_current_transformer_2")], + ]; + } + else if (config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM280) { + virtual_meter_items = [ + [CarloGavazziEM280VirtualMeter.Meter.toString(), __("meters_modbus_tcp.content.virtual_meter_meter")], + [CarloGavazziEM280VirtualMeter.CurrentTransformer1.toString(), __("meters_modbus_tcp.content.virtual_meter_current_transformer_1")], + [CarloGavazziEM280VirtualMeter.CurrentTransformer2.toString(), __("meters_modbus_tcp.content.virtual_meter_current_transformer_2")], + ]; + } if (virtual_meter_items.length > 0) { edit_children.push( @@ -759,6 +937,26 @@ export function init() { }} /> ); } + + if (config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM100 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziET100 + || config[1].table[0] == MeterModbusTCPTableID.CarloGavazziEM510) { + edit_children.push( + + { + on_config(util.get_updated_union(config, {table: util.get_updated_union(config[1].table, {phase: parseInt(v)})})); + }} /> + ); + } } else if (util.hasValue(config[1].table) && config[1].table[0] == MeterModbusTCPTableID.Custom) { diff --git a/software/web/src/modules/meters_modbus_tcp/translation_de.tsx b/software/web/src/modules/meters_modbus_tcp/translation_de.tsx index d11d721aa..610361261 100644 --- a/software/web/src/modules/meters_modbus_tcp/translation_de.tsx +++ b/software/web/src/modules/meters_modbus_tcp/translation_de.tsx @@ -36,6 +36,18 @@ let x = { "table_siemens_pac3220": "Siemens PAC3220", "table_siemens_pac4200": "Siemens PAC4200", "table_siemens_pac4220": "Siemens PAC4220", + "table_carlo_gavazzi_em24_din": "Carlo Gavazzi EM24-DIN", + "table_carlo_gavazzi_em24_e1": "Carlo Gavazzi EM24-E1", + "table_carlo_gavazzi_em100": "Carlo Gavazzi EM100", + "table_carlo_gavazzi_et100": "Carlo Gavazzi ET100", + "table_carlo_gavazzi_em210": "Carlo Gavazzi EM210", + "table_carlo_gavazzi_em270": "Carlo Gavazzi EM270", + "table_carlo_gavazzi_em280": "Carlo Gavazzi EM280", + "table_carlo_gavazzi_em300": "Carlo Gavazzi EM300", + "table_carlo_gavazzi_et300": "Carlo Gavazzi ET300", + "table_carlo_gavazzi_em510": "Carlo Gavazzi EM510", + "table_carlo_gavazzi_em530": "Carlo Gavazzi EM530", + "table_carlo_gavazzi_em540": "Carlo Gavazzi EM540", "virtual_meter": "Virtueller Zähler", "virtual_meter_select": "Auswählen...", "virtual_meter_inverter": "Wechselrichter", @@ -44,6 +56,8 @@ let x = { "virtual_meter_load": "Last", "virtual_meter_backup_load": "Backup-Last", "virtual_meter_meter": "Zähler", + "virtual_meter_current_transformer_1": "Stromwandler 1", + "virtual_meter_current_transformer_2": "Stromwandler 2", "device_address": "Geräteadresse", "device_address_muted": /*SFN*/(device_address: number) => "typischerweise " + device_address/*NF*/, "shelly_pro_3em_device_profile": "Geräteprofil", @@ -59,6 +73,11 @@ let x = { "shelly_em_monophase_mapping_l1": "L1", "shelly_em_monophase_mapping_l2": "L2", "shelly_em_monophase_mapping_l3": "L3", + "carlo_gavazzi_phase": "Phase", + "carlo_gavazzi_phase_select": "Auswählen...", + "carlo_gavazzi_phase_l1": "L1", + "carlo_gavazzi_phase_l2": "L2", + "carlo_gavazzi_phase_l3": "L3", "register_address_mode": "Adressmodus", "register_address_mode_select": "Auswählen...", "register_address_mode_address": "Registeradresse (beginnt bei 0)", diff --git a/software/web/src/modules/meters_modbus_tcp/translation_en.tsx b/software/web/src/modules/meters_modbus_tcp/translation_en.tsx index 19d0b45c2..5775f70c0 100644 --- a/software/web/src/modules/meters_modbus_tcp/translation_en.tsx +++ b/software/web/src/modules/meters_modbus_tcp/translation_en.tsx @@ -36,6 +36,18 @@ let x = { "table_siemens_pac3220": "Siemens PAC3220", "table_siemens_pac4200": "Siemens PAC4200", "table_siemens_pac4220": "Siemens PAC4220", + "table_carlo_gavazzi_em24_din": "Carlo Gavazzi EM24-DIN", + "table_carlo_gavazzi_em24_e1": "Carlo Gavazzi EM24-E1", + "table_carlo_gavazzi_em100": "Carlo Gavazzi EM100", + "table_carlo_gavazzi_et100": "Carlo Gavazzi ET100", + "table_carlo_gavazzi_em210": "Carlo Gavazzi EM210", + "table_carlo_gavazzi_em270": "Carlo Gavazzi EM270", + "table_carlo_gavazzi_em280": "Carlo Gavazzi EM280", + "table_carlo_gavazzi_em300": "Carlo Gavazzi EM300", + "table_carlo_gavazzi_et300": "Carlo Gavazzi ET300", + "table_carlo_gavazzi_em510": "Carlo Gavazzi EM510", + "table_carlo_gavazzi_em530": "Carlo Gavazzi EM530", + "table_carlo_gavazzi_em540": "Carlo Gavazzi EM540", "virtual_meter": "Virtual meter", "virtual_meter_select": "Select...", "virtual_meter_inverter": "Inverter", @@ -44,6 +56,8 @@ let x = { "virtual_meter_load": "Load", "virtual_meter_backup_load": "Backup load", "virtual_meter_meter": "Meter", + "virtual_meter_current_transformer_1": "Current transformer 1", + "virtual_meter_current_transformer_2": "Current transformer 2", "device_address": "Device address", "device_address_muted": /*SFN*/(device_address: number) => "typically " + device_address/*NF*/, "shelly_pro_3em_device_profile": "Device profile", @@ -59,6 +73,11 @@ let x = { "shelly_em_monophase_mapping_l1": "L1", "shelly_em_monophase_mapping_l2": "L2", "shelly_em_monophase_mapping_l3": "L3", + "carlo_gavazzi_phase": "Phase", + "carlo_gavazzi_phase_select": "Select...", + "carlo_gavazzi_phase_l1": "L1", + "carlo_gavazzi_phase_l2": "L2", + "carlo_gavazzi_phase_l3": "L3", "register_address_mode": "Address mode", "register_address_mode_select": "Select...", "register_address_mode_address": "Register address (begins at 0)",