]> pilppa.org Git - lib1wire.git/blob - src/W1Store.cc
4f35376762bd72758a4f2a3d285b6d28ae859a16
[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         string                  n_path;
79         string                  f_path;
80         string                  line;
81         Data                    *data;
82         ofstream                *ostream;
83         Date                    date;
84         list<Data *>::iterator  iter;
85
86         ostream =  NULL;
87         f_path  = "";
88         log_info("[%s] writing %d data values to save.\n", device_id.c_str(), data_list->size());
89         // TODO: add mutex to protect string_list while it's read and emptied
90         for(iter = data_list->begin(); iter != data_list->end(); iter++) {
91                 data    = (Data *)*iter;
92                 date    = data->get_date();
93                 n_path  = get_file_name(device_id, &date);
94                 if (n_path.compare(f_path) != 0) {
95                         if (ostream != NULL) {
96                                 ostream->close();
97                                 delete(ostream);
98                         }
99                         f_path  = n_path;
100                         log_info("[%s] Opening file for save: %s\n", device_id.c_str(), f_path.c_str());
101                         ostream = W1Util::open_for_writing(f_path.c_str());
102                 }
103                 if ((ostream != NULL) &&
104                     (ostream->is_open() == true)) {
105                         line    = data->to_string();
106                         if (line.length() > 0) {
107                                 log_debug("storing line: %s\n", line.c_str());
108                                 *ostream << line << endl;
109                         }
110                 }
111                 else {
112                         log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), f_path.c_str());
113                 }
114         }
115         if (ostream != NULL) {
116                 ostream->close();
117                 delete(ostream);
118         }
119 }
120
121 bool W1Store::load() {
122         Data            *data;
123         ifstream        in;
124         string          data_str;
125         bool            ret_val;
126
127         ret_val = false;
128         if (store_data != NULL) {
129                 delete(store_data);
130                 store_data      = NULL;
131         }
132         log_debug("opening file: %s\n", store_file_name.c_str());
133         in.open(store_file_name.c_str());
134         if (in.is_open() == true) {
135                 while (in.eof() == false) {
136                         getline(in, data_str);
137                         if (data_str.empty() == false) {
138                                 data    = Data::parse_string(data_str);
139                                 if (data != NULL) {
140                                         if (store_data == NULL) {
141                                                 store_data      = new DataRange(data);
142                                         }
143                                         else {
144                                                 store_data->add_data(data);
145                                         }
146                                         delete(data);
147                                 }
148                         }
149                 }
150                 ret_val = true;
151         }
152         else {
153                 log_error("Could not load data from file: %s\n", store_file_name.c_str());
154         }
155         return ret_val;
156 }
157
158 Data *W1Store::get_sum() {
159         int     row_count;
160         int     col_count;
161         double  new_val;
162         int     ii;
163         int     jj;
164         Data    *data;
165         Data    *ret_val;
166         Date    date;
167
168         ret_val = NULL;
169         data    = NULL;
170         if (store_data == NULL) {
171                 load();
172         }
173         if (store_data != NULL) {
174                 row_count       = store_data->get_data_row_count();
175                 log_debug("data row count: %d\n", row_count);
176                 if (row_count > 0) {
177                         col_count       = store_data->get_data_column_count();
178                         log_debug("data item count per row: %d\n", col_count);
179                         ret_val         = new Data(col_count);
180                         if (col_count > 0) {
181                                 for (ii = 0; ii < row_count - 1; ii++) {
182                                         data    = store_data->get_data(ii);
183                                         for (jj = 0; jj < col_count; jj++) {
184                                                 new_val                 = data->value_arr[jj];
185                                                 ret_val->value_arr[jj]  = ret_val->value_arr[jj] + new_val;
186                                         }
187                                         if (ii < (row_count - 2)) {
188                                                 delete(data);
189                                                 data    = NULL;
190                                         }
191                                         //log_debug("new val: %f, sum: %f\n", new_val, sum);
192                                 }
193                         }
194                         date    = data->get_date();
195                         ret_val->set_date(&date);
196                         if (data != NULL) {
197                                 delete(data);
198                         }
199                 }
200         }
201         return ret_val;
202 }
203
204 Data *W1Store::get_delta() {
205         int             row_count;
206         int             col_count;
207         Data            *o_data;
208         Data            *n_data;
209         Data            *ret_val;
210         int             ii;
211         DataRange       *dr;
212         Date            date;
213
214         ret_val = NULL;
215         dr      = get_oldest_and_newest_data();
216         if (dr != NULL) {
217                 row_count       = dr->get_data_row_count();
218                 if (row_count == 2) {
219                         o_data          = dr->get_data(0);
220                         n_data          = dr->get_data(1);
221                         col_count       = dr->get_data_column_count();
222                         ret_val         = new Data(col_count);
223                         if (col_count > 0) {
224                                 for (ii = 0; ii < col_count; ii++) {
225                                         log_debug("old_data[%d]: %f new data: %f\n", ii, o_data->value_arr[ii], n_data->value_arr[ii]);
226                                         ret_val->value_arr[ii]  = n_data->value_arr[ii] - o_data->value_arr[ii];
227                                 }
228                         }
229                         date    = n_data->get_date();
230                         ret_val->set_date(&date);
231                         delete(o_data);
232                         delete(n_data);
233                 }
234                 delete(dr);
235         }
236         return ret_val;
237 }
238
239 Data *W1Store::get_mean() {
240         int     row_count;
241         int     col_count;
242         int     ii;
243         Data    *ret_val;
244
245         ret_val = NULL;
246         if (store_data == NULL) {
247                 load();
248         }
249         if (store_data != NULL) {
250                 row_count       = store_data->get_data_row_count();
251                 if (row_count > 0) {
252                         col_count       = store_data->get_data_column_count();
253                         ret_val         = get_sum();
254                         if (col_count > 0) {
255                                 for (ii = 0; ii < col_count; ii++) {
256                                         ret_val->value_arr[ii]  = ret_val->value_arr[ii] / row_count;
257                                         log_debug("avg: %f\n", ret_val->value_arr[ii]);
258                                 }
259                         }
260                 }
261         }
262         return ret_val;
263 }
264
265 Data *W1Store::get_max() {
266         int     row_count;
267         int     col_count;
268         double  new_val;
269         int     ii;
270         int     jj;
271         Data    *data;
272         Data    *ret_val;
273         double  min_val;
274         Date    date;
275
276         ret_val = NULL;
277         data    = NULL;
278         if (store_data == NULL) {
279                 load();
280         }
281         if (store_data != NULL) {
282                 row_count       = store_data->get_data_row_count();
283                 log_debug("data row count: %d\n", row_count);
284                 if (row_count > 0) {
285                         col_count       = store_data->get_data_column_count();
286                         log_debug("data item count per row: %d\n", col_count);
287                         min_val         = numeric_limits<double>::min();
288                         data    = store_data->get_data(0);
289                         ret_val         = new Data(col_count,
290                                                 min_val,
291                                                 data->get_unit());
292                         if (col_count > 0) {
293                                 for (ii = 0; ii < row_count - 1; ii++) {
294                                         data    = store_data->get_data(ii);
295                                         for (jj = 0; jj < col_count; jj++) {
296                                                 new_val = data->value_arr[jj];
297                                                 if (new_val > ret_val->value_arr[jj]) {
298                                                         ret_val->value_arr[jj]  = new_val;
299                                                 }
300                                         }
301                                         if (ii < (row_count - 2)) {
302                                                 delete(data);
303                                                 data    = NULL;
304                                         }
305                                 }
306                         }
307                         date    = data->get_date();
308                         ret_val->set_date(&date);
309                         if (data != NULL) {
310                                 delete(data);
311                         }
312                 }
313         }
314         return ret_val;
315 }
316
317 Data *W1Store::get_min() {
318         int     row_count;
319         int     col_count;
320         double  new_val;
321         int     ii;
322         int     jj;
323         Data    *data;
324         Data    *ret_val;
325         double  max_val;
326         Date    date;
327
328         ret_val = NULL;
329         data    = NULL;
330         if (store_data == NULL) {
331                 load();
332         }
333         if (store_data != NULL) {
334                 row_count       = store_data->get_data_row_count();
335                 log_debug("data row count: %d\n", row_count);
336                 if (row_count > 0) {
337                         col_count       = store_data->get_data_column_count();
338                         log_debug("data item count per row: %d\n", col_count);
339                         max_val         = numeric_limits<double>::max();
340                         data            = store_data->get_data(0);
341                         ret_val         = new Data(col_count,
342                                                 max_val,
343                                                 data->get_unit());
344                         if (col_count > 0) {
345                                 for (ii = 0; ii < row_count - 1; ii++) {
346                                         data    = store_data->get_data(ii);
347                                         for (jj = 0; jj < col_count; jj++) {
348                                                 new_val = data->value_arr[jj];
349                                                 if (new_val < ret_val->value_arr[jj]) {
350                                                         ret_val->value_arr[jj]  = new_val;
351                                                 }
352                                         }
353                                         if (ii < (row_count - 2)) {
354                                                 delete(data);
355                                                 data    = NULL;
356                                         }
357                                 }
358                         }
359                         date    = data->get_date();
360                         ret_val->set_date(&date);
361                         if (data != NULL) {
362                                 delete(data);
363                         }
364                 }
365         }
366         return ret_val;
367 }
368
369 vector<Data *> W1Store::get_mean(int freq_sec) {
370         int             row_count;
371         int             col_count;
372         int             d_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         calc    = NULL;
382         limit_d = NULL;
383         d_count = 1;
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                                                         d_count         = 1;
397                                                         calc            = data->clone();
398                                                         limit_d         = data->get_date().clone();
399                                                         limit_d->min    = 0;
400                                                         limit_d->sec    = 0;
401                                                         limit_d->inc_seconds(freq_sec);
402                                                 }
403                                                 else {
404                                                         date    = data->get_date();
405                                                         if (date.before(*limit_d)) {
406                                                                 for (jj = 0; jj < col_count; jj++) {
407                                                                         calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
408                                                                 }
409                                                                 d_count++;
410                                                         }
411                                                         else {
412                                                                 for (jj = 0; jj < col_count; jj++) {
413                                                                         calc->value_arr[jj]     = calc->value_arr[jj] / d_count;
414                                                                 }
415                                                                 ret_val.push_back(calc);
416                                                                 d_count         = 1;
417                                                                 calc            = data->clone();
418                                                                 if (limit_d != NULL) {
419                                                                         delete(limit_d);
420                                                                 }
421                                                                 limit_d         = data->get_date().clone();
422                                                                 limit_d->min    = 0;
423                                                                 limit_d->sec    = 0;
424                                                                 limit_d->inc_seconds(freq_sec);
425                                                         }
426                                                 }
427                                                 delete(data);
428                                         }
429                                 }
430                                 if (calc != NULL) {
431                                         delete(calc);
432                                         calc    = NULL;
433                                 }
434                                 if (limit_d != NULL) {
435                                         delete(limit_d);
436                                 }
437                         }
438                 }
439         }
440         return ret_val;
441 }
442
443 vector<Data *> W1Store::get_delta(int freq_sec) {
444         int             row_count;
445         int             col_count;
446         int             jj;
447         int             ii;
448         Data            *data;
449         Data            *calc1;
450         Data            *calc2;
451         Date            *limit_d;
452         Date            date;
453         vector<Data *>  ret_val;
454
455         calc1   = NULL;
456         calc2   = NULL;
457         limit_d = NULL;
458         if (store_data == NULL) {
459                 load();
460         }
461         if (store_data != NULL) {
462                 row_count       = store_data->get_data_row_count();
463                 if (row_count > 0) {
464                         col_count       = store_data->get_data_column_count();
465                         if (col_count > 0) {
466                                 for (ii = 0; ii < row_count; ii++) {
467                                         data    = store_data->get_data(ii);
468                                         if (data != NULL) {
469                                                 if (calc1 == NULL) {
470                                                         calc1           = data->clone();
471                                                         limit_d         = data->get_date().clone();
472                                                         limit_d->min    = 0;
473                                                         limit_d->sec    = 0;
474                                                         limit_d->inc_seconds(freq_sec);
475                                                         if (calc2 != NULL) {
476                                                                 delete(calc2);
477                                                         }
478                                                         calc2           = NULL;
479                                                 }
480                                                 else {
481                                                         date    = data->get_date();
482                                                         if (date.before(*limit_d)) {
483                                                                 if (calc2 != NULL) {
484                                                                         delete(calc2);
485                                                                 }
486                                                                 calc2   = data->clone();
487                                                         }
488                                                         else {
489                                                                 if (calc2 == NULL) {
490                                                                         calc2   = calc1->clone();
491                                                                 }
492                                                                 for (jj = 0; jj < col_count; jj++) {
493                                                                         calc2->value_arr[jj]    = calc2->value_arr[jj] - calc1->value_arr[jj];
494                                                                 }
495                                                                 ret_val.push_back(calc2);
496                                                                 delete(calc1);
497                                                                 calc1   = data->clone();
498                                                                 calc2   = NULL; // do not delete calc2 as it's stored to array
499                                                                 if (limit_d != NULL) {
500                                                                         delete(limit_d);
501                                                                 }
502                                                                 limit_d         = data->get_date().clone();
503                                                                 limit_d->min    = 0;
504                                                                 limit_d->sec    = 0;
505                                                                 limit_d->inc_seconds(freq_sec);
506                                                         }
507                                                 }
508                                                 delete(data);
509                                         }
510                                 }
511                                 if (calc1 != NULL) {
512                                         delete(calc1);
513                                         calc1   = NULL;
514                                 }
515                                 if (calc2 != NULL) {
516                                         delete(calc2);
517                                         calc2   = NULL;
518                                 }
519                                 if (limit_d != NULL) {
520                                         delete(limit_d);
521                                 }
522                         }
523                 }
524         }
525         return ret_val;
526 }
527
528 DataRange *W1Store::get_oldest_and_newest_data() {
529         DataRange       *ret_val;
530         ifstream        in;
531         Data            *o_data;
532         Data            *n_data;
533         string          latest;
534         int             row_count;
535         string          line;
536         string          prev_line;
537
538         ret_val = NULL;
539         o_data  = NULL;
540         n_data  = NULL;
541         if (store_data != NULL) {
542                 row_count       = store_data->get_data_row_count();
543                 if (row_count > 0) {
544                         o_data          = store_data->get_data(0);
545                         n_data          = store_data->get_data(row_count - 1);
546                 }
547         }
548         else {
549                 if (range_data != NULL) {
550                         row_count       = range_data->get_data_row_count();
551                         if (row_count > 0) {
552                                 o_data          = range_data->get_data(0);
553                                 n_data          = range_data->get_data(row_count - 1);
554                         }
555                 }
556                 else {
557                         in.open(store_file_name.c_str());
558                         while (in.eof() == false) {
559                                 getline(in, line);
560                                 if (line.empty() == false) {
561                                         if (o_data == NULL) {
562                                                 o_data  = Data::parse_string(line);
563                                         }
564                                         prev_line       = line;
565                                 }
566                         }
567                         if (prev_line.empty() == false) {
568                                 n_data  = Data::parse_string(prev_line);
569                         }
570                 }
571         }
572         if ((o_data != NULL) &&
573             (n_data != NULL)) {
574                 ret_val = new DataRange(o_data);
575                 ret_val->add_data(n_data);
576                 if (range_data != NULL) {
577                         range_data      = new DataRange(o_data);
578                         range_data->add_data(n_data);
579                 }
580         }
581         if (o_data != NULL) {
582                 delete(o_data);
583         }
584         if (n_data != NULL) {
585                 delete(n_data);
586         }
587         return ret_val;
588 }
589
590 Data *W1Store::get_oldest_data() {
591         int             row_count;
592         Data            *ret_val;
593         DataRange       *dr;
594
595         ret_val = NULL;
596         dr      = get_oldest_and_newest_data();
597         if (dr != NULL) {
598                 row_count       = dr->get_data_row_count();
599                 if (row_count >= 1) {
600                         ret_val = dr->get_data(0);
601                 }
602                 delete(dr);
603         }
604         return ret_val;
605 }
606
607 Data *W1Store::get_newest_data() {
608         int             row_count;
609         Data            *ret_val;
610         DataRange       *dr;
611
612         ret_val = NULL;
613         dr      = get_oldest_and_newest_data();
614         if (dr != NULL) {
615                 row_count       = dr->get_data_row_count();
616                 if (row_count == 2) {
617                         ret_val = dr->get_data(1);
618                 }
619                 delete(dr);
620         }
621         return ret_val;
622 }