From c83b35d6456c8a77e5b8f6a08c9262122c3cbcfc Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Mon, 19 Nov 2018 22:09:59 +0100 Subject: 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. --- apps/SoilMoisture.cpp | 69 +++++++++++++++++++++------------------- apps/SoilMoisture.h | 2 +- apps/ble-inspect-device.cpp | 2 +- apps/ble-read-characteristic.cpp | 69 +++++++++++++++++++++++++++++++++------- 4 files changed, 97 insertions(+), 45 deletions(-) (limited to 'apps') 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(sm_cmd_code::SM_CMD_GET_SENSOR_COUNT)); } static -ByteBuffer createGetValue(uint8_t sensor) { - return ByteBuffer::alloc(100) // - .write8(static_cast(sm_cmd_code::SM_CMD_GET_VALUE)) // +void createGetValue(ByteBuffer &buffer, uint8_t sensor) { + buffer + .write8(static_cast(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(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(sm_cmd_code::SM_CMD_SET_SENSOR_NAME)) .write8(sensor) .write(reinterpret_cast(name.c_str()), name.length()); } static -ByteBuffer createGetSensorName(uint8_t sensor) { - return ByteBuffer::alloc(100).write8(static_cast(sm_cmd_code::SM_CMD_GET_SENSOR_NAME)).write8(sensor); +void createGetSensorName(ByteBuffer &buffer, uint8_t sensor) { + buffer + .write8(static_cast(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(sm_cmd_code::SM_CMD_SET_UPDATE_INTERVAL)) .write8(sensor) .write8(interval_in_seconds); @@ -93,47 +94,49 @@ SoilMoisture::SoilMoisture(const shared_ptr &gatt, const o temperatureCharacteristic, const o 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 SoilMoisture::readTemperature() { return o(); } - 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 temperatureCharacteristic, const o lightCharacteristic); - ByteBuffer writeAndRead(const BluetoothGattCharacteristicPtr &c, ByteBuffer &requestBytes); + void writeAndRead(const BluetoothGattCharacteristicPtr &c, ByteBuffer &requestBytes); shared_ptr gatt; shared_ptr 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 &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()->required(), "The MAC of the device to inspect"); options("service", po::value()->required(), "The UUID of the service to read"); options("characteristic", po::value()->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 &device, const Uuid &service_uuid, const Uuid &characteristic_uuid) { - cout << "Inspecting device: " << device->getMac().str() << endl; + int with_device(const shared_ptr &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); } -- cgit v1.2.3