2022-04-22 21:20:37 +02:00
//#define DISABLE_WIFI
2022-05-20 23:08:36 +02:00
# define HW_PROTO_PAPER 1
# define HW_PROTO_V1 2
2022-04-22 21:20:37 +02:00
2024-04-05 20:16:05 +02:00
# ifndef LED_BUILTIN
# define LED_BUILTIN 2
# endif
# ifndef BUTTON_BUILTIN
# define BUTTON_BUILTIN 0
# endif
# include <WiFiManager-esp32.h> // https://github.com/admarschoonen/WiFiManager
2022-04-22 21:20:37 +02:00
# include <dESPatch.h>
# include <WiFi.h>
# include <WiFiMulti.h>
# include <HTTPClient.h>
# include <Adafruit_NeoPixel.h>
2022-05-22 23:41:02 +02:00
# include "bsec.h"
2022-05-21 10:28:59 +02:00
2024-04-05 20:16:05 +02:00
# include "soc/soc.h"
# include "soc/rtc_cntl_reg.h"
# ifndef LED_BUILTIN
# define LED_BUILTIN 2
# endif
2022-05-21 10:28:59 +02:00
# define NUM_LEDS_PROTO_PAPER 93
# define DATA_PIN_PROTO_PAPER 5
2022-05-22 15:02:17 +02:00
# define CONNECT_SW_PIN_PROTO_PAPER BUTTON_BUILTIN
2022-05-21 10:28:59 +02:00
# define NUM_LEDS_PROTO_V1 29
# define DATA_PIN_PROTO_V1 14
2022-05-22 15:02:17 +02:00
# define CONNECT_SW_PIN_PROTO_V1 21
2022-05-21 10:28:59 +02:00
static int BUIENRADAR_START_LED = 0 ;
static int BUIENRADAR_SKIP_LED = 1 ;
static int BUIENRADAR_NUM_LEDS = 12 ;
static int PAQI_START_LED = 0 ;
static int PAQI_SKIP_LED = 0 ;
static int PAQI_NUM_LEDS = 0 ;
static int UVI_LED = 0 ;
static int AQI_LED = 0 ;
static int POLLEN_LED = 0 ;
static int IAQI_LED = 0 ;
2022-05-22 15:02:17 +02:00
static int CONNECT_SW_PIN = 0 ;
2022-05-24 22:42:44 +02:00
static int LIGHT_PIN = 0 ;
2022-04-22 21:20:37 +02:00
# define SHOW_AQI_LED
# define SHOW_POLLEN_LED
# define SHOW_UVI_LED
# define MIN(x, y) (((x) <= (y)) ? (x) : (y))
2022-05-21 10:28:59 +02:00
Adafruit_NeoPixel leds_rgb_proto_paper ( NUM_LEDS_PROTO_PAPER , DATA_PIN_PROTO_PAPER , NEO_GRB + NEO_KHZ800 ) ;
Adafruit_NeoPixel leds_rgbw_proto_v1 ( NUM_LEDS_PROTO_V1 , DATA_PIN_PROTO_V1 , NEO_RGBW + NEO_KHZ800 ) ;
2022-05-24 22:24:39 +02:00
const uint8_t bsec_config_iaq [ ] = {
# include "config/generic_33v_3s_4d/bsec_iaq.txt"
} ;
2022-05-24 00:07:24 +02:00
static int ledMapPrecipitation [ 12 ] = { 0 } ;
static int ledMapPAQI [ 12 ] = { 0 } ;
static int ledMapUVI = 0 ;
static int ledMapPollen = 0 ;
static int ledMapIAQI = 0 ;
static int ledMapAQI = 0 ;
2022-05-21 10:28:59 +02:00
# define SEALEVELPRESSURE_HPA (1013.25)
# define BME_CS 5
2022-05-22 23:41:02 +02:00
String output ;
Bsec iaqSensor ;
2022-04-22 21:20:37 +02:00
static HTTPClient http ;
2022-05-27 20:48:58 +02:00
static const String baseUrlAQI = " https://sinoptik.luon.net/forecast?metrics=PAQI&metrics=AQI&metrics=pollen&metrics=UVI " ;
static const String baseUrlPrecipitation = " https://sinoptik.luon.net/forecast?metrics=precipitation " ;
2022-04-22 21:20:37 +02:00
2022-05-21 10:28:59 +02:00
static int hw_variant = 0 ;
2022-04-22 21:20:37 +02:00
WiFiManager wifiManager ;
DESPatch dESPatch ;
const char * root_ca = \
" -----BEGIN CERTIFICATE----- \n " \
2024-04-05 20:16:05 +02:00
" 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 \n " \
2022-04-22 21:20:37 +02:00
" -----END CERTIFICATE----- \n " ;
2024-04-05 20:16:05 +02:00
2022-04-22 21:20:37 +02:00
const float location [ ] = { 51.445466493287434 , 5.515445691496135 } ; // Telefoonstraat, Eindhoven
const String address = " Telefoonstraat 18, Eindhoven " ;
//const float location[] = {51.44083, 5.47778}; // Eindhoven
//const float location[] = {52.09083, 5.12222}; // Utrecht
//const float location[] = {51.8425, 5.85278}; // Nijmegen
//const float location[] = {52.37403, 4.88969}; // Amsterdam
//const float location[] = {52.15833, 4.49306}; // Leiden
typedef struct RainPickerDataArray24 {
const int len = 24 ;
long time [ 24 ] ;
float value [ 24 ] ;
} RainPickerDataArray24 ;
typedef struct RainPickerDataArray5 {
const int len = 5 ;
long time [ 5 ] ;
float value [ 5 ] ;
} RainPickerDataArray5 ;
typedef struct RainpickerData {
float lat ;
float lon ;
2022-05-15 07:45:31 +02:00
long time ;
2022-04-22 21:20:37 +02:00
RainPickerDataArray24 PAQI ;
2022-05-20 20:15:34 +02:00
RainPickerDataArray24 AQI ;
RainPickerDataArray24 pollen ;
2022-04-22 21:20:37 +02:00
RainPickerDataArray5 UVI ;
RainPickerDataArray24 precipitation ;
} RainpickerData ;
RainpickerData rainpickerData ;
StaticJsonDocument < 6144 > doc ;
2022-05-22 22:25:08 +02:00
static bool initDone = false ;
2022-04-22 21:20:37 +02:00
void parseJson ( String * payload )
{
doc . clear ( ) ;
DeserializationError error = deserializeJson ( doc , * payload ) ;
if ( error ) {
Serial . print ( F ( " deserializeJson() failed: " ) ) ;
Serial . println ( error . f_str ( ) ) ;
return ;
}
rainpickerData . lat = doc [ " lat " ] ;
rainpickerData . lon = doc [ " lon " ] ;
rainpickerData . time = doc [ " time " ] ;
int n = 0 ;
for ( JsonObject elem : doc [ " PAQI " ] . as < JsonArray > ( ) ) {
if ( n > = rainpickerData . PAQI . len ) {
break ;
}
rainpickerData . PAQI . time [ n ] = elem [ " time " ] ;
rainpickerData . PAQI . value [ n ] = elem [ " value " ] ;
n = n + 1 ;
}
2022-05-20 20:15:34 +02:00
n = 0 ;
for ( JsonObject elem : doc [ " AQI " ] . as < JsonArray > ( ) ) {
if ( n > = rainpickerData . AQI . len ) {
break ;
}
rainpickerData . AQI . time [ n ] = elem [ " time " ] ;
rainpickerData . AQI . value [ n ] = elem [ " value " ] ;
n = n + 1 ;
2022-05-16 22:07:27 +02:00
}
2022-05-20 20:15:34 +02:00
n = 0 ;
for ( JsonObject elem : doc [ " pollen " ] . as < JsonArray > ( ) ) {
if ( n > = rainpickerData . pollen . len ) {
break ;
}
rainpickerData . pollen . time [ n ] = elem [ " time " ] ;
rainpickerData . pollen . value [ n ] = elem [ " value " ] ;
n = n + 1 ;
2022-05-16 22:07:27 +02:00
}
2022-05-15 07:45:31 +02:00
2022-04-22 21:20:37 +02:00
n = 0 ;
for ( JsonObject elem : doc [ " UVI " ] . as < JsonArray > ( ) ) {
if ( n > = rainpickerData . UVI . len ) {
break ;
}
rainpickerData . UVI . time [ n ] = elem [ " time " ] ;
rainpickerData . UVI . value [ n ] = elem [ " value " ] ;
n = n + 1 ;
}
n = 0 ;
for ( JsonObject elem : doc [ " precipitation " ] . as < JsonArray > ( ) ) {
if ( n > = rainpickerData . precipitation . len ) {
break ;
}
rainpickerData . precipitation . time [ n ] = elem [ " time " ] ;
rainpickerData . precipitation . value [ n ] = elem [ " value " ] ;
n = n + 1 ;
}
}
2022-05-21 10:28:59 +02:00
static void setup_pins_proto_paper ( void )
{
2022-05-24 00:07:24 +02:00
int n = 0 ;
2022-05-21 10:28:59 +02:00
BUIENRADAR_START_LED = 32 ;
BUIENRADAR_SKIP_LED = 1 ;
BUIENRADAR_NUM_LEDS = 12 ;
PAQI_START_LED = 72 ;
PAQI_SKIP_LED = 0 ;
PAQI_NUM_LEDS = 12 ;
// #define UVI_LED 92 // LED in center
UVI_LED = 84 ; // LED above center
AQI_LED = 86 ; // LED to the right
POLLEN_LED = 90 ; // LED to the left
IAQI_LED = 88 ; // LED below center
2022-05-22 15:02:17 +02:00
CONNECT_SW_PIN = CONNECT_SW_PIN_PROTO_PAPER ;
2022-05-24 00:07:24 +02:00
n = 0 ;
while ( n < BUIENRADAR_NUM_LEDS ) {
ledMapPrecipitation [ n ] = BUIENRADAR_START_LED + n * ( BUIENRADAR_SKIP_LED + 1 ) ;
n = n + 1 ;
}
n = 0 ;
while ( n < PAQI_NUM_LEDS ) {
ledMapPAQI [ n ] = PAQI_START_LED + n * ( PAQI_SKIP_LED + 1 ) ;
n = n + 1 ;
}
ledMapAQI = AQI_LED ;
ledMapUVI = UVI_LED ;
ledMapPollen = POLLEN_LED ;
ledMapIAQI = IAQI_LED ;
2022-05-21 10:28:59 +02:00
}
static void setup_pins_proto_v1 ( void )
{
2022-05-24 00:07:24 +02:00
int n = 0 ;
2022-05-21 10:28:59 +02:00
BUIENRADAR_START_LED = 0 ;
BUIENRADAR_SKIP_LED = 0 ;
BUIENRADAR_NUM_LEDS = 12 ;
PAQI_START_LED = 12 ;
PAQI_SKIP_LED = 0 ;
PAQI_NUM_LEDS = 12 ;
UVI_LED = 27 ; // LED above center
AQI_LED = 24 ; // LED to the right
POLLEN_LED = 26 ; // LED to the left
IAQI_LED = 25 ; // LED below center
2022-05-22 15:02:17 +02:00
CONNECT_SW_PIN = CONNECT_SW_PIN_PROTO_V1 ;
2022-05-24 00:07:24 +02:00
ledMapPrecipitation [ 0 ] = 11 ;
n = 1 ;
while ( n < BUIENRADAR_NUM_LEDS ) {
ledMapPrecipitation [ n ] = BUIENRADAR_START_LED + ( n - 1 ) * ( BUIENRADAR_SKIP_LED + 1 ) ;
n = n + 1 ;
}
ledMapPAQI [ 0 ] = 23 ;
n = 1 ;
while ( n < PAQI_NUM_LEDS ) {
ledMapPAQI [ n ] = PAQI_START_LED + ( n - 1 ) * ( PAQI_SKIP_LED + 1 ) ;
n = n + 1 ;
}
ledMapAQI = AQI_LED ;
ledMapUVI = UVI_LED ;
ledMapPollen = POLLEN_LED ;
ledMapIAQI = IAQI_LED ;
2022-05-24 22:42:44 +02:00
LIGHT_PIN = 34 ;
2022-05-25 23:04:20 +02:00
analogSetPinAttenuation ( LIGHT_PIN , ADC_0db ) ;
analogReadResolution ( 12 ) ;
2022-05-22 15:02:17 +02:00
}
void leds_clear ( void ) {
if ( hw_variant = = HW_PROTO_PAPER ) {
leds_rgb_proto_paper . clear ( ) ;
leds_rgb_proto_paper . show ( ) ;
} else if ( hw_variant = = HW_PROTO_V1 ) {
leds_rgbw_proto_v1 . clear ( ) ;
leds_rgbw_proto_v1 . show ( ) ;
}
2022-05-21 10:28:59 +02:00
}
2022-05-22 23:41:02 +02:00
int checkIaqSensorStatus ( void )
{
2024-04-05 20:16:05 +02:00
if ( iaqSensor . bsecStatus ! = BSEC_OK ) {
if ( iaqSensor . bsecStatus < BSEC_OK ) {
output = " BSEC error code : " + String ( iaqSensor . bsecStatus ) ;
2022-05-22 23:41:02 +02:00
Serial . println ( output ) ;
//for (;;);
} else {
2024-04-05 20:16:05 +02:00
output = " BSEC warning code : " + String ( iaqSensor . bsecStatus ) ;
2022-05-22 23:41:02 +02:00
Serial . println ( output ) ;
}
}
2024-04-05 20:16:05 +02:00
if ( iaqSensor . bme68xStatus ! = BME68X_OK ) {
if ( iaqSensor . bme68xStatus < BME68X_OK ) {
output = " BME680 error code : " + String ( iaqSensor . bme68xStatus ) ;
2022-05-22 23:41:02 +02:00
Serial . println ( output ) ;
//for (;;);
} else {
2024-04-05 20:16:05 +02:00
output = " BME680 warning code : " + String ( iaqSensor . bme68xStatus ) ;
2022-05-22 23:41:02 +02:00
Serial . println ( output ) ;
}
}
2024-04-05 20:16:05 +02:00
return iaqSensor . bme68xStatus ;
2022-05-22 23:41:02 +02:00
}
2022-05-22 22:25:08 +02:00
void readSensors ( void ) {
static bool readingInProgress = false ;
static unsigned long endTime = 0 ;
if ( hw_variant = = HW_PROTO_PAPER ) {
return ;
}
2022-05-22 23:41:02 +02:00
unsigned long time_trigger = millis ( ) ;
if ( iaqSensor . run ( ) ) { // If new data is available
2022-06-04 10:37:23 +02:00
output = String ( time_trigger ) ;
output + = " Sensor data: Traw: " + String ( iaqSensor . rawTemperature ) ;
2022-05-22 23:41:02 +02:00
output + = " *C , P: " + String ( iaqSensor . pressure ) ;
output + = " hPa, RHraw: " + String ( iaqSensor . rawHumidity ) ;
output + = " %, Rgas: " + String ( iaqSensor . gasResistance ) ;
output + = " Ohm, IAQ: " + String ( iaqSensor . iaq ) ;
output + = " , accuracy: " + String ( iaqSensor . iaqAccuracy ) ;
output + = " , Tcorr: " + String ( iaqSensor . temperature ) ;
2022-05-24 22:24:39 +02:00
output + = " *C, RHcorr: " + String ( iaqSensor . humidity ) ;
output + = " %, IAQstatic: " + String ( iaqSensor . staticIaq ) ;
2022-05-22 23:41:02 +02:00
output + = " , eCO2: " + String ( iaqSensor . co2Equivalent ) ;
output + = " ppm, eVOC: " + String ( iaqSensor . breathVocEquivalent ) ;
output + = " ppm " ;
2022-05-24 22:42:44 +02:00
2022-05-25 23:33:57 +02:00
int light = 0 ;
for ( int n = 0 ; n < 256 ; n + + ) {
light + = analogRead ( LIGHT_PIN ) ;
}
light = ( light + 128 ) > > 8 ;
2022-05-24 22:42:44 +02:00
output + = " , light: " + String ( light ) ;
2022-05-22 23:41:02 +02:00
Serial . println ( output ) ;
2022-05-22 22:25:08 +02:00
} else {
2022-05-22 23:41:02 +02:00
checkIaqSensorStatus ( ) ;
2022-05-22 22:25:08 +02:00
}
}
void taskBME680 ( void * parameter )
{
while ( initDone = = false ) {
delay ( 100 ) ;
}
while ( true ) {
readSensors ( ) ;
delay ( 100 ) ;
}
//Serial.println("Ending task 1");
//vTaskDelete( NULL );
}
2022-04-22 21:20:37 +02:00
void setup ( ) {
const char url [ ] = " https://apikey:cqprlgiafadnidsgeqozcpldkaeqimqw@despatch.luon.net/files/4/despatch.json " ;
unsigned long interval = 60 ; // By default check for updates every 60 seconds
int x ;
2024-04-05 20:16:05 +02:00
WRITE_PERI_REG ( RTC_CNTL_BROWN_OUT_REG , 0 ) ; // Disable brownout; needed for some dev kits
2022-04-22 21:20:37 +02:00
// sanity check delay - allows reprogramming if accidently blowing power w/leds
delay ( 2000 ) ;
2022-05-21 10:28:59 +02:00
2022-04-22 21:20:37 +02:00
Serial . begin ( 115200 ) ;
Serial . println ( " buienradarklok starting " ) ;
2022-05-27 20:48:58 +02:00
http . setReuse ( false ) ;
2022-05-22 23:41:02 +02:00
SPI . begin ( ) ;
iaqSensor . begin ( BME_CS , SPI ) ;
String output = " \n BSEC library version " + String ( iaqSensor . version . major ) + " . " + String ( iaqSensor . version . minor ) + " . " + String ( iaqSensor . version . major_bugfix ) + " . " + String ( iaqSensor . version . minor_bugfix ) ;
Serial . println ( output ) ;
x = checkIaqSensorStatus ( ) ;
2024-04-05 20:16:05 +02:00
if ( x ! = BME68X_OK ) {
2022-05-21 10:28:59 +02:00
Serial . println ( F ( " Could not find a valid BME680 sensor; assuming hw variant \" paper prototype \" ! " ) ) ;
hw_variant = HW_PROTO_PAPER ;
setup_pins_proto_paper ( ) ;
leds_rgb_proto_paper . begin ( ) ; // INITIALIZE NeoPixel strip object
} else {
Serial . println ( F ( " BME680 found; assuming hw variant \" proto v1 \" " ) ) ;
2022-05-24 22:24:39 +02:00
iaqSensor . setConfig ( bsec_config_iaq ) ;
iaqSensor . setTemperatureOffset ( 13.5f ) ;
checkIaqSensorStatus ( ) ;
2022-05-22 23:41:02 +02:00
2022-05-21 10:28:59 +02:00
hw_variant = HW_PROTO_V1 ;
setup_pins_proto_v1 ( ) ;
leds_rgbw_proto_v1 . begin ( ) ; // INITIALIZE NeoPixel strip object
}
2022-05-22 23:41:02 +02:00
bsec_virtual_sensor_t sensorList [ 10 ] = {
BSEC_OUTPUT_RAW_TEMPERATURE ,
BSEC_OUTPUT_RAW_PRESSURE ,
BSEC_OUTPUT_RAW_HUMIDITY ,
BSEC_OUTPUT_RAW_GAS ,
BSEC_OUTPUT_IAQ ,
BSEC_OUTPUT_STATIC_IAQ ,
BSEC_OUTPUT_CO2_EQUIVALENT ,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT ,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE ,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY ,
} ;
iaqSensor . updateSubscription ( sensorList , 10 , BSEC_SAMPLE_RATE_LP ) ;
checkIaqSensorStatus ( ) ;
// Print the header
output = " Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%], Static IAQ, CO2 equivalent, breath VOC equivalent " ;
Serial . println ( output ) ;
2022-05-22 15:02:17 +02:00
leds_clear ( ) ;
2022-04-22 21:20:37 +02:00
# ifndef DISABLE_WIFI
//wifiManager.resetSettings();
2022-05-22 15:02:17 +02:00
wifiManager . configure ( " Claire- " , true , LED_BUILTIN , true , CONNECT_SW_PIN , false ) ;
2024-04-05 20:16:05 +02:00
2022-04-22 21:20:37 +02:00
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point
//and goes into a blocking loop awaiting configuration
if ( ! wifiManager . autoConnect ( ) ) {
Serial . println ( " failed to connect and hit timeout " ) ;
//reset and try again, or maybe put it to deep sleep
ESP . restart ( ) ;
delay ( 1000 ) ;
}
//if you get here you have connected to the WiFi
Serial . print ( " connected with address: " ) ;
Serial . println ( WiFi . localIP ( ) ) ;
2022-05-21 10:28:59 +02:00
if ( hw_variant = = HW_PROTO_PAPER ) {
//keep LED on
digitalWrite ( LED_BUILTIN , LED_ON_VALUE_DEFAULT ) ;
}
2022-04-22 21:20:37 +02:00
x = dESPatch . configure ( url , true , false , interval , false , root_ca ) ;
Serial . print ( " dESPatch.configure() returned with code " ) ;
Serial . println ( x ) ;
# endif
2022-05-22 22:25:08 +02:00
initDone = true ;
xTaskCreate ( taskBME680 , " taskBME680 " , 10000 , NULL , 1 , NULL ) ;
2022-04-22 21:20:37 +02:00
}
// From https://circuits4you.com/2019/03/21/esp8266-url-encode-decode-example/
String urlencode ( String str )
{
String encodedString = " " ;
char c ;
char code0 ;
char code1 ;
char code2 ;
for ( int i = 0 ; i < str . length ( ) ; i + + ) {
c = str . charAt ( i ) ;
if ( c = = ' ' ) {
encodedString + = ' + ' ;
} else if ( isalnum ( c ) ) {
encodedString + = c ;
} else {
code1 = ( c & 0xf ) + ' 0 ' ;
if ( ( c & 0xf ) > 9 ) {
code1 = ( c & 0xf ) - 10 + ' A ' ;
}
c = ( c > > 4 ) & 0xf ;
code0 = c + ' 0 ' ;
if ( c > 9 ) {
code0 = c - 10 + ' A ' ;
}
code2 = ' \0 ' ;
encodedString + = ' % ' ;
encodedString + = code0 ;
encodedString + = code1 ;
//encodedString+=code2;
}
yield ( ) ;
}
return encodedString ;
}
void getPrecipitation ( const float * location ) {
int httpCode ;
//String url = baseUrl + "&lat=" + String(location[0]) + "&lon=" + String(location[1]);
String url , latS , lonS ;
int tmp1 , tmp2 ;
String payload = " " ;
tmp1 = int ( location [ 0 ] ) ;
tmp2 = int ( ( location [ 0 ] - tmp1 ) * 1000000 ) ;
latS = String ( tmp1 ) + " . " + String ( tmp2 ) ;
tmp1 = int ( location [ 1 ] ) ;
tmp2 = int ( ( location [ 1 ] - tmp1 ) * 1000000 ) ;
lonS = String ( tmp1 ) + " . " + String ( tmp2 ) ;
url = baseUrlPrecipitation + " &lat= " + latS + " &lon= " + lonS ;
2022-06-04 10:37:23 +02:00
Serial . print ( millis ( ) ) ;
Serial . print ( " Retrieving precipitation from " ) ;
2022-04-22 21:20:37 +02:00
Serial . println ( url ) ;
2022-05-27 20:48:58 +02:00
http . begin ( url , root_ca ) ;
2022-04-22 21:20:37 +02:00
httpCode = http . GET ( ) ;
if ( httpCode > 0 ) {
payload = http . getString ( ) ;
parseJson ( & payload ) ;
} else {
2022-06-04 10:37:23 +02:00
Serial . print ( millis ( ) ) ;
Serial . print ( " Got http code " ) ;
2022-04-22 21:20:37 +02:00
Serial . println ( httpCode ) ;
}
http . end ( ) ;
}
void getPrecipitation ( const String address ) {
int httpCode ;
//String url = baseUrl + "&lat=" + String(location[0]) + "&lon=" + String(location[1]);
String url , a ;
String payload = " " ;
a = urlencode ( address ) ;
url = baseUrlPrecipitation + " &address= " + a ;
2022-06-04 10:37:23 +02:00
Serial . print ( millis ( ) ) ;
Serial . print ( " Retrieving precipitation from " ) ;
2022-04-22 21:20:37 +02:00
Serial . println ( url ) ;
2022-05-27 20:48:58 +02:00
http . begin ( url , root_ca ) ;
2022-04-22 21:20:37 +02:00
httpCode = http . GET ( ) ;
if ( httpCode > 0 ) {
payload = http . getString ( ) ;
parseJson ( & payload ) ;
} else {
2022-06-04 10:37:23 +02:00
Serial . print ( millis ( ) ) ;
Serial . print ( " Got http code " ) ;
2022-04-22 21:20:37 +02:00
Serial . println ( httpCode ) ;
}
http . end ( ) ;
}
void getAQI ( const float * location ) {
int httpCode ;
//String url = baseUrl + "&lat=" + String(location[0]) + "&lon=" + String(location[1]);
String url , latS , lonS ;
int tmp1 , tmp2 ;
String payload = " " ;
tmp1 = int ( location [ 0 ] ) ;
tmp2 = int ( ( location [ 0 ] - tmp1 ) * 1000000 ) ;
latS = String ( tmp1 ) + " . " + String ( tmp2 ) ;
tmp1 = int ( location [ 1 ] ) ;
tmp2 = int ( ( location [ 1 ] - tmp1 ) * 1000000 ) ;
lonS = String ( tmp1 ) + " . " + String ( tmp2 ) ;
url = baseUrlAQI + " &lat= " + latS + " &lon= " + lonS ;
2022-06-04 10:37:23 +02:00
Serial . print ( millis ( ) ) ;
Serial . print ( " Retrieving AQI from " ) ;
2022-04-22 21:20:37 +02:00
Serial . println ( url ) ;
2022-05-27 20:48:58 +02:00
http . begin ( url , root_ca ) ;
2022-04-22 21:20:37 +02:00
httpCode = http . GET ( ) ;
if ( httpCode > 0 ) {
payload = http . getString ( ) ;
parseJson ( & payload ) ;
} else {
2022-06-04 10:37:23 +02:00
Serial . print ( millis ( ) ) ;
Serial . print ( " Got http code " ) ;
2022-04-22 21:20:37 +02:00
Serial . println ( httpCode ) ;
}
http . end ( ) ;
}
void getAQI ( const String address ) {
int httpCode ;
//String url = baseUrl + "&lat=" + String(location[0]) + "&lon=" + String(location[1]);
String url , a ;
String payload = " " ;
a = urlencode ( address ) ;
url = baseUrlAQI + " &address= " + a ;
2022-06-04 10:37:23 +02:00
Serial . print ( millis ( ) ) ;
Serial . print ( " Retrieving AQI from " ) ;
2022-04-22 21:20:37 +02:00
Serial . println ( url ) ;
2022-05-27 20:48:58 +02:00
http . begin ( url , root_ca ) ;
2022-04-22 21:20:37 +02:00
httpCode = http . GET ( ) ;
if ( httpCode > 0 ) {
payload = http . getString ( ) ;
parseJson ( & payload ) ;
} else {
2022-06-04 10:37:23 +02:00
Serial . print ( millis ( ) ) ;
Serial . print ( " Got http code " ) ;
2022-04-22 21:20:37 +02:00
Serial . println ( httpCode ) ;
}
http . end ( ) ;
}
static int colormap ( float x ) {
// Input: intensity
// Output: RGB encoded pixel color similar to luchtmeetnet legend
int y = 0 ;
if ( x < 1.0 ) {
y = ( 0 < < 16 ) | ( 0 < < 8 ) | 0 ; // black (good)
} else if ( x < 2.0 ) {
// 1.0 <= x < 2.0
2022-05-21 10:28:59 +02:00
if ( hw_variant = = HW_PROTO_PAPER ) {
y = ( 0 < < 16 ) | ( 0 < < 8 ) | 160 ; // blue (good)
} else if ( hw_variant = = HW_PROTO_V1 ) {
y = ( 0 < < 16 ) | ( 0 < < 8 ) | 255 ; // blue (good)
}
2022-04-22 21:20:37 +02:00
} else if ( x < 3.0 ) {
// 2.0 <= x < 3.0
y = ( 0 < < 16 ) | ( 255 < < 8 ) | 255 ; // cyan (good)
} else if ( x < 4.0 ) {
// 3.0 <= x < 4.0
y = ( 255 < < 16 ) | ( 255 < < 8 ) | 255 ; // white (mediocre)
} else if ( x < 5.0 ) {
// 4.0 <= x < 5.0
y = ( 200 < < 16 ) | ( 200 < < 8 ) | 32 ; // light yellow (mediocre)
} else if ( x < 6.0 ) {
// 5.0 <= x < 6.0
y = ( 120 < < 16 ) | ( 120 < < 8 ) | 0 ; // yellow (mediocre)
} else if ( x < 7.0 ) {
// 6.0 <= x < 7.0
y = ( 200 < < 16 ) | ( 80 < < 8 ) | 0 ; // orange (inadequate)
} else if ( x < 8.0 ) {
// 7.0 <= x < 8.0
y = ( 255 < < 16 ) | ( 50 < < 8 ) | 0 ; // red orange (inadequate)
} else if ( x < 9.0 ) {
// 8.0 <= x < 9.0
y = ( 180 < < 16 ) | ( 0 < < 8 ) | 0 ; // red (bad)
} else if ( x < 10.0 ) {
// 9.0 <= x < 10.0
y = ( 200 < < 16 ) | ( 0 < < 8 ) | 160 ; // magenta (bad)
} else {
// 10.0 <= x
y = ( 60 < < 16 ) | ( 0 < < 8 ) | 210 ; // purple (terrible)
}
return y ;
}
2022-05-23 00:07:50 +02:00
float colormapIaqi ( void )
{
float x = 0.0f ;
2022-05-24 22:24:39 +02:00
float iaqi = iaqSensor . staticIaq ;
2022-05-23 00:07:50 +02:00
if ( iaqi < = 50.0f ) {
x = 1.0f ; // Excellent
} else if ( iaqi < = 100.0f ) {
x = 2.0f ; // Good
2022-05-24 00:07:24 +02:00
} else if ( iaqi < = 125.0f ) {
x = 4.0f ;
2022-05-23 00:07:50 +02:00
} else if ( iaqi < = 150.0f ) {
x = 4.0f ; // Lightly polluted
2022-05-24 00:07:24 +02:00
} else if ( iaqi < = 175.0f ) {
x = 5.0f ;
2022-05-23 00:07:50 +02:00
} else if ( iaqi < = 200.0f ) {
2022-05-24 00:07:24 +02:00
x = 6.0f ; // Moderately polluted
} else if ( iaqi < = 225.0f ) {
x = 7.0f ;
2022-05-23 00:07:50 +02:00
} else if ( iaqi < = 250.0f ) {
2022-05-24 00:07:24 +02:00
x = 8.0f ; // Heavily polluted
} else if ( iaqi < = 300.0f ) {
x = 9.0f ;
2022-05-23 00:07:50 +02:00
} else if ( iaqi < = 350.0f ) {
x = 10.0f ; // Severely polluted
} else {
x = 11.0f ; // Extremely polluted
}
return colormap ( x ) ;
}
2022-04-22 21:20:37 +02:00
static float buienradarMap ( float x ) {
// Input: rain intensity (mm/h)
// Output: floating point number which can be mapped on color scale
float y = 0 ;
// Use E3 series of preferred numbers to map intensity to color
if ( x < 0.1 ) {
y = 0.5 ;
} else if ( x < 0.22 ) {
y = 1.5 ;
} else if ( x < 0.47 ) {
y = 2.5 ;
} else if ( x < 1.0 ) {
y = 3.5 ;
} else if ( x < 2.2 ) {
y = 4.5 ;
} else if ( x < 4.7 ) {
y = 5.5 ;
} else if ( x < 10 ) {
y = 6.5 ;
} else if ( x < 22 ) {
y = 7.5 ;
} else if ( x < 47 ) {
y = 8.5 ;
} else if ( x < 100 ) {
y = 9.5 ;
} else {
y = 10.5 ;
}
return y ;
}
2022-05-22 15:02:17 +02:00
static void ledsSetPixelColor ( uint32_t ledIdx , int r , int g , int b , int w ) {
if ( hw_variant = = HW_PROTO_PAPER ) {
leds_rgb_proto_paper . setPixelColor ( ledIdx , leds_rgb_proto_paper . Color ( r , g , b ) ) ;
} else if ( hw_variant = = HW_PROTO_V1 ) {
leds_rgbw_proto_v1 . setPixelColor ( ledIdx , leds_rgbw_proto_v1 . Color ( g , r , b , w ) ) ;
}
}
static void ledsSetPixelColor ( uint32_t ledIdx , int r , int g , int b ) {
ledsSetPixelColor ( ledIdx , r , g , b , 0 ) ;
}
2022-05-20 23:08:36 +02:00
static void updateLedsNoWifi ( void ) {
uint32_t ledIdx ;
uint32_t ledCount ;
uint32_t color ;
int r , g , b , w , n ;
2022-05-21 10:28:59 +02:00
if ( hw_variant = = HW_PROTO_PAPER ) {
// Start by setting all leds to value of the first datapoint
ledIdx = 11 ;
ledCount = 0 ;
for ( ledCount = 0 ; ledCount < 11 ; ledCount + + ) {
color = colormap ( ledCount ) ;
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
2022-05-22 15:02:17 +02:00
ledsSetPixelColor ( ledIdx , r , g , b ) ;
2022-05-21 10:28:59 +02:00
ledIdx = ledIdx + PAQI_SKIP_LED + 1 ;
}
} else if ( hw_variant = = HW_PROTO_V1 ) {
// Start by setting all leds to value of the first datapoint
ledIdx = 0 ;
ledCount = 0 ;
for ( ledCount = 0 ; ledCount < 11 ; ledCount + + ) {
color = colormap ( ledCount ) ;
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
w = ( color & 0xFF000000 ) > > 24 ;
2022-05-22 15:02:17 +02:00
ledsSetPixelColor ( ledIdx , r , g , b , w ) ;
2022-05-21 10:28:59 +02:00
ledIdx = ledIdx + PAQI_SKIP_LED + 1 ;
}
}
2022-05-20 23:08:36 +02:00
}
2022-04-22 21:20:37 +02:00
static void updateLeds ( void ) {
uint32_t ledIdx ;
uint32_t ledCount ;
uint32_t color ;
2022-05-21 10:28:59 +02:00
int r , g , b , w , n ;
2022-04-22 21:20:37 +02:00
// Start by setting all leds to value of the first datapoint
ledIdx = PAQI_START_LED ;
ledCount = 0 ;
for ( ledCount = 0 ; ledCount < PAQI_NUM_LEDS ; ledCount + + ) {
color = colormap ( rainpickerData . PAQI . value [ 0 ] ) ;
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
2022-05-21 10:28:59 +02:00
w = ( color & 0xFF000000 ) > > 24 ;
2022-04-22 21:20:37 +02:00
2022-05-24 00:07:24 +02:00
ledsSetPixelColor ( ledMapPAQI [ ledCount ] , r , g , b ) ;
2022-04-22 21:20:37 +02:00
ledIdx = ledIdx + PAQI_SKIP_LED + 1 ;
}
ledIdx = PAQI_START_LED ;
ledCount = 0 ;
for ( n = 0 ; n < rainpickerData . PAQI . len ; n + + ) {
if ( rainpickerData . time < rainpickerData . PAQI . time [ n ] ) {
ledIdx = ledIdx + PAQI_SKIP_LED + 1 ;
ledCount = ledCount + 1 ;
}
if ( ledCount > = PAQI_NUM_LEDS ) {
break ;
}
color = colormap ( rainpickerData . PAQI . value [ n ] ) ;
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
2022-05-21 10:28:59 +02:00
w = ( color & 0xFF000000 ) > > 24 ;
2022-04-22 21:20:37 +02:00
2022-05-24 00:07:24 +02:00
ledsSetPixelColor ( ledMapPAQI [ ledCount ] , r , g , b ) ;
2022-04-22 21:20:37 +02:00
}
# ifdef SHOW_AQI_LED
2022-05-20 20:15:34 +02:00
// calculate AQI max value for next 12 hours
uint32_t AQI_max_value = 0 ;
//Serial.println("AQI:");
for ( n = 0 ; n < rainpickerData . AQI . len ; n + + ) {
/*Serial.print(" ");
Serial . print ( rainpickerData . AQI . time [ n ] ) ;
Serial . print ( " : " ) ;
Serial . println ( rainpickerData . AQI . value [ n ] ) ; */
if ( rainpickerData . time - rainpickerData . AQI . time [ n ] > = 60 * 60 ) {
continue ;
}
if ( rainpickerData . AQI . time [ n ] > = rainpickerData . time + PAQI_NUM_LEDS * 60 * 60 ) {
break ;
}
if ( rainpickerData . AQI . value [ n ] > AQI_max_value ) {
AQI_max_value = rainpickerData . AQI . value [ n ] ;
}
}
//Serial.print("AQI max value: ");
//Serial.println(AQI_max_value);
color = colormap ( AQI_max_value ) ;
2022-04-22 21:20:37 +02:00
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
2022-05-22 15:02:17 +02:00
ledsSetPixelColor ( AQI_LED , r , g , b ) ;
2022-04-22 21:20:37 +02:00
# endif
# ifdef SHOW_POLLEN_LED
2022-05-20 20:15:34 +02:00
// calculate pollen max value for next 12 hours
uint32_t pollen_max_value = rainpickerData . pollen . value [ 0 ] ;
for ( n = 0 ; n < rainpickerData . pollen . len ; n + + ) {
if ( rainpickerData . time - rainpickerData . pollen . time [ n ] > = 60 * 60 ) {
continue ;
}
if ( rainpickerData . pollen . time [ n ] > = rainpickerData . time + PAQI_NUM_LEDS * 60 * 60 ) {
break ;
}
if ( rainpickerData . pollen . value [ n ] > pollen_max_value ) {
pollen_max_value = rainpickerData . pollen . value [ n ] ;
}
}
color = colormap ( pollen_max_value ) ;
2022-04-22 21:20:37 +02:00
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
2022-05-22 15:02:17 +02:00
ledsSetPixelColor ( POLLEN_LED , r , g , b ) ;
2022-04-22 21:20:37 +02:00
# endif
# ifdef SHOW_UVI_LED
// calculate UVI led value
// UVI data is daily based --> search for first timestamp in the future and select value of the timestamp just before that
uint32_t UVI_value = rainpickerData . UVI . value [ 0 ] ;
for ( n = 0 ; n < rainpickerData . UVI . len ; n + + ) {
if ( rainpickerData . UVI . time [ n ] > = rainpickerData . time ) {
break ;
}
UVI_value = rainpickerData . UVI . value [ n ] ;
}
color = colormap ( UVI_value ) ;
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
2022-05-22 15:02:17 +02:00
ledsSetPixelColor ( UVI_LED , r , g , b ) ;
2022-04-22 21:20:37 +02:00
# endif
// Start by setting all leds to value of the first datapoint
ledIdx = BUIENRADAR_START_LED ;
for ( ledCount = 0 ; ledCount < BUIENRADAR_NUM_LEDS ; ledCount + + ) {
color = colormap ( rainpickerData . precipitation . value [ 0 ] ) ;
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
2022-05-24 00:07:24 +02:00
ledsSetPixelColor ( ledMapPrecipitation [ ledCount ] , r , g , b ) ;
2022-04-22 21:20:37 +02:00
ledIdx = ledIdx + BUIENRADAR_SKIP_LED + 1 ;
}
ledIdx = BUIENRADAR_START_LED ;
ledCount = 0 ;
for ( n = 0 ; n < rainpickerData . precipitation . len ; n + + ) {
if ( rainpickerData . time < rainpickerData . precipitation . time [ n ] ) {
ledIdx = ledIdx + BUIENRADAR_SKIP_LED + 1 ;
ledCount = ledCount + 1 ;
}
if ( ledCount > = BUIENRADAR_NUM_LEDS ) {
break ;
}
color = colormap ( buienradarMap ( rainpickerData . precipitation . value [ n ] ) ) ;
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
2022-05-24 00:07:24 +02:00
ledsSetPixelColor ( ledMapPrecipitation [ ledCount ] , r , g , b ) ;
2022-05-21 10:28:59 +02:00
}
2022-05-22 15:02:17 +02:00
ledsSetPixelColor ( IAQI_LED , r , g , b ) ;
2022-05-22 23:41:02 +02:00
if ( hw_variant = = HW_PROTO_V1 ) {
2022-05-23 00:07:50 +02:00
color = colormapIaqi ( ) ;
2022-05-22 23:41:02 +02:00
r = ( color & 0xFF0000 ) > > 16 ;
g = ( color & 0x00FF00 ) > > 8 ;
b = ( color & 0x0000FF ) ;
ledsSetPixelColor ( IAQI_LED , r , g , b ) ;
}
2022-05-21 10:28:59 +02:00
}
2022-05-22 15:02:17 +02:00
void readConnectButton ( void ) {
static int reset_wifi_timer = millis ( ) ;
static bool reset_blocked = true ;
2022-05-21 10:28:59 +02:00
2022-05-22 15:02:17 +02:00
if ( digitalRead ( CONNECT_SW_PIN ) = = HIGH ) {
// button released
reset_wifi_timer = millis ( ) ;
reset_blocked = false ;
digitalWrite ( LED_BUILTIN , LOW ) ;
} else {
// button pressed
if ( reset_blocked = = false ) {
int delta = millis ( ) - reset_wifi_timer ;
if ( delta < 10000 ) {
if ( delta % 1000 < 500 ) {
digitalWrite ( LED_BUILTIN , HIGH ) ;
} else {
digitalWrite ( LED_BUILTIN , LOW ) ;
}
} else {
leds_clear ( ) ;
wifiManager . resetSettings ( ) ;
// block reset so user must release button before we can reset again
reset_blocked = true ;
digitalWrite ( LED_BUILTIN , LOW ) ;
ESP . restart ( ) ;
}
}
}
2022-04-22 21:20:37 +02:00
}
void loop ( void ) {
static unsigned long t_prev = 0 ;
static bool ledOn = false ;
unsigned long t_now = millis ( ) ;
const int buttonPin = 0 ;
static int rainColor [ 12 ] = { 0 } ;
static int AQIColor [ 12 ] = { 0 } ;
static bool firstTime = true ;
static int counter = 0 ;
if ( firstTime | | ( t_now - t_prev > = 60000 ) ) {
t_prev = t_now ;
firstTime = false ;
# ifndef DISABLE_WIFI
2022-06-05 17:22:54 +02:00
if ( WiFi . status ( ) ! = WL_CONNECTED ) {
Serial . print ( millis ( ) ) ;
Serial . print ( " wifi status error: " ) ;
Serial . print ( WiFi . status ( ) ) ;
Serial . print ( " ; expected: " ) ;
Serial . println ( WL_CONNECTED ) ;
bool result = WiFi . reconnect ( ) ;
Serial . print ( millis ( ) ) ;
Serial . print ( " reconnecting result: " ) ;
Serial . print ( result ) ;
Serial . print ( " ; expected: " ) ;
Serial . println ( ESP_OK ) ;
}
getPrecipitation ( address ) ;
2022-04-22 21:20:37 +02:00
if ( counter = = 0 ) {
getAQI ( address ) ;
}
counter = counter + 1 ;
if ( counter = = 5 ) {
// AQI should only be retreived every 5 minutes
counter = 0 ;
}
# endif
}
# ifdef DISABLE_WIFI
updateLedsNoWifi ( ) ;
# else
updateLeds ( ) ;
# endif
2022-05-21 10:28:59 +02:00
if ( hw_variant = = HW_PROTO_PAPER ) {
leds_rgb_proto_paper . show ( ) ;
} else if ( hw_variant = = HW_PROTO_V1 ) {
leds_rgbw_proto_v1 . show ( ) ;
}
2022-05-22 15:02:17 +02:00
readConnectButton ( ) ;
2022-04-22 21:20:37 +02:00
delay ( 100 ) ;
# ifndef DISABLE_WIFI
dESPatch . checkForUpdate ( true ) ;
# endif
}