wifi: rewrite wifi task
This commit is contained in:
@@ -15,7 +15,8 @@ real-output = []
|
||||
simulation = ["dep:rmp"]
|
||||
radio = [
|
||||
"dep:bleps",
|
||||
"dep:esp-wifi"
|
||||
"dep:esp-wifi",
|
||||
"dep:reqwless"
|
||||
]
|
||||
motion = ["mpu", "gps"]
|
||||
max-usb-power = []
|
||||
@@ -102,6 +103,8 @@ esp-storage = { version = "0.7.0", features = ["esp32s3"] }
|
||||
embedded-storage = "0.3.1"
|
||||
rmp = { path = "../msgpack-rust/rmp/", optional = true, default-features = false }
|
||||
display-interface = "0.5.0"
|
||||
embassy-net = { version = "0.7.1", features = ["alloc", "dns", "medium-ethernet", "proto-ipv4", "tcp", "udp", "dhcpv4"] }
|
||||
reqwless = { version = "0.13.0", optional = true }
|
||||
|
||||
[profile.dev]
|
||||
# Rust debug is too slow.
|
||||
|
||||
@@ -41,7 +41,7 @@ esp_bootloader_esp_idf::esp_app_desc!();
|
||||
static STATIC_HI_EXEC: StaticCell<InterruptExecutor<0>> = StaticCell::new();
|
||||
|
||||
static BUS_GARAGE: StaticCell<BusGarage> = StaticCell::new();
|
||||
static mut CORE2_STACK: Stack<8192> = Stack::new();
|
||||
static mut CORE2_STACK: Stack<16384> = Stack::new();
|
||||
static CORE_HANDLE: StaticCell<AppCoreGuard> = StaticCell::new();
|
||||
|
||||
#[esp_hal_embassy::main]
|
||||
@@ -145,39 +145,52 @@ async fn main(spawner: Spawner) {
|
||||
info!("Launching motion engine");
|
||||
spawner.must_spawn(motion_task(garage.motion.dyn_receiver(), garage.notify.dyn_publisher().unwrap(), garage.predict.dyn_sender()));
|
||||
|
||||
#[cfg(feature="radio")]
|
||||
let wifi_init = {
|
||||
info!("Configuring wifi");
|
||||
|
||||
static WIFI_INIT: StaticCell<esp_wifi::EspWifiController<'static>> = StaticCell::new();
|
||||
let rng = esp_hal::rng::Rng::new(peripherals.RNG);
|
||||
WIFI_INIT.init_with(|| {esp_wifi::init(timer0.timer0, rng).expect("Failed to initialize radio controller")})
|
||||
};
|
||||
|
||||
info!("Starting core 2");
|
||||
let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);
|
||||
CORE_HANDLE.init(cpu_control.start_app_core(unsafe { &mut *addr_of_mut!(CORE2_STACK) }, || {
|
||||
static STATIC_EXEC: StaticCell<Executor> = StaticCell::new();
|
||||
let exec = STATIC_EXEC.init(Executor::new());
|
||||
exec.run(|spawner| {
|
||||
#[cfg(feature="radio")]
|
||||
{
|
||||
info!("Launching wifi");
|
||||
//spawner.must_spawn(renderbug_embassy::tasks::wifi::wireless_task(garage.notify.dyn_receiver().unwrap(), timer0.timer0.into(), peripherals.RNG, peripherals.WIFI, peripherals.BT));
|
||||
}
|
||||
info!("Launching Safety UI");
|
||||
spawner.must_spawn(safety_ui_main(garage.notify.dyn_subscriber().unwrap(), safety_ui));
|
||||
info!("Launching UI");
|
||||
spawner.must_spawn(ui_main(garage.notify.dyn_subscriber().unwrap(), garage.telemetry.dyn_publisher().unwrap(), ui));
|
||||
info!("Launching OLED UI");
|
||||
spawner.must_spawn(oled_ui(garage.telemetry.dyn_subscriber().unwrap(), oledui));
|
||||
#[cfg(feature="demo")]
|
||||
{
|
||||
warn!("Launching with demo sequencer");
|
||||
spawner.must_spawn(renderbug_embassy::tasks::demo::demo_task(garage.notify.dyn_publisher().unwrap()));
|
||||
}
|
||||
#[cfg(not(feature="demo"))]
|
||||
{
|
||||
info!("Launching prediction engine");
|
||||
spawner.must_spawn(renderbug_embassy::tasks::predict::prediction_task(garage.predict.dyn_receiver(), garage.notify.dyn_publisher().unwrap(), garage.telemetry.dyn_publisher().unwrap()));
|
||||
}
|
||||
info!("Launching core 2 watchdog");
|
||||
spawner.must_spawn(wdt_task(ui_wdt));
|
||||
CORE_HANDLE.init_with(|| {
|
||||
cpu_control.start_app_core(unsafe { &mut *addr_of_mut!(CORE2_STACK) }, || {
|
||||
let exec = CORE2_EXEC.init_with(|| { Executor::new() });
|
||||
exec.run(|spawner| {
|
||||
info!("Launching Safety UI");
|
||||
spawner.must_spawn(safety_ui_main(garage.notify.dyn_subscriber().unwrap(), safety_ui));
|
||||
info!("Launching UI");
|
||||
spawner.must_spawn(ui_main(garage.notify.dyn_subscriber().unwrap(), garage.telemetry.dyn_publisher().unwrap(), ui));
|
||||
info!("Launching OLED UI");
|
||||
spawner.must_spawn(oled_ui(garage.telemetry.dyn_subscriber().unwrap(), oledui));
|
||||
|
||||
info!("System is ready in {}ms", Instant::now().as_millis());
|
||||
});
|
||||
}).unwrap());
|
||||
#[cfg(feature="radio")]
|
||||
{
|
||||
info!("Launching networking stack");
|
||||
spawner.must_spawn(renderbug_embassy::tasks::wifi::wireless_task(garage.telemetry.dyn_subscriber().unwrap(), wifi_init, peripherals.WIFI));
|
||||
}
|
||||
|
||||
#[cfg(feature="demo")]
|
||||
{
|
||||
warn!("Launching with demo sequencer");
|
||||
spawner.must_spawn(renderbug_embassy::tasks::demo::demo_task(garage.notify.dyn_publisher().unwrap()));
|
||||
}
|
||||
#[cfg(not(feature="demo"))]
|
||||
{
|
||||
info!("Launching prediction engine");
|
||||
spawner.must_spawn(renderbug_embassy::tasks::predict::prediction_task(garage.predict.dyn_receiver(), garage.notify.dyn_publisher().unwrap(), garage.telemetry.dyn_publisher().unwrap()));
|
||||
}
|
||||
|
||||
info!("Launching core 2 watchdog");
|
||||
spawner.must_spawn(wdt_task(ui_wdt));
|
||||
|
||||
info!("System is ready in {}ms", Instant::now().as_millis());
|
||||
});
|
||||
}).unwrap()
|
||||
});
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
|
||||
@@ -1,127 +1,114 @@
|
||||
use bleps::{ad_structure::{create_advertising_data, AdStructure, BR_EDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE}, attribute_server::AttributeServer, gatt, Ble, HciConnector};
|
||||
use embassy_sync::channel::DynamicReceiver;
|
||||
use alloc::string::ToString;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_sync::pubsub::DynSubscriber;
|
||||
use esp_hal::timer::AnyTimer;
|
||||
use esp_wifi::ble::controller::BleConnector;
|
||||
use esp_wifi::{EspWifiController, wifi::{ClientConfiguration, WifiDevice}};
|
||||
use log::*;
|
||||
use alloc::format;
|
||||
|
||||
use crate::events::Notification;
|
||||
use embassy_net::dns::DnsSocket;
|
||||
use embassy_net::tcp::client::{TcpClient, TcpClientState};
|
||||
use embassy_net::{Config, StackResources};
|
||||
use nalgebra::Vector2;
|
||||
use reqwless::client::{HttpClient, TlsConfig};
|
||||
use static_cell::StaticCell;
|
||||
|
||||
pub async fn ble_task(_notify: DynSubscriber<'static, Notification>, wifi_init: &esp_wifi::EspWifiController<'_>, bluetooth_device: esp_hal::peripherals::BT<'static>) {
|
||||
info!("Setting up BLE stack");
|
||||
let connector = BleConnector::new(wifi_init, bluetooth_device);
|
||||
let get_millis = || esp_hal::time::Instant::now().duration_since_epoch().as_millis();
|
||||
let hci = HciConnector::new(connector, get_millis);
|
||||
let mut ble = Ble::new(&hci);
|
||||
ble.init().unwrap();
|
||||
ble.cmd_set_le_advertising_parameters().unwrap();
|
||||
ble.cmd_set_le_advertising_data(
|
||||
create_advertising_data(&[
|
||||
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
|
||||
AdStructure::ServiceUuids16(&[Uuid::Uuid16(0x0001)]),
|
||||
AdStructure::CompleteLocalName("Renderbug!")
|
||||
])
|
||||
.unwrap()
|
||||
).unwrap();
|
||||
ble.cmd_set_le_advertise_enable(true).unwrap();
|
||||
use crate::{backoff::Backoff, events::{Prediction, Telemetry}};
|
||||
|
||||
let mut wf1 = |_offset: usize, data: &[u8]| {
|
||||
info!("Read serial data! {data:?}");
|
||||
};
|
||||
|
||||
// https://nextcloud.malloc.hackerbots.net/nextcloud/index.php/apps/phonetrack/logGet/cc668656ef51680c99b0eb6e5323a459/renderbug?lat=LAT&lon=LON&alt=ALT&acc=ACC&bat=BAT&sat=SAT&speed=SPD&bearing=DIR×tamp=TIME
|
||||
|
||||
// Other useful characteristics:
|
||||
// 0x2A67 - Location and speed
|
||||
// 0x2A00 - Device name
|
||||
// 0x2B90 - Device time
|
||||
// Permitted characteristics:
|
||||
// Acceleration
|
||||
// Force
|
||||
// Length
|
||||
// Linear position
|
||||
// Rotational speed
|
||||
// Temperature
|
||||
// Torque
|
||||
// Useful app that logs data: https://github.com/a2ruan/ArduNetApp?tab=readme-ov-file
|
||||
// Requires service 4fafc201-1fb5-459e-8fcc-c5c9c331914b, characteristic beb5483e-36e1-4688-b7f5-ea07361b26a8
|
||||
let s = &b""[..];
|
||||
gatt!([service {
|
||||
uuid: "6E400001-B5A3-F393-E0A9-E50E24DCCA9E", // Nordic UART
|
||||
characteristics: [
|
||||
characteristic {
|
||||
uuid: "6E400003-B5A3-F393-E0A9-E50E24DCCA9E", // TX from device, everything is sent as notifications
|
||||
notify: true,
|
||||
name: "tx",
|
||||
value: s
|
||||
},
|
||||
characteristic {
|
||||
uuid: "6E400002-B5A3-F393-E0A9-E50E24DCCA9E", // RX from phone
|
||||
write: wf1
|
||||
},
|
||||
]
|
||||
}]);
|
||||
let mut rng = bleps::no_rng::NoRng;
|
||||
let mut _srv = AttributeServer::new(&mut ble, &mut gatt_attributes, &mut rng);
|
||||
|
||||
info!("BLE running!");
|
||||
// TODO: Somehow need to recreate the attributeserver after disconnecting?
|
||||
/*loop {
|
||||
let notification = match notify.try_receive() {
|
||||
Err(_) => None,
|
||||
Ok(Notification::Beat) => Some("beat"),
|
||||
_ => None
|
||||
};
|
||||
|
||||
match notification {
|
||||
None => {
|
||||
srv.do_work().unwrap();
|
||||
Timer::after_millis(5).await;
|
||||
},
|
||||
Some(serial_data) => {
|
||||
for chunk in serial_data.as_bytes().chunks(20) {
|
||||
srv.do_work_with_notification(Some(NotificationData::new(tx_handle, chunk))).unwrap();
|
||||
}
|
||||
srv.do_work_with_notification(Some(NotificationData::new(tx_handle, &b"\n"[..]))).unwrap();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
#[embassy_executor::task]
|
||||
async fn net_task(mut runner: embassy_net::Runner<'static, WifiDevice<'static>>) {
|
||||
info!("Network stack is running");
|
||||
runner.run().await
|
||||
}
|
||||
|
||||
static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
|
||||
|
||||
// TODO: Wifi task needs to know when there is data to upload, so it only connects when needed.
|
||||
#[embassy_executor::task]
|
||||
pub async fn wireless_task(_notify: DynamicReceiver<'static, Notification>, timer: AnyTimer<'static>, rng: esp_hal::peripherals::RNG<'static>, _wifi_device: esp_hal::peripherals::WIFI<'static>, _bluetooth_device: esp_hal::peripherals::BT<'static>) {
|
||||
let rng = esp_hal::rng::Rng::new(rng);
|
||||
let _wifi_init =
|
||||
esp_wifi::init(timer, rng).expect("Failed to initialize WIFI/BLE controller");
|
||||
pub async fn wireless_task(mut telemetry: DynSubscriber<'static, Telemetry>, wifi_init: &'static mut EspWifiController<'static>, wifi_device: esp_hal::peripherals::WIFI<'static>) {
|
||||
let (mut wifi, interfaces) = esp_wifi::wifi::new(wifi_init, wifi_device)
|
||||
.expect("Failed to initialize WIFI!");
|
||||
wifi.set_configuration(&esp_wifi::wifi::Configuration::Client(
|
||||
ClientConfiguration {
|
||||
ssid: "The Frequency".to_string(),
|
||||
auth_method: esp_wifi::wifi::AuthMethod::WPA2Personal,
|
||||
password: "thepasswordkenneth".to_string(),
|
||||
..Default::default()
|
||||
}
|
||||
)).unwrap();
|
||||
wifi.set_mode(esp_wifi::wifi::WifiMode::Sta).unwrap();
|
||||
wifi.set_power_saving(esp_wifi::config::PowerSaveMode::Maximum).unwrap();
|
||||
wifi.start_async().await.unwrap();
|
||||
|
||||
//ble_task(notify, &wifi_init, bluetooth_device).await;
|
||||
let device = interfaces.sta;
|
||||
// TODO: Somehow grab a real random seed from main()
|
||||
let seed = 0;
|
||||
|
||||
let config = Config::dhcpv4(Default::default());
|
||||
let (stack, runner) = embassy_net::new(device, config, RESOURCES.init_with(|| { StackResources::new() }), seed as u64);
|
||||
info!("Launching network task");
|
||||
Spawner::for_current_executor().await.must_spawn(net_task(runner));
|
||||
|
||||
/*
|
||||
loop {
|
||||
let (mut wifi, _interfaces) = esp_wifi::wifi::new(&wifi_init, wifi_device)
|
||||
.expect("Failed to initialize WIFI controller"); }
|
||||
Backoff::from_secs(3).forever().attempt(async || {
|
||||
info!("Connecting to wifi...");
|
||||
match wifi.connect_async().await {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => {
|
||||
error!("Wifi error: {e:?}");
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}).await.unwrap();
|
||||
|
||||
info!("Waiting for DHCP");
|
||||
stack.wait_config_up().await;
|
||||
|
||||
info!("Online!");
|
||||
let ip_cfg = stack.config_v4().unwrap();
|
||||
info!("ip={ip_cfg:?}");
|
||||
|
||||
let mut rx_buf = [0; 4096];
|
||||
let mut tx_buf = [0; 4096];
|
||||
let dns = DnsSocket::new(stack);
|
||||
let tcp_state = TcpClientState::<1, 4096, 4096>::new();
|
||||
let tcp = TcpClient::new(stack, &tcp_state);
|
||||
let tls = TlsConfig::new(
|
||||
seed as u64,
|
||||
&mut rx_buf,
|
||||
&mut tx_buf,
|
||||
reqwless::client::TlsVerify::None,
|
||||
);
|
||||
|
||||
let mut client = HttpClient::new_with_tls(&tcp, &dns, tls);
|
||||
|
||||
loop {
|
||||
//let results = wifi.scan_n_async(16).await.unwrap();
|
||||
wifi.set_configuration(&esp_wifi::wifi::Configuration::Client(
|
||||
ClientConfiguration {
|
||||
ssid: "The Frequency".to_string(),
|
||||
auth_method: esp_wifi::wifi::AuthMethod::WPA2Personal,
|
||||
password: "thepasswordkenneth".to_string(),
|
||||
..Default::default()
|
||||
if let Telemetry::Prediction(Prediction::Location(coords)) = telemetry.next_message_pure().await {
|
||||
if let Err(e) = push_location(&mut client, coords).await {
|
||||
error!("HTTP error in publishing location: {e:?}");
|
||||
break
|
||||
}
|
||||
)).unwrap();
|
||||
|
||||
if wifi.connect_async().await.is_ok() {
|
||||
info!("Connected to wifi!");
|
||||
while wifi.is_connected().unwrap() {
|
||||
Timer::after_secs(60).await;
|
||||
}
|
||||
info!("Disconnected.");
|
||||
}
|
||||
Timer::after_secs(30).await;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
async fn push_location(client: &mut HttpClient<'_, TcpClient<'_, 1, 4096, 4096>, DnsSocket<'_>>, location: Vector2<f64>) -> Result<(), reqwless::Error> {
|
||||
let mut buffer = [0u8; 4096];
|
||||
let base = "https://nextcloud.malloc.hackerbots.net/nextcloud/index.php/apps/phonetrack/logGet/a062000067304e9dee6590f1b8f9e0db/renderbug";
|
||||
let url = format!("{base}?lat={}&lon={}", location.y, location.x);
|
||||
info!("Pushing to {url}");
|
||||
let mut http_req = client
|
||||
.request(
|
||||
reqwless::request::Method::GET,
|
||||
&url,
|
||||
)
|
||||
.await?;
|
||||
let response = http_req.send(&mut buffer).await?;
|
||||
|
||||
info!("Got response");
|
||||
let res = response.body().read_to_end().await?;
|
||||
|
||||
let content = core::str::from_utf8(res).unwrap();
|
||||
info!("{content}");
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user