]> pilppa.org Git - lib1wire.git/blob - src/W1Store.cc
9913d0dcd8cefad6787cdcf299accf15fd56b210
[lib1wire.git] / src / W1Store.cc
1 /*
2  * W1Store.cc
3  *
4  *  Created on: Oct 31, 2010
5  *      Author: lamikr
6  */
7
8 #include <list>
9 #include <string>
10 #include <fstream>
11 #include <valarray>
12 #include <limits>
13
14 #include <time.h>
15 #include <dirent.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <unistd.h>
19
20 #include <plp/log.h>
21
22 #include "DeviceConfig.hh"
23 #include "W1Configure.hh"
24 #include "W1Store.hh"
25 #include "W1Util.hh"
26
27 using namespace std;
28 using namespace w1;
29 using namespace plp;
30
31 W1Store::W1Store(string device_id,
32                 Date *date_time) {
33         store_data      = NULL;
34         range_data      = NULL;
35         store_file_name = get_file_name(device_id, date_time);
36         log_debug("data file name: %s\n", store_file_name.c_str());
37 }
38
39 W1Store::W1Store(string file_name_param) {
40         store_data      = NULL;
41         range_data      = NULL;
42         store_file_name = file_name_param;
43 }
44
45 W1Store::~W1Store() {
46         if (store_data != NULL) {
47                 delete(store_data);
48                 store_data      = NULL;
49         }
50 }
51
52 string W1Store::get_dir_name(string device_id, Date *date_time) {
53         string  ret_val;
54         char    buffer[30];
55         string  d_name;
56
57         d_name  = DeviceConfig::get_base_dir_name();
58         snprintf(buffer, 30, "%d/%02d", date_time->year, date_time->month);
59         ret_val = W1Util::concat_paths(d_name, device_id);
60         ret_val = ret_val + "/" + buffer;
61         return ret_val;
62 }
63
64 string W1Store::get_file_name(string device_id, Date *date_time) {
65         string  ret_val;
66         string  fname;
67         char    buffer[30];
68
69         snprintf(buffer, 30, "%d-%02d-%02d", date_time->year, date_time->month, date_time->day);
70         fname   = buffer;
71         fname   = fname + DATAFILE_SUFFIX;
72         ret_val = get_dir_name(device_id, date_time);
73         ret_val = W1Util::concat_paths(ret_val, fname);
74         return ret_val;
75 }
76
77 void W1Store::store(std::string device_id,
78                 std::list<std::string> *string_list) {
79         string          f_path;
80         string          line;
81         ofstream        *ostream;
82         Date            *date;
83
84         date    = new Date();
85         f_path  = get_file_name(device_id, date);
86         ostream = W1Util::open_for_writing(f_path.c_str());
87         // TODO: add mutex to protect string_list while it's read and emptied
88         if (ostream != NULL) {
89                 if (ostream->is_open()) {
90                         log_info("[%s] writing %d data values to file: %s\n", device_id.c_str(), string_list->size(), f_path.c_str());
91                         while(string_list->size() > 0) {
92                                 line    = string_list->front();
93                                 string_list->pop_front();
94                                 if (line.length() > 0) {
95                                         log_debug("storing line: %s\n", line.c_str());
96                                         *ostream << line << endl;
97                                 }
98                         }
99                         ostream->close();
100                 }
101                 else {
102                         log_error("[%s] Could not store data to file: %s\n", device_id.c_str(), f_path.c_str());
103                 }
104                 delete(ostream);
105         }
106         else {
107                 log_error("[%s] Could not store data to file: %s\n", device_id.c_str(), f_path.c_str());
108         }
109         delete(date);
110 }
111
112 bool W1Store::load() {
113         Data            *data;
114         ifstream        in;
115         string          line;
116         bool            ret_val;
117
118         ret_val = false;
119         if (store_data != NULL) {
120                 delete(store_data);
121                 store_data      = NULL;
122         }
123         in.open(store_file_name.c_str());
124         if (in.is_open() == true) {
125                 while (in.eof() == false) {
126                         getline(in, line);
127                         data    = Data::parse_data_string(line);
128                         if (store_data == NULL) {
129                                 store_data      = new DataRange(*data);
130                         }
131                         else {
132                                 store_data->add_data(*data);
133                         }
134                         delete(data);
135                 }
136                 ret_val = true;
137         }
138         else {
139                 log_error("Could not load data from file: %s\n", store_file_name.c_str());
140         }
141         return ret_val;
142 }
143
144 Data *W1Store::get_sum() {
145         int     row_count;
146         int     col_count;
147         double  new_val;
148         int     ii;
149         int     jj;
150         Data    *data;
151         Data    *ret_val;
152
153         ret_val = NULL;
154         data    = NULL;
155         if (store_data == NULL) {
156                 load();
157         }
158         if (store_data != NULL) {
159                 row_count       = store_data->get_data_row_count();
160                 log_debug("data row count: %d\n", row_count);
161                 if (row_count > 0) {
162                         col_count       = store_data->get_data_column_count();
163                         log_debug("data item count per row: %d\n", col_count);
164                         ret_val         = new Data(col_count);
165                         if (col_count > 0) {
166                                 for (ii = 0; ii < row_count - 1; ii++) {
167                                         data    = store_data->get_data(ii);
168                                         for (jj = 0; jj < col_count; jj++) {
169                                                 new_val                 = data->value_arr[jj];
170                                                 ret_val->value_arr[jj]  = ret_val->value_arr[jj] + new_val;
171                                         }
172                                         if (ii < (row_count - 2)) {
173                                                 delete(data);
174                                                 data    = NULL;
175                                         }
176                                         //log_debug("new val: %f, sum: %f\n", new_val, sum);
177                                 }
178                         }
179                         ret_val->set_date(data->get_date());
180                         if (data != NULL) {
181                                 delete(data);
182                         }
183                 }
184         }
185         return ret_val;
186 }
187
188 Data *W1Store::get_delta() {
189         int             row_count;
190         int             col_count;
191         Data            *o_data;
192         Data            *n_data;
193         Data            *ret_val;
194         int             ii;
195         DataRange       *dr;
196
197         ret_val = NULL;
198         dr      = get_oldest_and_newest_data();
199         if (dr != NULL) {
200                 row_count       = dr->get_data_row_count();
201                 if (row_count == 2) {
202                         o_data          = dr->get_data(0);
203                         n_data          = dr->get_data(1);
204                         col_count       = dr->get_data_column_count();
205                         ret_val         = new Data(col_count);
206                         if (col_count > 0) {
207                                 for (ii = 0; ii < col_count; ii++) {
208                                         ret_val->value_arr[ii]  = n_data->value_arr[ii] - o_data->value_arr[ii];
209                                 }
210                         }
211                         ret_val->set_date(n_data->get_date());
212                         delete(o_data);
213                         delete(n_data);
214                 }
215                 delete(dr);
216         }
217         return ret_val;
218 }
219
220 Data *W1Store::get_mean() {
221         int     row_count;
222         int     col_count;
223         int     ii;
224         Data    *ret_val;
225
226         ret_val = NULL;
227         if (store_data == NULL) {
228                 load();
229         }
230         if (store_data != NULL) {
231                 row_count       = store_data->get_data_row_count();
232                 if (row_count > 0) {
233                         col_count       = store_data->get_data_column_count();
234                         ret_val         = get_sum();
235                         if (col_count > 0) {
236                                 for (ii = 0; ii < col_count; ii++) {
237                                         ret_val->value_arr[ii]  = ret_val->value_arr[ii] / row_count;
238                                         log_debug("avg: %f\n", ret_val->value_arr[ii]);
239                                 }
240                         }
241                 }
242         }
243         return ret_val;
244 }
245
246 Data *W1Store::get_max() {
247         int     row_count;
248         int     col_count;
249         double  new_val;
250         int     ii;
251         int     jj;
252         Data    *data;
253         Data    *ret_val;
254         double  min_val;
255
256         ret_val = NULL;
257         data    = NULL;
258         if (store_data == NULL) {
259                 load();
260         }
261         if (store_data != NULL) {
262                 row_count       = store_data->get_data_row_count();
263                 log_debug("data row count: %d\n", row_count);
264                 if (row_count > 0) {
265                         col_count       = store_data->get_data_column_count();
266                         log_debug("data item count per row: %d\n", col_count);
267                         min_val         = numeric_limits<double>::min();
268                         ret_val         = new Data(col_count, min_val);
269                         if (col_count > 0) {
270                                 for (ii = 0; ii < row_count - 1; ii++) {
271                                         data    = store_data->get_data(ii);
272                                         for (jj = 0; jj < col_count; jj++) {
273                                                 new_val = data->value_arr[jj];
274                                                 if (new_val > ret_val->value_arr[jj]) {
275                                                         ret_val->value_arr[jj]  = new_val;
276                                                 }
277                                         }
278                                         if (ii < (row_count - 2)) {
279                                                 delete(data);
280                                                 data    = NULL;
281                                         }
282                                 }
283                         }
284                         ret_val->set_date(data->get_date());
285                         if (data != NULL) {
286                                 delete(data);
287                         }
288                 }
289         }
290         return ret_val;
291 }
292
293 Data *W1Store::get_min() {
294         int     row_count;
295         int     col_count;
296         double  new_val;
297         int     ii;
298         int     jj;
299         Data    *data;
300         Data    *ret_val;
301         double  max_val;
302
303         ret_val = NULL;
304         data    = NULL;
305         if (store_data == NULL) {
306                 load();
307         }
308         if (store_data != NULL) {
309                 row_count       = store_data->get_data_row_count();
310                 log_debug("data row count: %d\n", row_count);
311                 if (row_count > 0) {
312                         col_count       = store_data->get_data_column_count();
313                         log_debug("data item count per row: %d\n", col_count);
314                         max_val         = numeric_limits<double>::max();
315                         ret_val         = new Data(col_count, max_val);
316                         if (col_count > 0) {
317                                 for (ii = 0; ii < row_count - 1; ii++) {
318                                         data    = store_data->get_data(ii);
319                                         for (jj = 0; jj < col_count; jj++) {
320                                                 new_val = data->value_arr[jj];
321                                                 if (new_val < ret_val->value_arr[jj]) {
322                                                         ret_val->value_arr[jj]  = new_val;
323                                                 }
324                                         }
325                                         if (ii < (row_count - 2)) {
326                                                 delete(data);
327                                                 data    = NULL;
328                                         }
329                                 }
330                         }
331                         ret_val->set_date(data->get_date());
332                         if (data != NULL) {
333                                 delete(data);
334                         }
335                 }
336         }
337         return ret_val;
338 }
339
340 vector<Data *> W1Store::get_mean(int freq_sec) {
341         int             row_count;
342         int             col_count;
343         int             d_count;
344         int             jj;
345         int             ii;
346         Data            *data;
347         Data            *calc;
348         Date            *limit_d;
349         Date            date;
350         vector<Data *>  ret_val;
351
352         calc    = NULL;
353         limit_d = NULL;
354         d_count = 1;
355         if (store_data == NULL) {
356                 load();
357         }
358         if (store_data != NULL) {
359                 row_count       = store_data->get_data_row_count();
360                 if (row_count > 0) {
361                         col_count       = store_data->get_data_column_count();
362                         if (col_count > 0) {
363                                 for (ii = 0; ii < row_count; ii++) {
364                                         data    = store_data->get_data(ii);
365                                         if (data != NULL) {
366                                                 if (calc == NULL) {
367                                                         d_count         = 1;
368                                                         calc            = data->clone();
369                                                         limit_d         = data->get_date().clone();
370                                                         limit_d->min    = 0;
371                                                         limit_d->sec    = 0;
372                                                         limit_d->inc_seconds(freq_sec);
373                                                 }
374                                                 else {
375                                                         date    = data->get_date();
376                                                         if (date.before(*limit_d)) {
377                                                                 for (jj = 0; jj < col_count; jj++) {
378                                                                         calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
379                                                                 }
380                                                                 d_count++;
381                                                         }
382                                                         else {
383                                                                 for (jj = 0; jj < col_count; jj++) {
384                                                                         calc->value_arr[jj]     = calc->value_arr[jj] / d_count;
385                                                                 }
386                                                                 ret_val.push_back(calc);
387                                                                 d_count         = 1;
388                                                                 calc            = data->clone();
389                                                                 if (limit_d != NULL) {
390                                                                         delete(limit_d);
391                                                                 }
392                                                                 limit_d         = data->get_date().clone();
393                                                                 limit_d->min    = 0;
394                                                                 limit_d->sec    = 0;
395                                                                 limit_d->inc_seconds(freq_sec);
396                                                         }
397                                                 }
398                                                 delete(data);
399                                         }
400                                 }
401                                 if (calc != NULL) {
402                                         delete(calc);
403                                         calc    = NULL;
404                                 }
405                                 if (limit_d != NULL) {
406                                         delete(limit_d);
407                                 }
408                         }
409                 }
410         }
411         return ret_val;
412 }
413
414 vector<Data *> W1Store::get_delta(int freq_sec) {
415         int             row_count;
416         int             col_count;
417         int             jj;
418         int             ii;
419         Data            *data;
420         Data            *calc1;
421         Data            *calc2;
422         Date            *limit_d;
423         Date            date;
424         vector<Data *>  ret_val;
425
426         calc1   = NULL;
427         calc2   = NULL;
428         limit_d = NULL;
429         if (store_data == NULL) {
430                 load();
431         }
432         if (store_data != NULL) {
433                 row_count       = store_data->get_data_row_count();
434                 if (row_count > 0) {
435                         col_count       = store_data->get_data_column_count();
436                         if (col_count > 0) {
437                                 for (ii = 0; ii < row_count; ii++) {
438                                         data    = store_data->get_data(ii);
439                                         if (data != NULL) {
440                                                 if (calc1 == NULL) {
441                                                         calc1           = data->clone();
442                                                         limit_d         = data->get_date().clone();
443                                                         limit_d->min    = 0;
444                                                         limit_d->sec    = 0;
445                                                         limit_d->inc_seconds(freq_sec);
446                                                         if (calc2 != NULL) {
447                                                                 delete(calc2);
448                                                         }
449                                                         calc2           = NULL;
450                                                 }
451                                                 else {
452                                                         date    = data->get_date();
453                                                         if (date.before(*limit_d)) {
454                                                                 if (calc2 != NULL) {
455                                                                         delete(calc2);
456                                                                 }
457                                                                 calc2   = data->clone();
458                                                         }
459                                                         else {
460                                                                 if (calc2 == NULL) {
461                                                                         calc2   = calc1->clone();
462                                                                 }
463                                                                 for (jj = 0; jj < col_count; jj++) {
464                                                                         calc2->value_arr[jj]    = calc2->value_arr[jj] - calc1->value_arr[jj];
465                                                                 }
466                                                                 ret_val.push_back(calc2);
467                                                                 delete(calc1);
468                                                                 calc1   = data->clone();
469                                                                 calc2   = NULL; // do not delete calc2 as it's stored to array
470                                                                 if (limit_d != NULL) {
471                                                                         delete(limit_d);
472                                                                 }
473                                                                 limit_d         = data->get_date().clone();
474                                                                 limit_d->min    = 0;
475                                                                 limit_d->sec    = 0;
476                                                                 limit_d->inc_seconds(freq_sec);
477                                                         }
478                                                 }
479                                                 delete(data);
480                                         }
481                                 }
482                                 if (calc1 != NULL) {
483                                         delete(calc1);
484                                         calc1   = NULL;
485                                 }
486                                 if (calc2 != NULL) {
487                                         delete(calc2);
488                                         calc2   = NULL;
489                                 }
490                                 if (limit_d != NULL) {
491                                         delete(limit_d);
492                                 }
493                         }
494                 }
495         }
496         return ret_val;
497 }
498
499 DataRange *W1Store::get_oldest_and_newest_data() {
500         DataRange       *ret_val;
501         ifstream        in;
502         Data            *o_data;
503         Data            *n_data;
504         string          latest;
505         int             row_count;
506         string          line;
507         string          prev_line;
508
509         ret_val = NULL;
510         o_data  = NULL;
511         n_data  = NULL;
512         if (store_data != NULL) {
513                 row_count       = store_data->get_data_row_count();
514                 if (row_count > 0) {
515                         o_data          = store_data->get_data(0);
516                         n_data          = store_data->get_data(row_count - 1);
517                 }
518         }
519         else {
520                 if (range_data != NULL) {
521                         row_count       = range_data->get_data_row_count();
522                         if (row_count > 0) {
523                                 o_data          = range_data->get_data(0);
524                                 n_data          = range_data->get_data(row_count - 1);
525                         }
526                 }
527                 else {
528                         in.open(store_file_name.c_str());
529                         while (in.eof() == false) {
530                                 getline(in, line);
531                                 if (line.empty() == false) {
532                                         if (o_data == NULL) {
533                                                 o_data  = Data::parse_data_string(line);
534                                         }
535                                         prev_line       = line;
536                                 }
537                         }
538                         if (prev_line.empty() == false) {
539                                 n_data  = Data::parse_data_string(prev_line);
540                         }
541                 }
542         }
543         if ((o_data != NULL) &&
544             (n_data != NULL)) {
545                 ret_val = new DataRange(*o_data);
546                 ret_val->add_data(*n_data);
547                 if (range_data != NULL) {
548                         range_data      = new DataRange(*o_data);
549                         range_data->add_data(*n_data);
550                 }
551         }
552         if (o_data != NULL) {
553                 delete(o_data);
554         }
555         if (n_data != NULL) {
556                 delete(n_data);
557         }
558         return ret_val;
559 }
560
561 Data *W1Store::get_oldest_data() {
562         int             row_count;
563         Data            *ret_val;
564         DataRange       *dr;
565
566         ret_val = NULL;
567         dr      = get_oldest_and_newest_data();
568         if (dr != NULL) {
569                 row_count       = dr->get_data_row_count();
570                 if (row_count >= 1) {
571                         ret_val = dr->get_data(0);
572                 }
573                 delete(dr);
574         }
575         return ret_val;
576 }
577
578 Data *W1Store::get_newest_data() {
579         int             row_count;
580         Data            *ret_val;
581         DataRange       *dr;
582
583         ret_val = NULL;
584         dr      = get_oldest_and_newest_data();
585         if (dr != NULL) {
586                 row_count       = dr->get_data_row_count();
587                 if (row_count == 2) {
588                         ret_val = dr->get_data(1);
589                 }
590                 delete(dr);
591         }
592         return ret_val;
593 }