diff --git a/src/main.rs b/src/main.rs index 0b2c8e2..bcb3da9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,35 @@ mod modem; +use std; +use std::io::{BufReader, BufWriter, Cursor}; +use std::io::{Read, Write}; use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +fn start_loop(_m: &mut modem::Modem) -> () { + println!("Starting rx/tx loop (not implemented yet) ..."); +} + +struct Ap<'a> { + apn: &'a str, + username: &'a str, + password: &'a str, +} + +const A1: Ap = Ap { + apn: "internet", + username: "internet", + password: "internet", +}; + fn main() { println!("Starting GPRS ..."); - let sim800l = modem::Modem::new(); - sim800l.connect_to_gprs_ap("internet", "internet", "internet"); - println!("GPRS started ..."); + + let rx = Cursor::new(Vec::new()); + let tx = Cursor::new(Vec::new()); + let mut sim800l = modem::Modem::new(BufReader::new(rx), BufWriter::new(tx)); + + match sim800l.connect_to_gprs_ap(A1.apn, A1.username, A1.password) { + Ok(_) => start_loop(&mut sim800l), + Err(e) => println!("{}", e), + } } diff --git a/src/modem.rs b/src/modem.rs index 4e98b58..e2664b8 100644 --- a/src/modem.rs +++ b/src/modem.rs @@ -1,29 +1,64 @@ use std; +use std::io::{Read, Write}; -pub struct Modem { +pub struct Modem { is_connected: bool, + rx: R, + tx: W, } -#[derive(Debug, Clone)] -pub struct ModemConnectionError; +pub enum ModemError { + GprsAPConnectionError(String), + ATCommandError(String), + CommandError(String), +} -impl std::fmt::Display for ModemConnectionError { +impl std::fmt::Display for ModemError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "gprs connection error") - } -} - -type ModemConnection = Result; - -impl Modem { - pub fn new() -> Self { - Self { - is_connected: false, + match self { + Self::GprsAPConnectionError(msg) => write!(f, "gprs connection error {}", msg), + Self::ATCommandError(msg) => write!(f, "AT command error {}", msg), + Self::CommandError(msg) => write!(f, "Modem command error {}", msg), } } - pub fn connect_to_gprs_ap(mut self, apn: &str, username: &str, password: &str)-> ModemConnection { - // TODO: set AT command for connecting to gprs - self.is_connected = true; - Ok(self) +} + +pub type Result = std::result::Result; + +impl Modem { + pub fn new(rx: R, tx: W) -> Self { + Self { + is_connected: false, + rx, + tx, + } + } + + fn at_command(&mut self, cmd: &str) -> Result { + let mut msg = "AT+".to_owned(); + msg.push_str(cmd); + self.send_command(msg.to_owned()) + .map_err(|err| ModemError::ATCommandError(format!("{}", err))) + } + + fn send_command(&mut self, cmd: String) -> Result { + self.tx.write(cmd.as_bytes()) + .map_err(|err| ModemError::CommandError(format!("{}", err)))?; + let mut response = String::new(); + self.rx.read_to_string(&mut response) + .map_err(|err| ModemError::CommandError(format!("{}", err)))?; + if cfg!(debug_assertions) { + println!("{} = {}", cmd, response); + } + Ok(response) + } + + pub fn connect_to_gprs_ap(&mut self, apn: &str, username: &str, password: &str)-> Result<()> { + self.at_command("CGATTCGATT=1") + .map(|_| { + println!("connecting to {} with {}:{}", apn, username, password); + self.is_connected = true; + }) + .map_err(|err| ModemError::GprsAPConnectionError(format!("{}", err))) } }