tapo 0.9.0

Unofficial Tapo API Client. Works with TP-Link Tapo smart devices. Tested with light bulbs (L510, L520, L530, L535, L610, L630), light strips (L900, L920, L930), plugs (P100, P105, P110, P110M, P115), power strips (P300, P304M, P306, P316M), hubs (H100), switches (S200B, S200D, S210) and sensors (KE100, T100, T110, T300, T310, T315).
Documentation
use std::time::{SystemTime, UNIX_EPOCH};

use serde::Serialize;

use super::{
    ControlChildParams, DeviceRebootParams, GetChildDeviceListParams, GetEnergyDataParams,
    GetPowerDataParams, GetTriggerLogsParams, HandshakeParams, LightingEffect, LoginDeviceParams,
    MultipleRequestParams, PlayAlarmParams, SecurePassthroughParams, SegmentEffect,
    SmartCamDoParams, SmartCamGetParams,
};

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "method")]
pub(crate) enum TapoRequest {
    #[serde(rename = "component_nego")]
    ComponentNegotiation(TapoParams<EmptyParams>),
    Handshake(TapoParams<HandshakeParams>),
    LoginDevice(TapoParams<LoginDeviceParams>),
    #[serde(rename = "securePassthrough")]
    SecurePassthrough(TapoParams<SecurePassthroughParams>),
    SetDeviceInfo(Box<TapoParams<serde_json::Value>>),
    SetLightingEffect(Box<TapoParams<LightingEffect>>),
    ApplySegmentEffectRule(Box<TapoParams<SegmentEffect>>),
    DeviceReset(TapoParams<EmptyParams>),
    DeviceReboot(TapoParams<DeviceRebootParams>),
    GetDeviceInfo(TapoParams<EmptyParams>),
    GetDeviceUsage(TapoParams<EmptyParams>),
    GetEnergyUsage(TapoParams<EmptyParams>),
    GetCurrentPower(TapoParams<EmptyParams>),
    GetEnergyData(TapoParams<GetEnergyDataParams>),
    GetPowerData(TapoParams<GetPowerDataParams>),
    GetChildDeviceList(TapoParams<GetChildDeviceListParams>),
    #[cfg(feature = "debug")]
    GetChildDeviceComponentList(TapoParams<EmptyParams>),
    ControlChild(Box<TapoParams<ControlChildParams>>),
    // Child requests
    #[serde(rename = "multipleRequest")]
    MultipleRequest(Box<TapoParams<MultipleRequestParams>>),
    GetTriggerLogs(Box<TapoParams<GetTriggerLogsParams>>),
    #[serde(rename = "get_temp_humidity_records")]
    GetTemperatureHumidityRecords(Box<TapoParams<EmptyParams>>),
    PlayAlarm(TapoParams<PlayAlarmParams>),
    StopAlarm(TapoParams<EmptyParams>),
    #[cfg(feature = "debug")]
    #[serde(rename = "get_support_alarm_type_list")]
    GetSupportedAlarmTypeList(TapoParams<EmptyParams>),
    // Smart Camera requests
    #[serde(rename = "get")]
    SmartCamGet(SmartCamGetParams),
    #[serde(rename = "do")]
    SmartCamDo(SmartCamDoParams),
}

#[derive(Debug, Serialize)]
pub(crate) struct EmptyParams;

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct TapoParams<T> {
    params: T,
    #[serde(skip_serializing_if = "Option::is_none")]
    request_time_milis: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none", rename = "terminalUUID")]
    terminal_uuid: Option<String>,
}

impl<T> TapoParams<T> {
    pub fn new(params: T) -> Self {
        Self {
            params,
            request_time_milis: None,
            terminal_uuid: None,
        }
    }

    pub fn set_request_time_mils(mut self) -> anyhow::Result<Self> {
        self.request_time_milis
            .replace(SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis() as u64);
        Ok(self)
    }

    pub fn set_terminal_uuid(mut self, terminal_uuid: &str) -> Self {
        self.terminal_uuid.replace(terminal_uuid.to_string());
        self
    }
}