diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 2521773..3762d44 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ firmware/config_user.h +firmware/.DS_Store +.DS_Store +schematics/#auto_saved_files# +schematics/_autosave-oko-weatherstation.sch +firmware.ino.bin diff --git a/esphome_config/esphome_run_weatherstation.sh b/esphome_config/esphome_run_weatherstation.sh deleted file mode 100644 index adfd1b8..0000000 --- a/esphome_config/esphome_run_weatherstation.sh +++ /dev/null @@ -1,2 +0,0 @@ - -sudo docker-compose exec esphome esphome run /config/weatherstation.yml diff --git a/esphome_config/weatherstation.yml b/esphome_config/weatherstation.yml deleted file mode 100644 index 6f240c9..0000000 --- a/esphome_config/weatherstation.yml +++ /dev/null @@ -1,179 +0,0 @@ -esphome: - name: weatherstation - platform: ESP8266 - board: d1_mini - -i2c: - - id: bus_a - sda: 4 # D2 - scl: 5 # D1 - scan: true - -apds9960: - address: 0x39 - update_interval: 300s - -sensor: - # - #################### wind sensor - - platform: pulse_counter - pin: - # pin D8 - number: GPIO15 - mode: INPUT # TODO check if required - unit_of_measurement: 'm/s' ##change to m/s if metric - name: 'wind_speed' - icon: 'mdi:weather-windy' - id: my_wind - count_mode: - rising_edge: DISABLE - falling_edge: INCREMENT - internal_filter: 50us - update_interval: 60s - #rotations_per_sec = pulses/2/60 - #circ_m=0.09*2*3.14 = 0.5652 - #mps = 1.18*circ_m*rotations_per_sec - #mps = 1.18*0.5652/2/60 =0,0055578 - filters: - - multiply: 0.0055578 #use for m/s - # - multiply: 2.237 #m/s to mph - # - sliding_window_moving_average: - # window_size: 4 - # send_every: 1 - #- multiply: 0.04973 #1.492mph switch to close 1/sec per spec, pulse/sec (/60/2)*1.492 - #- multiply: 0.0124327986 #m/s * mph conversion - - #################### apds9960 sensor i2c - - platform: apds9960 - type: CLEAR - name: "APDS9960_clear_channel" - - platform: apds9960 - type: RED - name: "APDS9960_red_channel" - id: apds9960_red - - platform: apds9960 - type: GREEN - name: "APDS9960_green_channel" - id: apds9960_green - - platform: apds9960 - type: BLUE - name: "APDS9960_blue_channel" - id: apds9960_blue - # TODO fix calculation to get lux instead of a percentual value - # - # Code from Adafruit_APDS9960 lib: - # illuminance = (-0.32466F * r) + (1.57837F * g) + (-0.73191F * b); - # - # Code from: https://esphome.io/api/apds9960_8cpp_source.html - # 180: float red_perc = (uint_red / float(UINT16_MAX)) * 100.0f; - # 181: float green_perc = (uint_green / float(UINT16_MAX)) * 100.0f; - # 182: float blue_perc = (uint_blue / float(UINT16_MAX)) * 100.0f; - - platform: template - name: "light" - lambda: |- - const float perc_to_raw = 65535.0 / 100.0; - const float red_to_lux = -0.32466; - const float green_to_lux = 1.57837; - const float blue_to_lux = -0.73191; - return ((red_to_lux * id(apds9960_red).raw_state) + (green_to_lux * id(apds9960_green).raw_state) + (blue_to_lux * id(apds9960_blue).raw_state)) * perc_to_raw; - update_interval: 300s - accuracy_decimals: 2 - unit_of_measurement: 'lux' - - #################### bme280 sensor i2c - - platform: bme280 - temperature: - name: "BME280_temperature" - id: bme280_temperature - pressure: - name: "BME280_ressure" - id: bme280_pressure - humidity: - name: "BME280 Relative Humidity" - id: bme280_humidity - address: 0x76 - update_interval: 300s - - - platform: template - name: "altitude" - lambda: |- - const float STANDARD_SEA_LEVEL_PRESSURE = 1013.25; //in hPa, see note - return ((id(bme280_temperature).state + 273.15) / 0.0065) * - (powf((STANDARD_SEA_LEVEL_PRESSURE / id(bme280_pressure).state), 0.190234) - 1); // in meter - update_interval: 300s - icon: 'mdi:signal' - unit_of_measurement: 'm' - - - platform: template - name: "absolute_humidity" - lambda: |- - const float mw = 18.01534; // molar mass of water g/mol - const float r = 8.31447215; // Universal gas constant J/mol/K - return (6.112 * powf(2.718281828, (17.67 * id(bme280_temperature).state) / - (id(bme280_temperature).state + 243.5)) * id(bme280_humidity).state * mw) / - ((273.15 + id(bme280_temperature).state) * r); // in grams/m^3 - accuracy_decimals: 2 - update_interval: 300s - icon: 'mdi:water' - unit_of_measurement: 'g/m³' - - - platform: template - name: "dew_point" - lambda: |- - return (243.5*(log(id(bme280_humidity).state/100)+((17.67*id(bme280_temperature).state)/ - (243.5+id(bme280_temperature).state)))/(17.67-log(id(bme280_humidity).state/100)- - ((17.67*id(bme280_temperature).state)/(243.5+id(bme280_temperature).state)))); - unit_of_measurement: °C - update_interval: 300s - icon: 'mdi:thermometer-alert' - - # battery power adc - - platform: adc - pin: A0 - name: "battery_power" - update_interval: 300s - -binary_sensor: - # battery charged pin - - platform: gpio - pin: - number: 12 # D6 - mode: - input: true - pullup: false - name: "battery_charged" - - # battery charging pin - - platform: gpio - pin: - number: 14 # D5 - mode: - input: true - pullup: false - name: "battery_charging" - -time: - - platform: sntp - id: my_time - -# Enable logging -logger: - -# Enable Home Assistant API -api: - -ota: - password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" - -wifi: - ssid: UPC4556888 - password: emmydhvZ4faw - manual_ip: - # Set this to the IP of the ESP - static_ip: 192.168.0.91 - # Set this to the IP address of the router. Often ends with .1 - gateway: 192.168.0.1 - # The subnet of the network. 255.255.255.0 works for most home networks. - subnet: 255.255.255.0 - -captive_portal: diff --git a/esphome_firmware/weatherstation.yml b/esphome_firmware/weatherstation.yml deleted file mode 100644 index 61f0e38..0000000 --- a/esphome_firmware/weatherstation.yml +++ /dev/null @@ -1,146 +0,0 @@ -esphome: - name: weatherstation - platform: ESP8266 - board: d1_mini - -i2c: - - id: bus_a - sda: 4 # D2 - scl: 5 # D1 - scan: true - -apds9960: - address: 0x39 - update_interval: 300s - -sensor: - # - #################### wind sensor - - platform: pulse_counter - pin: - # pin D8 - number: GPIO15 - mode: INPUT_PULLUP # TODO check if required - unit_of_measurement: 'm/s' ##change to m/s if metric - name: 'wind_speed' - icon: 'mdi:weather-windy' - id: my_wind - count_mode: - rising_edge: DISABLE - falling_edge: INCREMENT - internal_filter: 50us - update_interval: 300s - #rotations_per_sec = pulses/2/60 - #circ_m=0.09*2*3.14 = 0.5652 - #mps = 1.18*circ_m*rotations_per_sec - #mps = 1.18*0.5652/2/60 =0,0055578 - filters: - - multiply: 0.0055578 #use for m/s - # - multiply: 2.237 #m/s to mph - # - sliding_window_moving_average: - # window_size: 4 - # send_every: 1 - #- multiply: 0.04973 #1.492mph switch to close 1/sec per spec, pulse/sec (/60/2)*1.492 - #- multiply: 0.0124327986 #m/s * mph conversion - - #################### apds9960 sensor i2c - - platform: apds9960 - type: CLEAR - name: "APDS9960_clear_channel" - - - platform: bme280 - temperature: - name: "BME280_temperature" - id: bme280_temperature - pressure: - name: "BME280_ressure" - id: bme280_pressure - humidity: - name: "BME280 Relative Humidity" - id: bme280_humidity - address: 0x76 - update_interval: 300s - - - platform: template - name: "altitude" - lambda: |- - const float STANDARD_SEA_LEVEL_PRESSURE = 1013.25; //in hPa, see note - return ((id(bme280_temperature).state + 273.15) / 0.0065) * - (powf((STANDARD_SEA_LEVEL_PRESSURE / id(bme280_pressure).state), 0.190234) - 1); // in meter - update_interval: 300s - icon: 'mdi:signal' - unit_of_measurement: 'm' - - - platform: template - name: "absolute_humidity" - lambda: |- - const float mw = 18.01534; // molar mass of water g/mol - const float r = 8.31447215; // Universal gas constant J/mol/K - return (6.112 * powf(2.718281828, (17.67 * id(bme280_temperature).state) / - (id(bme280_temperature).state + 243.5)) * id(bme280_humidity).state * mw) / - ((273.15 + id(bme280_temperature).state) * r); // in grams/m^3 - accuracy_decimals: 2 - update_interval: 300s - icon: 'mdi:water' - unit_of_measurement: 'g/m³' - - - platform: template - name: "dew_point" - lambda: |- - return (243.5*(log(id(bme280_humidity).state/100)+((17.67*id(bme280_temperature).state)/ - (243.5+id(bme280_temperature).state)))/(17.67-log(id(bme280_humidity).state/100)- - ((17.67*id(bme280_temperature).state)/(243.5+id(bme280_temperature).state)))); - unit_of_measurement: °C - update_interval: 300s - icon: 'mdi:thermometer-alert' - - # battery power adc - - platform: adc - pin: A0 - name: "battery_power" - update_interval: 300s - -binary_sensor: - # battery charged pin - - platform: gpio - pin: - number: 12 # D6 - mode: - input: true - pullup: false - name: "battery_charged" - - # battery charging pin - - platform: gpio - pin: - number: 14 # D5 - mode: - input: true - pullup: false - name: "battery_charging" - -time: - - platform: sntp - id: my_time - -# Enable logging -logger: - -# Enable Home Assistant API -api: - -ota: - password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" - -wifi: - ssid: UPC4556888 - password: emmydhvZ4faw - manual_ip: - # Set this to the IP of the ESP - static_ip: 192.168.0.91 - # Set this to the IP address of the router. Often ends with .1 - gateway: 192.168.0.1 - # The subnet of the network. 255.255.255.0 works for most home networks. - subnet: 255.255.255.0 - -captive_portal: diff --git a/firmware/README.md b/firmware/README.md old mode 100644 new mode 100755 diff --git a/firmware/config.h b/firmware/config.h old mode 100755 new mode 100644 index 09ffc77..2b2c99e --- a/firmware/config.h +++ b/firmware/config.h @@ -1,29 +1,21 @@ #ifndef __CONFIG_H__ #define __CONFIG_H__ -#define SENSOR_TEMPERATURE 0 -#define SENSOR_HUMIDITY 1 -#define SENSOR_LIGHT 2 -#define SENSOR_WINDSPEED 3 -#define SENSOR_PRESSURE 4 -#define SENSOR_BAT_VOLTAGE 5 -#define SENSOR_ESAVEMODE 6 -#define SENSOR_BATCHARGESTATE 7 +// config general setting and behavior of the weatherstation -#define BAT_CHARGE_STATE_CHARGED 2.0 -#define BAT_CHARGE_STATE_CHARGING 1.0 -#define BAT_CHARGE_STATE_NOTCHARGING 0.0 -#define ENERGY_SAVE_MODE_ENABLED 1.0 -#define ENERGY_SAVE_MODE_DISABLED 0.0 - -#define WIFI_AUTOCONNECT_TIMEOUT_S 120 -#define WIFI_CONFIG_PORTAL_TIMEOUT_S 120 -#define UPDATE_SENSOR_INTERVAL_S 10 -#define UPDATE_WEBSERVER_INTVERVAL_S 1 +#define WIFI_AUTOCONNECT_TIMEOUT_S 120 +#define WIFI_CONFIG_PORTAL_TIMEOUT_S 120 +#define UPDATE_SENSOR_INTERVAL_S 300 +#define UPDATE_WEBSERVER_INTVERVAL_S 1 // Do not change, bigger values will prevent using webupdater webinterface #define DELAY_LOOP_MS 50 #define POWERSAVING_SLEEP_S 600 #define EMERGENCY_SLEEP_S 172800 // Sleep for 2 days to recover +#define RESET_ESP_TIME_INTERVAL_MS 3600000 +#define WIND_SENSOR_MEAS_TIME_S 15 +#define INITIAL_WEBSERVER_TIME 20 + #define ENERGY_SAVING_ITERATIONS 30 +#define WIFI_MINIMUM_SIGNAL_QUALITY 10 // percent #define BAT_LOW_VOLTAGE 3.6 #define BAT_EMERGENCY_DEEPSLEEP_VOLTAGE 3.5 @@ -47,6 +39,6 @@ #define BME_CS 10 #define BME_ADDRESS 0x76 -#define INITIAL_WEBSERVER_TIME 20 +#define WEB_UPDATER_HTTP_PORT 8080 -#endif +#endif diff --git a/firmware/config_user.h.example b/firmware/config_user.h.example old mode 100644 new mode 100755 index 4383af4..6dbd1b4 --- a/firmware/config_user.h.example +++ b/firmware/config_user.h.example @@ -7,20 +7,34 @@ // Debug output on the serial console #define DEBUG +// Device name +// WARNING: Keep the name short! If your access point did not show up, you +// maybe have a TOO LONG SSID! +String DEVICE_NAME = "weatherstation"; + // Enable/Disable features //#define WEBUPDATER_FEATURE #define INFLUXDB_FEATURE +#define INFLUXDB_VERSION 1 // 1 or 2 #define SERIAL_FEATURE -#define BATTERY_POWERED -#define SENSOR_WIND +//#define BATTERY_POWERED +//#define SENSOR_WIND #define SENSOR_APDS9960 //#define SENSOR_APDS9930 #define SENSOR_BME280 #define SENSOR_BATTERY //#define BAT_PINS_D34 +// Homebridge Webstat is only possible if webupdater is also enabled +//#define HOMEBRIDGE_WEBSTAT +// retries to connect after 5 seconds or starts the wifimanager +#define SLEEP_IF_NO_WLAN_CONNECTION +// Restarts the firmware every n seconds +//#define RESET_ESP_TIMEINTERVAL // BETA STATUS +//#define HTTP_CALL_ON_WINDSPEED_EXCEED // BETA STATUS const float HUMIDITY_FACTOR = 1.0; const float LIGHT_FACTOR = 1.0; +const float TEMP_FACTOR = 1.0; // InfluxDB credentials const char *INFLUXDB_HOST = "hostname"; @@ -29,9 +43,34 @@ const char *INFLUXDB_DB = "database"; const char *INFLUXDB_USER = "user"; const char *INFLUXDB_PASS = "password"; -// Device name -// WARNING: Keep the name short! If your access point did not show up, you -// maybe have a TOO LONG SSID! -String DEVICE_NAME = "devicename"; +// InfluxDB2 credentials +/* +const char *INFLUXDB_URL = "http://192.168.0.123:3124"; +const char *INFLUXDB_ORG = "home_org"; +const char *INFLUXDB_BUCKET = "mybucket"; +const char *INFLUXDB_TOKEN = "your api token"; +*/ + +// enable HTTP_CALL_ON_WINDSPEED_EXCEED to enable this feature +#define HTTP_CALL_ON_WINDSPEED_EXCEED_MPS 5.0 // 5.0 m/s == 18 km/h +#define HTTP_CALL_ON_WINDSPEED_INTERVAL_S 60 // it's required to be bigger than WIND_SENSOR_MEAS_TIME_S +#define HTTP_CALL_ON_WINDSPEED_URL "http://192.168.178.100:3001/button-windspeedexceed?event=click" + +// anemometer settings, to use enable SENSOR_WIND +// thingiverse anemometer settings: https://www.thingiverse.com/thing:2559929/files +#define ROTOR_LENGTH_CM 8.25 +#define ROTOR_LENGTH_M (ROTOR_LENGTH_CM / 100.0) +//#define ROTOR_LENGTH_KM (ROTOR_LENGTH_M / 1000.0) // configuration example for generalization +//#define SEC_TO_HOUR_FACTOR (60.0 * 60.0) // configuration example for generalization +#define MPS_CORRECT_FACT 9.28 +//#define COUNT_TO_KMH ((TWO_PI * ROTOR_LENGTH_KM / WIND_SENSOR_MEAS_TIME_S) * SEC_TO_HOUR_FACTOR) // configuration exampe for generalization +#define COUNT_TO_MPS (TWO_PI * ROTOR_LENGTH_M / WIND_SENSOR_MEAS_TIME_S) +// only this define is used for calculation, all other before are only used to describe the math v_wind = correction_factor * rotations * 2 * pi * radius / time_of_measurement_in_sec +// and if required the result has t be multiplied by another factor to convert it from m/s +#define WINDSPEED_FACTOR (COUNT_TO_MPS * MPS_CORRECT_FACT) + +// china aliexpress anemometer settings (calculation unknown) +//#define WINDSPEED_FACTOR 2.4 #endif + diff --git a/firmware/constants.h b/firmware/constants.h new file mode 100644 index 0000000..6710d2e --- /dev/null +++ b/firmware/constants.h @@ -0,0 +1,20 @@ + +#ifndef __CONSTANTS_H__ +#define __CONSTANTS_H__ + +#define SENSOR_TEMPERATURE 0 +#define SENSOR_HUMIDITY 1 +#define SENSOR_LIGHT 2 +#define SENSOR_WINDSPEED 3 +#define SENSOR_PRESSURE 4 +#define SENSOR_BAT_VOLTAGE 5 +#define SENSOR_ESAVEMODE 6 +#define SENSOR_BATCHARGESTATE 7 + +#define BAT_CHARGE_STATE_CHARGED 2.0 +#define BAT_CHARGE_STATE_CHARGING 1.0 +#define BAT_CHARGE_STATE_NOTCHARGING 0.0 +#define ENERGY_SAVE_MODE_ENABLED 1.0 +#define ENERGY_SAVE_MODE_DISABLED 0.0 + +#endif diff --git a/firmware/firmware.ino b/firmware/firmware.ino old mode 100755 new mode 100644 index 5918152..3009661 --- a/firmware/firmware.ino +++ b/firmware/firmware.ino @@ -1,55 +1,63 @@ -// Standard ESP8266 libs +// Standard ESP8266 libs from project folder #include #include #include #include #include +#include -#include // WiFiClient -#include // WiFiManager +#include // WiFiClient +#include // WiFiManager from bib manager // Project includes +#include "constants.h" #include "config.h" - #include "config_user.h" //*************************************************************************// +// check if some settings are correct + +#ifdef HTTP_CALL_ON_WINDSPEED_EXCEED +#if (HTTP_CALL_ON_WINDSPEED_INTERVAL_S < WIND_SENSOR_MEAS_TIME_S) +#error "HTTP_CALL_ON_WINDSPEED_INTERVAL_S < WIND_SENSOR_MEAS_TIME_S" +#endif +#endif + +//*************************************************************************// +// constant variables const uint8_t VALUES = 8; float currentSensorData[VALUES] = {nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value"), nanf("no value")}; float (*sensors[VALUES])() = {}; -uint16_t update_sensor_cnt = 0; -uint16_t update_webserver_cnt = 0; +uint16_t update_sensor_cnt = 0; +uint16_t update_webserver_cnt = 0; +uint16_t update_windspeed_exceed_cnt = 0; WiFiManager wifiManager; //*************************************************************************// -void debug(String x) { +void debug(String x) +{ #ifdef DEBUG Serial.println(x); #endif } - -void setup() { - - // Erase WiFi Credentials (maybe this will work ...) - //WiFi.disconnect(true); - //delay(2000); - //ESP.reset(); +void setup() +{ #if defined(DEBUG) || defined(SERIAL_FEATURE) Serial.begin(115200); #endif // Pin settings - pinMode(BAT_CHARGED_PIN, INPUT); - pinMode(BAT_CHARGING_PIN, INPUT); - pinMode(STATUS_LED_PIN, OUTPUT); - pinMode(ANEMOMETER_PIN, INPUT_PULLUP); - pinMode(A0, INPUT); + pinMode(BAT_CHARGED_PIN, INPUT); + pinMode(BAT_CHARGING_PIN, INPUT); + pinMode(STATUS_LED_PIN, OUTPUT); + pinMode(ANEMOMETER_PIN, INPUT_PULLUP); + pinMode(A0, INPUT); digitalWrite(STATUS_LED_PIN, LOW); @@ -62,18 +70,28 @@ void setup() { #ifdef BATTERY_POWERED criticalBatCheck(); #endif + // Establish WiFi connection String wifiName = "oko-weather-" + DEVICE_NAME; - wifiManager.setMinimumSignalQuality(16); - wifiManager.setConnectTimeout(WIFI_AUTOCONNECT_TIMEOUT_S); // the time in seconds to wait for the known wifi connection - wifiManager.setTimeout(WIFI_CONFIG_PORTAL_TIMEOUT_S); // the time in seconds to wait for the user to configure the device + wifiManager.setMinimumSignalQuality(WIFI_MINIMUM_SIGNAL_QUALITY); + // the time in seconds to wait for the known wifi connection + wifiManager.setConnectTimeout(WIFI_AUTOCONNECT_TIMEOUT_S); + // the time in seconds to wait for the user to configure the device + wifiManager.setTimeout(WIFI_CONFIG_PORTAL_TIMEOUT_S); - if (!wifiManager.autoConnect(wifiName.c_str(), "DEADBEEF")) { - debug("WiFi connection failed, going into deep sleep ..."); + while (!wifiManager.autoConnect(wifiName.c_str(), "DEADBEEF")) + { + debug("WiFi connection failed, try again in 5 seconds..."); // If autoconnect to WLAN failed and no client connected, go to deep sleep +#ifdef SLEEP_IF_NO_WLAN_CONNECTION ESP.deepSleep(POWERSAVING_SLEEP_S * 1000000, WAKE_RF_DEFAULT); delay(100); +#endif +#ifndef SLEEP_IF_NO_WLAN_CONNECTION + // sleep a few seconds and go on trying to connect + delay(5000); +#endif } debug("Connected!"); @@ -123,6 +141,16 @@ void setup() { //It's magic! leave in delay(100); +#ifdef RESET_ESP_TIMEINTERVAL + // if millis() reached interval (1h) restart ESP + if (millis() >= RESET_ESP_TIME_INTERVAL_MS) + { + debug("Resetting firmware intentionally"); + // Push reset button after flashing once or do a manual power cycle to get the functionality working. + ESP.restart(); + } +#endif + #ifdef BATTERY_POWERED debug("battery powered"); _loop(); @@ -145,7 +173,8 @@ void setup() { //*************************************************************************// #ifdef BATTERY_POWERED -void criticalBatCheck() { +void criticalBatCheck() +{ float volt = battery_voltage(); if (volt <= BAT_EMERGENCY_DEEPSLEEP_VOLTAGE) { debug("Bat Voltage: " + String(volt) + " V"); @@ -157,21 +186,14 @@ void criticalBatCheck() { } #endif - -void loop() { +void loop() +{ #ifdef BATTERY_POWERED delay(50); return; #endif -#ifdef WEBUPDATER_FEATURE - if (UPDATE_WEBSERVER_INTVERVAL_S * 1000 / DELAY_LOOP_MS <= update_webserver_cnt) { - update_webserver_cnt = 0; - doWebUpdater(); - } -#endif - - + // call sub loop function _loop(); //Needed to give WIFI time to function properly @@ -182,17 +204,70 @@ void loop() { #ifdef WEBUPDATER_FEATURE update_webserver_cnt++; #endif + +#ifdef HTTP_CALL_ON_WINDSPEED_EXCEED + update_windspeed_exceed_cnt++; +#endif } void _loop() { +#ifdef WEBUPDATER_FEATURE + if (UPDATE_WEBSERVER_INTVERVAL_S * 1000 / DELAY_LOOP_MS <= update_webserver_cnt) + { + update_webserver_cnt = 0; + doWebUpdater(); + } +#endif + +#ifdef HTTP_CALL_ON_WINDSPEED_EXCEED + if (HTTP_CALL_ON_WINDSPEED_INTERVAL_S * 1000 / DELAY_LOOP_MS <= update_windspeed_exceed_cnt) + { + debug("Reading wind sensor because of exceed call functionality"); + if (sensors[SENSOR_WINDSPEED]) + { + // read from windspeed sensorSTATUS_LED_PIN + digitalWrite(STATUS_LED_PIN, HIGH); + currentSensorData[SENSOR_WINDSPEED] = sensors[SENSOR_WINDSPEED](); + digitalWrite(STATUS_LED_PIN, LOW); + + if (currentSensorData[SENSOR_WINDSPEED] >= HTTP_CALL_ON_WINDSPEED_EXCEED_MPS) + { + digitalWrite(STATUS_LED_PIN, HIGH); + + // call the url HTTP_CALL_ON_WINDSPEED_URL + WiFiClient client; + HTTPClient http; + + http.begin(client, String(HTTP_CALL_ON_WINDSPEED_URL).c_str()); + // Send HTTP GET request + int httpResponseCode = http.GET(); + + if (httpResponseCode > 0) { + String response = http.getString(); +#ifdef DEBUG + Serial.println("http response code: " + String(httpResponseCode) + " = " + response); +#endif + // TODO handle response + } + + http.end(); + debug("Called windspeed exceed callout"); + digitalWrite(STATUS_LED_PIN, LOW); + } + } else { + currentSensorData[SENSOR_WINDSPEED] = nan("no value"); + } + update_windspeed_exceed_cnt = 0; + } +#endif + #ifndef BATTERY_POWERED if (UPDATE_SENSOR_INTERVAL_S * 1000 / DELAY_LOOP_MS > update_sensor_cnt) { return; } #endif - #ifdef defined(BATTERY_POWERED) && defined(SENSOR_WIND) if (energySavingMode() == 1) { // Disable expensive tasks @@ -203,7 +278,6 @@ void _loop() { #endif update_sensor_cnt = 0; - for (uint8_t i = 0; i < VALUES; i++) { if (sensors[i]) { currentSensorData[i] = sensors[i](); @@ -225,6 +299,7 @@ void _loop() { #ifdef WEBUPDATER_FEATURE setSensorData(currentSensorData); #endif + } void logToSerial(float sensorValues[]) { @@ -238,4 +313,4 @@ void logToSerial(float sensorValues[]) { Serial.println("Bat Voltage: " + String(sensorValues[SENSOR_BAT_VOLTAGE]) + " V"); Serial.println("Bat charge state: " + String(sensorValues[SENSOR_BATCHARGESTATE])); Serial.println("Energy saving: " + String(sensorValues[SENSOR_ESAVEMODE])); -} +} diff --git a/firmware/influxdb.ino b/firmware/influxdb.ino index 8d1ebde..8356d43 100644 --- a/firmware/influxdb.ino +++ b/firmware/influxdb.ino @@ -1,3 +1,8 @@ + +#include "config_user.h" + +#if INFLUXDB_VERSION == 1 + #include // https://github.com/hwwong/ESP8266Influxdb Influxdb _influxdb(INFLUXDB_HOST, INFLUXDB_PORT); @@ -74,3 +79,111 @@ void pushToInfluxDB(String device, float sensorValues[]) { _influxdb.write(msg); } while (_influxdb.response() != DB_SUCCESS and tries < 5); } + +#elif INFLUXDB_VERSION == 2 + +#include // from bib manager + +// Data point +Point sensor(DEVICE_NAME); + +// Init variables to influxdb config - doesn't talk to database +InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN); + +void influxdb_begin() { + + // Check server connection + if (client.validateConnection()) { + // success +#ifdef DEBUG + Serial.print("InfluxDB connect success\n"); +#endif + } else { + // fail +#ifdef DEBUG + Serial.print("InfluxDB connect failed\n"); +#endif + } + +} + +void pushToInfluxDB(String device, float sensorValues[]) { + + if (!(isnan(sensorValues[SENSOR_TEMPERATURE]))) + { + sensor.clearFields(); + sensor.addField("temperature", sensorValues[SENSOR_TEMPERATURE]); + _writePoint(); + } + if (!(isnan(sensorValues[SENSOR_HUMIDITY]))) + { + sensor.clearFields(); + sensor.addField("humidity", sensorValues[SENSOR_HUMIDITY]); + _writePoint(); + } + if (!(isnan(sensorValues[SENSOR_LIGHT]))) + { + sensor.clearFields(); + sensor.addField("light", sensorValues[SENSOR_LIGHT]); + _writePoint(); + } + if (!(isnan(sensorValues[SENSOR_WINDSPEED]))) + { + sensor.clearFields(); + sensor.addField("windspeed", sensorValues[SENSOR_WINDSPEED]); + _writePoint(); + } + if (!(isnan(sensorValues[SENSOR_PRESSURE]))) + { + sensor.clearFields(); + sensor.addField("pressure", sensorValues[SENSOR_PRESSURE]); + _writePoint(); + } + if (!(isnan(sensorValues[SENSOR_BAT_VOLTAGE]))) + { + sensor.clearFields(); + sensor.addField("batvoltage", sensorValues[SENSOR_BAT_VOLTAGE]); + _writePoint(); + } + if (!(isnan(sensorValues[SENSOR_ESAVEMODE]))) + { + sensor.clearFields(); + sensor.addField("esavemode", sensorValues[SENSOR_ESAVEMODE]); + _writePoint(); + } + if (!(isnan(sensorValues[SENSOR_BATCHARGESTATE]))) + { + sensor.clearFields(); + sensor.addField("batchargestate", sensorValues[SENSOR_BATCHARGESTATE]); + _writePoint(); + } + +} + +void _writePoint() { + + // wait unitl ready + do { +#ifdef DEBUG + Serial.print("InfluxDB: waiting for write ready\n"); +#endif + } while (client.canSendRequest() == false); + + // Write point + if (!client.writePoint(sensor)) { +#ifdef DEBUG + Serial.print("InfluxDB write failed: "); + Serial.println(client.getLastErrorMessage()); + Serial.print("\nErrorcode: "); + Serial.println(client.getLastStatusCode()); + Serial.print("\n"); +#endif + } else { +#ifdef DEBUG + Serial.print("InfluxDB write done\n"); +#endif + } + +} + +#endif // influxdb version 2 check diff --git a/firmware/sensor_apds9930.ino b/firmware/sensor_apds9930.ino old mode 100755 new mode 100644 index 9a81c36..0917dd5 --- a/firmware/sensor_apds9930.ino +++ b/firmware/sensor_apds9930.ino @@ -20,4 +20,4 @@ float apds9930_light() { } else { return 0; } -} +} diff --git a/firmware/sensor_battery.ino b/firmware/sensor_battery.ino old mode 100755 new mode 100644 index 4cba750..a2e7745 --- a/firmware/sensor_battery.ino +++ b/firmware/sensor_battery.ino @@ -48,4 +48,4 @@ int energySavingMode() { float isEnergySavingMode() { return _sensor_battery_saveMode; -} +} diff --git a/firmware/sensor_bme280.ino b/firmware/sensor_bme280.ino old mode 100755 new mode 100644 index 5510f79..ae22d3f --- a/firmware/sensor_bme280.ino +++ b/firmware/sensor_bme280.ino @@ -14,11 +14,11 @@ bool sensor_bme280_begin(uint8_t addr) { } float bme280_temperature() { - return _sensor_bme280.readTemperature(); + return _sensor_bme280.readTemperature() * TEMP_FACTOR; } float bme280_pressure() { return _sensor_bme280.readPressure() / 100.0F; } float bme280_humidity() { return _sensor_bme280.readHumidity() * HUMIDITY_FACTOR; -} +} diff --git a/firmware/sensor_wind.ino b/firmware/sensor_wind.ino index 746a5f5..f7cd6bd 100644 --- a/firmware/sensor_wind.ino +++ b/firmware/sensor_wind.ino @@ -1,23 +1,34 @@ + #include "config_user.h" +#include "config.h" -int anemometerRotations = 0; -unsigned long currentTime = 0; +unsigned int anemometerRotations = 0; -ICACHE_RAM_ATTR void _anemometerInterrupt() { +ICACHE_RAM_ATTR void _anemometerInterrupt() +{ anemometerRotations++; #ifdef DEBUG Serial.print("*"); #endif } -float wind_speed() { +float wind_speed() +{ anemometerRotations = 0; - currentTime = millis(); + int interruptNumber = digitalPinToInterrupt(ANEMOMETER_PIN); attachInterrupt(interruptNumber, _anemometerInterrupt, RISING); - delay(1000 * 5); + delay(1000 * WIND_SENSOR_MEAS_TIME_S); // time to measure detachInterrupt(interruptNumber); - return (float)anemometerRotations / 5.0 * 2.4; + // calculate the speed as km/h + float tmp_speed = (float)anemometerRotations * WINDSPEED_FACTOR; + +#ifdef DEBUG + Serial.print("Windspeed: " + String(tmp_speed)); +#endif + + return tmp_speed; + } diff --git a/firmware/webUpdater.ino b/firmware/webUpdater.ino index 82b264d..f8e3a7d 100644 --- a/firmware/webUpdater.ino +++ b/firmware/webUpdater.ino @@ -11,13 +11,26 @@ #include #include +#include // WiFiManager from bib manager -ESP8266WebServer httpServer(8080); +#include "config.h" +#include "config_user.h" + +ESP8266WebServer httpServer(WEB_UPDATER_HTTP_PORT); ESP8266HTTPUpdateServer httpUpdater; String _webUpdater_ip = "127.0.0.1"; String _webUpdater_dev = "unknown"; -float _webUpdater_sensValues[VALUES]; +float _webUpdater_sensValues[VALUES]; + +String hb_ws_msg_start = "{"; +String hb_ws_msg_temp = "\"temperature\": "; +String hb_ws_msg_humi = "\"humidity\": "; +String hb_ws_msg_light = "\"lightlevel\": "; +String hb_ws_msg_windspeed = "\"windspeed\": "; +String hb_ws_msg_pressure = "\"pressure\": "; +String hb_ws_msg_timestamp = "\"timestamp\": "; +String hb_ws_msg_end = "}"; void setupWebUpdater(String device, String ip) { @@ -27,7 +40,11 @@ void setupWebUpdater(String device, String ip) httpUpdater.setup(&httpServer); - httpServer.on("/", showHTMLMain); // oko specific site + httpServer.on("/", showHTMLMain); + httpServer.on("/resetWifiManager", resetWifiManager); +#ifdef HOMEBRIDGE_WEBSTAT + httpServer.on("/hbWebstat", hb_webstat_send); +#endif httpServer.begin(); @@ -40,13 +57,15 @@ void doWebUpdater(void) httpServer.handleClient(); } -void setSensorData(float sensorValues[]) { +void setSensorData(float sensorValues[]) +{ for (uint8_t i = 0; i < VALUES; i++) { _webUpdater_sensValues[i] = sensorValues[i]; } } -void showHTMLMain(void) { +void showHTMLMain(void) +{ String message = "OKO Weatherstation - " + String(_webUpdater_dev) + "" "" "" @@ -63,3 +82,55 @@ void showHTMLMain(void) { httpServer.send(200, "text/html", message); } + +void hb_webstat_send(void) +{ + unsigned int timestamp = 0; + for (int i = 0; i < VALUES; i++) + { + timestamp += int(_webUpdater_sensValues[i]) + millis(); + } + String msg = hb_ws_msg_start + + hb_ws_msg_temp + + String(_webUpdater_sensValues[SENSOR_TEMPERATURE], 2) + + ", " + + hb_ws_msg_humi + + String(_webUpdater_sensValues[SENSOR_HUMIDITY], 2) + + ", " + + hb_ws_msg_light + + String(_webUpdater_sensValues[SENSOR_LIGHT], 0) + // The light level for the homebridge-http-lux2 plugin is only able to parse integer values + ", " + + hb_ws_msg_windspeed + + String(_webUpdater_sensValues[SENSOR_WINDSPEED], 2) + + ", " + + hb_ws_msg_pressure + + String(_webUpdater_sensValues[SENSOR_PRESSURE], 2) + + ", " + + hb_ws_msg_timestamp + + String(timestamp) + + hb_ws_msg_end; + + httpServer.send(200, "text/html", msg); +} + +void resetWifiManager() +{ + + String message = "OKO Weatherstation - " + String(_webUpdater_dev) + "" +"" +"" +"Reset WifiManager config.
" +"Rebooting...
" +""; + + httpServer.send(200, "text/html", message); + + // Erase WiFi Credentials, enable, compile, flash, disable and reflash. + WiFiManager wifiManager; + wifiManager.resetSettings(); + + delay(5000); + + // manual reset after restart is required + ESP.restart(); +} diff --git a/influxdb-lib/examples/influxdb_write/influxdb_write.ino b/influxdb-lib/examples/influxdb_write/influxdb_write.ino old mode 100644 new mode 100755