zigbee2mqtt-types 0.4.0

Struct definitions for zigbee2mqtt json messages.
Documentation
// a few random tests to document how the crate can be used and confirm thing are working
// Actually I say random but I'm probably going to be biased and test the zigbee devices I have :/ :D

#[cfg(all(feature = "xiaomi", feature = "debug"))]
#[test]
fn contact_sensor_mccgq11lm() {
    //https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html
    let json = serde_json::json!({
        "voltage": 2995,
        "battery": 97,
        "device_temperature": 19,
        "power_outage_count": 6,
        "linkquality": 247,
        "contact": false,
    })
    .to_string();
    let parsed: zigbee2mqtt_types::xiaomi::ZigbeeMccgq11lm = match serde_json::from_str(&json) {
        Ok(contact) => contact,
        Err(err) => {
            println!("{:?}", err);
            assert!(false);
            unimplemented!()
        }
    };

    assert_eq!(None, parsed.last_seen);
    assert_eq!(None, parsed.elapsed);
    assert_eq!(2995.0, parsed.voltage);
    assert_eq!(97.0, parsed.battery);
    assert_eq!(19.0, parsed.device_temperature);
    assert_eq!(6.0, parsed.power_outage_count);
    assert_eq!(247.0, parsed.linkquality);
    assert_eq!(false, parsed.contact);
}

#[cfg(all(feature = "xiaomi", feature = "debug"))]
#[test]
fn contact_sensor_mccgq11lm_last_seen_iso_8601() {
    //https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html
    let json = serde_json::json!({
        "voltage": 2995,
        "battery": 97,
        "device_temperature": 19,
        "last_seen": "2022_10_20T11:55:07.199z", // this is a zigbee2mqtt setting, see https://www.zigbee2mqtt.io/guide/configuration/mqtt.html#mqtt-behaviour
        "power_outage_count": 6,
        "linkquality": 247,
        "contact": false,
    })
    .to_string();
    let parsed: zigbee2mqtt_types::xiaomi::ZigbeeMccgq11lm = match serde_json::from_str(&json) {
        Ok(contact) => contact,
        Err(err) => {
            println!("{:?}", err);
            assert!(false);
            unimplemented!()
        }
    };

    match parsed.last_seen.unwrap() {
        zigbee2mqtt_types_base_types::LastSeen::Iso8601(val) => {
            assert_eq!("2022_10_20T11:55:07.199z", val);
        }
        zigbee2mqtt_types_base_types::LastSeen::Epoch(_) => {
            panic!("Value parsed as epoch instead of Iso8601")
        }
    }

    assert_eq!(2995.0, parsed.voltage);
    assert_eq!(97.0, parsed.battery);
    assert_eq!(19.0, parsed.device_temperature);
    assert_eq!(6.0, parsed.power_outage_count);
    assert_eq!(247.0, parsed.linkquality);
    assert_eq!(false, parsed.contact);
}

#[cfg(all(feature = "xiaomi", feature = "debug"))]
#[test]
fn contact_sensor_mccgq11lm_last_seen_iso_8601_elapsed() {
    //https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html
    let json = serde_json::json!({
        "voltage": 2995,
        "battery": 97,
        "device_temperature": 19,
        "last_seen": "2022_10_20T11:55:07.199z", // this is a zigbee2mqtt setting, see https://www.zigbee2mqtt.io/guide/configuration/mqtt.html#mqtt-behaviour
        "power_outage_count": 6,
        "linkquality": 247,
        "contact": false,
        "elapsed": 2547593 // another zigbee2mqtt addon setting
    })
    .to_string();
    let parsed: zigbee2mqtt_types::xiaomi::ZigbeeMccgq11lm = match serde_json::from_str(&json) {
        Ok(contact) => contact,
        Err(err) => {
            println!("{:?}", err);
            assert!(false);
            unimplemented!()
        }
    };

    match parsed.last_seen.unwrap() {
        zigbee2mqtt_types_base_types::LastSeen::Iso8601(val) => {
            assert_eq!("2022_10_20T11:55:07.199z", val);
        }
        zigbee2mqtt_types_base_types::LastSeen::Epoch(_) => {
            panic!("Value parsed as epoch instead of Iso8601")
        }
    }

    assert_eq!(Some(2547593), parsed.elapsed);

    assert_eq!(2995.0, parsed.voltage);
    assert_eq!(97.0, parsed.battery);
    assert_eq!(19.0, parsed.device_temperature);
    assert_eq!(6.0, parsed.power_outage_count);
    assert_eq!(247.0, parsed.linkquality);
    assert_eq!(false, parsed.contact);
}

#[cfg(all(feature = "xiaomi", feature = "debug"))]
#[test]
fn contact_sensor_mccgq11lm_elapsed() {
    //https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html
    let json = serde_json::json!({
        "voltage": 2995,
        "battery": 97,
        "device_temperature": 19,
        "power_outage_count": 6,
        "linkquality": 247,
        "contact": false,
        "elapsed": 2547593 // another zigbee2mqtt addon setting
    })
    .to_string();
    let parsed: zigbee2mqtt_types::xiaomi::ZigbeeMccgq11lm = match serde_json::from_str(&json) {
        Ok(contact) => contact,
        Err(err) => {
            println!("{:?}", err);
            assert!(false);
            unimplemented!()
        }
    };

    assert_eq!(Some(2547593), parsed.elapsed);

    assert_eq!(2995.0, parsed.voltage);
    assert_eq!(97.0, parsed.battery);
    assert_eq!(19.0, parsed.device_temperature);
    assert_eq!(6.0, parsed.power_outage_count);
    assert_eq!(247.0, parsed.linkquality);
    assert_eq!(false, parsed.contact);
}

#[cfg(all(feature = "philips", feature = "debug"))]
#[test]
fn motion_sensor_9290012607() {
    //https://www.zigbee2mqtt.io/devices/9290012607.html
    let json = serde_json::json!({
        "occupancy": true,
        "occupancy_timeout": 0,
        "temperature": 17,
        "battery": 100,
        "motion_sensitivity": "high",
        "update": { "state":"available"},
        "illuminance": 0,
        "illuminance_lux": 0,
        "update_available": true,
        "linkquality": 255,
        "led_indication": true
    })
    .to_string();
    let parsed: zigbee2mqtt_types::philips::Zigbee9290012607 = match serde_json::from_str(&json) {
        Ok(contact) => contact,
        Err(err) => {
            println!("{:?}", err);
            assert!(false);
            unimplemented!()
        }
    };

    assert_eq!(0.0, parsed.illuminance);
    assert_eq!(0.0, parsed.illuminance_lux);
    assert_eq!(100.0, parsed.battery);
    assert_eq!(17.0, parsed.temperature);
    assert_eq!(255.0, parsed.linkquality);
    assert_eq!(true, parsed.occupancy);
    assert_eq!(true, parsed.led_indication);
    assert_eq!(
        zigbee2mqtt_types::philips::Zigbee9290012607Motionsensitivity::High,
        parsed.motion_sensitivity
    );
}

// todo double check power_on_behavior is sent or not (after updating zigbee2mqtt device) it has access 7 so should show
// lights dreaded lights!
/*#[cfg(all(feature = "philips", feature = "debug"))]
#[test]
fn spot_light_929001953101() {
    // https://www.zigbee2mqtt.io/devices/929001953101.html#philips-929001953101
    let json = serde_json::json!({
      "brightness": 81.5,
      "color": {
        "hue": 25,
        "saturation": 95,
        "x": 0.5267,
        "y": 0.4133
      },
      "color_mode": "color_temp",
      "color_temp": 500,
      "color_temp_startup": 366,
      "linkquality": 255,
      "state": "OFF",
      "update": {
        "state": "available"
      },
    })
    .to_string();
    let parsed: zigbee2mqtt_types::philips::Zigbee929001953101 = match serde_json::from_str(&json) {
        Ok(contact) => contact,
        Err(err) => {
            println!("{:?}", err);
            assert!(false);
            unimplemented!();
        }
    };
    assert_eq!(81.5, parsed.brightness);
    // assert_eq!(25.0, parsed.color.hue);
    // assert_eq!(95.0, parsed.color.saturation);
    // assert_eq!(0.5267, parsed.color.x);
    // assert_eq!(0.4133, parsed.color.y);
    // assert_eq!(todo!("Some enum"), parsed.color_mode);
    assert_eq!(500.0, parsed.color_temp);
    assert_eq!(366.0, parsed.color_temp_startup);
    assert_eq!(false, parsed.state); //todo maybe enum is nicer!
    assert_eq!(255.0, parsed.linkquality);
    // assert_eq!(
    //     zigbee2mqtt_types::philips::Zigbee9290012607Motionsensitivity::High,
    //     parsed.motion_sensitivity
    // );
}*/


// todo doesnt work atm
/*#[cfg(all(feature = "eurotronic", feature = "debug"))]
#[test]
fn thermostat_eurotronic_spzb0001() {
    //https://www.zigbee2mqtt.io/devices/9290012607.html
    let json = serde_json::json!({
        "battery": 100,
        "occupied_heating_setpoint": 15.5,
        "local_temperature": 100.5,
        "system_mode": "auto",
        "running_state": "idle",
        "local_temperature_calibration": -0.2,
        "pi_heating_demand": 50,
        "trv_mode": 1,
        "valve_position": 123,
        "linkquality": 255,
    })
    .to_string();
    let parsed: zigbee2mqtt_types::eurotronic::ZigbeeSpzb0001 = match serde_json::from_str(&json) {
        Ok(contact) => contact,
        Err(err) => {
            println!("{:?}", err);
            assert!(false);
            unimplemented!()
        }
    };

    // todo update values
    assert_eq!(100.0, parsed.battery);
    // assert_eq!(zigbee2mqtt_types::eurotronic::ZigbeeSpzb0001Trvmode::Number1, parsed.trv_mode);
}*/