#include "SoilMoisture.h" namespace trygvis { 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}; 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); using namespace trygvis::bluetooth; ByteBuffer createGetSensorCount() { return ByteBuffer::alloc(100). write8(static_cast(sm_cmd_code::SM_CMD_GET_SENSOR_COUNT)); } ByteBuffer createGetValue(uint8_t sensor) { return ByteBuffer::alloc(100). write8(static_cast(sm_cmd_code::SM_CMD_GET_VALUE)). write16le(sensor); } ByteBuffer createSetWarningValue(uint8_t sensor, uint16_t warning_value) { return ByteBuffer::alloc(100). write8(static_cast(sm_cmd_code::SM_CMD_SET_WARNING_VALUE)). write8(sensor). write16le(warning_value); } ByteBuffer createSetSensorName(uint8_t sensor, string name) { return ByteBuffer::alloc(100). write8(static_cast(sm_cmd_code::SM_CMD_SET_SENSOR_NAME)). write8(sensor). write(reinterpret_cast(name.c_str()), name.length()); } ByteBuffer createGetSensorName(uint8_t sensor) { return ByteBuffer::alloc(100). write8(static_cast(sm_cmd_code::SM_CMD_GET_SENSOR_NAME)). write8(sensor); } 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)). write8(sensor). write8(interval_in_seconds); } SoilMoisture SoilMoisture::create(BluetoothGatt &gatt) { gatt.discoverServices(); auto service = gatt.findService(soil_moisture_service); if (!service) { throw runtime_error("The device is missing the soil moisture service"); } auto c = service->findCharacteristic(soil_moisture_characteristic); if (!c) { throw runtime_error("The device is missing the soil moisture characteristic"); } return SoilMoisture(gatt, *service, *c); } SoilMoisture::SoilMoisture(BluetoothGatt &gatt, BluetoothGattService &s, BluetoothGattCharacteristic &c) : gatt(gatt), s(s), c(c) { } ByteBuffer SoilMoisture::writeAndRead(ByteBuffer &requestBytes) { requestBytes.setCursor(0); uint8_t expectedCode = requestBytes.get8(0); gatt.writeValue(c, requestBytes); auto responseBytes = gatt.readValue(c); if (responseBytes.getSize() < 1) { throw runtime_error("Unexpected number of bytes read: " + to_string(requestBytes.getSize())); } uint8_t actualCode = responseBytes.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(buffer).read8(); } uint16_t SoilMoisture::getValue(uint8_t sensor) { auto req = createGetValue(sensor); return writeAndRead(req).read16le(); } } }