]> pilppa.org Git - lib1wire.git/blob - src/W1Store.cc
fddf015ea2795dee3c5399b866bc5dcd27b11a3e
[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 <limits>
12
13 #include <time.h>
14 #include <dirent.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18
19 #include <plp/log.h>
20
21 #include "DeviceConfig.hh"
22 #include "W1Configure.hh"
23 #include "W1Store.hh"
24 #include "W1Util.hh"
25
26 using namespace std;
27 using namespace w1;
28 using namespace plp;
29
30 W1Store::W1Store(string device_id,
31                 Date *date_time) {
32         store_data      = NULL;
33         range_data      = NULL;
34         store_file_name = get_file_name(device_id, date_time);
35         log_debug("data file name: %s\n", store_file_name.c_str());
36 }
37
38 W1Store::W1Store(string file_name_param) {
39         store_data      = NULL;
40         range_data      = NULL;
41         store_file_name = file_name_param;
42 }
43
44 W1Store::~W1Store() {
45         if (store_data != NULL) {
46                 delete(store_data);
47                 store_data      = NULL;
48         }
49 }
50
51 string W1Store::get_dir_name(string device_id, Date *date_time) {
52         string  ret_val;
53         char    buffer[30];
54         string  d_name;
55
56         d_name  = DeviceConfig::get_base_dir_name();
57         snprintf(buffer, 30, "%d/%02d", date_time->year, date_time->month);
58         ret_val = W1Util::concat_paths(d_name, device_id);
59         ret_val = ret_val + "/" + buffer;
60         return ret_val;
61 }
62
63 string W1Store::get_file_name(string device_id, Date *date_time) {
64         string  ret_val;
65         string  fname;
66         char    buffer[30];
67
68         snprintf(buffer, 30, "%d-%02d-%02d", date_time->year, date_time->month, date_time->day);
69         fname   = buffer;
70         fname   = fname + DATAFILE_SUFFIX;
71         ret_val = get_dir_name(device_id, date_time);
72         ret_val = W1Util::concat_paths(ret_val, fname);
73         return ret_val;
74 }
75
76 void W1Store::save(string device_id,
77                 std::list<Data *> *data_list,
78                 int dec_precision) {
79         string                  n_path;
80         string                  f_path;
81         string                  line;
82         Data                    *data;
83         ofstream                *ostream;
84         Date                    date;
85         list<Data *>::iterator  iter;
86
87         ostream =  NULL;
88         f_path  = "";
89         log_info("[%s] writing %d data values to save.\n", device_id.c_str(), data_list->size());
90         // TODO: add mutex to protect string_list while it's read and emptied
91         for(iter = data_list->begin(); iter != data_list->end(); iter++) {
92                 data    = (Data *)*iter;
93                 date    = data->get_date();
94                 n_path  = get_file_name(device_id, &date);
95                 if (n_path.compare(f_path) != 0) {
96                         if (ostream != NULL) {
97                                 ostream->close();
98                                 delete(ostream);
99                         }
100                         f_path  = n_path;
101                         log_info("[%s] Opening file for save: %s\n", device_id.c_str(), f_path.c_str());
102                         ostream = W1Util::open_for_writing(f_path.c_str());
103                 }
104                 if ((ostream != NULL) &&
105                     (ostream->is_open() == true)) {
106                         line    = data->to_string(dec_precision);
107                         if (line.length() > 0) {
108                                 log_debug("storing line: %s\n", line.c_str());
109                                 *ostream << line << endl;
110                         }
111                 }
112                 else {
113                         log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), f_path.c_str());
114                 }
115         }
116         if (ostream != NULL) {
117                 ostream->close();
118                 delete(ostream);
119         }
120 }
121
122 bool W1Store::load() {
123         Data            *data;
124         ifstream        in;
125         string          data_str;
126         bool            ret_val;
127
128         ret_val = false;
129         if (store_data != NULL) {
130                 delete(store_data);
131                 store_data      = NULL;
132         }
133         log_debug("opening file: %s\n", store_file_name.c_str());
134         in.open(store_file_name.c_str());
135         if (in.is_open() == true) {
136                 while (in.eof() == false) {
137                         getline(in, data_str);
138                         if (data_str.empty() == false) {
139                                 data    = Data::parse_string(data_str);
140                                 if (data != NULL) {
141                                         if (store_data == NULL) {
142                                                 store_data      = new DataRange(data);
143                                         }
144                                         else {
145                                                 store_data->add_data(data);
146                                         }
147                                         delete(data);
148                                 }
149                         }
150                 }
151                 ret_val = true;
152         }
153         else {
154                 log_error("Could not load data from file: %s\n", store_file_name.c_str());
155         }
156         return ret_val;
157 }
158
159 Data *W1Store::get_sum() {
160         int     row_count;
161         int     col_count;
162         double  new_val;
163         int     ii;
164         int     jj;
165         Data    *data;
166         Data    *ret_val;
167         Date    date;
168
169         ret_val = NULL;
170         data    = NULL;
171         if (store_data == NULL) {
172                 load();
173         }
174         if (store_data != NULL) {
175                 row_count       = store_data->get_data_row_count();
176                 log_debug("data row count: %d\n", row_count);
177                 if (row_count > 0) {
178                         col_count       = store_data->get_data_column_count();
179                         log_debug("data item count per row: %d\n", col_count);
180                         ret_val         = new Data(col_count);
181                         if (col_count > 0) {
182                                 for (ii = 0; ii < row_count - 1; ii++) {
183                                         data    = store_data->get_data(ii);
184                                         for (jj = 0; jj < col_count; jj++) {
185                                                 new_val                 = data->value_arr[jj];
186                                                 ret_val->value_arr[jj]  = ret_val->value_arr[jj] + new_val;
187                                         }
188                                         if (ii < (row_count - 2)) {
189                                                 delete(data);
190                                                 data    = NULL;
191                                         }
192                                         //log_debug("new val: %f, sum: %f\n", new_val, sum);
193                                 }
194                         }
195                         date    = data->get_date();
196                         ret_val->set_date(&date);
197                         if (data != NULL) {
198                                 delete(data);
199                         }
200                 }
201         }
202         return ret_val;
203 }
204
205 Data *W1Store::get_delta() {
206         int             row_count;
207         int             col_count;
208         Data            *o_data;
209         Data            *n_data;
210         Data            *ret_val;
211         int             ii;
212         DataRange       *dr;
213         Date            date;
214
215         ret_val = NULL;
216         dr      = get_oldest_and_newest_data();
217         if (dr != NULL) {
218                 row_count       = dr->get_data_row_count();
219                 if (row_count == 2) {
220                         o_data          = dr->get_data(0);
221                         n_data          = dr->get_data(1);
222                         col_count       = dr->get_data_column_count();
223                         ret_val         = new Data(col_count);
224                         if (col_count > 0) {
225                                 for (ii = 0; ii < col_count; ii++) {
226                                         log_debug("old_data[%d]: %f new data: %f\n", ii, o_data->value_arr[ii], n_data->value_arr[ii]);
227                                         ret_val->value_arr[ii]  = n_data->value_arr[ii] - o_data->value_arr[ii];
228                                 }
229                         }
230                         date    = n_data->get_date();
231                         ret_val->set_date(&date);
232                         delete(o_data);
233                         delete(n_data);
234                 }
235                 delete(dr);
236         }
237         return ret_val;
238 }
239
240 Data *W1Store::get_mean() {
241         int     row_count;
242         int     col_count;
243         int     ii;
244         Data    *ret_val;
245
246         ret_val = NULL;
247         if (store_data == NULL) {
248                 load();
249         }
250         if (store_data != NULL) {
251                 row_count       = store_data->get_data_row_count();
252                 if (row_count > 0) {
253                         col_count       = store_data->get_data_column_count();
254                         ret_val         = get_sum();
255                         if (col_count > 0) {
256                                 for (ii = 0; ii < col_count; ii++) {
257                                         ret_val->value_arr[ii]  = ret_val->value_arr[ii] / row_count;
258                                         log_debug("avg: %f\n", ret_val->value_arr[ii]);
259                                 }
260                         }
261                 }
262         }
263         return ret_val;
264 }
265
266 Data *W1Store::get_max() {
267         int     row_count;
268         int     col_count;
269         double  new_val;
270         int     ii;
271         int     jj;
272         Data    *data;
273         Data    *ret_val;
274         double  min_val;
275         Date    date;
276
277         ret_val = NULL;
278         data    = NULL;
279         if (store_data == NULL) {
280                 load();
281         }
282         if (store_data != NULL) {
283                 row_count       = store_data->get_data_row_count();
284                 log_debug("data row count: %d\n", row_count);
285                 if (row_count > 0) {
286                         col_count       = store_data->get_data_column_count();
287                         log_debug("data item count per row: %d\n", col_count);
288                         min_val         = numeric_limits<double>::min();
289                         data    = store_data->get_data(0);
290                         ret_val         = new Data(col_count,
291                                                 min_val,
292                                                 data->get_unit());
293                         if (col_count > 0) {
294                                 for (ii = 0; ii < row_count - 1; ii++) {
295                                         data    = store_data->get_data(ii);
296                                         for (jj = 0; jj < col_count; jj++) {
297                                                 new_val = data->value_arr[jj];
298                                                 if (new_val > ret_val->value_arr[jj]) {
299                                                         ret_val->value_arr[jj]  = new_val;
300                                                 }
301                                         }
302                                         if (ii < (row_count - 2)) {
303                                                 delete(data);
304                                                 data    = NULL;
305                                         }
306                                 }
307                         }
308                         date    = data->get_date();
309                         ret_val->set_date(&date);
310                         if (data != NULL) {
311                                 delete(data);
312                         }
313                 }
314         }
315         return ret_val;
316 }
317
318 Data *W1Store::get_min() {
319         int     row_count;
320         int     col_count;
321         double  new_val;
322         int     ii;
323         int     jj;
324         Data    *data;
325         Data    *ret_val;
326         double  max_val;
327         Date    date;
328
329         ret_val = NULL;
330         data    = NULL;
331         if (store_data == NULL) {
332                 load();
333         }
334         if (store_data != NULL) {
335                 row_count       = store_data->get_data_row_count();
336                 log_debug("data row count: %d\n", row_count);
337                 if (row_count > 0) {
338                         col_count       = store_data->get_data_column_count();
339                         log_debug("data item count per row: %d\n", col_count);
340                         max_val         = numeric_limits<double>::max();
341                         data            = store_data->get_data(0);
342                         ret_val         = new Data(col_count,
343                                                 max_val,
344                                                 data->get_unit());
345                         if (col_count > 0) {
346                                 for (ii = 0; ii < row_count - 1; ii++) {
347                                         data    = store_data->get_data(ii);
348                                         for (jj = 0; jj < col_count; jj++) {
349                                                 new_val = data->value_arr[jj];
350                                                 if (new_val < ret_val->value_arr[jj]) {
351                                                         ret_val->value_arr[jj]  = new_val;
352                                                 }
353                                         }
354                                         if (ii < (row_count - 2)) {
355                                                 delete(data);
356                                                 data    = NULL;
357                                         }
358                                 }
359                         }
360                         date    = data->get_date();
361                         ret_val->set_date(&date);
362                         if (data != NULL) {
363                                 delete(data);
364                         }
365                 }
366         }
367         return ret_val;
368 }
369
370 vector<Data *> *W1Store::get_sum(int freq_sec) {
371         int             row_count;
372         int             col_count;
373         int             jj;
374         int             ii;
375         Data            *data;
376         Data            *calc;
377         Date            *limit_d;
378         Date            date;
379         vector<Data *>  *ret_val;
380
381         ret_val = new vector<Data *>();
382         calc    = NULL;
383         limit_d = NULL;
384         if (store_data == NULL) {
385                 load();
386         }
387         if (store_data != NULL) {
388                 row_count       = store_data->get_data_row_count();
389                 if (row_count > 0) {
390                         col_count       = store_data->get_data_column_count();
391                         if (col_count > 0) {
392                                 for (ii = 0; ii < row_count; ii++) {
393                                         data    = store_data->get_data(ii);
394                                         if (data != NULL) {
395                                                 if (calc == NULL) {
396                                                         calc            = data->clone();
397                                                         limit_d         = data->get_date().clone();
398                                                         limit_d->min    = 0;
399                                                         limit_d->sec    = 0;
400                                                         limit_d->inc_seconds(freq_sec);
401                                                 }
402                                                 else {
403                                                         date    = data->get_date();
404                                                         if (date.before(limit_d)) {
405                                                                 for (jj = 0; jj < col_count; jj++) {
406                                                                         calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
407                                                                 }
408                                                         }
409                                                         else {
410                                                                 ret_val->push_back(calc);
411                                                                 calc            = data->clone();
412                                                                 if (limit_d != NULL) {
413                                                                         delete(limit_d);
414                                                                 }
415                                                                 limit_d         = data->get_date().clone();
416                                                                 limit_d->min    = 0;
417                                                                 limit_d->sec    = 0;
418                                                                 limit_d->inc_seconds(freq_sec);
419                                                         }
420                                                 }
421                                                 delete(data);
422                                         }
423                                 }
424                                 if (calc != NULL) {
425                                         delete(calc);
426                                         calc    = NULL;
427                                 }
428                                 if (limit_d != NULL) {
429                                         delete(limit_d);
430                                 }
431                         }
432                 }
433         }
434         return ret_val;
435 }
436
437 vector<Data *> *W1Store::get_mean(int freq_sec) {
438         int             row_count;
439         int             col_count;
440         int             d_count;
441         int             jj;
442         int             ii;
443         Data            *data;
444         Data            *calc;
445         Date            *limit_d;
446         Date            date;
447         vector<Data *>  *ret_val;
448
449         ret_val = new vector<Data *>();
450         calc    = NULL;
451         limit_d = NULL;
452         d_count = 1;
453         if (store_data == NULL) {
454                 load();
455         }
456         if (store_data != NULL) {
457                 row_count       = store_data->get_data_row_count();
458                 if (row_count > 0) {
459                         col_count       = store_data->get_data_column_count();
460                         if (col_count > 0) {
461                                 for (ii = 0; ii < row_count; ii++) {
462                                         data    = store_data->get_data(ii);
463                                         if (data != NULL) {
464                                                 if (calc == NULL) {
465                                                         d_count         = 1;
466                                                         calc            = data->clone();
467                                                         limit_d         = data->get_date().clone();
468                                                         limit_d->min    = 0;
469                                                         limit_d->sec    = 0;
470                                                         limit_d->inc_seconds(freq_sec);
471                                                 }
472                                                 else {
473                                                         date    = data->get_date();
474                                                         if (date.before(limit_d)) {
475                                                                 for (jj = 0; jj < col_count; jj++) {
476                                                                         calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
477                                                                 }
478                                                                 d_count++;
479                                                         }
480                                                         else {
481                                                                 for (jj = 0; jj < col_count; jj++) {
482                                                                         calc->value_arr[jj]     = calc->value_arr[jj] / d_count;
483                                                                 }
484                                                                 ret_val->push_back(calc);
485                                                                 d_count         = 1;
486                                                                 calc            = data->clone();
487                                                                 if (limit_d != NULL) {
488                                                                         delete(limit_d);
489                                                                 }
490                                                                 limit_d         = data->get_date().clone();
491                                                                 limit_d->min    = 0;
492                                                                 limit_d->sec    = 0;
493                                                                 limit_d->inc_seconds(freq_sec);
494                                                         }
495                                                 }
496                                                 delete(data);
497                                         }
498                                 }
499                                 if (calc != NULL) {
500                                         delete(calc);
501                                         calc    = NULL;
502                                 }
503                                 if (limit_d != NULL) {
504                                         delete(limit_d);
505                                 }
506                         }
507                 }
508         }
509         return ret_val;
510 }
511
512 vector<Data *> *W1Store::get_delta(int freq_sec) {
513         int             row_count;
514         int             col_count;
515         int             jj;
516         int             ii;
517         Data            *data;
518         Data            *calc1;
519         Data            *calc2;
520         Date            *limit_d;
521         Date            date;
522         vector<Data *>  *ret_val;
523
524         ret_val = new vector<Data *>();
525         calc1   = NULL;
526         calc2   = NULL;
527         limit_d = NULL;
528         if (store_data == NULL) {
529                 load();
530         }
531         if (store_data != NULL) {
532                 row_count       = store_data->get_data_row_count();
533                 if (row_count > 0) {
534                         col_count       = store_data->get_data_column_count();
535                         if (col_count > 0) {
536                                 for (ii = 0; ii < row_count; ii++) {
537                                         data    = store_data->get_data(ii);
538                                         if (data != NULL) {
539                                                 if (calc1 == NULL) {
540                                                         calc1           = data->clone();
541                                                         limit_d         = data->get_date().clone();
542                                                         limit_d->min    = 0;
543                                                         limit_d->sec    = 0;
544                                                         limit_d->inc_seconds(freq_sec);
545                                                         if (calc2 != NULL) {
546                                                                 delete(calc2);
547                                                         }
548                                                         calc2           = NULL;
549                                                 }
550                                                 else {
551                                                         date    = data->get_date();
552                                                         if (date.before(limit_d)) {
553                                                                 if (calc2 != NULL) {
554                                                                         delete(calc2);
555                                                                 }
556                                                                 calc2   = data->clone();
557                                                         }
558                                                         else {
559                                                                 if (calc2 == NULL) {
560                                                                         calc2   = calc1->clone();
561                                                                 }
562                                                                 for (jj = 0; jj < col_count; jj++) {
563                                                                         calc2->value_arr[jj]    = calc2->value_arr[jj] - calc1->value_arr[jj];
564                                                                 }
565                                                                 ret_val->push_back(calc2);
566                                                                 delete(calc1);
567                                                                 calc1   = data->clone();
568                                                                 calc2   = NULL; // do not delete calc2 as it's stored to array
569                                                                 if (limit_d != NULL) {
570                                                                         delete(limit_d);
571                                                                 }
572                                                                 limit_d         = data->get_date().clone();
573                                                                 limit_d->min    = 0;
574                                                                 limit_d->sec    = 0;
575                                                                 limit_d->inc_seconds(freq_sec);
576                                                         }
577                                                 }
578                                                 delete(data);
579                                         }
580                                 }
581                                 if (calc1 != NULL) {
582                                         delete(calc1);
583                                         calc1   = NULL;
584                                 }
585                                 if (calc2 != NULL) {
586                                         delete(calc2);
587                                         calc2   = NULL;
588                                 }
589                                 if (limit_d != NULL) {
590                                         delete(limit_d);
591                                 }
592                         }
593                 }
594         }
595         return ret_val;
596 }
597
598 vector<Data *> *W1Store::get_max_or_min(int freq_sec, bool max) {
599         int             row_count;
600         int             col_count;
601         int             jj;
602         int             ii;
603         Data            *data;
604         Data            *calc;
605         Date            *limit_d;
606         Date            date;
607         vector<Data *>  *ret_val;
608
609         ret_val = new vector<Data *>();
610         calc    = NULL;
611         limit_d = NULL;
612         if (store_data == NULL) {
613                 load();
614         }
615         if (store_data != NULL) {
616                 row_count       = store_data->get_data_row_count();
617                 if (row_count > 0) {
618                         col_count       = store_data->get_data_column_count();
619                         if (col_count > 0) {
620                                 for (ii = 0; ii < row_count; ii++) {
621                                         data    = store_data->get_data(ii);
622                                         if (data != NULL) {
623                                                 if (calc == NULL) {
624                                                         calc            = data->clone();
625                                                         limit_d         = data->get_date().clone();
626                                                         limit_d->min    = 0;
627                                                         limit_d->sec    = 0;
628                                                         limit_d->inc_seconds(freq_sec);
629                                                 }
630                                                 else {
631                                                         date    = data->get_date();
632                                                         if (date.before(limit_d)) {
633                                                                 if (max == true) {
634                                                                         for (jj = 0; jj < col_count; jj++) {
635                                                                                 if (calc->value_arr[jj] < data->value_arr[jj]) {
636                                                                                         calc->value_arr[jj]     = data->value_arr[jj];
637                                                                                 }
638                                                                         }
639                                                                 }
640                                                                 else {
641                                                                         for (jj = 0; jj < col_count; jj++) {
642                                                                                 if (data->value_arr[jj] < calc->value_arr[jj]) {
643                                                                                         calc->value_arr[jj]     = data->value_arr[jj];
644                                                                                 }
645                                                                         }
646                                                                 }
647                                                         }
648                                                         else {
649                                                                 ret_val->push_back(calc);
650                                                                 calc            = data->clone();
651                                                                 if (limit_d != NULL) {
652                                                                         delete(limit_d);
653                                                                 }
654                                                                 limit_d         = data->get_date().clone();
655                                                                 limit_d->min    = 0;
656                                                                 limit_d->sec    = 0;
657                                                                 limit_d->inc_seconds(freq_sec);
658                                                         }
659                                                 }
660                                                 delete(data);
661                                         }
662                                 }
663                                 if (calc != NULL) {
664                                         delete(calc);
665                                         calc    = NULL;
666                                 }
667                                 if (limit_d != NULL) {
668                                         delete(limit_d);
669                                 }
670                         }
671                 }
672         }
673         return ret_val;
674 }
675
676 vector<Data *> *W1Store::get_max(int freq_sec) {
677         vector<Data *>  *ret_val;
678
679         ret_val = get_max_or_min(freq_sec, true);
680         return ret_val;
681 }
682
683 vector<Data *> *W1Store::get_min(int freq_sec) {
684         vector<Data *>  *ret_val;
685
686         ret_val = get_max_or_min(freq_sec, false);
687         return ret_val;
688 }
689
690 DataRange *W1Store::get_oldest_and_newest_data() {
691         DataRange       *ret_val;
692         ifstream        in;
693         Data            *o_data;
694         Data            *n_data;
695         string          latest;
696         int             row_count;
697         string          line;
698         string          prev_line;
699
700         ret_val = NULL;
701         o_data  = NULL;
702         n_data  = NULL;
703         if (store_data != NULL) {
704                 row_count       = store_data->get_data_row_count();
705                 if (row_count > 0) {
706                         o_data          = store_data->get_data(0);
707                         n_data          = store_data->get_data(row_count - 1);
708                 }
709         }
710         else {
711                 if (range_data != NULL) {
712                         row_count       = range_data->get_data_row_count();
713                         if (row_count > 0) {
714                                 o_data          = range_data->get_data(0);
715                                 n_data          = range_data->get_data(row_count - 1);
716                         }
717                 }
718                 else {
719                         in.open(store_file_name.c_str());
720                         while (in.eof() == false) {
721                                 getline(in, line);
722                                 if (line.empty() == false) {
723                                         if (o_data == NULL) {
724                                                 o_data  = Data::parse_string(line);
725                                         }
726                                         prev_line       = line;
727                                 }
728                         }
729                         if (prev_line.empty() == false) {
730                                 n_data  = Data::parse_string(prev_line);
731                         }
732                 }
733         }
734         if ((o_data != NULL) &&
735             (n_data != NULL)) {
736                 ret_val = new DataRange(o_data);
737                 ret_val->add_data(n_data);
738                 if (range_data != NULL) {
739                         range_data      = new DataRange(o_data);
740                         range_data->add_data(n_data);
741                 }
742         }
743         if (o_data != NULL) {
744                 delete(o_data);
745         }
746         if (n_data != NULL) {
747                 delete(n_data);
748         }
749         return ret_val;
750 }
751
752 Data *W1Store::get_oldest_data() {
753         int             row_count;
754         Data            *ret_val;
755         DataRange       *dr;
756
757         ret_val = NULL;
758         dr      = get_oldest_and_newest_data();
759         if (dr != NULL) {
760                 row_count       = dr->get_data_row_count();
761                 if (row_count >= 1) {
762                         ret_val = dr->get_data(0);
763                 }
764                 delete(dr);
765         }
766         return ret_val;
767 }
768
769 Data *W1Store::get_newest_data() {
770         int             row_count;
771         Data            *ret_val;
772         DataRange       *dr;
773
774         ret_val = NULL;
775         dr      = get_oldest_and_newest_data();
776         if (dr != NULL) {
777                 row_count       = dr->get_data_row_count();
778                 if (row_count == 2) {
779                         ret_val = dr->get_data(1);
780                 }
781                 delete(dr);
782         }
783         return ret_val;
784 }