Crate sunspec

source ·
Expand description

§SunSpec Rust Implementation

Latest Version Unsafe forbidden

This Rust crate contains code for accessing SunSpec compliant devices in a safe and convenient way.

§Highlights

  • Pure Rust library
  • No unsafe code
  • Panic free
  • All communication is done via tokio-modbus without wrapping it in some kind of abstraction layer.
  • Supports Modbus TCP and RTU (via tokio-modbus).
  • Implements “Device Information Model Discovery” as defined in the SunSpec specification.
  • Fully typed models generated from the JSON files contained in the SunSpec models repository
  • Fully typed enums
  • Fully typed bitfields
  • Fully documented. Even the generated models.
  • Reading of complete models in a single request.

Nested and repeating groups are not supported, yet.

§Features

FeatureDescriptionExtra dependenciesDefault
tokioEnable tokio_modbus supporttokio-modbusyes

§Examples

The examples directory in the code repository contains the unabridged code.

§Example code for accessing data from a three phase inverter using the model 103

use std::{error::Error, net::SocketAddr, time::Duration};

use clap::Parser;
use itertools::Itertools;
use sunspec::tokio_modbus::{discover_models, read_model};
use tokio::time::sleep;
use tokio_modbus::{client::tcp::connect_slave, Slave};

#[derive(Parser)]
struct Args {
    addr: SocketAddr,
    device_id: u8,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let args = Args::parse();
    let mut ctx = connect_slave(args.addr, Slave(args.device_id)).await?;

    let models = discover_models(&mut ctx).await?.models;
    let m1 = read_model(&mut ctx, &models.m1).await?;

    println!("Manufacturer: {}", m1.mn);
    println!("Model: {}", m1.md);
    println!("Version: {}", m1.vr.as_deref().unwrap_or("(unspecified)"));
    println!("Serial Number: {}", m1.sn);

    println!(
        "Supported models: {}",
        models
            .supported_model_ids()
            .iter()
            .map(|id| id.to_string())
            .join(", ")
    );

    loop {
        let m103 = read_model(&mut ctx, &models.m103).await?;
        let w = m103.w as f32 * 10f32.powf(m103.w_sf.into());
        let wh = m103.wh as f32 * 10f32.powf(m103.wh_sf.into());
        println!("{:12.3} kWh {:9.3} kW", wh / 1000.0, w / 1000.0,);
        sleep(Duration::from_secs(1)).await;
    }
}

§FAQ

How does this crate differ from crates like tokio-sunspec, sunspec-models, sunspec_rs?

  • This crate generates all code using Rust code via the official SunSpec models repository with a code generator that was written in Rust, too.

  • All generated models are plain Rust structs. A single Modbus call can return the complete data for a model rather than having to fetch points individually.

  • All public types are documented. Even the generated models.

§License

Licensed under either of

at your option.

Re-exports§

Modules§

  • This module contains all the genererated SunSpec models.
  • This module contains the actual communication methods via tokio-modbus.

Structs§

  • The result of a SunSpec model discovery.
  • This structure is used to store the address of models after a successful model discovery.
  • Definition of a point
  • For every discovered but unknown model to this library this structure is returned.

Enums§

  • This error is returned if there was an error decoding the value of a given point.
  • This error is returned when an error occurs during model discovery.
  • This error is returned if there was an error loading the requested model.
  • This error is returned if there was an error while reading data from a point.
  • This error is returned if there was an error while writing data to a point.

Constants§

  • “SunS” identifier used when performing the model discovery.

Traits§

  • This trait marks points with a fixed size. All non-string values are actually fixed size.
  • Every model implements this trait which contains methods for accessing
  • This trait contains all the conversion methods needed for working with points of the SunSpec models.