Implement timeout

This commit is contained in:
Sofia 2026-06-02 13:17:08 +03:00
parent 8c9afa6128
commit 3ad6892578
4 changed files with 189 additions and 122 deletions

View File

@ -10,7 +10,7 @@ use alloc::{
}; };
use critical_section::Mutex; use critical_section::Mutex;
use crate::at_commands::{ATCommand, ATParseError, ATResponseParser, SimpleATCommand}; use crate::at_commands::{ATCommand, ATError, ATResponseParser, SimpleATCommand};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum KeypadButton { pub enum KeypadButton {
@ -110,7 +110,7 @@ impl Keypad {
pub struct AsyncIO { pub struct AsyncIO {
at_command: Rc<Mutex<RefCell<Option<Box<dyn SimpleATCommand>>>>>, at_command: Rc<Mutex<RefCell<Option<Box<dyn SimpleATCommand>>>>>,
handling_at_command: Rc<Mutex<RefCell<bool>>>, handling_at_command: Rc<Mutex<RefCell<bool>>>,
at_response: Rc<Mutex<RefCell<Option<Vec<String>>>>>, at_response: Rc<Mutex<RefCell<Option<Result<Vec<String>, ATError>>>>>,
pub keypad: Keypad, pub keypad: Keypad,
} }
@ -134,16 +134,19 @@ pub struct ATPromise<T: ATCommand> {
} }
impl<T: ATCommand> ATPromise<T> { impl<T: ATCommand> ATPromise<T> {
pub fn poll(&self, io: &mut AsyncIO) -> Option<Option<Result<T::Response, ATParseError>>> { pub fn poll(&self, io: &mut AsyncIO) -> Option<Result<T::Response, ATError>> {
match io.poll_at_response() { match io.poll_at_response() {
Some(response) => match response {
Some(response) => { Some(response) => {
log::info!("Response: {:?}", response);
match response {
Ok(response) => {
let mut parser = ATResponseParser::from(response); let mut parser = ATResponseParser::from(response);
Some(Some(T::parse_response(&mut parser))) Some(T::parse_response(&mut parser))
} }
None => Some(None), Err(err) => Some(Err(err)),
}, }
None => Some(None), }
None => None,
} }
} }
} }
@ -173,7 +176,7 @@ impl AsyncIO {
}) })
} }
pub unsafe fn set_at_response(&self, response_str: Vec<String>) { pub unsafe fn set_at_response(&self, response_str: Result<Vec<String>, ATError>) {
critical_section::with(|cs| { critical_section::with(|cs| {
*self.handling_at_command.borrow_ref_mut(cs) = false; *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);
@ -183,15 +186,15 @@ impl AsyncIO {
}) })
} }
fn poll_at_response(&self) -> Option<Option<Vec<String>>> { fn poll_at_response(&self) -> Option<Result<Vec<String>, ATError>> {
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() || *self.handling_at_command.borrow_ref(cs) { if command.is_some() {
return Some(None); return None;
} }
if let Some(resp) = response.take() { if let Some(resp) = response.take() {
return Some(Some(resp)); return Some(resp);
} }
None None
}) })

View File

@ -2,6 +2,7 @@ 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 esp_hal::time::{Duration, Instant};
use esp_hal::{Blocking, delay::Delay, gpio::Output, uart::Uart}; use esp_hal::{Blocking, delay::Delay, gpio::Output, uart::Uart};
static RESPONSES: [&'static str; 3] = ["OK", "ERROR", "DOWNLOAD"]; static RESPONSES: [&'static str; 3] = ["OK", "ERROR", "DOWNLOAD"];
@ -54,7 +55,12 @@ impl<'a, 'd> ATCommands<'a, 'd> {
self.flush_rx(); self.flush_rx();
} }
pub fn raw_command<T: SimpleATCommand>(&mut self, cmd: &T, command: String) -> Vec<String> { pub fn raw_command<T: SimpleATCommand>(
&mut self,
cmd: &T,
command: String,
timeout: Duration,
) -> Result<Vec<String>, ATError> {
self.uart.flush().unwrap(); self.uart.flush().unwrap();
self.flush_rx(); self.flush_rx();
let command = command.clone() + "\r"; let command = command.clone() + "\r";
@ -62,7 +68,7 @@ impl<'a, 'd> ATCommands<'a, 'd> {
self.uart.flush().unwrap(); self.uart.flush().unwrap();
self.delay.delay_millis(500); self.delay.delay_millis(500);
log::info!("Wrote command {}", command); log::info!("Wrote command {}", command);
self.read_response(cmd, command) self.read_response(cmd, command, timeout)
} }
pub fn raw_two_part_command<T: SimpleATCommand>( pub fn raw_two_part_command<T: SimpleATCommand>(
@ -70,7 +76,8 @@ impl<'a, 'd> ATCommands<'a, 'd> {
cmd: &T, cmd: &T,
command: String, command: String,
additional: String, additional: String,
) -> Vec<String> { timeout: Duration,
) -> Result<Vec<String>, ATError> {
self.uart.flush().unwrap(); self.uart.flush().unwrap();
self.flush_rx(); self.flush_rx();
self.uart.write_str(&(command.clone() + "\r")).unwrap(); self.uart.write_str(&(command.clone() + "\r")).unwrap();
@ -90,7 +97,7 @@ impl<'a, 'd> ATCommands<'a, 'd> {
} }
self.uart.flush().unwrap(); self.uart.flush().unwrap();
self.read_response(cmd, command) self.read_response(cmd, command, timeout)
} }
pub fn readline(&mut self) -> Option<String> { pub fn readline(&mut self) -> Option<String> {
@ -102,16 +109,23 @@ impl<'a, 'd> ATCommands<'a, 'd> {
} }
} }
fn read_response<T: SimpleATCommand>(&mut self, cmd: &T, start: String) -> Vec<String> { fn read_response<T: SimpleATCommand>(
&mut self,
cmd: &T,
start: String,
timeout: Duration,
) -> Result<Vec<String>, ATError> {
let start_time = Instant::now();
let mut response = None; let mut response = None;
while response.is_none() { while response.is_none() {
if (start_time + timeout) < Instant::now() {
return Err(ATError::Timeout);
}
self.flush_rx(); self.flush_rx();
log::info!("{:?}", self.lines);
response = self.parse_response(cmd, &start); response = self.parse_response(cmd, &start);
} }
log::info!("{:?}", response);
response.unwrap() response.unwrap()
} }
@ -119,7 +133,7 @@ impl<'a, 'd> ATCommands<'a, 'd> {
&mut self, &mut self,
cmd: &T, cmd: &T,
start: &String, start: &String,
) -> Option<Vec<String>> { ) -> Option<Result<Vec<String>, ATError>> {
let start_idx = self let start_idx = self
.lines .lines
.iter() .iter()
@ -127,6 +141,8 @@ impl<'a, 'd> ATCommands<'a, 'd> {
.find(|(_, l)| l.starts_with(start)) .find(|(_, l)| l.starts_with(start))
.map(|(i, _)| i); .map(|(i, _)| i);
log::info!("{:?}", self.lines);
if let Some(start_idx) = start_idx { if let Some(start_idx) = start_idx {
let mut response = Vec::new(); let mut response = Vec::new();
@ -136,6 +152,8 @@ impl<'a, 'd> ATCommands<'a, 'd> {
} }
response.push(line.trim().to_string()); response.push(line.trim().to_string());
log::info!("{:?}", response);
let mut parser = ATResponseParser::from(response.clone()); let mut parser = ATResponseParser::from(response.clone());
match cmd.try_parse(&mut parser) { match cmd.try_parse(&mut parser) {
@ -148,11 +166,11 @@ impl<'a, 'd> ATCommands<'a, 'd> {
for _ in 0..parser.lines { for _ in 0..parser.lines {
output_lines.push(self.lines.remove(start_idx)); output_lines.push(self.lines.remove(start_idx));
} }
return Some(output_lines); return Some(Ok(output_lines));
} }
Err(err) => match err { Err(err) => match err {
ATParseError::EOF => {} ATError::EOF => {}
ATParseError::InvalidResponse => panic!("Invalid response"), _ => return Some(Err(err)),
}, },
} }
} }
@ -215,11 +233,11 @@ impl ATResponseParser {
result.cloned() result.cloned()
} }
pub fn expect(&mut self, text: String) -> Result<(), ATParseError> { pub fn expect(&mut self, text: String) -> Result<(), ATError> {
let line = if let Some(curr_line) = self.curr_line.take() { let line = if let Some(curr_line) = self.curr_line.take() {
curr_line curr_line
} else { } else {
self.readline().ok_or(ATParseError::EOF)? self.readline().ok_or(ATError::EOF)?
}; };
if let Some(text) = line.strip_prefix(&text) { if let Some(text) = line.strip_prefix(&text) {
@ -227,34 +245,35 @@ impl ATResponseParser {
Ok(()) Ok(())
} else { } else {
self.curr_line = Some(line); self.curr_line = Some(line);
Err(ATParseError::InvalidResponse) Err(ATError::InvalidResponse)
} }
} }
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum ATParseError { pub enum ATError {
EOF, EOF,
InvalidResponse, InvalidResponse,
Timeout,
} }
pub trait ATCommand: Send + Sync { pub trait ATCommand: Send + Sync {
type Response: core::fmt::Debug + ATResponse; type Response: core::fmt::Debug + ATResponse;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String>; fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError>;
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError>; fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError>;
} }
pub trait SimpleATCommand: Send + Sync { pub trait SimpleATCommand: Send + Sync {
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String>; fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError>;
fn try_parse(&self, parser: &mut ATResponseParser) -> Result<(), ATParseError>; fn try_parse(&self, parser: &mut ATResponseParser) -> Result<(), ATError>;
} }
impl<T: ATCommand> SimpleATCommand for T { impl<T: ATCommand> SimpleATCommand for T {
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
self.execute(at_commands) self.execute(at_commands)
} }
fn try_parse(&self, parser: &mut ATResponseParser) -> Result<(), ATParseError> { fn try_parse(&self, parser: &mut ATResponseParser) -> Result<(), ATError> {
let result = Self::parse_response(parser); let result = Self::parse_response(parser);
result.map(|_| ()) result.map(|_| ())
} }
@ -298,11 +317,11 @@ pub struct ATInformationCommand;
impl ATCommand for ATInformationCommand { impl ATCommand for ATInformationCommand {
type Response = ATInformation; type Response = ATInformation;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
at_commands.raw_command(self, "ATI".to_string()) at_commands.raw_command(self, "ATI".to_string(), Duration::from_millis(2000))
} }
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError> { fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError> {
parser.expect("Manufacturer: ".to_string())?; parser.expect("Manufacturer: ".to_string())?;
let manufacturer = parser.readline().unwrap(); let manufacturer = parser.readline().unwrap();
parser.expect("Model: ".to_string())?; parser.expect("Model: ".to_string())?;
@ -322,7 +341,7 @@ impl ATCommand for ATInformationCommand {
}); });
} }
} }
Err(ATParseError::EOF) Err(ATError::EOF)
} }
} }
@ -347,11 +366,15 @@ pub struct EnterPinCommand(pub String);
impl ATCommand for EnterPinCommand { impl ATCommand for EnterPinCommand {
type Response = EnterPinResult; type Response = EnterPinResult;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
at_commands.raw_command(self, format!("AT+CPIN={}", self.0)) at_commands.raw_command(
self,
format!("AT+CPIN={}", self.0),
Duration::from_millis(2000),
)
} }
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError> { fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError> {
while let Some(line) = parser.readline() { while let Some(line) = parser.readline() {
if line.starts_with("OK") { if line.starts_with("OK") {
return Ok(EnterPinResult::Ok); return Ok(EnterPinResult::Ok);
@ -361,7 +384,7 @@ impl ATCommand for EnterPinCommand {
return Ok(EnterPinResult::ErrorMessage(status.to_string())); return Ok(EnterPinResult::ErrorMessage(status.to_string()));
} }
} }
Err(ATParseError::EOF) Err(ATError::EOF)
} }
} }
@ -386,11 +409,11 @@ pub struct CheckPinCommand;
impl ATCommand for CheckPinCommand { impl ATCommand for CheckPinCommand {
type Response = CheckPinResult; type Response = CheckPinResult;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
at_commands.raw_command(self, "AT+CPIN?".to_string()) at_commands.raw_command(self, "AT+CPIN?".to_string(), Duration::from_millis(2000))
} }
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError> { fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError> {
if let Ok(_) = parser.expect("+CPIN: ".to_string()) { if let Ok(_) = parser.expect("+CPIN: ".to_string()) {
let status = parser.readline().unwrap(); let status = parser.readline().unwrap();
while let Some(line) = parser.readline() { while let Some(line) = parser.readline() {
@ -407,7 +430,7 @@ impl ATCommand for CheckPinCommand {
return Ok(CheckPinResult::ErrorMessage(status.to_string())); return Ok(CheckPinResult::ErrorMessage(status.to_string()));
} }
} }
Err(ATParseError::EOF) Err(ATError::EOF)
} }
} }
@ -422,11 +445,15 @@ pub struct SelectSMSFormatCommand(pub SMSFormat);
impl ATCommand for SelectSMSFormatCommand { impl ATCommand for SelectSMSFormatCommand {
type Response = SimpleATResponse; type Response = SimpleATResponse;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
at_commands.raw_command(self, format!("AT+CMGF={}", self.0 as u8)) at_commands.raw_command(
self,
format!("AT+CMGF={}", self.0 as u8),
Duration::from_millis(2000),
)
} }
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError> { fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError> {
while let Some(line) = parser.readline() { while let Some(line) = parser.readline() {
if line.starts_with("OK") { if line.starts_with("OK") {
return Ok(SimpleATResponse::Ok); return Ok(SimpleATResponse::Ok);
@ -434,7 +461,7 @@ impl ATCommand for SelectSMSFormatCommand {
return Ok(SimpleATResponse::Error); return Ok(SimpleATResponse::Error);
} }
} }
Err(ATParseError::EOF) Err(ATError::EOF)
} }
} }
@ -458,11 +485,11 @@ pub struct CheckSMSFormatCommand;
impl ATCommand for CheckSMSFormatCommand { impl ATCommand for CheckSMSFormatCommand {
type Response = CheckSMSFormatResult; type Response = CheckSMSFormatResult;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
at_commands.raw_command(self, "AT+CMGF?".to_string()) at_commands.raw_command(self, "AT+CMGF?".to_string(), Duration::from_millis(2000))
} }
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError> { fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError> {
if let Ok(_) = parser.expect("+CMGF: ".to_string()) { if let Ok(_) = parser.expect("+CMGF: ".to_string()) {
let mode = parser.readline().unwrap(); let mode = parser.readline().unwrap();
while let Some(line) = parser.readline() { while let Some(line) = parser.readline() {
@ -477,7 +504,7 @@ impl ATCommand for CheckSMSFormatCommand {
return Ok(CheckSMSFormatResult::Error); return Ok(CheckSMSFormatResult::Error);
} }
} }
Err(ATParseError::EOF) Err(ATError::EOF)
} }
} }
@ -499,11 +526,11 @@ pub struct ListTECharacterSetsCommand;
impl ATCommand for ListTECharacterSetsCommand { impl ATCommand for ListTECharacterSetsCommand {
type Response = TECharacterSets; type Response = TECharacterSets;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
at_commands.raw_command(self, "AT+CSCS=?".to_string()) at_commands.raw_command(self, "AT+CSCS=?".to_string(), Duration::from_millis(2000))
} }
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError> { fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError> {
parser.expect("+CSCS: ".to_owned())?; parser.expect("+CSCS: ".to_owned())?;
let result = parser.readline().unwrap(); let result = parser.readline().unwrap();
let result = result.strip_prefix("(").unwrap().strip_suffix(")").unwrap(); let result = result.strip_prefix("(").unwrap().strip_suffix(")").unwrap();
@ -514,7 +541,7 @@ impl ATCommand for ListTECharacterSetsCommand {
return Ok(TECharacterSets::Charsets(results)); return Ok(TECharacterSets::Charsets(results));
} }
} }
Err(ATParseError::EOF) Err(ATError::EOF)
} }
} }
@ -542,11 +569,15 @@ pub struct SetTECharsetCommand(pub TECharset);
impl ATCommand for SetTECharsetCommand { impl ATCommand for SetTECharsetCommand {
type Response = SimpleATResponse; type Response = SimpleATResponse;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
at_commands.raw_command(self, format!("AT+CSCS=\"{}\"", self.0.into_str())) at_commands.raw_command(
self,
format!("AT+CSCS=\"{}\"", self.0.into_str()),
Duration::from_millis(2000),
)
} }
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError> { fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError> {
while let Some(line) = parser.readline() { while let Some(line) = parser.readline() {
if line.starts_with("OK") { if line.starts_with("OK") {
return Ok(SimpleATResponse::Ok); return Ok(SimpleATResponse::Ok);
@ -554,7 +585,7 @@ impl ATCommand for SetTECharsetCommand {
return Ok(SimpleATResponse::Error); return Ok(SimpleATResponse::Error);
} }
} }
Err(ATParseError::EOF) Err(ATError::EOF)
} }
} }
@ -583,15 +614,16 @@ pub struct SendSMSCommand {
impl ATCommand for SendSMSCommand { impl ATCommand for SendSMSCommand {
type Response = SendSMSResponse; type Response = SendSMSResponse;
fn execute(&self, at_commands: &mut ATCommands) -> Vec<String> { fn execute(&self, at_commands: &mut ATCommands) -> Result<Vec<String>, ATError> {
at_commands.raw_two_part_command( at_commands.raw_two_part_command(
self, self,
format!("AT+CMGS=\"{}\"", self.destination), format!("AT+CMGS=\"{}\"", self.destination),
self.message.clone(), self.message.clone(),
Duration::from_millis(30000),
) )
} }
fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATParseError> { fn parse_response(parser: &mut ATResponseParser) -> Result<Self::Response, ATError> {
if let Ok(_) = parser.expect("+CMS ERROR: ".to_owned()) { if let Ok(_) = parser.expect("+CMS ERROR: ".to_owned()) {
let result = parser.readline().unwrap(); let result = parser.readline().unwrap();
return Ok(SendSMSResponse::ErrorMessage(result)); return Ok(SendSMSResponse::ErrorMessage(result));
@ -618,6 +650,6 @@ impl ATCommand for SendSMSCommand {
} }
} }
Err(ATParseError::EOF) Err(ATError::EOF)
} }
} }

View File

@ -3,7 +3,7 @@ use esp_hal::{Blocking, delay::Delay};
use crate::{ use crate::{
async_io::{ATPromise, AsyncIO}, async_io::{ATPromise, AsyncIO},
at_commands::{ATCommand, ATParseError}, at_commands::{ATCommand, ATError},
display::{Color, Display, Position, Rgb565}, display::{Color, Display, Position, Rgb565},
font::{FontRenderer, HorizontalAlignment, VerticalAlignment}, font::{FontRenderer, HorizontalAlignment, VerticalAlignment},
}; };
@ -118,7 +118,7 @@ impl<'a> StateManager<'a> {
pub struct ATCommandHelper<T: ATCommand> { pub struct ATCommandHelper<T: ATCommand> {
command: Option<T>, command: Option<T>,
promise: Option<ATPromise<T>>, promise: Option<ATPromise<T>>,
response: Option<Result<T::Response, ATParseError>>, response: Option<Result<T::Response, ATError>>,
} }
impl<T: ATCommand + 'static> ATCommandHelper<T> impl<T: ATCommand + 'static> ATCommandHelper<T>
@ -133,20 +133,17 @@ where
} }
} }
pub fn poll(&mut self, io: &mut AsyncIO) -> Option<Result<T::Response, ATParseError>> { pub fn poll(&mut self, io: &mut AsyncIO) -> Option<Result<T::Response, ATError>> {
if let Some(resp) = self.response.clone() { if let Some(resp) = self.response.clone() {
return Some(resp); return Some(resp);
} else { } else {
if let Some(promise) = &mut self.promise { if let Some(promise) = &mut self.promise {
match promise.poll(io) { match promise.poll(io) {
Some(response) => match response {
Some(response) => { Some(response) => {
self.response = Some(response); self.response = Some(response);
self.response.clone() self.response.clone()
} }
None => None, None => None,
},
None => None,
} }
} else if let Some(cmd) = self.command.take() { } else if let Some(cmd) = self.command.take() {
self.promise = Some(io.send_at_command(cmd).unwrap()); self.promise = Some(io.send_at_command(cmd).unwrap());

View File

@ -11,9 +11,9 @@ use esp_hal::time::{Duration, Instant};
use crate::{ use crate::{
async_io::{ATPromise, KeypadButton, NumberInput, TextInput}, async_io::{ATPromise, KeypadButton, NumberInput, TextInput},
at_commands::{ at_commands::{
ATCommand, ATInformationCommand, ATParseError, CheckPinCommand, CheckPinResult, ATCommand, ATError, ATInformationCommand, CheckPinCommand, CheckPinResult, EnterPinCommand,
EnterPinCommand, EnterPinResult, SMSFormat, SelectSMSFormatCommand, SendSMSCommand, EnterPinResult, SMSFormat, SelectSMSFormatCommand, SendSMSCommand, SendSMSResponse,
SendSMSResponse, SetTECharsetCommand, SimpleATResponse, TECharset, SetTECharsetCommand, SimpleATResponse, TECharset,
}, },
display::{Position, Rgb565}, display::{Position, Rgb565},
font::{HorizontalAlignment, VerticalAlignment}, font::{HorizontalAlignment, VerticalAlignment},
@ -53,7 +53,7 @@ impl DotsMessage {
pub struct ATCommandState<Cmd: ATCommand, F> pub struct ATCommandState<Cmd: ATCommand, F>
where where
F: FnOnce(Result<Cmd::Response, ATParseError>) -> Box<dyn State>, F: FnOnce(Result<Cmd::Response, ATError>) -> Box<dyn State>,
{ {
message: DotsMessage, message: DotsMessage,
command: Cmd, command: Cmd,
@ -63,7 +63,7 @@ where
impl<Cmd: ATCommand, F> ATCommandState<Cmd, F> impl<Cmd: ATCommand, F> ATCommandState<Cmd, F>
where where
F: FnOnce(Result<Cmd::Response, ATParseError>) -> Box<dyn State>, F: FnOnce(Result<Cmd::Response, ATError>) -> Box<dyn State>,
{ {
pub fn with(message: String, command: Cmd, after: F) -> ATCommandState<Cmd, F> { pub fn with(message: String, command: Cmd, after: F) -> ATCommandState<Cmd, F> {
ATCommandState { ATCommandState {
@ -80,7 +80,7 @@ where
impl<Cmd: ATCommand + Clone + 'static, F: Clone> State for ATCommandState<Cmd, F> impl<Cmd: ATCommand + Clone + 'static, F: Clone> State for ATCommandState<Cmd, F>
where where
F: FnOnce(Result<Cmd::Response, ATParseError>) -> Box<dyn State>, F: FnOnce(Result<Cmd::Response, ATError>) -> Box<dyn State>,
{ {
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());
@ -92,12 +92,9 @@ where
if let Some(promise) = &self.promise { if let Some(promise) = &self.promise {
match promise.poll(&mut data.io) { match promise.poll(&mut data.io) {
Some(response) => match response {
Some(response) => { Some(response) => {
return Some((self.fun.clone())(response)); return Some((self.fun.clone())(response));
} }
None => {}
},
None => self.promise = None, None => self.promise = None,
} }
return None; return None;
@ -141,14 +138,23 @@ impl State for InitATState {
self.message.poll(); self.message.poll();
if let Some(resp) = self.ati.poll(&mut data.io) { if let Some(resp) = self.ati.poll(&mut data.io) {
resp.unwrap() match resp {
Ok(_) => {}
Err(err) => {
return Some(Box::new(TextState {
text: format!("Err: {:?}", err),
after: InitATState::default(),
}));
}
}
} else { } else {
self.message.message = "Checking ATI".to_owned(); self.message.message = "Checking ATI".to_owned();
return None; return None;
}; };
if let Some(resp) = self.sms_charset.poll(&mut data.io) { if let Some(resp) = self.sms_charset.poll(&mut data.io) {
match resp.unwrap() { match resp {
Ok(resp) => match resp {
SimpleATResponse::Ok => {} SimpleATResponse::Ok => {}
SimpleATResponse::Error => { SimpleATResponse::Error => {
return Some(Box::new(TextState { return Some(Box::new(TextState {
@ -156,6 +162,13 @@ impl State for InitATState {
after: InitATState::default(), after: InitATState::default(),
})); }));
} }
},
Err(err) => {
return Some(Box::new(TextState {
text: format!("Err: {:?}", err),
after: InitATState::default(),
}));
}
} }
} else { } else {
self.message.message = "Selecting SMS\ncharset".to_owned(); self.message.message = "Selecting SMS\ncharset".to_owned();
@ -163,7 +176,8 @@ impl State for InitATState {
}; };
if let Some(resp) = self.te_charset.poll(&mut data.io) { if let Some(resp) = self.te_charset.poll(&mut data.io) {
match resp.unwrap() { match resp {
Ok(resp) => match resp {
SimpleATResponse::Ok => {} SimpleATResponse::Ok => {}
SimpleATResponse::Error => { SimpleATResponse::Error => {
return Some(Box::new(TextState { return Some(Box::new(TextState {
@ -171,6 +185,13 @@ impl State for InitATState {
after: InitATState::default(), after: InitATState::default(),
})); }));
} }
},
Err(err) => {
return Some(Box::new(TextState {
text: format!("Err: {:?}", err),
after: InitATState::default(),
}));
}
} }
} else { } else {
self.message.message = "Selecting TE\ncharset".to_owned(); self.message.message = "Selecting TE\ncharset".to_owned();
@ -230,7 +251,8 @@ impl State for EnterPinState {
fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> { fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> {
if let Some(helper) = &mut self.helper { if let Some(helper) = &mut self.helper {
match helper.poll(&mut data.io) { match helper.poll(&mut data.io) {
Some(response) => match response.unwrap() { Some(response) => match response {
Ok(response) => match response {
EnterPinResult::Ok => { EnterPinResult::Ok => {
return Some(Box::new(MainMenuState::default())); return Some(Box::new(MainMenuState::default()));
} }
@ -247,6 +269,13 @@ impl State for EnterPinState {
})); }));
} }
}, },
Err(err) => {
return Some(Box::new(TextState {
text: format!("Error:\n{:?}", err),
after: EnterPinState::default(),
}));
}
},
None => return None, None => return None,
} }
} }
@ -365,7 +394,8 @@ impl State for MessageState {
destination: self.number.clone(), destination: self.number.clone(),
message: self.input.read().clone(), message: self.input.read().clone(),
}, },
|resp| match resp.unwrap() { |resp| match resp {
Ok(resp) => match resp {
SendSMSResponse::MessageRefrence(refrence) => Box::new(TextState { SendSMSResponse::MessageRefrence(refrence) => Box::new(TextState {
text: format!("SMS sent\nRef: {}", refrence), text: format!("SMS sent\nRef: {}", refrence),
after: MainMenuState::default(), after: MainMenuState::default(),
@ -379,6 +409,11 @@ impl State for MessageState {
after: MainMenuState::default(), after: MainMenuState::default(),
}), }),
}, },
Err(err) => Box::new(TextState {
text: format!("Error:\n{:?}", err),
after: MainMenuState::default(),
}),
},
))) )))
} else { } else {
None None