let the bluetooth stack handle its own discovery state

custom
jacqueline 1 year ago
parent a75adfc124
commit aff28342d9
  1. 74
      src/drivers/bluetooth.cpp
  2. 14
      src/drivers/include/bluetooth.hpp
  3. 1
      src/drivers/include/bluetooth_types.hpp
  4. 1
      src/ui/include/ui_fsm.hpp
  5. 6
      src/ui/ui_fsm.cpp

@ -102,19 +102,6 @@ auto Bluetooth::ConnectedDevice() -> std::optional<bluetooth::Device> {
return {}; return {};
} }
auto Bluetooth::SetDeviceDiscovery(bool allowed) -> void {
if (allowed == bluetooth::BluetoothState::discovery()) {
return;
}
bluetooth::BluetoothState::discovery(allowed);
tinyfsm::FsmList<bluetooth::BluetoothState>::dispatch(
bluetooth::events::DiscoveryChanged{});
}
auto Bluetooth::IsDiscovering() -> bool {
return bluetooth::BluetoothState::discovery();
}
auto Bluetooth::KnownDevices() -> std::vector<bluetooth::Device> { auto Bluetooth::KnownDevices() -> std::vector<bluetooth::Device> {
std::vector<bluetooth::Device> out = bluetooth::BluetoothState::devices(); std::vector<bluetooth::Device> out = bluetooth::BluetoothState::devices();
std::sort(out.begin(), out.end(), [](const auto& a, const auto& b) -> bool { std::sort(out.begin(), out.end(), [](const auto& a, const auto& b) -> bool {
@ -308,7 +295,6 @@ std::mutex BluetoothState::sDevicesMutex_{};
std::map<mac_addr_t, Device> BluetoothState::sDevices_{}; std::map<mac_addr_t, Device> BluetoothState::sDevices_{};
std::optional<MacAndName> BluetoothState::sPreferredDevice_{}; std::optional<MacAndName> BluetoothState::sPreferredDevice_{};
std::optional<MacAndName> BluetoothState::sConnectingDevice_{}; std::optional<MacAndName> BluetoothState::sConnectingDevice_{};
bool BluetoothState::sIsDiscoveryAllowed_{false};
std::atomic<StreamBufferHandle_t> BluetoothState::sSource_; std::atomic<StreamBufferHandle_t> BluetoothState::sSource_;
std::function<void(Event)> BluetoothState::sEventHandler_; std::function<void(Event)> BluetoothState::sEventHandler_;
@ -338,16 +324,6 @@ auto BluetoothState::preferred_device(std::optional<MacAndName> addr) -> void {
sPreferredDevice_ = addr; sPreferredDevice_ = addr;
} }
auto BluetoothState::discovery() -> bool {
std::lock_guard lock{sDevicesMutex_};
return sIsDiscoveryAllowed_;
}
auto BluetoothState::discovery(bool en) -> void {
std::lock_guard lock{sDevicesMutex_};
sIsDiscoveryAllowed_ = en;
}
auto BluetoothState::source() -> StreamBufferHandle_t { auto BluetoothState::source() -> StreamBufferHandle_t {
std::lock_guard lock{sDevicesMutex_}; std::lock_guard lock{sDevicesMutex_};
return sSource_.load(); return sSource_.load();
@ -380,17 +356,21 @@ auto BluetoothState::react(const events::DeviceDiscovered& ev) -> void {
} }
} }
if (is_preferred && is_in_state<Idle>()) { if (is_preferred && sPreferredDevice_) {
ESP_LOGI(kTag, "new device is preferred. connecting."); connect(*sPreferredDevice_);
transit<Connecting>();
} }
} }
auto BluetoothState::react(const events::DiscoveryChanged& ev) -> void { auto BluetoothState::connect(const MacAndName& dev) -> void {
if (sIsDiscoveryAllowed_) { if (!is_in_state<Idle>()) {
sScanner_->ScanContinuously(); return;
} else { }
sScanner_->StopScanning(); sConnectingDevice_ = dev;
ESP_LOGI(kTag, "connecting to '%s' (%u%u%u%u%u%u)", dev.name.c_str(),
dev.mac[0], dev.mac[1], dev.mac[2], dev.mac[3], dev.mac[4],
dev.mac[5]);
if (esp_a2d_source_connect(sConnectingDevice_->mac.data()) == ESP_OK) {
transit<Connecting>();
} }
} }
@ -415,16 +395,6 @@ void Disabled::entry() {
esp_bt_controller_deinit(); esp_bt_controller_deinit();
} }
void Disabled::exit() {
if (sIsDiscoveryAllowed_) {
ESP_LOGI(kTag, "bt enabled, beginning discovery");
sScanner_->ScanContinuously();
} else {
ESP_LOGI(kTag, "bt enabled, scanning once");
sScanner_->ScanOnce();
}
}
void Disabled::react(const events::Enable&) { void Disabled::react(const events::Enable&) {
esp_bt_controller_config_t config = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); esp_bt_controller_config_t config = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
esp_err_t err; esp_err_t err;
@ -477,8 +447,7 @@ void Disabled::react(const events::Enable&) {
esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
if (sPreferredDevice_) { if (sPreferredDevice_) {
sConnectingDevice_ = sPreferredDevice_; connect(*sPreferredDevice_);
transit<Connecting>();
} else { } else {
transit<Idle>(); transit<Idle>();
} }
@ -501,8 +470,7 @@ void Idle::react(const events::PreferredDeviceChanged& ev) {
} }
} }
if (is_discovered) { if (is_discovered) {
sConnectingDevice_ = sPreferredDevice_; connect(*sPreferredDevice_);
transit<Connecting>();
} }
} }
@ -512,20 +480,13 @@ void Idle::react(const events::internal::Gap& ev) {
void Connecting::entry() { void Connecting::entry() {
sScanner_->StopScanning(); sScanner_->StopScanning();
auto dev = sConnectingDevice_;
ESP_LOGI(kTag, "connecting to '%s' (%u%u%u%u%u%u)", dev->name.c_str(),
dev->mac[0], dev->mac[1], dev->mac[2], dev->mac[3], dev->mac[4],
dev->mac[5]);
esp_a2d_source_connect(sConnectingDevice_->mac.data());
if (sEventHandler_) { if (sEventHandler_) {
std::invoke(sEventHandler_, Event::kConnectionStateChanged); std::invoke(sEventHandler_, Event::kConnectionStateChanged);
} }
} }
void Connecting::exit() { void Connecting::exit() {
ESP_LOGI(kTag, "connecting finished"); sConnectingDevice_ = {};
if (sEventHandler_) { if (sEventHandler_) {
std::invoke(sEventHandler_, Event::kConnectionStateChanged); std::invoke(sEventHandler_, Event::kConnectionStateChanged);
} }
@ -546,7 +507,6 @@ void Connecting::react(const events::internal::Gap& ev) {
case ESP_BT_GAP_AUTH_CMPL_EVT: case ESP_BT_GAP_AUTH_CMPL_EVT:
if (ev.param->auth_cmpl.stat != ESP_BT_STATUS_SUCCESS) { if (ev.param->auth_cmpl.stat != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(kTag, "auth failed"); ESP_LOGE(kTag, "auth failed");
sConnectingDevice_ = {};
transit<Idle>(); transit<Idle>();
} }
break; break;
@ -556,22 +516,18 @@ void Connecting::react(const events::internal::Gap& ev) {
break; break;
case ESP_BT_GAP_PIN_REQ_EVT: case ESP_BT_GAP_PIN_REQ_EVT:
ESP_LOGW(kTag, "device needs a pin to connect"); ESP_LOGW(kTag, "device needs a pin to connect");
sConnectingDevice_ = {};
transit<Idle>(); transit<Idle>();
break; break;
case ESP_BT_GAP_CFM_REQ_EVT: case ESP_BT_GAP_CFM_REQ_EVT:
ESP_LOGW(kTag, "user needs to do cfm. idk man."); ESP_LOGW(kTag, "user needs to do cfm. idk man.");
sConnectingDevice_ = {};
transit<Idle>(); transit<Idle>();
break; break;
case ESP_BT_GAP_KEY_NOTIF_EVT: case ESP_BT_GAP_KEY_NOTIF_EVT:
ESP_LOGW(kTag, "the device is telling us a password??"); ESP_LOGW(kTag, "the device is telling us a password??");
sConnectingDevice_ = {};
transit<Idle>(); transit<Idle>();
break; break;
case ESP_BT_GAP_KEY_REQ_EVT: case ESP_BT_GAP_KEY_REQ_EVT:
ESP_LOGW(kTag, "the device wants a password!"); ESP_LOGW(kTag, "the device wants a password!");
sConnectingDevice_ = {};
transit<Idle>(); transit<Idle>();
break; break;
case ESP_BT_GAP_MODE_CHG_EVT: case ESP_BT_GAP_MODE_CHG_EVT:

@ -36,13 +36,6 @@ class Bluetooth {
auto IsConnected() -> bool; auto IsConnected() -> bool;
auto ConnectedDevice() -> std::optional<bluetooth::Device>; auto ConnectedDevice() -> std::optional<bluetooth::Device>;
/*
* Sets whether or not the bluetooth stack is allowed to actively scan for
* new devices.
*/
auto SetDeviceDiscovery(bool) -> void;
auto IsDiscovering() -> bool;
auto KnownDevices() -> std::vector<bluetooth::Device>; auto KnownDevices() -> std::vector<bluetooth::Device>;
auto SetPreferredDevice(std::optional<bluetooth::MacAndName> dev) -> void; auto SetPreferredDevice(std::optional<bluetooth::MacAndName> dev) -> void;
@ -62,7 +55,6 @@ struct Disable : public tinyfsm::Event {};
struct PreferredDeviceChanged : public tinyfsm::Event {}; struct PreferredDeviceChanged : public tinyfsm::Event {};
struct SourceChanged : public tinyfsm::Event {}; struct SourceChanged : public tinyfsm::Event {};
struct DiscoveryChanged : public tinyfsm::Event {};
struct DeviceDiscovered : public tinyfsm::Event { struct DeviceDiscovered : public tinyfsm::Event {
const Device& device; const Device& device;
}; };
@ -134,7 +126,6 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
virtual void react(const events::Disable& ev) = 0; virtual void react(const events::Disable& ev) = 0;
virtual void react(const events::PreferredDeviceChanged& ev){}; virtual void react(const events::PreferredDeviceChanged& ev){};
virtual void react(const events::SourceChanged& ev){}; virtual void react(const events::SourceChanged& ev){};
virtual void react(const events::DiscoveryChanged&);
virtual void react(const events::ChangeVolume&) {} virtual void react(const events::ChangeVolume&) {}
virtual void react(const events::DeviceDiscovered&); virtual void react(const events::DeviceDiscovered&);
@ -151,23 +142,22 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
static std::map<mac_addr_t, Device> sDevices_; static std::map<mac_addr_t, Device> sDevices_;
static std::optional<bluetooth::MacAndName> sPreferredDevice_; static std::optional<bluetooth::MacAndName> sPreferredDevice_;
static std::optional<bluetooth::MacAndName> sConnectingDevice_; static std::optional<bluetooth::MacAndName> sConnectingDevice_;
static bool sIsDiscoveryAllowed_;
static std::atomic<StreamBufferHandle_t> sSource_; static std::atomic<StreamBufferHandle_t> sSource_;
static std::function<void(Event)> sEventHandler_; static std::function<void(Event)> sEventHandler_;
auto connect(const bluetooth::MacAndName&) -> void;
}; };
class Disabled : public BluetoothState { class Disabled : public BluetoothState {
public: public:
void entry() override; void entry() override;
void exit() override;
void react(const events::Enable& ev) override; void react(const events::Enable& ev) override;
void react(const events::Disable& ev) override{}; void react(const events::Disable& ev) override{};
void react(const events::internal::Gap& ev) override {} void react(const events::internal::Gap& ev) override {}
void react(const events::internal::A2dp& ev) override {} void react(const events::internal::A2dp& ev) override {}
void react(const events::DiscoveryChanged& ev) override{};
using BluetoothState::react; using BluetoothState::react;
}; };

@ -27,7 +27,6 @@ enum class Event {
kKnownDevicesChanged, kKnownDevicesChanged,
kConnectionStateChanged, kConnectionStateChanged,
kPreferredDeviceChanged, kPreferredDeviceChanged,
kDiscoveryChanged,
}; };
} // namespace bluetooth } // namespace bluetooth

@ -108,7 +108,6 @@ class UiState : public tinyfsm::Fsm<UiState> {
static lua::Property sBluetoothConnected; static lua::Property sBluetoothConnected;
static lua::Property sBluetoothPairedDevice; static lua::Property sBluetoothPairedDevice;
static lua::Property sBluetoothDevices; static lua::Property sBluetoothDevices;
static lua::Property sBluetoothScanning;
static lua::Property sPlaybackPlaying; static lua::Property sPlaybackPlaying;

@ -85,7 +85,6 @@ lua::Property UiState::sBluetoothEnabled{
if (std::get<bool>(val)) { if (std::get<bool>(val)) {
sServices->nvs().OutputMode(drivers::NvsStorage::Output::kBluetooth); sServices->nvs().OutputMode(drivers::NvsStorage::Output::kBluetooth);
sServices->bluetooth().Enable(); sServices->bluetooth().Enable();
sServices->bluetooth().SetDeviceDiscovery(true);
} else { } else {
sServices->nvs().OutputMode(drivers::NvsStorage::Output::kHeadphones); sServices->nvs().OutputMode(drivers::NvsStorage::Output::kHeadphones);
sServices->bluetooth().Disable(); sServices->bluetooth().Disable();
@ -109,7 +108,6 @@ lua::Property UiState::sBluetoothPairedDevice{
}}; }};
lua::Property UiState::sBluetoothDevices{ lua::Property UiState::sBluetoothDevices{
std::vector<drivers::bluetooth::Device>{}}; std::vector<drivers::bluetooth::Device>{}};
lua::Property UiState::sBluetoothScanning{false};
lua::Property UiState::sPlaybackPlaying{ lua::Property UiState::sPlaybackPlaying{
false, [](const lua::LuaValue& val) { false, [](const lua::LuaValue& val) {
@ -340,9 +338,6 @@ void UiState::react(const system_fsm::BluetoothEvent& ev) {
sBluetoothPairedDevice.Update(std::monostate{}); sBluetoothPairedDevice.Update(std::monostate{});
} }
break; break;
case drivers::bluetooth::Event::kDiscoveryChanged:
sBluetoothScanning.Update(bt.IsDiscovering());
break;
case drivers::bluetooth::Event::kPreferredDeviceChanged: case drivers::bluetooth::Event::kPreferredDeviceChanged:
break; break;
} }
@ -466,7 +461,6 @@ void Lua::entry() {
sBluetoothPairedDevice.Update(bt.ConnectedDevice().value()); sBluetoothPairedDevice.Update(bt.ConnectedDevice().value());
} }
sBluetoothDevices.Update(bt.KnownDevices()); sBluetoothDevices.Update(bt.KnownDevices());
sBluetoothScanning.Update(bt.IsDiscovering());
sCurrentScreen.reset(); sCurrentScreen.reset();
sLua->RunScript("/lua/main.lua"); sLua->RunScript("/lua/main.lua");

Loading…
Cancel
Save