aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/CMakeLists.txt1
-rw-r--r--apps/SoilMoisture.cpp16
-rw-r--r--apps/SoilMoisture.h4
-rw-r--r--apps/ble-bts.cpp108
-rw-r--r--apps/ble-inspect-device.cpp2
-rw-r--r--apps/sm-get-value.cpp4
-rw-r--r--ble/Bluetooth.cpp52
-rw-r--r--ble/BluetoothImpl.h77
-rw-r--r--ble/LinuxBluetooth.cpp83
-rw-r--r--include/ble/Bluetooth.h143
10 files changed, 325 insertions, 165 deletions
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 8f8feb3..6491ef1 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -100,6 +100,7 @@ endfunction()
add_app(NAME ble-inspect-device)
add_app(NAME ble-scan)
+add_app(NAME ble-bts)
add_app(NAME sample-add-timestamp)
add_app(NAME sample-convert)
add_app(NAME sample-select)
diff --git a/apps/SoilMoisture.cpp b/apps/SoilMoisture.cpp
index 4b9dfe5..d92752d 100644
--- a/apps/SoilMoisture.cpp
+++ b/apps/SoilMoisture.cpp
@@ -7,16 +7,16 @@ namespace sensor {
#define BLUETOOTH_UUID_INITIALIZER \
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb };
-auto trygvis_io_base_uuid =
- boost::uuids::uuid{0x32, 0xd0, 0x00, 0x00, 0x03, 0x5d, 0x59, 0xc5, 0x70, 0xd3, 0xbc, 0x8e, 0x4a, 0x1f, 0xd8, 0x3f};
+Uuid trygvis_io_base_uuid =
+ {0x32, 0xd0, 0x00, 0x00, 0x03, 0x5d, 0x59, 0xc5, 0x70, 0xd3, 0xbc, 0x8e, 0x4a, 0x1f, 0xd8, 0x3f};
-auto bluetooth_base_uuid =
- boost::uuids::uuid{0x00, 0x00, 0x18, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+Uuid bluetooth_base_uuid =
+ {0x00, 0x00, 0x18, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
-const boost::uuids::uuid soil_moisture_service = makeUuid(trygvis_io_base_uuid, 0x00, 0x10);
-const boost::uuids::uuid soil_moisture_characteristic = makeUuid(trygvis_io_base_uuid, 0x00, 0x11);
-const boost::uuids::uuid temperature_characteristic = makeUuid(bluetooth_base_uuid, 0x2a, 0x1e);
-const boost::uuids::uuid light_characteristic = makeUuid(trygvis_io_base_uuid, 0x00, 0x12);
+const Uuid soil_moisture_service = makeUuid(trygvis_io_base_uuid, 0x00, 0x10);
+const Uuid soil_moisture_characteristic = makeUuid(trygvis_io_base_uuid, 0x00, 0x11);
+const Uuid temperature_characteristic = makeUuid(bluetooth_base_uuid, 0x2a, 0x1e);
+const Uuid light_characteristic = makeUuid(trygvis_io_base_uuid, 0x00, 0x12);
using namespace trygvis::bluetooth;
diff --git a/apps/SoilMoisture.h b/apps/SoilMoisture.h
index 0ad1d15..499c9f6 100644
--- a/apps/SoilMoisture.h
+++ b/apps/SoilMoisture.h
@@ -24,8 +24,8 @@ enum class sm_cmd_code : uint8_t {
SM_CMD_FAIL = 255,
};
-extern const boost::uuids::uuid soil_moisture_service;
-extern const boost::uuids::uuid soil_moisture_characteristic;
+extern const Uuid soil_moisture_service;
+extern const Uuid soil_moisture_characteristic;
class SoilMoisture {
public:
diff --git a/apps/ble-bts.cpp b/apps/ble-bts.cpp
new file mode 100644
index 0000000..1e76f60
--- /dev/null
+++ b/apps/ble-bts.cpp
@@ -0,0 +1,108 @@
+#include "ble/Bluetooth.h"
+#include "apps.h"
+
+#include <csignal>
+#include "apps.h"
+
+namespace trygvis {
+namespace apps {
+
+using namespace std;
+using namespace trygvis::bluetooth;
+using namespace trygvis::apps;
+
+namespace ble_bts_utils {
+
+static std::function<void(int)> onSignal;
+
+static void signal_handler(int signal) {
+ onSignal(signal);
+}
+}
+
+class ble_bts : public app {
+public:
+ ble_bts() : app("ble-scan") {}
+
+ ~ble_bts() override = default;
+
+ string adapter_name;
+
+ void add_options(po::options_description_easy_init &options) override {
+ auto adapter_value = po::value<>(&adapter_name)->default_value("0");
+ options("adapter", adapter_value, "Which adapter to use.");
+ options("device", po::value<string>()->required(), "The MAC of the device to inspect");
+ }
+
+ int main(app_execution &execution) override {
+ BluetoothSystem bluetoothSystem;
+ shared_ptr<BluetoothAdapter> adapter;
+
+ struct sigaction sigIntHandler{};
+
+ ble_bts_utils::onSignal = [&](int signal) { adapter->stopScan(); };
+
+ sigIntHandler.sa_handler = &ble_bts_utils::signal_handler;
+ sigemptyset(&sigIntHandler.sa_mask);
+ sigIntHandler.sa_flags = 0;
+
+ sigaction(SIGINT, &sigIntHandler, nullptr);
+
+ try {
+ adapter = bluetoothSystem.getAdapter(adapter_name);
+
+ string mac_str = execution.vm["device"].as<string>();
+ Mac mac = Mac::parseMac(mac_str);
+
+ auto device = adapter->getDevice(mac);
+
+ auto gatt = device->connectGatt();
+ cout << "Connected" << endl;
+
+ auto bts = gatt->findService(uuids::HealthTermometerService);
+ if (!bts) {
+ cout << "Device does not implement Health thermometer service" << endl;
+ return EXIT_FAILURE;
+ }
+
+ auto tmc = bts->get()->findCharacteristic(uuids::TemperatureMeasurement);
+
+ if (!tmc) {
+ cout << "The device does not have temperature measurement characteristic" << endl;
+ return EXIT_FAILURE;
+ }
+
+ with_connection(gatt, tmc.value());
+
+ return EXIT_SUCCESS;
+ } catch (std::runtime_error &ex) {
+ cout << "std::runtime_error: " << ex.what() << endl;
+ return EXIT_FAILURE;
+ } catch (std::exception &ex) {
+ cout << "std::exception: " << ex.what() << endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ void with_connection(BluetoothGattPtr gatt, BluetoothGattCharacteristicPtr tmc) {
+ auto svc = tmc->getService();
+
+ cout << "Reading temp value" << endl;
+
+ auto buf = gatt->readValue(tmc);
+
+ cout << "bytes " << buf.getSize() << endl;
+
+ for (int i = 0; i < buf.getSize(); i++) {
+ cout << "byte " << i << " = " << hex << buf.get8(i) << endl;
+ }
+ }
+};
+}
+}
+
+int main(int argc, const char *argv[]) {
+ using namespace trygvis::apps;
+
+ return real_main(new ble_bts(), argc, argv);
+}
diff --git a/apps/ble-inspect-device.cpp b/apps/ble-inspect-device.cpp
index baee93a..8f85e5c 100644
--- a/apps/ble-inspect-device.cpp
+++ b/apps/ble-inspect-device.cpp
@@ -16,7 +16,7 @@ class ble_inspect_device : public app {
public:
ble_inspect_device() : app("ble-inspect-device") {}
- ~ble_inspect_device() = default;
+ ~ble_inspect_device() override = default;
void add_options(po::options_description_easy_init &options) override {
options("device", po::value<string>()->required(), "The MAC of the device to inspect");
diff --git a/apps/sm-get-value.cpp b/apps/sm-get-value.cpp
index 483df70..eb7a141 100644
--- a/apps/sm-get-value.cpp
+++ b/apps/sm-get-value.cpp
@@ -153,7 +153,7 @@ public:
}
// If the user didn't specify any sensors, add all.
- if (sensors.size() == 0) {
+ if (sensors.empty()) {
for (unsigned int i = 0; i < sensorCount; i++) {
sensorIndexes.push_back(i);
}
@@ -165,7 +165,7 @@ public:
return;
}
- sensors.push_back(make_pair(i, soilMoisture.getName(i)));
+ sensors.emplace_back(make_pair(i, soilMoisture.getName(i)));
});
}
auto mac = gatt->getDevice().getMac().str();
diff --git a/ble/Bluetooth.cpp b/ble/Bluetooth.cpp
index 13c81b3..4160acc 100644
--- a/ble/Bluetooth.cpp
+++ b/ble/Bluetooth.cpp
@@ -71,14 +71,14 @@ AttPduType AttPdu::getType() {
return (AttPduType) bytes.get8(0);
}
-void AttPdu::makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, SpecUuid uuid) {
+void AttPdu::makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, ShortUuid uuid) {
bytes.write8(AttPduType::READ_BY_GROUP_TYPE_REQ);
bytes.write16le(startHandle);
bytes.write16le(endHandle);
bytes.write16le(uuid.value);
}
-void AttPdu::makeReadByType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, SpecUuid uuid) {
+void AttPdu::makeReadByType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, ShortUuid uuid) {
bytes.write8(AttPduType::READ_BY_TYPE_REQ);
bytes.write16le(startHandle);
bytes.write16le(endHandle);
@@ -99,14 +99,14 @@ void AttPdu::makeWrite(ByteBuffer &req, uint16_t handle, const ByteBuffer &bytes
vector<AttributeData> AttPdu::parse(ByteBuffer &bytes, AttPduType type) {
// cout << "bytes: " << bytes.toString();
- AttPduType t = (AttPduType) bytes.read8();
+ auto t = static_cast<AttPduType>(bytes.read8());
- if (t == INVALID_HANDLE) {
+ if (t == ERROR) {
return vector<AttributeData>();
}
if (t != type) {
- throw BluetoothException("Unexpected type: " + to_string(t));
+ throw BluetoothException("Unexpected type: " + to_string(t) + ", expected " + to_string(type));
}
if (bytes.getSize() < 4) {
@@ -138,11 +138,13 @@ vector<AttributeData> AttPdu::parseReadByType(ByteBuffer &bytes) {
return parse(bytes, READ_BY_TYPE_RES);
}
+static uint16_t parseExchangeMtuReq(ByteBuffer &bytes);
+
void AttPdu::parseRead(ByteBuffer &bytes) {
AttPduType t = (AttPduType) bytes.read8();
if (t != READ_RES) {
- throw BluetoothException("Unexpected type: " + to_string(t));
+ throw BluetoothException("Unexpected type: " + to_string(t) + ", expected " + to_string(READ_RES));
}
}
@@ -150,7 +152,7 @@ void AttPdu::parseWrite(ByteBuffer &bytes) {
AttPduType t = (AttPduType) bytes.read8();
if (t != WRITE_RES) {
- throw BluetoothException("Unexpected type: " + to_string(t));
+ throw BluetoothException("Unexpected type: " + to_string(t) + ", expected " + to_string(WRITE_RES));
}
}
@@ -168,45 +170,36 @@ AttributeData::AttributeData(uint16_t handle, ByteBuffer value) :
handle(handle), value(value) {
}
-AttributeData::~AttributeData() {
-}
+AttributeData::~AttributeData() = default;
// -----------------------------------------------------------------------
// Gatt
// -----------------------------------------------------------------------
-BluetoothGatt::BluetoothGatt() {
-}
+BluetoothGatt::BluetoothGatt() = default;
-BluetoothGatt::~BluetoothGatt() {
-}
+BluetoothGatt::~BluetoothGatt() = default;
// -----------------------------------------------------------------------
// Device
// -----------------------------------------------------------------------
-BluetoothDevice::BluetoothDevice() {
-}
+BluetoothDevice::BluetoothDevice() = default;
-BluetoothDevice::~BluetoothDevice() {
-}
+BluetoothDevice::~BluetoothDevice() = default;
// -----------------------------------------------------------------------
// Adapter
// -----------------------------------------------------------------------
-BluetoothAdapter::BluetoothAdapter() {
-}
-
-BluetoothAdapter::~BluetoothAdapter() {
-}
+BluetoothAdapter::BluetoothAdapter() = default;
+BluetoothAdapter::~BluetoothAdapter() = default;
// -----------------------------------------------------------------------
// Bluetooth System. This is not sub-classed by implementations.
// -----------------------------------------------------------------------
-BluetoothSystem::BluetoothSystem() {
-}
+BluetoothSystem::BluetoothSystem() = default;
BluetoothSystem::~BluetoothSystem() {
adapters.clear();
@@ -223,11 +216,12 @@ shared_ptr<BluetoothAdapter> BluetoothSystem::getAdapter(string name) {
return it->second;
}
-uuid_t makeUuid(const uuid_t base, uint8_t a, uint8_t b) {
- uuid_t c = base;
- c.data[2] = a;
- c.data[3] = b;
- return c;
+Uuid makeUuid(const Uuid &base, uint8_t a, uint8_t b) {
+ uint8_t value[16];
+ memcpy(value, base.value, 16);
+ value[2] = a;
+ value[3] = b;
+ return Uuid{value};
}
}
diff --git a/ble/BluetoothImpl.h b/ble/BluetoothImpl.h
index 8663b20..c660b4b 100644
--- a/ble/BluetoothImpl.h
+++ b/ble/BluetoothImpl.h
@@ -25,14 +25,13 @@ namespace trygvis {
namespace bluetooth {
// Utility typedefs
-typedef boost::uuids::uuid uuid_t;
using namespace log4cplus;
// Logging
class LogSetup {
public:
- LogSetup(std::string name) : logger(Logger::getInstance(LOG4CPLUS_TEXT(name))) {
+ explicit LogSetup(const std::string &name) : logger(Logger::getInstance(LOG4CPLUS_TEXT(name))) {
}
protected:
@@ -61,7 +60,7 @@ struct constify2<T *, U const *> {
template<typename A, typename B>
class CollectionImpl : public Collection<A> {
public:
- CollectionImpl(B &b) : b(b) {
+ explicit CollectionImpl(B &b) : b(b) {
}
private:
@@ -70,47 +69,46 @@ private:
class DefaultBluetoothGattCharacteristic : protected LogSetup, public BluetoothGattCharacteristic {
public:
- DefaultBluetoothGattCharacteristic(const BluetoothGattServicePtr &service, uint16_t handle, uuid_t uuid,
+ DefaultBluetoothGattCharacteristic(const BluetoothGattServicePtr &service, uint16_t handle, Uuid uuid,
uint8_t properties, uint16_t valueHandle)
- : LogSetup("BluetoothGattCharacteristic"), service(service), handle(handle), uuid(uuid),
- properties(properties), valueHandle(valueHandle) {
+ : LogSetup("BluetoothGattCharacteristic"), service(service), handle(handle), uuid(uuid),
+ properties(properties), valueHandle(valueHandle) {
}
- virtual ~DefaultBluetoothGattCharacteristic() {
- }
+ ~DefaultBluetoothGattCharacteristic() override = default;
- BluetoothGattServicePtr getService() const {
+ BluetoothGattServicePtr getService() const override {
return service;
}
- uint16_t getHandle() const {
+ uint16_t getHandle() const override {
return handle;
}
- const uuid_t getUuid() const {
+ const Uuid getUuid() const override {
return uuid;
}
- uint8_t getProperties() const {
+ uint8_t getProperties() const override {
return properties;
}
- uint16_t getValueHandle() const {
+ uint16_t getValueHandle() const override {
return valueHandle;
}
protected:
BluetoothGattServicePtr service;
uint16_t handle;
- uuid_t uuid;
+ Uuid uuid;
uint8_t properties;
uint16_t valueHandle;
};
-template<typename DeviceType, typename CharacteristicType>
+template<typename DeviceType>
class DefaultBluetoothGattService : public BluetoothGattService {
public:
- DefaultBluetoothGattService(DeviceType &device, const uuid_t uuid, const uint16_t handle,
+ DefaultBluetoothGattService(DeviceType &device, const Uuid uuid, const uint16_t handle,
const uint16_t endGroupHandle)
: device(device), uuid(uuid), handle(handle), endGroupHandle(endGroupHandle) {
}
@@ -122,48 +120,47 @@ public:
endGroupHandle(std::move(o.endGroupHandle)), characteristics(std::move(o.characteristics)) {
}
- virtual ~DefaultBluetoothGattService() {
- }
+ ~DefaultBluetoothGattService() override = default;
- virtual BluetoothDevice &getDevice() const {
+ BluetoothDevice &getDevice() const override {
return device;
}
- virtual uuid_t getUuid() const {
+ Uuid getUuid() const override {
return uuid;
}
- virtual uint16_t getHandle() const {
+ uint16_t getHandle() const override {
return handle;
}
- virtual uint16_t getEndGroupHandle() const {
+ uint16_t getEndGroupHandle() const override {
return endGroupHandle;
}
- virtual vector<shared_ptr<BluetoothGattCharacteristic>> getCharacteristics() const {
+ vector<shared_ptr<BluetoothGattCharacteristic>> getCharacteristics() const override {
vector<shared_ptr<BluetoothGattCharacteristic>> cs(characteristics.size());
std::copy(begin(characteristics), end(characteristics), begin(cs));
return cs;
}
- virtual void addCharacteristic(shared_ptr<CharacteristicType> &&characteristic) {
+ virtual void addCharacteristic(shared_ptr<BluetoothGattCharacteristic> &&characteristic) {
characteristics.emplace_back(characteristic);
}
- virtual o<shared_ptr<BluetoothGattCharacteristic>> findCharacteristic(uuid_t uuid) {
+ o<shared_ptr<BluetoothGattCharacteristic>> findCharacteristic(Uuid uuid) override {
for (auto &c: characteristics) {
- if (memcmp(c->getUuid().data, uuid.data, 16) == 0) {
- return o<shared_ptr<BluetoothGattCharacteristic>>(c);
+ if (c->getUuid() == uuid) {
+ return {c};
}
}
- return o<shared_ptr<BluetoothGattCharacteristic>>();
+ return {};
}
protected:
DeviceType &device;
- const uuid_t uuid;
+ const Uuid uuid;
const uint16_t handle;
const uint16_t endGroupHandle;
vector<shared_ptr<BluetoothGattCharacteristic>> characteristics;
@@ -172,7 +169,7 @@ protected:
template<class _D, class _S>
class DefaultBluetoothGatt : protected LogSetup, public BluetoothGatt {
public:
- virtual _D &getDevice() const {
+ _D &getDevice() const override {
return device;
}
@@ -180,15 +177,15 @@ public:
// return CollectionImpl<BluetoothGattService, vector<_S>>(services);
// }
- virtual vector<shared_ptr<BluetoothGattService>> getServices() const {
+ vector<shared_ptr<BluetoothGattService>> getServices() const override {
vector<shared_ptr<BluetoothGattService>> ss(services.size());
std::copy(begin(services), end(services), begin(ss));
return ss;
}
- virtual o <BluetoothGattServicePtr> findService(uuid_t uuid) {
+ o <BluetoothGattServicePtr> findService(Uuid uuid) override {
for (auto &s: services) {
- if (memcmp(s->getUuid().data, uuid.data, 16) == 0) {
+ if (s->getUuid() == uuid) {
return o<shared_ptr<BluetoothGattService>>(s);
}
}
@@ -201,12 +198,10 @@ public:
}
protected:
- DefaultBluetoothGatt(_D &device) : LogSetup("BluetoothGatt"), device(device) {
+ explicit DefaultBluetoothGatt(_D &device) : LogSetup("BluetoothGatt"), device(device) {
}
- virtual ~DefaultBluetoothGatt() {
-// removeServices();
- }
+ ~DefaultBluetoothGatt() override = default;
void removeServices() {
// for (auto s: services) {
@@ -223,11 +218,11 @@ template<class A>
class DefaultBluetoothDevice : protected LogSetup, public BluetoothDevice {
public:
- virtual Mac const &getMac() override {
+ Mac const &getMac() override {
return mac;
}
- virtual A &getAdapter() override {
+ A &getAdapter() override {
return adapter;
}
@@ -240,7 +235,7 @@ protected:
LogSetup("BluetoothDevice"), adapter(std::move(o.adapter)), mac(std::move(o.mac)) {
}
- virtual ~DefaultBluetoothDevice() {
+ ~DefaultBluetoothDevice() override {
removeServices();
}
@@ -259,7 +254,7 @@ protected:
class DefaultBluetoothAdapter : protected LogSetup, public BluetoothAdapter {
public:
protected:
- DefaultBluetoothAdapter(Mac &mac) :
+ explicit DefaultBluetoothAdapter(Mac &mac) :
LogSetup("BluetoothAdapter"), mac(mac) {
}
diff --git a/ble/LinuxBluetooth.cpp b/ble/LinuxBluetooth.cpp
index d4073d1..7e7c9dc 100644
--- a/ble/LinuxBluetooth.cpp
+++ b/ble/LinuxBluetooth.cpp
@@ -28,9 +28,9 @@ class LinuxBluetoothAdapter;
class LinuxBluetoothManager;
-class LinuxBluetoothGattService : public DefaultBluetoothGattService<LinuxBluetoothDevice, DefaultBluetoothGattCharacteristic> {
+class LinuxBluetoothGattService : public DefaultBluetoothGattService<LinuxBluetoothDevice> {
public:
- LinuxBluetoothGattService(LinuxBluetoothDevice &device, const uuid_t uuid, const uint16_t handle,
+ LinuxBluetoothGattService(LinuxBluetoothDevice &device, const Uuid uuid, const uint16_t handle,
const uint16_t endGroupHandle) : DefaultBluetoothGattService(device, uuid, handle, endGroupHandle) {
};
@@ -41,7 +41,7 @@ class LinuxBluetoothAdapter final : public DefaultBluetoothAdapter {
public:
LinuxBluetoothAdapter(int hciDeviceId, Mac &mac);
- ~LinuxBluetoothAdapter();
+ ~LinuxBluetoothAdapter() override;
LinuxBluetoothAdapter(const LinuxBluetoothAdapter &) = delete;
@@ -67,9 +67,9 @@ private:
class LinuxBluetoothDevice final : public DefaultBluetoothDevice<LinuxBluetoothAdapter>,
public std::enable_shared_from_this<LinuxBluetoothDevice> {
public:
- LinuxBluetoothDevice(LinuxBluetoothAdapter &adapter, Mac &mac);
+ explicit LinuxBluetoothDevice(LinuxBluetoothAdapter &adapter, Mac &mac);
- virtual ~LinuxBluetoothDevice();
+ ~LinuxBluetoothDevice() override;
LinuxBluetoothDevice(const LinuxBluetoothDevice &) = delete;
@@ -83,9 +83,9 @@ private:
class LinuxBluetoothGatt final : public DefaultBluetoothGatt<LinuxBluetoothDevice, LinuxBluetoothGattService> {
public:
- LinuxBluetoothGatt(LinuxBluetoothDevice &device);
+ explicit LinuxBluetoothGatt(LinuxBluetoothDevice &device);
- ~LinuxBluetoothGatt();
+ ~LinuxBluetoothGatt() override;
LinuxBluetoothGatt(const LinuxBluetoothGatt&) = delete;
@@ -110,6 +110,7 @@ private:
ByteBuffer writeAndRead(ByteBuffer &out, shared_ptr<uint8_t> buffer, size_t size);
+
int l2cap;
};
@@ -124,7 +125,7 @@ string errnoAsString() {
// -----------------------------------------------------------------------
Mac parseMac(bdaddr_t &a) {
- return Mac(a.b[5], a.b[4], a.b[3], a.b[2], a.b[1], a.b[0]);
+ return Mac{a.b[5], a.b[4], a.b[3], a.b[2], a.b[1], a.b[0]};
}
// -----------------------------------------------------------------------
@@ -137,16 +138,13 @@ LinuxBluetoothDevice::LinuxBluetoothDevice(LinuxBluetoothAdapter &adapter, Mac &
LinuxBluetoothDevice::~LinuxBluetoothDevice() {
LOG_DEBUG("Closing device " << mac.str());
- if (gatt) {
- delete gatt;
- }
+
+ delete gatt;
};
shared_ptr<BluetoothGatt> LinuxBluetoothDevice::connectGatt() {
// Make sure that we close the old connection and create a new one when the user asks for it.
- if (gatt) {
- delete gatt;
- }
+ delete gatt;
gatt = new LinuxBluetoothGatt(*this);
@@ -158,7 +156,7 @@ shared_ptr<BluetoothGatt> LinuxBluetoothDevice::connectGatt() {
// -----------------------------------------------------------------------
LinuxBluetoothGatt::LinuxBluetoothGatt(LinuxBluetoothDevice &device) :
- DefaultBluetoothGatt(device) {
+ DefaultBluetoothGatt(device), l2cap() {
connect();
}
@@ -171,7 +169,7 @@ bool LinuxBluetoothGatt::isConnected() const {
}
void LinuxBluetoothGatt::connect() {
- struct sockaddr_l2 addr;
+ struct sockaddr_l2 addr{};
LOG_DEBUG("connect: mac=" << device.getMac().str());
@@ -191,7 +189,7 @@ void LinuxBluetoothGatt::connect() {
throw BluetoothException(&device, "bind(): " + errnoAsString());
}
- struct bt_security btsec;
+ struct bt_security btsec{};
memset(&btsec, 0, sizeof(btsec));
btsec.level = BT_SECURITY_LOW;
if (setsockopt(l2cap, SOL_BLUETOOTH, BT_SECURITY, &btsec, sizeof(btsec)) != 0) {
@@ -225,40 +223,21 @@ void LinuxBluetoothGatt::disconnect() {
close(l2cap);
}
-uuid_t readUuid(BluetoothDevice *device, const ByteBuffer &bytes) {
+Uuid readUuid(BluetoothDevice *device, const ByteBuffer &bytes) {
size_t bytesLeft = bytes.getBytesLeft();
- uuid_t u;
-
if (bytesLeft == 2) {
uint8_t bs[16] = BLUETOOTH_UUID_INITIALIZER;
bs[2] = bytes.get8(1);
bs[3] = bytes.get8(0);
- memcpy(&u, bs, 16);
+
+ return Uuid(bs);
} else if (bytesLeft == 16) {
- uint8_t bs[16];
- bs[15] = bytes.get8(0);
- bs[14] = bytes.get8(1);
- bs[13] = bytes.get8(2);
- bs[12] = bytes.get8(3);
- bs[11] = bytes.get8(4);
- bs[10] = bytes.get8(5);
- bs[9] = bytes.get8(6);
- bs[8] = bytes.get8(7);
- bs[7] = bytes.get8(8);
- bs[6] = bytes.get8(9);
- bs[5] = bytes.get8(10);
- bs[4] = bytes.get8(11);
- bs[3] = bytes.get8(12);
- bs[2] = bytes.get8(13);
- bs[1] = bytes.get8(14);
- bs[0] = bytes.get8(15);
- memcpy(&u, bs, 16);
+ return {bytes.get8(0), bytes.get8(1), bytes.get8(2), bytes.get8(3), bytes.get8(4), bytes.get8(5), bytes.get8(6), bytes.get8(7),
+ bytes.get8(8), bytes.get8(9), bytes.get8(10), bytes.get8(11), bytes.get8(12), bytes.get8(13), bytes.get8(14), bytes.get8(15)};
} else {
throw BluetoothException(device, "Unexpected bytes left: " + to_string(bytesLeft));
}
-
- return u;
}
void LinuxBluetoothGatt::writeValue(const BluetoothGattCharacteristicPtr &c, const ByteBuffer &bytes) {
@@ -302,7 +281,7 @@ void LinuxBluetoothGatt::discoverServices() {
vector<AttributeData> values = discoverServices(startHandle);
// Shouldn't happen, but you never know.
- if (values.size() == 0) {
+ if (values.empty()) {
break;
}
@@ -315,7 +294,7 @@ void LinuxBluetoothGatt::discoverServices() {
// ", endGroupHandle: 0x" << hex << setw(4) << setfill('0') << endGroupHandle <<
// ", value: " << data.value.toString();
- uuid_t u = readUuid(&device, data.value);
+ auto u = readUuid(&device, data.value);
addService(make_shared<LinuxBluetoothGattService>(device, u, data.handle, endGroupHandle));
}
@@ -344,7 +323,7 @@ void LinuxBluetoothGatt::discoverServices() {
do {
vector<AttributeData> values = discoverCharacteristics(startHandle, 0xffff);
- if (values.size() == 0) {
+ if (values.empty()) {
break;
}
@@ -360,7 +339,7 @@ void LinuxBluetoothGatt::discoverServices() {
uint8_t properties = c.value.read8();
uint16_t valueHandle = c.value.read16le();
- uuid_t uuid = readUuid(&device, c.value);
+ auto uuid = readUuid(&device, c.value);
// D << "characteristic: handle: " << setw(2) << setfill('0') << hex << (int) c.handle <<
// ", properties: " << setw(2) << setfill('0') << hex << (int) properties <<
@@ -435,7 +414,7 @@ vector<AttributeData> LinuxBluetoothGatt::discoverCharacteristics(uint16_t start
// -----------------------------------------------------------------------
LinuxBluetoothAdapter::LinuxBluetoothAdapter(int hciDeviceId, Mac &mac) : DefaultBluetoothAdapter(mac),
- scanning(false) {
+ scanning(false), hciFilter() {
LOG_DEBUG("hciDeviceId=" << hciDeviceId);
this->hciDeviceId = hciDeviceId;
@@ -466,7 +445,7 @@ LinuxBluetoothAdapter::~LinuxBluetoothAdapter() {
}
void LinuxBluetoothAdapter::startScan() {
- struct hci_dev_info di;
+ struct hci_dev_info di{};
if (hci_devinfo(hciDeviceId, &di) < 0) {
throw BluetoothException(this, "Could not query device info: " + errnoAsString());
@@ -541,11 +520,11 @@ void LinuxBluetoothAdapter::runScan(std::function<void(const shared_ptr<Bluetoot
FD_SET(hciSocket, &rfds);
// Linux can change tv, so it has to be reinitialized
- struct timeval tv;
+ struct timeval tv{};
tv.tv_sec = 1;
tv.tv_usec = 0;
- int selected = select(hciSocket + 1, &rfds, NULL, NULL, &tv);
+ int selected = select(hciSocket + 1, &rfds, nullptr, nullptr, &tv);
if (selected == -1) {
// Someone stopped the scan, so this is no problem
@@ -564,13 +543,13 @@ void LinuxBluetoothAdapter::runScan(std::function<void(const shared_ptr<Bluetoot
unsigned char hciEventBuf[HCI_MAX_EVENT_SIZE];
ssize_t len = read(hciSocket, hciEventBuf, sizeof(hciEventBuf));
- evt_le_meta_event *metaEvent = (evt_le_meta_event *) (hciEventBuf + (1 + HCI_EVENT_HDR_SIZE));
+ auto *metaEvent = (evt_le_meta_event *) (hciEventBuf + (1 + HCI_EVENT_HDR_SIZE));
len -= (1 + HCI_EVENT_HDR_SIZE);
LOG_DEBUG("metaEvent->subevent = " << std::hex << (int) metaEvent->subevent);
if (metaEvent->subevent == EVT_LE_ADVERTISING_REPORT) {
- le_advertising_info *advertisingInfo = (le_advertising_info *) (metaEvent->data + 1);
+ auto *advertisingInfo = (le_advertising_info *) (metaEvent->data + 1);
Mac mac = parseMac(advertisingInfo->bdaddr);
@@ -605,7 +584,7 @@ shared_ptr<BluetoothAdapter> getAdapterImpl(string name) {
throw BluetoothException("Bad device name: " + name);
}
- struct hci_dev_info di;
+ struct hci_dev_info di{};
if (hci_devinfo(hciDevice, &di) < 0) {
throw BluetoothException("Could not query device info: " + errnoAsString());
}
diff --git a/include/ble/Bluetooth.h b/include/ble/Bluetooth.h
index d5875a5..abddc94 100644
--- a/include/ble/Bluetooth.h
+++ b/include/ble/Bluetooth.h
@@ -1,14 +1,15 @@
#ifndef BLUETOOTH_H
#define BLUETOOTH_H
-#include <boost/uuid/uuid.hpp>
#include <experimental/optional>
#include <iosfwd>
+#include <iostream>
#include <stdexcept>
#include <vector>
#include <cstdint>
#include <map>
#include <functional>
+#include <cstring>
#include "ByteBuffer.h"
@@ -19,44 +20,95 @@ using namespace std;
template<typename T>
using o = std::experimental::optional<T>;
-struct SpecUuid {
+struct Uuid {
+ uint8_t value[16];
+
+ explicit Uuid(uint8_t value[16]) noexcept : value() {
+ memcpy(this->value, value, 16);
+ }
+
+ Uuid(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7,
+ uint8_t b8, uint8_t b9, uint8_t b10, uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15) noexcept : value{
+ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15} {}
+
+ bool operator==(const Uuid &other) {
+ return std::memcmp(value, other.value, 16) == 0;
+ }
+
+ bool operator==(const Uuid &other) const {
+ return std::memcmp(value, other.value, 16) == 0;
+ }
+
+ friend std::ostream &operator<<(std::ostream &s, Uuid const &uuid) {
+ auto &v = uuid.value;
+ s << std::hex <<
+ v[0] << v[1] << ":" <<
+ v[2] << v[3] << ":" <<
+ v[4] << v[5] << ":" <<
+ v[6] << v[7] << ":" <<
+ v[8] << v[9] << ":" <<
+ v[10] << v[11] << ":" <<
+ v[12] << v[13] << ":" <<
+ v[14] << v[15] << ":" <<
+ std::endl;
+ return s;
+ }
+
+ static Uuid fromShort(uint8_t b2, uint8_t b3) {
+ return {0x00, 0x00, b2, b3, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ }
+};
+
+struct ShortUuid {
+private:
public:
- SpecUuid(uint16_t value) : value(value) {
+ explicit ShortUuid(uint16_t value) : value(value) {}
+
+ Uuid toLong()
+ {
+ auto b2 = static_cast<uint8_t>(value >> 8);
+ auto b3 = static_cast<uint8_t>(value & 0xff);
+ return Uuid::fromShort(b2, b3);
}
uint16_t value;
};
+
namespace uuids {
-const SpecUuid PRIMARY_SERVICE = SpecUuid(0x2800);
-const SpecUuid SECONDARY_SERVICE = SpecUuid(0x2801);
-const SpecUuid CHARACTERISTIC = SpecUuid(0x2803);
+
+const ShortUuid HealthTermometerService{0x1809};
+const ShortUuid DeviceInformationService{0x180a};
+const ShortUuid BatteryService{0x180f};
+
+const ShortUuid PRIMARY_SERVICE{0x2800};
+const ShortUuid SECONDARY_SERVICE{0x2801};
+const ShortUuid CHARACTERISTIC{0x2803};
+
+const ShortUuid TemperatureMeasurement{0x2A1C};
}
class BluetoothAdapter;
class BluetoothDevice;
+class BluetoothGatt;
+
class BluetoothGattService;
class BluetoothGattCharacteristic;
+typedef shared_ptr<BluetoothGatt> BluetoothGattPtr;
typedef shared_ptr<BluetoothGattCharacteristic> BluetoothGattCharacteristicPtr;
typedef shared_ptr<BluetoothGattService> BluetoothGattServicePtr;
class BluetoothException : public runtime_error {
public:
- BluetoothException(const BluetoothAdapter *adapter, string const &what) :
- runtime_error(what), adapter(adapter), device(nullptr) {
- }
+ BluetoothException(const BluetoothAdapter *adapter, string const &what) : runtime_error(what), adapter(adapter), device(nullptr) {}
- BluetoothException(const BluetoothDevice *device, string const &what) :
- runtime_error(what), adapter(nullptr), device(device) {
- }
+ BluetoothException(const BluetoothDevice *device, string const &what) : runtime_error(what), adapter(nullptr), device(device) {}
- BluetoothException(string const &what) :
- runtime_error(what), adapter(nullptr), device(nullptr) {
- }
+ explicit BluetoothException(string const &what) : runtime_error(what), adapter(nullptr), device(nullptr) {}
const BluetoothAdapter *adapter;
const BluetoothDevice *device;
@@ -64,7 +116,7 @@ public:
class Mac {
public:
- Mac(uint8_t _5, uint8_t _4, uint8_t _3, uint8_t _2, uint8_t _1, uint8_t _0) {
+ explicit Mac(uint8_t _5, uint8_t _4, uint8_t _3, uint8_t _2, uint8_t _1, uint8_t _0) : bytes() {
bytes[5] = _5;
bytes[4] = _4;
bytes[3] = _3;
@@ -105,14 +157,13 @@ public:
class BluetoothGattCharacteristic {
public:
- virtual ~BluetoothGattCharacteristic() {
- };
+ virtual ~BluetoothGattCharacteristic() = default;
virtual BluetoothGattServicePtr getService() const = 0;
virtual uint16_t getHandle() const = 0;
- virtual const boost::uuids::uuid getUuid() const = 0;
+ virtual const Uuid getUuid() const = 0;
virtual uint8_t getProperties() const = 0;
@@ -121,12 +172,11 @@ public:
class BluetoothGattService {
public:
- virtual ~BluetoothGattService() {
- };
+ virtual ~BluetoothGattService() = default;
virtual BluetoothDevice &getDevice() const = 0;
- virtual boost::uuids::uuid getUuid() const = 0;
+ virtual Uuid getUuid() const = 0;
virtual uint16_t getHandle() const = 0;
@@ -134,7 +184,11 @@ public:
virtual vector<shared_ptr<BluetoothGattCharacteristic>> getCharacteristics() const = 0;
- virtual o<BluetoothGattCharacteristicPtr> findCharacteristic(boost::uuids::uuid uuid) = 0;
+ virtual o<BluetoothGattCharacteristicPtr> findCharacteristic(Uuid uuid) = 0;
+
+ o<BluetoothGattCharacteristicPtr> findCharacteristic(ShortUuid uuid) {
+ return findCharacteristic(uuid.toLong());
+ };
};
class BluetoothGatt {
@@ -160,7 +214,11 @@ public:
virtual vector<shared_ptr<BluetoothGattService>> getServices() const = 0;
- virtual o<BluetoothGattServicePtr> findService(boost::uuids::uuid uuid) = 0;
+ virtual o<BluetoothGattServicePtr> findService(Uuid uuid) = 0;
+
+ o<BluetoothGattServicePtr> findService(ShortUuid uuid) {
+ return findService(uuid.toLong());
+ }
};
class BluetoothDevice {
@@ -211,24 +269,47 @@ private:
map<string, shared_ptr<BluetoothAdapter>> adapters;
};
+/**
+ * BLUETOOTH SPECIFICATION Version 4.0 [Vol 3] - Attribute Protocol (ATT) - 3.4.8 Attribute Opcode Summary
+ * Table 3.37
+ */
enum AttPduType {
- ERROR = 0x00,
- INVALID_HANDLE = 0x01,
+ ERROR = 0x01,
+ EXCHANGE_MTU_REQ = 0x02,
+ EXCHANGE_MTU_RES = 0x03,
+ FIND_INFORMATION_REQ = 0x04,
+ FIND_INFORMATION_RES = 0x05,
+ FIND_BY_TYPE_VALUE_REQ = 0x06,
+ FIND_BY_TYPE_VALUE_RES = 0x07,
READ_BY_TYPE_REQ = 0x08,
READ_BY_TYPE_RES = 0x09,
READ_REQ = 0x0a,
READ_RES = 0x0b,
+ READ_BLOB_REQ = 0x0c,
+ READ_BLOB_RES = 0x0d,
+ READ_MULTIPLE_REQ = 0x0e,
+ READ_MULTIPLE_RES = 0x0f,
READ_BY_GROUP_TYPE_REQ = 0x10,
READ_BY_GROUP_TYPE_RES = 0x11,
WRITE_REQ = 0x12,
WRITE_RES = 0x13,
+
+ WRITE_CMD = 0x52,
+ PREPARE_WRITE_REQ = 0x16,
+ PREPARE_WRITE_RES = 0x17,
+ EXECUTE_WRITE_REQ = 0x18,
+ EXECUTE_WRITE_RES = 0x19,
+ HANDLE_VALUE_NOTIFICATION = 0x1b,
+ HANDLE_VALUE_INDICATION = 0x1d,
+ HANDLE_VALUE_CONFIRMATION = 0x1e,
+ SIGNED_WRITE_COMMAND = 0xd2,
};
class AttributeData;
class AttPdu {
public:
- AttPdu(ByteBuffer &bytes);
+ explicit AttPdu(ByteBuffer &bytes);
AttPdu(ByteBuffer &bytes, AttPduType type);
@@ -238,13 +319,15 @@ public:
static vector<AttributeData> parseReadByType(ByteBuffer &bytes);
+ static uint16_t parseExchangeMtuReq(ByteBuffer &bytes);
+
static void parseRead(ByteBuffer &bytes);
static void parseWrite(ByteBuffer &bytes);
- static void makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, SpecUuid uuid);
+ static void makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, ShortUuid uuid);
- static void makeReadByType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, SpecUuid uuid);
+ static void makeReadByType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, ShortUuid uuid);
static void makeRead(ByteBuffer &bytes, uint16_t handle);
@@ -271,7 +354,7 @@ private:
AttributeData(uint16_t handle, ByteBuffer value);
};
-boost::uuids::uuid makeUuid(const boost::uuids::uuid base, uint8_t a, uint8_t b);
+Uuid makeUuid(const Uuid& base, uint8_t a, uint8_t b);
}
}