mihai-dinculescu / tapo

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, P115), power strips (P300, P304), hubs (H100), switches (S200B) and sensors (KE100, T100, T110, T300, T310, T315).
MIT License
390 stars 41 forks source link

P115 support #75

Closed nine-2-five closed 1 year ago

nine-2-five commented 1 year ago

Hi, is Tapo P115 supported?

mihai-dinculescu commented 1 year ago

I don't see why not, but unfortunately, I don't have a P115 to test with.

Can you please try and use it through the P110 interface and see how that goes?

nine-2-five commented 1 year ago

I tried cargo run --example tapo_p110 but I get: Couldn't connect to server

nine-2-five commented 1 year ago

It's actually working. I haven't written a byte in Rust until now, can you help with serializing tapo_date_format to JSON?

nine-2-five commented 1 year ago

I found a way using, not sure if it's the best.

    pub fn serialize<S>(
        date: &OffsetDateTime,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {        
        // let format = format_description::parse(
        //     "[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour \
        //          sign:mandatory]:[offset_minute]:[offset_second]",
        // )?;
        let s = format!("{}", date);
        serializer.serialize_str(&s)
    }
mihai-dinculescu commented 1 year ago

What are you trying to achieve that requires you to serialize a date?

If you're trying to send the tapo responses to another API, which requires serialization, you will probably be better off with building your own structs that #[derive(serde::Serialize)] and map the tapo response into them.

nine-2-five commented 1 year ago

I'd like to save them as JSON to docker stdout log, and pick them up with Logstash. Mapping in Rust is done using From trait? Or is there an automapper lib like in C#?

mihai-dinculescu commented 1 year ago

Probably there are some mappers, but they might be overkill for your use case.

You're correct, the From trait would get the job done quite easily.

#[derive(Debug, serde::Serialize)]
pub struct EnergyData {
    pub local_time: time::OffsetDateTime,
    pub data: Vec<u64>,
    pub start_timestamp: u64,
    pub end_timestamp: u64,
    pub interval: u64,
}

impl From<EnergyDataResult> for EnergyData {
    fn from(energy_data: EnergyDataResult) -> Self {
        Self {
            local_time: energy_data.local_time,
            data: energy_data.data,
            start_timestamp: energy_data.start_timestamp,
            end_timestamp: energy_data.end_timestamp,
            interval: energy_data.interval,
        }
    }
}

Then you can use it like this:

let energy_data: EnergyData = energy_data_monthly.into();
let _json = serde_json::to_string_pretty(&energy_data)?;

One gotcha is that you have to bring in the time crate with the serde feature so that you can serialize time::OffsetDateTime automatically.

time = { version = "0.3", features = ["serde"] }