Implement timeout
This commit is contained in:
parent
8c9afa6128
commit
3ad6892578
@ -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
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user