From a215c628a794b5fd471051542bce897b7e17ecfb Mon Sep 17 00:00:00 2001 From: Vladan Popovic Date: Sun, 3 Jul 2022 02:27:36 +0200 Subject: [PATCH] http post - not working because sim800l supports tlsv1.0 only --- src/command.rs | 126 ++++++++++++++++++++++++++++++++++--------------- src/main.rs | 92 +++++++++++++++--------------------- src/modem.rs | 68 ++++++++++++++++++++------ 3 files changed, 179 insertions(+), 107 deletions(-) diff --git a/src/command.rs b/src/command.rs index f44a914..e8e6a49 100644 --- a/src/command.rs +++ b/src/command.rs @@ -71,14 +71,6 @@ impl Command { } } - pub fn gprs_open() -> Command { - Command { - text: "AT+SAPBR=1,1".to_string(), - timeout: Duration::from_millis(3000), - contains: Some("OK".to_string()), - } - } - pub fn gprs_set_apn(apn: &str) -> Command { Command { text: format!("AT+SAPBR=3,1,\"APN\",\"{}\"", apn), @@ -103,7 +95,7 @@ impl Command { } } - pub fn getbear() -> Command { + pub fn gprs_bearer_status() -> Command { Command { text: "AT+SAPBR=2,1".to_string(), timeout: Duration::from_millis(3000), @@ -111,6 +103,22 @@ impl Command { } } + pub fn gprs_bearer_open() -> Command { + Command { + text: "AT+SAPBR=1,1".to_string(), + timeout: Duration::from_millis(3000), + contains: Some("OK".to_string()), + } + } + + pub fn gprs_bearer_close() -> Command { + Command { + text: "AT+SAPBR=0,1".to_string(), + timeout: Duration::from_millis(3000), + contains: Some("OK".to_string()), + } + } + pub fn get_local_ip_addr() -> Command { Command { text: "AT+CIFSR".to_string(), @@ -135,7 +143,7 @@ impl Command { } } - pub fn http_set() -> Command { + pub fn http_set_cid() -> Command { Command { text: "AT+HTTPPARA=\"CID\",1".to_string(), timeout: Duration::from_millis(3000), @@ -159,9 +167,25 @@ impl Command { } } - pub fn http_init_url() -> Command { + pub fn http_init_url(url: &str) -> Command { Command { - text: "AT+HTTPPARA=\"URL\",\"{}\"".to_string(), + text: format!("AT+HTTPPARA=\"URL\",\"{}\"", url), + timeout: Duration::from_millis(3000), + contains: Some("OK".to_string()), + } + } + + pub fn http_set_ssl(enabled: bool) -> Command { + Command { + text: format!("AT+HTTPSSL={}", enabled as u8), + timeout: Duration::from_millis(1000), + contains: Some("OK".to_string()), + } + } + + pub fn http_set_header(header: &str, value: &str) -> Command { + Command { + text: format!("AT+HTTPPARA=\"USERDATA\",\"{}: {}\"", header, value), timeout: Duration::from_millis(3000), contains: Some("OK".to_string()), } @@ -175,31 +199,31 @@ impl Command { } } - pub fn http_set_content() -> Command { + pub fn http_set_content(content: &str) -> Command { Command { - text: "AT+HTTPPARA=\"CONTENT\",\"{}\"".to_string(), + text: format!("AT+HTTPPARA=\"CONTENT\",\"{}\"", content), timeout: Duration::from_millis(3000), contains: Some("OK".to_string()), } } - pub fn http_post_len() -> Command { + pub fn http_post_len(size: usize, time: usize) -> Command { Command { - text: "AT+HTTPDATA={}5000".to_string(), - timeout: Duration::from_millis(3000), - contains: Some("DOWNLOAD".to_string()), + text: format!("AT+HTTPDATA={},{}", size, time), + timeout: Duration::from_millis(5000), + contains: Some("OK".to_string()), } } pub fn http_post() -> Command { Command { text: "AT+HTTPACTION=1".to_string(), - timeout: Duration::from_millis(3000), - contains: Some("+HTTPACTION".to_string()), + timeout: Duration::from_millis(10000), + contains: Some("HTTPACTION".to_string()), } } - pub fn http_get_data() -> Command { + pub fn http_response() -> Command { Command { text: "AT+HTTPREAD".to_string(), timeout: Duration::from_millis(3000), @@ -207,7 +231,7 @@ impl Command { } } - pub fn closehttp() -> Command { + pub fn http_close() -> Command { Command { text: "AT+HTTPTERM".to_string(), timeout: Duration::from_millis(3000), @@ -215,19 +239,11 @@ impl Command { } } - pub fn closebear() -> Command { - Command { - text: "AT+SAPBR=0,1".to_string(), - timeout: Duration::from_millis(3000), - contains: Some("OK".to_string()), - } - } - pub fn probe() -> Command { Command { text: "AT".to_string(), timeout: Duration::from_millis(3000), - contains: Some("+CIEV".to_string()), + contains: Some("OK".to_string()), } } @@ -247,14 +263,6 @@ impl Command { } } - pub fn tcp_ssl_enable() -> Command { - Command { - text: "AT+CIPSSL=1".to_string(), - timeout: Duration::from_millis(3000), - contains: Some("OK".to_string()), - } - } - pub fn tcp_ssl_check() -> Command { Command { text: "AT+CIPSSL=?".to_string(), @@ -342,4 +350,44 @@ impl Command { contains: Some("CLOSE OK".to_string()), } } + + pub fn manufacturer_id() -> Command { + Command { + text: "AT+GMI".to_string(), + timeout: Duration::from_millis(3000), + contains: Some("OK".to_string()), + } + } + + pub fn model_id() -> Command { + Command { + text: "AT+GMM".to_string(), + timeout: Duration::from_millis(3000), + contains: Some("OK".to_string()), + } + } + + pub fn release_id() -> Command { + Command { + text: "AT+GMR".to_string(), + timeout: Duration::from_millis(3000), + contains: Some("OK".to_string()), + } + } + + pub fn get_location() -> Command { + Command { + text: "AT+CLBS=1,1".to_string(), + timeout: Duration::from_millis(10000), + contains: Some("OK".to_string()), + } + } + + pub fn ssl_opt() -> Command { + Command { + text: "AT+SSLOPT=1,1".to_string(), + timeout: Duration::from_millis(3000), + contains: Some("OK".to_string()), + } + } } diff --git a/src/main.rs b/src/main.rs index 292a6f1..a441730 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,68 +50,52 @@ fn main() -> anyhow::Result<()> { mdm.init(modem_pwrkey, modem_rst, modem_power)?; if !mdm.is_gprs_attached()? { - let _ = mdm.connect_to_gprs_ap( + let _ = mdm.gprs_attach_ap( config::A1_GPRS_AP.apn, config::A1_GPRS_AP.username, config::A1_GPRS_AP.password, )?; } - if mdm.is_gprs_attached()? { - let _ = mdm.get_ip_addr()?; + thread::sleep(Duration::from_millis(2000)); - //println!("connecting to server!"); - //if !mdm.tcp_is_ssl_enabled()? { - // let _ = mdm.tcp_ssl_enable()?; - //} - if mdm.tcp_is_ssl_enabled()? { - let _ = mdm.tcp_ssl_disable()?; + let _ = mdm.chip_info()?; + + loop { + if mdm.is_gprs_attached()? { + let _ = mdm.gprs_connect()?; + for _ in 0..3 { + let ip_addr = mdm.gprs_status()?; + if ip_addr.contains("0.0.0.0") { + thread::sleep(Duration::from_millis(2000)); + } else { + break + } + } + + let _ = mdm.location()?; + let _ = mdm.ssl_opt()?; + + println!("connecting to server!"); + //if !mdm.tcp_is_ssl_enabled()? { + // let _ = mdm.tcp_ssl_enable()?; + //} + //if mdm.tcp_is_ssl_enabled()? { + // let _ = mdm.tcp_ssl_disable()?; + //} + // + let message = "{\"lat\": 20.475370, \"long\": 44.747224}"; + let url = "https://a.tracker.called.quest"; + //let url = "https://rest.iot.fr-par.scw.cloud"; + let token = "eyJOZXRJRCI6ImUwYTc5YzM2LWExZjYtNDNiMC1hMGY3LWE2YTk1OGI3Zjk1ZCIsIk5ldEtleSI6IjZhZGU2ZWZkLThiMGYtNDQ3ZC1hNWY5LThkNDJjNDk4NDQ3MSJ9"; + let reply = mdm.http_post(url, token, message.as_bytes())?; + println!("+++++++++++++++++++++++++++++++++"); + println!("REPLY({}) = {}", reply.len(), reply); + println!("+++++++++++++++++++++++++++++++++"); + let _ = mdm.http_close()?; + + break } - let _ = mdm.tcp_set_quick_mode(false); - let _ = mdm.tcp_set_manual_receive()?; - let _ = mdm.tcp_connect("51.158.66.64", 9988)?; - - let client_id = "e-bike-tracker"; - let mut conn = ConnectPacket::new(client_id); - conn.set_clean_session(true); - let mut buf = Vec::new(); - let _ = conn.encode(&mut buf)?; - - let _ = mdm.tcp_send(&mut buf)?; - drop(buf); - - println!("+++++++++++++++++++++++++++++++++"); - let size = mdm.tcp_receive_reply_len()?; - - let mut reply = vec![0 as u8; size]; - let received_size = mdm.tcp_receive(&mut reply)?; - - println!("expected: {} / received: {}", size, received_size); - println!("+++++++++++++++++++++++++++++++++"); - drop(reply); - - let topic = TopicName::new("location")?; - let message = "{\"lat\": 20, \"long\": 44}"; - let qos = QoSWithPacketIdentifier::Level0; - - let publish_packet = PublishPacketRef::new(&topic, qos, message.as_bytes()); - let mut buf = Vec::new(); - publish_packet.encode(&mut buf)?; - let _ = mdm.tcp_send(&mut buf)?; - drop(buf); - - thread::sleep(Duration::from_millis(300)); - let size = mdm.tcp_receive_reply_len()?; - - let mut reply = vec![0 as u8; size]; - let received_size = mdm.tcp_receive(&mut reply)?; - println!("expected: {} / received: {}", size, received_size); - println!("+++++++++++++++++++++++++++++++++"); - println!("REPLY({}) = {}", reply.len(), reply.iter().map(|b| char::from(*b)).collect::()); - println!("+++++++++++++++++++++++++++++++++"); - drop(reply); - - let _ = mdm.tcp_close_connection()?; } Ok(()) diff --git a/src/modem.rs b/src/modem.rs index c7f86b7..190eaea 100644 --- a/src/modem.rs +++ b/src/modem.rs @@ -165,26 +165,25 @@ impl Modem { } #[inline(always)] - fn send_bytes(&mut self, payload: &[u8], eos: char) -> Result<()> { + fn send_bytes(&mut self, payload: &[u8], eos: Option) -> Result<()> { + self.rx.clear(); for b in payload.iter() { nb::block!(self.tx.write(*b)) .map_err(|_| ModemError::CommandError(format!("error writing {} to serial", b)))?; } - nb::block!(self.tx.write(eos as u8)) - .map_err(|_| ModemError::CommandError(format!("error writing {} to serial", eos)))?; + eos.map(|b| nb::block!(self.tx.write(b))); Ok(()) } fn send_command(&mut self, cmd: Command) -> Result { println!("-----------------------------------------------------------"); println!("Sending {} ...", cmd.text); - let _ = self.send_bytes(cmd.text.as_bytes(), '\r')?; + let _ = self.send_bytes(cmd.text.as_bytes(), Some('\r' as u8))?; self.read_response(cmd.contains, cmd.timeout) } - fn send_data(&mut self, buf: &[u8]) -> Result { - self.rx.clear(); - let _ = self.send_bytes("AT+CIPSEND".as_bytes(), '\r')?; + fn tcp_send_data(&mut self, buf: &[u8]) -> Result { + let _ = self.send_bytes("AT+CIPSEND".as_bytes(), Some('\r' as u8))?; let send_request: String = self.rx.reset(Duration::from_millis(3000)) .map(char::from) .take_while(|c| *c != '>').collect(); @@ -193,10 +192,9 @@ impl Modem { return Err(ModemError::SendDataError); } - self.send_bytes(buf, 26 as char)?; // 26_u8 = Ctrl+z - to end sending data + self.send_bytes(buf, Some(26))?; // 26_u8 = Ctrl+z - to end sending data let _ = self.read_response(Some("DATA ACCEPT".to_string()), Duration::from_millis(3000)); - self.rx.clear(); let res = self.send_command(Command { text: "AT+CIPACK".to_string(), contains: Some("OK".to_string()), @@ -205,11 +203,11 @@ impl Modem { Ok(res) } - pub fn get_ip_addr(&mut self) -> Result { - self.send_command(Command::getbear()) + pub fn gprs_status(&mut self) -> Result { + self.send_command(Command::gprs_bearer_status()) } - pub fn connect_to_gprs_ap(&mut self, apn: &str, username: &str, password: &str)-> Result<()> { + pub fn gprs_attach_ap(&mut self, apn: &str, username: &str, password: &str)-> Result<()> { println!("init gprs ..."); let _ = self.send_command(Command::gprs_init())?; @@ -219,8 +217,12 @@ impl Modem { let _ = self.send_command(Command::gprs_set_user(username))?; let _ = self.send_command(Command::gprs_set_pwd(password))?; + Ok(()) + } + + pub fn gprs_connect(&mut self)-> Result<()> { println!("open gprs ..."); - let _ = self.send_command(Command::gprs_open())?; + let _ = self.send_command(Command::gprs_bearer_open())?; Ok(()) } @@ -261,7 +263,7 @@ impl Modem { } pub fn tcp_send(&mut self, buf: &[u8]) -> Result<()> { - self.send_data(buf)?; + self.tcp_send_data(buf)?; Ok(()) } @@ -313,4 +315,42 @@ impl Modem { pub fn tcp_close_connection(&mut self) -> Result { self.send_command(Command::tcp_close()) } + + pub fn http_post(&mut self, url: &str, token: &str, content: &[u8]) -> Result { + let _ = self.send_command(Command::http_init()); + let _ = self.send_command(Command::http_set_ssl(true)); + let _ = self.send_command(Command::http_set_cid()); + let _ = self.send_command(Command::http_init_url(url)); + let _ = self.send_command(Command::http_set_header("X-Secret", token)); + let _ = self.send_command(Command::http_set_header("X-Topic", "device-dev")); + let _ = self.send_command(Command::http_set_content("application/json")); + let _ = self.send_command(Command::http_post_len(content.len(), 100000)); + let _ = self.send_bytes(content, Some(26)); + let _ = self.send_command(Command::http_post()); + self.send_command(Command::http_response()) + } + + pub fn http_close(&mut self) -> Result<()> { + let _ = self.send_command(Command::http_close())?; + Ok(()) + } + + pub fn chip_info(&mut self) -> Result<()> { + let _ = self.send_command(Command::manufacturer_id())?; + thread::sleep(Duration::from_millis(1000)); + let _ = self.send_command(Command::model_id())?; + thread::sleep(Duration::from_millis(1000)); + let _ = self.send_command(Command::release_id())?; + Ok(()) + } + + pub fn location(&mut self) -> Result<()> { + let _ = self.send_command(Command::get_location())?; + Ok(()) + } + + pub fn ssl_opt(&mut self) -> Result<()> { + let _ = self.send_command(Command::ssl_opt())?; + Ok(()) + } }