work in progress on switching to direct mode
This commit is contained in:
@ -34,6 +34,9 @@ impl BleServer {
|
|||||||
Commands::NotifyMotorDown { data: 0 },
|
Commands::NotifyMotorDown { data: 0 },
|
||||||
Commands::NotifyMotorStop { data: 0 },
|
Commands::NotifyMotorStop { data: 0 },
|
||||||
Commands::NotifyMotorUp { data: 0 },
|
Commands::NotifyMotorUp { data: 0 },
|
||||||
|
Commands::PairTimerExpired,
|
||||||
|
Commands::AllowPairing,
|
||||||
|
Commands::EraseBleBonds,
|
||||||
];
|
];
|
||||||
let r = dp.get_callback_channel(&cmds);
|
let r = dp.get_callback_channel(&cmds);
|
||||||
let s = dp.get_cmd_channel();
|
let s = dp.get_cmd_channel();
|
||||||
@ -55,7 +58,7 @@ impl BleServer {
|
|||||||
let ble_device = BLEDevice::take();
|
let ble_device = BLEDevice::take();
|
||||||
set_device_security(ble_device);
|
set_device_security(ble_device);
|
||||||
let server = ble_device.get_server();
|
let server = ble_device.get_server();
|
||||||
set_server_callbacks(server);
|
set_server_callbacks(server, self.send_q.clone());
|
||||||
let _pairing_service = server.create_service(UUID_SERVICE_PAIR);
|
let _pairing_service = server.create_service(UUID_SERVICE_PAIR);
|
||||||
let lift_service = server.create_service(UUID_SERVICE_LIFT);
|
let lift_service = server.create_service(UUID_SERVICE_LIFT);
|
||||||
|
|
||||||
@ -94,7 +97,7 @@ impl BleServer {
|
|||||||
let ble_advertiser = ble_device.get_advertising();
|
let ble_advertiser = ble_device.get_advertising();
|
||||||
|
|
||||||
// TODO: we will need to enable / disable the ability to pair!
|
// TODO: we will need to enable / disable the ability to pair!
|
||||||
advertise_pairing(ble_advertiser)?;
|
advertise(ble_advertiser)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
debug!("Waiting for updates that should be notified via bluetooth");
|
debug!("Waiting for updates that should be notified via bluetooth");
|
||||||
@ -111,6 +114,16 @@ impl BleServer {
|
|||||||
Commands::NotifyMotorStop{data} => {
|
Commands::NotifyMotorStop{data} => {
|
||||||
button_up.lock().set_value(&[data]).notify();
|
button_up.lock().set_value(&[data]).notify();
|
||||||
}
|
}
|
||||||
|
Commands::PairTimerExpired => {
|
||||||
|
advertise_to_direct(ble_advertiser).expect("Failed to exit pairing mode");
|
||||||
|
self.send_q.send(Commands::PairTimerClear).await?;
|
||||||
|
}
|
||||||
|
Commands::AllowPairing => {
|
||||||
|
advertise_to_undirected(ble_advertiser).expect("Failed to enter pairing mode");
|
||||||
|
}
|
||||||
|
Commands::EraseBleBonds => {
|
||||||
|
ble_device.delete_all_bonds().expect("Failed trying to erase bluetooth bonding information");
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
error!("Invalid command received by bluetooth handler {:?}", cmd);
|
error!("Invalid command received by bluetooth handler {:?}", cmd);
|
||||||
// No need to reboot as state is recoverable.
|
// No need to reboot as state is recoverable.
|
||||||
@ -150,7 +163,7 @@ fn on_bluetooth_cmd(sender: &SendQ, args: &mut OnWriteArgs, cmd: Commands) {
|
|||||||
|
|
||||||
fn set_device_security(dev: &mut BLEDevice) {
|
fn set_device_security(dev: &mut BLEDevice) {
|
||||||
dev.security()
|
dev.security()
|
||||||
// Enable all security protections
|
// Enable all security protections (including bond, so that bond info is saved)
|
||||||
.set_auth(AuthReq::all())
|
.set_auth(AuthReq::all())
|
||||||
// Options we support for putting in pairing info.
|
// Options we support for putting in pairing info.
|
||||||
// "NoInputOutput" means that we will have "just works" pairing
|
// "NoInputOutput" means that we will have "just works" pairing
|
||||||
@ -159,8 +172,8 @@ fn set_device_security(dev: &mut BLEDevice) {
|
|||||||
.resolve_rpa();
|
.resolve_rpa();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_server_callbacks(server: &mut BLEServer) {
|
fn set_server_callbacks(server: &mut BLEServer, sender: SendQ) {
|
||||||
server.on_connect(|server, clntdesc| {
|
server.on_connect(move |server, clntdesc| {
|
||||||
// Print connected client data
|
// Print connected client data
|
||||||
info!("client connected: {:?}", clntdesc);
|
info!("client connected: {:?}", clntdesc);
|
||||||
// Update connection parameters
|
// Update connection parameters
|
||||||
@ -172,24 +185,40 @@ fn set_server_callbacks(server: &mut BLEServer) {
|
|||||||
BLE_LATENCY,
|
BLE_LATENCY,
|
||||||
BLE_TIMEOUT,
|
BLE_TIMEOUT,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
sender.send_blocking(Commands::PairTimerClear).unwrap();
|
||||||
|
// TODO: Cancel pairing mode timeout
|
||||||
});
|
});
|
||||||
server.on_disconnect(|_desc, _reason| {
|
server.on_disconnect(|_desc, _reason| {
|
||||||
info!("Disconnected, back to advertising");
|
info!("Disconnected, back to advertising");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advertise_pairing(advertiser: &Mutex<BLEAdvertising>) -> Result<()> {
|
fn advertise(advertiser: &Mutex<BLEAdvertising>) -> Result<()> {
|
||||||
trace!("Setting up advertiser");
|
trace!("Setting up advertiser");
|
||||||
advertiser
|
advertiser
|
||||||
.lock()
|
.lock()
|
||||||
|
.advertisement_type(ConnMode::Und)
|
||||||
.set_data(
|
.set_data(
|
||||||
BLEAdvertisementData::new()
|
BLEAdvertisementData::new()
|
||||||
.name(DEVICE_NAME)
|
.name(DEVICE_NAME)
|
||||||
.add_service_uuid(UUID_SERVICE_PAIR)
|
.add_service_uuid(UUID_SERVICE_PAIR)
|
||||||
)?;
|
)?;
|
||||||
// TODO: this appears to run in its own thread; verify.
|
|
||||||
// TODO: isn't there a restart? We'll need to switch between pairing and not.
|
|
||||||
info!("Staring Bluetooth Server");
|
info!("Staring Bluetooth Server");
|
||||||
advertiser.lock().start()?;
|
advertiser.lock().start()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn advertise_to_direct(advertiser: &Mutex<BLEAdvertising>) -> Result<()> {
|
||||||
|
advertiser.lock().stop()?;
|
||||||
|
advertiser.lock().advertisement_type(ConnMode::Dir).start()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn advertise_to_undirected(advertiser: &Mutex<BLEAdvertising>) -> Result<()> {
|
||||||
|
advertiser.lock().stop()?;
|
||||||
|
advertiser.lock().advertisement_type(ConnMode::Und).start()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO set maximum pairs to remember?
|
||||||
|
//TODO after disconnect, it returns to scanning - will it return to directed scanning? Find out when directed is working.
|
||||||
@ -23,10 +23,15 @@ pub enum Commands {
|
|||||||
ButtonTimerExpired,
|
ButtonTimerExpired,
|
||||||
ButtonTimerRestart,
|
ButtonTimerRestart,
|
||||||
ButtonTimerClear,
|
ButtonTimerClear,
|
||||||
|
PairTimerExpired,
|
||||||
|
AllowPairing, // Also serves as the timer restart command
|
||||||
|
PairTimerClear,
|
||||||
|
|
||||||
NotifyMotorUp {data: u8},
|
NotifyMotorUp {data: u8},
|
||||||
NotifyMotorDown {data: u8},
|
NotifyMotorDown {data: u8},
|
||||||
NotifyMotorStop {data: u8},
|
NotifyMotorStop {data: u8},
|
||||||
|
|
||||||
|
EraseBleBonds,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
const BUTTON_HOLD_TIME_MS: u64 = 500;
|
const BUTTON_HOLD_TIME_MS: u64 = 500;
|
||||||
const STOP_SAFETY_TIME_MS: u64 = 2000;
|
const STOP_SAFETY_TIME_MS: u64 = 2000;
|
||||||
|
const PAIR_TIME_MS: u64 = 10000; //180000; TODO:Debug go back to 3 minutes from 10s
|
||||||
|
|
||||||
// Crates used in release
|
// Crates used in release
|
||||||
use log::*; //{trace, debug, info, warn, error}
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
@ -19,12 +20,15 @@ mod motor_controller;
|
|||||||
mod motor_driver;
|
mod motor_driver;
|
||||||
mod message_timer;
|
mod message_timer;
|
||||||
mod ble_server;
|
mod ble_server;
|
||||||
|
mod pair_button_driver;
|
||||||
|
|
||||||
use crate::message_timer::MessageTimer;
|
use crate::message_timer::MessageTimer;
|
||||||
use crate::commands::Commands;
|
use crate::commands::Commands;
|
||||||
|
|
||||||
//TODO: limit switch driver, would be good in long run if it checked limit switches periodically (every 1s?) to ensure they are still functioning
|
//TODO: limit switch driver, would be good in long run if it checked limit switches periodically (every 1s?) to ensure they are still functioning
|
||||||
|
|
||||||
|
//TODO: pair button driver, listens to PIC uart or eventually physical button, sends pairing active command and resets pairing timer.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Do basic initialization
|
// Do basic initialization
|
||||||
esp_idf_svc::sys::link_patches();
|
esp_idf_svc::sys::link_patches();
|
||||||
@ -84,6 +88,12 @@ async fn main_loop() -> Result<()> {
|
|||||||
Commands::StopTimerExpired,
|
Commands::StopTimerExpired,
|
||||||
STOP_SAFETY_TIME_MS,
|
STOP_SAFETY_TIME_MS,
|
||||||
&mut dp);
|
&mut dp);
|
||||||
|
let mut pairing_timer = MessageTimer::<Commands, Commands>::new_on_dispatch(
|
||||||
|
Commands::AllowPairing,
|
||||||
|
Commands::PairTimerClear,
|
||||||
|
Commands::PairTimerExpired,
|
||||||
|
PAIR_TIME_MS,
|
||||||
|
&mut dp);
|
||||||
let ble_server = ble_server::BleServer::new(&mut dp);
|
let ble_server = ble_server::BleServer::new(&mut dp);
|
||||||
|
|
||||||
let executor = Executor::new();
|
let executor = Executor::new();
|
||||||
@ -97,6 +107,7 @@ async fn main_loop() -> Result<()> {
|
|||||||
tasks.push(executor.spawn(motor_control.run()));
|
tasks.push(executor.spawn(motor_control.run()));
|
||||||
tasks.push(executor.spawn(button_timer.run()));
|
tasks.push(executor.spawn(button_timer.run()));
|
||||||
tasks.push(executor.spawn(stopping_timer.run()));
|
tasks.push(executor.spawn(stopping_timer.run()));
|
||||||
|
tasks.push(executor.spawn(pairing_timer.run()));
|
||||||
tasks.push(executor.spawn(ble_server.run()));
|
tasks.push(executor.spawn(ble_server.run()));
|
||||||
tasks.push(executor.spawn(motor_driver.run()));
|
tasks.push(executor.spawn(motor_driver.run()));
|
||||||
tasks.push(executor.spawn(dp.cmd_loop()));
|
tasks.push(executor.spawn(dp.cmd_loop()));
|
||||||
|
|||||||
32
gem-remotes-esp32/src/pair_button_driver.rs
Normal file
32
gem-remotes-esp32/src/pair_button_driver.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use log::*; //{trace, debug, info, warn, error}
|
||||||
|
use anyhow::Result;
|
||||||
|
use async_channel::Sender;
|
||||||
|
use esp_idf_svc::timer::EspTaskTimerService;
|
||||||
|
use core::time::Duration;
|
||||||
|
|
||||||
|
use crate::commands::Commands;
|
||||||
|
use crate::dispatch::Dispatch;
|
||||||
|
|
||||||
|
type SendQ = Sender<Commands>;
|
||||||
|
|
||||||
|
pub struct PairButtonDriver {
|
||||||
|
_send: SendQ
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PairButtonDriver {
|
||||||
|
pub fn new(dp: &mut Dispatch) -> Self {
|
||||||
|
let s = dp.get_cmd_channel();
|
||||||
|
Self { _send: s }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(&self) -> Result<()> {
|
||||||
|
let timer_service = EspTaskTimerService::new()?;
|
||||||
|
let mut async_timer = timer_service.timer_async()?;
|
||||||
|
debug!("Waiting on pairing button presses");
|
||||||
|
loop {
|
||||||
|
//TO DO: Watch for incoming pair button presses from the PIC and/or hardware buttons
|
||||||
|
async_timer.after(Duration::from_millis(10000)).await?; // no need to panic on test console driver timer failure
|
||||||
|
//When we find a press, send PicRecvPair
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,6 +39,9 @@ pub enum Menu<'a> {
|
|||||||
/// Simulate the PIC controller sending us a Stop character
|
/// Simulate the PIC controller sending us a Stop character
|
||||||
PicRecvStop,
|
PicRecvStop,
|
||||||
|
|
||||||
|
/// Simulate the PIC controller sending a "pair" button press
|
||||||
|
PicRecvPair,
|
||||||
|
|
||||||
/// Send a bluetooth characteristic: Up
|
/// Send a bluetooth characteristic: Up
|
||||||
BluetoothUp {
|
BluetoothUp {
|
||||||
/// 0 for not pressed, 1 for pressed
|
/// 0 for not pressed, 1 for pressed
|
||||||
@ -74,10 +77,14 @@ pub enum Menu<'a> {
|
|||||||
/// Send a bluetooth characteristic: Wifi Password
|
/// Send a bluetooth characteristic: Wifi Password
|
||||||
BluetoothWifiPassword { wifipass: &'a str },
|
BluetoothWifiPassword { wifipass: &'a str },
|
||||||
|
|
||||||
|
/// Change log level (None: 0, .. Tracing: 5)
|
||||||
Log { level: u8 },
|
Log { level: u8 },
|
||||||
|
|
||||||
/// Abort (resets microcontroller)
|
/// Abort (resets microcontroller)
|
||||||
Abort,
|
Abort,
|
||||||
|
|
||||||
|
/// Erase BLE Bonding information
|
||||||
|
ClearBleBonds,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +108,10 @@ pub fn process_menu(
|
|||||||
cli.writer().write_str("Sending PicButtonStop command")?;
|
cli.writer().write_str("Sending PicButtonStop command")?;
|
||||||
let _ = dispatch.send_blocking(Commands::PicRecvStop);
|
let _ = dispatch.send_blocking(Commands::PicRecvStop);
|
||||||
}
|
}
|
||||||
|
Menu::PicRecvPair => {
|
||||||
|
cli.writer().write_str("Sending PIC command and timer reset (the job of the pair button driver, once PIC interface exists)")?; //TODO: PIC get this.
|
||||||
|
let _ = dispatch.send_blocking(Commands::AllowPairing);
|
||||||
|
}
|
||||||
Menu::BluetoothUp { data } => {
|
Menu::BluetoothUp { data } => {
|
||||||
cli.writer()
|
cli.writer()
|
||||||
.write_str("Sending BluetoothUp")?;
|
.write_str("Sending BluetoothUp")?;
|
||||||
@ -180,6 +191,9 @@ pub fn process_menu(
|
|||||||
trace!("trace test");
|
trace!("trace test");
|
||||||
}
|
}
|
||||||
Menu::Abort => {panic!("CLI user requested abort");}
|
Menu::Abort => {panic!("CLI user requested abort");}
|
||||||
|
Menu::ClearBleBonds => {
|
||||||
|
let _ = dispatch.send_blocking(Commands::EraseBleBonds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user