]> pilppa.org Git - lib1wire.git/blob - src/W1Store.cc
83e16150fdb388565f8c5c77a3b53647210eeb88
[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_mean(int freq_sec) {
371         int             row_count;
372         int             col_count;
373         int             d_count;
374         int             jj;
375         int             ii;
376         Data            *data;
377         Data            *calc;
378         Date            *limit_d;
379         Date            date;
380         vector<Data *>  ret_val;
381
382         calc    = NULL;
383         limit_d = NULL;
384         d_count = 1;
385         if (store_data == NULL) {
386                 load();
387         }
388         if (store_data != NULL) {
389                 row_count       = store_data->get_data_row_count();
390                 if (row_count > 0) {
391                         col_count       = store_data->get_data_column_count();
392                         if (col_count > 0) {
393                                 for (ii = 0; ii < row_count; ii++) {
394                                         data    = store_data->get_data(ii);
395                                         if (data != NULL) {
396                                                 if (calc == NULL) {
397                                                         d_count         = 1;
398                                                         calc            = data->clone();
399                                                         limit_d         = data->get_date().clone();
400                                                         limit_d->min    = 0;
401                                                         limit_d->sec    = 0;
402                                                         limit_d->inc_seconds(freq_sec);
403                                                 }
404                                                 else {
405                                                         date    = data->get_date();
406                                                         if (date.before(*limit_d)) {
407                                                                 for (jj = 0; jj < col_count; jj++) {
408                                                                         calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
409                                                                 }
410                                                                 d_count++;
411                                                         }
412                                                         else {
413                                                                 for (jj = 0; jj < col_count; jj++) {
414                                                                         calc->value_arr[jj]     = calc->value_arr[jj] / d_count;
415                                                                 }
416                                                                 ret_val.push_back(calc);
417                                                                 d_count         = 1;
418                                                                 calc            = data->clone();
419                                                                 if (limit_d != NULL) {
420                                                                         delete(limit_d);
421                                                                 }
422                                                                 limit_d         = data->get_date().clone();
423                                                                 limit_d->min    = 0;
424                                                                 limit_d->sec    = 0;
425                                                                 limit_d->inc_seconds(freq_sec);
426                                                         }
427                                                 }
428                                                 delete(data);
429                                         }
430                                 }
431                                 if (calc != NULL) {
432                                         delete(calc);
433                                         calc    = NULL;
434                                 }
435                                 if (limit_d != NULL) {
436                                         delete(limit_d);
437                                 }
438                         }
439                 }
440         }
441         return ret_val;
442 }
443
444 vector<Data *> W1Store::get_delta(int freq_sec) {
445         int             row_count;
446         int             col_count;
447         int             jj;
448         int             ii;
449         Data            *data;
450         Data            *calc1;
451         Data            *calc2;
452         Date            *limit_d;
453         Date            date;
454         vector<Data *>  ret_val;
455
456         calc1   = NULL;
457         calc2   = NULL;
458         limit_d = NULL;
459         if (store_data == NULL) {
460                 load();
461         }
462         if (store_data != NULL) {
463                 row_count       = store_data->get_data_row_count();
464                 if (row_count > 0) {
465                         col_count       = store_data->get_data_column_count();
466                         if (col_count > 0) {
467                                 for (ii = 0; ii < row_count; ii++) {
468                                         data    = store_data->get_data(ii);
469                                         if (data != NULL) {
470                                                 if (calc1 == NULL) {
471                                                         calc1           = data->clone();
472                                                         limit_d         = data->get_date().clone();
473                                                         limit_d->min    = 0;
474                                                         limit_d->sec    = 0;
475                                                         limit_d->inc_seconds(freq_sec);
476                                                         if (calc2 != NULL) {
477                                                                 delete(calc2);
478                                                         }
479                                                         calc2           = NULL;
480                                                 }
481                                                 else {
482                                                         date    = data->get_date();
483                                                         if (date.before(*limit_d)) {
484                                                                 if (calc2 != NULL) {
485                                                                         delete(calc2);
486                                                                 }
487                                                                 calc2   = data->clone();
488                                                         }
489                                                         else {
490                                                                 if (calc2 == NULL) {
491                                                                         calc2   = calc1->clone();
492                                                                 }
493                                                                 for (jj = 0; jj < col_count; jj++) {
494                                                                         calc2->value_arr[jj]    = calc2->value_arr[jj] - calc1->value_arr[jj];
495                                                                 }
496                                                                 ret_val.push_back(calc2);
497                                                                 delete(calc1);
498                                                                 calc1   = data->clone();
499                                                                 calc2   = NULL; // do not delete calc2 as it's stored to array
500                                                                 if (limit_d != NULL) {
501                                                                         delete(limit_d);
502                                                                 }
503                                                                 limit_d         = data->get_date().clone();
504                                                                 limit_d->min    = 0;
505                                                                 limit_d->sec    = 0;
506                                                                 limit_d->inc_seconds(freq_sec);
507                                                         }
508                                                 }
509                                                 delete(data);
510                                         }
511                                 }
512                                 if (calc1 != NULL) {
513                                         delete(calc1);
514                                         calc1   = NULL;
515                                 }
516                                 if (calc2 != NULL) {
517                                         delete(calc2);
518                                         calc2   = NULL;
519                                 }
520                                 if (limit_d != NULL) {
521                                         delete(limit_d);
522                                 }
523                         }
524                 }
525         }
526         return ret_val;
527 }
528
529 DataRange *W1Store::get_oldest_and_newest_data() {
530         DataRange       *ret_val;
531         ifstream        in;
532         Data            *o_data;
533         Data            *n_data;
534         string          latest;
535         int             row_count;
536         string          line;
537         string          prev_line;
538
539         ret_val = NULL;
540         o_data  = NULL;
541         n_data  = NULL;
542         if (store_data != NULL) {
543                 row_count       = store_data->get_data_row_count();
544                 if (row_count > 0) {
545                         o_data          = store_data->get_data(0);
546                         n_data          = store_data->get_data(row_count - 1);
547                 }
548         }
549         else {
550                 if (range_data != NULL) {
551                         row_count       = range_data->get_data_row_count();
552                         if (row_count > 0) {
553                                 o_data          = range_data->get_data(0);
554                                 n_data          = range_data->get_data(row_count - 1);
555                         }
556                 }
557                 else {
558                         in.open(store_file_name.c_str());
559                         while (in.eof() == false) {
560                                 getline(in, line);
561                                 if (line.empty() == false) {
562                                         if (o_data == NULL) {
563                                                 o_data  = Data::parse_string(line);
564                                         }
565                                         prev_line       = line;
566                                 }
567                         }
568                         if (prev_line.empty() == false) {
569                                 n_data  = Data::parse_string(prev_line);
570                         }
571                 }
572         }
573         if ((o_data != NULL) &&
574             (n_data != NULL)) {
575                 ret_val = new DataRange(o_data);
576                 ret_val->add_data(n_data);
577                 if (range_data != NULL) {
578                         range_data      = new DataRange(o_data);
579                         range_data->add_data(n_data);
580                 }
581         }
582         if (o_data != NULL) {
583                 delete(o_data);
584         }
585         if (n_data != NULL) {
586                 delete(n_data);
587         }
588         return ret_val;
589 }
590
591 Data *W1Store::get_oldest_data() {
592         int             row_count;
593         Data            *ret_val;
594         DataRange       *dr;
595
596         ret_val = NULL;
597         dr      = get_oldest_and_newest_data();
598         if (dr != NULL) {
599                 row_count       = dr->get_data_row_count();
600                 if (row_count >= 1) {
601                         ret_val = dr->get_data(0);
602                 }
603                 delete(dr);
604         }
605         return ret_val;
606 }
607
608 Data *W1Store::get_newest_data() {
609         int             row_count;
610         Data            *ret_val;
611         DataRange       *dr;
612
613         ret_val = NULL;
614         dr      = get_oldest_and_newest_data();
615         if (dr != NULL) {
616                 row_count       = dr->get_data_row_count();
617                 if (row_count == 2) {
618                         ret_val = dr->get_data(1);
619                 }
620                 delete(dr);
621         }
622         return ret_val;
623 }