Skip to content

Commit a833e95

Browse files
committed
Encapsulate parsing into class
1 parent e084641 commit a833e95

File tree

3 files changed

+447
-124
lines changed

3 files changed

+447
-124
lines changed

examples/UARTRead/UARTRead.ino

Lines changed: 83 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -26,153 +26,112 @@
2626
*
2727
*/
2828

29-
#include <map>
30-
#include <vector>
31-
#include <tuple>
32-
33-
constexpr char DEFAULT_DELIMITER = ',';
34-
35-
std::map<u_int8_t, std::tuple<String, String>> csvFieldMapping = {
36-
{0, {"HS4001 sample counter", "uint32"}},
37-
{1, {"HS4001 temperature (degC)", "float"}},
38-
{2, {"HS4001 humidity (%RH)", "float"}},
39-
{3, {"ZMOD4510 status", "uint8"}},
40-
{4, {"ZMOD4510 sample counter", "uint32"}},
41-
{5, {"ZMOD4510 EPA AQI", "uint16"}},
42-
{6, {"ZMOD4510 Fast AQI", "uint16"}},
43-
{7, {"ZMOD4510 O3 (ppb)", "float"}},
44-
{8, {"ZMOD4510 NO2 (ppb)", "float"}},
45-
{9, {"ZMOD4510 Rmox[0]", "float"}},
46-
{10, {"ZMOD4510 Rmox[1]", "float"}},
47-
{11, {"ZMOD4510 Rmox[2]", "float"}},
48-
{12, {"ZMOD4510 Rmox[3]", "float"}},
49-
{13, {"ZMOD4510 Rmox[4]", "float"}},
50-
{14, {"ZMOD4510 Rmox[5]", "float"}},
51-
{15, {"ZMOD4510 Rmox[6]", "float"}},
52-
{16, {"ZMOD4510 Rmox[7]", "float"}},
53-
{17, {"ZMOD4510 Rmox[8]", "float"}},
54-
{18, {"ZMOD4510 Rmox[9]", "float"}},
55-
{19, {"ZMOD4510 Rmox[10]", "float"}},
56-
{20, {"ZMOD4510 Rmox[11]", "float"}},
57-
{21, {"ZMOD4510 Rmox[12]", "float"}},
58-
{22, {"ZMOD4410 status", "uint8"}},
59-
{23, {"ZMD4410 sample counter", "uint32"}},
60-
{24, {"ZMOD4410 IAQ", "float"}},
61-
{25, {"ZMOD4410 TVOC (mg/m^3)", "float"}},
62-
{26, {"ZMOD4410 eCO2 (ppm)", "float"}},
63-
{27, {"ZMOD4410 Rel IAQ", "float"}},
64-
{28, {"ZMOD4410 EtOH (ppm)", "float"}},
65-
{29, {"ZMOD4410 Rmox[0]", "float"}},
66-
{30, {"ZMOD4410 Rmox[1]", "float"}},
67-
{31, {"ZMOD4410 Rmox[2]", "float"}},
68-
{32, {"ZMOD4410 Rmox[3]", "float"}},
69-
{33, {"ZMOD4410 Rmox[4]", "float"}},
70-
{34, {"ZMOD4410 Rmox[5]", "float"}},
71-
{35, {"ZMOD4410 Rmox[6]", "float"}},
72-
{36, {"ZMOD4410 Rmox[7]", "float"}},
73-
{37, {"ZMOD4410 Rmox[8]", "float"}},
74-
{38, {"ZMOD4410 Rmox[9]", "float"}},
75-
{39, {"ZMOD4410 Rmox[10]", "float"}},
76-
{40, {"ZMOD4410 Rmox[11]", "float"}},
77-
{41, {"ZMOD4410 Rmox[12]", "float"}},
78-
{42, {"ZMOD4410 Rcda[0]", "float"}},
79-
{43, {"ZMOD4410 Rcda[1]", "float"}},
80-
{44, {"ZMOD4410 Rcda[2]", "float"}},
81-
{45, {"ZMOD4410 Rhtr", "float"}},
82-
{46, {"ZMOD4410 Temp", "float"}},
83-
{47, {"ZMOD4410 intensity", "float"}},
84-
{48, {"ZMOD4410 odor", "uint8"}}
85-
};
86-
87-
std::map<String, String> parsedValuesMap;
88-
89-
// Function to convert a string to a float, handling exponents
90-
float parseFloatWithExponent(const String &str) {
91-
// Convert the string to a double
92-
double value = str.toDouble();
93-
94-
// Convert the double to a float
95-
return static_cast<float>(value);
96-
}
29+
#include "NiclaSenseEnvSerial.h"
9730

98-
// Function to process a CSV line
99-
void processCSVLine(String data, char delimiter, std::map<String, String> &targetMap) {
100-
// Skip lines that start with INFO: or WARNING:
101-
if (data.startsWith("INFO:") || data.startsWith("WARNING:")) {
102-
return;
31+
NiclaSenseEnvSerial niclaSerial(Serial1);
32+
33+
void setup() {
34+
Serial.begin(115200);
35+
niclaSerial.begin();
36+
37+
while (!Serial) {
38+
delay(100);
10339
}
10440

105-
// Print the error message if the line starts with ERROR:
106-
if (data.startsWith("ERROR:")) {
107-
Serial.println(data);
41+
Serial.println("Serial ports initialized");
42+
}
43+
44+
void loop() {
45+
bool updated = niclaSerial.update();
46+
47+
if (!updated) {
48+
String err = niclaSerial.lastErrorMessage();
49+
if (err.length() > 0) {
50+
Serial.print("Error: ");
51+
Serial.println(err);
52+
}
53+
delay(100);
10854
return;
10955
}
11056

111-
// Split CSV line into fields
112-
std::vector<String> fields;
113-
size_t pos = 0;
114-
while ((pos = data.indexOf(delimiter)) != -1) {
115-
fields.push_back(data.substring(0, pos));
116-
data = data.substring(pos + 1);
57+
float temperature = niclaSerial.temperature();
58+
if (!isnan(temperature)) {
59+
Serial.print("🌡 HS4001 temperature (°C): ");
60+
Serial.println(temperature);
11761
}
118-
fields.push_back(data); // Last field
11962

120-
// Map fields to their corresponding names and store in parsedValuesMap
121-
for (size_t i = 0; i < fields.size(); ++i) {
122-
// Use index as key to get tuple (name, type)
123-
auto [name, type] = csvFieldMapping[i];
124-
String fieldValue = fields[i];
63+
float humidity = niclaSerial.humidity();
64+
if (!isnan(humidity)) {
65+
Serial.print("💧 HS4001 humidity (%RH): ");
66+
Serial.println(humidity);
67+
}
12568

126-
// Check if the field is empty
127-
if (fieldValue == "") {
128-
continue;
129-
}
69+
int epaAqi = niclaSerial.airQualityIndex();
70+
if (epaAqi >= 0) {
71+
Serial.print("🏭 ZMOD4510 EPA AQI: ");
72+
Serial.println(epaAqi);
73+
Serial.print("🏭 ZMOD4510 EPA AQI interpreted: ");
74+
Serial.println(niclaSerial.airQualityIndexInterpreted());
75+
}
13076

131-
// Check if the field is a float based on the "type" property
132-
if (type == "float") {
133-
float floatValue = parseFloatWithExponent(fieldValue);
134-
targetMap[name] = String(floatValue);
135-
} else {
136-
targetMap[name] = fieldValue;
137-
}
77+
int fastAqi = niclaSerial.fastAirQualityIndex();
78+
if (fastAqi >= 0) {
79+
Serial.print("🏭 ZMOD4510 Fast AQI: ");
80+
Serial.println(fastAqi);
13881
}
139-
}
14082

141-
void setup(){
142-
Serial.begin(115200);
143-
Serial1.begin(38400, SERIAL_8N1);
83+
float o3 = niclaSerial.O3();
84+
if (!isnan(o3)) {
85+
Serial.print("🌬 ZMOD4510 O3 (ppb): ");
86+
Serial.println(o3);
87+
}
14488

145-
while (!Serial || !Serial1) {
146-
delay(100);
89+
float no2 = niclaSerial.NO2();
90+
if (!isnan(no2)) {
91+
Serial.print("🌬 ZMOD4510 NO2 (ppb): ");
92+
Serial.println(no2);
14793
}
14894

149-
Serial.println("Serial ports initialized");
150-
}
95+
float iaq = niclaSerial.airQuality();
96+
if (!isnan(iaq)) {
97+
Serial.print("🏠 ZMOD4410 IAQ: ");
98+
Serial.println(iaq);
99+
Serial.print("🏠 ZMOD4410 IAQ interpreted: ");
100+
Serial.println(niclaSerial.airQualityInterpreted());
101+
}
151102

103+
float relIaq = niclaSerial.relativeAirQuality();
104+
if (!isnan(relIaq)) {
105+
Serial.print("🏠 ZMOD4410 Rel IAQ: ");
106+
Serial.println(relIaq);
107+
}
152108

153-
void loop() {
154-
if (!Serial1.available()) {
155-
delay(100);
156-
return;
109+
float co2 = niclaSerial.CO2();
110+
if (!isnan(co2)) {
111+
Serial.print("🌬 ZMOD4410 eCO2 (ppm): ");
112+
Serial.println(co2);
157113
}
158114

159-
String csvLine = Serial1.readStringUntil('\n');
160-
processCSVLine(csvLine, DEFAULT_DELIMITER, parsedValuesMap);
115+
float tvoc = niclaSerial.TVOC();
116+
if (!isnan(tvoc)) {
117+
Serial.print("🌬 ZMOD4410 TVOC (mg/m^3): ");
118+
Serial.println(tvoc);
119+
}
161120

162-
// If map is empty, there was no data to parse
163-
if (parsedValuesMap.empty()) {
164-
Serial.println("No data to parse.");
165-
return;
121+
float ethanol = niclaSerial.ethanol();
122+
if (!isnan(ethanol)) {
123+
Serial.print("🍺 ZMOD4410 EtOH (ppm): ");
124+
Serial.println(ethanol);
166125
}
167126

168-
// Print parsed values in the loop
169-
for (const auto &entry : parsedValuesMap) {
170-
Serial.print(entry.first + ": ");
171-
Serial.println(entry.second);
127+
float odorIntensity = niclaSerial.odorIntensity();
128+
if (!isnan(odorIntensity)) {
129+
Serial.print("👃 ZMOD4410 intensity: ");
130+
Serial.println(odorIntensity);
172131
}
173132

174-
Serial.println();
133+
Serial.print("👃 ZMOD4410 odor: ");
134+
Serial.println(niclaSerial.sulfurOdor() ? "detected" : "not detected");
175135

176-
// Clear the map for the next iteration
177-
parsedValuesMap.clear();
136+
Serial.println();
178137
}

0 commit comments

Comments
 (0)