Pass SimpleATCommand in Async IO instead of command

This commit is contained in:
Sofia 2026-05-30 17:27:27 +03:00
parent c44ce1dcb3
commit 178fbaa791
4 changed files with 28 additions and 12 deletions

View File

@ -1,6 +1,7 @@
use core::{cell::RefCell, marker::PhantomData}; use core::{cell::RefCell, marker::PhantomData};
use alloc::{ use alloc::{
boxed::Box,
collections::{btree_map::BTreeMap, btree_set::BTreeSet}, collections::{btree_map::BTreeMap, btree_set::BTreeSet},
rc::Rc, rc::Rc,
string::String, string::String,
@ -8,7 +9,7 @@ use alloc::{
}; };
use critical_section::Mutex; use critical_section::Mutex;
use crate::at_commands::{ATCommand, StubATCommand}; use crate::at_commands::{ATCommand, SimpleATCommand, StubATCommand};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum KeypadButton { pub enum KeypadButton {
@ -114,7 +115,8 @@ unsafe impl Sync for ConstructedATCommand {}
#[derive(Clone)] #[derive(Clone)]
pub struct AsyncIO { pub struct AsyncIO {
at_command: Rc<Mutex<RefCell<Option<ConstructedATCommand>>>>, at_command: Rc<Mutex<RefCell<Option<Box<dyn SimpleATCommand>>>>>,
handling_at_command: Rc<Mutex<RefCell<bool>>>,
at_response: Rc<Mutex<RefCell<Option<String>>>>, at_response: Rc<Mutex<RefCell<Option<String>>>>,
pub keypad: Keypad, pub keypad: Keypad,
} }
@ -123,6 +125,7 @@ impl Default for AsyncIO {
fn default() -> Self { fn default() -> Self {
Self { Self {
at_command: Rc::new(Mutex::new(RefCell::new(None))), at_command: Rc::new(Mutex::new(RefCell::new(None))),
handling_at_command: Rc::new(Mutex::new(RefCell::new(false))),
at_response: Rc::new(Mutex::new(RefCell::new(None))), at_response: Rc::new(Mutex::new(RefCell::new(None))),
keypad: Keypad::default(), keypad: Keypad::default(),
} }
@ -154,7 +157,7 @@ impl<T: ATCommand> ATPromise<T> {
} }
impl AsyncIO { impl AsyncIO {
pub fn send_at_command<Resp, T: ATCommand<Response = Resp>>( pub fn send_at_command<Resp, T: ATCommand<Response = Resp> + 'static>(
&self, &self,
command: T, command: T,
) -> Result<ATPromise<T>, ()> { ) -> Result<ATPromise<T>, ()> {
@ -164,21 +167,23 @@ impl AsyncIO {
return Err(()); return Err(());
} }
*borrow = Some(command.execute()); *borrow = Some(Box::new(command));
Ok(ATPromise { _data: PhantomData }) Ok(ATPromise { _data: PhantomData })
}) })
} }
pub unsafe fn check_at_command(&self) -> Option<ConstructedATCommand> { pub unsafe fn check_at_command(self) -> Option<Box<dyn SimpleATCommand>> {
critical_section::with(|cs| { critical_section::with(|cs| {
let borrow = self.at_command.borrow_ref(cs); let mut borrow = self.at_command.borrow_ref_mut(cs);
borrow.clone() *self.handling_at_command.borrow_ref_mut(cs) = true;
borrow.take()
}) })
} }
pub unsafe fn set_at_response(&self, response_str: String) { pub unsafe fn set_at_response(&self, response_str: String) {
critical_section::with(|cs| { critical_section::with(|cs| {
*self.handling_at_command.borrow_ref_mut(cs) = false;
let mut command = self.at_command.borrow_ref_mut(cs); let mut command = self.at_command.borrow_ref_mut(cs);
let mut response = self.at_response.borrow_ref_mut(cs); let mut response = self.at_response.borrow_ref_mut(cs);
command.take(); command.take();
@ -190,7 +195,7 @@ impl AsyncIO {
critical_section::with(|cs| { critical_section::with(|cs| {
let command = self.at_command.borrow_ref(cs); let command = self.at_command.borrow_ref(cs);
let mut response = self.at_response.borrow_ref_mut(cs); let mut response = self.at_response.borrow_ref_mut(cs);
if command.is_some() { if command.is_some() || *self.handling_at_command.borrow_ref(cs) {
return Some(None); return Some(None);
} }
if let Some(resp) = response.take() { if let Some(resp) = response.take() {

View File

@ -2,7 +2,6 @@ use alloc::string::{String, ToString};
use alloc::vec::Vec; use alloc::vec::Vec;
use alloc::{borrow::ToOwned, format}; use alloc::{borrow::ToOwned, format};
use core::fmt::Write; use core::fmt::Write;
use core::marker::PhantomData;
use esp_hal::{Blocking, delay::Delay, gpio::Output, uart::Uart}; use esp_hal::{Blocking, delay::Delay, gpio::Output, uart::Uart};
use crate::async_io::ConstructedATCommand; use crate::async_io::ConstructedATCommand;
@ -173,6 +172,16 @@ pub trait ATCommand: Send + Sync {
fn parse_response(text: String) -> Self::Response; fn parse_response(text: String) -> Self::Response;
} }
pub trait SimpleATCommand: Send + Sync {
fn execute(&self) -> ConstructedATCommand;
}
impl<T: ATCommand> SimpleATCommand for T {
fn execute(&self) -> ConstructedATCommand {
self.execute()
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct StubATCommand(()); pub struct StubATCommand(());
impl ATCommand for StubATCommand { impl ATCommand for StubATCommand {

View File

@ -227,8 +227,8 @@ fn thread_2_main(
let delay = Delay::new(); let delay = Delay::new();
loop { loop {
if let Some(command) = unsafe { async_io.check_at_command() } { if let Some(command) = unsafe { async_io.clone().check_at_command() } {
let response = match command { let response = match command.execute() {
async_io::ConstructedATCommand::Single(cmd) => at_commands.raw_command(cmd), async_io::ConstructedATCommand::Single(cmd) => at_commands.raw_command(cmd),
async_io::ConstructedATCommand::AddInfo(cmd, add) => { async_io::ConstructedATCommand::AddInfo(cmd, add) => {
at_commands.raw_two_part_command(cmd, add) at_commands.raw_two_part_command(cmd, add)

View File

@ -42,7 +42,9 @@ impl<T: State + Clone, Cmd: ATCommand> ATCommandState<T, Cmd> {
} }
} }
impl<T: State + Clone + 'static, Cmd: ATCommand + Clone> State for ATCommandState<T, Cmd> { impl<T: State + Clone + 'static, Cmd: ATCommand + Clone + 'static> State
for ATCommandState<T, Cmd>
{
fn init(&mut self, data: &mut StateData) { fn init(&mut self, data: &mut StateData) {
self.promise = Some(data.io.send_at_command(self.command.clone()).unwrap()); self.promise = Some(data.io.send_at_command(self.command.clone()).unwrap());
} }