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
use crate::io::gpio::{GPIOState, PinUpdate};
use log::{debug, error, info, warn};
use sqlx::{Executor, MySqlPool, Row};
use std::collections::HashMap;
use tokio::sync::mpsc::Receiver;

pub async fn run(conn: MySqlPool, mut receiver: Receiver<PinUpdate>) {
    info!("Running database GPIO updater.");
    let mut map: HashMap<u32, u32> = HashMap::new();

    let result = conn
        .fetch_all(sqlx::query!(
            "SELECT id, channel FROM sensor WHERE type='GPIO'"
        ))
        .await;

    if result.is_err() {
        error!(
            "Failed to fetch GPIO sensors from DB {:?} - WONT BE ABLE TO RECORD INTO DB",
            result.unwrap_err()
        );
        return;
    }

    let rows = result.unwrap();
    for row in rows {
        let channel: String = row.get("channel");
        map.insert(channel.parse().unwrap(), row.get("id"));
    }
    let map = map;
    debug!("Sensor Map: {:?}", map);

    loop {
        let result = receiver.recv().await;
        if result.is_none() {
            warn!("Sender seems to have been dropped for the database gpio updater.");
            break;
        }
        let pin_update = result.unwrap();
        debug!("Received pin update: {:?}", pin_update);

        let pin = pin_update.pin as u32;
        if let Some(sensor_id) = map.get(&pin) {
            let to = gpio_state_to_on_off(&pin_update.to);
            conn.execute(sqlx::query!(
                "INSERT INTO reading (sensor_id, raw_value) VALUES (?,?)",
                sensor_id,
                to
            ))
            .await
            .unwrap();
            debug!("Recorded {sensor_id}: {to} in DB");
        } else {
            error!("No database entry found for gpio pin: {}", pin)
        }
    }

    fn gpio_state_to_on_off(state: &GPIOState) -> u16 {
        match state {
            GPIOState::Low => 1,
            GPIOState::High => 0,
        }
    }
}