From 1cf0d4c224b32e31d9cd9ba3a4719f57118321fb Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 3 Mar 2015 23:11:26 +0100 Subject: o An app to read the serial port and parse its values. Not very useful yet. --- apps/CMakeLists.txt | 12 ++-- apps/sm-serial-read.cpp | 162 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 apps/sm-serial-read.cpp 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 +#include +#include +#include +#include +#include +#include "json.hpp" +#include "apps.h" + +enum class Format { + PLAIN, + JSON, + SQL +}; + +void validate(boost::any &v, const std::vector &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(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>(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>(1024); + } else { + packet->emplace_back(b); + } + } + } + + cout << "port closed" << endl; + } + + void on_packet(shared_ptr> 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 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()->required(), "The serial port to read") + ("format", po::value(&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(); + + 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); +} -- cgit v1.2.3