From 063ec715601bf9662797725cb39732bea0572d26 Mon Sep 17 00:00:00 2001 From: Mika Laitio Date: Sat, 5 Mar 2011 22:48:54 +0200 Subject: [PATCH] w1 independent file cleanups. Moving w1 independent device and store files from lib1wire to libplp. Signed-off-by: Mika Laitio --- configure.ac | 6 +- src/Data.cc | 372 +++++++++++++++++++ src/Data.hh | 68 ++++ src/DataReader.cc | 426 ++++++++++++++++++++++ src/DataReader.hh | 68 ++++ src/Date.cc | 383 ++++++++++++++++++++ src/Date.hh | 61 ++++ src/Device.cc | 19 + src/Device.hh | 25 ++ src/DeviceConfig.cc | 190 ++++++++++ src/DeviceConfig.hh | 65 ++++ src/DeviceData.cc | 52 +++ src/DeviceData.hh | 37 ++ src/DeviceTypes.hh | 15 + src/FileUtil.cc | 288 +++++++++++++++ src/FileUtil.hh | 33 ++ src/Makefile.am | 27 +- src/SensorDevice.hh | 24 ++ src/Store.cc | 78 ++++ src/Store.hh | 36 ++ src/StoreCache.cc | 852 ++++++++++++++++++++++++++++++++++++++++++++ src/StoreCache.hh | 46 +++ src/StoreDay.cc | 604 +++++++++++++++++++++++++++++++ src/StoreDay.hh | 54 +++ src/retval.h | 3 +- 25 files changed, 3829 insertions(+), 3 deletions(-) create mode 100644 src/Data.cc create mode 100644 src/Data.hh create mode 100644 src/DataReader.cc create mode 100644 src/DataReader.hh create mode 100644 src/Date.cc create mode 100644 src/Date.hh create mode 100644 src/Device.cc create mode 100644 src/Device.hh create mode 100644 src/DeviceConfig.cc create mode 100644 src/DeviceConfig.hh create mode 100644 src/DeviceData.cc create mode 100644 src/DeviceData.hh create mode 100644 src/DeviceTypes.hh create mode 100644 src/FileUtil.cc create mode 100644 src/FileUtil.hh create mode 100644 src/SensorDevice.hh create mode 100644 src/Store.cc create mode 100644 src/Store.hh create mode 100644 src/StoreCache.cc create mode 100644 src/StoreCache.hh create mode 100644 src/StoreDay.cc create mode 100644 src/StoreDay.hh diff --git a/configure.ac b/configure.ac index bb27450..ebfa5b1 100644 --- a/configure.ac +++ b/configure.ac @@ -9,11 +9,15 @@ CFLAGS="$CFLAGS -g -Wall -Werror" 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 diff --git a/src/Data.cc b/src/Data.cc new file mode 100644 index 0000000..544f3c8 --- /dev/null +++ b/src/Data.cc @@ -0,0 +1,372 @@ +/* + * DataRange.cc + * + * Created on: Dec 7, 2010 + * Author: lamikr + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "log.h" +#include "Data.hh" +#include "Date.hh" + +using namespace std; +using namespace plp; + +template +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 *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 *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 *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 *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 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(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 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"); +} diff --git a/src/Data.hh b/src/Data.hh new file mode 100644 index 0000000..07bea1a --- /dev/null +++ b/src/Data.hh @@ -0,0 +1,68 @@ +/* + * Data.hh + * + * Created on: Dec 8, 2010 + * Author: lamikr + */ + +#ifndef DATA_HH_ +#define DATA_HH_ + +#include +#include +#include + +#include "Date.hh" + +namespace plp { + class Data { + public: + Data(int size); + Data(int size, double default_value, std::string unit_param); + Data(std::vector *val_vector_param); + Data(std::vector *val_vector_param, std::string unit_param); + Data(std::vector *val_vector_param, plp::Date *date_param, std::string unit_param); + Data(std::valarray *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 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 date_list; + int row_count; + int column_count; + std::string unit; + }; +} + +#endif /* DATA_HH_ */ diff --git a/src/DataReader.cc b/src/DataReader.cc new file mode 100644 index 0000000..1c7e9a3 --- /dev/null +++ b/src/DataReader.cc @@ -0,0 +1,426 @@ +/* + * DataReader.cc + * + * Created on: Nov 7, 2010 + * Author: lamikr + */ +#include + +#include +#include +#include +#include + +#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 +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 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(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 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 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(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 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; +} diff --git a/src/DataReader.hh b/src/DataReader.hh new file mode 100644 index 0000000..3266ec2 --- /dev/null +++ b/src/DataReader.hh @@ -0,0 +1,68 @@ +/* + * DataReader.hh + * + * Created on: Nov 7, 2010 + * Author: lamikr + */ + +#ifndef DATAREADER_H_ +#define DATAREADER_H_ + +#include +#include + +#include "Data.hh" +#include "Date.hh" +#include "DeviceConfig.hh" + +#include + +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 year_vector); + Data *find_latest_data(std::vector year_vector); + DataRange *get_summary(Date *date_param, + EnumSummaryCalculationType calc_type_param, + EnumSummaryPeriod period_type_param); + }; +} + +#endif /* DATAREADER_H_ */ diff --git a/src/Date.cc b/src/Date.cc new file mode 100644 index 0000000..461c9d0 --- /dev/null +++ b/src/Date.cc @@ -0,0 +1,383 @@ +/* + * Date.cc + * + * Created on: Dec 7, 2010 + * Author: lamikr + */ + +#include +#include + +#include +#include +#include + +#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; +} diff --git a/src/Date.hh b/src/Date.hh new file mode 100644 index 0000000..21b6bbe --- /dev/null +++ b/src/Date.hh @@ -0,0 +1,61 @@ +/* + * Date.hh + * + * Created on: Dec 7, 2010 + * Author: lamikr + */ + +#ifndef DATE_HH_ +#define DATE_HH_ + +#include + +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_ */ diff --git a/src/Device.cc b/src/Device.cc new file mode 100644 index 0000000..8923ff8 --- /dev/null +++ b/src/Device.cc @@ -0,0 +1,19 @@ +/* + * Device.cc + * + * Created on: Mar 5, 2011 + * Author: lamikr + */ +#include + +#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) { +} diff --git a/src/Device.hh b/src/Device.hh new file mode 100644 index 0000000..a0984ff --- /dev/null +++ b/src/Device.hh @@ -0,0 +1,25 @@ +/* + * GenericDevice.hh + * + * Created on: Feb 28, 2011 + * Author: lamikr + */ + +#ifndef DEVICE_HH_ +#define DEVICE_HH_ + +#include + +#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_ */ diff --git a/src/DeviceConfig.cc b/src/DeviceConfig.cc new file mode 100644 index 0000000..a78a62f --- /dev/null +++ b/src/DeviceConfig.cc @@ -0,0 +1,190 @@ +/* + * DeviceConfig.cc + * + * Created on: Dec 9, 2010 + * Author: lamikr + */ + +#include "DeviceConfig.hh" + +#include +#include + +#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; +} diff --git a/src/DeviceConfig.hh b/src/DeviceConfig.hh new file mode 100644 index 0000000..90ff28d --- /dev/null +++ b/src/DeviceConfig.hh @@ -0,0 +1,65 @@ +/* + * DeviceConfig.hh + * + * Created on: Dec 9, 2010 + * Author: lamikr + */ + +#ifndef DEVICECONFIG_HH_ +#define DEVICECONFIG_HH_ + +#include + +extern "C" { + #include + #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_ */ diff --git a/src/DeviceData.cc b/src/DeviceData.cc new file mode 100644 index 0000000..60edf5e --- /dev/null +++ b/src/DeviceData.cc @@ -0,0 +1,52 @@ +/* + * DeviceData.cc + * + * Created on: Mar 4, 2011 + * Author: lamikr + */ +#include +#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() { + +} diff --git a/src/DeviceData.hh b/src/DeviceData.hh new file mode 100644 index 0000000..ce0f89a --- /dev/null +++ b/src/DeviceData.hh @@ -0,0 +1,37 @@ +/* + * DeviceData.hh + * + * Created on: Mar 4, 2011 + * Author: lamikr + */ + +#ifndef DEVICEINFO_HH_ +#define DEVICEINFO_HH_ + +#include + +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_ */ diff --git a/src/DeviceTypes.hh b/src/DeviceTypes.hh new file mode 100644 index 0000000..e37a68b --- /dev/null +++ b/src/DeviceTypes.hh @@ -0,0 +1,15 @@ +/* + * 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_ */ diff --git a/src/FileUtil.cc b/src/FileUtil.cc new file mode 100644 index 0000000..7d95bef --- /dev/null +++ b/src/FileUtil.cc @@ -0,0 +1,288 @@ +/* + * FileUtil.cc + * + * Created on: Mar 5, 2011 + * Author: lamikr + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "log.h" +#include "FileUtil.hh" +#include "DeviceConfig.hh" + +using namespace std; +using namespace plp; + +template +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 FileUtil::get_subdirectories(const string& path) { + dirent *direntry; + DIR *dir; + bool bool_flg; + vector 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 FileUtil::get_data_files(const string& path) { + dirent *direntry; + DIR *dir; + vector 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; +} diff --git a/src/FileUtil.hh b/src/FileUtil.hh new file mode 100644 index 0000000..e69ada8 --- /dev/null +++ b/src/FileUtil.hh @@ -0,0 +1,33 @@ +/* + * FileUtil.hh + * + * Created on: Mar 5, 2011 + * Author: lamikr + */ + +#ifndef FILEUTIL_HH_ +#define FILEUTIL_HH_ + +#include +#include + +#include + +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 get_subdirectories(const std::string& path); + static std::vector 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_ */ diff --git a/src/Makefile.am b/src/Makefile.am index 7ad0d5a..183b03b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,18 @@ 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 \ @@ -13,4 +25,17 @@ libplpinclude_HEADERS = \ 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 + diff --git a/src/SensorDevice.hh b/src/SensorDevice.hh new file mode 100644 index 0000000..80c02df --- /dev/null +++ b/src/SensorDevice.hh @@ -0,0 +1,24 @@ +/* + * DeviceTypeSensor.hh + * + * Created on: Feb 28, 2011 + * Author: lamikr + */ + +#ifndef DEVICETYPESENSOR_HH_ +#define DEVICETYPESENSOR_HH_ + +#include + +#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_ */ diff --git a/src/Store.cc b/src/Store.cc new file mode 100644 index 0000000..ba29ed1 --- /dev/null +++ b/src/Store.cc @@ -0,0 +1,78 @@ +/* + * Store.cc + * + * Created on: Jan 20, 2011 + * Author: lamikr + */ +#include + +#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; +} diff --git a/src/Store.hh b/src/Store.hh new file mode 100644 index 0000000..cb0b6c2 --- /dev/null +++ b/src/Store.hh @@ -0,0 +1,36 @@ +/* + * Store.hh + * + * Created on: Jan 20, 2011 + * Author: lamikr + */ + +#ifndef STORE_HH_ +#define STORE_HH_ + +#include + +#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_ */ diff --git a/src/StoreCache.cc b/src/StoreCache.cc new file mode 100644 index 0000000..6e19690 --- /dev/null +++ b/src/StoreCache.cc @@ -0,0 +1,852 @@ +/* + * StoreCache.cc + * + * Created on: Jan 6, 2011 + * Author: lamikr + */ +#include +#include + +#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 mon_vcr; + vector 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 mon_vcr; + vector 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; +} diff --git a/src/StoreCache.hh b/src/StoreCache.hh new file mode 100644 index 0000000..4be7b1f --- /dev/null +++ b/src/StoreCache.hh @@ -0,0 +1,46 @@ +/* + * StoreCache.hh + * + * Created on: Jan 6, 2011 + * Author: lamikr + */ + +#ifndef STORECACHE_HH_ +#define STORECACHE_HH_ + +#include +#include + +#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_ */ diff --git a/src/StoreDay.cc b/src/StoreDay.cc new file mode 100644 index 0000000..08e56c9 --- /dev/null +++ b/src/StoreDay.cc @@ -0,0 +1,604 @@ +/* + * Store.cc + * + * Created on: Oct 31, 2010 + * Author: lamikr + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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_list, + int dec_precision) { + string n_path; + string f_path; + string line; + Data *data; + ofstream *ostream; + Date date; + list::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; +} diff --git a/src/StoreDay.hh b/src/StoreDay.hh new file mode 100644 index 0000000..1b416e5 --- /dev/null +++ b/src/StoreDay.hh @@ -0,0 +1,54 @@ +/* + * Store.hh + * + * Created on: Oct 31, 2010 + * Author: lamikr + */ + +#ifndef W1STORE_HH_ +#define W1STORE_HH_ + +#include +#include +#include + +#include + +#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 *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_ */ diff --git a/src/retval.h b/src/retval.h index 1baf3c5..bee4062 100644 --- a/src/retval.h +++ b/src/retval.h @@ -11,7 +11,8 @@ enum { PLP_OK = 0, - PLP_ERR_UNKNOWN, + PLP_ERR, + PLP_ERR_DATA_NOT_FOUND, C_ERR_MEMORY, PLP_ERR_IO }; -- 2.41.0