aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2015-06-21 00:15:04 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2015-06-21 00:15:43 +0200
commitc56840f03cf139d60c6d90b55cf16e70f6ae2bc2 (patch)
treec9f19ab065496ac704fbf855da031ef5643eefa3 /apps
parentd91e500592790f1ef22ebfe921f273a61ff6252f (diff)
downloadble-toys-c56840f03cf139d60c6d90b55cf16e70f6ae2bc2.tar.gz
ble-toys-c56840f03cf139d60c6d90b55cf16e70f6ae2bc2.tar.bz2
ble-toys-c56840f03cf139d60c6d90b55cf16e70f6ae2bc2.tar.xz
ble-toys-c56840f03cf139d60c6d90b55cf16e70f6ae2bc2.zip
o Going all header file based and single-executable to launch all apps.
o Ading CMake magic to generate the launcher
Diffstat (limited to 'apps')
-rw-r--r--apps/CMakeLists.txt59
-rw-r--r--apps/apps.cpp63
-rw-r--r--apps/apps.h40
-rw-r--r--apps/ble-inspect-device.cpp58
-rw-r--r--apps/ble-inspect-device.h79
-rw-r--r--apps/generate.cpp71
-rw-r--r--apps/launcher.cpp94
-rw-r--r--apps/log4cplus-test.cpp50
-rw-r--r--apps/sample-add-timestamp.h (renamed from apps/sample-add-timestamp.cpp)8
-rw-r--r--apps/sample-convert.h (renamed from apps/sample-convert.cpp)7
-rw-r--r--apps/sample-select.h (renamed from apps/sample-select.cpp)7
-rw-r--r--apps/sm-db-insert.cpp78
-rw-r--r--apps/sm-db-insert.h80
-rw-r--r--apps/sm-db-select.cpp82
-rw-r--r--apps/sm-db-select.h81
-rw-r--r--apps/sm-get-value.h (renamed from apps/sm-get-value.cpp)8
-rw-r--r--apps/sm-serial-read-all.h (renamed from apps/sm-serial-read-all.cpp)14
-rw-r--r--apps/sm-serial-read.h (renamed from apps/sm-serial-read.cpp)15
18 files changed, 488 insertions, 406 deletions
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 988a989..c9eea9e 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -1,4 +1,3 @@
-list(APPEND APPS log4cplus-test)
list(APPEND APPS ble-inspect-device)
list(APPEND APPS sample-add-timestamp)
list(APPEND APPS sample-convert)
@@ -9,10 +8,6 @@ list(APPEND APPS sm-get-value)
list(APPEND APPS sm-serial-read)
list(APPEND APPS sm-serial-read-all)
-add_library(trygvis-apps
- SoilMoisture.cpp
- apps.cpp)
-
# Boost
find_package(Boost COMPONENTS regex system program_options REQUIRED)
@@ -34,20 +29,44 @@ if(LOG4CPLUS_LIBRARIES MATCHES NOTFOUND)
message(FATAL_ERROR "Could not find log4cplus library files")
endif()
-include_directories("${PROJECT_SOURCE_DIR}/include")
-include_directories("${PROJECT_SOURCE_DIR}/json/src")
-include_directories("${PROJECT_SOURCE_DIR}/sensor/include")
-include_directories("${LOG4CPLUS_INCLUDE_DIRECTORIES}")
+add_executable(generate generate.cpp)
+
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated)
+
+add_custom_command(
+ OUTPUT generated/apps-list.gen.h
+ COMMAND generate ${CMAKE_CURRENT_BINARY_DIR}/generated/apps-list.gen.h ${APPS}
+ DEPENDS generate ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
+
+foreach(app ${APPS})
+ list(APPEND APPS_SOURCES ${app}.h)
+endforeach()
+
+list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/generated/apps-list.gen.h)
+list(APPEND SOURCES SoilMoisture.cpp SoilMoisture.h)
+list(APPEND SOURCES apps.cpp apps.h)
+
+add_executable(launcher launcher.cpp
+ ${SOURCES}
+ ${APPS_SOURCES})
+target_include_directories(launcher
+ PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/generated
+ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+ PUBLIC "${PROJECT_SOURCE_DIR}/include"
+ PUBLIC "${PROJECT_SOURCE_DIR}/json/src"
+ PUBLIC "${PROJECT_SOURCE_DIR}/sensor/include"
+ PUBLIC "${LOG4CPLUS_INCLUDE_DIRECTORIES}")
+
+target_link_libraries(launcher ble)
+target_link_libraries(launcher trygvis-sensor)
+target_link_libraries(launcher ${Boost_LIBRARIES})
+target_link_libraries(launcher ${BLUEZ_LIBRARIES})
+target_link_libraries(launcher ${PQXX_LIBRARIES})
+target_link_libraries(launcher ${LOG4CPLUS_LIBRARIES})
+target_link_libraries(launcher ${CMAKE_THREAD_LIBS_INIT})
foreach(app ${APPS})
- add_executable(${app} ${app}.cpp)
-
- target_link_libraries(${app} ble)
- target_link_libraries(${app} trygvis-apps)
- target_link_libraries(${app} trygvis-sensor)
- target_link_libraries(${app} ${Boost_LIBRARIES})
- target_link_libraries(${app} ${BLUEZ_LIBRARIES})
- target_link_libraries(${app} ${PQXX_LIBRARIES})
- target_link_libraries(${app} ${LOG4CPLUS_LIBRARIES})
- target_link_libraries(${app} ${CMAKE_THREAD_LIBS_INIT})
-endforeach(app)
+ add_custom_command(
+ TARGET launcher POST_BUILD
+ COMMAND ln -sf launcher ${app})
+endforeach()
diff --git a/apps/apps.cpp b/apps/apps.cpp
index b9ee81c..783c0b0 100644
--- a/apps/apps.cpp
+++ b/apps/apps.cpp
@@ -1,8 +1,4 @@
#include "apps.h"
-#include <log4cplus/logger.h>
-#include <log4cplus/consoleappender.h>
-#include <log4cplus/layout.h>
-#include <log4cplus/configurator.h>
#include <netdb.h>
namespace trygvis {
@@ -12,65 +8,6 @@ using namespace log4cplus;
using namespace std;
namespace po = boost::program_options;
-const po::options_description logging_options() {
- po::options_description desc;
-
- return desc;
-}
-
-void setup_logging(po::variables_map vm) {
- Appender *console = new ConsoleAppender(true, true);
- PatternLayout* layout = new PatternLayout(LOG4CPLUS_TEXT("%-5p %r %-20c %m%n"));
- console->setLayout(auto_ptr<Layout>(layout));
-
- Hierarchy &h = Logger::getDefaultHierarchy();
- h.getRoot().addAppender(SharedAppenderPtr(console));
-}
-
-int launch_app(int argc, char *argv[], app &app) {
- po::options_description all("Options");
-
- auto all_options = all.add_options();
- app.add_options(all_options);
-
- all.add(logging_options());
- app.add_extra_options(all);
-
- po::variables_map vm;
-
- try {
- auto parsed = po::parse_command_line(argc, argv, all);
- po::store(parsed, vm);
-
- po::notify(vm);
-
- auto unrecognized = po::collect_unrecognized(parsed.options, po::include_positional);
-
- if (vm.count("help")) {
- cerr << all << "\n";
- return EXIT_FAILURE;
- }
-
- if (unrecognized.size()) {
- cerr << "Unrecognized option: " << unrecognized.at(0) << "\n";
- return EXIT_FAILURE;
- }
-
- setup_logging(vm);
-
- app_execution execution(all, vm);
-
- return app.main(execution);
- } catch (po::required_option &e) {
- cerr << "Missing required option: " << e.get_option_name() << endl;
- cerr << all << endl;
- return EXIT_FAILURE;
- } catch (po::unknown_option &e) {
- cerr << e.what() << endl;
- return EXIT_FAILURE;
- }
-}
-
std::string get_hostname() {
struct addrinfo hints, *info, *p;
// int gai_result;
diff --git a/apps/apps.h b/apps/apps.h
index 8173c51..7569a9f 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -3,27 +3,53 @@
#include <boost/program_options.hpp>
#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
+#include "json.hpp"
+#include <exception>
namespace trygvis {
namespace apps {
namespace po = boost::program_options;
+using namespace log4cplus;
+
+using json = nlohmann::json;
+
+class missing_key : public std::runtime_error {
+public:
+ missing_key(const json::string_t key) : runtime_error("Missing key: " + key), key(key) {
+ }
+
+ const json::string_t key;
+};
+
+template<typename T>
+T get(json j, std::string key) {
+ auto ref = j[key];
+
+ if (ref.is_null()) {
+ throw missing_key(key);
+ }
+
+ return ref;
+}
class app_execution {
public:
- app_execution(po::options_description desc, po::variables_map vm) : desc(desc), vm(vm) {
+ app_execution(po::options_description desc, po::variables_map vm, Logger logger) : desc(desc), vm(vm), logger(logger) {
}
- po::options_description desc;
- po::variables_map vm;
+ const po::options_description desc;
+ const po::variables_map vm;
+ const log4cplus::Logger logger;
void usage();
};
class app {
public:
- app(std::string app_name): _app_name(app_name), logger(log4cplus::Logger::getInstance(LOG4CPLUS_TEXT(app_name))) {
+ app(std::string app_name) : app_name(app_name) {
}
+
virtual ~app() = default;
virtual void add_options(po::options_description_easy_init &options) {
@@ -34,13 +60,9 @@ public:
virtual int main(app_execution &execution) = 0;
-protected:
- const std::string _app_name;
- const log4cplus::Logger logger;
+ const std::string app_name;
};
-int launch_app(int argc, char *argv[], app &app);
-
std::string get_hostname();
template<typename T>
diff --git a/apps/ble-inspect-device.cpp b/apps/ble-inspect-device.cpp
deleted file mode 100644
index e4e7113..0000000
--- a/apps/ble-inspect-device.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <exception>
-#include <iostream>
-#include <vector>
-#include <boost/uuid/uuid_io.hpp>
-#include "ble/Bluetooth.h"
-
-using namespace std;
-using namespace trygvis::bluetooth;
-
-void scan_callback(BluetoothDevice &device) {
- cout << "Inspecting device: " << device.getMac().str() << endl;
-
- auto &gatt = device.connectGatt();
-
- gatt.discoverServices();
-
- vector<BluetoothGattService *> services = gatt.getServices();
- cout << "Device has " << services.size() << " services" << endl;
-
- for (auto &s: services) {
- const vector<BluetoothGattCharacteristic *> characteristics = s->getCharacteristics();
-
- cout << "Service: UUID: " << s->getUuid() << ", has " << characteristics.size() << " characteristics" << endl;
-
- for (auto &c: characteristics) {
- cout << "Characteristic: UUID: " << c->getUuid() << ", properties: " << (int) c->getProperties() << endl;
- }
- }
-
- gatt.disconnect();
-}
-
-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]);
-
- BluetoothAdapter &adapter = getAdapter(0);
-
- BluetoothDevice &device = adapter.getDevice(mac);
-
- scan_callback(device);
-
- return EXIT_SUCCESS;
- } catch (std::runtime_error ex) {
- cout << "std::runtime_error: " << ex.what() << endl;
- return EXIT_FAILURE;
- } catch (std::exception ex) {
- cout << "std::exception: " << ex.what() << endl;
- return EXIT_FAILURE;
- }
-}
diff --git a/apps/ble-inspect-device.h b/apps/ble-inspect-device.h
new file mode 100644
index 0000000..bf79b2c
--- /dev/null
+++ b/apps/ble-inspect-device.h
@@ -0,0 +1,79 @@
+#include <exception>
+#include <iostream>
+#include <vector>
+#include <boost/uuid/uuid_io.hpp>
+#include "ble/Bluetooth.h"
+#include "apps.h"
+
+namespace trygvis {
+namespace apps {
+
+using namespace std;
+using namespace trygvis::bluetooth;
+using namespace trygvis::apps;
+
+class ble_inspect_device : public app {
+
+public:
+ ble_inspect_device() : app("ble-inspect-device") {
+ }
+
+ ~ble_inspect_device() = default;
+
+ void add_options(po::options_description_easy_init &options) override {
+ options
+ ("device", po::value<string>()->required(), "The MAC of the device to inspect");
+ }
+
+ void scan_callback(BluetoothDevice &device) {
+ cout << "Inspecting device: " << device.getMac().str() << endl;
+
+ auto &gatt = device.connectGatt();
+
+ gatt.discoverServices();
+
+ vector < BluetoothGattService * > services = gatt.getServices();
+ cout << "Device has " << services.size() << " services" << endl;
+
+ for (auto &s: services) {
+ const vector<BluetoothGattCharacteristic *> characteristics = s->getCharacteristics();
+
+ cout << "Service: UUID: " << s->getUuid() << ", has " << characteristics.size() << " characteristics" <<
+ endl;
+
+ for (auto &c: characteristics) {
+ cout << "Characteristic: UUID: " << c->getUuid() << ", properties: " << (int) c->getProperties() <<
+ endl;
+ }
+ }
+
+ gatt.disconnect();
+ }
+
+ int main(app_execution &execution) override {
+ string mac_str = execution.vm["mac"].as<string>();
+
+ BluetoothSystem bluetoothSystem;
+
+ try {
+ Mac mac = Mac::parseMac(mac_str);
+
+ BluetoothAdapter &adapter = getAdapter(0);
+
+ BluetoothDevice &device = adapter.getDevice(mac);
+
+ scan_callback(device);
+
+ return EXIT_SUCCESS;
+ } catch (std::runtime_error ex) {
+ cout << "std::runtime_error: " << ex.what() << endl;
+ return EXIT_FAILURE;
+ } catch (std::exception ex) {
+ cout << "std::exception: " << ex.what() << endl;
+ return EXIT_FAILURE;
+ }
+ }
+};
+
+}
+}
diff --git a/apps/generate.cpp b/apps/generate.cpp
new file mode 100644
index 0000000..f0bf0fd
--- /dev/null
+++ b/apps/generate.cpp
@@ -0,0 +1,71 @@
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <regex>
+
+using namespace std;
+
+int main(int argc, char *argv[]) {
+
+ cout << "Generating " << argv[1] << endl;
+
+ ofstream out;
+
+ out.open(argv[1], ofstream::out);
+
+ if (!out.is_open()) {
+ return EXIT_FAILURE;
+ }
+
+ out << "#pragma once" << endl
+ << "#include <string>" << endl
+ << endl;
+
+ vector<pair<string, string>> apps;
+
+ regex r("-");
+ for (int i = 2; i < argc; i++) {
+ string app_name = argv[i];
+ stringstream buf;
+
+ regex_replace(ostream_iterator<char>(buf),
+ app_name.begin(), app_name.end(),
+ r, "_");
+ string class_name = buf.str();
+
+ apps.emplace_back(make_pair(app_name, class_name));
+ }
+
+ for_each(begin(apps), end(apps), [&](pair<string, string> pair) {
+// out << "class " << pair.second << ";" << endl;
+ out << "#include \"" << pair.first << ".h\"" << endl;
+ });
+ out << endl;
+
+ bool first = true;
+
+ out << "template<typename App>" << endl
+ << "int launch_app(int argc, const char *argv[]);"
+ << endl;
+
+ out << "int launch(const std::string app_name, int argc, const char *argv[]) {" << endl;
+
+ for_each(begin(apps), end(apps), [&](auto pair) {
+ out << " ";
+ if (!first) {
+ out << "} else ";
+ } else {
+ first = false;
+ }
+
+ out << "if (app_name == \"" << pair.first << "\") {" << endl
+ << " return launch_app<" << pair.second << ">(argc, argv);" << endl;
+ });
+
+ out << " } else {" << endl
+ << " return EXIT_FAILURE;" << endl
+ << " }" << endl
+ << "}" << endl;
+
+ return EXIT_SUCCESS;
+}
diff --git a/apps/launcher.cpp b/apps/launcher.cpp
new file mode 100644
index 0000000..dc31abd
--- /dev/null
+++ b/apps/launcher.cpp
@@ -0,0 +1,94 @@
+#include "apps.h"
+#include "apps-list.gen.h"
+#include <log4cplus/consoleappender.h>
+#include <log4cplus/configurator.h>
+#include <boost/algorithm/string/predicate.hpp>
+
+using namespace trygvis::apps;
+using namespace std;
+
+const po::options_description logging_options() {
+ po::options_description desc;
+
+ return desc;
+}
+
+void setup_logging(po::variables_map vm) {
+ Appender *console = new ConsoleAppender(true, true);
+ PatternLayout *layout = new PatternLayout(LOG4CPLUS_TEXT("%-5p" /*" %6r"*/ " %-20c %m%n"));
+ console->setLayout(auto_ptr<Layout>(layout));
+
+ Hierarchy &h = Logger::getDefaultHierarchy();
+ h.getRoot().addAppender(SharedAppenderPtr(console));
+}
+
+template<typename App>
+int launch_app(int argc, const char *argv[]) {
+ App app;
+
+ po::options_description all("Options");
+
+ auto all_options = all.add_options();
+ app.add_options(all_options);
+
+ all.add(logging_options());
+ app.add_extra_options(all);
+
+ po::variables_map vm;
+
+ try {
+ auto parsed = po::parse_command_line(argc, argv, all);
+ po::store(parsed, vm);
+
+ po::notify(vm);
+
+ auto unrecognized = po::collect_unrecognized(parsed.options, po::include_positional);
+
+ if (vm.count("help")) {
+ cerr << all << "\n";
+ return EXIT_FAILURE;
+ }
+
+ if (unrecognized.size()) {
+ cerr << "Unrecognized option: " << unrecognized.at(0) << "\n";
+ return EXIT_FAILURE;
+ }
+
+ setup_logging(vm);
+
+ Logger logger = Logger::getInstance(LOG4CPLUS_TEXT(app.app_name));
+
+ app_execution execution(all, vm, logger);
+
+ return app.main(execution);
+ } catch (po::required_option &e) {
+ cerr << "Missing required option: " << e.get_option_name() << endl;
+ cerr << all << endl;
+ return EXIT_FAILURE;
+ } catch (po::unknown_option &e) {
+ cerr << e.what() << endl;
+ return EXIT_FAILURE;
+ }
+}
+
+int main(int argc, const char *argv[]) {
+ if (argc == 0) {
+ return EXIT_FAILURE;
+ }
+
+ string app_name;
+ if (boost::ends_with(argv[0], "launcher")) {
+ if (argc <= 1) {
+ cerr << "Missing required argument: app" << endl;
+ return EXIT_FAILURE;
+ }
+
+ app_name = argv[1];
+ --argc;
+ argv = &argv[1];
+ } else {
+ app_name = argv[0];
+ }
+
+ return launch(app_name, argc, argv);
+}
diff --git a/apps/log4cplus-test.cpp b/apps/log4cplus-test.cpp
deleted file mode 100644
index 39d9884..0000000
--- a/apps/log4cplus-test.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <log4cplus/logger.h>
-#include <log4cplus/configurator.h>
-#include <iomanip>
-
-namespace trygvis {
-using namespace log4cplus;
-using namespace std;
-
-class LogSetup {
-public:
- LogSetup(string name) : logger(Logger::getInstance(LOG4CPLUS_TEXT(name))) {
- }
-
-protected:
- Logger logger;
-};
-
-class MyService : LogSetup {
-public:
- MyService() : LogSetup("trygvis.MyService") {
- }
-
- void launchMissiles() {
- LOG4CPLUS_DEBUG(logger, "some debug message");
- LOG4CPLUS_INFO(logger, "some info message");
- LOG4CPLUS_WARN(logger, "some warning message");
- }
-};
-}
-
-using namespace std;
-using namespace log4cplus;
-using namespace trygvis;
-
-int main() {
- BasicConfigurator config;
- config.configure();
-
- cout << "Hello world!" << endl;
-
- Logger l = Logger::getRoot();
-
- l.setLogLevel(INFO_LOG_LEVEL);
-
- MyService myService;
-
- myService.launchMissiles();
-
- return EXIT_SUCCESS;
-}
diff --git a/apps/sample-add-timestamp.cpp b/apps/sample-add-timestamp.h
index 22d81a6..13d2216 100644
--- a/apps/sample-add-timestamp.cpp
+++ b/apps/sample-add-timestamp.h
@@ -52,6 +52,7 @@ private:
public:
sample_add_timestamp() : app("sample-add-timestamp") {
}
+
~sample_add_timestamp() = default;
void add_options(po::options_description_easy_init &options) override {
@@ -96,10 +97,3 @@ public:
}
}
-
-using namespace trygvis::apps;
-
-int main(int argc, char *argv[]) {
- sample_add_timestamp app;
- return launch_app(argc, argv, app);
-}
diff --git a/apps/sample-convert.cpp b/apps/sample-convert.h
index 2dc34b3..0b805be 100644
--- a/apps/sample-convert.cpp
+++ b/apps/sample-convert.h
@@ -119,10 +119,3 @@ public:
}
}
-
-using namespace trygvis::apps;
-
-int main(int argc, char *argv[]) {
- sample_convert app;
- return launch_app(argc, argv, app);
-}
diff --git a/apps/sample-select.cpp b/apps/sample-select.h
index c4304da..2701338 100644
--- a/apps/sample-select.cpp
+++ b/apps/sample-select.h
@@ -119,10 +119,3 @@ public:
}
}
-
-using namespace trygvis::apps;
-
-int main(int argc, char *argv[]) {
- sample_select app;
- return launch_app(argc, argv, app);
-}
diff --git a/apps/sm-db-insert.cpp b/apps/sm-db-insert.cpp
deleted file mode 100644
index a3ebb76..0000000
--- a/apps/sm-db-insert.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <boost/optional.hpp>
-#include <boost/lexical_cast.hpp>
-#include <pqxx/connection.hxx>
-#include <pqxx/transaction.hxx>
-#include "json.hpp"
-#include <fstream>
-
-template<class T>
-using o = boost::optional<T>;
-using namespace std;
-using json = nlohmann::json;
-
-class missing_key : public runtime_error {
-public:
- missing_key(const json::string_t key) : runtime_error("Missing key: " + key), key(key) {
- }
-
- const json::string_t key;
-};
-
-template<typename T>
-T get(json j, string key) {
- auto ref = j[key];
-
- if (ref.is_null()) {
- throw missing_key(key);
- }
-
- return ref;
-}
-
-int main(int argc, char *argv[]) {
- cout << "reading from " << argv[1] << endl;
-
- fstream f(argv[1]);
-
- json j;
-
- j << f;
-
- pqxx::connection c("host=localhost dbname=soil-moisture");
-
- pqxx::work work(c);
-
- string mac = j["mac"]; // "aa:bb:cc:dd:ee:ff";
-
- auto rs = work.parameterized("select id from soil_moisture_device where mac=$1")(mac).exec();
-
- if (!rs.size()) {
- cout << "New device: " << mac << endl;
-
- rs = work.parameterized("insert into soil_moisture_device(mac) values($1) returning id")(mac).exec();
- }
-
- auto deviceId = rs.begin()["id"].as<int>();
-
- int sensor = j["sensor"];
-
- rs = work.parameterized("select id from soil_moisture_sensor where device=$1 and sensor=$2")(deviceId)(sensor).exec();
-
- if (!rs.size()) {
- cout << "New sensor: " << sensor << endl;
-
- rs = work.parameterized("insert into soil_moisture_sensor(device, sensor) values($1, $2) returning id")(deviceId)(sensor).exec();
- }
- auto sensorId = rs.begin()["id"].as<int>();
-
- unsigned long timestamp = get<unsigned long>(j, "timestamp");
- unsigned int value = get<unsigned int>(j, "value");
-
- work.parameterized("insert into soil_moisture_sample(sensor, timestamp, value) values($1, $2, $3)")(sensorId)(timestamp)(value).exec();
-
- cout << "Sample inserted" << endl;
-
- work.commit();
-
- return EXIT_SUCCESS;
-}
diff --git a/apps/sm-db-insert.h b/apps/sm-db-insert.h
new file mode 100644
index 0000000..b786e41
--- /dev/null
+++ b/apps/sm-db-insert.h
@@ -0,0 +1,80 @@
+#include <boost/optional.hpp>
+#include <boost/lexical_cast.hpp>
+#include <pqxx/connection.hxx>
+#include <pqxx/transaction.hxx>
+#include "json.hpp"
+#include <fstream>
+
+namespace trygvis {
+namespace apps {
+
+template<class T>
+using o = boost::optional<T>;
+using namespace std;
+using json = nlohmann::json;
+
+class sm_db_insert : public app {
+
+public:
+ sm_db_insert() : app("sm-db-insert") {
+ }
+
+ ~sm_db_insert() = default;
+
+ void add_options(po::options_description_easy_init &options) override {
+ options
+ ("file", po::value<string>()->required(), "The file to read");
+ }
+
+ int main(app_execution &execution) override {
+ auto file = execution.vm["file"].as<string>();
+ cout << "reading from " << file << endl;
+
+ fstream f(file);
+
+ json j;
+
+ j << f;
+
+ pqxx::connection c("host=localhost dbname=soil-moisture");
+
+ pqxx::work work(c);
+
+ string mac = j["mac"]; // "aa:bb:cc:dd:ee:ff";
+
+ auto rs = work.parameterized("select id from soil_moisture_device where mac=$1")(mac).exec();
+
+ if (!rs.size()) {
+ cout << "New device: " << mac << endl;
+
+ rs = work.parameterized("insert into soil_moisture_device(mac) values($1) returning id")(mac).exec();
+ }
+
+ auto deviceId = rs.begin()["id"].as<int>();
+
+ int sensor = j["sensor"];
+
+ rs = work.parameterized("select id from soil_moisture_sensor where device=$1 and sensor=$2")(deviceId)(sensor).exec();
+
+ if (!rs.size()) {
+ cout << "New sensor: " << sensor << endl;
+
+ rs = work.parameterized("insert into soil_moisture_sensor(device, sensor) values($1, $2) returning id")(deviceId)(sensor).exec();
+ }
+ auto sensorId = rs.begin()["id"].as<int>();
+
+ unsigned long timestamp = get<unsigned long>(j, "timestamp");
+ unsigned int value = get<unsigned int>(j, "value");
+
+ work.parameterized("insert into soil_moisture_sample(sensor, timestamp, value) values($1, $2, $3)")(sensorId)(timestamp)(value).exec();
+
+ cout << "Sample inserted" << endl;
+
+ work.commit();
+
+ return EXIT_SUCCESS;
+ }
+};
+
+}
+}
diff --git a/apps/sm-db-select.cpp b/apps/sm-db-select.cpp
deleted file mode 100644
index 8bcce32..0000000
--- a/apps/sm-db-select.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-#include <boost/optional.hpp>
-#include <boost/lexical_cast.hpp>
-#include <pqxx/connection.hxx>
-#include <pqxx/transaction.hxx>
-#include "json.hpp"
-
-template<class T>
-using o = boost::optional<T>;
-using namespace std;
-using json = nlohmann::json;
-
-class missing_key : public runtime_error {
-public:
- missing_key(const json::string_t key) : runtime_error("Missing key: " + key), key(key) {
- }
-
- const json::string_t key;
-};
-
-template<typename T>
-T get(json j, string key) {
- auto ref = j[key];
-
- if (ref.is_null()) {
- throw missing_key(key);
- }
-
- return ref;
-}
-
-int main(int argc, char *argv[]) {
- string mac = "aa:bb:cc:dd:ee:ff";
- int sensor = 1;
-
- json j;
-
- pqxx::connection c("host=localhost dbname=soil-moisture");
-
- pqxx::work work(c);
-
- auto rs = work.parameterized("select id from soil_moisture_device where mac=$1")(mac).exec();
-
- if (!rs.size()) {
- cout << "Unknown device: " << mac << endl;
- return EXIT_FAILURE;
- }
-
- auto deviceId = rs.begin()["id"].as<int>();
-
- rs = work.parameterized("select id from soil_moisture_sensor where device=$1 and sensor=$2")(deviceId)(sensor).exec();
-
- if (!rs.size()) {
- cout << "Unknown sensor: " << sensor << endl;
- return EXIT_FAILURE;
- }
-
- auto sensorId = rs.begin()["id"].as<int>();
-
- rs = work.parameterized("select timestamp, sensor, value from soil_moisture_sample where sensor=$1")(sensorId).exec();
-
- json points = json::array();
- for (auto sample: rs) {
- json s;
- s.push_back(sample["timestamp"].as<unsigned long>());
- s.push_back(sample["sensor"].as<unsigned long>());
- s.push_back(sample["value"].as<unsigned long>());
- points.push_back({s});
- }
-
- json o;
- o["columns"] = json::array({"time", "sensor", "value"});
- o["points"] = json(points);
- j.push_back(o);
-
- cout << "JSON" << endl;
- cout << setw(2) << j << endl;
- cout << "JSON" << endl;
-
- work.commit();
-
- return EXIT_SUCCESS;
-}
diff --git a/apps/sm-db-select.h b/apps/sm-db-select.h
new file mode 100644
index 0000000..fcbe91b
--- /dev/null
+++ b/apps/sm-db-select.h
@@ -0,0 +1,81 @@
+#include <boost/optional.hpp>
+#include <boost/lexical_cast.hpp>
+#include <pqxx/connection.hxx>
+#include <pqxx/transaction.hxx>
+#include "json.hpp"
+
+namespace trygvis {
+namespace apps {
+
+template<class T>
+using o = boost::optional<T>;
+using namespace std;
+using json = nlohmann::json;
+
+class sm_db_select : public app {
+
+public:
+ sm_db_select() : app("sm-db-select") {
+ }
+
+ ~sm_db_select() = default;
+
+ int main(app_execution &execution) override {
+ string mac = "aa:bb:cc:dd:ee:ff";
+ int sensor = 1;
+
+ json j;
+
+ pqxx::connection c("host=localhost dbname=soil-moisture");
+
+ pqxx::work work(c);
+
+ auto rs = work.parameterized("select id from soil_moisture_device where mac=$1")(mac).exec();
+
+ if (!rs.size()) {
+ cout << "Unknown device: " << mac << endl;
+ return EXIT_FAILURE;
+ }
+
+ auto deviceId = rs.begin()["id"].as<int>();
+
+ rs = work.parameterized("select id from soil_moisture_sensor where device=$1 and sensor=$2")(deviceId)(
+ sensor).exec();
+
+ if (!rs.size()) {
+ cout << "Unknown sensor: " << sensor << endl;
+ return EXIT_FAILURE;
+ }
+
+ auto sensorId = rs.begin()["id"].as<int>();
+
+ rs = work.parameterized("select timestamp, sensor, value from soil_moisture_sample where sensor=$1")(
+ sensorId).exec();
+
+ json points = json::array();
+ for (auto sample: rs) {
+ json s;
+ s.push_back(sample["timestamp"].as<unsigned long>());
+ s.push_back(sample["sensor"].as<unsigned long>());
+ s.push_back(sample["value"].as<unsigned long>());
+ points.push_back({s});
+ }
+
+ json o;
+ o["columns"] = json::array({"time", "sensor", "value"});
+ o["points"] = json(points);
+ j.push_back(o);
+
+ cout << "JSON" << endl;
+ cout << setw(2) << j << endl;
+ cout << "JSON" << endl;
+
+ work.commit();
+
+ return EXIT_SUCCESS;
+ }
+
+};
+
+}
+}
diff --git a/apps/sm-get-value.cpp b/apps/sm-get-value.h
index 883495a..e0275c1 100644
--- a/apps/sm-get-value.cpp
+++ b/apps/sm-get-value.h
@@ -15,7 +15,6 @@ using namespace std::chrono;
using namespace trygvis::apps;
using namespace trygvis::bluetooth;
using namespace trygvis::sensor;
-namespace po = boost::program_options;
using json = nlohmann::json;
bool loop;
@@ -128,7 +127,7 @@ public:
loop = sleepTime > 0;
do {
- LOG4CPLUS_INFO(logger, "Connecting to device: " + device.getMac().str());
+ LOG4CPLUS_INFO(execution.logger, "Connecting to device: " + device.getMac().str());
auto &gatt = device.connectGatt();
try {
@@ -152,8 +151,3 @@ public:
}
}
-
-int main(int argc, char *argv[]) {
- sm_get_value app;
- return trygvis::apps::launch_app(argc, argv, app);
-}
diff --git a/apps/sm-serial-read-all.cpp b/apps/sm-serial-read-all.h
index 5fa3f79..39b585a 100644
--- a/apps/sm-serial-read-all.cpp
+++ b/apps/sm-serial-read-all.h
@@ -17,8 +17,7 @@ using namespace trygvis::sensor::io;
namespace po = boost::program_options;
using json = nlohmann::json;
-sample_format_type format;
-string hostname = get_hostname();
+namespace sm_serial_read_all_utils {
class port_handler {
public:
@@ -56,6 +55,8 @@ private:
unique_ptr<SampleStreamParser> parser;
};
+}
+
// This only supports Linux
#if 1
@@ -87,6 +88,7 @@ vector<string> &&find_ports() {
#endif
class sm_serial_read_all : public app {
+ typedef trygvis::apps::sm_serial_read_all_utils::port_handler port_handler;
public:
sm_serial_read_all() : app("sm-serial-read-all") {
@@ -95,6 +97,7 @@ public:
~sm_serial_read_all() = default;
bool run = true;
+ sample_format_type format;
void add_options(po::options_description_easy_init &options) override {
options
@@ -166,10 +169,3 @@ public:
}
}
-
-using namespace trygvis::apps;
-
-int main(int argc, char *argv[]) {
- sm_serial_read_all app;
- return launch_app(argc, argv, app);
-}
diff --git a/apps/sm-serial-read.cpp b/apps/sm-serial-read.h
index 8c4c299..a3e3872 100644
--- a/apps/sm-serial-read.cpp
+++ b/apps/sm-serial-read.h
@@ -18,8 +18,7 @@ using namespace trygvis::sensor::io;
namespace po = boost::program_options;
using json = nlohmann::json;
-sample_format_type format;
-string hostname = get_hostname();
+namespace sm_serial_read_utils {
class port_handler {
public:
@@ -51,7 +50,10 @@ private:
shared_ptr<KeyValueSampleStreamParser> input;
};
+}
+
class sm_serial_read : public app {
+ typedef trygvis::apps::sm_serial_read_utils::port_handler port_handler;
public:
sm_serial_read() : app("sm-serial-read") {
@@ -59,6 +61,8 @@ public:
~sm_serial_read() = default;
+ sample_format_type format;
+
void add_options(po::options_description_easy_init &options) override {
options
("help", "produce help message")
@@ -105,10 +109,3 @@ public:
}
}
-
-using namespace trygvis::apps;
-
-int main(int argc, char *argv[]) {
- sm_serial_read app;
- return launch_app(argc, argv, app);
-}