move code around to make the modem restartable
This commit is contained in:
parent
9d536bdce9
commit
7a22f14e1f
2 changed files with 95 additions and 103 deletions
67
src/main.rs
67
src/main.rs
|
@ -10,6 +10,10 @@ mod gps;
|
||||||
use anyhow;
|
use anyhow;
|
||||||
use std::{thread::{self, JoinHandle}, time::Duration};
|
use std::{thread::{self, JoinHandle}, time::Duration};
|
||||||
use esp_idf_hal::peripherals::Peripherals;
|
use esp_idf_hal::peripherals::Peripherals;
|
||||||
|
use esp_idf_hal::prelude::*;
|
||||||
|
use esp_idf_hal::serial::{Pins, config::Config, Serial, UART1, Uart};
|
||||||
|
use embedded_hal::digital::v2::OutputPin;
|
||||||
|
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
|
@ -19,6 +23,27 @@ fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
println!("Rust main thread: {:?}", thread::current());
|
println!("Rust main thread: {:?}", thread::current());
|
||||||
|
|
||||||
|
let mut threads: Vec<JoinHandle<anyhow::Result<_>>> = vec![];
|
||||||
|
|
||||||
|
// // Rx/Tx pins for the GPS modem
|
||||||
|
let gps_rx = dp.pins.gpio32;
|
||||||
|
let gps_tx = dp.pins.gpio33;
|
||||||
|
// // UART interface for the GPS modem
|
||||||
|
let gps_uart = dp.uart2;
|
||||||
|
|
||||||
|
|
||||||
|
let (gps_sender, receiver) = std::sync::mpsc::sync_channel::<Msg>(10);
|
||||||
|
//let accel_sender = gps_sender.clone();
|
||||||
|
|
||||||
|
//let _ = gps::main(gps_tx, gps_rx, gps_uart, gps_sender)?;
|
||||||
|
threads.push(thread::spawn(move || gps::main(gps_tx, gps_rx, gps_uart, gps_sender)));
|
||||||
|
thread::sleep(Duration::from_millis(1000));
|
||||||
|
//threads.push(thread::spawn(move || accel::main(accel_sender)));
|
||||||
|
|
||||||
|
// ==================================
|
||||||
|
// MODEM INITIALIZATION AND MAIN LOOP
|
||||||
|
// ==================================
|
||||||
|
|
||||||
// LilyGo TTGO T-Call sim800l board serial pins.
|
// LilyGo TTGO T-Call sim800l board serial pins.
|
||||||
let modem_rx = dp.pins.gpio26;
|
let modem_rx = dp.pins.gpio26;
|
||||||
let modem_tx = dp.pins.gpio27;
|
let modem_tx = dp.pins.gpio27;
|
||||||
|
@ -29,24 +54,36 @@ fn main() -> anyhow::Result<()> {
|
||||||
// UART interface for the GSM modem
|
// UART interface for the GSM modem
|
||||||
let modem_uart = dp.uart1;
|
let modem_uart = dp.uart1;
|
||||||
|
|
||||||
let mut threads: Vec<JoinHandle<anyhow::Result<_>>> = vec![];
|
let serial_pins = Pins {
|
||||||
|
tx: modem_tx,
|
||||||
|
rx: modem_rx,
|
||||||
|
cts: None,
|
||||||
|
rts: None,
|
||||||
|
};
|
||||||
|
|
||||||
// // Rx/Tx pins for the GPS modem
|
let serial: Serial<UART1, _, _> = Serial::new(
|
||||||
let gps_rx = dp.pins.gpio32;
|
modem_uart,
|
||||||
let gps_tx = dp.pins.gpio33;
|
serial_pins,
|
||||||
// // UART interface for the GPS modem
|
Config::default().baudrate(Hertz(115200)),
|
||||||
let gps_uart = dp.uart2;
|
)?;
|
||||||
|
|
||||||
|
let (tx, rx) = serial.split();
|
||||||
|
type PwrkeyOutput = esp_idf_hal::gpio::Gpio4<esp_idf_hal::gpio::Output>;
|
||||||
|
type ResetOutput = esp_idf_hal::gpio::Gpio5<esp_idf_hal::gpio::Output>;
|
||||||
|
type PowerOutput = esp_idf_hal::gpio::Gpio23<esp_idf_hal::gpio::Output>;
|
||||||
|
|
||||||
let (gps_sender, receiver) = std::sync::mpsc::sync_channel::<Msg>(1);
|
let mut mdm: modem::Modem<UART1, PwrkeyOutput, ResetOutput, PowerOutput> = modem::Modem::new(tx, rx, modem_pwrkey, modem_rst, modem_power, receiver);
|
||||||
//let accel_sender = gps_sender.clone();
|
|
||||||
|
|
||||||
//let _ = gps::main(gps_tx, gps_rx, gps_uart, gps_sender)?;
|
let mqtt_username = include_str!("../secret/username").trim();
|
||||||
threads.push(thread::spawn(move || gps::main(gps_tx, gps_rx, gps_uart, gps_sender)));
|
let mqtt_password = include_str!("../secret/password").trim();
|
||||||
thread::sleep(Duration::from_millis(1000));
|
|
||||||
//threads.push(thread::spawn(move || accel::main(accel_sender)));
|
|
||||||
|
|
||||||
let _ = modem::main(modem_rx, modem_tx, modem_uart, modem_pwrkey, modem_rst, modem_power, receiver)?;
|
loop {
|
||||||
|
println!("======================= MAIN =======================");
|
||||||
Ok(())
|
mdm.init().unwrap_or(());
|
||||||
|
let _ = mdm.echo(false).unwrap_or(());
|
||||||
|
println!("resetting modem ... ");
|
||||||
|
println!("======================= MODEM =======================");
|
||||||
|
let _ = mdm.start_sending(mqtt_username, mqtt_password).unwrap_or(());
|
||||||
|
thread::sleep(Duration::from_millis(1500));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
131
src/modem.rs
131
src/modem.rs
|
@ -13,7 +13,6 @@ use std::{
|
||||||
sync::mpsc::Receiver,
|
sync::mpsc::Receiver,
|
||||||
};
|
};
|
||||||
|
|
||||||
use esp_idf_hal::prelude::*;
|
|
||||||
use esp_idf_hal::serial::{self, Rx, Tx};
|
use esp_idf_hal::serial::{self, Rx, Tx};
|
||||||
|
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
use embedded_hal::digital::v2::OutputPin;
|
||||||
|
@ -33,10 +32,6 @@ use serde_json_core;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, ModemError>;
|
pub type Result<T> = std::result::Result<T, ModemError>;
|
||||||
|
|
||||||
pub struct Modem<UART: serial::Uart> {
|
|
||||||
serial: SerialIO<UART>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ModemError {
|
pub enum ModemError {
|
||||||
CommandError(String),
|
CommandError(String),
|
||||||
|
@ -54,10 +49,22 @@ impl std::fmt::Display for ModemError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<UART: serial::Uart> Modem<UART> {
|
pub struct Modem<UART: serial::Uart, PWK: OutputPin, RST: OutputPin, PW: OutputPin> {
|
||||||
pub fn new(tx: Tx<UART>, rx: Rx<UART>) -> Self {
|
serial: SerialIO<UART>,
|
||||||
|
reset: RST,
|
||||||
|
power: PW,
|
||||||
|
power_key: PWK,
|
||||||
|
receiver: Receiver<Msg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<UART: serial::Uart, PWK: OutputPin, RST: OutputPin, PW: OutputPin> Modem<UART, PWK, RST, PW> {
|
||||||
|
pub fn new(tx: Tx<UART>, rx: Rx<UART>, mut pwrkey: PWK, mut rst: RST, mut power: PW, receiver: Receiver<Msg>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
serial: SerialIO::new(tx, rx),
|
serial: SerialIO::new(tx, rx),
|
||||||
|
reset: rst,
|
||||||
|
power,
|
||||||
|
power_key: pwrkey,
|
||||||
|
receiver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,22 +83,23 @@ impl<UART: serial::Uart> Modem<UART> {
|
||||||
///
|
///
|
||||||
/// modem::init(modem_pwrkey, modem_rst, modem_power);
|
/// modem::init(modem_pwrkey, modem_rst, modem_power);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn init(&mut self, mut pwrkey: impl OutputPin, mut rst: impl OutputPin, mut power: impl OutputPin) -> Result<()> {
|
pub fn init(&mut self) -> Result<()> {
|
||||||
println!("Turning SIM800L on ...");
|
println!("Turning SIM800L on ...");
|
||||||
power.set_high().map_err(|_| ModemError::SetupError("Error setting POWER to high.".to_string()))?;
|
self.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_string()))?;
|
self.reset.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_string()))?;
|
self.power_key.set_high().map_err(|_| ModemError::SetupError("Error setting PWRKEY to high.".to_string()))?;
|
||||||
thread::sleep(Duration::from_millis(1500));
|
thread::sleep(Duration::from_millis(1500));
|
||||||
pwrkey.set_low().map_err(|_| ModemError::SetupError("Error setting PWRKEY to low.".to_string()))?;
|
self.power_key.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_string()))?;
|
self.power_key.set_high().map_err(|_| ModemError::SetupError("Error setting PWRKEY to high.".to_string()))?;
|
||||||
println!("Waiting for sim module to come online ...");
|
println!("Waiting for sim module to come online ...");
|
||||||
thread::sleep(Duration::from_millis(3000));
|
thread::sleep(Duration::from_millis(3000));
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let _ = self.send_command(Command::probe()).unwrap_or("".to_string());
|
let _ = self.send_command(Command::probe()).unwrap_or("".to_string());
|
||||||
thread::sleep(Duration::from_millis(1000));
|
thread::sleep(Duration::from_millis(1000));
|
||||||
}
|
}
|
||||||
|
self.serial.clear();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +150,7 @@ impl<UART: serial::Uart> Modem<UART> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&mut self, at_command: &str, contains: &str) -> Result<String> {
|
fn send(&mut self, at_command: &str, contains: &str) -> Result<String> {
|
||||||
|
self.serial.clear();
|
||||||
println!("-----------------------------------------------------------");
|
println!("-----------------------------------------------------------");
|
||||||
println!("Sending {} ...", at_command);
|
println!("Sending {} ...", at_command);
|
||||||
|
|
||||||
|
@ -303,8 +312,8 @@ impl<UART: serial::Uart> Modem<UART> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tcp_manual_send(&mut self, buf: &[u8]) -> Result<()> {
|
pub fn tcp_manual_send(&mut self, buf: &[u8]) -> Result<()> {
|
||||||
thread::sleep(Duration::from_millis(200));
|
thread::sleep(Duration::from_millis(200));
|
||||||
self.serial.clear();
|
// self.serial.clear();
|
||||||
self.tcp_manual_send_data(buf)
|
self.tcp_manual_send_data(buf)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
@ -360,8 +369,8 @@ impl<UART: serial::Uart> Modem<UART> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tcp_close_connection(&mut self) -> Result<String> {
|
pub fn tcp_close_connection(&mut self) -> Result<()> {
|
||||||
self.send_command(Command::tcp_close())
|
self.send_command(Command::tcp_close()).map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn http_post(&mut self, url: &str, token: &str, content: &[u8]) -> Result<String> {
|
pub fn http_post(&mut self, url: &str, token: &str, content: &[u8]) -> Result<String> {
|
||||||
|
@ -506,96 +515,43 @@ impl<UART: serial::Uart> Modem<UART> {
|
||||||
self.tcp_manual_send(&mut buf)?;
|
self.tcp_manual_send(&mut buf)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<UART: serial::Uart> std::io::Read for Modem<UART> {
|
pub fn start_sending(&mut self, mqtt_username: &str, mqtt_password: &str) -> anyhow::Result<()> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
if !self.is_gprs_attached()? {
|
||||||
self.tcp_receive(buf).map_err(|_| std::io::Error::from(std::io::ErrorKind::ConnectionAborted))
|
let _ = self.gprs_attach_ap(crate::config::MTS)?;
|
||||||
}
|
let _ = self.try_connect_gprs()?;
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main<PRx,PTx, DPK, DR, DP>
|
|
||||||
(
|
|
||||||
rx: PRx,
|
|
||||||
tx: PTx,
|
|
||||||
uart: serial::UART1,
|
|
||||||
pwrkey: DPK,
|
|
||||||
rst: DR,
|
|
||||||
power: DP,
|
|
||||||
receiver: Receiver<Msg>,
|
|
||||||
) -> std::result::Result<(), anyhow::Error>
|
|
||||||
where
|
|
||||||
PRx: esp_idf_hal::gpio::Pin + esp_idf_hal::gpio::InputPin + esp_idf_hal::gpio::OutputPin,
|
|
||||||
PTx: esp_idf_hal::gpio::Pin + esp_idf_hal::gpio::InputPin + esp_idf_hal::gpio::OutputPin,
|
|
||||||
DPK: embedded_hal::digital::v2::OutputPin,
|
|
||||||
DR: embedded_hal::digital::v2::OutputPin,
|
|
||||||
DP: embedded_hal::digital::v2::OutputPin,
|
|
||||||
{
|
|
||||||
let serial_pins = serial::Pins {
|
|
||||||
tx,
|
|
||||||
rx,
|
|
||||||
cts: None,
|
|
||||||
rts: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let serial: serial::Serial<serial::UART1, _, _> = serial::Serial::new(
|
|
||||||
uart,
|
|
||||||
serial_pins,
|
|
||||||
serial::config::Config::default().baudrate(Hertz(115200)),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let (tx, rx) = serial.split();
|
|
||||||
let mut mdm = Modem::new(tx, rx);
|
|
||||||
|
|
||||||
let mqtt_username = include_str!("../secret/username").trim();
|
|
||||||
let mqtt_password = include_str!("../secret/password").trim();
|
|
||||||
|
|
||||||
// thread::sleep(Duration::from_millis(500));
|
|
||||||
|
|
||||||
//println!("setting up client TLS cert");
|
|
||||||
//let client_cert = include_bytes!("../certs/full-bin.p12");
|
|
||||||
//let client_cert_path = "C:\\USER\\fullchain.pem";
|
|
||||||
|
|
||||||
//let _ = mdm.upload_cert(client_cert_path, client_cert)?;
|
|
||||||
//let _ = mdm.ssl_set_client_cert(client_cert_path, "t")?;
|
|
||||||
//let _ = mdm.fs_list("C:\\USER\\")?;
|
|
||||||
|
|
||||||
fn start_sending(mdm: &mut Modem<serial::UART1>, mqtt_username: &str, mqtt_password: &str, receiver: Receiver<Msg>) -> anyhow::Result<()> {
|
|
||||||
if !mdm.is_gprs_attached()? {
|
|
||||||
let _ = mdm.gprs_attach_ap(crate::config::MTS)?;
|
|
||||||
let _ = mdm.try_connect_gprs()?;
|
|
||||||
}
|
}
|
||||||
// When command AT+CIPQSEND=0, it is in normal sending mode. In this mode, after user
|
// When command AT+CIPQSEND=0, it is in normal sending mode. In this mode, after user
|
||||||
// sends data by AT+CIPSEND, if the server receives TCP data, it will give ACK message
|
// sends data by AT+CIPSEND, if the server receives TCP data, it will give ACK message
|
||||||
// to module, and the module will respond SEND OK.
|
// to module, and the module will respond SEND OK.
|
||||||
let _ = mdm.send("AT+CIPQSEND=0", "OK");
|
let _ = self.send("AT+CIPQSEND=0", "OK");
|
||||||
// Enables getting data from network manually.
|
// Enables getting data from network manually.
|
||||||
let _ = mdm.send("AT+CIPRXGET=1", "OK");
|
let _ = self.send("AT+CIPRXGET=1", "OK");
|
||||||
|
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
if let Ok(_) = mdm.tcp_connect("51.158.66.64", 7887) {
|
if let Ok(_) = self.tcp_connect("51.158.66.64", 7887) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let device_id = "c36a72df-5bd6-4f9b-995d-059433bc3267";
|
let device_id = "c36a72df-5bd6-4f9b-995d-059433bc3267";
|
||||||
println!("connecting to MQTT with ({}:{})", mqtt_username, mqtt_password);
|
println!("connecting to MQTT with ({}:{})", mqtt_username, mqtt_password);
|
||||||
let _ = mdm.mqtt_connect(device_id, mqtt_username, mqtt_password)?;
|
let _ = self.mqtt_connect(device_id, mqtt_username, mqtt_password)?;
|
||||||
|
|
||||||
println!("entering queue receive loop ...");
|
println!("entering queue receive loop ...");
|
||||||
let mut err_count = 0;
|
let mut err_count = 0;
|
||||||
let _ = loop {
|
let _ = loop {
|
||||||
match receiver.recv() {
|
match self.receiver.recv() {
|
||||||
Ok(Msg::Gps(solution)) => {
|
Ok(Msg::Gps(solution)) => {
|
||||||
println!("received GPS solution {:?} | sending to mqtt ...", solution);
|
println!("received GPS solution {:?} | sending to mqtt ...", solution);
|
||||||
serde_json_core::ser::to_string::<Solution, 512>(&solution)
|
serde_json_core::ser::to_string::<Solution, 512>(&solution)
|
||||||
.map_err(|e| anyhow::Error::new(e))
|
.map_err(|e| anyhow::Error::new(e))
|
||||||
.and_then(|sol| mdm.mqtt_publish(device_id, &sol))?;
|
.and_then(|sol| self.mqtt_publish(device_id, &sol))?;
|
||||||
err_count = 0;
|
err_count = 0;
|
||||||
},
|
},
|
||||||
Ok(Msg::Accelerometer(acc)) => {
|
Ok(Msg::Accelerometer(acc)) => {
|
||||||
println!("received accel {} | sending to mqtt ...", acc);
|
println!("received accel {} | sending to mqtt ...", acc);
|
||||||
let _ = mdm.mqtt_publish(device_id, &format!("{:?}", acc))?;
|
let _ = self.mqtt_publish(device_id, &format!("{:?}", acc))?;
|
||||||
err_count = 0;
|
err_count = 0;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -612,11 +568,10 @@ where
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
mdm.init(pwrkey, rst, power)?;
|
|
||||||
let _ = mdm.echo(false)?;
|
impl<UART: serial::Uart, PWK: OutputPin, RST: OutputPin, PW: OutputPin> std::io::Read for Modem<UART, PWK, RST, PW> {
|
||||||
let _ = start_sending(&mut mdm, mqtt_username, mqtt_password, receiver)?;
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
let _ = mdm.tcp_close_connection()?;
|
self.tcp_receive(buf).map_err(|_| std::io::Error::from(std::io::ErrorKind::ConnectionAborted))
|
||||||
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue