summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-02-12 17:07:39 +1100
committerjacqueline <me@jacqueline.id.au>2024-02-12 17:07:39 +1100
commit26df5c4a7f54d493a09724a5f4f8f4a3a5c90f31 (patch)
tree168c313734ed388efa1847226d6cea61b8c0c7e0 /src/drivers
parenta7ac34eaa9b895e16aed816c504d167027898d7b (diff)
downloadtangara-fw-26df5c4a7f54d493a09724a5f4f8f4a3a5c90f31.tar.gz
Remember per-device bluetooth volume
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/CMakeLists.txt2
-rw-r--r--src/drivers/bluetooth.cpp13
-rw-r--r--src/drivers/include/bluetooth.hpp2
-rw-r--r--src/drivers/include/nvs.hpp6
-rw-r--r--src/drivers/nvs.cpp98
5 files changed, 108 insertions, 13 deletions
diff --git a/src/drivers/CMakeLists.txt b/src/drivers/CMakeLists.txt
index 4155ed66..0b7ead94 100644
--- a/src/drivers/CMakeLists.txt
+++ b/src/drivers/CMakeLists.txt
@@ -9,5 +9,5 @@ idf_component_register(
"spiffs.cpp"
INCLUDE_DIRS "include"
REQUIRES "esp_adc" "fatfs" "result" "lvgl" "span" "tasks" "nvs_flash" "spiffs"
- "bt" "tinyfsm")
+ "bt" "tinyfsm" "util")
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
diff --git a/src/drivers/bluetooth.cpp b/src/drivers/bluetooth.cpp
index 1a303748..84c81de0 100644
--- a/src/drivers/bluetooth.cpp
+++ b/src/drivers/bluetooth.cpp
@@ -103,21 +103,12 @@ auto Bluetooth::IsConnected() -> bool {
return bluetooth::BluetoothState::is_in_state<bluetooth::Connected>();
}
-auto Bluetooth::ConnectedDevice() -> std::optional<bluetooth::Device> {
+auto Bluetooth::ConnectedDevice() -> std::optional<bluetooth::MacAndName> {
auto lock = bluetooth::BluetoothState::lock();
if (!bluetooth::BluetoothState::is_in_state<bluetooth::Connected>()) {
return {};
}
- auto looking_for = bluetooth::BluetoothState::preferred_device();
- if (!looking_for) {
- return {};
- }
- for (const auto& dev : bluetooth::BluetoothState::devices()) {
- if (dev.address == looking_for->mac) {
- return dev;
- }
- }
- return {};
+ return bluetooth::BluetoothState::preferred_device();
}
auto Bluetooth::KnownDevices() -> std::vector<bluetooth::Device> {
diff --git a/src/drivers/include/bluetooth.hpp b/src/drivers/include/bluetooth.hpp
index 5fdd527c..988c7e93 100644
--- a/src/drivers/include/bluetooth.hpp
+++ b/src/drivers/include/bluetooth.hpp
@@ -35,7 +35,7 @@ class Bluetooth {
auto IsEnabled() -> bool;
auto IsConnected() -> bool;
- auto ConnectedDevice() -> std::optional<bluetooth::Device>;
+ auto ConnectedDevice() -> std::optional<bluetooth::MacAndName>;
auto KnownDevices() -> std::vector<bluetooth::Device>;
diff --git a/src/drivers/include/nvs.hpp b/src/drivers/include/nvs.hpp
index 1184b72c..264d9784 100644
--- a/src/drivers/include/nvs.hpp
+++ b/src/drivers/include/nvs.hpp
@@ -15,6 +15,7 @@
#include "bluetooth_types.hpp"
#include "tasks.hpp"
+#include "lru_cache.hpp"
namespace drivers {
@@ -28,6 +29,11 @@ class NvsStorage {
auto PreferredBluetoothDevice() -> std::optional<bluetooth::MacAndName>;
auto PreferredBluetoothDevice(std::optional<bluetooth::MacAndName>) -> bool;
+ using BtVolumes = util::LruCache<10, bluetooth::mac_addr_t, uint8_t> ;
+
+ auto BluetoothVolumes() -> BtVolumes;
+ auto BluetoothVolumes(const BtVolumes&) -> bool;
+
enum class Output : uint8_t {
kHeadphones = 0,
kBluetooth = 1,
diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp
index ab623d01..f7687dcb 100644
--- a/src/drivers/nvs.cpp
+++ b/src/drivers/nvs.cpp
@@ -13,6 +13,8 @@
#include "bluetooth.hpp"
#include "bluetooth_types.hpp"
+#include "cppbor.h"
+#include "cppbor_parse.h"
#include "esp_log.h"
#include "nvs.h"
#include "nvs_flash.h"
@@ -27,6 +29,7 @@ static constexpr uint8_t kSchemaVersion = 1;
static constexpr char kKeyVersion[] = "ver";
static constexpr char kKeyBluetoothMac[] = "bt_mac";
static constexpr char kKeyBluetoothName[] = "bt_name";
+static constexpr char kKeyBluetoothVolumes[] = "bt_vols";
static constexpr char kKeyOutput[] = "out";
static constexpr char kKeyBrightness[] = "bright";
static constexpr char kKeyAmpMaxVolume[] = "hp_vol_max";
@@ -135,6 +138,101 @@ auto NvsStorage::PreferredBluetoothDevice(
return nvs_commit(handle_) == ESP_OK;
}
+class VolumesParseClient : public cppbor::ParseClient {
+ public:
+ VolumesParseClient(NvsStorage::BtVolumes& out)
+ : state_(State::kInit), mac_(), vol_(), out_(out) {}
+
+ ParseClient* item(std::unique_ptr<cppbor::Item>& item,
+ const uint8_t* hdrBegin,
+ const uint8_t* valueBegin,
+ const uint8_t* end) override {
+ if (item->type() == cppbor::ARRAY) {
+ if (state_ == State::kInit) {
+ ESP_LOGI(kTag, "enter root");
+ state_ = State::kRoot;
+ } else if (state_ == State::kRoot) {
+ ESP_LOGI(kTag, "enter pair");
+ state_ = State::kPair;
+ }
+ } else if (item->type() == cppbor::BSTR && state_ == State::kPair) {
+ ESP_LOGI(kTag, "get str");
+ auto data = item->asBstr()->value();
+ mac_.emplace();
+ std::copy(data.begin(), data.end(), mac_->begin());
+ } else if (item->type() == cppbor::UINT && state_ == State::kPair) {
+ vol_ =
+ std::clamp<uint64_t>(item->asUint()->unsignedValue(), 0, UINT8_MAX);
+ }
+ return this;
+ }
+
+ ParseClient* itemEnd(std::unique_ptr<cppbor::Item>& item,
+ const uint8_t* hdrBegin,
+ const uint8_t* valueBegin,
+ const uint8_t* end) override {
+ if (item->type() == cppbor::ARRAY) {
+ if (state_ == State::kRoot) {
+ state_ = State::kFinished;
+ } else if (state_ == State::kPair) {
+ if (vol_ && mac_) {
+ out_.Put(*mac_, *vol_);
+ }
+ mac_.reset();
+ vol_.reset();
+ state_ = State::kRoot;
+ }
+ }
+ return this;
+ }
+
+ void error(const uint8_t* position,
+ const std::string& errorMessage) override {}
+
+ private:
+ enum class State {
+ kInit,
+ kRoot,
+ kPair,
+ kFinished,
+ };
+
+ State state_;
+ std::optional<bluetooth::mac_addr_t> mac_;
+ std::optional<uint8_t> vol_;
+ NvsStorage::BtVolumes& out_;
+};
+
+auto NvsStorage::BluetoothVolumes() -> BtVolumes {
+ BtVolumes out;
+ size_t encoded_len = 0;
+ if (nvs_get_str(handle_, kKeyBluetoothVolumes, NULL, &encoded_len) !=
+ ESP_OK) {
+ return out;
+ }
+ auto encoded = std::unique_ptr<char[]>{new char[encoded_len]};
+ if (nvs_get_str(handle_, kKeyBluetoothVolumes, encoded.get(), &encoded_len) !=
+ ESP_OK) {
+ return out;
+ }
+ VolumesParseClient client{out};
+ auto data = reinterpret_cast<const uint8_t*>(encoded.get());
+ cppbor::parse(data, data + encoded_len, &client);
+ return out;
+}
+
+auto NvsStorage::BluetoothVolumes(const BtVolumes& vols) -> bool {
+ cppbor::Array enc;
+ auto vols_list = vols.Get();
+ for (auto vol = vols_list.rbegin(); vol < vols_list.rend(); vol++) {
+ enc.add(cppbor::Array{cppbor::Bstr{{vol->first.data(), vol->first.size()}},
+ cppbor::Uint{vol->second}});
+ }
+ std::string encoded = enc.toString();
+ nvs_set_str(handle_, kKeyBluetoothVolumes, encoded.c_str());
+ return nvs_commit(handle_) == ESP_OK;
+}
+
auto NvsStorage::OutputMode() -> Output {
uint8_t out = 0;
nvs_get_u8(handle_, kKeyOutput, &out);