aboutsummaryrefslogtreecommitdiff
path: root/apps/SoilMoisture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'apps/SoilMoisture.cpp')
-rw-r--r--apps/SoilMoisture.cpp64
1 files changed, 56 insertions, 8 deletions
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 <bitset>
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<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)) //
.write16le(sensor);
}
+static
ByteBuffer createSetWarningValue(uint8_t sensor, uint16_t warning_value) {
return ByteBuffer::alloc(100)
.write8(static_cast<uint8_t>(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<uint8_t>(sm_cmd_code::SM_CMD_SET_SENSOR_NAME))
@@ -39,10 +48,12 @@ ByteBuffer createSetSensorName(uint8_t sensor, string name) {
.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);
}
+static
ByteBuffer createSetUpdateInterval(uint8_t sensor, uint8_t interval_in_seconds) {
return ByteBuffer::alloc(100)
.write8(static_cast<uint8_t>(sm_cmd_code::SM_CMD_SET_UPDATE_INTERVAL))
@@ -65,13 +76,18 @@ SoilMoisture SoilMoisture::create(shared_ptr<BluetoothGatt> 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<BluetoothGatt> gatt, BluetoothGattService &s, BluetoothGattCharacteristic &c)
- : gatt(std::move(gatt)), s(s), c(c) {}
+SoilMoisture::SoilMoisture(const shared_ptr<BluetoothGatt> &gatt, BluetoothGattService &s,
+ const BluetoothGattCharacteristic &soilMoistureCharacteristic,
+ const o<const BluetoothGattCharacteristic &> 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<double> SoilMoisture::readTemperature() {
+ if (!temperatureCharacteristic) {
+ return o<double>();
+ }
+
+ 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<double>(temperature);
+}
+
}
}