LDFLAGS="$LDFLAGS -lpthread"
AC_SUBST(CFLAGS)
AC_SUBST(LDFLAGS)
+
+CXXFLAGS="$CXXFLAGS -ggdb -Wall -Werror"
+AC_SUBST(CXXFLAGS)
+
AC_MSG_NOTICE([libplp Makefile])
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
-#AC_PROG_CXX
+AC_PROG_CXX
AC_STDC_HEADERS
AC_PROG_LIBTOOL
AC_PROG_INSTALL
--- /dev/null
+/*
+ * DataRange.cc
+ *
+ * Created on: Dec 7, 2010
+ * Author: lamikr
+ */
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#include <stdio.h>
+#include <time.h>
+#include <malloc.h>
+
+#include "log.h"
+#include "Data.hh"
+#include "Date.hh"
+
+using namespace std;
+using namespace plp;
+
+template <class NumberDataType>
+bool string_to_number(NumberDataType& result,
+ const string& string_param,
+ std::ios_base& (*format)(std::ios_base&))
+{
+ std::istringstream iss(string_param);
+ return !(iss >> format >> result).fail();
+}
+
+Data::Data(int size) {
+ value_arr.resize(size);
+}
+
+Data::Data(int size, double default_value, string unit_param) {
+ int ii;
+
+ value_arr.resize(size);
+ for (ii = 0; ii < size; ii++) {
+ value_arr[ii] = default_value;
+ }
+ unit = unit_param;
+}
+
+Data::Data(vector<double> *vect_param) {
+ unsigned int ii;
+ unsigned int sz;
+
+ sz = vect_param->size();
+ //log_debug("Data(), value count: %d\n", size);
+ value_arr.resize(sz);
+ for (ii = 0; ii < sz; ii++) {
+ value_arr[ii] = vect_param->at(ii);
+ //log_debug("Data(), value[%d]: %f\n", ii, value_arr[ii]);
+ }
+}
+
+Data::Data(std::vector<double> *vector_param, string unit_param) {
+ unsigned int ii;
+ unsigned int sz;
+
+ sz = vector_param->size();
+ //log_debug("Data(), value count: %d\n", size);
+ value_arr.resize(sz);
+ for (ii = 0; ii < sz; ii++) {
+ value_arr[ii] = vector_param->at(ii);
+ //log_debug("Data(), value[%d]: %f\n", ii, value_arr[ii]);
+ }
+ unit = unit_param;
+}
+
+Data::Data(vector<double> *vector_param,
+ Date *date_param,
+ string unit_param) {
+ unsigned int ii;
+ unsigned int size;
+
+ size = vector_param->size();
+ //log_debug("Data(), value count: %d\n", size);
+ value_arr.resize(size);
+ for (ii = 0; ii < size; ii++) {
+ value_arr[ii] = vector_param->at(ii);
+ //log_debug("Data(), value[%d]: %f\n", ii, value_arr[ii]);
+ }
+ date_time.copy(date_param);
+ unit = unit_param;
+}
+
+Data::Data(std::valarray<double> *val_arr_param, Date *date_param) {
+ unsigned int ii;
+ unsigned int sz;
+
+ sz = val_arr_param->size();
+ value_arr.resize(sz);
+ for (ii = 0; ii < sz; ii++) {
+ value_arr[ii] = (*val_arr_param)[ii];
+ }
+ date_time.copy(date_param);
+}
+
+Data::~Data() {
+}
+
+Data *Data::clone() {
+ Data *ret_val;
+
+ ret_val = new Data(&value_arr, &date_time);
+ return ret_val;
+}
+
+void Data::printout() {
+ log_debug(" data: %s\n", to_string().c_str());
+}
+
+plp::Date Data::get_date() {
+ return date_time;
+}
+
+void Data::set_date(Date *date_param) {
+ date_time.copy(date_param);
+}
+
+string Data::get_unit() {
+ return unit;
+}
+
+Data *Data::parse_string(const string& dataline) {
+ stringstream ss(dataline);
+ string item;
+ double val;
+ Data *ret_val;
+ int ii;
+ int sz;
+ bool suc_flg;
+ vector<double> v;
+ string unit;
+ Date date;
+
+ ii = 0;
+ ret_val = NULL;
+ //log_debug("parse_string: %s\n", dataline.c_str());
+ while(getline(ss, item, '|')) {
+ if (ii == 0) {
+ // parse date
+ date = Date::parse_date_str(item);
+ }
+ else if (ii >= 1) {
+ suc_flg = string_to_number<double>(val, item, dec);
+ if (suc_flg) {
+ //log_debug("adding number: %f\n", val);
+ v.push_back(val);
+ }
+ }
+ ii++;
+ }
+ ii = item.find_last_of(" ");
+ sz = item.size();
+ if ((ii >= 0) &&
+ ((ii + 1) <= (sz - 1))) {
+ unit = item.substr(ii + 1);
+ }
+ else {
+ unit = "";
+ }
+ if (v.size() > 0) {
+ ret_val = new Data(&v, &date, unit);
+ }
+ return ret_val;
+}
+
+string Data::to_string(int dec_precision) {
+ unsigned int ii;
+ ostringstream out;
+ string ret_val;
+
+ ret_val = date_time.to_string();
+ if (value_arr.size() > 0) {
+ for (ii = 0; ii < value_arr.size(); ii++) {
+ out << "|" << fixed << setprecision(dec_precision) << value_arr[ii];
+ }
+ ret_val.append(out.str());
+ if (unit.empty() == false) {
+ ret_val.append(" ");
+ ret_val.append(unit.c_str());
+ }
+ }
+ return ret_val;
+}
+
+string Data::to_string() {
+ return to_string(3);
+}
+
+int Data::get_value_count() {
+ return value_arr.size();
+}
+
+double Data::get(int indx) {
+ return value_arr[indx];
+}
+
+DataRange::DataRange() {
+ val_matrix = NULL;
+ column_count = 0;
+ row_count = 0;
+ unit = "";
+}
+
+DataRange::DataRange(Data *data) {
+ val_matrix = NULL;
+ row_count = 0;
+ if (data != NULL) {
+ column_count = data->value_arr.size();
+ unit = data->get_unit();
+ add(data);
+ }
+ else {
+ column_count = 0;
+ unit = "";
+ }
+}
+
+DataRange::DataRange(DataRange *datarange) {
+ val_matrix = NULL;
+ row_count = 0;
+ column_count = 0;
+ unit = "";
+ if (datarange != NULL) {
+ add(datarange);
+ }
+}
+
+DataRange::DataRange(int value_count_per_data_item, string unit_param) {
+ val_matrix = NULL;
+ column_count = value_count_per_data_item;
+ row_count = 0;
+ unit = unit_param;
+}
+
+DataRange::~DataRange() {
+ unsigned int ii;
+ Date *date;
+
+ if (val_matrix != NULL) {
+ free(val_matrix);
+ val_matrix = NULL;
+ }
+ for (ii = 0; ii < date_list.size(); ii++) {
+ date = date_list.at(ii);
+ delete(date);
+ }
+}
+
+void DataRange::add(Data *data) {
+ int ii;
+ int indx;
+ Date *date;
+ int cnt;
+
+ if (data != NULL) {
+ if ((val_matrix == NULL) &&
+ (column_count == 0) &&
+ (unit.empty() == true)) {
+ column_count = data->value_arr.size();
+ unit = data->get_unit();
+ }
+ cnt = (row_count + 1) * column_count;
+ val_matrix = (double *)realloc(val_matrix, cnt * sizeof(double));
+ indx = row_count * column_count;
+ cnt = data->value_arr.size();
+ if (cnt != column_count) {
+ log_error("Error when adding data... Invalid data item count!\n");
+ if (cnt > column_count) {
+ cnt = column_count;
+ }
+ else {
+ for (ii = cnt; ii < column_count; ii++) {
+ val_matrix[indx + ii] = 0;
+ }
+ }
+ }
+ for (ii = 0; ii < cnt; ii++) {
+ val_matrix[indx + ii] = data->value_arr[ii];
+ }
+/*
+ for (int ii = 0; ii < ((row_count + 1) * column_count); ii++) {
+ log_debug("data_matrix[%d] = %f\n", ii, val_matrix[ii]);
+ }
+*/
+ date = data->get_date().clone();
+ date_list.push_back(date);
+ row_count++;
+ }
+}
+
+void DataRange::add(DataRange *datarange) {
+ int ii;
+ int cnt;
+ Data *dta;
+
+ if (datarange != NULL) {
+ cnt = datarange->get_count();
+ for (ii = 0; ii < cnt; ii++) {
+ dta = datarange->get(ii);
+ add(dta);
+ delete(dta);
+ }
+ }
+}
+
+Data *DataRange::get(int row_index) {
+ Data *ret_val;
+ int start_indx;
+ int ii;
+ vector<double> vect;
+ Date *date;
+ double val;
+
+ ret_val = NULL;
+ if ((row_index >= 0) &&
+ (row_index < row_count)) {
+ start_indx = row_index * column_count;
+ for (ii = 0; ii < column_count; ii++) {
+ //val = val_matrix[0];
+ val = val_matrix[start_indx + ii];
+ //log_debug("val[%d] = %f\n", (start_indx + ii), val);
+ vect.push_back(val);
+ }
+ date = date_list.at(row_index);
+ ret_val = new Data(&vect, date, unit);
+ }
+ return ret_val;
+}
+
+int DataRange::get_count() {
+ return row_count;
+}
+
+int DataRange::get_data_item_value_count() {
+ return column_count;
+}
+
+Data *DataRange::get_first() {
+ Data *ret_val;
+
+ ret_val = NULL;
+ if (row_count > 0) {
+ ret_val = get(0);
+ }
+ return ret_val;
+}
+
+Data *DataRange::get_last() {
+ return get(row_count - 1);
+}
+
+void DataRange::printout() {
+ int ii;
+ Data *data;
+
+ log_debug("---- DataRange, number of data items: %d\n ----", row_count);
+ for (ii = 0; ii < row_count; ii++) {
+ data = get(ii);
+ if (data != NULL) {
+ data->printout();
+ delete(data);
+ }
+ }
+ log_debug("---- DataRange printout done ----\n");
+}
--- /dev/null
+/*
+ * Data.hh
+ *
+ * Created on: Dec 8, 2010
+ * Author: lamikr
+ */
+
+#ifndef DATA_HH_
+#define DATA_HH_
+
+#include <string>
+#include <valarray>
+#include <vector>
+
+#include "Date.hh"
+
+namespace plp {
+ class Data {
+ public:
+ Data(int size);
+ Data(int size, double default_value, std::string unit_param);
+ Data(std::vector<double> *val_vector_param);
+ Data(std::vector<double> *val_vector_param, std::string unit_param);
+ Data(std::vector<double> *val_vector_param, plp::Date *date_param, std::string unit_param);
+ Data(std::valarray<double> *val_arr_param, plp::Date *date_param);
+ virtual ~Data();
+ Data *clone();
+ void printout();
+ std::string to_string(int dec_precision);
+ std::string to_string();
+ static Data *parse_string(const std::string& data_str);
+ plp::Date get_date();
+ void set_date(plp::Date *date_param);
+ int get_value_count();
+ double get(int indx);
+ std::string get_unit();
+ std::valarray<double> value_arr;
+ private:
+ plp::Date date_time;
+ std::string unit;
+ };
+
+ class DataRange {
+ public:
+ DataRange();
+ DataRange(Data *data);
+ DataRange(DataRange *datarange);
+ DataRange(int item_count_per_value, std::string unit_param);
+ virtual ~DataRange();
+ void add(Data *data);
+ void add(DataRange *datarange);
+ Data *get(int row_index);
+ Data *get_first();
+ Data *get_last();
+ int get_count();
+ int get_data_item_value_count();
+ std::string get_unit();
+ void printout();
+ protected:
+ double *val_matrix;
+ std::vector<plp::Date *> date_list;
+ int row_count;
+ int column_count;
+ std::string unit;
+ };
+}
+
+#endif /* DATA_HH_ */
--- /dev/null
+/*
+ * DataReader.cc
+ *
+ * Created on: Nov 7, 2010
+ * Author: lamikr
+ */
+#include <sstream>
+
+#include <dirent.h>
+#include <malloc.h>
+#include <errno.h>
+#include <string.h>
+
+#include "log.h"
+
+#include "DataReader.hh"
+#include "DeviceConfig.hh"
+#include "FileUtil.hh"
+#include "StoreDay.hh"
+#include "StoreCache.hh"
+
+using namespace std;
+using namespace plp;
+
+template <class NumberDataType>
+bool string_to_number(NumberDataType& result,
+ const std::string& string_param,
+ std::ios_base& (*format)(std::ios_base&))
+{
+ istringstream iss(string_param);
+ return !(iss >> format >> result).fail();
+}
+
+DataReader::DataReader(string device_id_param) {
+ string base_dir;
+
+ device_config = NULL;
+ device_id = device_id_param;
+ base_dir = DeviceConfig::get_base_dir_name();
+ device_dir = FileUtil::concat_paths(base_dir, device_id);
+ device_ch_dir = FileUtil::concat_paths(base_dir, "cache");
+ device_ch_dir = FileUtil::concat_paths(device_ch_dir, device_id);
+}
+
+DataReader::~DataReader() {
+ if (device_config != NULL) {
+ delete(device_config);
+ device_config = NULL;
+ }
+}
+
+Data *DataReader::find_latest_data(vector<string> year_name_vector_param) {
+ string year_name;
+ int size;
+ Data *ret_val;
+ Date date;
+ int val_int;
+
+ ret_val = NULL;
+ size = year_name_vector_param.size();
+ if (size > 0) {
+ // dirs are alphabetically sorted
+ year_name = year_name_vector_param.at(size - 1);
+ string_to_number<int>(val_int, year_name, dec);
+ date.year = val_int;
+ ret_val = StoreCache::get_latest_data(&date, device_id, PERIOD_YEARLY);
+ }
+ return ret_val;
+}
+
+Data *DataReader::get_latest_data() {
+ vector<string> y_list;
+ Data *ret_val;
+
+ ret_val = NULL;
+ y_list = FileUtil::get_subdirectories(device_dir);
+ ret_val = find_latest_data(y_list);
+ return ret_val;
+}
+
+Data *DataReader::find_oldest_data(vector<string> year_name_vector_param) {
+ int size;
+ string year_name;
+ Data *ret_val;
+ Date date;
+ int val_int;
+
+ ret_val = NULL;
+ size = year_name_vector_param.size();
+ if (size > 0) {
+ // dirs are alphabetically sorted
+ year_name = year_name_vector_param.at(0);
+ string_to_number<int>(val_int, year_name, dec);
+ date.year = val_int;
+ ret_val = StoreCache::get_oldest_data(&date, device_id, PERIOD_YEARLY);
+ }
+ return ret_val;
+}
+
+DataRange *DataReader::get_data_range() {
+ DataRange *ret_val;
+ vector<string> y_list;
+ Data *o_data;
+ Data *n_data;
+
+ ret_val = NULL;
+ y_list = FileUtil::get_subdirectories(device_dir);
+ o_data = find_oldest_data(y_list);
+ if (o_data != NULL) {
+ n_data = find_latest_data(y_list);
+ if (n_data != NULL) {
+ ret_val = new DataRange(o_data);
+ ret_val->add(n_data);
+ delete(n_data);
+ }
+ delete(o_data);
+ }
+ return ret_val;
+}
+
+EnumSummaryPeriod get_period_type(Date *start_date,
+ Date *end_date) {
+ int diff;
+ EnumSummaryPeriod ret_val;
+
+ ret_val = PERIOD_YEARLY;
+ diff = end_date->year - start_date->year;
+ if (diff != 0) {
+ ret_val = PERIOD_YEARLY;
+ }
+ else {
+ diff = end_date->month - start_date->month;
+ if (diff != 0) {
+ ret_val = PERIOD_MONTHLY;
+ }
+ else {
+ diff = end_date->day - start_date->day;
+ if (diff != 0) {
+ ret_val = PERIOD_DAILY;
+ }
+ else {
+ diff = end_date->hour - start_date->hour;
+ if (diff != 0) {
+ ret_val = PERIOD_HOURLY;
+ }
+ else {
+ diff = end_date->min - start_date->min;
+ if (diff != 0) {
+ ret_val = PERIOD_MINUTELY;
+ }
+ else {
+ ret_val = PERIOD_SECONDLY;
+ }
+ }
+ }
+ }
+ }
+ return ret_val;
+}
+
+DataRange *DataReader::get_summary(Date *date_param,
+ EnumSummaryCalculationType calc_type_param,
+ EnumSummaryPeriod period_type_param) {
+ DataRange *ret_val;
+ StoreCache *store;
+
+ ret_val = NULL;
+ //store = new StoreDay(device_id, date_param);
+ store = new StoreCache(device_id, date_param);
+ if (store != NULL) {
+ switch(calc_type_param) {
+ case SUM:
+ ret_val = store->get_sum(period_type_param);
+ break;
+ case DELTA:
+ ret_val = store->get_delta(period_type_param);
+ break;
+ case MAX:
+ ret_val = store->get_max(period_type_param);
+ break;
+ case MIN:
+ ret_val = store->get_min(period_type_param);
+ break;
+ case MEAN:
+ default:
+ ret_val = store->get_mean(period_type_param);
+ break;
+ }
+ if (ret_val != NULL) {
+ ret_val->printout();
+ }
+ else {
+ log_error("Could not read data log for device: %s\n", device_id.c_str());
+ }
+ }
+ else {
+ log_error("Could not read data log for device: %s\n", device_id.c_str());
+ }
+ delete(store);
+ return ret_val;
+}
+
+DataRange *DataReader::get_yearly_summary(Date *date,
+ EnumSummaryCalculationType calc_type_param) {
+ return get_summary(date, calc_type_param, PERIOD_YEARLY);
+}
+
+DataRange *DataReader::get_yearly_summary(Date *date) {
+ DataRange *ret_val;
+
+ if (device_config == NULL) {
+ device_config = DeviceConfig::get_device_config(device_id);
+ summary_calc_type = device_config->get_summary_calculation_type();
+ }
+ ret_val = get_yearly_summary(date, summary_calc_type);
+ return ret_val;
+}
+
+DataRange *DataReader::get_yearly_summary(Date *start_date,
+ Date *end_date) {
+ DataRange *ret_val;
+ DataRange *data;
+ Date *date;
+
+ ret_val = NULL;
+ date = start_date->clone();
+ while(date->before_or_equal_year(end_date)) {
+ data = get_yearly_summary(date);
+ if (data != NULL) {
+ if (ret_val == NULL) {
+ ret_val = new DataRange(data);
+ }
+ else {
+ ret_val->add(data);
+ }
+ delete(data);
+ }
+ date->next_year();
+ }
+ delete(date);
+ return ret_val;
+}
+
+DataRange *DataReader::get_monthly_summary(Date *date,
+ EnumSummaryCalculationType calc_type_param) {
+ return get_summary(date, calc_type_param, PERIOD_MONTHLY);
+}
+
+DataRange *DataReader::get_monthly_summary(Date *date) {
+ DataRange *ret_val;
+
+ if (device_config == NULL) {
+ device_config = DeviceConfig::get_device_config(device_id);
+ summary_calc_type = device_config->get_summary_calculation_type();
+ }
+ ret_val = get_monthly_summary(date, summary_calc_type);
+ return ret_val;
+}
+
+DataRange *DataReader::get_monthly_summary(Date *start_date,
+ Date *end_date) {
+ DataRange *ret_val;
+ DataRange *data;
+ Date *date;
+
+ ret_val = NULL;
+ date = start_date->clone();
+ while(date->before_or_equal_month(end_date)) {
+ data = get_monthly_summary(date);
+ if (data != NULL) {
+ if (ret_val == NULL) {
+ ret_val = new DataRange(data);
+ }
+ else {
+ ret_val->add(data);
+ }
+ delete(data);
+ }
+ date->next_month();
+ }
+ delete(date);
+ return ret_val;
+}
+
+DataRange *DataReader::get_daily_summary(Date *date,
+ EnumSummaryCalculationType calc_type_param) {
+ return get_summary(date, calc_type_param, PERIOD_DAILY);
+}
+
+DataRange *DataReader::get_daily_summary(Date *date) {
+ DataRange *ret_val;
+
+ if (device_config == NULL) {
+ device_config = DeviceConfig::get_device_config(device_id);
+ summary_calc_type = device_config->get_summary_calculation_type();
+ }
+ ret_val = get_daily_summary(date, summary_calc_type);
+ return ret_val;
+}
+
+DataRange *DataReader::get_daily_summary(Date *start_date,
+ Date *end_date) {
+ DataRange *ret_val;
+ DataRange *data;
+ Date *date;
+
+ ret_val = NULL;
+ date = start_date->clone();
+ while(date->before_or_equal_day(end_date)) {
+ data = get_daily_summary(date);
+ if (data != NULL) {
+ if (ret_val == NULL) {
+ ret_val = new DataRange(data);
+ }
+ else {
+ ret_val->add(data);
+ }
+ delete(data);
+ }
+ date->next_day();
+ }
+ delete(date);
+ return ret_val;
+}
+
+DataRange *DataReader::get_hourly_summary(Date *date,
+ EnumSummaryCalculationType calc_type_param) {
+ return get_summary(date, calc_type_param, PERIOD_HOURLY);
+}
+
+DataRange *DataReader::get_hourly_summary(Date *date) {
+ DataRange *ret_val;
+
+ if (device_config == NULL) {
+ device_config = DeviceConfig::get_device_config(device_id);
+ summary_calc_type = device_config->get_summary_calculation_type();
+ }
+ ret_val = get_hourly_summary(date, summary_calc_type);
+ return ret_val;
+}
+
+DataRange *DataReader::get_hourly_summary(Date *start_date,
+ Date *end_date) {
+ DataRange *ret_val;
+ DataRange *dta_lst;
+ Data *data;
+ Date *date;
+ int cnt;
+ int ii;
+
+ ret_val = NULL;
+ date = start_date->clone();
+ while(date->before_or_equal_hour(end_date)) {
+ dta_lst = get_hourly_summary(date);
+ cnt = dta_lst->get_count();
+ for(ii = 0; ii < cnt; ii++) {
+ data = dta_lst->get(ii);
+ if (data != NULL) {
+ if (ret_val == NULL) {
+ ret_val = new DataRange(data);
+ }
+ else {
+ ret_val->add(data);
+ }
+ delete(data);
+ }
+ }
+ date->next_day();
+ }
+ delete(date);
+ return ret_val;
+}
+
+DataRange *DataReader::get_data(Date *start_date,
+ Date *end_date) {
+ DataRange *ret_val;
+ EnumSummaryPeriod period;
+
+ ret_val = NULL;
+ start_date->printout();
+ end_date->printout();
+ period = get_period_type(start_date, end_date);
+ switch(period) {
+ case PERIOD_YEARLY:
+ log_debug("get yearly summary: %s - %s\n", start_date->to_string().c_str(), end_date->to_string().c_str());
+ ret_val = get_yearly_summary(start_date, end_date);
+ break;
+ case PERIOD_MONTHLY:
+ log_debug("get monthly summary\n");
+ ret_val = get_monthly_summary(start_date, end_date);
+ break;
+ case PERIOD_DAILY:
+ log_debug("get daily summary\n");
+ ret_val = get_daily_summary(start_date, end_date);
+ break;
+ case PERIOD_HOURLY:
+ log_debug("get hourly summary\n");
+ ret_val = get_hourly_summary(start_date, end_date);
+ break;
+ case PERIOD_MINUTELY:
+ log_debug("get minute summary data\n");
+ break;
+ case PERIOD_SECONDLY:
+ default:
+ log_debug("get second summary data\n");
+ break;
+ }
+ return ret_val;
+}
+
+string DataReader::get_device_id() {
+ return device_id;
+}
+
+/**
+ * Read device type from the device specific config file
+ */
+string DataReader::get_device_type() {
+ string ret_val;
+
+ if (device_config == NULL) {
+ device_config = DeviceConfig::get_device_config(device_id);
+ ret_val = device_config->get_cfg_value(DEVICE_CONFIG_VALUE_KEY__TYPE);
+ }
+ return ret_val;
+}
--- /dev/null
+/*
+ * DataReader.hh
+ *
+ * Created on: Nov 7, 2010
+ * Author: lamikr
+ */
+
+#ifndef DATAREADER_H_
+#define DATAREADER_H_
+
+#include <string>
+#include <vector>
+
+#include "Data.hh"
+#include "Date.hh"
+#include "DeviceConfig.hh"
+
+#include <time.h>
+
+namespace plp {
+ class DataReader {
+ public:
+ DataReader(std::string device_id);
+ virtual ~DataReader();
+ DataRange *get_data_range();
+ /**
+ * Get monthly summary data.
+ * Depending from the device type, it may be daily mean value, daily delta, highest value, etc...
+ */
+ DataRange *get_yearly_summary(Date *date, EnumSummaryCalculationType calc_type);
+ DataRange *get_yearly_summary(Date *date);
+ DataRange *get_yearly_summary(Date *start_date, Date *end_date);
+ /**
+ * Get monthly summary data.
+ * Depending from the device type, it may be daily mean value, daily delta, highest value, etc...
+ */
+ DataRange *get_monthly_summary(Date *date, EnumSummaryCalculationType calc_type);
+ DataRange *get_monthly_summary(Date *date);
+ DataRange *get_monthly_summary(Date *start_date, Date *end_date);
+ /**
+ * Get daily summary data calculated from the daily data items.
+ * Depending from the device type, it may be daily mean value, daily delta, highest value, etc...
+ */
+ DataRange *get_daily_summary(Date *date, EnumSummaryCalculationType calc_type);
+ DataRange *get_daily_summary(Date *date);
+ DataRange *get_daily_summary(Date *start_date, Date *end_date);
+ DataRange *get_hourly_summary(Date *date, EnumSummaryCalculationType calc_type);
+ DataRange *get_hourly_summary(Date *date);
+ DataRange *get_hourly_summary(Date *start_date, Date *end_date);
+ DataRange *get_data(Date *start_date, Date *end_date);
+ std::string get_device_id();
+ std::string get_device_type();
+ Data *get_latest_data();
+ protected:
+ std::string device_id;
+ std::string device_dir;
+ std::string device_ch_dir;
+ DeviceConfig *device_config;
+ EnumSummaryCalculationType summary_calc_type;
+ Data *find_oldest_data(std::vector<std::string> year_vector);
+ Data *find_latest_data(std::vector<std::string> year_vector);
+ DataRange *get_summary(Date *date_param,
+ EnumSummaryCalculationType calc_type_param,
+ EnumSummaryPeriod period_type_param);
+ };
+}
+
+#endif /* DATAREADER_H_ */
--- /dev/null
+/*
+ * Date.cc
+ *
+ * Created on: Dec 7, 2010
+ * Author: lamikr
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include <stdio.h>
+#include <time.h>
+#include <malloc.h>
+
+#include "log.h"
+#include "Date.hh"
+
+using namespace std;
+using namespace plp;
+
+static const int CONST__DAYS_PER_MONTH[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+Date::Date() {
+ time_t wtime;
+ struct tm *ltime;
+
+ time(&wtime);
+ ltime = localtime(&wtime);
+ year = 1900 + ltime->tm_year;
+ month = ltime->tm_mon + 1; // ltime-month: values 0 - 11...
+ day = ltime->tm_mday;
+ hour = ltime->tm_hour;
+ min = ltime->tm_min;
+ sec = ltime->tm_sec;
+}
+
+Date::Date(int year_param,
+ int month_param,
+ int day_param,
+ int hour_param,
+ int min_param,
+ int sec_param) {
+ year = year_param;
+ month = month_param;
+ day = day_param;
+ hour = hour_param;
+ min = min_param;
+ sec = sec_param;
+}
+
+Date::~Date() {
+ // TODO Auto-generated destructor stub
+}
+
+bool Date::is_leap_year() {
+ bool ret_val;
+
+ ret_val = false;
+ if ((year % 4 == 0) &&
+ ((year % 400 == 0) || (year % 100 != 0))) {
+ ret_val = true;
+ }
+ return ret_val;
+}
+
+void Date::printout() {
+ log_debug("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, min, sec);
+}
+
+Date *Date::clone() {
+ Date *ret_val;
+
+ ret_val = new Date(year,
+ month,
+ day,
+ hour,
+ min,
+ sec);
+ return ret_val;
+}
+
+void Date::copy(Date *date) {
+ year = date->year;
+ month = date->month;
+ day = date->day;
+ hour = date->hour;
+ min = date->min;
+ sec = date->sec;
+}
+
+bool Date::before(Date *date2) {
+ bool ret_val;
+ string s1;
+ string s2;
+
+ ret_val = false;
+ if (date2 != NULL) {
+ s1 = this->to_sortable_string();
+ s2 = date2->to_sortable_string();
+ if (s1.compare(s2) < 0) {
+ ret_val = true;
+ }
+ }
+ return ret_val;
+}
+
+bool Date::equals(Date *date2) {
+ bool ret_val;
+
+ ret_val = false;
+ if (date2 != NULL) {
+ if ((this->sec == date2->sec) &&
+ (this->min == date2->min) &&
+ (this->hour == date2->hour) &&
+ (this->day == date2->day) &&
+ (this->month == date2->month) &&
+ (this->year == date2->year)) {
+ ret_val = true;
+ }
+ }
+ return ret_val;
+}
+
+bool Date::before_or_equal_year(Date *date2) {
+ bool ret_val;
+ string s1;
+ string s2;
+
+ ret_val = (this->year <= date2->year);
+ return ret_val;
+}
+
+bool Date::before_or_equal_month(Date *date2) {
+ bool ret_val;
+ string s1;
+ string s2;
+
+ ret_val = false;
+ if (this->year < date2->year) {
+ ret_val = true;
+ }
+ else {
+ if ((this->year == date2->year) &&
+ (this->month <= date2->month)) {
+ ret_val = true;
+ }
+ }
+ return ret_val;
+}
+
+bool Date::before_or_equal_day(Date *date2) {
+ bool ret_val;
+ string s1;
+ string s2;
+
+ ret_val = false;
+ if (date2 != NULL) {
+ s1 = this->to_sortable_day_string();
+ s2 = date2->to_sortable_day_string();
+ if (s1.compare(s2) <= 0) {
+ ret_val = true;
+ }
+ }
+ return ret_val;
+}
+
+bool Date::before_or_equal_hour(Date *date2) {
+ bool ret_val;
+ string s1;
+ string s2;
+
+ ret_val = false;
+ if (date2 != NULL) {
+ s1 = this->to_sortable_hour_string();
+ s2 = date2->to_sortable_hour_string();
+ if (s1.compare(s2) <= 0) {
+ ret_val = true;
+ }
+ }
+ return ret_val;
+}
+
+bool Date::before_or_equal_min(Date *date2) {
+ bool ret_val;
+ string s1;
+ string s2;
+
+ ret_val = false;
+ if (date2 != NULL) {
+ s1 = this->to_sortable_min_string();
+ s2 = date2->to_sortable_min_string();
+ if (s1.compare(s2) <= 0) {
+ ret_val = true;
+ }
+ }
+ return ret_val;
+}
+
+bool Date::before_or_equal(Date *date2) {
+ bool ret_val;
+ string s1;
+ string s2;
+
+ ret_val = false;
+ if (date2 != NULL) {
+ s1 = this->to_sortable_string();
+ s2 = date2->to_sortable_string();
+ if (s1.compare(s2) <= 0) {
+ ret_val = true;
+ }
+ }
+ return ret_val;
+}
+
+void Date::next_second() {
+ if (sec < 59) {
+ sec++;
+ }
+ else {
+ next_min();
+ }
+}
+
+void Date::next_min() {
+ if (min < 59) {
+ sec = 0;
+ min++;
+ }
+ else {
+ next_hour();
+ }
+}
+
+void Date::next_hour() {
+ hour++;
+ if (hour < 23) {
+ sec = 0;
+ min = 0;
+ hour++;
+ }
+ else {
+ next_day();
+ }
+}
+
+void Date::next_day() {
+ if ((month > 0) &&
+ (month <= 12)) {
+ if ((day < CONST__DAYS_PER_MONTH[month - 1]) ||
+ ((month == 2) &&
+ (is_leap_year() == true) &&
+ (day == 28))) {
+ sec = 0;
+ min = 0;
+ hour = 0;
+ day++;
+ }
+ else {
+ next_month();
+ }
+ }
+}
+
+void Date::next_month() {
+ if (month < 12) {
+ sec = 0;
+ min = 0;
+ hour = 0;
+ day = 1;
+ month++;
+ }
+ else {
+ next_year();
+ }
+}
+
+void Date::next_year() {
+ sec = 0;
+ min = 0;
+ hour = 0;
+ day = 1;
+ month = 1;
+ year++;
+}
+
+void Date::inc_minutes(int minutes) {
+ int day_c;
+ int hour_c;
+ int ii;
+
+ day_c = minutes / 1440;
+ minutes = minutes - day_c * 1440;
+ hour_c = minutes / 60;
+ minutes = minutes - hour_c * 60;
+ for (ii = 0; ii < day_c; ii++) {
+ next_day();
+ }
+ for (ii = 0; ii < hour_c; ii++) {
+ hour++;
+ if (hour > 24) {
+ hour = 0;
+ next_day();
+ }
+ }
+ min = min + minutes;
+ if (min >= 60) {
+ min = min % 60;
+ hour++;
+ if (hour > 24) {
+ hour = 0;
+ next_day();
+ }
+ }
+}
+
+void Date::inc_seconds(int seconds) {
+ int min_c;
+
+ min_c = seconds / 60;
+ seconds = seconds - min_c * 60;
+ inc_minutes(min_c);
+ sec = sec + seconds;
+ if (sec >= 60) {
+ sec = sec % 60;
+ inc_minutes(1);
+ }
+}
+
+string Date::to_sortable_day_string() {
+ char buffer[30];
+
+
+ string ret_val;
+
+ sprintf(buffer, "%016d%02d%02d", year, month, day);
+ ret_val = buffer;
+ return ret_val;
+}
+
+string Date::to_sortable_hour_string() {
+ char buffer[30];
+ string ret_val;
+
+ sprintf(buffer, "%016d%02d%02d%02d", year, month, day, hour);
+ ret_val = buffer;
+ return ret_val;
+}
+
+string Date::to_sortable_min_string() {
+ char buffer[30];
+ string ret_val;
+
+ sprintf(buffer, "%016d%02d%02d%02d%02d", year, month, day, hour, min);
+ ret_val = buffer;
+ return ret_val;
+}
+
+string Date::to_sortable_string() {
+ char buffer[30];
+ string ret_val;
+
+ sprintf(buffer, "%016d%02d%02d%02d%02d%02d", year, month, day, hour, min, sec);
+ ret_val = buffer;
+ return ret_val;
+}
+
+string Date::to_string() {
+ char buffer[30];
+ string ret_val;
+
+ sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec);
+ ret_val = buffer;
+ return ret_val;
+}
+
+Date Date::parse_date_str(string date_str) {
+ char c;
+ stringstream ss(date_str);
+ Date ret_val;
+
+ ss >>ret_val.year >>c >>ret_val.month >>c >>ret_val.day >>ret_val.hour >>c >>ret_val.min >>c >>ret_val.sec;
+ return ret_val;
+}
--- /dev/null
+/*
+ * Date.hh
+ *
+ * Created on: Dec 7, 2010
+ * Author: lamikr
+ */
+
+#ifndef DATE_HH_
+#define DATE_HH_
+
+#include <string>
+
+namespace plp {
+ class Date {
+ public:
+ Date();
+ Date(int year_param,
+ int month_param,
+ int day_param,
+ int hour_param,
+ int min_param,
+ int sec_param);
+ virtual ~Date();
+ void printout();
+ bool is_leap_year();
+ void next_second();
+ void next_min();
+ void next_hour();
+ void next_day();
+ void next_month();
+ void next_year();
+ void inc_minutes(int minutes);
+ void inc_seconds(int seconds);
+ Date *clone();
+ void copy(Date *date);
+ bool before(Date *date2);
+ bool equals(Date *date2);
+ bool before_or_equal(Date *date2);
+ bool before_or_equal_year(Date *date2);
+ bool before_or_equal_month(Date *date2);
+ bool before_or_equal_day(Date *date2);
+ bool before_or_equal_hour(Date *date2);
+ bool before_or_equal_min(Date *date2);
+ static plp::Date parse_date_str(std::string date_str);
+ int year;
+ int month;
+ int day;
+ int hour;
+ int min;
+ int sec;
+ std::string to_string();
+ protected:
+ std::string to_sortable_string();
+ std::string to_sortable_day_string();
+ std::string to_sortable_hour_string();
+ std::string to_sortable_min_string();
+ //static const int arr_days_per_month[];
+ };
+}
+
+#endif /* DATE_HH_ */
--- /dev/null
+/*
+ * Device.cc
+ *
+ * Created on: Mar 5, 2011
+ * Author: lamikr
+ */
+#include <string>
+
+#include "Device.hh"
+#include "DeviceConfig.hh"
+
+using namespace std;
+using namespace plp;
+
+Device::Device(string id_param, string type_param) : plp::DeviceData(id_param, type_param) {
+}
+
+Device::Device(string id_param, string type_param, string name_param, EnumDeviceLifeCycleStatus status_param) : plp::DeviceData(id_param, type_param, name_param, status_param) {
+}
--- /dev/null
+/*
+ * GenericDevice.hh
+ *
+ * Created on: Feb 28, 2011
+ * Author: lamikr
+ */
+
+#ifndef DEVICE_HH_
+#define DEVICE_HH_
+
+#include <string>
+
+#include "DeviceData.hh"
+#include "DataReader.hh"
+
+namespace plp {
+ class Device : public DeviceData {
+ public:
+ Device(std::string id_param, std::string type_param);
+ Device(std::string id_param, std::string type_param, std::string name_param, plp::EnumDeviceLifeCycleStatus status_param);
+ virtual plp::DataReader *get_device_data() = 0;
+ };
+}
+
+#endif /* DEVICE_HH_ */
--- /dev/null
+/*
+ * DeviceConfig.cc
+ *
+ * Created on: Dec 9, 2010
+ * Author: lamikr
+ */
+
+#include "DeviceConfig.hh"
+
+#include <string.h>
+#include <malloc.h>
+
+#include "log.h"
+
+#include "DataReader.hh"
+#include "FileUtil.hh"
+
+using namespace std;
+using namespace plp;
+
+string DeviceConfig::store_base_dir = DEFAULT_STORAGE_BASE_DIR;
+
+ConfigHandle::ConfigHandle(uci_context *ctx_param, uci_package *pkg_param) {
+ _ctx = ctx_param;
+ _pkg = pkg_param;
+}
+
+ConfigHandle::~ConfigHandle() {
+ uci_unload(_ctx, _pkg);
+ uci_free_context(_ctx);
+}
+
+DeviceConfig::DeviceConfig(string device_id_param) {
+ device_id = device_id_param;
+ uci_handle = load_device_config(device_id_param);
+ if (uci_handle != NULL) {
+ device_type = get_cfg_value(DEVICE_CONFIG_VALUE_KEY__TYPE);
+ }
+ else {
+ log_error("Could not read device configuration.\n");
+ }
+}
+
+DeviceConfig::~DeviceConfig() {
+ if (uci_handle != NULL) {
+ delete(uci_handle);
+ uci_handle = NULL;
+ }
+}
+
+void DeviceConfig::set_base_dir_name(string store_param) {
+ int pos;
+ int b_count;
+
+ pos = store_param.find_last_of("/");
+ b_count = store_param.length();
+ if (pos == (b_count - 1)) {
+ store_base_dir = store_param;
+ }
+ else {
+ store_base_dir = store_param + "/";
+ }
+}
+
+string DeviceConfig::get_base_dir_name() {
+ return store_base_dir;
+}
+
+string DeviceConfig::get_dir_name(string device_id_param) {
+ string ret_val;
+ string d_name;
+
+ d_name = DeviceConfig::get_base_dir_name();
+ ret_val = FileUtil::concat_paths(d_name, device_id_param);
+ return ret_val;
+}
+
+string DeviceConfig::get_file_name(string device_id_param) {
+ string ret_val;
+ string fname;
+
+ fname = DEVICE_CONFIG__FILE_NAME;
+ ret_val = get_dir_name(device_id);
+ ret_val = FileUtil::concat_paths(ret_val, fname);
+ return ret_val;
+}
+
+string DeviceConfig::get_cfg_value(string key) {
+ struct uci_section *section;
+ struct uci_option *option;
+ string ret_val;
+
+ if (uci_handle != NULL) {
+ section = uci_lookup_section(uci_handle->_ctx, uci_handle->_pkg, DEVICE_CONFIG__SECTION_NAME);
+ if (section != NULL) {
+ option = uci_lookup_option(uci_handle->_ctx, section, key.c_str());
+ if (option != NULL) {
+ switch (option->type) {
+ case UCI_TYPE_STRING:
+ //log_info("key: %s option name: %s, value: %s\n", key.c_str(), option->e.name, option->v.string);
+ ret_val = option->v.string;
+ break;
+ default:
+ log_error("key: %s Failed to read parameter value\n", key.c_str());
+ break;
+ }
+ }
+ else {
+ log_error("key: %s Failed to read parameter value\n", key.c_str());
+ }
+ }
+ }
+ return ret_val;
+}
+
+void DeviceConfig::set_cfg_value(string key, string value) {
+ string cfg_dir;
+ string cfg_fl;
+
+ cfg_dir = get_dir_name(device_id);
+ cfg_fl = DEVICE_CONFIG__FILE_NAME;
+ set_config_value(cfg_dir.c_str(),
+ cfg_fl.c_str(),
+ DEVICE_CONFIG__SECTION_TYPE,
+ DEVICE_CONFIG__SECTION_NAME,
+ key.c_str(),
+ value.c_str());
+}
+
+EnumSummaryCalculationType DeviceConfig::get_summary_calculation_type() {
+ EnumSummaryCalculationType ret_val;
+
+ ret_val = MEAN;
+ if (device_type.empty() == false) {
+ if (device_type.compare("Counter Device") == 0) {
+ ret_val = DELTA;
+ }
+ }
+ return ret_val;;
+}
+
+ConfigHandle *DeviceConfig::load_device_config(string device_id_param) {
+ int err_flg;
+ struct uci_context *ctx;
+ struct uci_package *pkg;
+ string cfg_fl;
+ string cfg_dir;
+ ConfigHandle *ret_val;
+
+ ret_val = NULL;
+ cfg_dir = get_dir_name(device_id_param);
+ if (cfg_dir.empty() == false) {
+ if (access(cfg_dir.c_str(), W_OK) != 0) {
+ FileUtil::mkdirs(cfg_dir.c_str());
+ }
+ cfg_fl = get_file_name(device_id_param);
+ if (access(cfg_fl.c_str(), R_OK) == 0) {
+ ctx = uci_alloc_context();
+ if (ctx != NULL) {
+ //log_debug("uci_set_confdir: %s\n", cfg_dir.c_str());
+ uci_set_confdir(ctx, cfg_dir.c_str());
+ err_flg = uci_load(ctx, cfg_fl.c_str(), &pkg);
+ if (err_flg == UCI_OK) {
+ //log_debug("Loaded device configuration: %s.\n", cfg_fl.c_str());
+ ret_val = new ConfigHandle(ctx, pkg);
+ }
+ else {
+ log_debug("Failed to load device configuration: %s, err code: %d.\n", cfg_fl.c_str(), UCI_OK);
+ set_cfg_value(DEVICE_CONFIG_VALUE_KEY__TYPE, "");
+ uci_free_context(ctx);
+ }
+ }
+ else {
+ log_error("Failed to load device device configuration, memory allocation error.\n");
+ set_cfg_value(DEVICE_CONFIG_VALUE_KEY__TYPE, "");
+ }
+ }
+ else {
+ log_error("Failed to load device device configuration, file does not exist: %s.\n", cfg_fl.c_str());
+ }
+ }
+ return ret_val;
+}
+
+DeviceConfig *DeviceConfig::get_device_config(string device_id) {
+ DeviceConfig *ret_val;
+
+ ret_val = new DeviceConfig(device_id);
+ return ret_val;
+}
--- /dev/null
+/*
+ * DeviceConfig.hh
+ *
+ * Created on: Dec 9, 2010
+ * Author: lamikr
+ */
+
+#ifndef DEVICECONFIG_HH_
+#define DEVICECONFIG_HH_
+
+#include <string>
+
+extern "C" {
+ #include <uci.h>
+ #include "config.h"
+}
+
+enum EnumSummaryPeriod{PERIOD_YEARLY, PERIOD_MONTHLY, PERIOD_DAILY, PERIOD_HOURLY, PERIOD_MINUTELY, PERIOD_SECONDLY};
+enum EnumSummaryCalculationType {SUM, DELTA, MIN, MAX, MEAN};
+
+const std::string SUMMARY_PERIOD_NAMES_ARRAY[] = {"yearly", "monthly", "daily", "minutely", "secondly"};
+const std::string CALCULATION_TYPE_NAMES_ARRAY[] = {"sum", "delta", "min", "max", "mean"};
+
+#define DEVICE_CONFIG__FILE_NAME "dev_cfg.txt"
+#define DEVICE_CONFIG__SECTION_TYPE "device"
+#define DEVICE_CONFIG__SECTION_NAME "base_data"
+#define DEVICE_CONFIG_VALUE_KEY__TYPE "type"
+#define DEVICE_CONFIG_VALUE_KEY__ID "id"
+#define DEVICE_CONFIG_VALUE_KEY__NAME "name"
+
+#define DEFAULT_STORAGE_BASE_DIR "/tmp/w1data"
+#define DATAFILE_SUFFIX ".txt"
+#define CACHE_DIR_NAME "cache"
+
+namespace plp {
+ struct ConfigHandle {
+ public:
+ ConfigHandle(uci_context *ctx_param, uci_package *pkg_param);
+ ~ConfigHandle();
+ struct uci_context *_ctx;
+ struct uci_package *_pkg;
+ };
+
+ class DeviceConfig {
+ public:
+ DeviceConfig(std::string device_id_param);
+ virtual ~DeviceConfig();
+ static std::string get_base_dir_name();
+ static void set_base_dir_name(std::string store_param);
+ static DeviceConfig *get_device_config(std::string device_id);
+ std::string get_cfg_value(std::string key);
+ void set_cfg_value(std::string key, std::string value);
+ EnumSummaryCalculationType get_summary_calculation_type();
+ private:
+ static std::string store_base_dir;
+ std::string device_id;
+ std::string device_type;
+ ConfigHandle *uci_handle;
+ ConfigHandle *load_device_config(std::string device_id_param);
+ std::string get_dir_name(std::string device_id);
+ std::string get_file_name(std::string device_id_param);
+ };
+}
+
+#endif /* DEVICECONFIG_HH_ */
--- /dev/null
+/*
+ * DeviceData.cc
+ *
+ * Created on: Mar 4, 2011
+ * Author: lamikr
+ */
+#include <plp/Device.hh>
+#include "DeviceData.hh"
+
+using namespace std;
+using namespace plp;
+
+DeviceData::DeviceData(string id_param, string type_param) {
+ id = id_param;
+ type = type_param;
+ lifecycle_status = LIFECYCLE_STATUS__UNAVAILABLE;
+}
+
+DeviceData::DeviceData(std::string id_param, std::string type_param, std::string name_param, plp::EnumDeviceLifeCycleStatus status_param) {
+ id = id_param;
+ type = type_param;
+ name = name_param;
+ lifecycle_status = status_param;
+}
+
+DeviceData::~DeviceData() {
+
+}
+
+string DeviceData::get_id() {
+ return id;
+}
+
+string DeviceData::get_name() {
+ return name;
+}
+
+void DeviceData::set_name(string name_param) {
+ name = name_param;
+}
+
+EnumDeviceLifeCycleStatus DeviceData::get_lifecycle_state() {
+ return lifecycle_status;
+}
+
+string DeviceData::get_type() {
+ return type;
+}
+
+void DeviceData::printout() {
+
+}
--- /dev/null
+/*
+ * DeviceData.hh
+ *
+ * Created on: Mar 4, 2011
+ * Author: lamikr
+ */
+
+#ifndef DEVICEINFO_HH_
+#define DEVICEINFO_HH_
+
+#include <string>
+
+using namespace std;
+
+namespace plp {
+ enum EnumDeviceLifeCycleStatus {LIFECYCLE_STATUS__UNAVAILABLE, LIFECYCLE_STATUS__AVAILABLE};
+
+ class DeviceData {
+ public:
+ DeviceData(string id_param, string type_param);
+ DeviceData(string id_param, string type_param, string name_param, EnumDeviceLifeCycleStatus status_param);
+ ~DeviceData();
+ std::string get_id();
+ std::string get_name();
+ std::string get_type();
+ plp::EnumDeviceLifeCycleStatus get_lifecycle_state();
+ void set_name(std::string name_param);
+ void printout();
+ protected:
+ std::string id;
+ std::string name;
+ std::string type;
+ plp::EnumDeviceLifeCycleStatus lifecycle_status;
+ };
+}
+
+#endif /* DEVICEINFO_HH_ */
--- /dev/null
+/*
+ * DeviceTypes.hh
+ *
+ * Created on: Mar 3, 2011
+ * Author: lamikr
+ */
+
+#ifndef DEVICETYPES_HH_
+#define DEVICETYPES_HH_
+
+#define DEVICE_TYPE_UNKNOWN "Unknown"
+#define DEVICE_TYPE_TEMPERATURESENSOR "Temperature Sensor"
+#define DEVICE_TYPE_COUNTER_DEVICE "Counter Device"
+
+#endif /* DEVICETYPES_HH_ */
--- /dev/null
+/*
+ * FileUtil.cc
+ *
+ * Created on: Mar 5, 2011
+ * Author: lamikr
+ */
+
+#include <algorithm>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+
+#include "log.h"
+#include "FileUtil.hh"
+#include "DeviceConfig.hh"
+
+using namespace std;
+using namespace plp;
+
+template <class NumberDataType>
+bool string_to_number(NumberDataType& result,
+ const std::string& string_param,
+ std::ios_base& (*format)(std::ios_base&))
+{
+ std::istringstream iss(string_param);
+ return !(iss >> format >> result).fail();
+}
+
+FileUtil::FileUtil() {
+}
+
+FileUtil::~FileUtil() {
+}
+
+char *FileUtil::parse_directory_path(const char *file_path) {
+ char *p;
+ size_t b_count;
+ size_t f_size;
+ char *ret_val;
+
+ ret_val = NULL;
+ if (file_path != NULL) {
+ f_size = 0;
+ b_count = strlen(file_path);
+ for (p = &((char *)file_path)[b_count]; p != (char *)file_path; p--) {
+ f_size++;
+ if ((*p == '/') ||
+ (*p == '\\')) {
+ b_count = (b_count - f_size) + 1;
+ ret_val = strndup(file_path, b_count);
+ log_debug("dir: %s\n", ret_val);
+ break;
+ }
+ }
+ }
+ return ret_val;
+}
+
+bool FileUtil::mkdirs(const char *path) {
+ bool ret_val;
+ char *p;
+ int err_flg;
+
+ ret_val = true;
+ if (path != NULL) {
+ // go through each directory one by and and create if not exist
+ for (p = (char *)path; *p; p++) {
+ if ((p != path) &&
+ ((*p == '/') ||
+ (*p == '\\'))) {
+ *p = '\0';
+ // if dir does not exist, create it
+ if (access(path, F_OK) != 0) {
+ //log_debug("trying to create directory: %s\n", path);
+ err_flg = mkdir(path, S_IRWXU);
+ if (err_flg != 0) {
+ log_error("Could not create directory: %s\n", path);
+ ret_val = false;
+ break;
+ }
+ }
+ *p = '/';
+ }
+ }
+ if (ret_val == true) {
+ // if dir does not exist, create it
+ if (access(path, F_OK) != 0) {
+ //log_debug("trying to create directory: %s\n", path);
+ err_flg = mkdir(path, S_IRWXU);
+ if (err_flg != 0) {
+ log_error("Could not create directory: %s\n", path);
+ ret_val = false;
+ }
+ }
+ }
+ }
+ else {
+ ret_val = false;
+ log_error("Could not create NULL directory\n");
+ }
+ return ret_val;
+}
+
+std::ofstream *FileUtil::open_for_writing(const char *f_path) {
+ char *d_path;
+ size_t b_count;
+ ofstream *ret_val;
+ bool b_flg;
+
+ ret_val = NULL;
+ if (f_path != NULL) {
+ b_count = strlen(f_path);
+ if ((f_path[b_count - 1] != '/') &&
+ (f_path[b_count - 1] != '\\')) {
+ ret_val = new ofstream();
+ ret_val->open(f_path, ios::app);
+ if (ret_val->is_open() == false) {
+ d_path = parse_directory_path(f_path);
+ if (d_path != NULL) {
+ b_flg = mkdirs(d_path);
+ free(d_path);
+ }
+ if (b_flg == true) {
+ ret_val->open(f_path, ios::app);
+ }
+ }
+ }
+ else {
+ log_error("Could not open file, invalid file name. (%s)\n", f_path);
+ }
+ }
+ else {
+ log_error("Could not open file, invalid file name. (= NULL)\n");
+ }
+ return ret_val;
+}
+
+string FileUtil::concat_paths(string path_start, string path_end) {
+ return concat_paths(path_start.c_str(), path_end.c_str());
+}
+
+string FileUtil::concat_paths(const char *path_start, const char *path_end) {
+ string ret_val;
+ string end_str;
+ int pos;
+ int b_count;
+
+ if (path_start != NULL) {
+ ret_val = path_start;
+ if (path_end != NULL) {
+ end_str = path_end;
+ b_count = ret_val.length();
+ pos = ret_val.find_last_of("/");
+ if (pos == (b_count -1)) {
+ ret_val.append(end_str);
+ }
+ else {
+ pos = end_str.find_first_of("/");
+ if (pos == 0) {
+ ret_val.append(end_str);
+ }
+ else {
+ ret_val.append("/");
+ ret_val.append(end_str);
+ }
+ }
+ }
+ }
+ else {
+ if (path_end != NULL) {
+ ret_val = path_end;
+ }
+ }
+ return ret_val;
+}
+
+bool FileUtil::is_subdirectory(const char *path, dirent *direntry) {
+ bool ret_val;
+ struct stat stat_info;
+ string fname;
+
+ ret_val = false;
+ if (direntry != NULL) {
+ if ((strcmp(direntry->d_name, ".") == 0) ||
+ (strcmp(direntry->d_name, "..") == 0)) {
+ ret_val = false;
+ }
+ else {
+ fname = concat_paths(path, direntry->d_name);
+ stat(fname.c_str(), &stat_info);
+ ret_val = S_ISDIR(stat_info.st_mode);
+ //log_debug("stat for: %s: %d\n", fname.c_str(), ret_val);
+ }
+ }
+ return ret_val;
+}
+
+bool FileUtil::is_datafile(const char *path, dirent *direntry) {
+ bool ret_val;
+ struct stat stat_info;
+ string name;
+ int pos;
+ string fname;
+
+ ret_val = false;
+ if (direntry != NULL) {
+ name = direntry->d_name;
+ pos = name.find(DATAFILE_SUFFIX);
+ if (pos > 0) {
+ fname = concat_paths(path, direntry->d_name);
+ stat(fname.c_str(), &stat_info);
+ ret_val = S_ISREG(stat_info.st_mode);
+ }
+ }
+ return ret_val;
+}
+
+/**
+ * get sub-directories sorted in alphabetical order.
+ */
+vector<string> FileUtil::get_subdirectories(const string& path) {
+ dirent *direntry;
+ DIR *dir;
+ bool bool_flg;
+ vector<string> ret_val;
+
+ //log_debug("scanning path: %s\n", path.c_str());
+ errno = 0;
+ if (path.empty() == false) {
+ dir = opendir(path.c_str());
+ if (dir) {
+ while (true) {
+ errno = 0;
+ direntry = readdir(dir);
+ if (direntry != NULL) {
+ bool_flg = is_subdirectory(path.c_str(), direntry);
+ if (bool_flg == true) {
+ ret_val.push_back(string(direntry->d_name));
+ //log_debug("added dir: %s\n", direntry->d_name);
+ }
+ }
+ else {
+ break;
+ }
+ }
+ closedir(dir);
+ sort(ret_val.begin(), ret_val.end());
+ }
+ }
+ return ret_val;
+}
+
+/**
+ * get sub-directories sorted in alphabetical order.
+ */
+vector<string> FileUtil::get_data_files(const string& path) {
+ dirent *direntry;
+ DIR *dir;
+ vector<string> ret_val;
+
+ errno = 0;
+ if (path.empty() == false) {
+ dir = opendir(path.c_str());
+ if (dir) {
+ while (true) {
+ errno = 0;
+ direntry = readdir(dir);
+ if (direntry != NULL) {
+ if (is_datafile(path.c_str(), direntry) == true) {
+ ret_val.push_back(string(direntry->d_name));
+ }
+ }
+ else {
+ break;
+ }
+ }
+ closedir(dir);
+ sort(ret_val.begin(), ret_val.end());
+ }
+ }
+ return ret_val;
+}
--- /dev/null
+/*
+ * FileUtil.hh
+ *
+ * Created on: Mar 5, 2011
+ * Author: lamikr
+ */
+
+#ifndef FILEUTIL_HH_
+#define FILEUTIL_HH_
+
+#include <string>
+#include <vector>
+
+#include <dirent.h>
+
+namespace plp {
+ class FileUtil {
+ public:
+ FileUtil();
+ virtual ~FileUtil();
+ static std::string concat_paths(std::string path_start, std::string path_end);
+ static std::string concat_paths(const char *path_start, const char *path_end);
+ static bool is_subdirectory(const char *path, dirent *direntry);
+ static bool is_datafile(const char *path, dirent *direntry);
+ static std::vector<std::string> get_subdirectories(const std::string& path);
+ static std::vector<std::string> get_data_files(const std::string& path);
+ static char *parse_directory_path(const char *file_path);
+ static bool mkdirs(const char *path);
+ static std::ofstream *open_for_writing(const char *path);
+ };
+}
+
+#endif /* FILEUTIL_HH_ */
lib_LTLIBRARIES = libplp.la
libplp_la_SOURCES = \
config.c config.h \
+ Data.hh Data.cc \
+ DataReader.hh DataReader.cc \
+ Date.hh Date.cc \
+ Device.hh Device.cc \
+ DeviceConfig.hh DeviceConfig.cc \
+ DeviceData.hh DeviceData.cc \
+ DeviceTypes.hh \
+ FileUtil.cc FileUtil.hh \
+ SensorDevice.hh \
+ Store.cc Store.hh \
+ StoreDay.cc StoreDay.hh \
+ StoreCache.cc StoreCache.hh \
log.h \
log_config.c \
str_util.c str_util.h \
config.h \
log.h \
retval.h \
- str_util.h
+ str_util.h \
+ Data.hh \
+ DataReader.hh \
+ Date.hh \
+ Device.hh \
+ DeviceConfig.hh \
+ DeviceData.hh \
+ DeviceTypes.hh \
+ FileUtil.hh \
+ SensorDevice.hh \
+ Store.hh \
+ StoreDay.hh \
+ StoreCache.hh
+
--- /dev/null
+/*
+ * DeviceTypeSensor.hh
+ *
+ * Created on: Feb 28, 2011
+ * Author: lamikr
+ */
+
+#ifndef DEVICETYPESENSOR_HH_
+#define DEVICETYPESENSOR_HH_
+
+#include <string>
+
+#include "Device.hh"
+
+namespace plp {
+ class SensorDevice : public Device {
+ public:
+ SensorDevice(std::string id_param, std::string type_param) : Device(id_param, type_param) {}
+ virtual std::string get_unit() = 0;
+ virtual plp::Data *get_data() = 0;
+ };
+}
+
+#endif /* DEVICETYPESENSOR_HH_ */
--- /dev/null
+/*
+ * Store.cc
+ *
+ * Created on: Jan 20, 2011
+ * Author: lamikr
+ */
+#include <fstream>
+
+#include "log.h"
+#include "Store.hh"
+
+using namespace std;
+using namespace plp;
+
+Store::Store(string device_id_param,
+ Date *date_param) {
+ device_id = device_id_param;
+ if (date_param != NULL) {
+ date = date_param->clone();
+ }
+ else {
+ date = NULL;
+ }
+ store_data = NULL;
+ range_data = NULL;
+}
+
+Store::~Store() {
+ if (store_data != NULL) {
+ delete(store_data);
+ store_data = NULL;
+ }
+ if (date != NULL) {
+ delete(date);
+ }
+}
+
+bool Store::load(string fname_param) {
+ Data *data;
+ ifstream in;
+ string data_str;
+ bool ret_val;
+
+ ret_val = false;
+ if (store_data != NULL) {
+ delete(store_data);
+ store_data = NULL;
+ }
+ if (access(fname_param.c_str(), R_OK) == 0) {
+ //log_debug("opening file: %s\n", fname_param.c_str());
+ in.open(fname_param.c_str());
+ if (in.is_open() == true) {
+ while (in.eof() == false) {
+ getline(in, data_str);
+ if (data_str.empty() == false) {
+ data = Data::parse_string(data_str);
+ if (data != NULL) {
+ if (store_data == NULL) {
+ store_data = new DataRange(data);
+ }
+ else {
+ store_data->add(data);
+ }
+ delete(data);
+ }
+ }
+ }
+ ret_val = true;
+ }
+ else {
+ log_error("Could not open data file: %s\n", fname_param.c_str());
+ }
+ }
+ else {
+ log_error("Could not find file: %s\n", fname_param.c_str());
+ }
+ return ret_val;
+}
--- /dev/null
+/*
+ * Store.hh
+ *
+ * Created on: Jan 20, 2011
+ * Author: lamikr
+ */
+
+#ifndef STORE_HH_
+#define STORE_HH_
+
+#include <string>
+
+#include "Data.hh"
+#include "Date.hh"
+#include "DeviceConfig.hh"
+
+namespace plp {
+ class Store {
+ public:
+ Store(std::string device_id, plp::Date *date_time);
+ virtual ~Store();
+ virtual plp::DataRange *get_sum(EnumSummaryPeriod period_type_param) = 0;
+ virtual plp::DataRange *get_mean(EnumSummaryPeriod period_type_param) = 0;
+ virtual plp::DataRange *get_delta(EnumSummaryPeriod period_type_param) = 0;
+ virtual plp::DataRange *get_max(EnumSummaryPeriod period_type_param) = 0;
+ virtual plp::DataRange *get_min(EnumSummaryPeriod period_type_param) = 0;
+ protected:
+ std::string device_id;
+ plp::Date *date;
+ plp::DataRange *store_data;
+ plp::DataRange *range_data;
+ bool load(std::string fname_param);
+ };
+}
+
+#endif /* STORE_HH_ */
--- /dev/null
+/*
+ * StoreCache.cc
+ *
+ * Created on: Jan 6, 2011
+ * Author: lamikr
+ */
+#include <sstream>
+#include <fstream>
+
+#include "log.h"
+#include "Store.hh"
+#include "StoreCache.hh"
+#include "StoreDay.hh"
+#include "DeviceConfig.hh"
+#include "FileUtil.hh"
+
+using namespace std;
+using namespace plp;
+
+StoreCache::StoreCache(string device_id_param,
+ Date *date_time_param): Store(device_id_param, date_time_param) {
+}
+
+StoreCache::~StoreCache() {
+}
+
+string StoreCache::get_dir_name(string device_id_param,
+ Date *date_time_param,
+ EnumSummaryPeriod period_type_param,
+ EnumSummaryCalculationType calc_type_param) {
+ string ret_val;
+ char buffer[30];
+ string bd_name;
+
+ bd_name = DeviceConfig::get_base_dir_name();
+ bd_name = FileUtil::concat_paths(bd_name, CACHE_DIR_NAME);
+ bd_name = FileUtil::concat_paths(bd_name, device_id_param);
+ bd_name = FileUtil::concat_paths(bd_name, SUMMARY_PERIOD_NAMES_ARRAY[period_type_param]);
+ bd_name = FileUtil::concat_paths(bd_name, CALCULATION_TYPE_NAMES_ARRAY[calc_type_param]);
+ if (period_type_param == PERIOD_YEARLY) {
+ ret_val = bd_name;
+ }
+ else if (period_type_param == PERIOD_MONTHLY) {
+ snprintf(buffer, 30, "%d", date_time_param->year);
+ ret_val = bd_name + "/" + buffer;
+ }
+ else {
+ snprintf(buffer, 30, "%d/%02d", date_time_param->year, date_time_param->month);
+ ret_val = bd_name + "/" + buffer;
+ }
+ return ret_val;
+}
+
+string StoreCache::get_file_name(string device_id_param,
+ Date *date_time_param,
+ EnumSummaryPeriod period_type_param,
+ EnumSummaryCalculationType calc_type_param) {
+ string ret_val;
+ string fname;
+ char buffer[30];
+
+ if (period_type_param == PERIOD_YEARLY) {
+ snprintf(buffer, 30, "%d", date_time_param->year);
+ }
+ else if (period_type_param == PERIOD_MONTHLY) {
+ snprintf(buffer, 30, "%d-%02d",
+ date_time_param->year,
+ date_time_param->month);
+ }
+ else {
+ snprintf(buffer, 30, "%d-%02d-%02d",
+ date_time_param->year,
+ date_time_param->month,
+ date_time_param->day);
+ }
+ fname = buffer;
+ fname = fname + DATAFILE_SUFFIX;
+ ret_val = get_dir_name(device_id_param, date_time_param, period_type_param, calc_type_param);
+ ret_val = FileUtil::concat_paths(ret_val, fname);
+ return ret_val;
+}
+
+plp::Date *StoreCache::get_scanning_limit_date(EnumSummaryPeriod period_type_param) {
+ Data *cur_data;;
+ Date *ret_val;
+
+ cur_data = get_latest_data(date, device_id, period_type_param);
+ if (cur_data != NULL) {
+ ret_val = cur_data->get_date().clone();
+ ret_val->next_second();
+ delete(cur_data);
+ cur_data = NULL;
+ }
+ else {
+ ret_val = date->clone();
+ if (period_type_param == PERIOD_YEARLY) {
+ ret_val->next_year();
+ }
+ else {
+ ret_val->next_month();
+ }
+ }
+ return ret_val;
+}
+
+DataRange *StoreCache::get_mean(EnumSummaryPeriod period_type_param) {
+ int row_count;
+ DataRange *ret_val;
+ Data *dta;
+ string fname;
+
+ ret_val = NULL;
+ fname = get_file_name(device_id,
+ date,
+ period_type_param,
+ MEAN);
+ if (store_data == NULL) {
+ if (access(fname.c_str(), R_OK) == 0) {
+ load(fname);
+ }
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ ret_val = new DataRange();
+ dta = store_data->get(0);
+ ret_val->add(dta);
+ delete(dta);
+ }
+ }
+ if (ret_val == NULL) {
+ switch(period_type_param) {
+ case PERIOD_YEARLY:
+ case PERIOD_MONTHLY:
+ {
+ Data *cur_data;
+ Data *res_data;
+ Date *cur_date;
+ Date *max_date;
+ int ii;
+ int cnt;
+ int val_cnt;
+ DataRange *dr;
+ Store *store;
+
+ cur_date = date->clone();
+ max_date = get_scanning_limit_date(period_type_param);
+ cur_data = NULL;
+ res_data = NULL;
+ cnt = 0;
+ while(cur_date->before(max_date)) {
+ if (period_type_param == PERIOD_YEARLY) {
+ store = new StoreCache(device_id, cur_date);
+ dr = store->get_mean(PERIOD_MONTHLY);
+ }
+ else {
+ store = new StoreDay(device_id, cur_date);
+ dr = store->get_mean(PERIOD_DAILY);
+ }
+ if (dr != NULL) {
+ cur_data = dr->get_first();
+ if (cur_data != NULL) {
+ cnt++;
+ if (res_data == NULL) {
+ res_data = cur_data;
+ val_cnt = res_data->get_value_count();
+ }
+ else {
+ for (ii = 0; ii < val_cnt; ii++) {
+ res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
+ }
+ delete(cur_data);
+ }
+ }
+ delete(dr);
+ }
+ delete(store);
+ if (period_type_param == PERIOD_YEARLY) {
+ cur_date->next_month();
+ }
+ else {
+ cur_date->next_day();
+ }
+ }
+ if ((res_data != NULL) &&
+ (cnt > 0)) {
+ for (ii = 0; ii < val_cnt; ii++) {
+ res_data->value_arr[ii] = res_data->value_arr[ii] / cnt;
+ }
+ ret_val = new DataRange(res_data);
+ save(fname, ret_val, 4);
+ delete(res_data);
+ }
+ delete(cur_date);
+ delete(max_date);
+ }
+ break;
+ case PERIOD_DAILY:
+ case PERIOD_HOURLY:
+ case PERIOD_MINUTELY:
+ case PERIOD_SECONDLY: {
+ StoreDay *store;
+
+ store = new StoreDay(device_id, date);
+ ret_val = store->get_mean(period_type_param);
+ if ((period_type_param != PERIOD_MINUTELY) ||
+ (period_type_param != PERIOD_SECONDLY)) {
+ // no need cache second or minute data
+ save(fname, ret_val, 4);
+ }
+ delete(store);
+ }
+ break;
+ }
+ }
+ return ret_val;
+}
+
+DataRange *StoreCache::get_sum(EnumSummaryPeriod period_type_param) {
+ int row_count;
+ DataRange *ret_val;
+ Data *dta;
+ string fname;
+ Store *store;
+
+ ret_val = NULL;
+ fname = get_file_name(device_id,
+ date,
+ period_type_param,
+ SUM);
+ if (store_data == NULL) {
+ if (access(fname.c_str(), R_OK) == 0) {
+ load(fname);
+ }
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ ret_val = new DataRange();
+ dta = store_data->get(0);
+ ret_val->add(dta);
+ delete(dta);
+ }
+ }
+ if (ret_val == NULL) {
+ switch(period_type_param) {
+ case PERIOD_YEARLY:
+ case PERIOD_MONTHLY: {
+ Data *cur_data;
+ Data *res_data;
+ Date *cur_date;
+ Date *max_date;
+ int ii;
+ int cnt;
+ int val_cnt;
+ DataRange *dr;
+
+ cur_date = date->clone();
+ max_date = get_scanning_limit_date(period_type_param);
+ cur_data = NULL;
+ res_data = NULL;
+ cnt = 0;
+ while(cur_date->before(max_date)) {
+ if (period_type_param == PERIOD_YEARLY) {
+ store = new StoreCache(device_id, cur_date);
+ dr = store->get_sum(PERIOD_MONTHLY);
+ }
+ else {
+ store = new StoreDay(device_id, cur_date);
+ dr = store->get_sum(PERIOD_DAILY);
+ }
+ if (dr != NULL) {
+ cur_data = dr->get_first();
+ if (cur_data != NULL) {
+ cnt++;
+ if (res_data == NULL) {
+ res_data = cur_data;
+ }
+ else {
+ val_cnt = res_data->get_value_count();
+ for (ii = 0; ii < val_cnt; ii++) {
+ res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
+ }
+ delete(cur_data);
+ }
+ }
+ delete(dr);
+ }
+ delete(store);
+ if (period_type_param == PERIOD_YEARLY) {
+ cur_date->next_month();
+ }
+ else {
+ cur_date->next_day();
+ }
+ }
+ if ((res_data != NULL) &&
+ (cnt > 0)) {
+ ret_val = new DataRange(res_data);
+ save(fname, ret_val, 4);
+ delete(res_data);
+ }
+ delete(cur_date);
+ delete(max_date);
+ }
+ break;
+ case PERIOD_DAILY:
+ case PERIOD_HOURLY:
+ case PERIOD_MINUTELY:
+ case PERIOD_SECONDLY:
+ store = new StoreDay(device_id, date);
+ ret_val = store->get_sum(period_type_param);
+ if ((period_type_param != PERIOD_MINUTELY) ||
+ (period_type_param != PERIOD_SECONDLY)) {
+ // no need cache second or minute data
+ save(fname, ret_val, 4);
+ }
+ delete(store);
+ break;
+ }
+ }
+ return ret_val;
+}
+
+DataRange *StoreCache::get_delta(EnumSummaryPeriod period_type_param) {
+ int row_count;
+ DataRange *ret_val;
+ Data *dta;
+ string fname;
+ StoreDay *store;
+
+ ret_val = NULL;
+ fname = get_file_name(device_id,
+ date,
+ period_type_param,
+ DELTA);
+ if (store_data == NULL) {
+ if (access(fname.c_str(), R_OK) == 0) {
+ // read from cache file
+ load(fname);
+ }
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ ret_val = new DataRange();
+ dta = store_data->get(0);
+ ret_val->add(dta);
+ delete(dta);
+ }
+ }
+ if (ret_val == NULL) {
+ switch(period_type_param) {
+ case PERIOD_YEARLY: {
+ Data *first_data;
+ Data *last_data;
+ int ii;
+ int cnt;
+
+ first_data = get_oldest_data(date, device_id, PERIOD_YEARLY);
+ if (first_data != NULL) {
+ last_data = get_latest_data(date, device_id, PERIOD_YEARLY);
+ if (last_data != NULL) {
+ ret_val = new DataRange();
+ cnt = last_data->get_value_count();
+ for (ii = 0; ii < cnt; ii++) {
+ last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
+ }
+ ret_val->add(last_data);
+ delete(last_data);
+ }
+ delete(first_data);
+ save(fname, ret_val, 4);
+ }
+ else {
+ log_error("Could not read first or last data item from device %s for year: %d", device_id.c_str(), date->year);
+ }
+ }
+ break;
+ case PERIOD_MONTHLY: {
+ Data *first_data;
+ Data *last_data;
+ Data *cur_data;
+ Date *cur_date;
+ Date *limit_date;
+ int ii;
+ int cnt;
+
+ cur_date = date->clone();
+ limit_date = date->clone();
+ limit_date->next_month();
+ first_data = NULL;
+ last_data = NULL;
+ while(cur_date->before(limit_date)) {
+ store = new StoreDay(device_id, cur_date);
+ if (first_data == NULL) {
+ cur_data = store->get_oldest_data();
+ if (cur_data != NULL) {
+ first_data = cur_data->clone();
+ last_data = cur_data->clone();
+ delete(cur_data);
+ }
+ }
+ cur_data = store->get_latest_data();
+ if (cur_data != NULL) {
+ if (last_data != NULL) {
+ delete(last_data);
+ }
+ last_data = cur_data;
+ }
+ delete(store);
+ cur_date->next_day();
+ }
+ delete(cur_date);
+ delete(limit_date);
+ if (first_data != NULL) {
+ if (last_data == NULL) {
+ last_data = first_data->clone();
+ }
+ cnt = last_data->get_value_count();
+ for (ii = 0; ii < cnt; ii++) {
+ last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
+ }
+ cur_date = first_data->get_date().clone();
+ last_data->set_date(cur_date);
+ delete(cur_date);
+ ret_val = new DataRange(last_data);
+ delete(first_data);
+ delete(last_data);
+ save(fname, ret_val, 4);
+ }
+ }
+ break;
+ case PERIOD_DAILY:
+ case PERIOD_HOURLY:
+ case PERIOD_MINUTELY:
+ case PERIOD_SECONDLY:
+ store = new StoreDay(device_id, date);
+ ret_val = store->get_delta(period_type_param);
+ if ((period_type_param != PERIOD_MINUTELY) ||
+ (period_type_param != PERIOD_SECONDLY)) {
+ // no need cache second or minute data
+ save(fname, ret_val, 4);
+ }
+ delete(store);
+ break;
+ }
+ }
+ return ret_val;
+}
+
+DataRange *StoreCache::get_max(EnumSummaryPeriod period_type_param) {
+ int row_count;
+ DataRange *ret_val;
+ Data *dta;
+ string fname;
+ Store *store;
+
+ ret_val = NULL;
+ fname = get_file_name(device_id,
+ date,
+ period_type_param,
+ MAX);
+ if (store_data == NULL) {
+ if (access(fname.c_str(), R_OK) == 0) {
+ load(fname);
+ }
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ ret_val = new DataRange();
+ dta = store_data->get(0);
+ ret_val->add(dta);
+ delete(dta);
+ }
+ }
+ if (ret_val == NULL) {
+ switch(period_type_param) {
+ case PERIOD_YEARLY:
+ case PERIOD_MONTHLY: {
+ Data *cur_data;
+ Data *res_data;
+ Date *cur_date;
+ Date *max_date;
+ int ii;
+ int cnt;
+ int val_cnt;
+ DataRange *dr;
+
+ cur_date = date->clone();
+ max_date = get_scanning_limit_date(period_type_param);
+ cur_data = NULL;
+ res_data = NULL;
+ cnt = 0;
+ while(cur_date->before(max_date)) {
+ if (period_type_param == PERIOD_YEARLY) {
+ store = new StoreCache(device_id, cur_date);
+ dr = store->get_max(PERIOD_MONTHLY);
+ }
+ else {
+ store = new StoreDay(device_id, cur_date);
+ dr = store->get_max(PERIOD_DAILY);
+ }
+ if (dr != NULL) {
+ cur_data = dr->get_first();
+ if (cur_data != NULL) {
+ cnt++;
+ if (res_data == NULL) {
+ res_data = cur_data;
+ }
+ else {
+ val_cnt = res_data->get_value_count();
+ int changed = 0;
+ for (ii = 0; ii < val_cnt; ii++) {
+ if (cur_data->value_arr[ii] > res_data->value_arr[ii]) {
+ res_data->value_arr[ii] = cur_data->value_arr[ii];
+ changed = 1;
+ }
+ }
+ if (changed == 1) {
+ Date new_date;
+
+ new_date = cur_data->get_date();
+ res_data->set_date(&new_date);
+ }
+ delete(cur_data);
+ }
+ }
+ delete(dr);
+ }
+ delete(store);
+ if (period_type_param == PERIOD_YEARLY) {
+ cur_date->next_month();
+ }
+ else {
+ cur_date->next_day();
+ }
+ }
+ if ((res_data != NULL) &&
+ (cnt > 0)) {
+ ret_val = new DataRange(res_data);
+ save(fname, ret_val, 4);
+ delete(res_data);
+ }
+ delete(cur_date);
+ delete(max_date);
+ }
+ break;
+ case PERIOD_DAILY:
+ case PERIOD_HOURLY:
+ case PERIOD_MINUTELY:
+ case PERIOD_SECONDLY:
+ store = new StoreDay(device_id, date);
+ ret_val = store->get_max(period_type_param);
+ if ((period_type_param != PERIOD_MINUTELY) ||
+ (period_type_param != PERIOD_SECONDLY)) {
+ // no need cache second or minute data
+ save(fname, ret_val, 4);
+ }
+ delete(store);
+ break;
+ }
+ }
+ return ret_val;
+}
+
+DataRange *StoreCache::get_min(EnumSummaryPeriod period_type_param) {
+ int row_count;
+ DataRange *ret_val;
+ Data *dta;
+ string fname;
+ Store *store;
+
+ ret_val = NULL;
+ fname = get_file_name(device_id,
+ date,
+ period_type_param,
+ MIN);
+ if (store_data == NULL) {
+ if (access(fname.c_str(), R_OK) == 0) {
+ load(fname);
+ }
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ ret_val = new DataRange();
+ dta = store_data->get(0);
+ ret_val->add(dta);
+ delete(dta);
+ }
+ }
+ if (ret_val == NULL) {
+ switch(period_type_param) {
+ case PERIOD_YEARLY:
+ case PERIOD_MONTHLY: {
+ Data *cur_data;
+ Data *res_data;
+ Date *cur_date;
+ Date *max_date;
+ int ii;
+ int cnt;
+ int val_cnt;
+ DataRange *dr;
+
+ cur_date = date->clone();
+ max_date = get_scanning_limit_date(period_type_param);
+ cur_data = NULL;
+ res_data = NULL;
+ cnt = 0;
+ while(cur_date->before(max_date)) {
+ if (period_type_param == PERIOD_YEARLY) {
+ store = new StoreCache(device_id, cur_date);
+ dr = store->get_min(PERIOD_MONTHLY);
+ }
+ else {
+ store = new StoreDay(device_id, cur_date);
+ dr = store->get_min(PERIOD_DAILY);
+ }
+ if (dr != NULL) {
+ cur_data = dr->get_first();
+ if (cur_data != NULL) {
+ cnt++;
+ if (res_data == NULL) {
+ res_data = cur_data;
+ }
+ else {
+ val_cnt = res_data->get_value_count();
+ int changed = 0;
+ for (ii = 0; ii < val_cnt; ii++) {
+ if (cur_data->value_arr[ii] < res_data->value_arr[ii]) {
+ res_data->value_arr[ii] = cur_data->value_arr[ii];
+ changed = 1;
+ }
+ }
+ if (changed == 1) {
+ Date new_date;
+
+ new_date = cur_data->get_date();
+ res_data->set_date(&new_date);
+ }
+ delete(cur_data);
+ }
+ }
+ delete(dr);
+ }
+ delete(store);
+ if (period_type_param == PERIOD_YEARLY) {
+ cur_date->next_month();
+ }
+ else {
+ cur_date->next_day();
+ }
+ }
+ if ((res_data != NULL) &&
+ (cnt > 0)) {
+ ret_val = new DataRange(res_data);
+ save(fname, ret_val, 4);
+ delete(res_data);
+ }
+ delete(cur_date);
+ delete(max_date);
+ }
+ break;
+ case PERIOD_DAILY:
+ case PERIOD_HOURLY:
+ case PERIOD_MINUTELY:
+ case PERIOD_SECONDLY:
+ store = new StoreDay(device_id, date);
+ ret_val = store->get_min(period_type_param);
+ if ((period_type_param != PERIOD_MINUTELY) ||
+ (period_type_param != PERIOD_SECONDLY)) {
+ // no need cache second or minute data
+ save(fname, ret_val, 4);
+ }
+ delete(store);
+ break;
+ }
+ }
+ return ret_val;
+}
+
+void StoreCache::save(std::string fname_param, plp::DataRange *datarange_param, int decimal_count_param) {
+ string line;
+ Data *data;
+ ofstream *ostream;
+ int ii;
+ int cnt;
+
+ cnt = datarange_param->get_count();
+ ostream = NULL;
+ //log_info("[%s] cacheing %d data values.\n", device_id.c_str(), cnt);
+ ostream = FileUtil::open_for_writing(fname_param.c_str());
+ if ((ostream != NULL) &&
+ (ostream->is_open() == true)) {
+ // TODO: add mutex to protect string_list while it's read and emptied
+ for(ii = 0; ii < cnt; ii++) {
+ data = datarange_param->get(ii);
+ if (data != NULL) {
+ line = data->to_string(decimal_count_param);
+ if (line.length() > 0) {
+ *ostream << line << endl;
+ }
+ delete(data);
+ }
+ }
+ }
+ else {
+ log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), fname_param.c_str());
+ }
+ if (ostream != NULL) {
+ ostream->close();
+ delete(ostream);
+ }
+}
+
+Data *StoreCache::get_oldest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
+ int size;
+ unsigned int ii;
+ string year_dr;
+ string mon_dr;
+ vector<string> mon_vcr;
+ vector<string> dta_vcr;
+ string f_name;
+ StoreDay *store;
+ Data *ret_val;
+ string device_dir;
+ char buffer[30];
+ string year_name;
+
+ ret_val = NULL;
+ if (period_type_param == PERIOD_YEARLY) {
+ snprintf(buffer, 30, "%d", date_param->year);
+ year_name.append(buffer);
+ device_dir = DeviceConfig::get_base_dir_name();
+ device_dir = FileUtil::concat_paths(device_dir, device_id_param);
+ year_dr = FileUtil::concat_paths(device_dir, year_name);
+ mon_vcr = FileUtil::get_subdirectories(year_dr);
+ for (ii = 0; ii < mon_vcr.size(); ii++) {
+ mon_dr = mon_vcr.at(ii);
+ mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
+ // scan data files from month dir
+ dta_vcr = FileUtil::get_data_files(mon_dr);
+ size = dta_vcr.size();
+ if (size > 0) {
+ f_name = dta_vcr.at(0);
+ f_name = FileUtil::concat_paths(mon_dr, f_name);
+ store = new StoreDay(f_name);
+ ret_val = store->get_oldest_data();
+ delete(store);
+ break;
+ }
+ }
+ }
+ else if (period_type_param == PERIOD_MONTHLY) {
+ ret_val = NULL;
+ snprintf(buffer, 30, "%d", date_param->year);
+ year_name.append(buffer);
+ device_dir = DeviceConfig::get_base_dir_name();
+ device_dir = FileUtil::concat_paths(device_dir, device_id_param);
+ year_dr = FileUtil::concat_paths(device_dir, year_name);
+ snprintf(buffer, 30, "%02d", date_param->month);
+ mon_dr.append(buffer);
+ mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
+ // scan data files from month dir
+ dta_vcr = FileUtil::get_data_files(mon_dr);
+ size = dta_vcr.size();
+ if (size > 0) {
+ f_name = dta_vcr.at(0);
+ f_name = FileUtil::concat_paths(mon_dr, f_name);
+ store = new StoreDay(f_name);
+ ret_val = store->get_oldest_data();
+ delete(store);
+ }
+
+ }
+ else {
+ store = new StoreDay(device_id_param, date_param);
+ ret_val = store->get_oldest_data();
+ delete(store);
+ }
+ return ret_val;
+}
+
+Data *StoreCache::get_latest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
+ int ii;
+ string mon_dr;
+ vector<string> mon_vcr;
+ vector<string> dta_vcr;
+ string f_name;
+ StoreDay *store;
+ Data *ret_val;
+ string year_dr;
+ int size;
+ string device_dir;
+ char buffer[30];
+ string year_name;
+
+ ret_val = NULL;
+ if (period_type_param == PERIOD_YEARLY) {
+ snprintf(buffer, 30, "%d", date_param->year);
+ year_name.append(buffer);
+ device_dir = DeviceConfig::get_base_dir_name();
+ device_dir = FileUtil::concat_paths(device_dir, device_id_param);
+ year_dr = FileUtil::concat_paths(device_dir, year_name);
+ mon_vcr = FileUtil::get_subdirectories(year_dr);
+ for (ii = mon_vcr.size() - 1; ii >= 0; ii--) {
+ mon_dr = mon_vcr.at(ii);
+ mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
+ // scan data files from month dir
+ dta_vcr = FileUtil::get_data_files(mon_dr);
+ size = dta_vcr.size();
+ if (size > 0) {
+ f_name = dta_vcr.at(size - 1);
+ f_name = FileUtil::concat_paths(mon_dr, f_name);
+ store = new StoreDay(f_name);
+ ret_val = store->get_latest_data();
+ delete(store);
+ break;
+ }
+ }
+ }
+ else if (period_type_param == PERIOD_MONTHLY) {
+ ret_val = NULL;
+ snprintf(buffer, 30, "%d", date_param->year);
+ year_name.append(buffer);
+ device_dir = DeviceConfig::get_base_dir_name();
+ device_dir = FileUtil::concat_paths(device_dir, device_id_param);
+ year_dr = FileUtil::concat_paths(device_dir, year_name);
+ snprintf(buffer, 30, "%02d", date_param->month);
+ mon_dr.append(buffer);
+ mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
+ // scan data files from month dir
+ dta_vcr = FileUtil::get_data_files(mon_dr);
+ size = dta_vcr.size();
+ if (size > 0) {
+ f_name = dta_vcr.at(size - 1);
+ f_name = FileUtil::concat_paths(mon_dr, f_name);
+ store = new StoreDay(f_name);
+ ret_val = store->get_latest_data();
+ delete(store);
+ }
+
+ }
+ else {
+ store = new StoreDay(device_id_param, date_param);
+ ret_val = store->get_latest_data();
+ delete(store);
+ }
+ return ret_val;
+}
--- /dev/null
+/*
+ * StoreCache.hh
+ *
+ * Created on: Jan 6, 2011
+ * Author: lamikr
+ */
+
+#ifndef STORECACHE_HH_
+#define STORECACHE_HH_
+
+#include <vector>
+#include <list>
+
+#include "Data.hh"
+#include "Date.hh"
+#include "Store.hh"
+
+namespace plp {
+ class StoreCache: public plp::Store {
+ public:
+ StoreCache(std::string device_id_param,
+ plp::Date *date_time_param);
+ virtual ~StoreCache();
+ plp::DataRange *get_sum(EnumSummaryPeriod period_type_param);
+ plp::DataRange *get_mean(EnumSummaryPeriod period_type_param);
+ plp::DataRange *get_delta(EnumSummaryPeriod period_type_param);
+ plp::DataRange *get_max(EnumSummaryPeriod period_type_param);
+ plp::DataRange *get_min(EnumSummaryPeriod period_type_param);
+ static plp::Data *get_oldest_data(plp::Date *date_param, std::string device_id_param, EnumSummaryPeriod period_type_param);
+ static plp::Data *get_latest_data(plp::Date *date_param, std::string device_id_param, EnumSummaryPeriod period_type_param);
+ protected:
+ static std::string get_dir_name(std::string device_id_param,
+ Date *date_time_param,
+ EnumSummaryPeriod period_type_param,
+ EnumSummaryCalculationType calc_type_param);
+ static std::string get_file_name(std::string device_id_param,
+ Date *date_time_param,
+ EnumSummaryPeriod period_type_param,
+ EnumSummaryCalculationType calc_type_param);
+ void save(std::string fname_param, plp::DataRange *datarange_param, int decimal_count_param);
+ private:
+ plp::Date *get_scanning_limit_date(EnumSummaryPeriod period_type_param);
+ };
+}
+
+#endif /* STORECACHE_HH_ */
--- /dev/null
+/*
+ * Store.cc
+ *
+ * Created on: Oct 31, 2010
+ * Author: lamikr
+ */
+
+#include <list>
+#include <string>
+#include <fstream>
+#include <limits>
+
+#include <time.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "DeviceConfig.hh"
+#include "StoreDay.hh"
+#include "FileUtil.hh"
+
+using namespace std;
+using namespace plp;
+
+StoreDay::StoreDay(string device_id_param,
+ Date *date_time_param): Store(device_id_param, date_time_param) {
+ store_fname = get_file_name(device_id_param, date_time_param);
+}
+
+StoreDay::StoreDay(string fname_param): Store("", NULL) {
+ store_data = NULL;
+ range_data = NULL;
+ store_fname = fname_param;
+}
+
+StoreDay::~StoreDay() {
+ if (store_data != NULL) {
+ delete(store_data);
+ store_data = NULL;
+ }
+}
+
+string StoreDay::get_dir_name(string device_id, Date *date_time_param) {
+ string ret_val;
+ char buffer[30];
+ string bd_name;
+
+ snprintf(buffer, 30, "%d/%02d", date_time_param->year, date_time_param->month);
+ bd_name = DeviceConfig::get_base_dir_name();
+ bd_name = FileUtil::concat_paths(bd_name, device_id);
+ ret_val = bd_name + "/" + buffer;
+ return ret_val;
+}
+
+string StoreDay::get_file_name(string device_id, Date *date_time_param) {
+ string ret_val;
+ string fname;
+ char buffer[30];
+
+ snprintf(buffer, 30, "%d-%02d-%02d", date_time_param->year, date_time_param->month, date_time_param->day);
+ fname = buffer;
+ fname = fname + DATAFILE_SUFFIX;
+ ret_val = get_dir_name(device_id, date_time_param);
+ ret_val = FileUtil::concat_paths(ret_val, fname);
+ return ret_val;
+}
+
+void StoreDay::save(string device_id,
+ std::list<Data *> *data_list,
+ int dec_precision) {
+ string n_path;
+ string f_path;
+ string line;
+ Data *data;
+ ofstream *ostream;
+ Date date;
+ list<Data *>::iterator iter;
+
+ ostream = NULL;
+ f_path = "";
+ log_info("[%s] writing %d data values to save.\n", device_id.c_str(), data_list->size());
+ // TODO: add mutex to protect string_list while it's read and emptied
+ for(iter = data_list->begin(); iter != data_list->end(); iter++) {
+ data = (Data *)*iter;
+ date = data->get_date();
+ n_path = get_file_name(device_id, &date);
+ if (n_path.compare(f_path) != 0) {
+ if (ostream != NULL) {
+ ostream->close();
+ delete(ostream);
+ }
+ f_path = n_path;
+ log_info("[%s] Opening file for save: %s\n", device_id.c_str(), f_path.c_str());
+ ostream = FileUtil::open_for_writing(f_path.c_str());
+ }
+ if ((ostream != NULL) &&
+ (ostream->is_open() == true)) {
+ line = data->to_string(dec_precision);
+ if (line.length() > 0) {
+ log_debug("storing line: %s\n", line.c_str());
+ *ostream << line << endl;
+ }
+ }
+ else {
+ log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), f_path.c_str());
+ }
+ }
+ if (ostream != NULL) {
+ ostream->close();
+ delete(ostream);
+ }
+}
+
+bool StoreDay::load() {
+ return Store::load(store_fname);
+}
+
+bool StoreDay::exist(string fname_param) {
+ bool ret_val;
+ ret_val = (access(fname_param.c_str(), F_OK) == 0);
+ return ret_val;
+}
+
+bool StoreDay::exist() {
+ return exist(store_fname);
+}
+
+static int get_summary_period_as_freq_seconds(EnumSummaryPeriod period_type_param) {
+ int ret_val;
+
+ ret_val = 3600;
+ switch(period_type_param) {
+ case PERIOD_SECONDLY:
+ ret_val = 1;
+ break;
+ case PERIOD_MINUTELY:
+ ret_val = 60;
+ break;
+ case PERIOD_HOURLY:
+ ret_val = 3600;
+ break;
+ case PERIOD_DAILY:
+ case PERIOD_MONTHLY:
+ case PERIOD_YEARLY:
+ default:
+ // -1 as freq means that show all data from the current store
+ ret_val = -1;
+ break;
+ }
+ return ret_val;
+}
+
+plp::DataRange *StoreDay::get_sum(EnumSummaryPeriod period_type_param) {
+ int row_count;
+ int col_count;
+ int jj;
+ int ii;
+ Data *data;
+ Data *calc;
+ Date *limit_d;
+ Date date;
+ DataRange *ret_val;
+ int frq_sec;
+
+ ret_val = new DataRange();
+ calc = NULL;
+ limit_d = NULL;
+ frq_sec = get_summary_period_as_freq_seconds(period_type_param);
+ if (store_data == NULL) {
+ load();
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ col_count = store_data->get_data_item_value_count();
+ if (col_count > 0) {
+ for (ii = 0; ii < row_count; ii++) {
+ data = store_data->get(ii);
+ if (data != NULL) {
+ if (calc == NULL) {
+ calc = data->clone();
+ limit_d = data->get_date().clone();
+ limit_d->min = 0;
+ limit_d->sec = 0;
+ limit_d->inc_seconds(frq_sec);
+ }
+ else {
+ date = data->get_date();
+ if ((ii <= (row_count -1)) &&
+ ((frq_sec == -1) || (date.before(limit_d)))) {
+ for (jj = 0; jj < col_count; jj++) {
+ calc->value_arr[jj] = calc->value_arr[jj] + data->value_arr[jj];
+ }
+ }
+ if ((ii >= (row_count -1)) ||
+ ((frq_sec != -1) && (date.before(limit_d) == false))) {
+ ret_val->add(calc);
+ delete(calc);
+ calc = data->clone();
+ if (limit_d != NULL) {
+ delete(limit_d);
+ }
+ limit_d = data->get_date().clone();
+ limit_d->min = 0;
+ limit_d->sec = 0;
+ limit_d->inc_seconds(frq_sec);
+ }
+ }
+ delete(data);
+ }
+ }
+ if (calc != NULL) {
+ delete(calc);
+ calc = NULL;
+ }
+ if (limit_d != NULL) {
+ delete(limit_d);
+ }
+ }
+ }
+ }
+ return ret_val;
+}
+
+plp::DataRange *StoreDay::get_mean(EnumSummaryPeriod period_type_param) {
+ int row_count;
+ int col_count;
+ int d_count;
+ int jj;
+ int ii;
+ Data *data;
+ Data *calc;
+ Date *limit_d;
+ Date date;
+ DataRange *ret_val;
+ int frq_sec;
+
+ ret_val = new DataRange();
+ calc = NULL;
+ limit_d = NULL;
+ d_count = 1;
+ frq_sec = get_summary_period_as_freq_seconds(period_type_param);
+ if (store_data == NULL) {
+ load();
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ col_count = store_data->get_data_item_value_count();
+ if (col_count > 0) {
+ for (ii = 0; ii < row_count; ii++) {
+ data = store_data->get(ii);
+ if (data != NULL) {
+ if (calc == NULL) {
+ d_count = 1;
+ calc = data->clone();
+ limit_d = data->get_date().clone();
+ limit_d->min = 0;
+ limit_d->sec = 0;
+ limit_d->inc_seconds(frq_sec);
+ }
+ else {
+ date = data->get_date();
+ if ((ii <= (row_count -1)) &&
+ ((frq_sec == -1) || (date.before(limit_d)))) {
+ for (jj = 0; jj < col_count; jj++) {
+ calc->value_arr[jj] = calc->value_arr[jj] + data->value_arr[jj];
+ }
+ d_count++;
+ }
+ if ((ii >= (row_count -1)) ||
+ ((frq_sec != -1) && (date.before(limit_d) == false))) {
+ for (jj = 0; jj < col_count; jj++) {
+ calc->value_arr[jj] = calc->value_arr[jj] / d_count;
+ }
+ ret_val->add(calc);
+ delete(calc);
+ d_count = 1;
+ calc = data->clone();
+ if (limit_d != NULL) {
+ delete(limit_d);
+ }
+ limit_d = data->get_date().clone();
+ limit_d->min = 0;
+ limit_d->sec = 0;
+ limit_d->inc_seconds(frq_sec);
+ }
+ }
+ delete(data);
+ }
+ }
+ if (calc != NULL) {
+ delete(calc);
+ calc = NULL;
+ }
+ if (limit_d != NULL) {
+ delete(limit_d);
+ }
+ }
+ }
+ }
+ return ret_val;
+}
+
+plp::DataRange *StoreDay::get_delta(EnumSummaryPeriod period_type_param) {
+ int row_count;
+ int col_count;
+ int jj;
+ int ii;
+ Data *data;
+ Data *calc1;
+ Data *calc2;
+ Date *limit_d;
+ Date date;
+ DataRange *ret_val;
+ int frq_sec;
+
+ ret_val = new DataRange();
+ calc1 = NULL;
+ calc2 = NULL;
+ limit_d = NULL;
+ frq_sec = get_summary_period_as_freq_seconds(period_type_param);
+ if (store_data == NULL) {
+ load();
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ col_count = store_data->get_data_item_value_count();
+ if (col_count > 0) {
+ for (ii = 0; ii < row_count; ii++) {
+ data = store_data->get(ii);
+ if (data != NULL) {
+ if (calc1 == NULL) {
+ calc1 = data->clone();
+ limit_d = data->get_date().clone();
+ limit_d->min = 0;
+ limit_d->sec = 0;
+ limit_d->inc_seconds(frq_sec);
+ if (calc2 != NULL) {
+ delete(calc2);
+ }
+ calc2 = NULL;
+ }
+ else {
+ date = data->get_date();
+ if ((ii <= (row_count -1)) &&
+ ((frq_sec == -1) || (date.before(limit_d)))) {
+ if (calc2 != NULL) {
+ delete(calc2);
+ }
+ calc2 = data->clone();
+ }
+ if ((ii >= (row_count -1)) ||
+ ((frq_sec != -1) && (date.before(limit_d) == false))) {
+ if (calc2 == NULL) {
+ calc2 = calc1->clone();
+ }
+ for (jj = 0; jj < col_count; jj++) {
+ calc2->value_arr[jj] = calc2->value_arr[jj] - calc1->value_arr[jj];
+ }
+ ret_val->add(calc2);
+ delete(calc1);
+ calc1 = data->clone();
+ delete(calc2);
+ calc2 = NULL;
+ if (limit_d != NULL) {
+ delete(limit_d);
+ }
+ limit_d = data->get_date().clone();
+ limit_d->min = 0;
+ limit_d->sec = 0;
+ limit_d->inc_seconds(frq_sec);
+ }
+ }
+ delete(data);
+ }
+ }
+ if (calc1 != NULL) {
+ delete(calc1);
+ calc1 = NULL;
+ }
+ if (calc2 != NULL) {
+ delete(calc2);
+ calc2 = NULL;
+ }
+ if (limit_d != NULL) {
+ delete(limit_d);
+ }
+ }
+ }
+ }
+ return ret_val;
+}
+
+plp::DataRange *StoreDay::get_max_or_min(EnumSummaryPeriod period_type_param, bool max) {
+ int row_count;
+ int col_count;
+ int jj;
+ int ii;
+ Data *data;
+ Data *calc;
+ Date *limit_d;
+ Date date;
+ DataRange *ret_val;
+ int frq_sec;
+
+ ret_val = new DataRange();
+ calc = NULL;
+ limit_d = NULL;
+ frq_sec = get_summary_period_as_freq_seconds(period_type_param);
+ if (store_data == NULL) {
+ load();
+ }
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ col_count = store_data->get_data_item_value_count();
+ if (col_count > 0) {
+ for (ii = 0; ii < row_count; ii++) {
+ data = store_data->get(ii);
+ if (data != NULL) {
+ if (calc == NULL) {
+ calc = data->clone();
+ limit_d = data->get_date().clone();
+ limit_d->min = 0;
+ limit_d->sec = 0;
+ limit_d->inc_seconds(frq_sec);
+ }
+ else {
+ date = data->get_date();
+ if ((ii <= (row_count -1)) &&
+ ((frq_sec == -1) || (date.before(limit_d)))) {
+ int changed = 0;
+ if (max == true) {
+ for (jj = 0; jj < col_count; jj++) {
+ if (calc->value_arr[jj] < data->value_arr[jj]) {
+ calc->value_arr[jj] = data->value_arr[jj];
+ changed = 1;
+ }
+ }
+ }
+ else {
+ for (jj = 0; jj < col_count; jj++) {
+ if (data->value_arr[jj] < calc->value_arr[jj]) {
+ calc->value_arr[jj] = data->value_arr[jj];
+ changed = 1;
+ }
+ }
+ }
+ if (changed == 1) {
+ Date new_date;
+
+ new_date = data->get_date();
+ calc->set_date(&new_date);
+ }
+ }
+ if ((ii >= (row_count -1)) ||
+ ((frq_sec != -1) && (date.before(limit_d) == false))) {
+ ret_val->add(calc);
+ delete(calc);
+ calc = data->clone();
+ if (limit_d != NULL) {
+ delete(limit_d);
+ }
+ limit_d = data->get_date().clone();
+ limit_d->min = 0;
+ limit_d->sec = 0;
+ limit_d->inc_seconds(frq_sec);
+ }
+ }
+ delete(data);
+ }
+ }
+ if (calc != NULL) {
+ delete(calc);
+ calc = NULL;
+ }
+ if (limit_d != NULL) {
+ delete(limit_d);
+ }
+ }
+ }
+ }
+ return ret_val;
+}
+
+plp::DataRange *StoreDay::get_max(EnumSummaryPeriod period_type_param) {
+ DataRange *ret_val;
+
+ ret_val = get_max_or_min(period_type_param, true);
+ return ret_val;
+}
+
+plp::DataRange *StoreDay::get_min(EnumSummaryPeriod period_type_param) {
+ DataRange *ret_val;
+
+ ret_val = get_max_or_min(period_type_param, false);
+ return ret_val;
+}
+
+DataRange *StoreDay::get_oldest_and_latest_data(string fname_param) {
+ DataRange *ret_val;
+ ifstream in;
+ Data *o_data;
+ Data *n_data;
+ string latest;
+ int row_count;
+ string line;
+ string prev_line;
+
+ ret_val = NULL;
+ o_data = NULL;
+ n_data = NULL;
+ if (store_data != NULL) {
+ row_count = store_data->get_count();
+ if (row_count > 0) {
+ o_data = store_data->get(0);
+ n_data = store_data->get(row_count - 1);
+ }
+ }
+ else {
+ if (range_data != NULL) {
+ row_count = range_data->get_count();
+ if (row_count > 0) {
+ o_data = range_data->get(0);
+ n_data = range_data->get(row_count - 1);
+ }
+ }
+ else {
+ in.open(fname_param.c_str());
+ if (in.is_open() == true) {
+ while (in.eof() == false) {
+ getline(in, line);
+ if (line.empty() == false) {
+ if (o_data == NULL) {
+ o_data = Data::parse_string(line);
+ }
+ prev_line = line;
+ }
+ }
+ if (prev_line.empty() == false) {
+ n_data = Data::parse_string(prev_line);
+ }
+ }
+ }
+ }
+ if ((o_data != NULL) &&
+ (n_data != NULL)) {
+ ret_val = new DataRange(o_data);
+ ret_val->add(n_data);
+ if (range_data != NULL) {
+ range_data = new DataRange(o_data);
+ range_data->add(n_data);
+ }
+ }
+ if (o_data != NULL) {
+ delete(o_data);
+ }
+ if (n_data != NULL) {
+ delete(n_data);
+ }
+ return ret_val;
+}
+
+DataRange *StoreDay::get_oldest_and_latest_data() {
+ return get_oldest_and_latest_data(store_fname);
+}
+
+Data *StoreDay::get_oldest_data() {
+ int row_count;
+ Data *ret_val;
+ DataRange *dr;
+
+ ret_val = NULL;
+ dr = get_oldest_and_latest_data();
+ if (dr != NULL) {
+ row_count = dr->get_count();
+ if (row_count >= 1) {
+ ret_val = dr->get(0);
+ }
+ delete(dr);
+ }
+ return ret_val;
+}
+
+Data *StoreDay::get_latest_data() {
+ int row_count;
+ Data *ret_val;
+ DataRange *dr;
+
+ ret_val = NULL;
+ dr = get_oldest_and_latest_data();
+ if (dr != NULL) {
+ row_count = dr->get_count();
+ if (row_count == 2) {
+ ret_val = dr->get(1);
+ }
+ delete(dr);
+ }
+ return ret_val;
+}
--- /dev/null
+/*
+ * Store.hh
+ *
+ * Created on: Oct 31, 2010
+ * Author: lamikr
+ */
+
+#ifndef W1STORE_HH_
+#define W1STORE_HH_
+
+#include <string>
+#include <list>
+#include <vector>
+
+#include <stdbool.h>
+
+#include "Data.hh"
+#include "Date.hh"
+#include "Store.hh"
+
+namespace plp {
+ class StoreDay: public plp::Store {
+ public:
+ StoreDay(std::string device_id_param,
+ plp::Date *date_time_param);
+ StoreDay(std::string file_name_param);
+ virtual ~StoreDay();
+ static void save(std::string device_id, std::list<plp::Data *> *data_list, int dec_precision);
+ plp::DataRange *get_sum(EnumSummaryPeriod period_type_param);
+ plp::DataRange *get_mean(EnumSummaryPeriod period_type_param);
+ plp::DataRange *get_delta(EnumSummaryPeriod period_type_param);
+ plp::DataRange *get_max(EnumSummaryPeriod period_type_param);
+ plp::DataRange *get_min(EnumSummaryPeriod period_type_param);
+ plp::Data *get_oldest_data();
+ plp::Data *get_latest_data();
+ plp::DataRange *get_oldest_and_latest_data();
+ /*
+ * Checks whether store file exist.
+ */
+ bool exist();
+ protected:
+ std::string store_fname;
+ bool load();
+ plp::DataRange *get_max_or_min(EnumSummaryPeriod period_type_param, bool max);
+ static std::string get_dir_name(std::string device_id,
+ plp::Date *date_time_param);
+ static std::string get_file_name(std::string device_id,
+ plp::Date *date_time_param);
+ plp::DataRange *get_oldest_and_latest_data(std::string fname_param);
+ bool exist(std::string fname_param);
+ };
+}
+
+#endif /* W1STORE_HH_ */
enum
{
PLP_OK = 0,
- PLP_ERR_UNKNOWN,
+ PLP_ERR,
+ PLP_ERR_DATA_NOT_FOUND,
C_ERR_MEMORY,
PLP_ERR_IO
};