Sigenergy SigenStor / Sigen Hybrid (hybrid ESS)
Status: Vendor Confirmed · Register points: 144 · Transports: Modbus TCP, Modbus RTU
A curated ModDef profile for the Sigenergy SigenStor / Sigen Hybrid (hybrid ESS). Import it as
sigenergy.sigenstor or load the .moddef.yaml directly.
Connect to one over Web Serial and watch its values live in the device dashboard.
Usage
Load the profile, bind a transport, and read a point by name. The runtime applies the offset, scaling, byte order, and sentinels from the definition.
- Go
- TypeScript
- Rust
- Python
- C
- C++
doc, _ := moddef.Load("sigenergy-sigenstor.moddef.yaml")
dev, _ := client.New(doc, "sigenergy-sigenstor", transport) // your modbus.Transport
v, _ := dev.ReadPoint(ctx, "grid_active_power")
fmt.Println(v)
import {Device} from '@moddef/core';
import {loadDocument} from '@moddef/core/node';
const doc = await loadDocument('sigenergy-sigenstor.moddef.yaml');
const dev = Device.create(doc, 'sigenergy-sigenstor', transport);
console.log(await dev.readPoint('grid_active_power'));
let doc = moddef_core::load("sigenergy-sigenstor.moddef.yaml")?;
let mut dev = Device::new(&doc, Some("sigenergy-sigenstor"), transport)?;
let v = dev.read_point("grid_active_power").await?;
from moddef import Device, load
from moddef.pymodbus import Options, PymodbusTransport
doc = load("sigenergy-sigenstor.moddef.yaml")
transport = await PymodbusTransport.tcp("192.168.1.50", options=Options())
dev = Device.create(doc, "sigenergy-sigenstor", transport)
print(await dev.read_point("grid_active_power"))
md_doc_t doc;
md_doc_init(&doc, flash_ptr, flash_len); /* zero-copy view */
md_dev_t dev;
md_dev_init(&dev, &doc, MD_STR("sigenergy-sigenstor"), &transport);
md_value_t v;
md_dev_read(&dev, MD_STR("grid_active_power"), &v);
auto doc = moddef::Document::view(flash_bytes).value(); // zero-copy over flash
auto dev = moddef::Device::open(doc, "sigenergy-sigenstor", transport).value();
if (auto v = dev->read("grid_active_power"); v)
std::cout << v->to_string() << '\n';
Commands
Multi-step register procedures (spec §11.7)
this profile defines — write params, arm a trigger, poll for completion, then
read the result. Run one with your language's command executor (RunCommand,
runCommand, run_command, or md_cmd_begin/md_cmd_tick in C/C++).
enable_remote_ems — Enable Remote EMS Control
Hand plant control over to the Modbus master. Writes 1 to Remote EMS enable (40029) and then waits for the plant's EMS work mode (30003) to report 7, Remote EMS mode, which is how the document says the switch is confirmed. Nothing else in this profile's plant_control block does anything until this succeeds.
Results
| Field | Type |
|---|---|
ems_work_mode | UINT32 |
disable_remote_ems — Disable Remote EMS Control
Give plant control back to the built-in EMS by writing 0 to Remote EMS enable (40029). The plant returns to whichever work mode it was configured for locally, so the resulting EMS work mode is read back rather than polled for a fixed value.
Results
| Field | Type |
|---|---|
ems_work_mode | UINT32 |
set_pcs_power_target — Set PCS Active and Reactive Power Target
Take remote control and hold an absolute active and reactive power target at the plant. Enables remote EMS, selects control mode 0 (PCS remote control), then writes both targets. Mode 0 is required: the document notes that the power control registers not called out individually take effect only when the remote EMS control mode is 0. Command params carry no transform, so the limit is the raw register value in units of 1/1000 kW (the document's gain), not kW.
Params
| Field | Type | Required |
|---|---|---|
active_power_raw | INT32 | yes |
reactive_power_raw | INT32 | yes |
Results
| Field | Type |
|---|---|
active_power_target | DECIMAL |
reactive_power_target | DECIMAL |
command_charge — Command Charging
Take remote control and charge the battery at up to a given power. Enables remote EMS, writes the control mode, then writes the ESS max charging limit (40032), which the document says takes effect only in modes 3 and 4. Pass mode 3 to consume grid power first or 4 to consume PV power first. Command params carry no transform, so the limit is the raw register value in units of 1/1000 kW (the document's gain), not kW.
Params
| Field | Type | Required |
|---|---|---|
mode | UINT32 | yes |
charge_limit_raw | UINT32 | yes |
Results
| Field | Type |
|---|---|
control_mode | UINT32 |
charge_limit | DECIMAL |
command_discharge — Command Discharging
Take remote control and discharge at up to a given power. Enables remote EMS, writes the control mode, then writes the ESS max discharging limit (40034), which the document says takes effect only in modes 5 and 6. Pass mode 5 to output from PV first or 6 to output from the battery first. Command params carry no transform, so the limit is the raw register value in units of 1/1000 kW (the document's gain), not kW.
Params
| Field | Type | Required |
|---|---|---|
mode | UINT32 | yes |
discharge_limit_raw | UINT32 | yes |
Results
| Field | Type |
|---|---|
control_mode | UINT32 |
discharge_limit | DECIMAL |
set_remote_ems_mode — Set Remote EMS Control Mode
Enable remote EMS and put the plant into one of the modes from the document's appendix 6 without touching any power limit. Useful for the modes that need no setpoint: 1 is standby and 2 is maximum self-consumption. The charge and discharge modes 3 to 6 are better driven through command_charge and command_discharge, which also write the limit those modes read.
Params
| Field | Type | Required |
|---|---|---|
mode | UINT32 | yes |
Results
| Field | Type |
|---|---|
control_mode | UINT32 |
ems_work_mode | UINT32 |
Measurands
The 20 semantic quantities this device reports, each linked to the measurand catalog. Query a device by measurand instead of a raw point when you want portable code.
| Base quantity | Name | Unit | Description |
|---|---|---|---|
active_power | Active Power | W | Instantaneous real power |
reactive_power | Reactive Power | var | Instantaneous reactive power |
pv_power | PV Power | W | PV array / string power |
pv_voltage | PV Voltage | V | PV array / string voltage |
pv_current | PV Current | A | PV array / string current |
battery_power | Battery Power | W | Battery power (sign per direction) |
battery_voltage | Battery Voltage | V | Battery terminal voltage |
voltage | Voltage | V | RMS voltage; qualify with phase_ref (L1_N, L1_L2, ...) |
current | Current | A | RMS current; qualify with phase_ref / direction |
frequency | Frequency | Hz | Grid frequency |
state_of_charge | State of Charge | % | Battery charge level |
state_of_health | State of Health | % | Battery health |
charge_limit | Charge Limit | W | Maximum allowed charge power |
discharge_limit | Discharge Limit | W | Maximum allowed discharge power |
energy_active | Active Energy | Wh | Cumulative active energy register |
power_factor | Power Factor | 1 (ratio) | Ratio of real to apparent power (dimensionless) |
temperature | Temperature | degC | Temperature; qualify with location (INTERNAL, EXTERNAL, ...) |
inverter_temperature | Inverter Temperature | degC | Inverter internal temperature |
device_status | Device Status | undefined | Overall device operating status (enum) |
alarm_status | Alarm Status | undefined | Alarm state (enum or flag set) |
Source
- Profile:
battery-storage/sigenergy-sigenstor/sigenergy-sigenstor.moddef.yaml - Register map: vendor documentation