1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use crate::db::Db;
use crate::reading::Reading;
use crate::services::Service;
use crate::threading;
use crate::value::Value;
use crate::Result;
use chrono::Local;
use crossbeam_channel::{Receiver, Sender};
use eventsource::reqwest::Client;
use rouille::url::Url;
use serde::Deserialize;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
const URL: &str = "https://developer-api.nest.com";
pub struct Nest {
service_id: String,
token: String,
}
#[derive(Deserialize, Debug, Clone)]
pub struct Settings {
token: String,
}
impl Nest {
pub fn new(service_id: &str, settings: &Settings) -> Nest {
Nest {
service_id: service_id.into(),
token: settings.token.clone(),
}
}
}
impl Service for Nest {
fn spawn(self: Box<Self>, _db: Arc<Mutex<Db>>, tx: Sender<Reading>, _rx: Receiver<Reading>) -> Result<()> {
threading::spawn(self.service_id.clone(), move || loop {
let client = Client::new(Url::parse_with_params(URL, &[("auth", &self.token)]).unwrap());
for event in client {
if let Ok(event) = event {
if let Some(event_type) = event.event_type {
if event_type == "put" {
self.send_readings(&serde_json::from_str(&event.data).unwrap(), &tx)
.unwrap();
}
}
}
}
})?;
Ok(())
}
}
impl Nest {
fn send_readings(&self, event: &NestEvent, tx: &Sender<Reading>) -> Result<()> {
let now = Local::now();
for (id, thermostat) in event.data.devices.thermostats.iter() {
self.send(
tx,
vec![
Reading {
sensor: format!("{}::{}::ambient_temperature", &self.service_id, &id),
value: Value::Celsius(thermostat.ambient_temperature_c),
timestamp: now,
is_persisted: true,
},
Reading {
sensor: format!("{}::{}::humidity", &self.service_id, &id),
value: Value::Rh(thermostat.humidity),
timestamp: now,
is_persisted: true,
},
],
)?;
}
Ok(())
}
}
#[derive(Deserialize, Debug)]
pub struct NestEvent {
data: NestData,
}
#[derive(Deserialize, Debug)]
pub struct NestData {
devices: NestDevices,
}
#[derive(Deserialize, Debug)]
pub struct NestDevices {
thermostats: HashMap<String, NestThermostat>,
}
#[derive(Deserialize, Debug)]
pub struct NestThermostat {
ambient_temperature_c: f64,
humidity: f64,
}