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

Eric Duminil's avatar
Eric Duminil committed
3
#include "web_config.h"
Eric Duminil's avatar
Eric Duminil committed
4
#include "ntp.h"
5
6
7
#include "led_effects.h"
#include "sensor_console.h"

8
9
namespace csv_writer {
  unsigned long last_written_at = 0;
10
  char last_successful_write[23];
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

#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
49
#elif defined(ESP32)
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
  /**
   * 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

Eric Duminil's avatar
Rename    
Eric Duminil committed
82
  char filename[20]; // e.g. "/ESPxxxxxx.csv\0"
83
84
85
86
87

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

Eric Duminil's avatar
Rename    
Eric Duminil committed
88
89
  void initialize(const char *basename) {
    snprintf(filename, sizeof(filename), "/%.14s.csv", basename);
Eric Duminil's avatar
Eric Duminil committed
90

91
    Serial.println();
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
    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
118
    Serial.println(F("Filesystem content:"));
119
    showFilesystemContent();
Eric Duminil's avatar
Eric Duminil committed
120
    Serial.println();
Eric Duminil's avatar
Eric Duminil committed
121

122
123
124
    sensor_console::defineIntCommand("csv", setCSVinterval, F("60 (Sets CSV writing interval, in s)"));
    sensor_console::defineCommand("format_filesystem", formatFilesystem, F("(Deletes the whole filesystem)"));
    sensor_console::defineCommand("show_csv", showCSVContent, F("(Displays the complete CSV file on Serial)"));
125
126
127
128
129
130
131
132
  }

  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");
133
134
      csv_file.print(F("Sensor time;CO2 concentration\r\n"));
      csv_file.print(F("YYYY-MM-DD HH:MM:SS+ZZ;ppm\r\n"));
135
136
137
138
    }
    return csv_file;
  }

139
  void log(const char *timestamp, const int16_t &co2, const float &temperature, const float &humidity) {
140
    led_effects::onBoardLEDOn();
Eric Duminil's avatar
Eric Duminil committed
141
142
    File csv_file = openOrCreate();
    char csv_line[42];
143
    snprintf(csv_line, sizeof(csv_line), "%s;%d\r\n", timestamp, co2);
Eric Duminil's avatar
Eric Duminil committed
144
145
146
147
148
149
    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
150
        Serial.print(F("CSV - Wrote : "));
Eric Duminil's avatar
Eric Duminil committed
151
        Serial.print(csv_line);
152
        ntp::getLocalTime(last_successful_write);
Eric Duminil's avatar
Eric Duminil committed
153
154
155
156
157
158
159
      }
      updateFsInfo();
      delay(50);
    } else {
      //NOTE: Can it ever happen that outfile is false?
      Serial.println(F("Problem on create file!"));
    }
160
    led_effects::onBoardLEDOff();
Eric Duminil's avatar
Eric Duminil committed
161
162
  }

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

  /*****************************************************************
   * Callbacks for sensor commands                                 *
   *****************************************************************/
  void setCSVinterval(int32_t csv_interval) {
Eric Duminil's avatar
Eric Duminil committed
175
    config::csv_interval = csv_interval;
176
    Serial.print(F("Setting CSV Interval to : "));
Eric Duminil's avatar
Eric Duminil committed
177
    Serial.print(config::csv_interval);
178
179
180
    Serial.println("s.");
    led_effects::showKITTWheel(color::green, 1);
  }
181

Eric Duminil's avatar
Eric Duminil committed
182
  void showCSVContent() {
Eric Duminil's avatar
TODO    
Eric Duminil committed
183
    //TODO: Now that ampel_name can be set, should show the content of every csv
Eric Duminil's avatar
Eric Duminil committed
184
185
186
187
188
189
190
191
192
193
194
    Serial.print(F("### "));
    Serial.print(filename);
    Serial.println(F(" ###"));
    File csv_file;
    if (FS_LIB.exists(filename)) {
      csv_file = FS_LIB.open(filename, "r");
      while (csv_file.available()) {
        Serial.write(csv_file.read());
      }
      csv_file.close();
    }
Eric Duminil's avatar
Eric Duminil committed
195
    Serial.println(F("######################"));
Eric Duminil's avatar
Eric Duminil committed
196
197
  }

198
199
200
201
  void formatFilesystem() {
    FS_LIB.format();
    led_effects::showKITTWheel(color::blue, 2);
  }
202
}