alsuren / mijia-homie

A Homie MQTT bridge for the Xiaomi Mijia 2 hygrometer-thermometer. This repo also serves as the monorepo for a handful of helper crates related to Homie and Bluetooth.
Other
64 stars 14 forks source link

btsensor: thread 'main' panicked #498

Closed mreymann closed 4 months ago

mreymann commented 4 months ago

Hello,

I flashed MHO_C401N_v47.bin to an MHO-C401 over the air. The device should now emit BTHome v2 messages.

When using the OTA flash tool, I get sensible readings from the device:

Status: Hardware Version: MHO-C401N 2022, Software Version: 4.7
Vbat: 3067 mV , Temp: 24.48°C, Humi: 46.06%, ID: 22, Reed switch counter: 0, flg: 0x04:r0/t0

I'd like to use btsensor to get the readings from the device, but at the moment it fails:

[pigpen@shuttle2:~/src/btsensor]$ ./target/debug/btsensor | grep A4_C1_38_FB_03_65
thread 'main' panicked at /home/pigpen/.cargo/registry/src/index.crates.io-6f17d22bba15001f/btsensor-0.1.0/src/bthome/v2.rs:373:36:
called `Option::unwrap()` on a `None` value
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
hci0/dev_A4_C1_38_FB_03_65: {0000fcd2-0000-1000-8000-00805f9b34fb: [64, 0, 168, 1, 100, 2, 203, 9, 3, 38, 17]}

My Cargo.toml:

[package]
name = "btsensor"
version = "0.1.0"
edition = "2021"

[dependencies]
btsensor = "0.1.0"
log = "0.4.21"
num_enum = "0.7.2"
thiserror = "1.0.60"
uuid = "1.8.0"
bluez-async = "0.7.1"
futures = "0.3.30"
eyre = "0.6.12"
pretty_env_logger = "0.5.0"
tokio = { version = "1.37.0", features = ["macros", "rt", "rt-multi-thread"] }

My main.rs:

use bluez_async::{BluetoothEvent, BluetoothSession, DeviceEvent};
use btsensor::Reading;
use futures::stream::StreamExt;

#[tokio::main]
async fn main() -> Result<(), eyre::Report> {
    pretty_env_logger::init();

    let (_, session) = BluetoothSession::new().await?;
    let mut events = session.event_stream().await?;

    // Start scanning for Bluetooth devices.
    session.start_discovery().await?;

    // Wait for events.
    while let Some(event) = events.next().await {
        if let BluetoothEvent::Device {
            id,
            event: DeviceEvent::ServiceData { service_data },
        } = event
        {
            println!("{}: {:?}", id, service_data);
            if let Some(reading) = Reading::decode(&service_data) {
                println!("  {}", reading);
            } else {
                println!("  (Failed to decode.)");
            }
        }
    }

    Ok(())
}

Can you give me some hints on how to get it running?

mreymann commented 4 months ago

Ok, I've changed the send format to the "pvvx custom format" on the device. Now it works! Hooray! 👍

...
hci0/dev_A4_C1_38_FB_03_65: {0000181a-0000-1000-8000-00805f9b34fb: [101, 3, 251, 56, 193, 164, 132, 10, 115, 15, 13, 12, 100, 14, 4]}
  a4:c1:38:fb:03:65 (14): 26.92°C, 39.55% humidity, 100%/3085mV battery, flags 0x04
...

Question is: did the device send invalid BTHome v2 messages or did I really find a bug?

qwandor commented 4 months ago

Looks like a bug in the Display implementation for bthome::v2::Element. I'll fix it.