Last active
November 6, 2022 11:12
-
-
Save passcod/2132f8d1ca33232108f00e86f6147e47 to your computer and use it in GitHub Desktop.
Xiaomi Mi Scale 2 BLE Advertisement decode (service 0x181D) and ESPHome config
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn main() { | |
vec![ | |
// real data | |
[0xa2, 0x0c, 0x49, 0xe6, 0x07, 0x0b, 0x06, 0x01, 0x16, 0x00], // start | |
[0x02, 0x0c, 0x49, 0xe6, 0x07, 0x0b, 0x06, 0x01, 0x20, 0x26], // load | |
[0x22, 0x0c, 0x49, 0xe6, 0x07, 0x0b, 0x06, 0x01, 0x20, 0x26], // stable | |
[0xa2, 0x0c, 0x49, 0xe6, 0x07, 0x0b, 0x06, 0x01, 0x20, 0x2a], // idle | |
] | |
.into_iter() | |
.map(decode) | |
.for_each(|payload| drop(dbg!(payload))); | |
} | |
#[derive(Debug)] | |
#[allow(dead_code)] | |
struct Data { | |
pub flags: u8, | |
pub has_weight: bool, | |
pub stabilised: bool, | |
pub unit: Unit, | |
pub weight: f64, | |
} | |
#[derive(Debug, Clone, Copy)] | |
enum Unit { | |
Jin, | |
Lb, | |
Kg, | |
Unknown, | |
} | |
use std::convert::TryFrom; | |
fn decode(payload: [u8; 10]) -> Data { | |
let flags = payload[0]; | |
let stabilised = flags & (1 << 5) != 0; | |
let has_weight = flags & (1 << 7) == 0; | |
let unit = if flags & (1 << 4) != 0 { | |
Unit::Jin | |
} else if flags & (1 << 2) != 0 { | |
Unit::Lb | |
} else if flags & (1 << 1) != 0 { | |
Unit::Kg | |
} else { | |
Unit::Unknown | |
}; | |
let weight_raw = u16::from_le_bytes([payload[1], payload[2]]); | |
println!("raw={:02x}{:02x} u16={weight_raw}", payload[1], payload[2]); | |
let mut weight = f64::try_from(weight_raw).unwrap() / 100_f64; | |
if let Unit::Kg = unit { | |
weight /= 2.0; | |
} | |
Data { | |
flags, | |
has_weight, | |
stabilised, | |
unit, | |
weight, | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sensor: | |
- platform: template | |
name: "Bathroom Scale" | |
id: bathroom_scale | |
unit_of_measurement: "kg" | |
esp32_ble_tracker: | |
on_ble_service_data_advertise: | |
- mac_address: 70:87:9E:11:22:33 | |
service_uuid: 181D | |
then: | |
- lambda: |- | |
uint8_t flags = x[0]; | |
bool has_weight = (flags & (1 << 7)) == 0; | |
bool is_stable = (flags & (1 << 5)) != 0; | |
bool unit_jin = (flags & (1 << 4)) != 0; | |
bool unit_lb = (flags & (1 << 2)) != 0; | |
bool unit_kg = (flags & (1 << 1)) != 0; | |
ESP_LOGD("scale", "Flags: %u has_weight=%u is_stable=%u unit: jin=%u lb=%u kg=%u", flags, has_weight, is_stable, unit_jin, unit_lb, unit_kg); | |
uint16_t weight = (((uint16_t)x[2]) << 8) + x[1]; | |
double weight_f = (static_cast<double>(weight) / 100.0) / 2.0; // kg | |
ESP_LOGD("scale", "Weight: raw=%x%x u16=%u kg=%f", x[1], x[2], weight, weight_f); | |
if (has_weight && is_stable) { | |
ESP_LOGI("scale", "Publish weight %f", weight_f); | |
id(bathroom_scale).publish_state(weight_f); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment