aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2015-03-03 23:11:26 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2015-03-03 23:11:26 +0100
commit1cf0d4c224b32e31d9cd9ba3a4719f57118321fb (patch)
tree3c935d94883207ded67e30a888a1844bfb676e76
parent8c5aad737561837f0b8d616cc03130b7546e45a9 (diff)
downloadble-toys-1cf0d4c224b32e31d9cd9ba3a4719f57118321fb.tar.gz
ble-toys-1cf0d4c224b32e31d9cd9ba3a4719f57118321fb.tar.bz2
ble-toys-1cf0d4c224b32e31d9cd9ba3a4719f57118321fb.tar.xz
ble-toys-1cf0d4c224b32e31d9cd9ba3a4719f57118321fb.zip
o An app to read the serial port and parse its values. Not very useful yet.
-rw-r--r--apps/CMakeLists.txt12
-rw-r--r--apps/sm-serial-read.cpp162
2 files changed, 168 insertions, 6 deletions
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index ab9c529..7fa9443 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -2,16 +2,16 @@ set(APPS
ble-inspect-device
sm-db-insert
sm-db-select
- sm-get-value)
+ sm-get-value
+ sm-serial-read)
-set(APPS ${APPS} log4cplus-test)
+list(APPEND APPS log4cplus-test)
-set(shared_sources
- SoilMoisture.cpp
- apps.cpp)
+list(APPEND shared_sources SoilMoisture.cpp)
+list(APPEND shared_sources apps.cpp)
# Boost
-find_package(Boost COMPONENTS system program_options REQUIRED)
+find_package(Boost COMPONENTS regex system program_options REQUIRED)
# Bluez
pkg_check_modules(BLUEZ bluez REQUIRED)
diff --git a/apps/sm-serial-read.cpp b/apps/sm-serial-read.cpp
new file mode 100644
index 0000000..8d5e70b
--- /dev/null
+++ b/apps/sm-serial-read.cpp
@@ -0,0 +1,162 @@
+#include <iostream>
+#include <iomanip>
+#include <chrono>
+#include <thread>
+#include <boost/asio/serial_port.hpp>
+#include <boost/regex.hpp>
+#include "json.hpp"
+#include "apps.h"
+
+enum class Format {
+ PLAIN,
+ JSON,
+ SQL
+};
+
+void validate(boost::any &v, const std::vector<std::string> &values, Format *, int) {
+ using namespace boost::program_options;
+
+ const std::string &s = validators::get_single_string(values);
+
+ if (s == "plain") {
+ v = boost::any(Format::PLAIN);
+ } else if (s == "json") {
+ v = boost::any(Format::JSON);
+ } else if (s == "sql") {
+ v = boost::any(Format::SQL);
+ } else {
+ throw validation_error(validation_error::invalid_option_value);
+ }
+}
+
+namespace boost {
+
+template<>
+std::string lexical_cast(const Format &arg) {
+ if (arg == Format::PLAIN)
+ return "plain";
+ else if (arg == Format::JSON)
+ return "json";
+ else if (arg == Format::SQL)
+ return "sql";
+ else
+ throw std::runtime_error("Unknown format value: " + lexical_cast<std::string>(arg));
+}
+
+}
+
+namespace trygvis {
+namespace apps {
+
+using namespace boost::asio;
+using namespace std;
+using namespace std::chrono;
+using namespace trygvis::apps;
+namespace po = boost::program_options;
+using json = nlohmann::json;
+
+class sm_serial_read : public app {
+
+ Format format;
+
+ class port_handler {
+ public:
+ port_handler(serial_port &serial_port) : port(serial_port) {
+ }
+
+ void run() {
+ auto packet = make_shared<vector<uint8_t>>(1024);
+
+ while (port.is_open()) {
+ size_t some = port.read_some(buffer);
+ for (int i = 0; i < some; i++) {
+ uint8_t b = data[i];
+
+ if (b == packet_delimiter) {
+ on_packet(packet);
+ packet = make_shared<vector<uint8_t>>(1024);
+ } else {
+ packet->emplace_back(b);
+ }
+ }
+ }
+
+ cout << "port closed" << endl;
+ }
+
+ void on_packet(shared_ptr<vector<uint8_t>> packet) {
+ auto s = std::string((char *) packet->data(), packet->size());
+ cout << "packet: " << s << endl;
+
+ static const boost::regex e("#(\\d+) = (\\d+)");
+
+ std::string::const_iterator start = s.begin();
+ std::string::const_iterator end = s.end();
+ boost::match_results<std::string::const_iterator> what;
+ boost::match_flag_type flags = boost::match_default;
+
+ while(regex_search(start, end, what, e, flags)) {
+ auto sensor = what[1];
+ auto value = what[2];
+ start = what[0].second;
+
+ cout << "sensor #" << sensor << " = " << value << endl;
+
+ flags |= boost::match_prev_avail;
+ flags |= boost::match_not_bob;
+ }
+ }
+
+ private:
+ static const size_t size = 1024;
+ static const uint8_t packet_delimiter = '\n';
+ uint8_t data[size];
+ mutable_buffers_1 buffer = boost::asio::buffer(data, size);
+ serial_port &port;
+ };
+
+public:
+ void add_options(po::options_description_easy_init &options) override {
+ options
+ ("help", "produce help message")
+ ("port", po::value<string>()->required(), "The serial port to read")
+ ("format", po::value<Format>(&format)->default_value(Format::PLAIN), "Output format");
+ }
+
+ int main(app_execution &execution) override {
+ auto desc = execution.desc;
+ auto vm = execution.vm;
+
+ uint32_t baud_rate = 115200;
+ auto port_name = vm["port"].as<string>();
+
+ io_service io_service;
+
+ serial_port port(io_service, port_name);
+ port.set_option(serial_port_base::baud_rate(baud_rate));
+ port.set_option(serial_port_base::character_size(8));
+ port.set_option(serial_port_base::flow_control(serial_port_base::flow_control::none));
+ port.set_option(serial_port_base::parity(serial_port_base::parity::even));
+ port.set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::two));
+
+ if (port.is_open()) {
+ cout << "port is open" << endl;
+ } else {
+ cout << "port is not open" << endl;
+ }
+
+ port_handler(port).run();
+
+ return EXIT_SUCCESS;
+ }
+
+};
+
+}
+}
+
+using namespace trygvis::apps;
+int main(int argc, char *argv[]) {
+ sm_serial_read app;
+ return launch_app(argc, argv, app);
+}