aboutsummaryrefslogtreecommitdiff
path: root/datalog.h
blob: 73299b5804c668f02fdc0fc1b3ffe145fc26a297 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#pragma once
 
#include <mySD.h>
 
#include "data.h"
 
const int mySD_CS=13;
const int mySD_SCLK=14;
const int mySD_MISO=2;
const int mySD_MOSI=15;
 
/*
  we write fixed-length CSV lines because, at some point in the
  future, I may need to seek "10 measurements back" or something like
  that; also, it's easier to read
 
  column ranges and sizes:
  * secs: up to ~36 hours = 130000, unsigned: 6 characters
  * co2: up to ~4000, unsigned: 4 characters
  * temp: -20.0 … +40.0, signed: 5 characters
  * humid: 0.0 … 100.0, unsigned: 5 characters
  * pm*: 0.0 … 9999.9, unsigned: 6 characters
  * batt: 3.00 … 4.30, unsigned: 4 characters
 */
//                      123456, 1234, 12345, 12345, 123456, 123456, 123456, 123456, 1234\n 
const char csvHeader[]="  secs,  co2,  temp, humid,    pm1,  pm2.5,    pm4,   pm10, batt\n";
const char csvFormat[]="% 6lu% 4u% 5.1f%5.1f%6.1f%6.1f%6.1f%6.1f%4.2f\n";
const size_t lineLength=65;
 
class DataLog {
private:
  File logfile;
  char line[100];
  uint8_t linesSinceLastFlush;
  uint8_t flushThreshold;
public:
  DataLog(uint8_t ft=4) : flushThreshold(ft) {}
 
  void start() {
    bool sdok=SD.begin(mySD_CS, mySD_MOSI, mySD_MISO, mySD_SCLK);
    Serial.print("# sdok: ");Serial.println(sdok);
    logfile = SD.open("quality.csv",FILE_WRITE);
    Serial.print("# file: ");Serial.println(logfile.name());
    uint32_t fileSize = logfile.size();
    logfile.seek(fileSize);
    if (fileSize == 0{
      logfile.write((uint8_t*)csvHeader, lineLength);
    }                    
    linesSinceLastFlush=1;
  }
 
  void show(const SensorData *data) {
    snprintf(
             line, lineLength+1// zero terminator! 
             csvFormat,
             millis()/1000,
 
             data->co2,
             data->temperature,
             max(0.0f,data->humidity),
 
             max(0.0f,data->pm.mc_1p0),
             max(0.0f,data->pm.mc_2p5 - data->pm.mc_1p0),
             max(0.0f,data->pm.mc_4p0 - data->pm.mc_2p5),
             max(0.0f,data->pm.mc_10p0 - data->pm.mc_4p0),
 
             max(0.0f,data->batteryVoltage)
             );
    size_t written=logfile.write((uint8_t *)line,lineLength);
    Serial.print("");Serial.write(line);
    Serial.print("# written: ");Serial.println(written);
    if (++linesSinceLastFlush > flushThreshold) {
      logfile.flush();
      linesSinceLastFlush=0;
 
      Serial.println("# flushed");
    }
  }
 
  bool serialCommand(const String &tag, const String &command) {
    if (command == "log"{
      Serial.print(tag);Serial.println(" begin");
 
      uint8_t buffer[1024];
      logfile.flush();
      int remaining = logfile.position();
      logfile.seek(0);
      while (remaining > 0{
        int bytesRead = logfile.read(buffer, 1024);
        Serial.write(buffer, bytesRead);
        remaining -= bytesRead;
      }
 
      Serial.print(tag);Serial.println(" end");
 
      return true;
    }
 
    return false;
  }
};