aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2018-11-19 22:09:59 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2018-11-19 22:09:59 +0100
commitc83b35d6456c8a77e5b8f6a08c9262122c3cbcfc (patch)
tree68230e76666b5ef2a01471fc9d6951a719856662
parent52450ed3034b0ba058ea2c9f9baa2d5f78df6a94 (diff)
downloadble-toys-c83b35d6456c8a77e5b8f6a08c9262122c3cbcfc.tar.gz
ble-toys-c83b35d6456c8a77e5b8f6a08c9262122c3cbcfc.tar.bz2
ble-toys-c83b35d6456c8a77e5b8f6a08c9262122c3cbcfc.tar.xz
ble-toys-c83b35d6456c8a77e5b8f6a08c9262122c3cbcfc.zip
ByteBuffer:
o Reducing silliness, no allocations by ByteBuffer. o Create StaticByteBuffer as a nice one-liner to create a buffer. LinuxBluetooth: methods that want a buffer needs to pass it in, ByteBuffer is not allocating anymore.
-rw-r--r--apps/SoilMoisture.cpp69
-rw-r--r--apps/SoilMoisture.h2
-rw-r--r--apps/ble-inspect-device.cpp2
-rw-r--r--apps/ble-read-characteristic.cpp69
-rw-r--r--ble/ByteBuffer.cpp17
-rw-r--r--ble/LinuxBluetooth.cpp30
-rw-r--r--ble/misc.cpp2
-rw-r--r--include/ble/Bluetooth.h2
-rw-r--r--include/ble/ByteBuffer.h29
9 files changed, 142 insertions, 80 deletions
diff --git a/apps/SoilMoisture.cpp b/apps/SoilMoisture.cpp
index 03aeb00..79f168f 100644
--- a/apps/SoilMoisture.cpp
+++ b/apps/SoilMoisture.cpp
@@ -22,42 +22,43 @@ using namespace trygvis::bluetooth;
using std::to_string;
static
-ByteBuffer createGetSensorCount() {
- return ByteBuffer::alloc(100) //
+void createGetSensorCount(ByteBuffer &buffer) {
+ buffer
.write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_GET_SENSOR_COUNT));
}
static
-ByteBuffer createGetValue(uint8_t sensor) {
- return ByteBuffer::alloc(100) //
- .write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_GET_VALUE)) //
+void createGetValue(ByteBuffer &buffer, uint8_t sensor) {
+ buffer
+ .write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_GET_VALUE))
.write16le(sensor);
}
static
-ByteBuffer createSetWarningValue(uint8_t sensor, uint16_t warning_value) {
- return ByteBuffer::alloc(100)
+void createSetWarningValue(ByteBuffer &buffer, uint8_t sensor, uint16_t warning_value) {
+ buffer
.write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_SET_WARNING_VALUE))
.write8(sensor)
.write16le(warning_value);
}
static
-ByteBuffer createSetSensorName(uint8_t sensor, string name) {
- return ByteBuffer::alloc(100)
+void createSetSensorName(ByteBuffer &buffer, uint8_t sensor, string name) {
+ buffer
.write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_SET_SENSOR_NAME))
.write8(sensor)
.write(reinterpret_cast<const uint8_t *>(name.c_str()), name.length());
}
static
-ByteBuffer createGetSensorName(uint8_t sensor) {
- return ByteBuffer::alloc(100).write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_GET_SENSOR_NAME)).write8(sensor);
+void createGetSensorName(ByteBuffer &buffer, uint8_t sensor) {
+ buffer
+ .write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_GET_SENSOR_NAME)).write8(sensor);
}
static
-ByteBuffer createSetUpdateInterval(uint8_t sensor, uint8_t interval_in_seconds) {
- return ByteBuffer::alloc(100)
+void createSetUpdateInterval(ByteBuffer buffer, uint8_t sensor, uint8_t interval_in_seconds) {
+ buffer
.write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_SET_UPDATE_INTERVAL))
.write8(sensor)
.write8(interval_in_seconds);
@@ -93,47 +94,49 @@ SoilMoisture::SoilMoisture(const shared_ptr<BluetoothGatt> &gatt,
const o<BluetoothGattCharacteristicPtr> temperatureCharacteristic,
const o<BluetoothGattCharacteristicPtr> lightCharacteristic)
: gatt(gatt), s(s), soilMoistureCharacteristic(soilMoistureCharacteristic),
- temperatureCharacteristic(temperatureCharacteristic), lightCharacteristic(lightCharacteristic) { }
+ temperatureCharacteristic(temperatureCharacteristic), lightCharacteristic(lightCharacteristic) {}
-ByteBuffer SoilMoisture::writeAndRead(const BluetoothGattCharacteristicPtr &c, ByteBuffer &requestBytes) {
- requestBytes.setCursor(0);
+void SoilMoisture::writeAndRead(const BluetoothGattCharacteristicPtr &c, ByteBuffer &buffer) {
+ buffer.setCursor(0);
- uint8_t expectedCode = requestBytes.peek8(0);
+ uint8_t expectedCode = buffer.peek8(0);
- gatt->writeValue(c, requestBytes);
+ gatt->writeValue(c, buffer);
- auto responseBytes = gatt->readValue(c);
+ gatt->readValue(c, buffer);
- if (responseBytes.getSize() < 1) {
- throw runtime_error("Unexpected number of bytes read: " + to_string(responseBytes.getSize()));
+ if (buffer.getSize() < 1) {
+ throw runtime_error("Unexpected number of bytes read: " + to_string(buffer.getSize()));
}
- uint8_t actualCode = responseBytes.read8();
+ uint8_t actualCode = buffer.read8();
if (actualCode != expectedCode) {
throw runtime_error("Unexpected response code: " + to_string(actualCode) + ", expected " +
to_string(expectedCode));
}
-
- return responseBytes;
}
uint8_t SoilMoisture::getSensorCount() {
- auto buffer = createGetSensorCount();
- return writeAndRead(soilMoistureCharacteristic, buffer).read8();
+ StaticByteBuffer<100> buffer;
+ createGetSensorCount(buffer);
+ writeAndRead(soilMoistureCharacteristic, buffer);
+ return buffer.read8();
}
uint16_t SoilMoisture::getValue(uint8_t sensor) {
- auto req = createGetValue(sensor);
+ StaticByteBuffer<100> buffer;
+ createGetValue(buffer, sensor);
- auto buffer = writeAndRead(soilMoistureCharacteristic, req);
+ writeAndRead(soilMoistureCharacteristic, buffer);
buffer.read8(); // sensor index
return buffer.read16le();
}
string SoilMoisture::getName(uint8_t sensor) {
- auto req = createGetSensorName(sensor);
+ StaticByteBuffer<100> buffer;
+ createGetSensorName(buffer, sensor);
- auto buffer = writeAndRead(soilMoistureCharacteristic, req);
+ writeAndRead(soilMoistureCharacteristic, buffer);
size_t bytesLeft = buffer.getBytesLeft();
uint8_t bytes[bytesLeft];
buffer.copy(bytes, bytesLeft);
@@ -158,7 +161,8 @@ o<double> SoilMoisture::readTemperature() {
return o<double>();
}
- auto responseBytes = gatt->readValue(*temperatureCharacteristic);
+ StaticByteBuffer<100> responseBytes;
+ gatt->readValue(*temperatureCharacteristic, responseBytes);
if (responseBytes.getSize() < 2) {
throw runtime_error("Unexpected number of bytes read: " + to_string(responseBytes.getSize()));
@@ -180,7 +184,8 @@ void SoilMoisture::setLight(uint8_t light, uint8_t value) {
return;
}
- auto responseBytes = gatt->readValue(*lightCharacteristic);
+ StaticByteBuffer<100> responseBytes;
+ gatt->readValue(*lightCharacteristic, responseBytes);
if (responseBytes.getSize() < 2) {
throw runtime_error("Unexpected number of bytes read: " + to_string(responseBytes.getSize()));
diff --git a/apps/SoilMoisture.h b/apps/SoilMoisture.h
index 499c9f6..3bfd0d8 100644
--- a/apps/SoilMoisture.h
+++ b/apps/SoilMoisture.h
@@ -50,7 +50,7 @@ private:
const o<BluetoothGattCharacteristicPtr> temperatureCharacteristic,
const o<BluetoothGattCharacteristicPtr> lightCharacteristic);
- ByteBuffer writeAndRead(const BluetoothGattCharacteristicPtr &c, ByteBuffer &requestBytes);
+ void writeAndRead(const BluetoothGattCharacteristicPtr &c, ByteBuffer &requestBytes);
shared_ptr<BluetoothGatt> gatt;
shared_ptr<BluetoothGattService> s;
diff --git a/apps/ble-inspect-device.cpp b/apps/ble-inspect-device.cpp
index a06d86a..c07879b 100644
--- a/apps/ble-inspect-device.cpp
+++ b/apps/ble-inspect-device.cpp
@@ -27,7 +27,7 @@ public:
}
void with_device(const shared_ptr<BluetoothDevice> &device) {
- cout << "Inspecting device: " << device->getMac().str() << endl;
+ cout << "Connecting to device: " << device->getMac().str() << endl;
auto gatt = device->connectGatt();
cout << "Connected, discovering services" << endl;
diff --git a/apps/ble-read-characteristic.cpp b/apps/ble-read-characteristic.cpp
index 0aa5fdc..19bbfa3 100644
--- a/apps/ble-read-characteristic.cpp
+++ b/apps/ble-read-characteristic.cpp
@@ -12,24 +12,63 @@ using namespace std;
using namespace trygvis::bluetooth;
using namespace trygvis::apps;
-class ble_inspect_device : public app {
+namespace {
+enum class op {
+ READ, NOTIFY, LISTEN
+};
+
+std::istream &operator>>(std::istream &in, op &op) {
+ std::string token;
+ in >> token;
+ if (token == "read") {
+ op = op::READ;
+ } else if (token == "notify") {
+ op = op::NOTIFY;
+ } else if (token == "listen") {
+ op = op::LISTEN;
+ } else {
+ in.setstate(std::ios_base::failbit);
+ }
+ return in;
+}
+
+std::ostream &operator<<(std::ostream &out, const op op) {
+ if (op == op::READ) {
+ out << "read";
+ } else if (op == op::NOTIFY) {
+ out << "notify";
+ } else if (op == op::LISTEN) {
+ out << "listen";
+ } else {
+ out.setstate(std::ios_base::failbit);
+ }
+ return out;
+}
+}
+
+class ble_read_characteristic : public app {
public:
- ble_inspect_device() : app("ble-inspect-device") {}
+ ble_read_characteristic() : app("ble-read-characteristic") {}
- ~ble_inspect_device() override = default;
+ ~ble_read_characteristic() override = default;
- string adapter_name;
+ string adapter_name = "0";
+ enum op op_mode = op::READ;
void add_options(po::options_description_easy_init &options) override {
- auto adapter_value = po::value<>(&adapter_name)->default_value("0");
+ auto adapter_value = po::value<>(&adapter_name)->default_value(adapter_name);
options("adapter", adapter_value, "Which adapter to use.");
options("device", po::value<string>()->required(), "The MAC of the device to inspect");
options("service", po::value<string>()->required(), "The UUID of the service to read");
options("characteristic", po::value<string>()->required(), "The UUID of the characteristic to read");
+
+ auto mode_value = po::value<>(&op_mode)->default_value(op_mode);
+ options("mode", mode_value, "Operation mode");
}
- int with_device(const shared_ptr<BluetoothDevice> &device, const Uuid &service_uuid, const Uuid &characteristic_uuid) {
- cout << "Inspecting device: " << device->getMac().str() << endl;
+ int with_device(const shared_ptr<BluetoothDevice> &device, const Uuid &service_uuid,
+ const Uuid &characteristic_uuid) {
+ cout << "Connecting to device: " << device->getMac().str() << endl;
auto gatt = device->connectGatt();
cout << "Connected, discovering services" << endl;
@@ -52,7 +91,14 @@ public:
auto characteristic = characteristicO.value();
- gatt->readValue(characteristic);
+ if (op_mode == op::READ) {
+ cout << "Reading data" << endl;
+
+ StaticByteBuffer<100> buf;
+ auto response = gatt->readValue(characteristic, buf);
+
+ cout << "Got data, size=" << response.getSize() << endl;
+ }
return EXIT_SUCCESS;
}
@@ -84,11 +130,12 @@ public:
}
}
};
-}
-}
+
+} // namespace apps
+} // namespace trygvis
int main(int argc, const char *argv[]) {
using namespace trygvis::apps;
- return real_main(new ble_inspect_device(), argc, argv);
+ return real_main(new ble_read_characteristic(), argc, argv);
}
diff --git a/ble/ByteBuffer.cpp b/ble/ByteBuffer.cpp
index 1a294f1..40ba06c 100644
--- a/ble/ByteBuffer.cpp
+++ b/ble/ByteBuffer.cpp
@@ -7,13 +7,8 @@
#include <iostream>
#include <ble/ByteBuffer.h>
-
using namespace std;
-ByteBuffer ByteBuffer::alloc(std::size_t size) {
- return {new uint8_t[size], size};
-}
-
ByteBuffer::ByteBuffer(uint8_t* bytes, size_t size) :
zero(bytes), end_(&bytes[size]), cursor(bytes) {
}
@@ -47,7 +42,7 @@ ByteBuffer &ByteBuffer::write(const ByteBuffer &value) {
ByteBuffer &ByteBuffer::write(const uint8_t *bytes, size_t len) {
assertCanAccessRelative(len);
- memcpy(cursor, bytes, len);
+ std::memcpy(cursor, bytes, len);
cursor += len;
@@ -174,7 +169,13 @@ double ByteBuffer::readFLOAT() {
void ByteBuffer::copy(uint8_t *bytes, size_t length) const {
assertCanAccessRelative(length - 1);
- memcpy(bytes, cursor, length);
+ std::memcpy(bytes, cursor, length);
+}
+
+void ByteBuffer::copy(ByteBuffer& other) const {
+ other.assertCanAccessRelative(getBytesLeft());
+
+ std::memcpy(other.cursor, cursor, getBytesLeft());
}
void ByteBuffer::reset() {
@@ -182,7 +183,7 @@ void ByteBuffer::reset() {
}
ByteBuffer ByteBuffer::view() const {
-// DF << "cursor=" << getCursor() << ", size=" << getSize() << ", new size=" << end_ - cursor << ", cursor=" << (uint64_t) cursor << ", zero=" << (uint64_t) zero;
+// LOG_DEBUG("cursor=" << getCursor() << ", size=" << getSize() << ", new size=" << end_ - cursor << ", cursor=" << (uint64_t) cursor << ", zero=" << (uint64_t) zero);
return {cursor, getBytesLeft()};
}
diff --git a/ble/LinuxBluetooth.cpp b/ble/LinuxBluetooth.cpp
index e567d62..d3fe80b 100644
--- a/ble/LinuxBluetooth.cpp
+++ b/ble/LinuxBluetooth.cpp
@@ -103,7 +103,7 @@ public:
void writeValue(const BluetoothGattCharacteristicPtr &c, const ByteBuffer &bytes) override;
- ByteBuffer readValue(const BluetoothGattCharacteristicPtr &c) override;
+ ByteBuffer readValue(const BluetoothGattCharacteristicPtr &c, ByteBuffer& response) override;
private:
void connect();
@@ -116,7 +116,7 @@ private:
void writeL2cap(ByteBuffer &buffer);
- void writeAndRead(ByteBuffer &buffer);
+ void writeAndRead(const ByteBuffer &buffer, ByteBuffer& response);
AttVariant processAvailableMessages(ByteBuffer &buffer);
@@ -276,28 +276,30 @@ void LinuxBluetoothGatt::writeValue(const BluetoothGattCharacteristicPtr &c, con
AttPdu::makeWrite(buffer, c->getValueHandle(), bytes);
- writeAndRead(buffer);
+ writeAndRead(buffer, buffer);
AttPdu::parseWrite(buffer);
}
-ByteBuffer LinuxBluetoothGatt::readValue(const BluetoothGattCharacteristicPtr &c) {
+ByteBuffer LinuxBluetoothGatt::readValue(const BluetoothGattCharacteristicPtr &c, ByteBuffer& response) {
uint8_t b[mtu];
ByteBuffer buffer{b, mtu};
AttPdu::makeRead(buffer, c->getValueHandle());
- writeAndRead(buffer);
+ writeAndRead(buffer, response);
- AttPdu::parseRead(buffer);
+ auto cursor = response.getCursor();
+ response.setCursor(0);
-// D << "READ response has " + to_string(in.getBytesLeft()) + " bytes";
+ AttPdu::parseRead(response);
- auto response = buffer.view();
+ auto view = response.view(cursor - response.getCursor());
- LOG_DEBUG("Value of characteristic " << c->getUuid() << "=" << response.toString());
+ LOG_DEBUG("READ response has " + to_string(view.getSize()) + " bytes");
+ LOG_DEBUG("Value of characteristic " << c->getUuid() << "=" << view.toString());
- return response;
+ return view;
}
void LinuxBluetoothGatt::discoverServices() {
@@ -383,7 +385,7 @@ void LinuxBluetoothGatt::discoverServices() {
} while (startHandle != 0xffff);
}
-void LinuxBluetoothGatt::writeAndRead(ByteBuffer &buffer) {
+void LinuxBluetoothGatt::writeAndRead(const ByteBuffer &buffer, ByteBuffer& response) {
// LOG_DEBUG("pdu size=" << out.getCursor());
auto to_be_written = buffer.getCursor();
@@ -396,14 +398,14 @@ void LinuxBluetoothGatt::writeAndRead(ByteBuffer &buffer) {
// LOG_DEBUG("written=" << written);
- buffer.reset();
- ssize_t r = read(l2cap, buffer.begin(), buffer.getBytesLeft());
+ ssize_t r = read(l2cap, response.begin(), response.getSize());
if (r == -1) {
throw BluetoothException(&device, "read(): " + errnoAsString());
}
-// LOG_DEBUG("read: " << r << " bytes: " << buffer.toString());
+ LOG_DEBUG("read: " << r << " bytes: " << response.toString());
+ response.setCursor(static_cast<size_t>(r));
}
void LinuxBluetoothGatt::writeL2cap(ByteBuffer &buffer) {
diff --git a/ble/misc.cpp b/ble/misc.cpp
index a8df2cb..a4f4b57 100644
--- a/ble/misc.cpp
+++ b/ble/misc.cpp
@@ -50,7 +50,7 @@ o<Uuid> Uuid::fromString(const std::string &str) {
}
auto tmp = str.substr(i, 2);
- cout << "str=" << tmp << endl;
+ // cout << "str=" << tmp << endl;
unsigned long x = std::stoul(tmp, nullptr, 16);
if (x > std::numeric_limits<uint8_t>::max()) {
diff --git a/include/ble/Bluetooth.h b/include/ble/Bluetooth.h
index 477bd29..d95d843 100644
--- a/include/ble/Bluetooth.h
+++ b/include/ble/Bluetooth.h
@@ -129,7 +129,7 @@ public:
virtual void writeValue(const BluetoothGattCharacteristicPtr &c, const ByteBuffer &bytes) = 0;
- virtual ByteBuffer readValue(const BluetoothGattCharacteristicPtr &c) = 0;
+ virtual ByteBuffer readValue(const BluetoothGattCharacteristicPtr &c, ByteBuffer& response) = 0;
virtual void discoverServices() = 0;
diff --git a/include/ble/ByteBuffer.h b/include/ble/ByteBuffer.h
index 5e904c2..09deca5 100644
--- a/include/ble/ByteBuffer.h
+++ b/include/ble/ByteBuffer.h
@@ -1,13 +1,9 @@
#ifndef BYTE_STREAM_WRAPPER_H
#define BYTE_STREAM_WRAPPER_H
-#include <cstddef>
#include <cstdint>
-#include <cstdlib>
-#include <iosfwd>
#include <memory>
#include <stdexcept>
-#include <math.h>
namespace FLOAT {
static const uint32_t positive_infinity = 0x007FFFFE;
@@ -38,8 +34,6 @@ public:
class ByteBuffer {
public:
- static ByteBuffer alloc(std::size_t capacity);
-
template<size_t N>
explicit ByteBuffer(uint8_t (&bytes)[N]) : zero(bytes), end_(&bytes[N]), cursor(bytes) {}
@@ -58,7 +52,9 @@ public:
}
inline ByteBuffer &setCursor(size_t newCursor) {
- cursor = (uint8_t *) &zero[newCursor];
+ auto tmp = (uint8_t *) &zero[newCursor];
+ assertCanAccessIndex(tmp);
+ cursor = tmp;
return *this;
}
@@ -66,19 +62,19 @@ public:
cursor += length;
}
- inline const uint8_t *cbegin() {
+ inline const uint8_t *cbegin() const {
return zero;
}
- inline const uint8_t *cend() {
+ inline const uint8_t *cend() const {
return end_;
}
- inline uint8_t *begin() {
+ inline uint8_t *begin() const {
return const_cast<uint8_t *>(zero);
}
- inline uint8_t *end() {
+ inline uint8_t *end() const {
return const_cast<uint8_t *>(end_);
}
@@ -120,6 +116,8 @@ public:
void copy(uint8_t *bytes, size_t length) const;
+ void copy(ByteBuffer& other) const;
+
void reset();
/**
@@ -147,4 +145,13 @@ private:
uint8_t *cursor;
};
+template<size_t N>
+class StaticByteBuffer : public ByteBuffer {
+public:
+ StaticByteBuffer() : ByteBuffer(raw) {}
+
+private:
+ uint8_t raw[N] = {};
+};
+
#endif