Skip to content

viljami/ruuvi-decoders

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ruuvi Decoders 🦀

Crates.io Documentation License: MIT Build Status

High-performance Rust library for decoding Ruuvi sensor BLE advertisements. Supports all major Ruuvi data formats with comprehensive validation and type safety.

Features

  • 🚀 High Performance: Optimized for minimal latency
  • 🔒 Type Safe: Leverages Rust's type system for data integrity
  • 📊 Complete Coverage: Supports Data Formats v5, v6, and E1
  • 🧪 Thoroughly Tested: All official test vectors pass
  • 🔧 Easy Integration: Simple API with comprehensive error handling

Supported Formats

Format Status Description
v5 (RAWv2) ✅ Complete Temperature, humidity, pressure, acceleration, battery
v6 ✅ Complete Adds PM2.5, CO2, VOC, NOX, luminosity
E1 ✅ Complete Extended format with PM1.0/2.5/4.0/10.0

Quick Start

Add this to your Cargo.toml:

[dependencies]
ruuvi-decoders = "0.2"

Basic Usage

use ruuvi_decoders::{decode, extract_ruuvi_from_ble};

// From a full BLE advertisement
let ble_data = "02010603031691FF990405159F7C025A8BC4A53C00FB00000000E7FEE7FE00E7FE";
let ruuvi_hex = extract_ruuvi_from_ble(ble_data).unwrap();
let decoded = decode(&ruuvi_hex).unwrap();

match decoded {
    ruuvi_decoders::RuuviData::V5(data) => {
        println!("Temperature: {}°C", data.temperature.unwrap());
        println!("Humidity: {}%", data.humidity.unwrap());
        println!("Pressure: {} Pa", data.pressure.unwrap());
        println!("MAC: {}", data.mac_address);
    },
    // Handle v6 and E1 formats...
    _ => println!("Other format"),
}

Direct Hex Decoding

use ruuvi_decoders::decode;

// Direct Ruuvi payload (without BLE wrapper)
let hex_data = "0512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F";
let result = decode(hex_data).unwrap();

if let ruuvi_decoders::RuuviData::V5(data) = result {
    assert_eq!(data.temperature, Some(24.3));
    assert_eq!(data.humidity, Some(53.49));
    assert_eq!(data.pressure, Some(100044.0));
}

Data Format v5 (RAWv2)

The most common format used by RuuviTag sensors:

use ruuvi_decoders::v5::decode;

let bytes = hex::decode("0512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F").unwrap();
let data = decode(&bytes).unwrap();

println!("Sensor Data:");
println!("  MAC: {}", data.mac_address);
println!("  Temperature: {:.2}°C", data.temperature.unwrap_or(0.0));
println!("  Humidity: {:.2}%", data.humidity.unwrap_or(0.0));
println!("  Pressure: {:.0} Pa", data.pressure.unwrap_or(0.0));
println!("  Battery: {} mV", data.battery_voltage.unwrap_or(0));
println!("  TX Power: {} dBm", data.tx_power.unwrap_or(0));

Error Handling

The library provides comprehensive error handling:

use ruuvi_decoders::{decode, DecodeError};

match decode("invalid_hex") {
    Ok(data) => println!("Decoded: {:?}", data),
    Err(DecodeError::InvalidHex(msg)) => eprintln!("Invalid hex: {}", msg),
    Err(DecodeError::UnsupportedFormat(format)) => {
        eprintln!("Unsupported format: 0x{:02X}", format)
    },
    Err(DecodeError::InvalidLength(msg)) => eprintln!("Wrong length: {}", msg),
    Err(e) => eprintln!("Other error: {}", e),
}

Integration with Serde

All data structures support serialization:

use ruuvi_decoders::decode;

let hex_data = "0512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F";
let decoded = decode(hex_data).unwrap();

// Serialize to JSON
let json = serde_json::to_string(&decoded).unwrap();
println!("JSON: {}", json);

// Deserialize from JSON
let restored: ruuvi_decoders::RuuviData = serde_json::from_str(&json).unwrap();

Validation and Invalid Values

The library properly handles invalid/unavailable sensor readings:

use ruuvi_decoders::v5::decode;

// Test with invalid values (from official test vectors)
let invalid_data = hex::decode("058000FFFFFFFF800080008000FFFFFFFFFFFFFFFFFFFFFF").unwrap();
let result = decode(&invalid_data).unwrap();

// All sensor readings will be None for invalid data
assert_eq!(result.temperature, None);
assert_eq!(result.humidity, None);
assert_eq!(result.pressure, None);
assert_eq!(result.mac_address, "invalid");

Performance

Ruuvi Decoders is optimized for high-throughput scenarios:

  • Decoding: ~0.8μs per v5 message on modern hardware
  • Memory: Zero heap allocations in decode path
  • Throughput: >1M messages/second/core

Run benchmarks:

cargo bench

Examples

See the examples/ directory for complete examples:

Run an example:

cargo run --example basic_usage

Specification Compliance

This library implements the official Ruuvi specifications:

All test vectors from the official documentation are included and pass.

Development

Building

git clone https://github.com/ruuvi/ruuvi-decoders
cd ruuvi-decoders
cargo build

Testing

# Run all tests
cargo test

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Related Projects

About

Ruuvi BLE advertisement decoders for Data Formats v5, v6, and E1

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages