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 Sync for AsyncIO {}
#[derive(Default)]
#[derive(Default, Clone)]
pub struct ATPromise<T: ATCommand> {
_data: PhantomData<T>,
}

View File

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

View File

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

View File

@ -11,36 +11,43 @@ use esp_hal::time::{Duration, Instant};
use crate::{
async_io::ATPromise,
at_commands::{
ATInformationCommand, CheckPinCommand, EnterPinCommand, ListTECharacterSetsCommand,
SMSFormat, SelectSMSFormatCommand, SendSMSCommand, SetTECharsetCommand, StubATCommand,
TECharset,
ATCommand, ATInformationCommand, CheckPinCommand, EnterPinCommand,
ListTECharacterSetsCommand, SMSFormat, SelectSMSFormatCommand, SendSMSCommand,
SetTECharsetCommand, StubATCommand, TECharset,
},
display::{Position, Rgb565},
font::{HorizontalAlignment, VerticalAlignment},
state::{State, StateData, TextSettings},
};
pub struct InitATState {
inner_state: u8,
#[derive(Clone)]
pub struct ATCommandState<T: State, Cmd: ATCommand> {
message: String,
command: Cmd,
dots: u8,
prev_dots: Instant,
promise: Option<ATPromise<StubATCommand>>,
promise: Option<ATPromise<Cmd>>,
after_state: T,
}
impl Default for InitATState {
fn default() -> Self {
Self {
inner_state: 0,
message: "Initializing AT..".to_string(),
impl<T: State + Clone, Cmd: ATCommand> ATCommandState<T, Cmd> {
pub fn with(message: String, command: Cmd, after: T) -> ATCommandState<T, Cmd> {
ATCommandState {
message,
command,
dots: 0,
prev_dots: Instant::now(),
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>> {
// Update dots
if self.prev_dots.elapsed() > Duration::from_millis(200) {
@ -52,7 +59,7 @@ impl State for InitATState {
match promise.poll(&mut data.io) {
Some(response) => match response {
Some(response) => {
log::info!("Response: {}", response);
log::info!("Response: {:?}", response);
self.promise = None;
}
None => {}
@ -62,77 +69,7 @@ impl State for InitATState {
return None;
}
// Send next AT command
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
return Some(Box::new(self.after_state.clone()));
}
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 {
text: String,
}