#include "SoilMoistureIo.h" #include "json.hpp" #include "apps.h" #include #include #include 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; using namespace trygvis::soil_moisture; namespace po = boost::program_options; using json = nlohmann::json; Format format; string hostname = get_hostname(); class port_handler { public: port_handler(string device, serial_port &serial_port, shared_ptr input) : device(device), port(serial_port), input(input) { } void run() { auto packet = make_shared>(1024); while (port.is_open()) { std::size_t some = port.read_some(buffer); mutable_buffers_1 chunk = boost::asio::buffer(data, some); input->process(chunk); } cerr << "port closed" << endl; } private: static const size_t size = 1024; string device; serial_port &port; uint8_t data[size]; mutable_buffers_1 buffer = boost::asio::buffer(data, size); shared_ptr input; }; class sm_serial_read : public app { 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.open(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::parity(serial_port_base::parity::none)); port.set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one)); port.set_option(serial_port_base::flow_control(serial_port_base::flow_control::none)); if (port.is_open()) { cerr << "port is open" << endl; } else { cerr << "port is not open" << endl; } shared_ptr output; if (format == Format::JSON) { output = make_shared(cout); } else if (format == Format::SQL) { output = make_shared(cout, "raw"); } else if (format == Format::PLAIN) { output = make_shared(cout); } else { cerr << "Unsupported format: " << boost::lexical_cast(format) << endl; return EXIT_FAILURE; } shared_ptr input = make_shared(output); port_handler(port_name, port, input).run(); return EXIT_SUCCESS; } }; } } using namespace trygvis::apps; int main(int argc, char *argv[]) { sm_serial_read app; return launch_app(argc, argv, app); }