Skip to main content

km003c-rs

Typed Rust library, CLI tools, GUI monitor, and Python bindings for the ChargerLAB POWER-Z KM003C USB-C power analyzer.

crates.io docs.rs license CI

Overview

km003c-rs provides asynchronous device communication, recorded-packet parsing, real-time power analysis, and USB Power Delivery capture. Physical values in the Rust API are type-safe uom quantities.

km003c-egui screenshot

Features

Device Communication

  • Dual interface support: Vendor (bulk, ~0.6ms latency) or HID (interrupt)
  • Cross-platform support using nusb
  • Asynchronous communication with Tokio
  • Automatic device discovery, initialization, and authentication

ADC Data Acquisition

  • Real-time voltage, current, and power measurements
  • Two modes:
    • Simple ADC: Single-shot readings with temperature and statistics
    • AdcQueue streaming: High-speed continuous streaming (2, 10, 50, 1000 SPS)
  • USB data line voltage measurements (D+, D-)
  • USB-C CC line voltage measurements (CC1, CC2)

USB Power Delivery Support

  • Capture and parse USB PD messages
  • Connection/disconnection event detection
  • Full PD message parsing using the usbpd crate
  • Support for SPR and EPR source capabilities
  • Chunked message reassembly for EPR
  • Typed firmware Type-C and protocol-engine state traces

Device Information

  • Model, firmware version, hardware version
  • Serial number and UUID
  • Hardware ID and authentication level

Components

km003c-lib

Core library providing:

  • Device communication and automatic initialization
  • Streaming authentication (required for AdcQueue)
  • Firmware-selected calibration authentication for level-2 operations
  • ADC and AdcQueue data parsing
  • CRC-validated read-only device settings
  • Offline recording catalog and encrypted log downloads
  • USB PD event parsing
  • Optional stateful USB PD semantic decoding through the usbpd feature
  • Typed firmware PD state-trace parsing

km003c-cli

Command-line tools:

  • adc_simple - Single-shot ADC readings with device info
  • adc_queue_simple - AdcQueue streaming demo
  • test_usbpd - USB PD negotiation capture
  • offline-log - List and export stored recordings as CSV or JSON

km003c-egui

GUI application featuring:

  • Three independently configurable plots for live or device-stored measurements
  • AdcQueue streaming with configurable sample rates
  • Adjustable time window (2s to 5min or all data)
  • Live recording and plot-buffer export to Parquet or CSV
  • Device-stored offline recording catalog, download, plotting, and Parquet/CSV export
  • Host-integrated charge and energy with explicit missing-sample quality data
  • Combined wire-message and firmware-state USB PD timeline with source filters
  • Device info panel with auth status
  • Connect/disconnect control

Python Bindings

Python bindings expose the parser using numeric properties with explicit unit suffixes such as vbus_v, ibus_a, and power_w.

Quick Start

Prerequisites

  • Rust 1.97+
  • USB access permissions (udev rules on Linux)
  • POWER-Z KM003C device

Installation

git clone https://github.com/okhsunrog/km003c-rs.git
cd km003c-rs
cargo build --release

Linux USB Permissions

Create udev rules for non-root access:

sudo cp 71-powerz-km003c.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger

The rules use the uaccess tag for secure, dynamic access to logged-in users.

Usage Examples

ADC Reading

cargo run --bin adc_simple

AdcQueue Streaming

cargo run --bin adc_queue_simple -- --rate 50 --duration 10

# Print every sample; current remains in amperes across the CLI tools.
cargo run --bin adc_queue_simple -- --rate 1000 --duration 10 --every 1

USB PD Capture

cargo run --bin test_usbpd

Offline Recordings

cargo run --bin offline-log -- metadata
cargo run --bin offline-log -- download --index 0 --format csv

GUI Application

cargo run --bin km003c-egui

The GUI records the complete AdcQueue sample set, independently of which three measurements are currently plotted. Parquet is the default format; CSV is available for compatibility. Each row contains device-relative time and sequence information, VBUS/current/power, CC1/CC2/D+/D- voltages, and cumulative charge and energy. Integer electrical columns use units in their names (*_uv, *_ua, and *_uw). Signed net accumulation is stored in charge_uah and energy_uwh; positive transferred totals are stored in charge_throughput_uah and energy_throughput_uwh.

Charge and energy use trapezoidal integration over the KM003C sequence clock. If samples are missing, the interval is retained as a linear estimate rather than invalidating the rest of the recording. The affected row and cumulative quality are exposed through missing_samples, gap_duration_us, interpolated, cumulative_missing_samples, and cumulative_interpolated_duration_us. Duplicate, stale, and invalid-sequence samples are excluded from plots and integration and counted by discarded_sequence_samples and cumulative_discarded_sequence_samples. The GUI reports completeness as the fraction of elapsed time covered by received intervals rather than estimated gap intervals.

The Offline Recordings section loads the catalog stored by the KM003C, downloads a selected entry, and switches the same three plots between live and offline data. Offline exports use the same 23-column Parquet/CSV schema as live captures. Fields that the device does not store in offline samples—sequence, marker, sample rate, gap quality, CC1/CC2, and D+/D-—are null rather than fabricated as zero. Signed charge and energy preserve the device accumulators; positive throughput is derived from the absolute changes between successive device accumulator values.

Library Usage

use km003c_lib::uom::si::electric_current::ampere;
use km003c_lib::uom::si::electric_potential::volt;
use km003c_lib::{DeviceConfig, GraphSampleRate, KM003C};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect with vendor interface (Full mode - includes init and auth)
    let mut device = KM003C::new(DeviceConfig::vendor()).await?;

    // Access device info (always available in Full mode)
    let state = device.state().unwrap();
    println!("{}", state);  // Pretty-printed device info
    println!("AdcQueue enabled: {}", state.adcqueue_enabled);

    // Simple ADC reading
    let adc = device.request_adc_data().await?;
    println!("Voltage: {:.3} V", adc.vbus.get::<volt>());
    println!("Current: {:.3} A", adc.ibus.get::<ampere>());

    // AdcQueue streaming (if authenticated)
    if device.adcqueue_enabled() {
        device.start_graph_mode(GraphSampleRate::Sps50).await?;
        // ... poll for samples ...
        device.stop_graph_mode().await?;
    }

    Ok(())
}

Memory reads

Use the correlated high-level operation for a connected device. It validates the transaction, confirmation address and size, receives all encrypted USB transfers, and removes AES block padding:

let hardware_id = device.read_memory_block(0x4001_0450, 12).await?;
assert_eq!(hardware_id.len(), 12);

For offline protocol research on previously captured ciphertext, use the pure decrypt helper instead of a device receive method:

let plaintext_blocks = km003c_lib::auth::decrypt_memory_read_response(&ciphertext)
    .ok_or("ciphertext must contain complete AES blocks")?;

The offline helper returns complete decrypted AES blocks because a capture does not itself carry the originally requested byte count.

Stored recordings have a higher-level API. Metadata requests return every catalog entry; each entry carries the memory offset needed to download that specific log:

let catalog = device.request_log_metadata().await?;
if let Some(metadata) = catalog.into_iter().next() {
    let log = device.download_offline_log(metadata).await?;
    println!("downloaded {} samples", log.samples.len());
}

Python bindings

Install the published wheels:

pip install km003c

Wheels are built against the stable ABI, so one wheel per platform covers CPython 3.8 and newer.

To build and test the extension from a checkout instead:

uv sync --locked
uv run maturin develop
uv run pytest -q test_bindings.py

Context-free AdcQueue parsing preserves raw auxiliary-line counts because their scale depends on the configured graph rate. Decode them explicitly when the rate used by StartGraph is known:

packet = km003c.parse_packet(captured_bytes)
raw_queue = packet["DataResponse"]["payloads"][0]
queue = raw_queue.decode(km003c.RATE_50_SPS)

# Or parse directly with the known rate.
packet = km003c.parse_packet_with_graph_rate(captured_bytes, km003c.RATE_50_SPS)

Device Configuration

// Vendor interface (Full mode) - recommended, fastest
let config = DeviceConfig::vendor();

// HID interface (Basic mode) - most compatible, ADC/PD polling only
let config = DeviceConfig::hid();

// Skip USB reset (default on macOS for compatibility)
let config = DeviceConfig::vendor().skip_reset();

Protocol Research

This implementation is based on reverse engineering documented at: km003c-protocol-research

The research repository contains:

  • A capture-backed protocol reference and an explicit list of remaining gaps
  • USB transport documentation
  • PCAPNG captures and analysis tools
  • Firmware analysis notes

Development Status

Working Features

  • Device discovery and dual-interface communication
  • Automatic initialization and streaming authentication
  • Simple ADC measurements
  • AdcQueue high-speed streaming (2-1000 SPS)
  • USB PD message capture and parsing
  • Memory read for device info/calibration
  • Real-time GUI with plotting

Validation

Target Coverage
Linux Tests, lint, docs, package verification, and real KM003C hardware
macOS Workspace compile check; USB reset is skipped by default
Windows Workspace compile check
Python 3.13 Extension build and binding tests

Protocol tests use recorded device traffic and do not require USB hardware. Live testing was performed on firmware 1.9.9 with a Pixel 8 Pro PPS charging through the meter. AdcQueue sequence timing was checked at 2, 10, 50, and 1000 SPS; auxiliary CC/D-line scaling was compared with simultaneous ADC measurements.

Development

The Python development tools require Python 3.10 or newer. The package itself continues to support Python 3.8 or newer.

Common tasks are available through just:

just fmt
just test
just lint
just ci

Hardware commands are deliberately separate from the offline CI gate; use just hardware-stream 50 10 only with a KM003C connected.

Requirements

  • Rust: 1.97 or newer
  • Platforms: Linux, Windows, macOS
  • Hardware: POWER-Z KM003C

Contributing

Contributions welcome! See the research repository for protocol details.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Metadata

Release files for km003c 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for km003c 0.4.0
File Size Uploaded
km003c-0.4.0.tar.gz 128.9 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for km003c 0.4.0
File
km003c-0.4.0-cp38-abi3-win_amd64.whl CPython 3.8 abi3 Windows x86-64 Details
km003c-0.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.8 abi3 Linux glibc 2.17+ x86-64 Details
km003c-0.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.8 abi3 Linux glibc 2.17+ ARM64 Details
km003c-0.4.0-cp38-abi3-macosx_11_0_arm64.whl CPython 3.8 abi3 macOS 11.0+ ARM64 Details
km003c-0.4.0-cp38-abi3-macosx_10_12_x86_64.whl CPython 3.8 abi3 macOS 10.12+ x86-64 Details

Total release size: 2.1 MB

Release files / km003c-0.4.0.tar.gz

Download URL km003c-0.4.0.tar.gz
Size 128.9 kB
Tags Source
SHA-256 checksum
How to use checksums
c1cec24d071016a862983d2e56deab6b8936ba1eb7ad97c70392a41a093c6faf
BLAKE2b-256 checksum
How to use checksums
288b42b50f115c2a54de4b301a01d9c3e268bd8cee837f2c1dd24c36efeed910
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / km003c-0.4.0-cp38-abi3-win_amd64.whl

Download URL km003c-0.4.0-cp38-abi3-win_amd64.whl
Size 281.1 kB
Tags CPython 3.8 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
d73e883b088c9f9d74b5225619f97c8b0ac248a57acb035a9c4ac3c4083320e5
BLAKE2b-256 checksum
How to use checksums
6c267458bbbc80b1972b7052122b1c3ec1cfbe20c968dd0c2c44d2cb55ca7f66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / km003c-0.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL km003c-0.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 457.5 kB
Tags CPython 3.8 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
cb1715715eb8639a7f97db7f1fdb74d8789c400a7d84d60577bf2bce321a9582
BLAKE2b-256 checksum
How to use checksums
bbbce22b46c80da1f01f34c1780d8a65d02115556d5c1094f4cf4bde146c569d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / km003c-0.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL km003c-0.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 436.8 kB
Tags CPython 3.8 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
d9cffd01461e0c61d5cc9bdff28be4dabe364c24a12f35663c574f9c219fb688
BLAKE2b-256 checksum
How to use checksums
d67f73c1f74afd91ed8f62d9e941dec5b44c9196f1efbd6351512430aa4fe7c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / km003c-0.4.0-cp38-abi3-macosx_11_0_arm64.whl

Download URL km003c-0.4.0-cp38-abi3-macosx_11_0_arm64.whl
Size 378.2 kB
Tags CPython 3.8 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
6fa0cd7db9a8581ce92bb93d4735966e5bd17ee6bddb7c69fe9b35ace3d9919d
BLAKE2b-256 checksum
How to use checksums
765cacd770ddc043bbcda8c4cc233308454af9da234e3bd33e19bd4e73a96e4f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / km003c-0.4.0-cp38-abi3-macosx_10_12_x86_64.whl

Download URL km003c-0.4.0-cp38-abi3-macosx_10_12_x86_64.whl
Size 390.1 kB
Tags CPython 3.8 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
f7eb0ab4483ea0ed4d7512e498f759544c400993aecd43408f4fb65d56684dff
BLAKE2b-256 checksum
How to use checksums
b22c4bca2fb0c1370d0eaf7fa6cf06c1db51de970cb97d34bdbffa2def7451cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.0 This release

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page