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