From f4afc04ee7a085a89ad84ba89344bb50ca9e6e04 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 21 Jun 2015 12:27:48 +0200 Subject: o Trying to make the Bluetooth API more C++ idiomatic, a GATT connection has the same lifecycle as a BluetoothGatt. sm-get-value: o Better error handling. --- apps/sm-get-value.h | 180 +++++++++++++++++++++++++--------------------------- 1 file changed, 85 insertions(+), 95 deletions(-) (limited to 'apps/sm-get-value.h') diff --git a/apps/sm-get-value.h b/apps/sm-get-value.h index 11e797f..4083f8e 100644 --- a/apps/sm-get-value.h +++ b/apps/sm-get-value.h @@ -6,9 +6,11 @@ #include "ble/Bluetooth.h" #include "SoilMoisture.h" #include "trygvis/sensor.h" -#include "json.hpp" #include "apps.h" +namespace trygvis { +namespace apps { + // I'm lazy using namespace std; using namespace std::chrono; @@ -18,92 +20,6 @@ using namespace trygvis::sensor; using namespace trygvis::sensor::io; using json = nlohmann::json; -bool loop; -sample_format_type format; -time_point targetTime; -unsigned int sleepTime; -vector sensors; - -void withConnection(sample_format_type format, BluetoothGatt &gatt) { - SoilMoisture soilMoisture = SoilMoisture::create(gatt); - - const int sensorCount = soilMoisture.getSensorCount(); - - if (sensorCount == 0) { - throw runtime_error("Sensor count is 0"); - } - - // If the user didn't specify any sensors, add all. - if (sensors.size() == 0) { - for (unsigned int i = 0; i < sensorCount; i++) { - sensors.push_back(i); - } - } - - auto mac = gatt.getDevice().getMac(); - - targetTime = system_clock::now(); - - do { - KeyDictionary dict; - auto hostname_key = dict.indexOf("hostname"); - auto device_key = dict.indexOf("device"); - auto sensor_key = dict.indexOf("sensor"); - auto timestamp_key = dict.indexOf("timestamp"); - auto value_key = dict.indexOf("value"); - - auto unique_output_stream = open_sample_output_stream(shared_ptr(&cout, noop_deleter), dict, format); - shared_ptr output_stream{std::move(unique_output_stream)}; - - for (auto sensor : sensors) { - if (sensor >= sensorCount) { - // Ignore invalid sensors - continue; - } - - auto epoch = system_clock::now().time_since_epoch(); - auto timestamp = duration_cast(epoch).count(); - uint16_t value = soilMoisture.getValue((uint8_t) sensor); - - SampleRecord sample(dict); - - sample.set(hostname_key, get_hostname()); - sample.set(device_key, mac.str()); - sample.set(sensor_key, std::to_string(sensor)); - sample.set(timestamp_key, std::to_string(timestamp)); - sample.set(value_key, std::to_string(value)); - - output_stream->write(sample); - -// if (format == sample_format_type::KEY_VALUE) { -// cout << "device=" << device.str() -// << ", sensor=" << to_string(sensor) -// << ", timestamp=" << to_string(timestamp) -// << ", value=" << (int) value << endl; -// } else if (format == sample_format_type::JSON) { -// json j; -// j["device"] = device.str(); -// j["sensor"] = sensor; -// j["timestamp"] = timestamp; -// j["value"] = value; -// cout << j << endl; -// } else if (format == sample_format_type::SQL) { -// cout << "INSERT INTO soil_moisture_sample(device, sensor, timestamp, value) VALUES(" -// << "'" << device.str() << "', " -// << sensor << ", " -// << timestamp << ", " -// << value << ";" << endl; -// } - } - - targetTime = targetTime + seconds(sleepTime); - this_thread::sleep_until(targetTime); - } while (loop); -} - -namespace trygvis { -namespace apps { - class sm_get_value : public app { public: @@ -112,15 +28,21 @@ public: ~sm_get_value() = default; + bool loop; + sample_format_type format; + unsigned int sleepTime; + vector sensors; + void add_options(po::options_description_easy_init &options) override { auto default_sleep = po::value<>(&sleepTime)->default_value(0); + auto default_format = po::value(&format)->default_value(sample_format_type::KEY_VALUE); options ("device", po::value()->required(), "MAC of device to poll") ("sensor", po::value>(&sensors)->multitoken(), "Sensor to poll, defaults to all") - ("sleep", default_sleep, "How long to sleep in seconds between each poll. If not given, it will exit after first poll") - ("format", po::value(&format)->default_value(sample_format_type::KEY_VALUE), - "Output format"); + ("sleep", default_sleep, + "How long to sleep in seconds between each poll. If not given, it will exit after first poll") + ("format", default_format, "Output format"); } int main(app_execution &execution) override { @@ -148,15 +70,21 @@ public: loop = sleepTime > 0; do { - LOG4CPLUS_INFO(execution.logger, "Connecting to device: " + device.getMac().str()); - - auto &gatt = device.connectGatt(); try { + LOG4CPLUS_INFO(execution.logger, "Connecting to device: " + device.getMac().str()); + auto gatt = device.connectGatt(); + withConnection(format, gatt); } catch (runtime_error &e) { - cout << "exception: " << e.what() << endl; + LOG4CPLUS_ERROR(execution.logger, "Exception: " << e.what()); + } + + if (loop) { + LOG4CPLUS_DEBUG(execution.logger, "Sleeping for " + std::to_string(sleepTime) + " seconds after failure."); + + auto targetTime = system_clock::now() + seconds(sleepTime); + this_thread::sleep_until(targetTime); } - gatt.disconnect(); } while (loop); return EXIT_SUCCESS; @@ -168,6 +96,68 @@ public: return EXIT_FAILURE; } } + + void withConnection(sample_format_type format, shared_ptr gatt) { + SoilMoisture soilMoisture = SoilMoisture::create(gatt); + + const int sensorCount = soilMoisture.getSensorCount(); + + if (sensorCount == 0) { + throw runtime_error("Sensor count is 0"); + } + + // If the user didn't specify any sensors, add all. + if (sensors.size() == 0) { + for (unsigned int i = 0; i < sensorCount; i++) { + sensors.push_back(i); + } + } + + auto mac = gatt->getDevice().getMac(); + + KeyDictionary dict; + auto hostname_key = dict.indexOf("hostname"); + auto device_key = dict.indexOf("device"); + auto sensor_key = dict.indexOf("sensor"); + auto timestamp_key = dict.indexOf("timestamp"); + auto value_key = dict.indexOf("value"); + + time_point targetTime; + targetTime = system_clock::now(); + + do { + auto unique_output_stream = open_sample_output_stream(shared_ptr(&cout, noop_deleter), dict, + format); + shared_ptr output_stream{std::move(unique_output_stream)}; + + auto epoch = system_clock::now().time_since_epoch(); + auto timestamp = duration_cast(epoch).count(); + + for (auto sensor : sensors) { + if (sensor >= sensorCount) { + // Ignore invalid sensors + continue; + } + + uint16_t value = soilMoisture.getValue((uint8_t) sensor); + + auto sample = SampleRecord(dict) + .set(hostname_key, get_hostname()) + .set(device_key, mac.str()) + .set(sensor_key, std::to_string(sensor)) + .set(timestamp_key, std::to_string(timestamp)) + .set(value_key, std::to_string(value)); + + output_stream->write(sample); + } + + do { + targetTime = targetTime + seconds(sleepTime); + } while (targetTime < system_clock::now()); + + this_thread::sleep_until(targetTime); + } while (loop); + } }; } -- cgit v1.2.3