| Crates.io | hdc-rs |
| lib.rs | hdc-rs |
| version | 0.1.2 |
| created_at | 2026-01-07 07:51:18.843827+00 |
| updated_at | 2026-01-08 07:04:35.844481+00 |
| description | Rust client library for HarmonyOS Device Connector (HDC) |
| homepage | https://github.com/oslo254804746/hdc-rs |
| repository | https://github.com/oslo254804746/hdc-rs |
| max_upload_size | |
| id | 2027741 |
| size | 171,667 |
A pure Rust implementation of the HarmonyOS Device Connector (HDC) client library, providing both async and blocking APIs for interacting with HarmonyOS/OpenHarmony devices.
Note: HDC is to HarmonyOS what ADB is to Android - a bridge for device communication, debugging, and development.
bytes crateAdd this to your Cargo.toml:
[dependencies]
hdc-rs = "0.1"
tokio = { version = "1", features = ["full"] }
blocking - Enable synchronous/blocking API for FFI bindings[dependencies]
hdc-rs = { version = "0.1", features = ["blocking"] }
use hdc_rs::HdcClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to HDC server
let mut client = HdcClient::connect("127.0.0.1:8710").await?;
// List connected devices
let devices = client.list_targets().await?;
println!("Devices: {:?}", devices);
if devices.is_empty() {
println!("No devices connected!");
return Ok(());
}
// Select and connect to first device
client.connect_device(&devices[0]).await?;
println!("Connected to device: {}", devices[0]);
// Execute shell command on the selected device
let output = client.shell("ls -l /data").await?;
println!("Output:\n{}", output);
Ok(())
}
Enable the blocking feature for synchronous API:
[dependencies]
hdc-rs = { version = "0.1", features = ["blocking"] }
use hdc_rs::blocking::HdcClient;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to HDC server (synchronous!)
let mut client = HdcClient::connect("127.0.0.1:8710")?;
// List connected devices
let devices = client.list_targets()?;
println!("Devices: {:?}", devices);
if !devices.is_empty() {
// Connect and execute command
client.connect_device(&devices[0])?;
let output = client.shell("uname -a")?;
println!("Output: {}", output);
}
Ok(())
}
The repository includes several examples demonstrating different features:
| Example | Description | Command |
|---|---|---|
list_devices |
List all connected devices | cargo run --example list_devices |
simple_shell |
Interactive shell session | cargo run --example simple_shell |
blocking_demo |
Synchronous API demo | cargo run --example blocking_demo --features blocking |
device_monitor |
Monitor device connections | cargo run --example device_monitor |
file_demo |
File transfer operations | cargo run --example file_demo |
forward_demo |
Port forwarding setup | cargo run --example forward_demo |
app_demo |
App install/uninstall | cargo run --example app_demo |
hilog_demo |
Device log streaming | cargo run --example hilog_demo |
comprehensive |
All features combined | cargo run --example comprehensive |
# List all connected devices
cargo run --example list_devices
# Blocking API demo (synchronous)
cargo run --example blocking_demo --features blocking
# Monitor device connections/disconnections
cargo run --example device_monitor
# Interactive shell
cargo run --example simple_shell
# File transfer demo
cargo run --example file_demo
# Port forwarding demo
cargo run --example forward_demo
# App installation demo
cargo run --example app_demo
# Hilog (device logs) demo
cargo run --example hilog_demo
# Comprehensive example (all features)
cargo run --example comprehensive
# Enable debug logging for troubleshooting
RUST_LOG=hdc_rs=debug cargo run --example list_devices
For detailed API documentation, visit docs.rs/hdc-rs.
HdcClient - Main async client for HDC communicationblocking::HdcClient - Synchronous wrapper for FFI bindingsHdcError - Comprehensive error type with contextForwardNode - Port forwarding endpoint specificationInstallOptions / UninstallOptions - App management optionsFileTransferOptions - File transfer configurationβββββββββββββββββββ
β Your App β βββ Your Rust application
ββββββββββ¬βββββββββ
β (uses hdc-rs API)
βΌ
βββββββββββββββββββ
β hdc-rs β βββ This library (Rust)
β βββββββββββββ β
β β Client β β - Connection management
β β Protocol β β - Packet codec
β β Commands β β - Error handling
β βββββββββββββ β
ββββββββββ¬βββββββββ
β (TCP socket: 127.0.0.1:8710)
βΌ
βββββββββββββββββββ
β HDC Server β βββ Native HDC daemon
β (daemon) β
ββββββββββ¬βββββββββ
β (USB/TCP connection)
βΌ
βββββββββββββββββββ
β HarmonyOS β βββ Target device
β Device β
βββββββββββββββββββ
hdc-rs/
βββ hdc-rs/ # Core Rust library
β βββ src/
β β βββ lib.rs # Public API
β β βββ client.rs # HdcClient implementation
β β βββ blocking.rs # Synchronous wrapper
β β βββ error.rs # Error types
β β βββ app.rs # App management
β β βββ file.rs # File transfer
β β βββ forward.rs # Port forwarding
β β βββ protocol/ # Protocol implementation
β β βββ packet.rs # Packet codec
β β βββ command.rs # Command builders
β β βββ channel.rs # Channel management
β βββ Cargo.toml
βββ hdc-py/ # Python bindings (PyO3)
β βββ src/lib.rs
β βββ Cargo.toml
βββ examples/ # Usage examples
βββ tests/ # Integration tests
HDC uses a simple length-prefixed binary protocol over TCP:
ββββββββββββββββββββββββββββββββ
β 4 bytes: Payload Length β (Big-endian u32)
ββββββββββββββββββββββββββββββββ€
β N bytes: Payload Data β (Command + Arguments)
ββββββββββββββββββββββββββββββββ
Client Server
β β
βββββ TCP Connect ββββββββββββββ>β
β β
β<ββββ Handshake (Channel ID) ββββ€
β β
βββββ Connect Key ββββββββββββββ>β
β β
β<ββββ OK βββββββββββββββββββββββββ€
β β
βββββ Command ββββββββββββββββββ>β
β β
β<ββββ Response βββββββββββββββββββ€
β β
βββββ Close ββββββββββββββββββββ>β
β β
| Command | Description | Status |
|---|---|---|
list targets |
List connected devices | β Implemented |
checkserver |
Get server version | β Implemented |
tmode port <port> |
Connect device over TCP | β Implemented |
shell <cmd> |
Execute shell command | β Implemented |
file send <local> <remote> |
Upload file | β Implemented |
file recv <remote> <local> |
Download file | β Implemented |
fport <local> <remote> |
Forward port | β Implemented |
rport <remote> <local> |
Reverse forward | β Implemented |
install <path> |
Install app | β Implemented |
uninstall <pkg> |
Uninstall app | β Implemented |
hilog |
Stream device logs | β Implemented |
wait-for-device |
Wait for device | β Implemented |
This project includes Python bindings built with PyO3. See hdc-py/README.md for complete documentation.
from hdc_rs import HdcClient
# Connect and list devices
client = HdcClient("127.0.0.1:8710")
devices = client.list_targets()
print(f"Devices: {devices}")
if devices:
# Execute command
client.connect_device(devices[0])
output = client.shell("uname -a")
print(output)
cd hdc-py
pip install maturin
maturin develop # Development mode
# or
maturin build --release # Build wheel
pip install target/wheels/hdc_rs-*.whl
Main client for HDC communication.
connect(address) - Connect to HDC serverclose() - Close connectionis_connected() - Check if connectedlist_targets() - List all connected devicesconnect_device(device_id) - Select a device for subsequent commandscheck_server() - Get server versionwait_for_device() - Block until a device is connectedmonitor_devices(interval, callback) - Monitor device list changes with polling
interval: Polling interval (e.g., Duration::from_secs(2))callback: Function called when device list changes, return false to stopshell(cmd) - Execute shell command on the currently selected device
connect_device() first, or server will return errorshell_on_device(device_id, cmd) - Execute shell command on specific devicetarget_command(device_id, cmd) - Execute any command on specific devicefport(local, remote) - Forward local traffic to remote device
fport(ForwardNode::Tcp(8080), ForwardNode::Tcp(8081))rport(remote, local) - Reverse forward remote traffic to local host
rport(ForwardNode::Tcp(9090), ForwardNode::Tcp(9091))fport_list() - List all active forward/reverse tasksfport_remove(task_str) - Remove a forward task by task string
fport_remove("tcp:8080 tcp:8081")Forward Node Types:
ForwardNode::Tcp(port) - TCP portForwardNode::LocalFilesystem(path) - Unix domain socket (filesystem)ForwardNode::LocalReserved(name) - Unix domain socket (reserved)ForwardNode::LocalAbstract(name) - Unix domain socket (abstract)ForwardNode::Dev(name) - DeviceForwardNode::Jdwp(pid) - JDWP (Java Debug Wire Protocol, remote only)ForwardNode::Ark { pid, tid, debugger } - Ark debugger (remote only)install(paths, options) - Install application package(s)
paths: Single or multiple .hap/.hsp files or directoriesoptions: InstallOptions::new().replace(true).shared(false)
replace: Replace existing applicationshared: Install shared bundle for multi-appsuninstall(package, options) - Uninstall application package
package: Package name (e.g., "com.example.app")options: UninstallOptions::new().keep_data(true).shared(false)
keep_data: Keep the data and cache directoriesshared: Remove shared bundlehilog(args) - Read device logs (buffered mode)
args: Optional hilog arguments (e.g., "-h" for help, "-t app" for app logs)hilog_stream(args, callback) - Streaming hilog to given callbackfile_send(local, remote, options) - Send file to device
local: Local file pathremote: Remote device pathoptions: FileTransferOptions - configure transfer behaviorfile_recv(remote, local, options) - Receive file from device
remote: Remote device pathlocal: Local file pathoptions: FileTransferOptions - configure transfer behaviorFile Transfer Options:
hold_timestamp(bool) - Preserve file timestamps (-a)sync_mode(bool) - Only update if source is newer (-sync)compress(bool) - Compress during transfer (-z)mode_sync(bool) - Sync file permissions (-m)debug_dir(bool) - Transfer to/from debug app directory (-b)am device logs continuously
args: Optional hilog argumentscallback: Function called for each log chunk, return false to stop streamingOption 1: Select device first (Recommended)
let mut client = HdcClient::connect("127.0.0.1:8710").await?;
let devices = client.list_targets().await?;
// Connect to device - this re-establishes connection with device ID in handshake
client.connect_device(&devices[0]).await?;
// Now shell commands will be routed to the selected device
let output = client.shell("ls /data").await?;
Option 2: Specify device per command
let mut client = HdcClient::connect("127.0.0.1:8710").await?;
let devices = client.list_targets().await?;
// Execute on specific device without selecting
let output = client.shell_on_device(&devices[0], "ls /data").await?;
Option 3: Port forwarding
use hdc_rs::{HdcClient, ForwardNode};
let mut client = HdcClient::connect("127.0.0.1:8710").await?;
let devices = client.list_targets().await?;
client.connect_device(&devices[0]).await?;
// Forward local TCP 8080 to device TCP 8081
client.fport(ForwardNode::Tcp(8080), ForwardNode::Tcp(8081)).await?;
// List all forwards
let tasks = client.fport_list().await?;
for task in tasks {
println!("Forward: {}", task);
}
// Remove forward
client.fport_remove("tcp:8080 tcp:8081").await?;
Option 4: App management
use hdc_rs::{HdcClient, InstallOptions, UninstallOptions};
let mut client = HdcClient::connect("127.0.0.1:8710").await?;
let devices = client.list_targets().await?;
client.connect_device(&devices[0]).await?;
// Install app (replace if exists)
let opts = InstallOptions::new().replace(true);
client.install(&["app.hap"], opts).await?;
// Uninstall app (keep data)
let opts = UninstallOptions::new().keep_data(true);
client.uninstall("com.example.app", opts).await?;
Option 5: Device logs (hilog)
use hdc_rs::HdcClient;
let mut client = HdcClient::connect("127.0.0.1:8710").await?;
let devices = client.list_targets().await?;
client.connect_device(&devices[0]).await?;
// Get logs as buffered string
let logs = client.hilog(Some("-t app")).await?;
println!("App logs:\n{}", logs);
// Stream logs continuously
client.hilog_stream(None, |log_chunk| {
**Option 6: Monitor device connections**
```rust
use hdc_rs::HdcClient;
use std::time::Duration;
let mut client = HdcClient::connect("127.0.0.1:8710").await?;
// Wait for any device to connect (blocks until a device is available)
let device = client.wait_for_device().await?;
println!("Device connected: {}", device);
// Monitor device list changes in real-time
client.monitor_devices(Duration::from_secs(2), |devices| {
println!("Device list updated: {} device(s)", devices.len());
for device in devices {
println!(" - {}", device);
}
true // Continue monitoring, return false to stop
}).await?;
Option 7: File transfer
use hdc_rs::{HdcClient, FileTransferOptions};
let mut client = HdcClient::connect("127.0.0.1:8710").await?;
let devices = client.list_targets().await?;
client.connect_device(&devices[0]).await?;
// Send file to device with options
let opts = FileTransferOptions::new()
.hold_timestamp(true) // Preserve timestamp
.compress(true); // Compress transfer
client.file_send("local.txt", "/data/local/tmp/remote.txt", opts).await?;
// Receive file from device
let opts = FileTransferOptions::new().sync_mode(true);
client.file_recv("/data/local/tmp/remote.txt", "local.txt", opts).await?;
``` print!("{}", log_chunk);
true // Continue streaming, return false to stop
}).await?;
All methods return Result<T, HdcError>. The library provides comprehensive error types:
use hdc_rs::{HdcClient, HdcError};
match client.shell("ls").await {
Ok(output) => println!("{}", output),
Err(HdcError::NotConnected) => eprintln!("Not connected to HDC server!"),
Err(HdcError::Timeout) => eprintln!("Command timeout!"),
Err(HdcError::DeviceNotFound) => eprintln!("Device not found!"),
Err(HdcError::ProtocolError(msg)) => eprintln!("Protocol error: {}", msg),
Err(e) => eprintln!("Error: {}", e),
}
Available Error Types:
NotConnected - Not connected to HDC serverTimeout - Operation timeoutDeviceNotFound - Target device not foundProtocolError - Protocol-level errorIoError - I/O error (network, file, etc.)InvalidResponse - Invalid server responseCommandFailed - Command execution failedβββββββββββββββββββββββ
β 4 bytes: length β (big-endian u32)
βββββββββββββββββββββββ€
β N bytes: data β
βββββββββββββββββββββββ
list targets, shell, checkserverfile send, file recv)fport, rport)# Clone the repository
git clone https://github.com/oslo254804746/hdc-rs.git
cd hdc-rs
# Build the project
cargo build
# Build with release optimizations
cargo build --release
# Build with all features
cargo build --all-features
# Run all tests
cargo test
# Run integration tests (requires HDC server running)
cargo test --test integration_test
# Run specific test
cargo test test_name
Set the RUST_LOG environment variable for detailed logging:
# Linux/macOS
RUST_LOG=hdc_rs=debug cargo run --example list_devices
# Windows PowerShell
$env:RUST_LOG="hdc_rs=debug"; cargo run --example list_devices
# Windows CMD
set RUST_LOG=hdc_rs=debug && cargo run --example list_devices
# Format code
cargo fmt
# Lint with Clippy
cargo clippy -- -D warnings
# Check without building
cargo check
# Generate and open documentation
cargo doc --open
# Generate documentation for all features
cargo doc --all-features --no-deps --open
Solution:
hdc starthdc list targetshdc tconn <device_ip>:5555Symptoms: HdcError::Timeout or connection hangs
Solution:
netstat -ano | findstr 8710netstat -an | grep 8710 or lsof -i :8710hdc kill then hdc startSymptoms: HdcError::ProtocolError or unexpected responses
Solution:
hdc version or client.check_server().await?Symptoms: HdcError::IoError during file operations
Solution:
Solution:
hdc kill-server then reconnect deviceEnable verbose logging:
RUST_LOG=hdc_rs=trace cargo run --example your_example
Use the comprehensive example:
cargo run --example comprehensive
Check HDC server logs:
hdc -l 5 for verbose HDC loggingTest with official HDC client:
hdc list targets
hdc shell ls /data
If the official client works but hdc-rs doesn't, please file an issue.
bytes crateTypical performance on a modern system:
Contributions are welcome! Here's how you can help:
git checkout -b feature/amazing-feature)cargo test)cargo fmt)cargo clippy)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)# Run all tests
cargo test
# Run specific test suite
cargo test --lib
cargo test --test integration_test
# Run with verbose output
cargo test -- --nocapture
This project is dual-licensed under:
You may choose either license for your use.
Version: 0.1.0
Status: Active Development
Stability: Beta
Made with β€οΈ by the HDC-RS contributors