This is an auto generated lib containing concrete types that can easily deserialise any json MQTT payloads from zigbee2mqtt.
To speed up compile time all structs are behind feature flags, these are split into vendors e.g. if you are using a
sensor by xiaomi then you will need to add the xiaomi feature to your Cargo.toml like zigbee2mqtt-types = {features = ["xiaomi"]}
Example of using a door contact sensor (note: debug is also a feature)
add zigbee2mqtt-types = {features = ["debug", "xiaomi"]}
to Cargo.toml dependencies
```rust
use zigbee2mqtt_types::xiaomi::ZigbeeMccgq11lm;
fn contactsensormccgq11lm() { //https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html let json = serdejson::json!({ "voltage": 2995, "battery": 97, "devicetemperature": 19, "poweroutagecount": 6, "linkquality": 247, "contact": false, }) .tostring(); let parsed: ZigbeeMccgq11lm = match serdejson::from_str(&json) { Ok(contact) => contact, Err(err) => { println!("{:?}", err); assert!(false); } };
assert_eq!(2995, parsed.voltage);
assert_eq!(97, parsed.battery);
assert_eq!(19, parsed.device_temperature);
assert_eq!(6, parsed.power_outage_count);
assert_eq!(247, parsed.linkquality);
assert_eq!(false, parsed.contact);
} ```
Zigbee2MQTT has two additional options that add data to the JSON, 1) elapsed, 2) last_seen. There is a feature flag to also convert these to their static types (Note: Atm I am converting timestamps to String, I didn't want to way into converting the string into a real time struct I'm sorry. PR welcome, but I fear devils are awaiting)
1) Elapsed can be enabled with feature = elapsed
and it gets converted to a elapsed: u64
2) Lastseen can be iso8601(local and utc) or epoch. Note: A parse error will be thrown if these features are enabled but the field is not present in the json
- For either of the iso use feature = last_seen_iso_8601
and it gets converted to a last_seen: String
- For epoch use feature = last_seen_epoch
and it gets converted to a last_seen: u64
- Note: last_seen features are mutually exclusive as they both resolve to the same struct field just with different types, this does break Rust convention but I see no real use case that both would be enabled. If you have one please open an issue and I can look at a way to make it not mutually exclusive
These features manifest like so
```rust use zigbee2mqtt_types::xiaomi::ZigbeeMccgq11lm;
fn contactsensormccgq11lmlastseeniso8601elapsed() { //https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html let json = serdejson::json!({ "voltage": 2995, "battery": 97, "devicetemperature": 19, "lastseen": "20221020T11:55:07.199z", // zigbee2mqtt lastseen setting in ISO8601 mode "poweroutagecount": 6, "linkquality": 247, "contact": false, "elapsed": 2547593 // zigbee2mqtt elapsed setting true }) .tostring(); let parsed: ZigbeeMccgq11lm = match serdejson::fromstr(&json) { Ok(contact) => contact, Err(err) => { println!("{:?}", err); // with lastseen or elapsed feature flags turned on a parse errr will be thrown if not present in the json assert!(false); } };
assert_eq!("2022_10_20T11:55:07.199z", parsed.last_seen); // last_seen parsed to a string
assert_eq!(2547593, parsed.elapsed); // elapsed parsed to a u64
assert_eq!(2995, parsed.voltage);
assert_eq!(97, parsed.battery);
assert_eq!(19, parsed.device_temperature);
assert_eq!(6, parsed.power_outage_count);
assert_eq!(247, parsed.linkquality);
assert_eq!(false, parsed.contact);
} ```
1 gotcha is all not all model/vendor names strings conform to Rusts struct/package naming convention, so I needed
todo some transformation to them. Models roughly remove all invalid chars and have Zigbee infront of them. Vendors have
an _
in place of any invalid chars
example of changes to models
txt
"ZS057-D0Z" = "ZigbeeZs057Dd0z"
"BF 265" = "ZigbeeBf265"
"5110.40" = "Zigbee5110F40"
"MEAZON_BIZY_PLUG" = "ZigbeeMeazonUbizyUplug"
example of changes to vendors
txt
"Eaton/Halo LED" = "eaton_halo_led"
"Custom devices (DiY)" = "custom_devices__diy_"
"Villeroy & Boch" = "villeroy___boch"
"J.XUAN" = "j_xuan"
// the bellow is just removing non ascii chars I would personally prefer to swap them for similar ascii but for now I will _
"Müller Licht" = "m_ller_licht"
"Sinopé" = "sinop_"
Model function that does conversion is here Vendor function that does conversion is here
I currently don't parse object values so color on the philips light in mqtt it is "color": {"hue":25,"saturation":95,"x":0.5267,"y":0.4133}
,
in short anything with a {
in the value is not parsed. This will be fixed in a future update I just wanted to reduce scope
While creating a recent project I found myself being lazy with how I was defining my structs to consume MQTT payloads and given they are already defined in Zigbee2MQTT I went looking for a way to generate them programmatically.
All development should be in the top level generator binary as zigbee-herdsman updates too frequently to maintain human updating of this lib. Atm I don't have this generating wit CI but at some point I plan to that to keep this up to date with zigbee-herdsman
Up to date issues can be seen here https://gitlab.com/seam345/zigbee2mqtt-types/-/issues