NOTICE: All information contained herein is, and remains
the property of TechnoCore Automate.
Updated : 2026-03-16
ObjServiceSolarman integrates with the SolarMAN Open API (v1.1.6) to
retrieve and store solar inverter and plant data from SolarMAN-connected
installations. The service covers authentication, plant and device
discovery, real-time and historical data retrieval, device control
commands, alert monitoring, and database synchronisation.
The module lives in factory.service/package.gekko/ as part of the
Gekko home automation package. It follows the standard Axion service
pattern: class named ObjServiceApi, inheriting from ObjData, with
a process(context) workflow entry point and a typer CLI.
SolarMAN is a cloud monitoring platform for solar inverters, loggers
(data collectors / DTUs), batteries, and related devices. Each physical
installation is called a plant (identified by stationId). Each
plant contains one or more devices (identified by deviceSn).
The API base URL is https://globalapi.solarmanpv.com. All endpoints
use HTTP POST with JSON request/response bodies. The appId is passed
as a query parameter on every request.
Credentials are stored under base.solarman (or overridden per
package):
base:
solarman:
app_id: "302309262253568"
app_secret: "9e2576194289d0ed3146ce0cc8ecd573"
email: "user@example.com"
password: "plaintext_password"
The password is hashed with SHA256 before transmission. The plaintext
is never sent over the wire.
Module-level settings:
settings:
base_url: https://globalapi.solarmanpv.com
rate_limit_general: 300
rate_limit_window_seconds: 10
rate_limit_control: 50
rate_limit_control_window_seconds: 60
token_validity_seconds: 5184000
Authentication uses API 2.1 (/account/v1.0/token). The request sends
appSecret, email, and SHA256-hashed password. On success, an
access_token JWT is returned with approximately 2 months validity
(5,184,000 seconds).
The token is cached in memory and automatically refreshed when expired.
All subsequent API calls include the token in the Authorization: bearer
header.
svc = ObjServiceApi()
ok = svc.authenticate() # True on success
| SolarMAN API | Method | Description |
|---|---|---|
| 2.1 | authenticate() |
Obtain access token (2 month validity) |
| SolarMAN API | Method | Description |
|---|---|---|
| 3.1 | get_device_alert_detail(device_sn, alert_id) |
Alert details for a specific device alert |
| 3.2 | get_device_alerts(device_sn, page, size) |
Paginated alert list for a device |
| 3.3 | get_device_realtime(device_sn) |
Real-time inverter/battery/grid data |
| 3.4 | get_device_historical(device_sn, time_type, start_time, end_time) |
Historical device data (day/month/year) |
| 3.7 | send_device_command(device_sn, command) |
Issue control command (rate limited) |
| SolarMAN API | Method | Description |
|---|---|---|
| 4.1 | get_plant_info(station_id) |
Detailed plant information |
| 4.2 | get_device_list(station_id) |
All devices in a plant |
| 4.3 | get_plant_historical(station_id, time_type, start_time, end_time) |
Historical plant data (day/month/year) |
| 4.4 | get_plant_list(page, size) |
Paginated list of all plants |
| 4.5 | get_plant_realtime(station_id) |
Real-time production and consumption |
| 4.7 | get_plant_alerts(station_id, page, size) |
Paginated alert list for a plant |
| SolarMAN API | Description | Reason |
|---|---|---|
| 2.2–2.9 | Account management (register, modify, reset) | Not needed for data retrieval |
| 3.5 | Device list (standalone) | Covered by 4.2 (plant-scoped) |
| 3.6 | SIM card info | Gateway-specific, low priority |
| 3.8 | Device communication relationship | Low priority |
| 3.9 | Customised command | Rate limited, needs specific use case |
| 4.6 | Operation privilege | Administrative |
| 4.8–4.14 | Plant/device CRUD, offset, gateway | Administrative |
| 5.1 | Verification code | Account management |
Real-time device data is returned as a list of key-value items. Below
are the key inverter data points observed from a Deye three-phase LV
hybrid inverter:
| Key | Description | Unit |
|---|---|---|
| DV1–DV4 | PV string voltage | V |
| DC1–DC4 | PV string current | A |
| DP1–DP4 | PV string power | W |
| S_P_T | Total solar power | W |
| PV_D_P_G | Daily PV generation | kWh |
| Et_ge0 | Lifetime total generation | kWh |
| Etdy_ge1 | Daily generation | kWh |
| Key | Description | Unit |
|---|---|---|
| G_V_L1–L3 | Grid voltage per phase | V |
| G_C_L1–L3 | Grid current per phase | A |
| G_P_L1–L3 | Grid power per phase (negative = feeding) | W |
| PG_Pt1 | Total grid power (negative = feeding) | W |
| PG_F1 | Grid frequency | Hz |
| ST_PG1 | Grid status (e.g. "Purchasing energy") | — |
| CT1_P_E–CT3_P_E | CT clamp power per phase | W |
| CT_T_E | CT total power | W |
| Key | Description | Unit |
|---|---|---|
| AV1–AV3 | Inverter AC voltage per phase | V |
| AC1–AC3 | Inverter AC current per phase | A |
| A_Fo1 | Inverter output frequency | Hz |
| INV_O_P_L1–L3 | Inverter output power per phase | W |
| INV_O_P_T | Total inverter output power | W |
| Key | Description | Unit |
|---|---|---|
| B_ST1 | Battery status (Charging/Discharging/Standby) | — |
| B_V1 | Battery voltage | V |
| BATC1 | Battery current | A |
| B_P1 | Battery power | W |
| B_left_cap1 | Battery state of charge | % |
| B_TYP1 | Battery type (e.g. "lithium") | — |
| BMS_SOC | BMS state of charge | % |
| BMS_B_V1 | BMS battery voltage | V |
| BMS_B_C1 | BMS battery current | A |
| BMST | BMS temperature | C |
| BRC | Battery rated capacity | Ah |
| Etdy_cg1 | Daily charge | kWh |
| Etdy_dcg1 | Daily discharge | kWh |
| t_cg_n1 | Lifetime total charge | kWh |
| t_dcg_n1 | Lifetime total discharge | kWh |
| Key | Description | Unit |
|---|---|---|
| C_V_L1–L3 | Consumption voltage per phase | V |
| C_P_L1–L3 | Consumption power per phase | W |
| E_Puse_t1 | Total consumption power | W |
| Etdy_use1 | Daily consumption | kWh |
| E_C_T | Lifetime total consumption | kWh |
| L_F | Load frequency | Hz |
| Key | Description | Unit |
|---|---|---|
| AC_T | Inverter AC temperature | C |
| B_T1 | Battery temperature | C |
| BMST | BMS temperature | C |
Stores plant metadata synced from SolarMAN.
| Column | Type | Description |
|---|---|---|
| Guid | VARCHAR(64) | Unique record ID |
| StationId | VARCHAR(64) | SolarMAN plant ID (PK) |
| Name | VARCHAR(255) | Plant name |
| Capacity | DECIMAL(10,2) | Installed capacity (kW) |
| Location | VARCHAR(512) | Address |
| Latitude | DECIMAL(12,8) | GPS latitude |
| Longitude | DECIMAL(12,8) | GPS longitude |
| Status | VARCHAR(32) | Plant status |
| Package | VARCHAR(255) | Axion package (PK) |
| Module | VARCHAR(255) | Module identifier |
| UpdateDate | TIMESTAMP | Last sync timestamp |
Primary key: (StationId, Package)
Stores device metadata per plant.
| Column | Type | Description |
|---|---|---|
| Guid | VARCHAR(64) | Unique record ID |
| StationId | VARCHAR(64) | Parent plant ID |
| DeviceSn | VARCHAR(128) | Device serial number (PK) |
| DeviceId | VARCHAR(128) | SolarMAN internal device ID |
| DeviceType | VARCHAR(64) | INVERTER, COLLECTOR, BATTERY, etc. |
| DisplayName | VARCHAR(255) | Friendly name |
| ConnectStatus | INT | 0=offline, 1=online |
| Package | VARCHAR(255) | Axion package (PK) |
| Module | VARCHAR(255) | Module identifier |
| UpdateDate | TIMESTAMP | Last sync timestamp |
Primary key: (DeviceSn, Package)
Stores real-time device readings as JSON payloads. One row per device
per sync. The Payload column contains the full key-value map from the
device's dataList response.
| Column | Type | Description |
|---|---|---|
| Guid | VARCHAR(64) | Unique record ID (PK) |
| StationId | VARCHAR(64) | Parent plant ID |
| DeviceSn | VARCHAR(128) | Device serial number |
| Payload | JSON | Key-value pairs from device data |
| Package | VARCHAR(255) | Axion package |
| Module | VARCHAR(255) | Module identifier |
| CreateDate | TIMESTAMP | When the reading was stored |
Structured time-series storage for inverter readings. Each row
represents one snapshot from one inverter. The Guid is generated
via get_uuid("SOLARMAN"). Only INVERTER-type devices are recorded
(collectors/loggers are skipped).
The _SOLAR_KEY_MAP class attribute maps SolarMAN API keys (e.g.
DV1, G_P_L1, B_left_cap1) to the SQL placeholder names used
in the insert_solar query. String fields (status, model, type)
are escaped; all others default to 0 when absent from the API
response.
| Column | Type | API Key | Description |
|---|---|---|---|
| Guid | VARCHAR(64) PK | — | get_uuid("SOLARMAN") |
| StationId | VARCHAR(64) | — | Parent plant ID |
| DeviceSn | VARCHAR(128) | SN1 | Device serial number |
| DeviceModel | VARCHAR(128) | INV_MOD1 | Inverter model name |
| DeviceTime | VARCHAR(32) | SYSTIM1 | Device clock timestamp |
| CreateTime | DATETIME | — | DB insert timestamp |
| Package | VARCHAR(255) | — | Axion package |
| Module | VARCHAR(255) | — | ObjServiceSolarman |
| RatedPower | DECIMAL(10,2) | Pr1 | Rated inverter power (W) |
| PvVoltage1–4 | DECIMAL(10,2) | DV1–DV4 | PV string voltage (V) |
| PvCurrent1–4 | DECIMAL(10,2) | DC1–DC4 | PV string current (A) |
| PvPower1–4 | DECIMAL(10,2) | DP1–DP4 | PV string power (W) |
| PvPowerTotal | DECIMAL(10,2) | S_P_T | Total solar power (W) |
| PvDailyGeneration | DECIMAL(10,2) | PV_D_P_G | Daily PV generation (kWh) |
| TotalGeneration | DECIMAL(12,2) | Et_ge0 | Lifetime generation (kWh) |
| DailyGeneration | DECIMAL(10,2) | Etdy_ge1 | Daily generation (kWh) |
| InvVoltageL1–L3 | DECIMAL(10,2) | AV1–AV3 | Inverter AC voltage (V) |
| InvCurrentL1–L3 | DECIMAL(10,2) | AC1–AC3 | Inverter AC current (A) |
| InvFrequency | DECIMAL(8,2) | A_Fo1 | Inverter frequency (Hz) |
| InvPowerL1–L3 | DECIMAL(10,2) | INV_O_P_L1–L3 | Inverter output per phase (W) |
| InvPowerTotal | DECIMAL(10,2) | INV_O_P_T | Total inverter output (W) |
| InvTemperature | DECIMAL(8,2) | AC_T | Inverter temperature (C) |
| GridVoltageL1–L3 | DECIMAL(10,2) | G_V_L1–L3 | Grid voltage (V) |
| GridCurrentL1–L3 | DECIMAL(10,2) | G_C_L1–L3 | Grid current (A) |
| GridPowerL1–L3 | DECIMAL(10,2) | G_P_L1–L3 | Grid power per phase (W) |
| GridPowerTotal | DECIMAL(10,2) | PG_Pt1 | Total grid power (W) |
| GridFrequency | DECIMAL(8,2) | PG_F1 | Grid frequency (Hz) |
| GridStatus | VARCHAR(64) | ST_PG1 | Grid state text |
| GridRelayStatus | VARCHAR(64) | GRID_RELAY_ST1 | Grid relay state |
| CtPowerL1–L3 | DECIMAL(10,2) | CT1–3_P_E | CT clamp per phase (W) |
| CtPowerTotal | DECIMAL(10,2) | CT_T_E | CT total power (W) |
| BatteryStatus | VARCHAR(32) | B_ST1 | Charging/Discharging/Standby |
| BatteryVoltage | DECIMAL(8,2) | B_V1 | Battery voltage (V) |
| BatteryCurrent | DECIMAL(8,2) | BATC1 | Battery current (A) |
| BatteryPower | DECIMAL(10,2) | B_P1 | Battery power (W) |
| BatterySoc | DECIMAL(5,1) | B_left_cap1 | State of charge (%) |
| BatteryType | VARCHAR(32) | B_TYP1 | Battery chemistry |
| BatteryTemperature | DECIMAL(8,2) | B_T1 | Battery temperature (C) |
| BatteryRatedCapacity | DECIMAL(10,2) | BRC | Rated capacity (Ah) |
| BatteryDailyCharge | DECIMAL(10,2) | Etdy_cg1 | Daily charge (kWh) |
| BatteryDailyDischarge | DECIMAL(10,2) | Etdy_dcg1 | Daily discharge (kWh) |
| BatteryTotalCharge | DECIMAL(12,2) | t_cg_n1 | Lifetime charge (kWh) |
| BatteryTotalDischarge | DECIMAL(12,2) | t_dcg_n1 | Lifetime discharge (kWh) |
| BmsVoltage | DECIMAL(8,2) | BMS_B_V1 | BMS battery voltage (V) |
| BmsCurrent | DECIMAL(8,2) | BMS_B_C1 | BMS battery current (A) |
| BmsTemperature | DECIMAL(8,2) | BMST | BMS temperature (C) |
| BmsChargeVoltage | DECIMAL(8,2) | BMS_C_V | BMS charge voltage (V) |
| BmsDischargeVoltage | DECIMAL(8,2) | BMS_D_V | BMS discharge voltage (V) |
| BmsChargeCurrentLimit | DECIMAL(10,2) | BMS_C_C_L | BMS charge limit (A) |
| BmsDischargeCurrentLimit | DECIMAL(10,2) | BMS_D_C_L | BMS discharge limit (A) |
| BmsSoc | DECIMAL(5,1) | BMS_SOC | BMS state of charge (%) |
| ConsumptionVoltageL1–L3 | DECIMAL(10,2) | C_V_L1–L3 | Load voltage (V) |
| ConsumptionPowerL1–L3 | DECIMAL(10,2) | C_P_L1–L3 | Load power per phase (W) |
| ConsumptionPowerTotal | DECIMAL(10,2) | E_Puse_t1 | Total consumption (W) |
| ConsumptionVaTotal | DECIMAL(10,2) | E_Suse_t1 | Total apparent power (VA) |
| ConsumptionDaily | DECIMAL(10,2) | Etdy_use1 | Daily consumption (kWh) |
| ConsumptionTotal | DECIMAL(12,2) | E_C_T | Lifetime consumption (kWh) |
| LoadFrequency | DECIMAL(8,2) | L_F | Load frequency (Hz) |
| EnergyFromBatteryDaily | DECIMAL(10,2) | E_B_D | Daily from battery (kWh) |
| EnergyToBatteryDaily | DECIMAL(10,2) | E_S_D | Daily to battery (kWh) |
| EnergyFromBatteryTotal | DECIMAL(12,2) | E_B_TO | Lifetime from battery (kWh) |
| EnergyToBatteryTotal | DECIMAL(12,2) | E_S_TO | Lifetime to battery (kWh) |
| GenPowerL1–L3 | DECIMAL(10,2) | GEN_P_L1–L3 | Generator power per phase (W) |
| GenVoltageL1–L3 | DECIMAL(10,2) | GEN_V_L1–L3 | Generator voltage (V) |
| GenPowerTotal | DECIMAL(10,2) | GEN_P_T | Generator total power (W) |
| GenDailyEnergy | DECIMAL(10,2) | GEN_P_D | Generator daily energy (kWh) |
| GenTotalEnergy | DECIMAL(12,2) | GEN_P_TO | Generator lifetime energy (kWh) |
| GenRuntime | DECIMAL(10,2) | R_T_D | Generator runtime (h) |
| Method | Description |
|---|---|
sync_plants() |
Paginate through all plants and upsert into def_solarman_plants. Returns count. |
sync_devices(station_id) |
Fetch devices for a plant and upsert into def_solarman_devices. Returns count. |
sync_realtime(station_id) |
Fetch real-time data for all devices in a plant, store each as a JSON row in def_solarman_readings. Returns count. |
record_solar(station_id) |
Fetch real-time data for all inverters and insert structured rows into data_solar. Returns count. |
Sync methods use ON DUPLICATE KEY UPDATE for plants and devices
(idempotent upsert). Readings and solar records are insert-only
(append model for time-series history).
The process(context) method is the entry point when called from an
Axion workflow node. It reads command from the context dict and
dispatches to the appropriate method.
| Command | Required Context Keys | Result Key | Description |
|---|---|---|---|
sync_plants |
— | _solarman_result |
Sync all plants to DB |
sync_devices |
station_id |
_solarman_result |
Sync devices for a plant |
realtime |
station_id |
_solarman_result |
Store real-time readings for all devices |
record_solar |
station_id |
_solarman_result |
Record structured inverter data to data_solar |
plant_info |
station_id |
_solarman_result |
Return plant real-time data as JSON |
device_data |
device_sn |
_solarman_result |
Return device real-time data as JSON |
Example workflow context:
context = {
"command": "realtime",
"station_id": "2733410",
}
result = svc.process(context)
# result["_solarman_result"] == "2 readings stored"
All commands auto-authenticate before making API calls.
# Test authentication
python ObjServiceSolarman.py authenticate
# List all plants with capacity
python ObjServiceSolarman.py plants
# List devices for a plant
python ObjServiceSolarman.py devices 2733410
# Show real-time data for a specific device
python ObjServiceSolarman.py realtime 2206069217
# Show real-time data for a plant (JSON)
python ObjServiceSolarman.py plant-realtime 2733410
# Sync all plants and devices to database
python ObjServiceSolarman.py sync
# Show alerts for a plant
python ObjServiceSolarman.py alerts 2733410
| Scope | Limit | Window |
|---|---|---|
| General (all endpoints) | 300 requests | 10 seconds |
| Device control (API 3.7, 3.9) | 50 requests | 60 seconds |
Rate limits are per account, not per token.
| Method | Description |
|---|---|
_sha256_password() |
Hash plaintext password with SHA256 |
_headers(with_auth) |
Build HTTP headers with optional bearer token |
_post(path, payload, with_auth, timeout) |
Central POST dispatcher — appends appId as query param, auto-refreshes token, handles errors |
_is_token_valid() |
Check if cached token has not expired |
All API calls go through _post() which:
requests.exceptions.Timeout and returns {"code": -1, "msg": "timeout"}requests.exceptions.RequestException for network errorscode values from the API response via self.debug()SolarMAN error codes are documented in the API PDF Section 6.
Verified against the GekkoRidge installation:
Plant: GekkoRidge (station_id: 2733410, 6.0 kW)
Devices: COLLECTOR (SN: 2383613239), INVERTER (SN: 2206069217)
Inverter: Deye Three phase LV Hybrid (12 kW rated)
Battery: Lithium, 330 Ah rated, BMS-managed
Sample reading at 11:07:
PV: 2006 W (String 1: 938W, String 2: 1068W)
Grid: 67 W net import
Battery: 20% SOC, discharging 59W
Consumption: 1900 W
Daily gen: 8.2 kWh
Lifetime: 45,855 kWh total generation
from ObjServiceSolarman import ObjServiceApi
svc = ObjServiceApi()
svc.authenticate()
# List all plants
plants = svc.get_plant_list()
for plant in plants:
station_id = plant["id"]
print(f"{plant['name']} ({plant['installedCapacity']} kW)")
# Get devices
devices = svc.get_device_list(station_id)
for device in devices:
sn = device["deviceSn"]
data = svc.get_device_realtime(sn)
for item in data.get("dataList", []):
print(f" {item['key']}: {item['value']} {item.get('unit', '')}")
# Sync everything to database
svc.sync_plants()
for plant in plants:
svc.sync_devices(plant["id"])
svc.sync_realtime(plant["id"])
Updated : 2026-03-16