Update how InitATState works

This commit is contained in:
Sofia 2026-05-28 23:39:38 +03:00
parent 3ba28b7915
commit 730373a09b
4 changed files with 80 additions and 89 deletions

View File

@ -82,7 +82,7 @@ impl Default for AsyncIO {
unsafe impl Send for AsyncIO {} unsafe impl Send for AsyncIO {}
unsafe impl Sync for AsyncIO {} unsafe impl Sync for AsyncIO {}
#[derive(Default)] #[derive(Default, Clone)]
pub struct ATPromise<T: ATCommand> { pub struct ATPromise<T: ATCommand> {
_data: PhantomData<T>, _data: PhantomData<T>,
} }

View File

@ -160,11 +160,12 @@ impl<'a, 'd> ATCommands<'a, 'd> {
} }
pub trait ATCommand: Send + Sync { pub trait ATCommand: Send + Sync {
type Response; type Response: core::fmt::Debug;
fn execute(&self) -> ConstructedATCommand; fn execute(&self) -> ConstructedATCommand;
fn parse_response(text: String) -> Self::Response; fn parse_response(text: String) -> Self::Response;
} }
#[derive(Debug, Clone)]
pub struct StubATCommand(()); pub struct StubATCommand(());
impl ATCommand for StubATCommand { impl ATCommand for StubATCommand {
type Response = String; type Response = String;
@ -178,6 +179,7 @@ impl ATCommand for StubATCommand {
} }
} }
#[derive(Debug, Clone)]
pub struct ATInformationCommand; pub struct ATInformationCommand;
impl ATCommand for ATInformationCommand { impl ATCommand for ATInformationCommand {
type Response = String; type Response = String;
@ -191,6 +193,7 @@ impl ATCommand for ATInformationCommand {
} }
} }
#[derive(Debug, Clone)]
pub struct EnterPinCommand(pub String); pub struct EnterPinCommand(pub String);
impl ATCommand for EnterPinCommand { impl ATCommand for EnterPinCommand {
type Response = String; type Response = String;
@ -204,6 +207,7 @@ impl ATCommand for EnterPinCommand {
} }
} }
#[derive(Debug, Clone)]
pub struct CheckPinCommand; pub struct CheckPinCommand;
impl ATCommand for CheckPinCommand { impl ATCommand for CheckPinCommand {
type Response = String; type Response = String;
@ -217,12 +221,13 @@ impl ATCommand for CheckPinCommand {
} }
} }
#[derive(Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum SMSFormat { pub enum SMSFormat {
PDUMode = 0, PDUMode = 0,
TextMode = 1, TextMode = 1,
} }
#[derive(Debug, Clone)]
pub struct SelectSMSFormatCommand(pub SMSFormat); pub struct SelectSMSFormatCommand(pub SMSFormat);
impl ATCommand for SelectSMSFormatCommand { impl ATCommand for SelectSMSFormatCommand {
type Response = String; type Response = String;
@ -236,6 +241,7 @@ impl ATCommand for SelectSMSFormatCommand {
} }
} }
#[derive(Debug, Clone)]
pub struct CheckSMSFormatCommand; pub struct CheckSMSFormatCommand;
impl ATCommand for CheckSMSFormatCommand { impl ATCommand for CheckSMSFormatCommand {
type Response = String; type Response = String;
@ -249,6 +255,7 @@ impl ATCommand for CheckSMSFormatCommand {
} }
} }
#[derive(Debug, Clone)]
pub struct ListTECharacterSetsCommand; pub struct ListTECharacterSetsCommand;
impl ATCommand for ListTECharacterSetsCommand { impl ATCommand for ListTECharacterSetsCommand {
type Response = String; type Response = String;
@ -262,7 +269,7 @@ impl ATCommand for ListTECharacterSetsCommand {
} }
} }
#[derive(Clone)] #[derive(Debug, Clone)]
pub enum TECharset { pub enum TECharset {
IRA, IRA,
UCS2, UCS2,
@ -281,6 +288,7 @@ impl TECharset {
} }
} }
#[derive(Debug, Clone)]
pub struct SetTECharsetCommand(pub TECharset); pub struct SetTECharsetCommand(pub TECharset);
impl ATCommand for SetTECharsetCommand { impl ATCommand for SetTECharsetCommand {
type Response = String; type Response = String;
@ -294,6 +302,7 @@ impl ATCommand for SetTECharsetCommand {
} }
} }
#[derive(Debug, Clone)]
pub struct SendSMSCommand { pub struct SendSMSCommand {
pub destination: String, pub destination: String,
pub message: String, pub message: String,

View File

@ -67,6 +67,7 @@ impl<'a> StateData<'a> {
} }
pub trait State { pub trait State {
fn init(&mut self, data: &mut StateData) {}
fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>>; fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>>;
fn draw(&self, data: &mut StateData); fn draw(&self, data: &mut StateData);
} }
@ -79,7 +80,10 @@ pub struct StateManager<'a> {
impl<'a> StateManager<'a> { impl<'a> StateManager<'a> {
pub fn update(&mut self) { pub fn update(&mut self) {
match self.curr_state.update(&mut self.data) { match self.curr_state.update(&mut self.data) {
Some(next_state) => self.curr_state = next_state, Some(next_state) => {
self.curr_state = next_state;
self.curr_state.init(&mut self.data);
}
None => {} None => {}
} }
self.data.io.button.clear(); self.data.io.button.clear();

View File

@ -11,36 +11,43 @@ use esp_hal::time::{Duration, Instant};
use crate::{ use crate::{
async_io::ATPromise, async_io::ATPromise,
at_commands::{ at_commands::{
ATInformationCommand, CheckPinCommand, EnterPinCommand, ListTECharacterSetsCommand, ATCommand, ATInformationCommand, CheckPinCommand, EnterPinCommand,
SMSFormat, SelectSMSFormatCommand, SendSMSCommand, SetTECharsetCommand, StubATCommand, ListTECharacterSetsCommand, SMSFormat, SelectSMSFormatCommand, SendSMSCommand,
TECharset, SetTECharsetCommand, StubATCommand, TECharset,
}, },
display::{Position, Rgb565}, display::{Position, Rgb565},
font::{HorizontalAlignment, VerticalAlignment}, font::{HorizontalAlignment, VerticalAlignment},
state::{State, StateData, TextSettings}, state::{State, StateData, TextSettings},
}; };
pub struct InitATState { #[derive(Clone)]
inner_state: u8, pub struct ATCommandState<T: State, Cmd: ATCommand> {
message: String, message: String,
command: Cmd,
dots: u8, dots: u8,
prev_dots: Instant, prev_dots: Instant,
promise: Option<ATPromise<StubATCommand>>, promise: Option<ATPromise<Cmd>>,
after_state: T,
} }
impl Default for InitATState { impl<T: State + Clone, Cmd: ATCommand> ATCommandState<T, Cmd> {
fn default() -> Self { pub fn with(message: String, command: Cmd, after: T) -> ATCommandState<T, Cmd> {
Self { ATCommandState {
inner_state: 0, message,
message: "Initializing AT..".to_string(), command,
dots: 0, dots: 0,
prev_dots: Instant::now(), prev_dots: Instant::now(),
promise: None, promise: None,
after_state: after,
} }
} }
} }
impl State for InitATState { impl<T: State + Clone + 'static, Cmd: ATCommand + Clone> State for ATCommandState<T, Cmd> {
fn init(&mut self, data: &mut StateData) {
self.promise = Some(data.io.send_at_command(self.command.clone()).unwrap());
}
fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> { fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> {
// Update dots // Update dots
if self.prev_dots.elapsed() > Duration::from_millis(200) { if self.prev_dots.elapsed() > Duration::from_millis(200) {
@ -52,7 +59,7 @@ impl State for InitATState {
match promise.poll(&mut data.io) { match promise.poll(&mut data.io) {
Some(response) => match response { Some(response) => match response {
Some(response) => { Some(response) => {
log::info!("Response: {}", response); log::info!("Response: {:?}", response);
self.promise = None; self.promise = None;
} }
None => {} None => {}
@ -62,77 +69,7 @@ impl State for InitATState {
return None; return None;
} }
// Send next AT command return Some(Box::new(self.after_state.clone()));
let res: Option<Box<dyn State>> = match self.inner_state {
0 => {
self.promise = Some(
data.io
.send_at_command(ATInformationCommand)
.unwrap()
.downgrade(),
);
self.message = "Checking info".to_owned();
None
}
1 => {
self.promise = Some(
data.io
.send_at_command(EnterPinCommand("1234".to_owned()))
.unwrap()
.downgrade(),
);
self.message = "Entering PIN".to_owned();
None
}
2 => {
self.promise = Some(
data.io
.send_at_command(CheckPinCommand)
.unwrap()
.downgrade(),
);
None
}
3 => {
self.promise = Some(
data.io
.send_at_command(ListTECharacterSetsCommand)
.unwrap()
.downgrade(),
);
self.message = "Checking\ncharsets".to_owned();
None
}
4 => {
self.promise = Some(
data.io
.send_at_command(SelectSMSFormatCommand(SMSFormat::TextMode))
.unwrap()
.downgrade(),
);
self.message = "Selecting SMS\nformat".to_owned();
None
}
5 => {
self.promise = Some(
data.io
.send_at_command(SetTECharsetCommand(TECharset::IRA))
.unwrap()
.downgrade(),
);
self.message = "Selecting SMS\nformat".to_owned();
None
}
_ => {
data.delay.delay_millis(1000);
Some(Box::new(TextState {
text: "AT init done!".to_owned(),
}))
}
};
self.inner_state = (self.inner_state + 1).min(200);
res
} }
fn draw(&self, data: &mut StateData) { fn draw(&self, data: &mut StateData) {
@ -146,6 +83,47 @@ impl State for InitATState {
} }
} }
pub struct InitATState;
impl Default for InitATState {
fn default() -> Self {
Self {}
}
}
impl State for InitATState {
fn update(&mut self, _: &mut StateData) -> Option<Box<dyn State>> {
let state = ATCommandState::with(
"Checking info".to_owned(),
ATInformationCommand,
ATCommandState::with(
"Entering PIN".to_owned(),
EnterPinCommand("1234".to_owned()),
ATCommandState::with(
"Checking PIN".to_owned(),
CheckPinCommand,
ATCommandState::with(
"Selecting SMS\ncharset".to_owned(),
SelectSMSFormatCommand(SMSFormat::TextMode),
ATCommandState::with(
"Setting\nTE charset".to_owned(),
SetTECharsetCommand(TECharset::IRA),
TextState {
text: "All done!".to_owned(),
},
),
),
),
),
);
Some(Box::new(state))
}
fn draw(&self, data: &mut StateData) {}
}
#[derive(Clone)]
pub struct TextState { pub struct TextState {
text: String, text: String,
} }