Skip to content

slundi/azzurro

Repository files navigation

azzurro

Rust parsing library for the ZCS Azzurro Portal API.

Retrieve solar production, battery state, and energy consumption/import/export data from ZCS-compatible inverters and storage systems.

This crate handles JSON serialization/deserialization only — HTTP transport is left to the caller.

Features

  • Historic data — time-series values (power, energy, battery SoC, …) for any 24-hour window
  • Realtime data — latest snapshot values per device
  • Device alarms — active alarm codes and last-update timestamp per device

Installation

[dependencies]
azzurro = "0.1"
serde_json = "1"   # for serialization

Usage

Building a request

use azzurro::{HistoricRequest, RealtimeRequest, DeviceAlarmRequest};

// Historic: query a 24-hour window
let req = HistoricRequest::new(
    vec!["ZA1ES111H1C029".into(), "ZE1ES330M3E696".into()],
    "2021-09-15T00:00:00.000Z",
    "2021-09-15T23:59:59.059Z",
);
let body = serde_json::to_string(&req)?;

// Realtime: latest snapshot
let req = RealtimeRequest::new(vec!["ZA1ES111H1C029".into()]);
let body = serde_json::to_string(&req)?;

// Device alarms
let req = DeviceAlarmRequest::new(vec!["ZA1ES122JAH761".into()]);
let body = serde_json::to_string(&req)?;

Sending the request (caller-provided HTTP)

POST https://third.zcsazzurroportal.com:19003/
Content-Type: application/json
Authorization: Zcs <token>

Parsing a response

use azzurro::HistoricResponse;

let resp: HistoricResponse = serde_json::from_str(&response_body)?;
for device_map in &resp.historic_data.params.value {
    for (thing_key, data) in device_map {
        if let Some(ts) = &data.ts {
            println!("{}: {} samples", thing_key, ts.len());
        }
        if let Some(gen) = &data.power_generating {
            println!("  powerGenerating: {:?}", gen);
        }
    }
}

API coverage

historicData

Time-series arrays (one value per sample, aligned with ts). Max query window: 24 hours.

Field Unit Description
ts ISO 8601 timestamps
batterySoC % Battery state of charge
batteryCycletime Battery cycle count
batterySoC2 % Second battery SoC (dual-battery)
batteryCycletime2 Second battery cycle count
powerGenerating W PV generation power
powerConsuming W Load consumption power
powerCharging W Battery charging power
powerDischarging W Battery discharging power
powerExporting W Grid export power
powerImporting W Grid import power
powerAutoconsuming W Self-consumed power
powerDC W DC power
currentDC A DC current
voltageDC V DC voltage
temperature °C Inverter temperature
energyGenerating kWh PV energy generated (period)
energyConsuming kWh Energy consumed (period)
energyCharging kWh Energy into battery (period)
energyDischarging kWh Energy from battery (period)
energyExporting kWh Energy exported (period)
energyImporting kWh Energy imported (period)
energyAutoconsuming kWh Self-consumed energy (period)
energyGeneratingTotal kWh Lifetime PV energy
energyConsumingTotal kWh Lifetime consumption
energyChargingTotal kWh Lifetime battery in
energyDischargingTotal kWh Lifetime battery out
energyExportingTotal kWh Lifetime grid export
energyImportingTotal kWh Lifetime grid import

realtimeData

Same fields as historicData (scalar values, not arrays), plus:

Field Description
lastUpdate ISO 8601 timestamp of last packet
thingFind ISO 8601 timestamp of first-ever packet
energyAutoconsumingTotal kWh lifetime self-consumed

deviceAlarm

Field Description
deviceAlarm List of active alarm IDs ([] = no alarms, absent = no data)
lastUpdate ISO 8601 timestamp of last packet

RequiredValues

All requests default to RequiredValues::All ("*"), which asks the API to return every field the device supports. To request a subset, set required_values directly:

use azzurro::{RealtimeRequest, RequiredValues};

let mut req = RealtimeRequest::new(vec!["ZA1ES111H1C029".into()]);
req.realtime_data.params.required_values =
    RequiredValues::Fields(vec!["powerGenerating".into(), "lastUpdate".into()]);

Device compatibility

Not every field is returned for every device type. The API only includes fields that are compatible with the hardware. Missing fields deserialize to None.

License

MIT

About

Rust API bindings for Azzuro batteries.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors