Merge pull request 'feature/InfluxDB-Connection-Update' (#1) from feature/InfluxDB-Connection-Update into master

Reviewed-on: #1
This commit is contained in:
klaute 2022-05-23 17:36:58 +02:00
commit 2ae1d7a365
16 changed files with 406 additions and 407 deletions

5
.gitignore vendored Normal file → Executable file
View 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

View file

@ -1,2 +0,0 @@
sudo docker-compose exec esphome esphome run /config/weatherstation.yml

View file

@ -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:

View file

@ -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
View file

32
firmware/config.h Executable file → Normal file
View 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
View 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
View 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
View 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]));
}
}

View file

@ -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
View file

@ -20,4 +20,4 @@ float apds9930_light() {
} else {
return 0;
}
}
}

2
firmware/sensor_battery.ino Executable file → Normal file
View file

@ -48,4 +48,4 @@ int energySavingMode() {
float isEnergySavingMode() {
return _sensor_battery_saveMode;
}
}

4
firmware/sensor_bme280.ino Executable file → Normal file
View 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;
}
}

View file

@ -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;
}

View file

@ -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);
#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();
}

View file