connect to gprs and check if attached
This commit is contained in:
		
							parent
							
								
									1cb8a90caf
								
							
						
					
					
						commit
						94b9ce312f
					
				
					 3 changed files with 189 additions and 122 deletions
				
			
		
							
								
								
									
										168
									
								
								src/command.rs
									
										
									
									
									
								
							
							
						
						
									
										168
									
								
								src/command.rs
									
										
									
									
									
								
							|  | @ -3,215 +3,231 @@ use std::time::Duration; | ||||||
| pub struct Command { | pub struct Command { | ||||||
|     pub text: String, |     pub text: String, | ||||||
|     pub timeout: Duration, |     pub timeout: Duration, | ||||||
|     pub ends_with: Option<String>, |     pub contains: Option<String>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Command { | impl Command { | ||||||
|     pub fn initgprs() -> Command { |     pub fn initgprs() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+SAPBR=3,1,\"Contype\",\"GPRS\"".to_owned(), |             text: "AT+SAPBR=3,1,\"Contype\",\"GPRS\"".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn modeminfo() -> Command { |     pub fn modeminfo() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "ATI".to_owned(), |             text: "ATI".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(6000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("+CIEV".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn fwrevision() -> Command { |     pub fn fwrevision() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+CGMR".to_owned(), |             text: "AT+CGMR".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn battery() -> Command { |     pub fn battery() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+CBC".to_owned(), |             text: "AT+CBC".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn scan() -> Command { |     pub fn scan() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+COPS=?".to_owned(), |             text: "AT+COPS=?".to_string(), | ||||||
|             timeout: Duration::from_millis(60), |             timeout: Duration::from_millis(60000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn network() -> Command { |     pub fn network() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+COPS?".to_owned(), |             text: "AT+COPS?".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn signal() -> Command { |     pub fn signal() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+CSQ".to_owned(), |             text: "AT+CSQ".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn checkreg() -> Command { |     pub fn checkreg() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+CREG?".to_owned(), |             text: "AT+CREG?".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: None, |             contains: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn opengprs() -> Command { |     pub fn opengprs() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+SAPBR=1,1".to_owned(), |             text: "AT+SAPBR=1,1".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn getbear() -> Command { |     pub fn getbear() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+SAPBR=2,1".to_owned(), |             text: "AT+SAPBR=2,1".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn inithttp() -> Command { |     pub fn inithttp() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPINIT".to_owned(), |             text: "AT+HTTPINIT".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn sethttp() -> Command { |     pub fn sethttp() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPPARA=\"CID\",1".to_owned(), |             text: "AT+HTTPPARA=\"CID\",1".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn checkssl() -> Command { |     pub fn checkssl() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+CIPSSL=?".to_owned(), |             text: "AT+CIPSSL=?".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn enablessl() -> Command { |     pub fn enablessl() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPSSL=1".to_owned(), |             text: "AT+HTTPSSL=1".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn disablessl() -> Command { |     pub fn disablessl() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPSSL=0".to_owned(), |             text: "AT+HTTPSSL=0".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn initurl() -> Command { |     pub fn initurl() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPPARA=\"URL\",\"{}\"".to_owned(), |             text: "AT+HTTPPARA=\"URL\",\"{}\"".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn doget() -> Command { |     pub fn doget() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPACTION=0".to_owned(), |             text: "AT+HTTPACTION=0".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("+HTTPACTION".to_owned()), |             contains: Some("+HTTPACTION".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn setcontent() -> Command { |     pub fn setcontent() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPPARA=\"CONTENT\",\"{}\"".to_owned(), |             text: "AT+HTTPPARA=\"CONTENT\",\"{}\"".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn postlen() -> Command { |     pub fn postlen() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPDATA={}5000".to_owned(), |             text: "AT+HTTPDATA={}5000".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("DOWNLOAD".to_owned()), |             contains: Some("DOWNLOAD".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn dopost() -> Command { |     pub fn dopost() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPACTION=1".to_owned(), |             text: "AT+HTTPACTION=1".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("+HTTPACTION".to_owned()), |             contains: Some("+HTTPACTION".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn getdata() -> Command { |     pub fn getdata() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPREAD".to_owned(), |             text: "AT+HTTPREAD".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn closehttp() -> Command { |     pub fn closehttp() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+HTTPTERM".to_owned(), |             text: "AT+HTTPTERM".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn closebear() -> Command { |     pub fn closebear() -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: "AT+SAPBR=0,1".to_owned(), |             text: "AT+SAPBR=0,1".to_string(), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn setapn(apn: &str) -> Command { |     pub fn setapn(apn: &str) -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: format!("AT+SAPBR=3,1,\"APN\",\"{}\"", apn), |             text: format!("AT+SAPBR=3,1,\"APN\",\"{}\"", apn), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn setuser(user: &str) -> Command { |     pub fn setuser(user: &str) -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: format!("AT+SAPBR=3,1,\"USER\",\"{}\"", user), |             text: format!("AT+SAPBR=3,1,\"USER\",\"{}\"", user), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn setpwd(password: &str) -> Command { |     pub fn setpwd(password: &str) -> Command { | ||||||
|         Command { |         Command { | ||||||
|             text: format!("AT+SAPBR=3,1,\"PWD\",\"{}\"", password), |             text: format!("AT+SAPBR=3,1,\"PWD\",\"{}\"", password), | ||||||
|             timeout: Duration::from_millis(3), |             timeout: Duration::from_millis(3000), | ||||||
|             ends_with: Some("OK".to_owned()), |             contains: Some("OK".to_string()), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn probe() -> Command { | ||||||
|  |         Command { | ||||||
|  |             text: "AT".to_string(), | ||||||
|  |             timeout: Duration::from_millis(3000), | ||||||
|  |             contains: Some("+CIEV".to_string()), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn is_gprs_attached() -> Command { | ||||||
|  |         Command { | ||||||
|  |             text: "AT+CGATT?".to_string(), | ||||||
|  |             timeout: Duration::from_millis(1000), | ||||||
|  |             contains: Some("OK".to_string()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -7,6 +7,10 @@ use anyhow; | ||||||
| use esp_idf_hal::prelude::*; | use esp_idf_hal::prelude::*; | ||||||
| use esp_idf_hal::peripherals::Peripherals; | use esp_idf_hal::peripherals::Peripherals; | ||||||
| use esp_idf_hal::serial; | use esp_idf_hal::serial; | ||||||
|  | use std::time::Duration; | ||||||
|  | use std::thread; | ||||||
|  | 
 | ||||||
|  | use std::sync::mpsc::{channel, Receiver, Sender}; | ||||||
| 
 | 
 | ||||||
| fn main() -> anyhow::Result<()> { | fn main() -> anyhow::Result<()> { | ||||||
|     esp_idf_sys::link_patches(); |     esp_idf_sys::link_patches(); | ||||||
|  | @ -38,16 +42,18 @@ fn main() -> anyhow::Result<()> { | ||||||
|     let modem_power = dp.pins.gpio23.into_output().unwrap(); |     let modem_power = dp.pins.gpio23.into_output().unwrap(); | ||||||
| 
 | 
 | ||||||
|     modem::init(modem_pwrkey, modem_rst, modem_power)?; |     modem::init(modem_pwrkey, modem_rst, modem_power)?; | ||||||
| 
 |  | ||||||
|     let (tx, rx) = serial.split(); |     let (tx, rx) = serial.split(); | ||||||
|     let mut mdm = modem::Modem::new(tx, rx); |     let mut mdm = modem::Modem::new(tx, rx); | ||||||
| 
 | 
 | ||||||
|     let _ = mdm.modem_info()?; |     let _ = mdm.probe()?; | ||||||
|     let _ = mdm.connect_to_gprs_ap( |     let _ = mdm.connect_to_gprs_ap( | ||||||
|         config::A1_GPRS_AP.apn, |         config::A1_GPRS_AP.apn, | ||||||
|         config::A1_GPRS_AP.username, |         config::A1_GPRS_AP.username, | ||||||
|         config::A1_GPRS_AP.password, |         config::A1_GPRS_AP.password, | ||||||
|     )?; |     )?; | ||||||
|  |     if mdm.is_gprs_attached()? { | ||||||
|  |         println!("GPRS ATTACHEEEDDDDDDDDD!!!!!!!!!!!!!!!1"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										133
									
								
								src/modem.rs
									
										
									
									
									
								
							
							
						
						
									
										133
									
								
								src/modem.rs
									
										
									
									
									
								
							|  | @ -1,18 +1,19 @@ | ||||||
| use crate::command::Command; | use crate::command::Command; | ||||||
| 
 | 
 | ||||||
| use std::iter::FromIterator; |  | ||||||
| use std::thread; | use std::thread; | ||||||
|  | use std::io::{Error as IoError, ErrorKind, BufRead}; | ||||||
| use std::error::Error; | use std::error::Error; | ||||||
| use std::time::{Duration, Instant}; | use std::time::{Duration, Instant}; | ||||||
| 
 | 
 | ||||||
| use embedded_hal::serial::{Read, Write}; | use embedded_hal::serial::{Read, Write}; | ||||||
| use embedded_hal::digital::v2::OutputPin; | use embedded_hal::digital::v2::OutputPin; | ||||||
| use esp_idf_hal::serial::{self, Rx, Tx}; | use esp_idf_hal::serial::{self, Rx, Tx, SerialError}; | ||||||
| 
 | 
 | ||||||
|  | pub type Result<T> = std::result::Result<T, ModemError>; | ||||||
| 
 | 
 | ||||||
| pub struct Modem<UART: serial::Uart> { | pub struct Modem<UART: serial::Uart> { | ||||||
|     is_connected: bool, |     is_connected: bool, | ||||||
|     rx: Rx<UART>, |     rx: MyRx<UART>, | ||||||
|     tx: Tx<UART>, |     tx: Tx<UART>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -20,6 +21,7 @@ pub struct Modem<UART: serial::Uart> { | ||||||
| pub enum ModemError { | pub enum ModemError { | ||||||
|     CommandError(String), |     CommandError(String), | ||||||
|     SetupError(String), |     SetupError(String), | ||||||
|  |     TimeoutError, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Error for ModemError {} | impl Error for ModemError {} | ||||||
|  | @ -30,13 +32,39 @@ impl std::fmt::Display for ModemError { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub type Result<T> = std::result::Result<T, ModemError>; | struct MyRx<UART: serial::Uart>(Rx<UART>); | ||||||
|  | 
 | ||||||
|  | impl<UART: serial::Uart> MyRx<UART> { | ||||||
|  |     fn read(&mut self) -> nb::Result<u8, SerialError> { | ||||||
|  |         self.0.read() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn read_blocking(&mut self) -> std::result::Result<u8, SerialError> { | ||||||
|  |         nb::block!(self.read()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<UART: serial::Uart> std::io::Read for MyRx<UART> { | ||||||
|  |     fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { | ||||||
|  |         let mut read_bytes: usize = 0; | ||||||
|  |         loop { | ||||||
|  |             let b = self.read_blocking() | ||||||
|  |                 .map_err(|err| IoError::new(ErrorKind::Other, format!("Serial error {:?}", err)))?; | ||||||
|  |             buf[read_bytes] = b; | ||||||
|  |             read_bytes += 1; | ||||||
|  |             if b == '\0' as u8 || b == '\n' as u8 { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         Ok(read_bytes) | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| impl<UART: serial::Uart> Modem<UART> { | impl<UART: serial::Uart> Modem<UART> { | ||||||
|     pub fn new(tx: Tx<UART>, rx: Rx<UART>) -> Self { |     pub fn new(tx: Tx<UART>, rx: Rx<UART>) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             is_connected: false, |             is_connected: false, | ||||||
|             rx, |             rx: MyRx(rx), | ||||||
|             tx, |             tx, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -51,69 +79,86 @@ impl<UART: serial::Uart> Modem<UART> { | ||||||
|     /// It's ok to use this function like this for now because the write/read cycle is blocking,
 |     /// It's ok to use this function like this for now because the write/read cycle is blocking,
 | ||||||
|     /// hence the case where multiple writes happen asynchronously isn't handled. See
 |     /// hence the case where multiple writes happen asynchronously isn't handled. See
 | ||||||
|     /// [send_command](crate::modem::Modem::send_command) for more info on the blocking part.
 |     /// [send_command](crate::modem::Modem::send_command) for more info on the blocking part.
 | ||||||
|     fn read_response(&mut self, expected: Option<String>, timeout: Duration) -> Result<String> { |     fn read_response(&mut self, contains: Option<String>, timeout: Duration) -> Result<String> { | ||||||
|         let len = self.rx.count() |  | ||||||
|             .map_err(|_| ModemError::CommandError("Error getting RX fifo length".to_owned()))?; |  | ||||||
| 
 |  | ||||||
|         println!("Reading {} bytes from serial RX ...", len); |  | ||||||
| 
 |  | ||||||
|         let mut response = String::new(); |         let mut response = String::new(); | ||||||
|         let now = Instant::now(); |         let now = Instant::now(); | ||||||
|  |         let match_text: String = contains.unwrap_or("".to_string()); | ||||||
|  | 
 | ||||||
|  |         let mut reader = std::io::BufReader::new(&mut self.rx); | ||||||
| 
 | 
 | ||||||
|         loop { |         loop { | ||||||
|             let len = self.rx.count().unwrap(); |             let mut line = String::new(); | ||||||
|             if len == 0 { |             reader.read_line(&mut line) | ||||||
|  |                 .map_err(|err| ModemError::CommandError(format!("read line failed: {}", err)))?; | ||||||
|  |             println!("Read {} from serial ...", line.trim()); | ||||||
|  | 
 | ||||||
|  |             // check if empty first because it's much simpler and more frequent
 | ||||||
|  |             if line == "" { | ||||||
|                 if now + timeout > Instant::now() { |                 if now + timeout > Instant::now() { | ||||||
|  |                     return Err(ModemError::TimeoutError); | ||||||
|  |                 } | ||||||
|  |                 thread::sleep(Duration::from_millis(1000)); | ||||||
|  |                 continue; | ||||||
|  |             } else { | ||||||
|  |                 response.push_str(&line); | ||||||
|  |                 if line.contains(&match_text) { | ||||||
|  |                     println!("Found match {} for line {} ... exiting response reader now!", match_text, line); | ||||||
|  |                     println!("-----------------------------------------------------------"); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 thread::sleep(Duration::from_secs(1)); |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|             println!("Reading {} bytes from serial RX ...", len); |  | ||||||
| 
 |  | ||||||
|             for _ in 0..len { |  | ||||||
|                 nb::block!(self.rx.read()) |  | ||||||
|                     .map(|b| response.push(b as char)) |  | ||||||
|                     .map_err(|_| ModemError::CommandError("Error reading from RX".to_owned()))?; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         let response = response.trim(); |         Ok(response.to_string()) | ||||||
| 
 |  | ||||||
|         println!("Received: {}", response); |  | ||||||
| 
 |  | ||||||
|         expected.map(|expected_end| { |  | ||||||
|             if response.ends_with(&expected_end) { |  | ||||||
|                 Ok(response.to_owned()) |  | ||||||
|             } else { |  | ||||||
|                 let res = String::from_iter(response.chars().rev().take(expected_end.len())); |  | ||||||
|                 Err(ModemError::CommandError(format!("Got invalid response end {} instead of expected {}", res, expected_end))) |  | ||||||
|             } |  | ||||||
|         }).unwrap_or(Ok(response.to_owned())) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn send_command(&mut self, cmd: Command) -> Result<String> { |     fn send_command(&mut self, cmd: Command) -> Result<String> { | ||||||
|         for b in cmd.text.as_bytes().iter() { |         for b in cmd.text.as_bytes().iter() { | ||||||
|             nb::block!(self.tx.write(*b)).map_err(|_| ModemError::CommandError("error writing to serial".to_owned()))?; |             nb::block!(self.tx.write(*b)).map_err(|_| ModemError::CommandError("error writing to serial".to_string()))?; | ||||||
|         } |         } | ||||||
|         self.read_response(cmd.ends_with, cmd.timeout) |         nb::block!(self.tx.write('\r' as u8)).map_err(|_| ModemError::CommandError("error writing <CR> to serial".to_string()))?; | ||||||
|  |         self.read_response(cmd.contains.clone(), cmd.timeout.clone()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_ip_addr(&mut self) -> Result<String> { | ||||||
|  |         println!("getting ip addres ..."); | ||||||
|  |         let res = self.send_command(Command::getbear())?; | ||||||
|  |         println!("{}", res); | ||||||
|  |         Ok(res) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn connect_to_gprs_ap(&mut self, apn: &str, username: &str, password: &str)-> Result<()> { |     pub fn connect_to_gprs_ap(&mut self, apn: &str, username: &str, password: &str)-> Result<()> { | ||||||
|  |         println!("init gprs ..."); | ||||||
|  |         let _ = self.send_command(Command::initgprs())?; | ||||||
|  | 
 | ||||||
|         println!("connecting to {} with {}:{}", apn, username, password); |         println!("connecting to {} with {}:{}", apn, username, password); | ||||||
| 
 | 
 | ||||||
|         let _ = self.send_command(Command::setapn(apn))?; |         let _ = self.send_command(Command::setapn(apn))?; | ||||||
|         let _ = self.send_command(Command::setuser(username))?; |         let _ = self.send_command(Command::setuser(username))?; | ||||||
|         let _ = self.send_command(Command::setpwd(password))?; |         let _ = self.send_command(Command::setpwd(password))?; | ||||||
|         let _ = self.send_command(Command::opengprs())?; | 
 | ||||||
|  |         println!("open gprs ..."); | ||||||
|  |         let _ = self.send_command(Command::initgprs())?; | ||||||
| 
 | 
 | ||||||
|         self.is_connected = true; |         self.is_connected = true; | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn modem_info(&mut self)-> Result<String> { |     pub fn info(&mut self)-> Result<String> { | ||||||
|         println!("testing modem with AP command"); |         println!("getting modem info with API command"); | ||||||
|         self.send_command(Command::modeminfo()) |         self.send_command(Command::modeminfo()) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn probe(&mut self)-> Result<String> { | ||||||
|  |         println!("probing modem with AP command"); | ||||||
|  |         self.send_command(Command::probe()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn is_gprs_attached(&mut self)-> Result<bool> { | ||||||
|  |         println!("testing gprs connection ..."); | ||||||
|  |         let res = self.send_command(Command::is_gprs_attached())?; | ||||||
|  | 
 | ||||||
|  |         Ok(res.contains("+CGATT: 1")) | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Initialize the modem (sim800l in this case). The initialization process sets all pins in the
 | /// Initialize the modem (sim800l in this case). The initialization process sets all pins in the
 | ||||||
|  | @ -133,14 +178,14 @@ impl<UART: serial::Uart> Modem<UART> { | ||||||
| /// ```
 | /// ```
 | ||||||
| pub fn init(mut pwrkey: impl OutputPin, mut rst: impl OutputPin, mut power: impl OutputPin) -> Result<()> { | pub fn init(mut pwrkey: impl OutputPin, mut rst: impl OutputPin, mut power: impl OutputPin) -> Result<()> { | ||||||
|     println!("Turning SIM800L on ..."); |     println!("Turning SIM800L on ..."); | ||||||
|     power.set_high().map_err(|_| ModemError::SetupError("Error setting POWER to high.".to_owned()))?; |     power.set_high().map_err(|_| ModemError::SetupError("Error setting POWER to high.".to_string()))?; | ||||||
|     rst.set_high().map_err(|_| ModemError::SetupError("Error setting RST to high.".to_owned()))?; |     rst.set_high().map_err(|_| ModemError::SetupError("Error setting RST to high.".to_string()))?; | ||||||
|     // Pull down PWRKEY for more than 1 second according to manual requirements
 |     // Pull down PWRKEY for more than 1 second according to manual requirements
 | ||||||
|     pwrkey.set_high().map_err(|_| ModemError::SetupError("Error setting PWRKEY to high.".to_owned()))?; |     pwrkey.set_high().map_err(|_| ModemError::SetupError("Error setting PWRKEY to high.".to_string()))?; | ||||||
|     thread::sleep(Duration::from_millis(100)); |     thread::sleep(Duration::from_millis(100)); | ||||||
|     pwrkey.set_low().map_err(|_| ModemError::SetupError("Error setting PWRKEY to low.".to_owned()))?; |     pwrkey.set_low().map_err(|_| ModemError::SetupError("Error setting PWRKEY to low.".to_string()))?; | ||||||
|     thread::sleep(Duration::from_millis(1000)); |     thread::sleep(Duration::from_millis(1000)); | ||||||
|     pwrkey.set_high().map_err(|_| ModemError::SetupError("Error setting PWRKEY to high.".to_owned()))?; |     pwrkey.set_high().map_err(|_| ModemError::SetupError("Error setting PWRKEY to high.".to_string()))?; | ||||||
|     println!("Waiting 3s for sim module to come online ..."); |     println!("Waiting 3s for sim module to come online ..."); | ||||||
|     thread::sleep(Duration::from_millis(3000)); |     thread::sleep(Duration::from_millis(3000)); | ||||||
|     Ok(()) |     Ok(()) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue