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));
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(), sBtOutput.get());

@ -20,6 +20,7 @@
#include "esp_wifi.h"
#include "esp_wifi_types.h"
#include "freertos/portmacro.h"
#include "nvs.hpp"
#include "tinyfsm/include/tinyfsm.hpp"
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);
}
Bluetooth::Bluetooth() {
tinyfsm::FsmList<bluetooth::BluetoothState>::start();
Bluetooth::Bluetooth(NvsStorage* storage) {
bluetooth::BluetoothState::Init(storage);
}
auto Bluetooth::Enable() -> bool {
@ -101,12 +102,15 @@ auto DeviceName() -> std::string {
uint8_t mac[8]{0};
esp_efuse_mac_get_default(mac);
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();
}
namespace bluetooth {
NvsStorage* BluetoothState::sStorage_;
std::mutex BluetoothState::sDevicesMutex_;
std::map<mac_addr_t, Device> BluetoothState::sDevices_;
std::optional<mac_addr_t> BluetoothState::sPreferredDevice_;
@ -114,6 +118,12 @@ mac_addr_t BluetoothState::sCurrentDevice_;
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> {
std::lock_guard lock{sDevicesMutex_};
std::vector<Device> out;
@ -417,6 +427,11 @@ void Connecting::react(const events::internal::A2dp& ev) {
void Connected::entry() {
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
}

@ -11,32 +11,22 @@
#include <freertos/FreeRTOS.h>
#include <freertos/stream_buffer.h>
#include "bluetooth_types.hpp"
#include "esp_a2dp_api.h"
#include "esp_avrc_api.h"
#include "esp_gap_bt_api.h"
#include "nvs.hpp"
#include "tinyfsm.hpp"
#include "tinyfsm/include/tinyfsm.hpp"
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.
*/
class Bluetooth {
public:
Bluetooth();
Bluetooth(NvsStorage* storage);
auto Enable() -> bool;
auto Disable() -> void;
@ -74,6 +64,8 @@ struct Avrc : public tinyfsm::Event {
class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
public:
static auto Init(NvsStorage* storage) -> void;
static auto devices() -> std::vector<Device>;
static auto preferred_device() -> std::optional<mac_addr_t>;
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){};
protected:
static NvsStorage* sStorage_;
static std::mutex sDevicesMutex_;
static std::map<mac_addr_t, Device> sDevices_;
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
#include <optional>
#include "esp_err.h"
#include "nvs.h"
#include "bluetooth_types.hpp"
namespace drivers {
class NvsStorage {
@ -17,6 +21,9 @@ class NvsStorage {
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);
~NvsStorage();

@ -10,6 +10,7 @@
#include <cstdint>
#include <memory>
#include "bluetooth.hpp"
#include "esp_log.h"
#include "nvs.h"
#include "nvs_flash.h"
@ -20,6 +21,7 @@ static constexpr char kTag[] = "nvm";
static constexpr uint8_t kSchemaVersion = 1;
static constexpr char kKeyVersion[] = "ver";
static constexpr char kKeyBluetooth[] = "bt";
auto NvsStorage::Open() -> NvsStorage* {
esp_err_t err = nvs_flash_init();
@ -70,4 +72,24 @@ auto NvsStorage::SchemaVersion() -> uint8_t {
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

@ -62,7 +62,8 @@ auto Booting::entry() -> void {
}
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
// state machines and inform them that the system is ready.

Loading…
Cancel
Save