rsiot/drivers_i2c/pm_rq8/
device.rs

1use std::{sync::Arc, time::Duration};
2
3use futures::TryFutureExt;
4use tokio::{
5    sync::{mpsc::channel, Mutex},
6    task::JoinSet,
7};
8
9use crate::{
10    components::shared_tasks,
11    drivers_i2c::RsiotI2cDriverBase,
12    executor::{join_set_spawn, CmpInOut},
13    message::MsgDataBound,
14};
15
16use super::tasks;
17
18use super::Config;
19
20/// Модуль PM-RQ8
21pub struct Device<TMsg, TDriver>
22where
23    TMsg: MsgDataBound,
24    TDriver: RsiotI2cDriverBase,
25{
26    /// Внутренняя шина сообщений
27    pub msg_bus: CmpInOut<TMsg>,
28
29    /// Конфигурация
30    pub config: Config<TMsg>,
31
32    /// Драйвер I2C
33    pub driver: Arc<Mutex<TDriver>>,
34}
35
36impl<TMsg, TDriver> Device<TMsg, TDriver>
37where
38    TMsg: MsgDataBound + 'static,
39    TDriver: RsiotI2cDriverBase + 'static,
40{
41    /// Запустить на выполнение
42    pub async fn spawn(self) {
43        let buffer = super::config::Buffer::default();
44        let buffer: Arc<Mutex<super::config::Buffer>> = buffer.into();
45
46        let mut task_set: JoinSet<super::Result<()>> = JoinSet::new();
47
48        let (ch_0_send, ch_0_recv) = channel(100);
49        let (ch_1_send, ch_1_recv) = channel(100);
50        let (ch_2_send, ch_2_recv) = channel(100);
51
52        // Входящие сообщения в канал mpsc
53        let task = shared_tasks::msgbus_to_mpsc::MsgBusToMpsc {
54            msg_bus: self.msg_bus.clone(),
55            output: ch_0_send,
56        };
57        join_set_spawn(
58            &mut task_set,
59            task.spawn().map_err(super::Error::TaskMsgBusToMpsc),
60        );
61
62        // Обработка входящих сообщений
63        let task = tasks::Input {
64            input: ch_0_recv,
65            output: ch_1_send.clone(),
66            fn_input: self.config.fn_input,
67            buffer: buffer.clone(),
68        };
69        join_set_spawn(&mut task_set, task.spawn());
70
71        // Периодическая отправка, для надежности
72        let task = tasks::InputPeriodic {
73            output: ch_1_send,
74            buffer,
75            period: Duration::from_millis(1000),
76        };
77        join_set_spawn(&mut task_set, task.spawn());
78
79        // Коммуникация I2C
80        let task = tasks::I2cComm {
81            input: ch_1_recv,
82            output: ch_2_send,
83            i2c_driver: self.driver.clone(),
84            address: self.config.address,
85        };
86        join_set_spawn(&mut task_set, task.spawn());
87
88        // Обработка ответа
89        let task = tasks::Output {
90            input: ch_2_recv,
91            output: self.msg_bus,
92        };
93        join_set_spawn(&mut task_set, task.spawn());
94
95        while let Some(res) = task_set.join_next().await {
96            res.unwrap().unwrap();
97        }
98    }
99}