wifi accesspoint, urlparse config body, wifi setup, testing

This commit is contained in:
Evan Feenstra
2022-05-22 14:07:06 -07:00
parent 9d118c8398
commit bb69909f8d
9 changed files with 243 additions and 30 deletions

View File

@@ -1,9 +1,11 @@
# cd sphinx-key # sphinx-key
These notes were tested for macOS These notes were tested for macOS
### deps ### deps
`cd sphinx-key`
##### cargo nightly: ##### cargo nightly:
`rustup install nightly` `rustup install nightly`
@@ -30,12 +32,12 @@ These notes were tested for macOS
### flash ### flash
`espflash /dev/tty.SLAB_USBtoUART target/riscv32imc-esp-espidf/debug/sphinx-key`
If the above command does not work, try this one below:
`espflash target/riscv32imc-esp-espidf/debug/sphinx-key` `espflash target/riscv32imc-esp-espidf/debug/sphinx-key`
### monitor ### monitor
`espmonitor /dev/ttyUSB0` ```sh
ls /dev/tty.*
ls /dev/cu.*
espmonitor /dev/tty.usbserial-1420
```

View File

@@ -1,3 +1,3 @@
pub fn say_hi() { pub fn say_hi() {
println!("hi!"); println!("hi from signer module!");
} }

View File

@@ -24,6 +24,8 @@ esp-idf-hal = "0.37"
anyhow = {version = "1", features = ["backtrace"]} anyhow = {version = "1", features = ["backtrace"]}
log = "0.4" log = "0.4"
url = "2" url = "2"
serde_urlencoded = "0.7.1"
serde = "1.0.137"
[build-dependencies] [build-dependencies]
embuild = "0.29" embuild = "0.29"

3
sphinx-key/go.sh Executable file
View File

@@ -0,0 +1,3 @@
cargo build
espflash target/riscv32imc-esp-espidf/debug/sphinx-key
espmonitor /dev/tty.usbserial-1420

View File

@@ -0,0 +1,47 @@
mod html;
pub mod wifi;
use url;
use embedded_svc::httpd::*;
use esp_idf_svc::httpd as idf;
use std::sync::{Condvar, Mutex, Arc};
use embedded_svc::httpd::registry::Registry;
use esp_idf_sys::{self};
use esp_idf_svc::nvs::*;
use esp_idf_svc::nvs_storage::EspNvsStorage;
use embedded_svc::storage::Storage;
use serde::Deserialize;
#[derive(Clone, Debug, Deserialize)]
pub struct Config {
pub broker: String,
// pub ssid: String,
// pub pass: String,
}
/*
curl -X POST 192.168.71.1/config?broker=52.91.253.115%3A1883&ssid=apples%26acorns&pass=42flutes
curl -X POST 192.168.71.1/config?broker=52.91.253.115%3A1883
*/
#[allow(unused_variables)]
pub fn config_server(mutex: Arc<(Mutex<Option<Config>>, Condvar)>, store: Arc<Mutex<EspNvsStorage>>) -> Result<idf::Server> {
let server = idf::ServerRegistry::new()
.at("/")
.get(|_| Ok(html::HTML.into()))?
.at("/config")
.post(move |mut request| {
let bod = &request.query_string()
.ok_or(anyhow::anyhow!("failed to parse query string"))?;;
let conf = serde_urlencoded::from_str::<Config>(bod)?;
let mut wait = mutex.0.lock().unwrap();
*wait = Some(conf);
mutex.1.notify_one();
Ok("{\"success\":true}".to_owned().into())
})?;
server.start(&Default::default())
}

117
sphinx-key/src/conn/wifi.rs Normal file
View File

@@ -0,0 +1,117 @@
use esp_idf_svc::wifi::*;
use esp_idf_svc::sysloop::*;
use esp_idf_svc::netif::*;
use esp_idf_svc::nvs::EspDefaultNvs;
use esp_idf_svc::ping;
use embedded_svc::wifi::*;
use embedded_svc::httpd::Result;
use embedded_svc::ping::Ping;
use embedded_svc::ipv4;
use log::*;
use anyhow::bail;
use std::time::Duration;
use std::sync::Arc;
const SSID: &str = "apples&acorns";
const PASS: &str = "42flutes";
#[cfg(not(feature = "qemu"))]
#[allow(dead_code)]
pub fn connect(
netif_stack: Arc<EspNetifStack>,
sys_loop_stack: Arc<EspSysLoopStack>,
default_nvs: Arc<EspDefaultNvs>,
) -> Result<Box<EspWifi>> {
let mut wifi = Box::new(EspWifi::new(netif_stack, sys_loop_stack, default_nvs)?);
info!("Wifi created, about to scan");
let ap_infos = wifi.scan()?;
let ours = ap_infos.into_iter().find(|a| a.ssid == SSID);
let channel = if let Some(ours) = ours {
info!(
"Found configured access point {} on channel {}",
SSID, ours.channel
);
Some(ours.channel)
} else {
info!(
"Configured access point {} not found during scanning, will go with unknown channel",
SSID
);
None
};
// let conf = Configuration::Client(
// ClientConfiguration {
// ssid: SSID.into(),
// password: PASS.into(),
// channel,
// ..Default::default()
// };
// );
// let conf = Configuration::AccessPoint(
// AccessPointConfiguration {
// ssid: "aptest111".into(),
// channel: channel.unwrap_or(1),
// ..Default::default()
// },
// );
let conf = Configuration::Mixed(
ClientConfiguration {
ssid: SSID.into(),
password: PASS.into(),
channel,
..Default::default()
},
AccessPointConfiguration {
ssid: "aptest123".into(),
channel: channel.unwrap_or(1),
..Default::default()
},
);
wifi.set_configuration(&conf)?;
info!("Wifi configuration set, about to get status");
wifi.wait_status_with_timeout(Duration::from_secs(20), |status| !status.is_transitional())
.map_err(|e| anyhow::anyhow!("Unexpected Wifi status: {:?}", e))?;
let status = wifi.get_status();
if let Status(
ClientStatus::Started(ClientConnectionStatus::Connected(ClientIpStatus::Done(ip_settings))),
ApStatus::Started(ApIpStatus::Done),
) = status
{
info!("Wifi connected");
ping(&ip_settings)?;
} else {
bail!("Unexpected Wifi status: {:?}", status);
}
Ok(wifi)
}
fn ping(ip_settings: &ipv4::ClientSettings) -> Result<()> {
info!("About to do some pings for {:?}", ip_settings);
let ping_summary =
ping::EspPing::default().ping(ip_settings.subnet.gateway, &Default::default())?;
if ping_summary.transmitted != ping_summary.received {
bail!(
"Pinging gateway {} resulted in timeouts",
ip_settings.subnet.gateway
);
}
info!("Pinging done");
Ok(())
}

View File

@@ -1,11 +1,25 @@
#![allow(unused_imports)] #![allow(unused_imports)]
mod srv; mod conn;
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use sphinx_key_signer; use sphinx_key_signer;
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use std::thread;
use log::*;
use std::sync::{Condvar, Mutex, Arc}; use std::sync::{Condvar, Mutex, Arc};
use std::time::*;
use esp_idf_svc::nvs::*;
use esp_idf_svc::nvs_storage::EspNvsStorage;
use esp_idf_svc::netif::*;
use esp_idf_svc::eventloop::*;
use esp_idf_svc::sysloop::*;
use esp_idf_svc::wifi::*;
use embedded_svc::httpd::*; use embedded_svc::httpd::*;
use embedded_svc::wifi::*;
// use log::*; // use log::*;
// use url; // use url;
@@ -14,13 +28,60 @@ fn main() -> Result<()> {
// or else some patches to the runtime implemented by esp-idf-sys might not link properly. // or else some patches to the runtime implemented by esp-idf-sys might not link properly.
esp_idf_sys::link_patches(); esp_idf_sys::link_patches();
println!("Hello, world!"); esp_idf_svc::log::EspLogger::initialize_default();
sphinx_key_signer::say_hi(); sphinx_key_signer::say_hi();
// let init_conf = Some(conn::Config{
// broker: "52.91.253.115:1883".to_string(),
// });
let mutex = Arc::new((Mutex::new(None), Condvar::new())); let mutex = Arc::new((Mutex::new(None), Condvar::new()));
let _httpd = srv::httpd(mutex.clone()); let netif_stack = Arc::new(EspNetifStack::new()?);
let sys_loop_stack = Arc::new(EspSysLoopStack::new()?);
let default_nvs = Arc::new(EspDefaultNvs::new()?);
let storage = Arc::new(Mutex::new(EspNvsStorage::new_default(default_nvs.clone(), "sphinx", true).expect("NVS FAIL")));
#[allow(clippy::redundant_clone)]
#[allow(unused_mut)]
let mut wifi = conn::wifi::connect(
netif_stack.clone(),
sys_loop_stack.clone(),
default_nvs.clone(),
)?;
// conn::tcp::tcp_bind().expect("failed TCP bind");
let httpd = conn::config_server(mutex.clone(), storage);
info!("=====> yo yo");
let mut wait = mutex.0.lock().unwrap();
let config = loop {
if let Some(conf) = &*wait {
break conf;
} else {
wait = mutex
.1
.wait_timeout(wait, Duration::from_secs(1))
.unwrap()
.0;
println!("tick...");
}
};
println!("===> config! {:?}", config);
let mut i = 0;
loop {
thread::sleep(Duration::from_secs(5));
i = i + 1;
println!("wait forever... {}", i);
}
// drop(httpd);
// println!("Httpd stopped");
/* shutdown */ /* shutdown */
// drop(httpd); // drop(httpd);

View File

@@ -1,19 +0,0 @@
mod html;
use embedded_svc::httpd::*;
use esp_idf_svc::httpd as idf;
use std::sync::{Condvar, Mutex, Arc};
use embedded_svc::httpd::registry::Registry;
use esp_idf_sys::{self};
#[allow(unused_variables)]
pub fn httpd(mutex: Arc<(Mutex<Option<u32>>, Condvar)>) -> Result<idf::Server> {
let server = idf::ServerRegistry::new()
.at("/")
.get(|_| {
Ok(html::HTML.into())
})?;
server.start(&Default::default())
}