airtouch5 0.2.0

A library for communicating with AirTouch 5 air conditioning system control consoles
Documentation
//! Set the setpoint of all zones with a sensor to 19℃.
//!
//! Usage:
//!     `nineteen <ip>`
//!
//! Fetches the status of zones from the AirTouch 5 controller at `ip` in order
//! determine whether they have a sensor, and if so, sets their setpoint to 19℃.

use std::{net::IpAddr, str::FromStr};

use airtouch5::{
    types::{
        control::{ZoneControl, ZoneControlType, ZoneControlValue},
        status::ZoneSensorReading,
        Temperature,
    },
    AirTouch5,
};
use simplelog::TermLogger;

const USAGE_STR: &str = "Usage: nineteen <ip>";

/// Set a zone to temperature control at 19℃
const CONTROL_NINETEEN: ZoneControl = ZoneControl {
    power: None,
    control: Some(ZoneControlType::Temperature),
    value: Some(ZoneControlValue::Temperature(Temperature::from_deci(190))),
};

#[tokio::main(flavor = "current_thread")]
pub async fn main() {
    // log to console
    TermLogger::init(
        log::LevelFilter::Debug,
        simplelog::Config::default(),
        simplelog::TerminalMode::Mixed,
        simplelog::ColorChoice::Auto,
    )
    .expect("could non init logger");

    // connect to the given addess
    let addr = IpAddr::from_str(&std::env::args().nth(1).expect(USAGE_STR)).expect(USAGE_STR);
    let controller = AirTouch5::with_ipaddr(addr)
        .await
        .expect("could not connect");

    // fetch the current zone status
    let status = controller
        .zone_status()
        .await
        .expect("could not get zone status");

    // construct `ZoneControl`s for each zone with a sensor
    let zones = status
        .zones
        .iter()
        .filter(|(_, z)| z.sensor_reading != ZoneSensorReading::NoSensor)
        .map(|(i, _)| (*i, CONTROL_NINETEEN));

    // send the control request
    let status = controller
        .control_zones(zones)
        .await
        .expect("could not set zone control");

    // check that all zones were set as expected
    assert!(status.zones.values().all(|z| match z.control {
        // FIXME: awkward, one of status::ZoneControl or control::ZoneControl
        // should probably be renamed
        airtouch5::types::status::ZoneControl::Temperature(_, t)
            if t == Temperature::from_deci(190) =>
            true,
        _ => false,
    }));
}