rsiot/drivers_i2c/pcf8575/
task_read_inputs.rs

1use std::{sync::Arc, time::Duration};
2
3use bitvec::prelude::*;
4use tokio::{sync::Mutex, time::sleep};
5
6use crate::{
7    drivers_i2c::{I2cSlaveAddress, RsiotI2cDriverBase},
8    executor::CmpInOut,
9    message::MsgDataBound,
10};
11
12use super::{state::State, TPinFnOutput};
13
14/// Чтение и обработка входов
15pub struct TaskReadInputs<TMsg, Driver>
16where
17    TMsg: MsgDataBound,
18{
19    pub in_out: CmpInOut<TMsg>,
20    pub driver: Arc<Mutex<Driver>>,
21    pub address: I2cSlaveAddress,
22    pub pin_and_fn_output: TPinFnOutput<TMsg>,
23    pub state: State,
24}
25
26impl<TMsg, Driver> TaskReadInputs<TMsg, Driver>
27where
28    TMsg: MsgDataBound,
29    Driver: RsiotI2cDriverBase,
30{
31    pub async fn spawn(&self) -> Result<(), String> {
32        let mut status_saved = 0u16;
33        let status_saved_bits = status_saved.view_bits_mut::<Lsb0>();
34        let mut first_cycle = true;
35
36        loop {
37            let state = self.state.to_bytes().await;
38            let status_current = {
39                let mut driver = self.driver.lock().await;
40                driver
41                    .write_read(self.address, &state, 2, Duration::from_secs(2))
42                    .await
43                    .map_err(String::from)?
44            };
45            let status_current_bits = status_current.view_bits::<Lsb0>();
46            for (pin, fn_output) in &self.pin_and_fn_output {
47                if (status_current_bits[*pin] != status_saved_bits[*pin]) || first_cycle {
48                    let msg = fn_output(!status_current_bits[*pin]);
49                    status_saved_bits.set(*pin, status_current_bits[*pin]);
50                    let Some(msg) = msg else { continue };
51                    self.in_out
52                        .send_output(msg)
53                        .await
54                        .map_err(|e| e.to_string())?;
55                }
56            }
57            first_cycle = false;
58
59            sleep(Duration::from_millis(100)).await;
60        }
61    }
62}