csv_writer.cpp 4.31 KB
Newer Older
1
2
#include "csv_writer.h"

Eric Duminil's avatar
TODO    
Eric Duminil committed
3
4
//TODO: Allow CSV download via USB Serial, when requested (e.g. via a Python script)

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
namespace config {
  // Values should be defined in config.h
  uint16_t csv_interval = CSV_INTERVAL; // [s]
}
namespace csv_writer {
  unsigned long last_written_at = 0;
  String last_successful_write = "";

#if defined(ESP8266)
  /**
   * SPECIFIC FUNCTIONS FOR LITTLEFS
   */
  FSInfo fs_info;

  bool mountFS() {
    return LittleFS.begin(); // format if needed.
  }

  void updateFsInfo() {
    FS_LIB.info(fs_info);
  }

  int getTotalSpace() {
    return fs_info.totalBytes;
  }

  int getUsedSpace() {
    return fs_info.usedBytes;
  }

  void showFilesystemContent() {
    Dir dir = FS_LIB.openDir("/");
    while (dir.next()) {
      Serial.print("  ");
      Serial.print(dir.fileName());
      Serial.print(" - ");
      if (dir.fileSize()) {
        File f = dir.openFile("r");
        Serial.println(f.size());
        f.close();
      } else {
        Serial.println("0");
      }
    }
  }
Eric Duminil's avatar
Eric Duminil committed
50
#elif defined(ESP32)
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
  /**
   * SPECIFIC FUNCTIONS FOR SPIFFS
   */
  bool mountFS() {
    return SPIFFS.begin(true); // format if needed.
  }

  void updateFsInfo() {
    // Nothing to do.
  }

  int getTotalSpace() {
    return SPIFFS.totalBytes();
  }

  int getUsedSpace() {
    return SPIFFS.usedBytes();
  }

  void showFilesystemContent() {
    File root = SPIFFS.open("/");
    File file = root.openNextFile();
    while (file) {
      Serial.print("  ");
      Serial.print(file.name());
      Serial.print(" - ");
      Serial.println(file.size());
      file = root.openNextFile();
    }
  }
#endif

  const String filename = "/" + SENSOR_ID + ".csv";

  int getAvailableSpace() {
    return getTotalSpace() - getUsedSpace();
  }

Eric Duminil's avatar
Eric Duminil committed
89
90
91
92
93
94
95
96
  void setCSVinterval(int32_t csv_interval) {
    config::csv_interval = csv_interval;
    Serial.print(F("Setting CSV Interval to : "));
    Serial.print(config::csv_interval);
    Serial.println("s.");
    led_effects::showKITTWheel(color::green, 1);
  }

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  void initialize() {
    Serial.print(F("Initializing FS..."));
    if (mountFS()) {
      Serial.println(F("done."));
    } else {
      Serial.println(F("fail."));
      return;
    }

    updateFsInfo();

    Serial.println(F("File system info:"));

    Serial.print(F("  Total space    : "));
    Serial.print(getTotalSpace() / 1024);
    Serial.println("kB");

    Serial.print(F("  Used space     : "));
    Serial.print(getUsedSpace() / 1024);
    Serial.println("kB");

    Serial.print(F("  Available space: "));
    Serial.print(getAvailableSpace() / 1024);
    Serial.println("kB");
    Serial.println();

    // Open dir folder
Eric Duminil's avatar
Eric Duminil committed
124
    Serial.println(F("Filesystem content:"));
125
    showFilesystemContent();
Eric Duminil's avatar
Eric Duminil committed
126
    Serial.println();
Eric Duminil's avatar
Eric Duminil committed
127
128

    sensor_commands::defineCallback("csv", setCSVinterval);
Eric Duminil's avatar
Eric Duminil committed
129
    // sensor_commands::defineCallback("format_filesystem", FS_LIB.format);
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  }

  File openOrCreate() {
    File csv_file;
    if (FS_LIB.exists(filename)) {
      csv_file = FS_LIB.open(filename, "a+");
    } else {
      csv_file = FS_LIB.open(filename, "w");
      csv_file.print(F("Sensor time;CO2 concentration;Temperature;Humidity\r\n"));
      csv_file.print(F("YYYY-MM-DD HH:MM:SS+ZZ;ppm;degC;%\r\n"));
    }
    return csv_file;
  }

Eric Duminil's avatar
Eric Duminil committed
144
  void log(const String &timeStamp, const int16_t &co2, const float &temperature, const float &humidity) {
145
    led_effects::onBoardLEDOn();
Eric Duminil's avatar
Eric Duminil committed
146
147
148
149
150
151
152
153
154
    File csv_file = openOrCreate();
    char csv_line[42];
    snprintf(csv_line, sizeof(csv_line), "%s;%d;%.1f;%.1f\r\n", timeStamp.c_str(), co2, temperature, humidity);
    if (csv_file) {
      size_t written_bytes = csv_file.print(csv_line);
      csv_file.close();
      if (written_bytes == 0) {
        Serial.println(F("Nothing written. Disk full?"));
      } else {
Eric Duminil's avatar
Eric Duminil committed
155
        Serial.print(F("CSV - Wrote : "));
Eric Duminil's avatar
Eric Duminil committed
156
157
158
159
160
161
162
163
164
        Serial.print(csv_line);
        last_successful_write = ntp::getLocalTime();
      }
      updateFsInfo();
      delay(50);
    } else {
      //NOTE: Can it ever happen that outfile is false?
      Serial.println(F("Problem on create file!"));
    }
165
    led_effects::onBoardLEDOff();
Eric Duminil's avatar
Eric Duminil committed
166
167
168
  }

  void logIfTimeHasCome(const String &timeStamp, const int16_t &co2, const float &temperature, const float &humidity) {
169
170
171
    unsigned long now = seconds();
    if (now - last_written_at > config::csv_interval) {
      last_written_at = now;
Eric Duminil's avatar
Eric Duminil committed
172
      log(timeStamp, co2, temperature, humidity);
173
174
175
    }
  }
}