#include #include #include #include "Bluetooth.h" #include "soil-moisture.h" #include "log.h" using namespace std; using namespace trygvis::bluetooth; typedef boost::uuids::uuid uuid_t; template using o = boost::optional; #define BLUETOOTH_UUID_INITIALIZER \ { \ 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, \ 0x10, 0x00, \ 0x80, 0x00, \ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb \ }; uuid_t trygvis_io_base_uuid = { 0x32, 0xd0, 0x00, 0x00, 0x03, 0x5d, 0x59, 0xc5, 0x70, 0xd3, 0xbc, 0x8e, 0x4a, 0x1f, 0xd8, 0x3f}; uuid_t soil_moisture_service = makeUuid(trygvis_io_base_uuid, 0x00, 0x10); uuid_t soil_moisture_characteristic = makeUuid(trygvis_io_base_uuid, 0x00, 0x11); ByteBuffer &operator<<(ByteBuffer &bytes, const sm_req &req); int main(int argc, char *argv[]) { if (argc != 2) { cerr << "usage: " << argv[0] << " [mac]" << endl; return EXIT_FAILURE; } BluetoothSystem bluetoothSystem; try { Mac mac = Mac::parseMac(argv[1]); auto &adapter = getAdapter(0); auto &device = adapter.getDevice(mac); cout << "Connecting to device: " << device.getMac().str() << endl; auto &gatt = device.connectGatt(); gatt.discoverServices(); auto service = gatt.findService(soil_moisture_service); if (!service) { cout << "The device is missing the soil moisture service" << endl; return EXIT_FAILURE; } auto c = service->findCharacteristic(soil_moisture_characteristic); if (!c) { cout << "The device is missing the soil moisture characteristic" << endl; return EXIT_FAILURE; } sm_req req = { .code = SM_CMD_GET_SENSOR_COUNT, }; auto requestBytes = ByteBuffer::alloc(sizeof(struct sm_req)); requestBytes << req; gatt.writeValue(*c, requestBytes); auto responseBytes = gatt.readValue(*c); gatt.disconnect(); return EXIT_SUCCESS; } catch (std::runtime_error ex) { W << "std::runtime_error: " << ex.what(); return EXIT_FAILURE; } catch (std::exception ex) { W << "std::exception: " << ex.what(); return EXIT_FAILURE; } } ByteBuffer &operator<<(ByteBuffer &bytes, const sm_req &req) { bytes.write8(req.code); switch (req.code) { case SM_CMD_GET_SENSOR_COUNT: return bytes; case SM_CMD_GET_VALUE: return bytes. write8(req.get_value.sensor); case SM_CMD_SET_WARNING_VALUE: return bytes. write8(req.set_warning_value.sensor). write16le(req.set_warning_value.warning_value); case SM_CMD_GET_WARNING_VALUE: return bytes. write8(req.set_warning_value.sensor); case SM_CMD_SET_SENSOR_NAME: return bytes. write8(req.set_sensor_name.sensor). write8(req.set_sensor_name.length). write(req.set_sensor_name.name, req.set_sensor_name.length); case SM_CMD_GET_SENSOR_NAME: return bytes. write8(req.get_sensor_name.sensor); case SM_CMD_SET_UPDATE_INTERVAL: return bytes. write8(req.set_update_interval.sensor). write8(req.set_update_interval.interval_in_seconds); default: throw runtime_error("Unknown code: " + to_string(req.code)); } }