feature/InfluxDB-Connection-Update #1
16 changed files with 406 additions and 407 deletions
5
.gitignore
vendored
Normal file → Executable file
5
.gitignore
vendored
Normal file → Executable file
|
@ -1 +1,6 @@
|
|||
firmware/config_user.h
|
||||
firmware/.DS_Store
|
||||
.DS_Store
|
||||
schematics/#auto_saved_files#
|
||||
schematics/_autosave-oko-weatherstation.sch
|
||||
firmware.ino.bin
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
sudo docker-compose exec esphome esphome run /config/weatherstation.yml
|
|
@ -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:
|
|
@ -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:
|
0
firmware/README.md
Normal file → Executable file
0
firmware/README.md
Normal file → Executable file
32
firmware/config.h
Executable file → Normal file
32
firmware/config.h
Executable file → Normal file
|
@ -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
|
||||
|
|
51
firmware/config_user.h.example
Normal file → Executable file
51
firmware/config_user.h.example
Normal file → Executable file
|
@ -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) <add link here>
|
||||
//#define WINDSPEED_FACTOR 2.4
|
||||
|
||||
#endif
|
||||
|
||||
|
|
20
firmware/constants.h
Normal file
20
firmware/constants.h
Normal file
|
@ -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
|
151
firmware/firmware.ino
Executable file → Normal file
151
firmware/firmware.ino
Executable file → Normal file
|
@ -1,55 +1,63 @@
|
|||
// Standard ESP8266 libs
|
||||
// Standard ESP8266 libs from project folder
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
#include <WiFiClient.h> // WiFiClient
|
||||
#include <WiFiManager.h> // WiFiManager
|
||||
#include <WiFiClient.h> // WiFiClient
|
||||
#include <WiFiManager.h> // 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]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
|
||||
#include "config_user.h"
|
||||
|
||||
#if INFLUXDB_VERSION == 1
|
||||
|
||||
#include <ESP8266Influxdb.h> // 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 <InfluxDbClient.h> // 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
|
||||
|
|
2
firmware/sensor_apds9930.ino
Executable file → Normal file
2
firmware/sensor_apds9930.ino
Executable file → Normal file
|
@ -20,4 +20,4 @@ float apds9930_light() {
|
|||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2
firmware/sensor_battery.ino
Executable file → Normal file
2
firmware/sensor_battery.ino
Executable file → Normal file
|
@ -48,4 +48,4 @@ int energySavingMode() {
|
|||
|
||||
float isEnergySavingMode() {
|
||||
return _sensor_battery_saveMode;
|
||||
}
|
||||
}
|
||||
|
|
4
firmware/sensor_bme280.ino
Executable file → Normal file
4
firmware/sensor_bme280.ino
Executable file → Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -11,13 +11,26 @@
|
|||
#include <ESP8266HTTPUpdateServer.h>
|
||||
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiManager.h> // 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);
|
||||
klaute marked this conversation as resolved
|
||||
#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 = "<html><head><title>OKO Weatherstation - " + String(_webUpdater_dev) + "</title>"
|
||||
"<meta http-equiv=\"refresh\" content=\"20\">"
|
||||
"</head><body>"
|
||||
|
@ -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 = "<html><head><title>OKO Weatherstation - " + String(_webUpdater_dev) + "</title>"
|
||||
"<meta http-equiv=\"refresh\" content=\"20\">"
|
||||
"</head><body>"
|
||||
"Reset WifiManager config.<br>"
|
||||
"Rebooting...<br>"
|
||||
"</body></html>";
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
0
influxdb-lib/examples/influxdb_write/influxdb_write.ino
Normal file → Executable file
0
influxdb-lib/examples/influxdb_write/influxdb_write.ino
Normal file → Executable file
Loading…
Reference in a new issue
Ein Prometheus Endpunkt wäre noch der Oberhammer :)
Ich denke das bau ich dann ein, wenn der PR gemerged ist.
Das wäre super wenn wir noch mehrere andere Plattformen unterstützen könnten!