From d720fa36ad4768ed1b948a92ba5287c30093fbec Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 26 Jul 2015 18:33:15 +0200 Subject: o Overhaul of the bluetooth code. - Adding support for reading FLOAT (specified in IEEE 11073-20601) values from a bluetooth device. - More shared pointers to help keep track of the object's lifecycle. Makes sure that the connections are released back to Linux, Linux is way to sensitive with crashing applications. o Adding support for reading the temperature sensors from the SoilMoisture device. --- apps/SoilMoisture.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 8 deletions(-) (limited to 'apps/SoilMoisture.cpp') diff --git a/apps/SoilMoisture.cpp b/apps/SoilMoisture.cpp index 1d6888c..88f881a 100644 --- a/apps/SoilMoisture.cpp +++ b/apps/SoilMoisture.cpp @@ -1,4 +1,5 @@ #include "SoilMoisture.h" +#include namespace trygvis { namespace sensor { @@ -9,22 +10,29 @@ namespace sensor { auto trygvis_io_base_uuid = boost::uuids::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}; + 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); using namespace trygvis::bluetooth; +static ByteBuffer createGetSensorCount() { return ByteBuffer::alloc(100) // .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)) // .write16le(sensor); } +static ByteBuffer createSetWarningValue(uint8_t sensor, uint16_t warning_value) { return ByteBuffer::alloc(100) .write8(static_cast(sm_cmd_code::SM_CMD_SET_WARNING_VALUE)) @@ -32,6 +40,7 @@ ByteBuffer createSetWarningValue(uint8_t sensor, uint16_t warning_value) { .write16le(warning_value); } +static ByteBuffer createSetSensorName(uint8_t sensor, string name) { return ByteBuffer::alloc(100) .write8(static_cast(sm_cmd_code::SM_CMD_SET_SENSOR_NAME)) @@ -39,10 +48,12 @@ ByteBuffer createSetSensorName(uint8_t sensor, string name) { .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); } +static ByteBuffer createSetUpdateInterval(uint8_t sensor, uint8_t interval_in_seconds) { return ByteBuffer::alloc(100) .write8(static_cast(sm_cmd_code::SM_CMD_SET_UPDATE_INTERVAL)) @@ -65,13 +76,18 @@ SoilMoisture SoilMoisture::create(shared_ptr gatt) { throw runtime_error("The device is missing the soil moisture characteristic"); } - return SoilMoisture(gatt, *service, *c); + auto temperature = service->findCharacteristic(temperature_characteristic); + + return SoilMoisture(gatt, *service, c.get(), temperature); } -SoilMoisture::SoilMoisture(shared_ptr gatt, BluetoothGattService &s, BluetoothGattCharacteristic &c) - : gatt(std::move(gatt)), s(s), c(c) {} +SoilMoisture::SoilMoisture(const shared_ptr &gatt, BluetoothGattService &s, + const BluetoothGattCharacteristic &soilMoistureCharacteristic, + const o temperatureCharacteristic) + : gatt(gatt), s(s), soilMoistureCharacteristic(soilMoistureCharacteristic), + temperatureCharacteristic(temperatureCharacteristic) {} -ByteBuffer SoilMoisture::writeAndRead(ByteBuffer &requestBytes) { +ByteBuffer SoilMoisture::writeAndRead(const BluetoothGattCharacteristic &c, ByteBuffer &requestBytes) { requestBytes.setCursor(0); uint8_t expectedCode = requestBytes.get8(0); @@ -81,7 +97,7 @@ ByteBuffer SoilMoisture::writeAndRead(ByteBuffer &requestBytes) { auto responseBytes = gatt->readValue(c); if (responseBytes.getSize() < 1) { - throw runtime_error("Unexpected number of bytes read: " + to_string(requestBytes.getSize())); + throw runtime_error("Unexpected number of bytes read: " + to_string(responseBytes.getSize())); } uint8_t actualCode = responseBytes.read8(); @@ -95,13 +111,13 @@ ByteBuffer SoilMoisture::writeAndRead(ByteBuffer &requestBytes) { uint8_t SoilMoisture::getSensorCount() { auto buffer = createGetSensorCount(); - return writeAndRead(buffer).read8(); + return writeAndRead(soilMoistureCharacteristic, buffer).read8(); } uint16_t SoilMoisture::getValue(uint8_t sensor) { auto req = createGetValue(sensor); - auto buffer = writeAndRead(req); + auto buffer = writeAndRead(soilMoistureCharacteristic, req); buffer.read8(); // sensor index return buffer.read16le(); } @@ -109,12 +125,44 @@ uint16_t SoilMoisture::getValue(uint8_t sensor) { string SoilMoisture::getName(uint8_t sensor) { auto req = createGetSensorName(sensor); - auto buffer = writeAndRead(req); + auto buffer = writeAndRead(soilMoistureCharacteristic, req); size_t bytesLeft = buffer.getBytesLeft(); uint8_t bytes[bytesLeft]; buffer.copy(bytes, bytesLeft); return string((char *) bytes, (unsigned long) bytesLeft); } + +bool SoilMoisture::hasTemperatureSensor() { + return temperatureCharacteristic.is_initialized(); +} + +/** + * https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.intermediate_temperature.xml + */ +o SoilMoisture::readTemperature() { + if (!temperatureCharacteristic) { + return o(); + } + + auto &c = temperatureCharacteristic.get(); + + auto responseBytes = gatt->readValue(c); + + if (responseBytes.getSize() < 2) { + throw runtime_error("Unexpected number of bytes read: " + to_string(responseBytes.getSize())); + } + + bitset<8> b0 = responseBytes.read8(); + + bool is_fahrenheit = b0.test(0); + bool has_timestamp = b0.test(1); + bool has_type = b0.test(2); + + double temperature = responseBytes.readFLOAT(); + + return o(temperature); +} + } } -- cgit v1.2.3