diff options
-rw-r--r-- | README-apps.md | 1 | ||||
-rw-r--r-- | apps/CMakeLists.txt | 2 | ||||
-rw-r--r-- | apps/sample-add-timestamp.cpp | 101 | ||||
-rw-r--r-- | apps/sample-timestamp.cpp | 212 | ||||
-rw-r--r-- | sensor/include/trygvis/sensor.h | 9 | ||||
-rw-r--r-- | sensor/main/sensor.cpp | 24 |
6 files changed, 136 insertions, 213 deletions
diff --git a/README-apps.md b/README-apps.md index 228691a..2157631 100644 --- a/README-apps.md +++ b/README-apps.md @@ -34,3 +34,4 @@ Graphing values rrdtool graph graph.png --width 1024 --height 512 \ --start 1425593989 --end 1425991529 \ DEF:a=test.rrd:analog:AVERAGE LINE2:a#FF0000 + diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 15a1f0b..988a989 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,7 +1,7 @@ list(APPEND APPS log4cplus-test) list(APPEND APPS ble-inspect-device) +list(APPEND APPS sample-add-timestamp) list(APPEND APPS sample-convert) -list(APPEND APPS sample-timestamp) list(APPEND APPS sample-select) list(APPEND APPS sm-db-insert) list(APPEND APPS sm-db-select) diff --git a/apps/sample-add-timestamp.cpp b/apps/sample-add-timestamp.cpp new file mode 100644 index 0000000..dbf24a1 --- /dev/null +++ b/apps/sample-add-timestamp.cpp @@ -0,0 +1,101 @@ +#include "trygvis/sensor.h" +#include "trygvis/sensor/io.h" +#include "apps.h" +#include <vector> + +namespace trygvis { +namespace apps { + +using namespace std; +using namespace trygvis::apps; +using namespace trygvis::sensor; +using namespace trygvis::sensor::io; +namespace po = boost::program_options; + +class TimestampAddingSampleOutputStream : public SampleOutputStream { + +public: + TimestampAddingSampleOutputStream(shared_ptr<SampleOutputStream> output, KeyDictionary &dict, string timestamp_name) + : + timestamp_key(dict.indexOf(timestamp_name)) { + if (input_time_resolution_ == time_resolution::MILLISECONDS) { + factor = 1000; + } else { + factor = 1; + } + } + + virtual void write(SampleRecord const &sample) override { + time_t now = time(NULL) * factor; + + SampleRecord updated_sample(sample); + + updated_sample.set(timestamp_key, std::to_string(now)); + + output_->write(updated_sample); + }; + +private: + const SampleKey *timestamp_key; + time_resolution input_time_resolution_; + int factor; + shared_ptr<SampleOutputStream> output_; +}; + +class sample_add_timestamp : public app { + +private: + string timestamp_name; + time_resolution resolution; + sample_format_type output_format; + +public: + void add_options(po::options_description_easy_init &options) override { + options + ("help", "produce this help message") + ("resolution", po::value<time_resolution>(&resolution)->default_value(time_resolution::SECONDS)) + ("timestamp-name", po::value<string>(×tamp_name)->default_value("timestamp")) + ("output-format", po::value<sample_format_type>(&output_format)->default_value(sample_format_type::KEY_VALUE)); + } + + const int buffer_size = 1024; + + int main(app_execution &execution) override { + shared_ptr<istream> input; + + input = shared_ptr<istream>(&cin, noop_deleter); + + KeyDictionary dict; + + sample_output_stream_options options = {}; + unique_ptr<SampleOutputStream> unique_output_stream = open_sample_output_stream(shared_ptr<ostream>(&cout, noop_deleter), dict, output_format, options); + shared_ptr<SampleOutputStream> output_stream{std::move(unique_output_stream)}; + shared_ptr<SampleOutputStream> p = make_shared<TimestampAddingSampleOutputStream>(output_stream, dict, timestamp_name); + auto parser = open_sample_stream_parser(p, dict); + + int recordCount = 0; + + while (!input->eof()) { + char buffer[buffer_size]; + input->read(buffer, buffer_size); + size_t gcount = (size_t)input->gcount(); + + recordCount++; + + mutable_buffers_1 b = boost::asio::buffer(buffer, gcount); + parser->process(b); + } + + return EXIT_SUCCESS; + }; +}; + +} +} + +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-timestamp.cpp b/apps/sample-timestamp.cpp deleted file mode 100644 index cf0b7fe..0000000 --- a/apps/sample-timestamp.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include "trygvis/sensor.h" -#include "trygvis/sensor/io.h" -#include "apps.h" -#include <fstream> -#include <sys/stat.h> - -namespace trygvis { -namespace apps { - -using namespace std; -using namespace trygvis::apps; -using namespace trygvis::sensor; -using namespace trygvis::sensor::io; -namespace po = boost::program_options; - -enum class time_resolution { - SECONDS, - MILLISECONDS, -}; - -std::ostream& operator<<(std::ostream& os, time_resolution const& type) { - if (type == time_resolution::SECONDS) { - os << "seconds"; - } else if(type == time_resolution::MILLISECONDS) { - os << "milliseconds"; - } - - return os; -} - -std::istream& operator>>(std::istream& is, time_resolution & type) { - string s; - - is >> s; - - if(s == "seconds") { - type = time_resolution::SECONDS; - } else if(s == "milliseconds") { - type = time_resolution::MILLISECONDS; - } - - return is; -} - -class TimestampFixingSampleOutputStream : public SampleOutputStream { - -public: - TimestampFixingSampleOutputStream(shared_ptr<SampleOutputStream> output, KeyDictionary &dict, string timestamp_name, string relative_name, time_resolution input_time_resolution, time_t start_time) : - timestamp_key(dict.indexOf(timestamp_name)), relative_key(dict.indexOf(relative_name)), input_time_resolution_(input_time_resolution), start_time_(start_time), output_(output) { - } - - virtual void write(SampleRecord const &sample) override { - o<long> relative_time_o = sample.lexical_at<long>(relative_key); - - if (!relative_time_o) { - return; - } - - long relative_time = relative_time_o.get(); - - long updated_time; - if (input_time_resolution_ == time_resolution::SECONDS) { - updated_time = start_time_ + relative_time; - } else if (input_time_resolution_ == time_resolution::MILLISECONDS) { - updated_time = start_time_ + relative_time / 1000; - } - - string updated_value = std::to_string(updated_time); - - SampleRecord updated_sample(sample); - - updated_sample.set(timestamp_key, updated_value); - - output_->write(updated_sample); - }; - -private: - const SampleKey* relative_key, *timestamp_key; - time_t start_time_; - time_resolution input_time_resolution_; - shared_ptr<SampleOutputStream> output_; -}; - -class sample_timestamp : public app { - -private: - string input_file, timestamp_name, relative_name; - time_resolution relative_resolution; - SampleKey* relative_key; - -public: - sample_timestamp() : input_file("") { - } - - void add_options(po::options_description_easy_init &options) override { - options - ("help", "produce this help message") - ("input", po::value<string>(&input_file)->required()) - ("relative-name", po::value<string>(&relative_name)->default_value("relative")) - ("relative-resolution", po::value<time_resolution>(&relative_resolution)->default_value(time_resolution::SECONDS)) - ("timestamp-name", po::value<string>(×tamp_name)->default_value("timestamp")); - } - - int main(app_execution &execution) override { - ifstream input(input_file, std::ifstream::in | std::ifstream::binary); - - if (input.fail()) { - cerr << "Could not open file: " << input_file << endl; - return EXIT_FAILURE; - } - - const int buffer_size = 1024; - - input.seekg(-buffer_size, ios_base::end); - - struct stat buf; - - if (stat(input_file.c_str(), &buf)) { - cerr << "stat failed" << endl; - return EXIT_FAILURE; - } - - KeyDictionary dict; - - relative_key = dict.indexOf(relative_name); - - auto sample_buffer = make_shared<VectorSampleOutputStream>(); - auto parser = open_sample_stream_parser(sample_buffer, dict); - while (!input.fail()) { - char buffer[buffer_size]; - input.read(buffer, buffer_size); - auto count = (size_t) input.gcount(); - - cerr << "eof? " << input.eof() << endl; - mutable_buffers_1 b = boost::asio::buffer(buffer, count); - parser->process(b); - } - - if (sample_buffer->samples.empty()) { - cerr << "Could not find any samples" << endl; - return EXIT_FAILURE; - } - - time_t end_time = buf.st_mtim.tv_sec; - - SampleRecord sample = *--sample_buffer->samples.end(); - - o<string> s = sample.at(relative_key); - if (!s) { - cerr << "Missing key '" + relative_name + "'." << endl; - cerr << "Found " << sample_buffer->samples.size() << " samples." << endl; - cerr << "keys: " << sample.to_string() << endl; - return EXIT_FAILURE; - } - - long relative; - try { - relative = boost::lexical_cast<long>(s.get()); - } catch (const boost::bad_lexical_cast &e) { - cerr << "Bad integer value '" + s.get() + "'." << endl; - return EXIT_FAILURE; - } - - if (relative_resolution == time_resolution::MILLISECONDS) { - relative /= 1000; - } - - time_t start_time = end_time - relative; - cerr << "end_time " << end_time << endl; - cerr << "relative " << relative << endl; - cerr << "start_time " << start_time << endl; - - // Restart the reading of the input file and add the adjusted timestamp - input.clear(ios::eofbit); - input.seekg(0); - if(input.fail()) { - cerr << "Coult not seek input file" << endl; - return EXIT_FAILURE; - } - - sample_output_stream_options options; - unique_ptr<SampleOutputStream> unique_output_stream = open_sample_output_stream(shared_ptr<ostream>(&cout, noop_deleter), dict, parser->type(), options); - shared_ptr<SampleOutputStream> output_stream{std::move(unique_output_stream)}; - shared_ptr<SampleOutputStream> p = make_shared<TimestampFixingSampleOutputStream>(output_stream, dict, timestamp_name, relative_name, relative_resolution, start_time); - parser = open_sample_stream_parser(p, dict, parser->type()); - - int recordCount = 0; - - while (!input.eof()) { - char buffer[buffer_size]; - input.read(buffer, buffer_size); - size_t gcount = (size_t)input.gcount(); - - recordCount++; - - mutable_buffers_1 b = boost::asio::buffer(buffer, gcount); - parser->process(b); - } - - return EXIT_SUCCESS; - }; -}; - -} -} - -using namespace trygvis::apps; - -int main(int argc, char *argv[]) { - sample_timestamp app; - return launch_app(argc, argv, app); -} diff --git a/sensor/include/trygvis/sensor.h b/sensor/include/trygvis/sensor.h index f8cfbe5..bcbd43b 100644 --- a/sensor/include/trygvis/sensor.h +++ b/sensor/include/trygvis/sensor.h @@ -29,6 +29,15 @@ std::ostream& operator<<(std::ostream& os, sample_format_type const& type); std::istream& operator>>(std::istream& is, sample_format_type& type); +enum class time_resolution { + SECONDS, + MILLISECONDS, +}; + +std::ostream& operator<<(std::ostream& os, time_resolution const& type); + +std::istream& operator>>(std::istream& is, time_resolution & type); + class sample_exception : public runtime_error { public: sample_exception(const string &what) : runtime_error(what) { diff --git a/sensor/main/sensor.cpp b/sensor/main/sensor.cpp index a773e0b..be3d31e 100644 --- a/sensor/main/sensor.cpp +++ b/sensor/main/sensor.cpp @@ -53,6 +53,30 @@ std::istream& operator>>(std::istream& is, sample_format_type& type) { return is; } +std::ostream& operator<<(std::ostream& os, time_resolution const& type) { + if (type == time_resolution::SECONDS) { + os << "seconds"; + } else if(type == time_resolution::MILLISECONDS) { + os << "milliseconds"; + } + + return os; +} + +std::istream& operator>>(std::istream& is, time_resolution & type) { + string s; + + is >> s; + + if(s == "seconds") { + type = time_resolution::SECONDS; + } else if(s == "milliseconds") { + type = time_resolution::MILLISECONDS; + } + + return is; +} + template<> const o<long> SampleRecord::lexical_at(const SampleKey *key) const { auto value = at(key); |