Skip to main content
Skip table of contents

For DIY & developers

For DIY users and developers who want to put live Sigenergy data on a Shelly device, or build on top of the Sigenergy OpenAPI. Three working recipes plus full API, Modbus, and MQTT reference.

What you can build

Five live Sigenergy values mirrored as Virtual Components on any Shelly device with scripting capability (Pro 2, Pro 3EM, Pro 4PM, Plus 2PM, etc.). The values appear in the Shelly app, on the device's local web page, and in the Shelly Cloud dashboard.

NONE
VC 200 - PV Power (W)        icon: solar-power         (gold)
VC 201 - Battery SOC (%)     icon: battery-medium      (green)
VC 202 - Battery Power (W)   icon: battery-charging    (teal)   positive = charging
VC 203 - Grid Power (W)      icon: transmission-tower  (orange) positive = export
VC 204 - Load Power (W)      icon: home-lightning-bolt (blue)

Recipe A - Local Modbus TCP bridge

The Sigenergy system exposes Modbus TCP on port 502 with the inverter as the slave at unit ID 247. On a typical home installation, the inverter is reachable on the home LAN through the gateway. A small Python script on any always-on host on the same LAN - a small router with a Linux distro is a good fit - reads five registers once per second and pushes the values to the Shelly device over HTTP.

  • Polling: 1 second.

  • Cloud: not required.

  • Dependencies: none (Python stdlib only).

  • Auto-start: runs as a system service (procd on OpenWrt-based routers, systemd on Linux, Scheduled Task on Windows).

Architecture:

NONE
sigen-bridge.py
  -> Modbus TCP -> Sigenergy inverter (<SIGEN_IP>:502, Unit ID 247; reached via the gateway on the home LAN)
  -> Number.Set HTTP POST -> Shelly VCs 200-204

Script: sigen-bridge-router.py (in Downloads below).

Recipe B - Sigenergy data subscription (HTTP push)

Configure the Sigenergy developer portal to push data to an HTTPS endpoint you control, then have the Shelly device poll that endpoint. The full setup lives in the portal: App settings → Data Subscription, mode set to http, with three endpoint URLs (system, telemetry, alarm). Sigenergy then POSTs telemetry on its push cycle (5 minutes by default) and pushes system and alarm data on event.

For displaying live values on a Shelly device, the flow is:

  1. In your endpoint, parse the telemetry POST, extract pvPowerW, storageSOC%, storageChargeDischargePowerW, gridActivePowerW, and inverterActivePowerW. Compute load as inverterActivePowerW + gridActivePowerW. Store the latest values where they can be served back as JSON.

  2. Expose a GET on your endpoint that returns the cached JSON.

  3. Point the Shelly script (sigen-monitor.js in Downloads) at the GET URL. The script's Timer polls every 5 minutes and updates Virtual Components 200-204.

How you host the endpoint is up to you: a serverless function, a small VM, an existing internal API, anything that speaks HTTPS and is publicly reachable. A Cloudflare Workers starter is included in Downloads (worker.js, wrangler.toml) as one example.

For the portal-side steps and the activation API call, see Sigenergy's documentation: Application Dashboard → Data Subscription and Subscribe for Telemetry.

Recipe C - Modbus RS485 add-on (beta)

A direct RS485 link from the inverter's COM port terminal to a Shelly device with a Modbus RS485 add-on. The Shelly script reads the inverter's Modbus registers directly. There is no authentication, no tokens, no developer portal, no internet involved, just physical wiring and the Modbus serial parameters.

What you need:

  • A Shelly device with a Modbus RS485 add-on (for example a Shelly Pro device fitted with the add-on).

  • A twisted pair from the add-on's A+/B- terminals to the inverter COM port terminal. Ground bonded only at one end to avoid loops.

  • The inverter's RS485 serial parameters (baud rate, parity, stop bits) and slave ID, as documented in the SigenStor inverter spec sheet.

NONE
Shelly + Modbus RS485 add-on <-(twisted pair)-> inverter COM port
Shelly script: Modbus.Read every ~30 s -> Virtual.getHandle().setValue() -> VCs 200-204

The register map is the same one used over Modbus TCP and is documented in the next section. This recipe will be published in full (wiring photos, parameter values, ready-to-run script) once the inverter-side connection has been validated end-to-end on a production install.

API authentication

The Sigenergy OpenAPI uses a key-based auth pair (AppKey + AppSecret), obtained from the developer portal at developer.sigencloud.comControl CenterSettings. Developer registration requires an invitation code from Sigenergy (approval typically 3-5 days).

HTTP
POST /openapi/auth/login/key
Content-Type: application/json
Body: { "key": "<base64(AppKey:AppSecret)>" }

Response:
{
  "code": 0,
  "msg": "success",
  "data": "{\"tokenType\":\"Bearer\",\"accessToken\":\"<token>\",\"expiresIn\":43199}"
}

The data field is a JSON string, not an object - parse it twice. Token lifetime is ~12 hours; re-request within 5 minutes of expiry.

Include in every subsequent call:

HTTP
Authorization: Bearer <accessToken>
sigen-region: eu

Rate limits

  • Energy-flow / realtime endpoints: 1 call per 5 minutes per station.

  • General API: 10 requests per minute for third-party accounts.

Finding the System ID

mySigen → Settings → tap the three-dot menu (upper right). systemId appears in the Basic Info block.

Key endpoints

Energy Flow (real-time)

HTTP
GET /openapi/systems/{systemId}/energyFlow

Fields (all kW except batterySoc):

NONE
pvPower       - PV generation;       always >= 0
gridPower     - Grid power;          positive = export, negative = import
batteryPower  - Battery power;       positive = charging
batterySoc    - Battery SoC (%);     0-100
loadPower     - Load consumption;    always >= 0
evPower       - EV charging power
heatPumpPower - Heat-pump power

System realtime data (generation totals)

HTTP
POST /openapi/system/realtime/data
Body: { "systemId": "<systemId>" }

Returns daily, monthly, annual, and lifetime PV (kWh), plus CO2 / coal-saved / tree-equivalent figures.

Battery command (VPP / NBI)

HTTP
POST /openapi/system/battery/command

Switch the battery between charge, discharge, selfConsumption, and idle modes, with optional limits on charge power, PV use, sell/purchase caps, and priority. Maximum 24 commands per batch per station.

Switch operating mode (NBI only)

HTTP
POST /openapi/system/operationMode/switch
Body: { "systemId": "<systemId>", "energyStorageOperationMode": 0 }

Modes:
  MSC (0) - Maximum Self-Consumption
  FFG (5) - Full Feed-in to Grid
  VPP (6) - VPP mode (service provider only)
  NBI (8) - North Bound Integration

NBI onboarding / offboarding

HTTP
POST /openapi/board/onboard
POST /openapi/board/offboard
Body: [ "<systemId>" ]

Result codes: 0 = success, 1401 = already in the requested state (harmless).

Operating modes - quick reference

Mode

Behaviour

MSC

PV → load first; surplus charges battery; grid is last resort.

Charge

Charges the battery from PV first, then grid; surplus PV is exported.

Discharge

Discharges PV first, then battery - for peak shaving or export.

Self-Consumption Grid

Like MSC but surplus goes to the grid, not the battery.

Idle

Battery sits; PV surplus is exported.

VPP

Service provider controls dispatch; owner cannot change mode.

NBI

Designed for third-party integrations; query enabled by default, control requires explicit permission from Sigenergy.

Modbus register map (TCP and RS485)

Connection (TCP): <SIGEN_IP>:502, Unit ID 247. The Modbus slave is the inverter; on a typical home installation it is reachable on the home LAN through the gateway. The same register map is used over RS485 to the inverter's COM port.

Using pymodbus 3.x: PDU address = full register number - do not subtract 30001.

NONE
Signal        Register  Count  Type    Scale  Notes
gridPower     30005     2      int32   1 W    Positive = import from grid
batterySoc    30014     1      uint16  0.1    Divide by 10 for %
pvPower       30035     2      int32   1 W
batteryPower  30037     2      int32   1 W    Positive = charging
loadPower     30284     2      int32   1 W

The same register map applies on RS485. Physical RS485 parameters (baud, parity, stop bits) are in the SigenStor inverter spec sheet.

MQTT telemetry

NONE
Broker:     mqtts://mqtt-eu.sigencloud.com:8883
Auth:       Mutual TLS (ca.pem, client.pem, client.key from Sigenergy)
Data topic: {appKey}/openapi/period/{systemId}
Activation: publish {accessToken, systemIdList} to openapi/subscription/period
Interval:   5 minutes (configurable in developer portal)
Push types: Telemetry, Change (status change), Alarm (fault)

Telemetry payload includes per-phase grid and inverter power, total PV, storage SoC and power, charge/discharge headroom, plus system status, on/off-grid status, charge/discharge cut-off SoC, and peak-shaving / Storm Watch flags.

Sigenergy's MQTT broker enforces per-subscriber ACLs - mutual-TLS client certificates are scoped to subscribers registered through the developer portal. Plan to receive MQTT in a backend you control, then mirror to Shelly via HTTP.

Downloads

The following files are attached to this page:

  • sigen-bridge-router.py - Always-on Modbus-TCP bridge (Recipe A).

  • sigen-modbus-bridge.py - Same logic, laptop variant.

  • sigen-poller.py - Cloud-API poller, laptop variant.

  • worker.js - Cloudflare Worker (Recipe B).

  • wrangler.toml - Cloudflare Worker config.

  • sigen-monitor.js - Shelly script that polls the Worker URL and updates Virtual Components.

  • sigen-monitor-rs485.js - Shelly script for the RS485 add-on (Recipe C).

  • sigen_agent.py - Claude-powered Sigenergy API helper.

  • sigen_agent_README.md - Setup and usage guide for the helper.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.