az-device-contract-codegen 2026.5.18

Generate deterministic Modbus C, Markdown, and Tokio client artifacts from typed device contract definitions.
Documentation
  • Coverage
  • 0.88%
    1 out of 113 items documented1 out of 1 items with examples
  • Size
  • Source code size: 118.25 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.71 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 3s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • zjarlin

az-device-contract-codegen

Generate deterministic Modbus contract artifacts from typed service definitions.

  • Crate: az-device-contract-codegen
  • Local path: creates/az-device-contract-codegen
  • Install: cargo add az-device-contract-codegen

The crate plans a Modbus address layout, then emits a stable artifact bundle for:

  • C headers and sources for RTU/TCP handlers
  • Markdown protocol documents
  • Rust client code built around tokio-modbus

Minimal usage

use az_device_contract_codegen::{
    generate_bundle, ApiKind, ContractMethod, ContractRenderRequest, ContractService,
    ContractTypedItem, ReadReturnKind, TransportKind, ValueType,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let request = ContractRenderRequest {
        transports: vec![TransportKind::Rtu, TransportKind::Tcp],
        services: vec![ContractService {
            api_kind: ApiKind::RuntimeRead,
            interface_name: "DeviceReadApi".into(),
            interface_summary: Some("Runtime reads".into()),
            methods: vec![ContractMethod {
                summary: Some("Read signal lights".into()),
                method_name: "getSignalLights".into(),
                read_return_kind: Some(ReadReturnKind::Dto),
                read_return_type_name: Some("SignalLights".into()),
                read_area: None,
                write_area: None,
                read_fields: vec![
                    ContractTypedItem {
                        name: "ch1".into(),
                        summary: None,
                        value_type: ValueType::Boolean,
                    },
                    ContractTypedItem {
                        name: "ch2".into(),
                        summary: None,
                        value_type: ValueType::Boolean,
                    },
                ],
                parameters: vec![],
            }],
        }],
    };

    let bundle = generate_bundle(&request)?;

    for artifact in &bundle.artifacts {
        println!("{}", artifact.relative_path.display());
    }
    Ok(())
}

Typical output paths:

  • Core/Inc/generated/modbus/*.h
  • Core/Src/generated/modbus/**/*.c
  • Docs/generated/modbus/protocols/*.md
  • Docs/generated/modbus/rust/*.rs

Default mapping rules

  • STATIC_READ defaults to input registers (0x04)
  • RUNTIME_READ
    • all-boolean DTO/scalar reads default to discrete inputs (0x02)
    • everything else defaults to input registers (0x04)
  • WRITE
    • all-boolean parameters default to coils (0x05 / 0x0F)
    • everything else defaults to holding registers (0x06 / 0x10)

readArea and writeArea can override those defaults explicitly.

Notes

  • The crate itself does not write files; it returns GeneratedArtifact values.
  • Generated Rust clients assume the consumer compiles them with tokio-modbus and serialport.
  • Generated filenames and helper symbols currently use the existing okm_* naming line used by this repository.