diff --git a/CHANGELOG.md b/CHANGELOG.md index 3936089..3032bba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # node-sketch-templater Changelog +## v1.0.3 +- Bump sketch versions +- Unify sketch headers +- Implement sprintf_P PROGMEM based building of HTTP strings and payload +- Should send less TCP packets +- Use same structure in all templates except `custom` + ## v1.0.2 Add `encoding` field to `generateSketch` which allows to specify base64 encoding @@ -7,4 +14,4 @@ Add `encoding` field to `generateSketch` which allows to specify base64 encoding Fix npm package name in README.md ## v1.0.0 -Initial release to npm after extracting from sensebox/openSenseMap-API \ No newline at end of file +Initial release to npm after extracting from sensebox/openSenseMap-API diff --git a/README.md b/README.md index ce8c149..cc2bf68 100644 --- a/README.md +++ b/README.md @@ -57,9 +57,8 @@ Additionally, the following transformers are implemented: | Transformer name | Description | |------------------|-------------| | `as-is` | Do nothing. | -| `toHex` | Transforms a single string to hex tuples. Example: `"DEADBEEF" => "0xDE, 0xAD, 0xBE, 0xEF"` | | `toDefine` | Transform an array of sensors to multiple `#define` statements. | -| `toHexArray` | Transform an array of sensors to a list of hex encoded arrays. Uses `toHex` internally. | +| `toProgmem` | Transform an array of sensors to multiple `const char xxSENSOR_ID[] PROGMEM = "";` statements. | ## Adding Transformers diff --git a/package.json b/package.json index 38ca7a2..fe1eb03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sensebox/sketch-templater", - "version": "1.0.2", + "version": "1.0.3", "description": "nodejs library to create senseBox Arduino Sketches", "main": "src/index.js", "repository": "https://github.com/sensebox/node-sketch-templater.git", @@ -28,4 +28,4 @@ "publishConfig": { "access": "public" } -} +} \ No newline at end of file diff --git a/src/transformers.js b/src/transformers.js index 64e6501..acb8912 100644 --- a/src/transformers.js +++ b/src/transformers.js @@ -2,35 +2,10 @@ const dedent = require('dedent'); -/* Used in toHexArray - * sensors should follow this order strictlyI - * when using the standard senseBox:home wifi setup - * 0 Temperature - * 1 Humidity - * 2 Pressure - * 3 Lux - * 4 UV - * 5 PM10 - * 6 PM2.5 - * the rest - */ -const homeSensorTitles = [ - 'Temperatur', - 'rel. Luftfeuchte', - 'Luftdruck', - 'Beleuchtungsstärke', - 'UV-Intensität', - 'PM10', - 'PM2.5' -]; - module.exports = { 'as-is'(str) { return str; }, - toHex(idStr) { - return idStr.toString().replace(/(..)/g, ', 0x$1').substr(2); - }, toDefine(sensors) { const output = []; for (const [i, { _id, title }] of sensors.entries()) { @@ -40,20 +15,16 @@ module.exports = { return output.join('\r\n'); }, - toHexArray(sensors) { - const homeSensors = []; - const otherSensors = []; + toProgmem(sensors) { + const output = []; for (const { _id, title } of sensors) { - const index = homeSensorTitles.findIndex(t => t === title); - if (index !== -1) { - homeSensors[index] = dedent`// ${title} - { ${this.toHex(_id)} }`; - continue; - } - otherSensors.push(dedent`// ${title} - { ${this.toHex(_id)} }`); + output.push(dedent`// ${title} + const char ${title + .toUpperCase() + .replace(/[^A-Z0-9]+/g, '') + .slice(0, 6)}SENSOR_ID[] PROGMEM = "${_id}";`); } - return homeSensors.filter(s => s).concat(otherSensors).join(',\r\n'); + return output.join('\r\n'); } }; diff --git a/templates/home_ethernet.tpl b/templates/home_ethernet.tpl index 6143c21..525c62e 100644 --- a/templates/home_ethernet.tpl +++ b/templates/home_ethernet.tpl @@ -1,40 +1,39 @@ { "model":"homeEthernet" } /* - senseBox Home - Citizen Sensingplatform - Version: 2.4 - Date: 2017-Mar-06 + senseBox:home - Citizen Sensingplatform + Version: ethernet_2.6 + Date: 2017-07-29 Homepage: https://www.sensebox.de https://www.opensensemap.org Author: Institute for Geoinformatics, University of Muenster - Note: Sketch for senseBox:home + Note: Sketch for senseBox:home Ethernet Edition + Model: homeEthernet Email: support@sensebox.de + Code is in the public domain. + https://github.com/sensebox/node-sketch-templater */ -#include -#include "HDC100X.h" -#include "BMP280.h" -#include -#include #include -typedef struct sensor { - const uint8_t ID[12]; -} sensor; +/* ------------------------------------------------------------------------- */ +/* ------------------------------Configuration------------------------------ */ +/* ------------------------------------------------------------------------- */ -uint8_t sensorsIndex = 0; +// Interval of measuring and submitting values in seconds +const unsigned int postingInterval = 60e3; -// Number of sensors -static const uint8_t NUM_SENSORS = @@NUM_SENSORS@@; +// address of the server to send to +const char server[] PROGMEM = "@@INGRESS_DOMAIN@@"; // senseBox ID -const uint8_t SENSEBOX_ID[12] = { @@SENSEBOX_ID|toHex@@ }; +const char SENSEBOX_ID[] PROGMEM = "@@SENSEBOX_ID@@"; -// sensor IDs -// Do not change order of sensor IDs -const sensor sensors[NUM_SENSORS] = { -@@SENSOR_IDS|toHexArray@@ -}; +// Number of sensors +// Change this number if you add or remove sensors +// do not forget to remove or add the sensors on opensensemap.org +static const uint8_t NUM_SENSORS = @@NUM_SENSORS@@; -float values[NUM_SENSORS]; +// sensor IDs +@@SENSOR_IDS|toProgmem@@ //Configure static IP setup (only needed if DHCP is disabled) IPAddress myIp(192, 168, 0, 42); @@ -42,210 +41,180 @@ IPAddress myDns(8, 8, 8, 8); IPAddress myGateway(192, 168, 0, 177); IPAddress mySubnet(255, 255, 255, 0); -//Ethernet configuration +// Uncomment the next line to get debugging messages printed on the Serial port +// Do not leave this enabled for long time use +// #define ENABLE_DEBUG + +/* ------------------------------------------------------------------------- */ +/* --------------------------End of Configuration--------------------------- */ +/* ------------------------------------------------------------------------- */ + +#include "BMP280.h" +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_DEBUG +#define DEBUG(str) Serial.println(str) +#else +#define DEBUG(str) +#endif + byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; -const char *server = "@@INGRESS_DOMAIN@@"; EthernetClient client; -//Load sensors +// Sensor Instances Makerblog_TSL45315 TSL = Makerblog_TSL45315(TSL45315_TIME_M4); HDC100X HDC(0x43); BMP280 BMP; +VEML6070 VEML; -//measurement variables -float temperature = 0; -double tempBaro, pressure; -int count = 1; -char result; -#define UV_ADDR 0x38 -#define IT_1 0x1 +typedef struct measurement { + char *sensorId; + float value; +} measurement; -const unsigned int postingInterval = 60000; +measurement measurements[NUM_SENSORS]; +uint8_t num_measurements = 0; + +// buffer for sprintf +char buffer[150]; + +void addMeasurement(char *sensorId, float value) { + measurements[num_measurements].sensorId = sensorId; + measurements[num_measurements].value = value; + num_measurements++; +} + +void writeMeasurementsToClient(Print &stream) { + // iterate throug the measurements array + for (uint8_t i = 0; i < num_measurements; i++) { + sprintf_P(buffer, PSTR("%S,"), measurements[i].sensorId); + // arduino sprintf just returns "?" for floats, use dtostrf + dtostrf(measurements[i].value, 9, 2, &buffer[strlen(buffer)]); + + // transmit buffer to client + stream.println(buffer); + DEBUG(buffer); + } + + // reset num_measurements + num_measurements = 0; +} + +void submitValues() { + // close any connection before send a new request. + // This will free the socket on the Ethernet shield + if (client.connected()) { + client.stop(); + delay(1000); + } + bool connected = false; + char _server[strlen_P(server)]; + strcpy_P(_server, server); + for (uint8_t timeout = 2; timeout != 0; timeout--) { + DEBUG(F("connecting...")); + connected = client.connect(_server, 80); + if (connected == true) { + DEBUG(F("Connection successful, transferring...")); + // construct the HTTP POST request: + sprintf_P(buffer, + PSTR("POST /boxes/%S/data HTTP/1.1\nHost: %S\nContent-Type: " + "csv\nConnection: close\nContent-Length: %i\n"), + SENSEBOX_ID, server, num_measurements * 36); + DEBUG(buffer); + + // send the HTTP POST request: + client.println(buffer); + + // send measurements + writeMeasurementsToClient(client); + + // send empty line to end the request + client.println(); + + delay(100); + client.flush(); + client.stop(); + + DEBUG("done!"); + + // reset number of measurements + num_measurements = 0; + break; + } + delay(1000); + } + + if (connected == false) { + // Reset durchführen + Serial.println(F("connection failed. Restarting System.")); + delay(5000); + cli(); + wdt_enable(WDTO_60MS); + while (1) + ; + } +} void setup() { - sleep(2000); + // Initialize serial and wait for port to open: Serial.begin(9600); - Serial.println("senseBox Home software version 2.4"); - Serial.println(); - sleep(1000); - Serial.print("Initializing DHCP connection..."); + + DEBUG(F("Initializing DHCP connection...")); if (Ethernet.begin(mac) == 0) { - Serial.println("failed! Trying static IP setup."); + DEBUG(F("failed! Trying static IP setup.")); Ethernet.begin(mac, myIp, myDns, myGateway, mySubnet); //@TODO: Add reference to support site for network settings + } else { + DEBUG("done!"); } - else { - Serial.println("done!"); - } - sleep(1000); - Serial.print("Initializing sensors..."); - Wire.begin(); - Wire.beginTransmission(UV_ADDR); - Wire.write((IT_1 << 2) | 0x02); - Wire.endTransmission(); - sleep(500); + + // Sensor initialization + DEBUG(F("Initializing sensors...")); + VEML.begin(); + delay(500); HDC.begin(HDC100X_TEMP_HUMI, HDC100X_14BIT, HDC100X_14BIT, DISABLE); TSL.begin(); BMP.begin(); BMP.setOversampling(4); - Serial.println("done!"); - temperature = HDC.getTemp(); - Serial.println("Starting loop.\n"); + DEBUG(F("done!")); + DEBUG(F("Starting loop in 30 seconds.")); + HDC.getTemp(); + delay(30000); } void loop() { - addValue(HDC.getTemp()); - sleep(200); - addValue(HDC.getHumi()); + // capture loop start timestamp + unsigned long start = millis(); + + // read measurements from sensors + addMeasurement(TEMPERSENSOR_ID, HDC.getTemp()); + delay(200); + addMeasurement(RELLUFSENSOR_ID, HDC.getHumi()); + + double tempBaro, pressure; + char result; result = BMP.startMeasurment(); if (result != 0) { - sleep(result); + delay(result); result = BMP.getTemperatureAndPressure(tempBaro, pressure); + addMeasurement(LUFTDRSENSOR_ID, pressure); } - addValue(pressure); - addValue(TSL.readLux()); - addValue(getUV()); - - submitValues(); - - sleep(postingInterval); -} -void addValue(const float &value) { - values[sensorsIndex] = value; - sensorsIndex = sensorsIndex + 1; -} - -uint16_t getUV() { - byte msb = 0, lsb = 0; - uint16_t uvValue; - Wire.requestFrom(UV_ADDR + 1, 1); //MSB - sleep(1); - if (Wire.available()) msb = Wire.read(); - Wire.requestFrom(UV_ADDR + 0, 1); //LSB - sleep(1); - if (Wire.available()) lsb = Wire.read(); - uvValue = (msb << 8) | lsb; - return uvValue * 5.625; -} - -int printHexToStream(const uint8_t *data, uint8_t length, Print &stream) // prints 8-bit data in hex -{ - byte first; - int j = 0; - for (uint8_t i=0; i> 4) | 48; - if (first > 57) { - stream.write(first + (byte)39); - } else { - stream.write(first); - } - j++; - - first = (data[i] & 0x0F) | 48; - if (first > 57) { - stream.write(first + (byte)39); - } else { - stream.write(first); - } - j++; - } - return j; -} - -int printCsvToStream(Print &stream) { - int len = 0; - for (uint8_t i = 0; i < sensorsIndex; i++) { - if (!isnan(values[i])) { - len = len + printHexToStream(sensors[i].ID, 12, stream); - len = len + stream.print(","); - //do not print digits for illuminance und uv-intensity - if (i < 3 || i > 4) len = len + stream.println(values[i],1); - else len = len + stream.println(values[i],0); - } - } - return len; -} + addMeasurement(BELEUCSENSOR_ID, TSL.readLux()); + addMeasurement(UVINTESENSOR_ID, VEML.getUV()); + submitValues(); -// millis() rollover fix - http://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover -void sleep(unsigned long ms) { // ms: duration - unsigned long start = millis(); // start: timestamp + // schedule next round of measurements for (;;) { - unsigned long now = millis(); // now: timestamp - unsigned long elapsed = now - start; // elapsed: duration - if (elapsed >= ms) // comparing durations: OK + unsigned long now = millis(); + unsigned long elapsed = now - start; + if (elapsed >= postingInterval) return; } } - -void waitForResponse() -{ - // if there are incoming bytes from the server, read and print them - sleep(100); - String response = ""; - char c; - boolean repeat = true; - do { - if (client.available()) c = client.read(); - else repeat = false; - response += c; - if (response == "HTTP/1.1 ") response = ""; - if (c == '\n') repeat = false; - } - while (repeat); - - Serial.print("Server Response: "); Serial.print(response); - - client.flush(); - client.stop(); -} - -void submitValues() { - // close any connection before send a new request. - // This will free the socket on the WiFi shield - Serial.println("__________________________\n"); - if (client.connected()) { - client.stop(); - sleep(1000); - } - // if there's a successful connection: - if (client.connect(server, 80)) { - - Serial.println("connecting..."); - // send the HTTP POST request: - - client.print(F("POST /boxes/")); - printHexToStream(SENSEBOX_ID, 12, client); - client.println(F("/data HTTP/1.1")); - - // !!!!! DO NOT REMOVE !!!!! - // !!!!! NICHT LÖSCHEN !!!!! - // print once to Serial to get the content-length - int contentLen = printCsvToStream(Serial); - // !!!!! DO NOT REMOVE !!!!! - // !!!!! NICHT LÖSCHEN !!!!! - - // Send the required header parameters - client.print(F("Host: ")); - client.println(server); - client.print(F("Content-Type: text/csv\nConnection: close\nContent-Length: ")); - client.println(contentLen); - client.println(); - printCsvToStream(client); - client.println(); - Serial.println("done!"); - - waitForResponse(); - - // reset index - sensorsIndex = 0; - - } - else { - // if you couldn't make a connection: - Serial.println("connection failed. Restarting System."); - sleep(5000); - asm volatile (" jmp 0"); - } -} diff --git a/templates/home_ethernet_feinstaub.tpl b/templates/home_ethernet_feinstaub.tpl index abc40ba..5112107 100644 --- a/templates/home_ethernet_feinstaub.tpl +++ b/templates/home_ethernet_feinstaub.tpl @@ -1,44 +1,39 @@ { "model":"homeEthernetFeinstaub" } /* - senseBox Home - Citizen Sensingplatform - Version: 2.5 - Date: 2017-May-24 + senseBox:home - Citizen Sensingplatform + Version: ethernet_2.6 + Date: 2017-07-29 Homepage: https://www.sensebox.de https://www.opensensemap.org Author: Institute for Geoinformatics, University of Muenster - Note: Sketch for senseBox:home with dust particle upgrade + Note: Sketch for senseBox:home Ethernet with dust particle upgrade + Model: homeEthernetFeinstaub Email: support@sensebox.de Code is in the public domain. + https://github.com/sensebox/node-sketch-templater */ -#include -#include "HDC100X.h" -#include "BMP280.h" -#include -#include #include -#include -bool debug = 0; +/* ------------------------------------------------------------------------- */ +/* ------------------------------Configuration------------------------------ */ +/* ------------------------------------------------------------------------- */ -typedef struct sensor { - const uint8_t ID[12]; -} sensor; +// Interval of measuring and submitting values in seconds +const unsigned int postingInterval = 60e3; -uint8_t sensorsIndex = 0; +// address of the server to send to +const char server[] PROGMEM = "@@INGRESS_DOMAIN@@"; + +// senseBox ID +const char SENSEBOX_ID[] PROGMEM = "@@SENSEBOX_ID@@"; // Number of sensors +// Change this number if you add or remove sensors +// do not forget to remove or add the sensors on opensensemap.org static const uint8_t NUM_SENSORS = @@NUM_SENSORS@@; -// senseBox ID -const uint8_t SENSEBOX_ID[12] = { @@SENSEBOX_ID|toHex@@ }; - // sensor IDs -// Do not change order of sensor IDs -const sensor sensors[NUM_SENSORS] = { -@@SENSOR_IDS|toHexArray@@ -}; - -float values[NUM_SENSORS]; +@@SENSOR_IDS|toProgmem@@ //Configure static IP setup (only needed if DHCP is disabled) IPAddress myIp(192, 168, 0, 42); @@ -46,218 +41,194 @@ IPAddress myDns(8, 8, 8, 8); IPAddress myGateway(192, 168, 0, 177); IPAddress mySubnet(255, 255, 255, 0); -//Ethernet configuration +// Uncomment the next line to get debugging messages printed on the Serial port +// Do not leave this enabled for long time use +// #define ENABLE_DEBUG + +/* ------------------------------------------------------------------------- */ +/* --------------------------End of Configuration--------------------------- */ +/* ------------------------------------------------------------------------- */ + +#include "BMP280.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_DEBUG +#define DEBUG(str) Serial.println(str) +#else +#define DEBUG(str) +#endif + byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; -const char *server = "@@INGRESS_DOMAIN@@"; EthernetClient client; -//Load sensors +// Sensor Instances +SDS011 my_sds(Serial); Makerblog_TSL45315 TSL = Makerblog_TSL45315(TSL45315_TIME_M4); HDC100X HDC(0x43); BMP280 BMP; -SDS011 my_sds(Serial); +VEML6070 VEML; + +typedef struct measurement { + char *sensorId; + float value; +} measurement; + +measurement measurements[NUM_SENSORS]; +uint8_t num_measurements = 0; + +// buffer for sprintf +char buffer[150]; + +void addMeasurement(char *sensorId, float value) { + measurements[num_measurements].sensorId = sensorId; + measurements[num_measurements].value = value; + num_measurements++; +} + +void writeMeasurementsToClient(Print &stream) { + // iterate throug the measurements array + for (uint8_t i = 0; i < num_measurements; i++) { + sprintf_P(buffer, PSTR("%S,"), measurements[i].sensorId); + // arduino sprintf just returns "?" for floats, use dtostrf + dtostrf(measurements[i].value, 9, 2, &buffer[strlen(buffer)]); + + // transmit buffer to client + stream.println(buffer); + DEBUG(buffer); + } + + // reset num_measurements + num_measurements = 0; +} -//measurement variables -float temperature = 0; -double tempBaro, pressure; -int count = 1; -char result; -#define UV_ADDR 0x38 -#define IT_1 0x1 -float pm10,pm25; -int error; +void submitValues() { + // close any connection before send a new request. + // This will free the socket on the Ethernet shield + if (client.connected()) { + client.stop(); + delay(1000); + } + bool connected = false; + char _server[strlen_P(server)]; + strcpy_P(_server, server); + for (uint8_t timeout = 2; timeout != 0; timeout--) { + DEBUG(F("connecting...")); + connected = client.connect(_server, 80); + if (connected == true) { + DEBUG(F("Connection successful, transferring...")); + // construct the HTTP POST request: + sprintf_P(buffer, + PSTR("POST /boxes/%S/data HTTP/1.1\nHost: %S\nContent-Type: " + "csv\nConnection: close\nContent-Length: %i\n"), + SENSEBOX_ID, server, num_measurements * 36); + DEBUG(buffer); + + // send the HTTP POST request: + client.println(buffer); + + // send measurements + writeMeasurementsToClient(client); + + // send empty line to end the request + client.println(); + + delay(100); + client.flush(); + client.stop(); + + DEBUG("done!"); + + // reset number of measurements + num_measurements = 0; + break; + } + delay(1000); + } -const unsigned int postingInterval = 60000; + if (connected == false) { + // Reset durchführen + Serial.println(F("connection failed. Restarting System.")); + delay(5000); + cli(); + wdt_enable(WDTO_60MS); + while (1) + ; + } +} void setup() { - sleep(2000); + // Initialize serial and wait for port to open: Serial.begin(9600); - sleep(1000); - if(debug) Serial.print("Initializing DHCP connection..."); + + DEBUG(F("Initializing DHCP connection...")); if (Ethernet.begin(mac) == 0) { - if(debug) Serial.println("failed! Trying static IP setup."); + DEBUG(F("failed! Trying static IP setup.")); Ethernet.begin(mac, myIp, myDns, myGateway, mySubnet); //@TODO: Add reference to support site for network settings + } else { + DEBUG("done!"); } - else { - if(debug) Serial.println("done!"); - } - sleep(1000); - if(debug) Serial.print("Initializing sensors..."); - Wire.begin(); - Wire.beginTransmission(UV_ADDR); - Wire.write((IT_1 << 2) | 0x02); - Wire.endTransmission(); - sleep(500); + + // Sensor initialization + DEBUG(F("Initializing sensors...")); + VEML.begin(); + delay(500); HDC.begin(HDC100X_TEMP_HUMI, HDC100X_14BIT, HDC100X_14BIT, DISABLE); TSL.begin(); BMP.begin(); BMP.setOversampling(4); - if(debug) Serial.println("done!"); - temperature = HDC.getTemp(); - if(debug) Serial.println("Starting loop in 30 seconds.\n"); - sleep(30000); //heat-up time for dust particle sensor + DEBUG(F("done!")); + DEBUG(F("Starting loop in 30 seconds.")); + HDC.getTemp(); + delay(30000); } void loop() { - addValue(HDC.getTemp()); - sleep(200); - addValue(HDC.getHumi()); + // capture loop start timestamp + unsigned long start = millis(); + + // read measurements from sensors + addMeasurement(TEMPERSENSOR_ID, HDC.getTemp()); + delay(200); + addMeasurement(RELLUFSENSOR_ID, HDC.getHumi()); + + double tempBaro, pressure; + char result; result = BMP.startMeasurment(); if (result != 0) { - sleep(result); + delay(result); result = BMP.getTemperatureAndPressure(tempBaro, pressure); + addMeasurement(LUFTDRSENSOR_ID, pressure); } - else pressure = 0; - addValue(pressure); - addValue(TSL.readLux()); - addValue(getUV()); - error = my_sds.read(&pm25,&pm10); - if (error) { - pm25 = 0; - pm10 = 0; - } - addValue(pm10); - addValue(pm25); - - submitValues(); - - sleep(postingInterval); -} -void addValue(const float &value) { - values[sensorsIndex] = value; - sensorsIndex = sensorsIndex + 1; -} - -uint16_t getUV() { - byte msb = 0, lsb = 0; - uint16_t uvValue; - Wire.requestFrom(UV_ADDR + 1, 1); //MSB - sleep(1); - if (Wire.available()) msb = Wire.read(); - Wire.requestFrom(UV_ADDR + 0, 1); //LSB - sleep(1); - if (Wire.available()) lsb = Wire.read(); - uvValue = (msb << 8) | lsb; - return uvValue * 5.625; -} - -int printHexToStream(const uint8_t *data, uint8_t length, Print &stream) // prints 8-bit data in hex -{ - byte first; - int j = 0; - for (uint8_t i=0; i> 4) | 48; - if (first > 57) { - stream.write(first + (byte)39); - } else { - stream.write(first); - } - j++; - - first = (data[i] & 0x0F) | 48; - if (first > 57) { - stream.write(first + (byte)39); - } else { - stream.write(first); - } - j++; - } - return j; -} - -int printCsvToStream(Print &stream) { - int len = 0; - for (uint8_t i = 0; i < sensorsIndex; i++) { - if (!isnan(values[i])) { - len = len + printHexToStream(sensors[i].ID, 12, stream); - len = len + stream.print(","); - //do not print digits for illuminance und uv-intensity - if (i < 3 || i > 4) len = len + stream.println(values[i],1); - else len = len + stream.println(values[i],0); + addMeasurement(BELEUCSENSOR_ID, TSL.readLux()); + addMeasurement(UVINTESENSOR_ID, VEML.getUV()); + + uint8_t attempt = 0; + float pm10, pm25; + while (attempt < 5) { + bool error = my_sds.read(&pm25, &pm10); + if (!error) { + addMeasurement(PM10SENSOR_ID, pm10); + addMeasurement(PM25SENSOR_ID, pm25); + break; } + attempt++; } - return len; -} + submitValues(); -// millis() rollover fix - http://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover -void sleep(unsigned long ms) { // ms: duration - unsigned long start = millis(); // start: timestamp + // schedule next round of measurements for (;;) { - unsigned long now = millis(); // now: timestamp - unsigned long elapsed = now - start; // elapsed: duration - if (elapsed >= ms) // comparing durations: OK + unsigned long now = millis(); + unsigned long elapsed = now - start; + if (elapsed >= postingInterval) return; } } - -void waitForResponse() -{ - // if there are incoming bytes from the server, read and print them - sleep(100); - String response = ""; - char c; - boolean repeat = true; - do { - if (client.available()) c = client.read(); - else repeat = false; - response += c; - if (response == "HTTP/1.1 ") response = ""; - if (c == '\n') repeat = false; - } - while (repeat); - - if(debug) {Serial.print("Server Response: "); Serial.print(response);} - - client.flush(); - client.stop(); -} - -void submitValues() { - // close any connection before send a new request. - // This will free the socket on the WiFi shield - if(debug) Serial.println("__________________________\n"); - if (client.connected()) { - client.stop(); - sleep(1000); - } - // if there's a successful connection: - if (client.connect(server, 80)) { - - if(debug) Serial.println("connecting..."); - // send the HTTP POST request: - - client.print(F("POST /boxes/")); - printHexToStream(SENSEBOX_ID, 12, client); - client.println(F("/data HTTP/1.1")); - - // !!!!! NICHT LÖSCHEN !!!!! - // print once to Serial to get the content-length - int contentLen = printCsvToStream(Serial); - // !!!!! DO NOT REMOVE !!!!! - - // Send the required header parameters - client.print(F("Host: ")); - client.println(server); - client.print(F("Content-Type: text/csv\nConnection: close\nContent-Length: ")); - client.println(contentLen); - client.println(); - printCsvToStream(client); - client.println(); - if(debug) Serial.println("done!"); - - waitForResponse(); - - // reset index - sensorsIndex = 0; - - } - else { - // if you couldn't make a connection: - if(debug)Serial.println("connection failed. Restarting System."); - sleep(5000); - asm volatile (" jmp 0"); - } -} diff --git a/templates/home_wifi.tpl b/templates/home_wifi.tpl index a430e57..a76aa37 100644 --- a/templates/home_wifi.tpl +++ b/templates/home_wifi.tpl @@ -1,256 +1,238 @@ { "model": "homeWifi" } /* - senseBox Citizen Sensingplatform - WiFi Version: 1.2 - Date: 2017-02-28 - Homepage: http://www.sensebox.de + senseBox:home - Citizen Sensingplatform + Version: wifi_1.4 + Date: 2017-07-29 + Homepage: https://www.sensebox.de https://www.opensensemap.org Author: Institute for Geoinformatics, University of Muenster - Note: Sketch for SB-Home WiFi Edition + Note: Sketch for senseBox:home WiFi Edition + Model: homeWifi + Email: support@sensebox.de Code is in the public domain. + https://github.com/sensebox/node-sketch-templater */ -#include -#include "BMP280.h" -#include -#include -#include -#include -#include +/* ------------------------------------------------------------------------- */ +/* ------------------------------Configuration------------------------------ */ +/* ------------------------------------------------------------------------- */ -//Custom WiFi Parameters -const char ssid[] = ""; // your network SSID (name) -const char pass[] = ""; // your network password +// Wifi Credentials +const char *ssid = ""; // your network SSID (name) +const char *pass = ""; // your network password -//Network settings -const char *server = "@@INGRESS_DOMAIN@@"; -uint8_t status = WL_IDLE_STATUS; -WiFiClient client; +// Interval of measuring and submitting values in seconds +const unsigned int postingInterval = 60e3; -//Sensor Instances -Makerblog_TSL45315 TSL = Makerblog_TSL45315(TSL45315_TIME_M4); -HDC100X HDC(0x43); -BMP280 BMP; +// address of the server to send to +const char server[] PROGMEM = "@@INGRESS_DOMAIN@@"; -//measurement variables -#define UV_ADDR 0x38 -#define IT_1 0x1 -double tempBaro, pressure; -char result; - -typedef struct sensor { - const uint8_t ID[12]; -} sensor; - -uint8_t sensorsIndex = 0; +// senseBox ID +const char SENSEBOX_ID[] PROGMEM = "@@SENSEBOX_ID@@"; // Number of sensors +// Change this number if you add or remove sensors +// do not forget to remove or add the sensors on opensensemap.org static const uint8_t NUM_SENSORS = @@NUM_SENSORS@@; -// senseBox ID -const uint8_t SENSEBOX_ID[12] = { @@SENSEBOX_ID|toHex@@ }; - // sensor IDs -// Do not change order of sensor IDs -const sensor sensors[NUM_SENSORS] = { -@@SENSOR_IDS|toHexArray@@ -}; +@@SENSOR_IDS|toProgmem@@ -float values[NUM_SENSORS]; +// Uncomment the next line to get debugging messages printed on the Serial port +// Do not leave this enabled for long time use +// #define ENABLE_DEBUG -void addValue(const float &value) { - values[sensorsIndex] = value; - sensorsIndex = sensorsIndex + 1; -} +/* ------------------------------------------------------------------------- */ +/* --------------------------End of Configuration--------------------------- */ +/* ------------------------------------------------------------------------- */ -uint16_t getUV() { - byte msb = 0, lsb = 0; - uint16_t uvValue; - Wire.requestFrom(UV_ADDR + 1, 1); //MSB - sleep(1); - if (Wire.available()) msb = Wire.read(); - Wire.requestFrom(UV_ADDR + 0, 1); //LSB - sleep(1); - if (Wire.available()) lsb = Wire.read(); - uvValue = (msb << 8) | lsb; - return uvValue * 5.625; -} +#include "BMP280.h" +#include +#include +#include +#include +#include +#include +#include -int printHexToStream(const uint8_t *data, uint8_t length, Print &stream) // prints 8-bit data in hex -{ - byte first; - int j = 0; - for (uint8_t i=0; i> 4) | 48; - if (first > 57) { - stream.write(first + (byte)39); - } else { - stream.write(first); - } - j++; - - first = (data[i] & 0x0F) | 48; - if (first > 57) { - stream.write(first + (byte)39); - } else { - stream.write(first); - } - j++; - } - return j; -} +#ifdef ENABLE_DEBUG +#define DEBUG(str) Serial.println(str) +#else +#define DEBUG(str) +#endif -int printCsvToStream(Print &stream) { - int len = 0; - for (uint8_t i = 0; i < sensorsIndex; i++) { - if (!isnan(values[i])) { - len = len + printHexToStream(sensors[i].ID, 12, stream); - len = len + stream.print(","); - //do not print digits for illuminance und uv-intensity - if (i < 3 || i > 4) len = len + stream.println(values[i],1); - else len = len + stream.println(values[i],0); - } - } - return len; -} +WiFiClient client; +// Sensor Instances +Makerblog_TSL45315 TSL = Makerblog_TSL45315(TSL45315_TIME_M4); +HDC100X HDC(0x43); +BMP280 BMP; +VEML6070 VEML; -// millis() rollover fix - http://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover -void sleep(unsigned long ms) { // ms: duration - unsigned long start = millis(); // start: timestamp - for (;;) { - unsigned long now = millis(); // now: timestamp - unsigned long elapsed = now - start; // elapsed: duration - if (elapsed >= ms) // comparing durations: OK - return; - } +typedef struct measurement { + char *sensorId; + float value; +} measurement; + +measurement measurements[NUM_SENSORS]; +uint8_t num_measurements = 0; + +// buffer for sprintf +char buffer[150]; + +void addMeasurement(char *sensorId, float value) { + measurements[num_measurements].sensorId = sensorId; + measurements[num_measurements].value = value; + num_measurements++; } -void waitForResponse() -{ - // if there are incoming bytes from the server, read and print them - sleep(100); - String response = ""; - char c; - boolean repeat = true; - do { - if (client.available()) c = client.read(); - else repeat = false; - response += c; - if (response == "HTTP/1.1 ") response = ""; - if (c == '\n') repeat = false; - } - while (repeat); +void writeMeasurementsToClient(Print &stream) { + // iterate throug the measurements array + for (uint8_t i = 0; i < num_measurements; i++) { + sprintf_P(buffer, PSTR("%S,"), measurements[i].sensorId); + // arduino sprintf just returns "?" for floats, use dtostrf + dtostrf(measurements[i].value, 9, 2, &buffer[strlen(buffer)]); - Serial.print("Server Response: "); Serial.print(response); + // transmit buffer to client + stream.println(buffer); + DEBUG(buffer); + } - client.flush(); - client.stop(); + // reset num_measurements + num_measurements = 0; } void submitValues() { + if (WiFi.status() != WL_CONNECTED) { + WiFi.disconnect(); + delay(1000); // wait 1s + WiFi.begin(ssid, pass); + delay(5000); // wait 5s + } // close any connection before send a new request. // This will free the socket on the WiFi shield - Serial.println("__________________________\n"); if (client.connected()) { client.stop(); - sleep(1000); + delay(1000); } - // if there's a successful connection: - if (client.connect(server, 80)) { - - Serial.println("connecting..."); - // send the HTTP POST request: - - client.print(F("POST /boxes/")); - printHexToStream(SENSEBOX_ID, 12, client); - client.println(F("/data HTTP/1.1")); - - // !!!!! DO NOT REMOVE !!!!! - // !!!!! NICHT LÖSCHEN !!!!! - // print once to Serial to get the content-length - int contentLen = printCsvToStream(Serial); - // !!!!! DO NOT REMOVE !!!!! - // !!!!! NICHT LÖSCHEN !!!!! - - // Send the required header parameters - client.print(F("Host: ")); - client.println(server); - client.print(F("Content-Type: text/csv\nConnection: close\nContent-Length: ")); - client.println(contentLen); - client.println(); - printCsvToStream(client); - client.println(); - Serial.println("done!"); - - waitForResponse(); - - // reset index - sensorsIndex = 0; - + bool connected = false; + char _server[strlen_P(server)]; + strcpy_P(_server, server); + for (uint8_t timeout = 2; timeout != 0; timeout--) { + DEBUG(F("connecting...")); + connected = client.connect(_server, 80); + if (connected == true) { + DEBUG(F("Connection successful, transferring...")); + // construct the HTTP POST request: + sprintf_P(buffer, + PSTR("POST /boxes/%S/data HTTP/1.1\nHost: %S\nContent-Type: " + "csv\nConnection: close\nContent-Length: %i\n"), + SENSEBOX_ID, server, num_measurements * 36); + DEBUG(buffer); + + // send the HTTP POST request: + client.println(buffer); + + // send measurements + writeMeasurementsToClient(client); + + // send empty line to end the request + client.println(); + + delay(100); + client.flush(); + client.stop(); + + DEBUG("done!"); + + // reset number of measurements + num_measurements = 0; + break; + } + delay(1000); } - else { - // if you couldn't make a connection: - Serial.println("connection failed. Restarting System."); - sleep(5000); - asm volatile (" jmp 0"); + + if (connected == false) { + // Reset durchführen + Serial.println(F("connection failed. Restarting System.")); + delay(5000); + cli(); + wdt_enable(WDTO_60MS); + while (1) + ; } } void setup() { - //Initialize serial and wait for port to open: + // Initialize serial and wait for port to open: Serial.begin(9600); - //Enable Wifi Shield + + // Enable Wifi Shield pinMode(4, INPUT); digitalWrite(4, HIGH); - sleep(2000); - //Check WiFi Shield status + delay(2000); + // Check WiFi Shield status if (WiFi.status() == WL_NO_SHIELD) { - Serial.println("WiFi shield not present"); + Serial.println(F("WiFi shield not present")); // don't continue: - while (true); + while (true) + ; } + uint8_t status = WL_IDLE_STATUS; // attempt to connect to Wifi network: - while ( status != WL_CONNECTED) { - Serial.print("Attempting to connect to SSID: "); - Serial.println(ssid); - // Connect to WPA/WPA2 network. Change this line if using open or WEP network + while (status != WL_CONNECTED) { + DEBUG(F("Attempting to connect to SSID: ")); + DEBUG(ssid); + // Connect to WPA/WPA2 network. Change this line if using open or WEP + // network status = WiFi.begin(ssid, pass); - // wait 60 seconds for connection: - Serial.println(); - Serial.print("Waiting 10 seconds for connection..."); - sleep(10000); - Serial.println("done."); + // wait 10 seconds for connection: + DEBUG(F("Waiting 10 seconds for connection...")); + delay(10000); + DEBUG(F("done.")); } - Serial.print("Initializing sensors..."); - Wire.begin(); - Wire.beginTransmission(UV_ADDR); - Wire.write((IT_1 << 2) | 0x02); - Wire.endTransmission(); - sleep(500); + + // Sensor initialization + DEBUG(F("Initializing sensors...")); + VEML.begin(); + delay(500); HDC.begin(HDC100X_TEMP_HUMI, HDC100X_14BIT, HDC100X_14BIT, DISABLE); TSL.begin(); BMP.begin(); BMP.setOversampling(4); - Serial.println("done!"); - Serial.println("Starting loop."); + DEBUG(F("done!")); + DEBUG(F("Starting loop in 30 seconds.")); HDC.getTemp(); + delay(30000); } void loop() { - addValue(HDC.getTemp()); - sleep(200); - addValue(HDC.getHumi()); + // capture loop start timestamp + unsigned long start = millis(); + + // read measurements from sensors + addMeasurement(TEMPERSENSOR_ID, HDC.getTemp()); + delay(200); + addMeasurement(RELLUFSENSOR_ID, HDC.getHumi()); + + double tempBaro, pressure; + char result; result = BMP.startMeasurment(); if (result != 0) { - sleep(result); + delay(result); result = BMP.getTemperatureAndPressure(tempBaro, pressure); + addMeasurement(LUFTDRSENSOR_ID, pressure); } - addValue(pressure); - addValue(TSL.readLux()); - addValue(getUV()); + + addMeasurement(BELEUCSENSOR_ID, TSL.readLux()); + addMeasurement(UVINTESENSOR_ID, VEML.getUV()); submitValues(); - sleep(60000); + // schedule next round of measurements + for (;;) { + unsigned long now = millis(); + unsigned long elapsed = now - start; + if (elapsed >= postingInterval) + return; + } } - diff --git a/templates/home_wifi_feinstaub.tpl b/templates/home_wifi_feinstaub.tpl index 992d2a8..d8c34ea 100644 --- a/templates/home_wifi_feinstaub.tpl +++ b/templates/home_wifi_feinstaub.tpl @@ -1,277 +1,252 @@ { "model": "homeWifiFeinstaub" } /* - senseBox Home - Citizen Sensingplatform - WiFi Version: 1.3 - Date: 2017-05-31 + senseBox:home - Citizen Sensingplatform + Version: wifi_1.4 + Date: 2017-07-29 Homepage: https://www.sensebox.de https://www.opensensemap.org Author: Institute for Geoinformatics, University of Muenster Note: Sketch for senseBox:home WiFi with dust particle upgrade + Model: homeWifiFeinstaub Email: support@sensebox.de Code is in the public domain. + https://github.com/sensebox/node-sketch-templater */ -#include -#include "BMP280.h" -#include -#include -#include -#include -#include -#include - -//Custom WiFi Parameters -const char ssid[] = ""; // your network SSID (name) -const char pass[] = ""; // your network password - -bool debug = 0; - -//Network settings -const char *server = "@@INGRESS_DOMAIN@@"; -uint8_t status = WL_IDLE_STATUS; -WiFiClient client; -SDS011 my_sds(Serial); - -//Sensor Instances -Makerblog_TSL45315 TSL = Makerblog_TSL45315(TSL45315_TIME_M4); -HDC100X HDC(0x43); -BMP280 BMP; +/* ------------------------------------------------------------------------- */ +/* ------------------------------Configuration------------------------------ */ +/* ------------------------------------------------------------------------- */ -//measurement variables -#define UV_ADDR 0x38 -#define IT_1 0x1 -double tempBaro, pressure; -char result; -float pm10,pm25; -int error; +// Wifi Credentials +const char *ssid = ""; // your network SSID (name) +const char *pass = ""; // your network password -const unsigned int postingInterval = 60000; +// Interval of measuring and submitting values in seconds +const unsigned int postingInterval = 60e3; -typedef struct sensor { - const uint8_t ID[12]; -} sensor; +// address of the server to send to +const char server[] PROGMEM = "@@INGRESS_DOMAIN@@"; -uint8_t sensorsIndex = 0; +// senseBox ID +const char SENSEBOX_ID[] PROGMEM = "@@SENSEBOX_ID@@"; // Number of sensors +// Change this number if you add or remove sensors +// do not forget to remove or add the sensors on opensensemap.org static const uint8_t NUM_SENSORS = @@NUM_SENSORS@@; -// senseBox ID -const uint8_t SENSEBOX_ID[12] = { @@SENSEBOX_ID|toHex@@ }; - // sensor IDs -// Do not change order of sensor IDs -const sensor sensors[NUM_SENSORS] = { -@@SENSOR_IDS|toHexArray@@ -}; +@@SENSOR_IDS|toProgmem@@ -float values[NUM_SENSORS]; +// Uncomment the next line to get debugging messages printed on the Serial port +// Do not leave this enabled for long time use +// #define ENABLE_DEBUG -void addValue(const float &value) { - values[sensorsIndex] = value; - sensorsIndex = sensorsIndex + 1; -} +/* ------------------------------------------------------------------------- */ +/* --------------------------End of Configuration--------------------------- */ +/* ------------------------------------------------------------------------- */ -uint16_t getUV() { - byte msb = 0, lsb = 0; - uint16_t uvValue; - Wire.requestFrom(UV_ADDR + 1, 1); //MSB - sleep(1); - if (Wire.available()) msb = Wire.read(); - Wire.requestFrom(UV_ADDR + 0, 1); //LSB - sleep(1); - if (Wire.available()) lsb = Wire.read(); - uvValue = (msb << 8) | lsb; - return uvValue * 5.625; -} +#include "BMP280.h" +#include +#include +#include +#include +#include +#include +#include +#include -int printHexToStream(const uint8_t *data, uint8_t length, Print &stream) // prints 8-bit data in hex -{ - byte first; - int j = 0; - for (uint8_t i=0; i> 4) | 48; - if (first > 57) { - stream.write(first + (byte)39); - } else { - stream.write(first); - } - j++; - - first = (data[i] & 0x0F) | 48; - if (first > 57) { - stream.write(first + (byte)39); - } else { - stream.write(first); - } - j++; - } - return j; -} +#ifdef ENABLE_DEBUG +#define DEBUG(str) Serial.println(str) +#else +#define DEBUG(str) +#endif -int printCsvToStream(Print &stream) { - int len = 0; - for (uint8_t i = 0; i < sensorsIndex; i++) { - if (!isnan(values[i])) { - len = len + printHexToStream(sensors[i].ID, 12, stream); - len = len + stream.print(","); - //do not print digits for illuminance und uv-intensity - if (i < 3 || i > 4) len = len + stream.println(values[i],1); - else len = len + stream.println(values[i],0); - } - } - return len; -} +WiFiClient client; +// Sensor Instances +SDS011 my_sds(Serial); +Makerblog_TSL45315 TSL = Makerblog_TSL45315(TSL45315_TIME_M4); +HDC100X HDC(0x43); +BMP280 BMP; +VEML6070 VEML; -// millis() rollover fix - http://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover -void sleep(unsigned long ms) { // ms: duration - unsigned long start = millis(); // start: timestamp - for (;;) { - unsigned long now = millis(); // now: timestamp - unsigned long elapsed = now - start; // elapsed: duration - if (elapsed >= ms) // comparing durations: OK - return; - } +typedef struct measurement { + char *sensorId; + float value; +} measurement; + +measurement measurements[NUM_SENSORS]; +uint8_t num_measurements = 0; + +// buffer for sprintf +char buffer[150]; + +void addMeasurement(char *sensorId, float value) { + measurements[num_measurements].sensorId = sensorId; + measurements[num_measurements].value = value; + num_measurements++; } -void waitForResponse() -{ - // if there are incoming bytes from the server, read and print them - sleep(100); - String response = ""; - char c; - boolean repeat = true; - do { - if (client.available()) c = client.read(); - else repeat = false; - response += c; - if (response == "HTTP/1.1 ") response = ""; - if (c == '\n') repeat = false; - } - while (repeat); +void writeMeasurementsToClient(Print &stream) { + // iterate throug the measurements array + for (uint8_t i = 0; i < num_measurements; i++) { + sprintf_P(buffer, PSTR("%S,"), measurements[i].sensorId); + // arduino sprintf just returns "?" for floats, use dtostrf + dtostrf(measurements[i].value, 9, 2, &buffer[strlen(buffer)]); - if (debug) { - Serial.print("Server Response: "); - Serial.print(response); + // transmit buffer to client + stream.println(buffer); + DEBUG(buffer); } - client.flush(); - client.stop(); + // reset num_measurements + num_measurements = 0; } void submitValues() { + if (WiFi.status() != WL_CONNECTED) { + WiFi.disconnect(); + delay(1000); // wait 1s + WiFi.begin(ssid, pass); + delay(5000); // wait 5s + } // close any connection before send a new request. // This will free the socket on the WiFi shield - if (debug) Serial.println("__________________________\n"); if (client.connected()) { client.stop(); - sleep(1000); + delay(1000); } - // if there's a successful connection: - if (client.connect(server, 80)) { - - if (debug) Serial.println("connecting..."); - // send the HTTP POST request: - - client.print(F("POST /boxes/")); - printHexToStream(SENSEBOX_ID, 12, client); - client.println(F("/data HTTP/1.1")); - - // !!!!! NICHT LÖSCHEN !!!!! - // print once to Serial to get the content-length - int contentLen = printCsvToStream(Serial); - // !!!!! DO NOT REMOVE !!!!! - - // Send the required header parameters - client.print(F("Host: ")); - client.println(server); - client.print(F("Content-Type: text/csv\nConnection: close\nContent-Length: ")); - client.println(contentLen); - client.println(); - printCsvToStream(client); - client.println(); - if (debug) Serial.println("done!"); - - waitForResponse(); - - // reset index - sensorsIndex = 0; - + bool connected = false; + char _server[strlen_P(server)]; + strcpy_P(_server, server); + for (uint8_t timeout = 2; timeout != 0; timeout--) { + DEBUG(F("connecting...")); + connected = client.connect(_server, 80); + if (connected == true) { + DEBUG(F("Connection successful, transferring...")); + // construct the HTTP POST request: + sprintf_P(buffer, + PSTR("POST /boxes/%S/data HTTP/1.1\nHost: %S\nContent-Type: " + "csv\nConnection: close\nContent-Length: %i\n"), + SENSEBOX_ID, server, num_measurements * 36); + DEBUG(buffer); + + // send the HTTP POST request: + client.println(buffer); + + // send measurements + writeMeasurementsToClient(client); + + // send empty line to end the request + client.println(); + + delay(100); + client.flush(); + client.stop(); + + DEBUG("done!"); + + // reset number of measurements + num_measurements = 0; + break; + } + delay(1000); } - else { - // if you couldn't make a connection: - if (debug) Serial.println("connection failed. Restarting System."); - sleep(5000); - asm volatile (" jmp 0"); + + if (connected == false) { + // Reset durchführen + Serial.println(F("connection failed. Restarting System.")); + delay(5000); + cli(); + wdt_enable(WDTO_60MS); + while (1) + ; } } void setup() { - //Initialize serial and wait for port to open: + // Initialize serial and wait for port to open: Serial.begin(9600); - //Enable Wifi Shield + + // Enable Wifi Shield pinMode(4, INPUT); digitalWrite(4, HIGH); - sleep(2000); - //Check WiFi Shield status + delay(2000); + // Check WiFi Shield status if (WiFi.status() == WL_NO_SHIELD) { - if (debug) Serial.println("WiFi shield not present"); + Serial.println(F("WiFi shield not present")); // don't continue: - while (true); + while (true) + ; } + uint8_t status = WL_IDLE_STATUS; // attempt to connect to Wifi network: - while ( status != WL_CONNECTED) { - if (debug) Serial.print("Attempting to connect to SSID: "); - if (debug) Serial.println(ssid); - // Connect to WPA/WPA2 network. Change this line if using open or WEP network + while (status != WL_CONNECTED) { + DEBUG(F("Attempting to connect to SSID: ")); + DEBUG(ssid); + // Connect to WPA/WPA2 network. Change this line if using open or WEP + // network status = WiFi.begin(ssid, pass); - // wait 60 seconds for connection: - if (debug) { - Serial.println(); - Serial.print("Waiting 10 seconds for connection..."); - } - sleep(10000); - if (debug) Serial.println("done."); + // wait 10 seconds for connection: + DEBUG(F("Waiting 10 seconds for connection...")); + delay(10000); + DEBUG(F("done.")); } - if (debug) Serial.print("Initializing sensors..."); - Wire.begin(); - Wire.beginTransmission(UV_ADDR); - Wire.write((IT_1 << 2) | 0x02); - Wire.endTransmission(); - sleep(500); + + // Sensor initialization + DEBUG(F("Initializing sensors...")); + VEML.begin(); + delay(500); HDC.begin(HDC100X_TEMP_HUMI, HDC100X_14BIT, HDC100X_14BIT, DISABLE); TSL.begin(); BMP.begin(); BMP.setOversampling(4); - if (debug) { - Serial.println("done!"); - Serial.println("Starting loop in 30 seconds."); - } + DEBUG(F("done!")); + DEBUG(F("Starting loop in 30 seconds.")); HDC.getTemp(); - sleep(30000); + delay(30000); } void loop() { - addValue(HDC.getTemp()); - sleep(200); - addValue(HDC.getHumi()); + // capture loop start timestamp + unsigned long start = millis(); + + // read measurements from sensors + addMeasurement(TEMPERSENSOR_ID, HDC.getTemp()); + delay(200); + addMeasurement(RELLUFSENSOR_ID, HDC.getHumi()); + + double tempBaro, pressure; + char result; result = BMP.startMeasurment(); if (result != 0) { - sleep(result); + delay(result); result = BMP.getTemperatureAndPressure(tempBaro, pressure); - }else pressure = 0; - addValue(pressure); - addValue(TSL.readLux()); - addValue(getUV()); - error = my_sds.read(&pm25,&pm10); - if (error) { - pm25 = 0; - pm10 = 0; + addMeasurement(LUFTDRSENSOR_ID, pressure); + } + + addMeasurement(BELEUCSENSOR_ID, TSL.readLux()); + addMeasurement(UVINTESENSOR_ID, VEML.getUV()); + + uint8_t attempt = 0; + float pm10, pm25; + while (attempt < 5) { + bool error = my_sds.read(&pm25, &pm10); + if (!error) { + addMeasurement(PM10SENSOR_ID, pm10); + addMeasurement(PM25SENSOR_ID, pm25); + break; + } + attempt++; } - addValue(pm10); - addValue(pm25); submitValues(); - sleep(postingInterval); + // schedule next round of measurements + for (;;) { + unsigned long now = millis(); + unsigned long elapsed = now - start; + if (elapsed >= postingInterval) + return; + } } diff --git a/test/0-included-templates.js b/test/0-included-templates.js index b902dc5..e250f5a 100644 --- a/test/0-included-templates.js +++ b/test/0-included-templates.js @@ -3,7 +3,6 @@ /* global describe it before after */ const expect = require('chai').expect, testBox = require('./test-data/testBox'), - { hex } = require('./helpers'), helpers = require('../src/helpers'), SketchTemplater = require('../src'); @@ -55,13 +54,13 @@ describe('Included templates', function() { const sketch = mySketchTemplater.generateSketch(box); expect(sketch).to.include(testDomain); - expect(sketch).to.include(hex(box._id)); + expect(sketch).to.include(box._id); expect(sketch).to.include( `static const uint8_t NUM_SENSORS = ${box.sensors.length};` ); for (const { title, _id } of box.sensors) { expect(sketch).to.include(title); - expect(sketch).to.include(hex(_id)); + expect(sketch).to.include(_id); } } } diff --git a/test/2-transformers.js b/test/2-transformers.js index 5f514e2..aac4cbe 100644 --- a/test/2-transformers.js +++ b/test/2-transformers.js @@ -2,7 +2,6 @@ /* global describe it */ const expect = require('chai').expect, - { hex } = require('./helpers'), testBox = require('./test-data/testBox'), transformers = require('../src/transformers'); @@ -12,12 +11,6 @@ describe('Transformers', function() { expect(transformers['as-is'](teststring)).to.equal(teststring); }); - it('toHex should hexify a string', function() { - const teststring = 'DEADBEEF'; - const testresult = hex(teststring); - expect(transformers['toHex'](teststring)).to.equal(testresult); - }); - it('toDefine should transform a sensor array to multiple lines with #defines', function() { const { sensors } = testBox(); @@ -32,14 +25,17 @@ describe('Transformers', function() { } }); - it('toHexArray should transform a sensor array to its hex representations', function() { + it('toProgmem should transform a sensor array to multiple lines with PROGMEM chars', function() { const { sensors } = testBox(); - const result = transformers.toHexArray(sensors); + const result = transformers.toProgmem(sensors); + + expect(result).to.include('PROGMEM'); + expect(result).to.include('SENSOR'); for (const { title, _id } of sensors) { expect(result).to.include(title); - expect(result).to.include(hex(_id)); + expect(result).to.include(_id); } }); }); diff --git a/test/helpers.js b/test/helpers.js deleted file mode 100644 index bd9523c..0000000 --- a/test/helpers.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -module.exports = { - hex(str) { - return str - .split('') - .map((c, i) => { - return i % 2 ? `${c}, ` : `0x${c}`; - }) - .join('') - .slice(0, -2); - } -};