#include <simpleble/Config.h>
#include <simpleble/Peripheral.h>
#include "AdapterDongl.h"
#include "BuilderBase.h"
#include "CommonUtils.h"
#include "PeripheralDongl.h"
#include "protocol/simpleble.pb.h"
#include "serial/Protocol.h"
#include <memory>
#include <thread>
using namespace SimpleBLE;
struct DecodedManufacturerData {
std::map<uint16_t, ByteArray> data;
};
struct DecodedServiceData {
std::map<BluetoothUUID, ByteArray> data;
};
bool AdapterDongl::bluetooth_enabled() { return true; }
AdapterDongl::AdapterDongl(const std::string& device_path)
: _serial_protocol(std::make_shared<Dongl::Serial::Protocol>(device_path)) {
fmt::print("Dongl adapter created with device path: {}\n", device_path);
_serial_protocol->set_event_callback([this](const dongl_Event& event) {
switch (event.which_evt) {
case dongl_Event_simpleble_tag:
_on_simpleble_event(event.evt.simpleble);
break;
default:
break;
}
});
auto response_whoami = _serial_protocol->basic_whoami();
_identifier = std::string(response_whoami.identifier);
_address = std::string(response_whoami.mac_address);
fmt::println("Whoami: version {}", response_whoami.version);
fmt::println("Whoami: identifier {}", response_whoami.identifier);
fmt::println("Whoami: mac_address {}", response_whoami.mac_address);
auto response_init = _serial_protocol->simpleble_init();
fmt::println("SimpleBLE init: {}", response_init.ret_code);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
AdapterDongl::~AdapterDongl() {
_serial_protocol->set_event_callback({});
seen_peripherals_.clear();
peripherals_.clear();
_serial_protocol.reset();
}
void* AdapterDongl::underlying() const { return nullptr; }
std::string AdapterDongl::identifier() { return _identifier; }
BluetoothAddress AdapterDongl::address() { return _address; }
void AdapterDongl::power_on() { _serial_protocol->basic_power_on(); }
void AdapterDongl::power_off() { _serial_protocol->basic_power_off(); }
bool AdapterDongl::is_powered() { return _serial_protocol->basic_is_powered().is_powered; }
void AdapterDongl::scan_start() {
auto response = _serial_protocol->simpleble_scan_start();
fmt::print("Scan start: {}\n", response.ret_code);
}
void AdapterDongl::scan_stop() {
auto response = _serial_protocol->simpleble_scan_stop();
fmt::print("Scan stop: {}\n", response.ret_code);
}
void AdapterDongl::scan_for(int timeout_ms) {
scan_start();
std::this_thread::sleep_for(std::chrono::milliseconds(timeout_ms));
scan_stop();
}
bool AdapterDongl::scan_is_active() { return _serial_protocol->simpleble_scan_is_active().is_active; }
SharedPtrVector<PeripheralBase> AdapterDongl::scan_get_results() { return Util::values(seen_peripherals_); }
SharedPtrVector<PeripheralBase> AdapterDongl::get_paired_peripherals() {
SharedPtrVector<PeripheralBase> paired_peripherals;
constexpr uint16_t kMaxPeerIds = 256;
const auto count_response = _serial_protocol->simpleble_get_paired_peripheral_count();
const uint16_t paired_count = count_response.count > kMaxPeerIds ? kMaxPeerIds : count_response.count;
paired_peripherals.reserve(paired_count);
for (uint16_t index = 0; index < paired_count; index++) {
auto response = _serial_protocol->simpleble_get_paired_peripheral(index);
if (!response.found) {
break;
}
BluetoothAddress address = std::string(response.address);
auto peripheral = peripherals_.find(address);
if (peripheral == peripherals_.end()) {
advertising_data_t data{};
data.identifier = address;
data.address_type = static_cast<BluetoothAddressType>(response.address_type);
data.mac_address = address;
data.connectable = true;
peripheral = peripherals_.emplace(address, std::make_shared<PeripheralDongl>(_serial_protocol, data)).first;
}
paired_peripherals.push_back(peripheral->second);
}
return paired_peripherals;
}
void AdapterDongl::_scan_received_callback(advertising_data_t data) {
if (this->peripherals_.count(data.mac_address) == 0) {
auto base_peripheral = std::make_shared<PeripheralDongl>(_serial_protocol, data);
this->peripherals_.insert(std::make_pair(data.mac_address, base_peripheral));
}
auto base_peripheral = this->peripherals_.at(data.mac_address);
base_peripheral->update_advertising_data(data);
Peripheral peripheral = Factory::build(base_peripheral);
if (this->seen_peripherals_.count(data.mac_address) == 0) {
this->seen_peripherals_.insert(std::make_pair(data.mac_address, base_peripheral));
SAFE_CALLBACK_CALL(this->_callback_on_scan_found, peripheral);
} else {
SAFE_CALLBACK_CALL(this->_callback_on_scan_updated, peripheral);
}
}
void AdapterDongl::_on_simpleble_event(const simpleble_Event& event) {
switch (event.which_evt) {
case simpleble_Event_adv_evt_tag: {
advertising_data_t data = advertising_data_t();
data.mac_address = std::string(event.evt.adv_evt.address);
data.address_type = static_cast<SimpleBLE::BluetoothAddressType>(event.evt.adv_evt.address_type);
data.identifier = std::string(event.evt.adv_evt.identifier);
data.connectable = event.evt.adv_evt.connectable;
data.rssi = event.evt.adv_evt.rssi;
data.tx_power = event.evt.adv_evt.tx_power;
for (int i = 0; i < event.evt.adv_evt.manufacturer_data_count; i++) {
ByteArray manufacturer_data(event.evt.adv_evt.manufacturer_data[i].data.bytes,
event.evt.adv_evt.manufacturer_data[i].data.size);
data.manufacturer_data[event.evt.adv_evt.manufacturer_data[i].company_id] = manufacturer_data;
}
_scan_received_callback(data);
break;
}
case simpleble_Event_connection_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->address() == std::string(event.evt.connection_evt.address)) {
peripheral->notify_connected(event.evt.connection_evt.conn_handle);
break;
}
}
break;
}
case simpleble_Event_disconnection_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->conn_handle() == event.evt.disconnection_evt.conn_handle) {
peripheral->notify_disconnected();
break;
}
}
break;
}
case simpleble_Event_service_discovered_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->conn_handle() == event.evt.service_discovered_evt.conn_handle) {
peripheral->notify_service_discovered(event.evt.service_discovered_evt);
break;
}
}
break;
}
case simpleble_Event_characteristic_discovered_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->conn_handle() == event.evt.characteristic_discovered_evt.conn_handle) {
peripheral->notify_characteristic_discovered(event.evt.characteristic_discovered_evt);
break;
}
}
break;
}
case simpleble_Event_descriptor_discovered_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->conn_handle() == event.evt.descriptor_discovered_evt.conn_handle) {
peripheral->notify_descriptor_discovered(event.evt.descriptor_discovered_evt);
break;
}
}
break;
}
case simpleble_Event_attribute_discovery_complete_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->conn_handle() == event.evt.attribute_discovery_complete_evt.conn_handle) {
peripheral->notify_attribute_discovery_complete();
break;
}
}
break;
}
case simpleble_Event_value_changed_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->conn_handle() == event.evt.value_changed_evt.conn_handle) {
peripheral->notify_value_changed(event.evt.value_changed_evt);
break;
}
}
break;
}
case simpleble_Event_passkey_display_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->conn_handle() == event.evt.passkey_display_evt.conn_handle) {
peripheral->notify_passkey_display(event.evt.passkey_display_evt);
break;
}
}
break;
}
case simpleble_Event_auth_key_request_evt_tag: {
for (auto& [address, peripheral] : this->peripherals_) {
if (peripheral->conn_handle() == event.evt.auth_key_request_evt.conn_handle) {
peripheral->notify_auth_key_request(event.evt.auth_key_request_evt);
break;
}
}
break;
}
}
}