persist preferred bluetooth device in nvs

custom
jacqueline 2 years ago
parent d6b83fcf4a
commit 544b0013b1
  1. 2
      src/audio/audio_fsm.cpp
  2. 21
      src/drivers/bluetooth.cpp
  3. 20
      src/drivers/include/bluetooth.hpp
  4. 20
      src/drivers/include/bluetooth_types.hpp
  5. 7
      src/drivers/include/nvs.hpp
  6. 22
      src/drivers/nvs.cpp
  7. 3
      src/system_fsm/booting.cpp

@ -59,7 +59,7 @@ auto AudioState::Init(drivers::IGpios* gpio_expander,
sFileSource.reset(new FatfsAudioInput(tag_parser)); sFileSource.reset(new FatfsAudioInput(tag_parser));
sI2SOutput.reset(new I2SAudioOutput(sIGpios, sDac)); sI2SOutput.reset(new I2SAudioOutput(sIGpios, sDac));
// sBtOutput.reset(new BluetoothAudioOutput(bluetooth)); sBtOutput.reset(new BluetoothAudioOutput(bluetooth));
AudioTask::Start(sFileSource.get(), sI2SOutput.get()); AudioTask::Start(sFileSource.get(), sI2SOutput.get());
// AudioTask::Start(sFileSource.get(), sBtOutput.get()); // AudioTask::Start(sFileSource.get(), sBtOutput.get());

@ -20,6 +20,7 @@
#include "esp_wifi.h" #include "esp_wifi.h"
#include "esp_wifi_types.h" #include "esp_wifi_types.h"
#include "freertos/portmacro.h" #include "freertos/portmacro.h"
#include "nvs.hpp"
#include "tinyfsm/include/tinyfsm.hpp" #include "tinyfsm/include/tinyfsm.hpp"
namespace drivers { namespace drivers {
@ -55,8 +56,8 @@ auto a2dp_data_cb(uint8_t* buf, int32_t buf_size) -> int32_t {
return xStreamBufferReceive(stream, buf, buf_size, 0); return xStreamBufferReceive(stream, buf, buf_size, 0);
} }
Bluetooth::Bluetooth() { Bluetooth::Bluetooth(NvsStorage* storage) {
tinyfsm::FsmList<bluetooth::BluetoothState>::start(); bluetooth::BluetoothState::Init(storage);
} }
auto Bluetooth::Enable() -> bool { auto Bluetooth::Enable() -> bool {
@ -101,12 +102,15 @@ auto DeviceName() -> std::string {
uint8_t mac[8]{0}; uint8_t mac[8]{0};
esp_efuse_mac_get_default(mac); esp_efuse_mac_get_default(mac);
std::ostringstream name; std::ostringstream name;
name << "TANGARA " << std::hex << mac[0] << mac[1]; name << "TANGARA " << std::hex << static_cast<int>(mac[0])
<< static_cast<int>(mac[1]);
return name.str(); return name.str();
} }
namespace bluetooth { namespace bluetooth {
NvsStorage* BluetoothState::sStorage_;
std::mutex BluetoothState::sDevicesMutex_; std::mutex BluetoothState::sDevicesMutex_;
std::map<mac_addr_t, Device> BluetoothState::sDevices_; std::map<mac_addr_t, Device> BluetoothState::sDevices_;
std::optional<mac_addr_t> BluetoothState::sPreferredDevice_; std::optional<mac_addr_t> BluetoothState::sPreferredDevice_;
@ -114,6 +118,12 @@ mac_addr_t BluetoothState::sCurrentDevice_;
std::atomic<StreamBufferHandle_t> BluetoothState::sSource_; std::atomic<StreamBufferHandle_t> BluetoothState::sSource_;
auto BluetoothState::Init(NvsStorage* storage) -> void {
sStorage_ = storage;
sPreferredDevice_ = storage->PreferredBluetoothDevice();
tinyfsm::FsmList<bluetooth::BluetoothState>::start();
}
auto BluetoothState::devices() -> std::vector<Device> { auto BluetoothState::devices() -> std::vector<Device> {
std::lock_guard lock{sDevicesMutex_}; std::lock_guard lock{sDevicesMutex_};
std::vector<Device> out; std::vector<Device> out;
@ -417,6 +427,11 @@ void Connecting::react(const events::internal::A2dp& ev) {
void Connected::entry() { void Connected::entry() {
ESP_LOGI(kTag, "entering connected state"); ESP_LOGI(kTag, "entering connected state");
auto stored_pref = sStorage_->PreferredBluetoothDevice();
if (stored_pref != sPreferredDevice_) {
sStorage_->PreferredBluetoothDevice(sPreferredDevice_);
}
// TODO: if we already have a source, immediately start playing // TODO: if we already have a source, immediately start playing
} }

@ -11,32 +11,22 @@
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/stream_buffer.h> #include <freertos/stream_buffer.h>
#include "bluetooth_types.hpp"
#include "esp_a2dp_api.h" #include "esp_a2dp_api.h"
#include "esp_avrc_api.h" #include "esp_avrc_api.h"
#include "esp_gap_bt_api.h" #include "esp_gap_bt_api.h"
#include "nvs.hpp"
#include "tinyfsm.hpp" #include "tinyfsm.hpp"
#include "tinyfsm/include/tinyfsm.hpp" #include "tinyfsm/include/tinyfsm.hpp"
namespace drivers { namespace drivers {
namespace bluetooth {
typedef std::array<uint8_t, 6> mac_addr_t;
struct Device {
mac_addr_t address;
std::string name;
uint32_t class_of_device;
int8_t signal_strength;
};
} // namespace bluetooth
/* /*
* A handle used to interact with the bluetooth state machine. * A handle used to interact with the bluetooth state machine.
*/ */
class Bluetooth { class Bluetooth {
public: public:
Bluetooth(); Bluetooth(NvsStorage* storage);
auto Enable() -> bool; auto Enable() -> bool;
auto Disable() -> void; auto Disable() -> void;
@ -74,6 +64,8 @@ struct Avrc : public tinyfsm::Event {
class BluetoothState : public tinyfsm::Fsm<BluetoothState> { class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
public: public:
static auto Init(NvsStorage* storage) -> void;
static auto devices() -> std::vector<Device>; static auto devices() -> std::vector<Device>;
static auto preferred_device() -> std::optional<mac_addr_t>; static auto preferred_device() -> std::optional<mac_addr_t>;
static auto preferred_device(const mac_addr_t&) -> void; static auto preferred_device(const mac_addr_t&) -> void;
@ -96,6 +88,8 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
virtual void react(const events::internal::Avrc& ev){}; virtual void react(const events::internal::Avrc& ev){};
protected: protected:
static NvsStorage* sStorage_;
static std::mutex sDevicesMutex_; static std::mutex sDevicesMutex_;
static std::map<mac_addr_t, Device> sDevices_; static std::map<mac_addr_t, Device> sDevices_;
static std::optional<mac_addr_t> sPreferredDevice_; static std::optional<mac_addr_t> sPreferredDevice_;

@ -0,0 +1,20 @@
#pragma once
#include <array>
#include <string>
namespace drivers {
namespace bluetooth {
typedef std::array<uint8_t, 6> mac_addr_t;
struct Device {
mac_addr_t address;
std::string name;
uint32_t class_of_device;
int8_t signal_strength;
};
} // namespace bluetooth
} // namespace drivers

@ -6,9 +6,13 @@
#pragma once #pragma once
#include <optional>
#include "esp_err.h" #include "esp_err.h"
#include "nvs.h" #include "nvs.h"
#include "bluetooth_types.hpp"
namespace drivers { namespace drivers {
class NvsStorage { class NvsStorage {
@ -17,6 +21,9 @@ class NvsStorage {
auto SchemaVersion() -> uint8_t; auto SchemaVersion() -> uint8_t;
auto PreferredBluetoothDevice() -> std::optional<bluetooth::mac_addr_t>;
auto PreferredBluetoothDevice(std::optional<bluetooth::mac_addr_t>) -> void;
explicit NvsStorage(nvs_handle_t); explicit NvsStorage(nvs_handle_t);
~NvsStorage(); ~NvsStorage();

@ -10,6 +10,7 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include "bluetooth.hpp"
#include "esp_log.h" #include "esp_log.h"
#include "nvs.h" #include "nvs.h"
#include "nvs_flash.h" #include "nvs_flash.h"
@ -20,6 +21,7 @@ static constexpr char kTag[] = "nvm";
static constexpr uint8_t kSchemaVersion = 1; static constexpr uint8_t kSchemaVersion = 1;
static constexpr char kKeyVersion[] = "ver"; static constexpr char kKeyVersion[] = "ver";
static constexpr char kKeyBluetooth[] = "bt";
auto NvsStorage::Open() -> NvsStorage* { auto NvsStorage::Open() -> NvsStorage* {
esp_err_t err = nvs_flash_init(); esp_err_t err = nvs_flash_init();
@ -70,4 +72,24 @@ auto NvsStorage::SchemaVersion() -> uint8_t {
return ret; return ret;
} }
auto NvsStorage::PreferredBluetoothDevice()
-> std::optional<bluetooth::mac_addr_t> {
bluetooth::mac_addr_t out{0};
size_t size = out.size();
if (nvs_get_blob(handle_, kKeyBluetooth, out.data(), &size) != ESP_OK) {
return {};
}
return out;
}
auto NvsStorage::PreferredBluetoothDevice(
std::optional<bluetooth::mac_addr_t> addr) -> void {
if (!addr) {
nvs_erase_key(handle_, kKeyBluetooth);
} else {
nvs_set_blob(handle_, kKeyBluetooth, addr.value().data(),
addr.value().size());
}
nvs_commit(handle_);
}
} // namespace drivers } // namespace drivers

@ -62,7 +62,8 @@ auto Booting::entry() -> void {
} }
ESP_LOGI(kTag, "starting bluetooth"); ESP_LOGI(kTag, "starting bluetooth");
sBluetooth.reset(new drivers::Bluetooth()); sBluetooth.reset(new drivers::Bluetooth(sNvs.get()));
// sBluetooth->Enable();
// At this point we've done all of the essential boot tasks. Start remaining // At this point we've done all of the essential boot tasks. Start remaining
// state machines and inform them that the system is ready. // state machines and inform them that the system is ready.

Loading…
Cancel
Save