Skip to content

Instantly share code, notes, and snippets.

@bernii
Created March 8, 2022 18:01
Show Gist options
  • Save bernii/dab01df90b0f3dc45fbd69749e8934b8 to your computer and use it in GitHub Desktop.
Save bernii/dab01df90b0f3dc45fbd69749e8934b8 to your computer and use it in GitHub Desktop.
esp now tests with esp-rs
use std::convert::TryInto;
use std::process;
use esp_idf_sys::{self as _, c_types}; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use std::net::Ipv4Addr;
use std::{sync::Arc, thread, time::*};
use anyhow::bail;
use log::*;
use embedded_svc::ipv4;
use embedded_svc::wifi::*;
use esp_idf_svc::netif::*;
use esp_idf_svc::wifi::*;
use esp_idf_svc::sysloop::*;
use esp_idf_svc::nvs::*;
use anyhow::Result;
use esp_idf_sys::{self, esp, EspError};
use std::ptr;
use std::ffi::CStr;
use embedded_svc::event_bus::{EventBus, Postbox};
const SSID: &str = env!("WIFI_SSID");
const PASS: &str = env!("WIFI_PASS");
const BROADCAST: [u8; 6] = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
fn main() -> Result<()> {
// Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
esp_idf_sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
// let sys_loop_stack = Arc::new(EspSysLoopStack::new()?);
// let (mut eventloop, _subscription) = init_eventloop().unwrap();
// init stack
let netif_stack = Arc::new(EspNetifStack::new().unwrap());
let sys_loop_stack = Arc::new(EspSysLoopStack::new().unwrap());
let default_nvs = Arc::new(EspDefaultNvs::new().unwrap());
info!("starting wifi.....");
// keep var so wifi is no getting deallocated
let wifi = setup_wifi(
netif_stack.clone(),
sys_loop_stack.clone(),
default_nvs.clone(),
)?;
info!("Initializing ESP NOW");
let resp = esp!(unsafe { esp_idf_sys::esp_now_init() });
info!("Initializing ESP NOW: resp {:?}", resp);
let mut peer_info = esp_idf_sys::esp_now_peer_info_t::default();
peer_info.peer_addr = BROADCAST;
peer_info.channel = 2;
peer_info.encrypt = false;
let resp1 = unsafe { esp_idf_sys::esp_now_add_peer(&peer_info) };
info!("Initializing ESP NOW, add peer resp: {:?}", resp1);
info!("Register callback");
extern "C" fn mycallback(mac_addr: *const u8, data: *const u8, data_len: c_types::c_int) -> () {
info!("raw data {:?}, DATA {:?} L: {}", mac_addr, data, data_len);
let c_mac = unsafe{ std::slice::from_raw_parts(mac_addr, 6usize) };
let c_str = unsafe {
std::str::from_utf8_unchecked(std::slice::from_raw_parts(
data, data_len as usize
))
};
info!("data mac: {:x?} data: {:?}", c_mac, c_str);
}
let resp_cb = unsafe { esp_idf_sys::esp_now_register_recv_cb(Some(mycallback)) };
info!("cb resp: {:?}", resp_cb);
let mut i = 0;
loop {
info!("Loop i={}", i); // sleep
esp_now_send(i);
thread::sleep(Duration::from_millis(100));
// std::thread::yield_now();
i += 1;
if i > 100 { i = 0; }
}
}
fn esp_now_send(i: i32) {
let br = BROADCAST.clone();
let mut data = format!("i={}", i);
let resp = esp!(unsafe { esp_idf_sys::esp_now_send(
br.as_ptr() as _,
data.as_ptr() as _,
data.len() as _,
)});
info!("esp_now_send {:?}", resp);
}
use embedded_svc::ipv4::ClientSettings;
use embedded_svc::ipv4::Subnet;
use crate::ipv4::Mask;
fn setup_wifi(
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 access point {} on channel {}", SSID, ours.channel);
Some(ours.channel)
} else {
info!("Configured AP {} not found, will go with unknown channel", SSID);
None
};
wifi.set_configuration(&Configuration::Client(
ClientConfiguration {
ssid: SSID.into(),
password: PASS.into(),
channel,
..Default::default()
},
))?;
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::Stopped,
) = status {
info!("Wifi connected");
} else {
bail!("Unexpected Wifi status: {:?}", status);
}
Ok(wifi)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment