km003c-rs
Typed Rust library, CLI tools, GUI monitor, and Python bindings for the ChargerLAB POWER-Z KM003C USB-C power analyzer.
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.
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
usbpdcrate - 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
usbpdfeature - Typed firmware PD state-trace parsing
km003c-cli
Command-line tools:
adc_simple- Single-shot ADC readings with device infoadc_queue_simple- AdcQueue streaming demotest_usbpd- USB PD negotiation captureoffline-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.
Related Projects
- km003c-protocol-research - Protocol reverse engineering
- usbpd - Rust USB PD protocol library
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)
| File | Size | Uploaded | |
|---|---|---|---|
| km003c-0.4.0.tar.gz | 128.9 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| 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 logRelease 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 logRelease 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 logRelease 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 logRelease 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 logRelease 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