rsiot/drivers_i2c/ds3231/
device.rs

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
use std::{sync::Arc, time::Duration};

use tokio::{sync::Mutex, task::JoinSet};
use tracing::warn;

use crate::{
    executor::CmpInOut,
    message::{Message, MsgDataBound, ServiceBound},
};

use super::{
    super::{I2cSlaveAddress, RsiotI2cDriverBase},
    task_input::{InputData, TaskInput},
    task_output::{OutputData, TaskOutput},
};

/// Часы реального времени
pub struct DS3231<TMsg, TService>
where
    TMsg: MsgDataBound,
    TService: ServiceBound,
{
    /// Адрес. По-умолчанию 0x68
    pub address: I2cSlaveAddress,
    /// Функция преобразования входящих сообщений в данные для записи в модуль
    pub fn_input: fn(Message<TMsg>) -> Option<InputData>,
    /// Функция преобразования данных с модуля в исходящие сообщения
    pub fn_output: fn(OutputData) -> Option<Vec<Message<TMsg>>>,
    /// Период чтения данных с часов
    pub fn_output_period: Duration,
    /// Внутренняя шина сообщений
    pub in_out: CmpInOut<TMsg, TService>,
}

impl<TMsg, TService> DS3231<TMsg, TService>
where
    TMsg: MsgDataBound + 'static,
    TService: ServiceBound + 'static,
{
    /// Запустить опрос датчика
    pub async fn spawn(&self, driver: Arc<Mutex<impl RsiotI2cDriverBase + 'static>>) {
        loop {
            let mut task_set: JoinSet<Result<(), String>> = JoinSet::new();

            let task_input = TaskInput {
                address: self.address,
                driver: driver.clone(),
                fn_input: self.fn_input,
                in_out: self.in_out.clone(),
            };
            task_set.spawn(async move { task_input.spawn().await });

            let task_output = TaskOutput {
                address: self.address,
                period: self.fn_output_period,
                driver: driver.clone(),
                fn_output: self.fn_output,
                in_out: self.in_out.clone(),
            };
            task_set.spawn(async move { task_output.spawn().await });

            while let Some(res) = task_set.join_next().await {
                warn!("{res:?}");
                task_set.shutdown().await;
            }
        }
    }
}