Improve how AT command responses are handled
This commit is contained in:
parent
a8a52c8a22
commit
e215987288
@ -1,19 +1,38 @@
|
|||||||
use alloc::format;
|
use alloc::string::{String, ToString};
|
||||||
use alloc::string::String;
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use alloc::{borrow::ToOwned, format};
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
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"];
|
||||||
|
|
||||||
pub struct ATCommands<'a, 'd> {
|
pub struct ATCommands<'a, 'd> {
|
||||||
pub rst: Output<'a>,
|
rst: Output<'a>,
|
||||||
pub pwr_key: Output<'a>,
|
pwr_key: Output<'a>,
|
||||||
pub uart: Uart<'d, Blocking>,
|
uart: Uart<'d, Blocking>,
|
||||||
pub delay: Delay,
|
delay: Delay,
|
||||||
|
|
||||||
|
buffer: String,
|
||||||
|
lines: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'd> ATCommands<'a, 'd> {
|
impl<'a, 'd> ATCommands<'a, 'd> {
|
||||||
|
pub fn new(
|
||||||
|
rst: Output<'a>,
|
||||||
|
pwr_key: Output<'a>,
|
||||||
|
uart: Uart<'d, Blocking>,
|
||||||
|
) -> ATCommands<'a, 'd> {
|
||||||
|
ATCommands {
|
||||||
|
rst,
|
||||||
|
pwr_key,
|
||||||
|
uart,
|
||||||
|
delay: Delay::new(),
|
||||||
|
|
||||||
|
buffer: String::new(),
|
||||||
|
lines: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(&mut self) {
|
pub fn init(&mut self) {
|
||||||
self.pwr_key.set_low();
|
self.pwr_key.set_low();
|
||||||
self.delay.delay_millis(1_000);
|
self.delay.delay_millis(1_000);
|
||||||
@ -38,11 +57,12 @@ impl<'a, 'd> ATCommands<'a, 'd> {
|
|||||||
pub fn raw_command(&mut self, command: String) -> String {
|
pub fn raw_command(&mut self, command: String) -> String {
|
||||||
self.uart.flush().unwrap();
|
self.uart.flush().unwrap();
|
||||||
self.flush_rx();
|
self.flush_rx();
|
||||||
self.uart.write_str(&(command.clone() + "\r")).unwrap();
|
let command = command.clone() + "\r";
|
||||||
|
self.uart.write_str(&command).unwrap();
|
||||||
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()
|
self.read_response(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw_two_part_command(&mut self, command: String, additional: String) -> String {
|
pub fn raw_two_part_command(&mut self, command: String, additional: String) -> String {
|
||||||
@ -52,55 +72,86 @@ 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);
|
||||||
log::info!("{}", self.flush_rx());
|
self.flush_rx();
|
||||||
|
|
||||||
self.uart.write_str(&(additional.clone() + "\x1A")).unwrap();
|
let text = additional.clone() + "\x1A";
|
||||||
|
self.uart.write_str(&text).unwrap();
|
||||||
self.uart.flush().unwrap();
|
self.uart.flush().unwrap();
|
||||||
|
|
||||||
self.read_response()
|
self.read_response(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_response(&mut self) -> String {
|
pub fn readline(&mut self) -> Option<String> {
|
||||||
let mut buffer = [0u8; 1024];
|
self.flush_rx();
|
||||||
|
if self.lines.len() > 0 {
|
||||||
let mut contents = String::new();
|
Some(self.lines.remove(0))
|
||||||
|
} else {
|
||||||
while {
|
None
|
||||||
let parts: Vec<&str> = contents.split("\r\n").collect();
|
}
|
||||||
!RESPONSES
|
|
||||||
.iter()
|
|
||||||
.any(|r| parts.iter().any(|p| p.contains(r)))
|
|
||||||
} {
|
|
||||||
let length = self.uart.read(&mut buffer).unwrap();
|
|
||||||
contents += str::from_utf8(&buffer[..length]).unwrap();
|
|
||||||
log::info!("Contents so far: {}", contents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let parts: Vec<&str> = contents.split("\r\n").collect();
|
fn read_response(&mut self, start: String) -> String {
|
||||||
let (idx, _) = parts
|
let mut response = None;
|
||||||
|
while response.is_none() {
|
||||||
|
self.flush_rx();
|
||||||
|
response = self.parse_response(&start);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(&mut self, start: &String) -> Option<String> {
|
||||||
|
let start_idx = self
|
||||||
|
.lines
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, part)| RESPONSES.iter().any(|r| part.contains(r)))
|
.find(|(_, l)| l.starts_with(start))
|
||||||
.unwrap();
|
.map(|(i, _)| i);
|
||||||
parts
|
|
||||||
.into_iter()
|
if let Some(start_idx) = start_idx {
|
||||||
.take(idx + 1)
|
let mut response = String::new();
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("\n")
|
for (i, line) in self.lines.iter().cloned().skip(start_idx).enumerate() {
|
||||||
|
if i == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if response.len() > 0 {
|
||||||
|
response += "\n";
|
||||||
|
}
|
||||||
|
response += &line;
|
||||||
|
if RESPONSES.iter().any(|r| line.starts_with(r)) {
|
||||||
|
for _ in 0..=i {
|
||||||
|
self.lines.remove(start_idx);
|
||||||
|
}
|
||||||
|
return Some(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flush_rx(&mut self) -> String {
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flush_rx(&mut self) {
|
||||||
let mut buffer = [0u8; 1024];
|
let mut buffer = [0u8; 1024];
|
||||||
|
|
||||||
let mut contents = String::new();
|
|
||||||
while {
|
while {
|
||||||
self.delay.delay_millis(10);
|
self.delay.delay_millis(10);
|
||||||
self.uart.read_ready()
|
self.uart.read_ready()
|
||||||
} {
|
} {
|
||||||
let length = self.uart.read(&mut buffer).unwrap();
|
let length = self.uart.read(&mut buffer).unwrap();
|
||||||
contents += str::from_utf8(&buffer[..length]).unwrap();
|
self.buffer += str::from_utf8(&buffer[..length]).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
contents
|
let lines = self
|
||||||
|
.buffer
|
||||||
|
.split("\n")
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
self.buffer = lines.last().unwrap().to_string();
|
||||||
|
|
||||||
|
let full_lines_len = lines.len() - 1;
|
||||||
|
for line in lines.into_iter().take(full_lines_len) {
|
||||||
|
self.lines.push(line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main.rs
11
src/main.rs
@ -126,12 +126,7 @@ fn main() -> ! {
|
|||||||
.with_rx(peripherals.GPIO7)
|
.with_rx(peripherals.GPIO7)
|
||||||
.with_tx(peripherals.GPIO8);
|
.with_tx(peripherals.GPIO8);
|
||||||
|
|
||||||
let mut at_commands = ATCommands {
|
let mut at_commands = ATCommands::new(sim_rst, sim_pwr_key, uart);
|
||||||
rst: sim_rst,
|
|
||||||
pwr_key: sim_pwr_key,
|
|
||||||
uart,
|
|
||||||
delay: Delay::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let font_renderer = FontRenderer::create(30);
|
let font_renderer = FontRenderer::create(30);
|
||||||
display.clear(Rgb565::black().as_color());
|
display.clear(Rgb565::black().as_color());
|
||||||
@ -290,5 +285,9 @@ fn thread_2_main(async_io: AsyncIO, mut at_commands: ATCommands<'static, 'static
|
|||||||
};
|
};
|
||||||
unsafe { async_io.set_at_response(response) };
|
unsafe { async_io.set_at_response(response) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(event) = at_commands.readline() {
|
||||||
|
log::info!("Event: {}", event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,9 @@ impl State for InitATState {
|
|||||||
// Wait for previous AT command to finish
|
// Wait for previous AT command to finish
|
||||||
if let Some(response) = data.io.poll_at_response() {
|
if let Some(response) = data.io.poll_at_response() {
|
||||||
match response {
|
match response {
|
||||||
Some(_) => {}
|
Some(response) => {
|
||||||
|
log::info!("Response: {}", response)
|
||||||
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user