Skip to content
Sourceful Energy

Docs · Data

Data Models

Telemetry data model v2, the format a Zap publishes and returns from its local API. Fields, units and signs.

Telemetry Data Models#

A Zap publishes telemetry in data model v2, and its local API returns the same payloads.

This page gives the rules. The fields of each DER type are listed by the API, which needs no authentication:

Shell
curl "https://novacore-mainnet.sourceful.dev/public/der-types/battery?format=v2"

Rules#

  • One flat JSON object per DER per reading, published on gateways.{gateway_id}.devices.{hardware_id}.ders.{der_name}.telemetry.json.v2. NATS uses ., MQTT uses /.
  • type is the DER type: solar, battery, inverter, meter or ev_charger_port.
  • Every field is always present. A value that was not read is null, never 0.
  • AC or DC is in the name. Every field in W, V, A, VA, var or Wh ends in _ac or _dc: W_ac, W_dc, l1_V_ac, total_charge_Wh_dc, reactive_var_ac. Only Hz has no postfix.
  • Lowercase except units. soc_nom_fract, l1_V_ac, temperature_C.
  • timestamp is Unix epoch milliseconds, set by the gateway. read_time_ms is how long the read took, a duration. A field ending in _at is a time in epoch milliseconds, one ending in _ms a duration.
  • make is a brand key, not a display name or a model: deye, eastron, sungrow. Show people the brand's display_name from GET /device-support/brands on the Novacore API.
  • der_name is the DER's provisioned name, by default its type. A device with two DERs of the same type gives them distinct names.
JSON
{
  "type": "solar",
  "make": "deye",
  "timestamp": 1767225600000,
  "read_time_ms": 42,
  "W_ac": null,
  "W_dc": -7562.5,
  "mppt": [
    { "V_dc": 380, "A_dc": -12.5, "W_dc": -4750 },
    { "V_dc": 375, "A_dc": -7.5, "W_dc": -2812.5 }
  ],
  "total_generation_Wh_ac": null,
  "total_generation_Wh_dc": 45230000,
  "lower_limit_W_ac": null,
  "lower_limit_W_dc": -8000
}

Which Power Field to Read#

DER typeSidePower
meterAC onlyW_ac, always a number
inverterAC only. Its DC side is the solar and battery DERsW_ac, always a number
solarNormally DCW_dc or W_ac: at least one is a number, both when both are measured
batteryDC, unless the device is AC-coupled and reports only ACW_dc or W_ac: at least one is a number, both when both are measured
ev_charger_portFollows the charger: an AC charger reports _ac, a DC charger _dcW_ac and W_dc may both be null

Sign Convention#

Sourceful sign convention: + import, − export, seen from the DER. Power into the DER (charge, consume) is positive. Power out of it (discharge, generation, delivery) is negative. This holds for _ac and _dc alike.

DER+−
solarnevergenerating
batterychargingdischarging
inverterabsorbing ACdelivering AC
meter at the grid connectionimportexport
ev_charger_portcharging the vehicleV2G

Gateway Status and Events#

A DER payload carries measurements only, and a device the gateway cannot read sends none. The gateway reports device health itself:

SubjectPayloadSent
gateways.{gateway_id}.status.json.v2GatewayStatus: each device's state (ok, stale, unreachable), the site's alarms, storage, uplinkAt a fixed period and on a change
gateways.{gateway_id}.events.json.v2GatewayEvent, such as device_unreachable and device_reachableOnce per transition

They are not buffered or replayed. Each status snapshot is the whole state, so the next one replaces a lost one. GET /stream/gateways/{id} on the Novacore API delivers both.