Compare commits

..

No commits in common. "f392fce1cc3c9257d13b9d1d30abdb3f38c1433f" and "0cf171093be0e020777ff1b30b4809c3a952de4b" have entirely different histories.

11 changed files with 386 additions and 143 deletions

View file

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

View file

@ -0,0 +1,179 @@
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

@ -0,0 +1,146 @@
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 Executable file → Normal file
View file

View file

@ -18,7 +18,7 @@
#define WIFI_AUTOCONNECT_TIMEOUT_S 120 #define WIFI_AUTOCONNECT_TIMEOUT_S 120
#define WIFI_CONFIG_PORTAL_TIMEOUT_S 120 #define WIFI_CONFIG_PORTAL_TIMEOUT_S 120
#define UPDATE_SENSOR_INTERVAL_S 300 #define UPDATE_SENSOR_INTERVAL_S 10
#define UPDATE_WEBSERVER_INTVERVAL_S 1 #define UPDATE_WEBSERVER_INTVERVAL_S 1
#define DELAY_LOOP_MS 50 #define DELAY_LOOP_MS 50
#define POWERSAVING_SLEEP_S 600 #define POWERSAVING_SLEEP_S 600

30
firmware/firmware.ino Normal file → Executable file
View file

@ -1,4 +1,4 @@
// Standard ESP8266 libs from project folder // Standard ESP8266 libs
#include <ESP8266mDNS.h> #include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h> #include <ESP8266HTTPUpdateServer.h>
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
@ -6,7 +6,7 @@
#include <ESP8266WebServer.h> #include <ESP8266WebServer.h>
#include <WiFiClient.h> // WiFiClient #include <WiFiClient.h> // WiFiClient
#include <WiFiManager.h> // WiFiManager from bib manager #include <WiFiManager.h> // WiFiManager
// Project includes // Project includes
#include "config.h" #include "config.h"
@ -35,6 +35,11 @@ void debug(String x) {
void setup() { void setup() {
// Erase WiFi Credentials (maybe this will work ...)
//WiFi.disconnect(true);
//delay(2000);
//ESP.reset();
#if defined(DEBUG) || defined(SERIAL_FEATURE) #if defined(DEBUG) || defined(SERIAL_FEATURE)
Serial.begin(115200); Serial.begin(115200);
#endif #endif
@ -64,12 +69,11 @@ void setup() {
wifiManager.setConnectTimeout(WIFI_AUTOCONNECT_TIMEOUT_S); // 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 known wifi connection
wifiManager.setTimeout(WIFI_CONFIG_PORTAL_TIMEOUT_S); // the time in seconds to wait for the user to configure the device wifiManager.setTimeout(WIFI_CONFIG_PORTAL_TIMEOUT_S); // the time in seconds to wait for the user to configure the device
while (!wifiManager.autoConnect(wifiName.c_str(), "DEADBEEF")) if (!wifiManager.autoConnect(wifiName.c_str(), "DEADBEEF")) {
{ debug("WiFi connection failed, going into deep sleep ...");
debug("WiFi connection failed, try again in 5 seconds...");
// If autoconnect to WLAN failed and no client connected, go to deep sleep // If autoconnect to WLAN failed and no client connected, go to deep sleep
//ESP.deepSleep(POWERSAVING_SLEEP_S * 1000000, WAKE_RF_DEFAULT); ESP.deepSleep(POWERSAVING_SLEEP_S * 1000000, WAKE_RF_DEFAULT);
delay(5000); delay(100);
} }
debug("Connected!"); debug("Connected!");
@ -114,12 +118,6 @@ void setup() {
#ifndef BATTERY_POWERED #ifndef BATTERY_POWERED
setupWebUpdater(DEVICE_NAME, WiFi.localIP().toString()); setupWebUpdater(DEVICE_NAME, WiFi.localIP().toString());
#endif #endif
#endif
#ifdef HOMEBRIDGE_WEBSTAT
#ifndef BATTERY_POWERED
hb_webstat_server_setup();
#endif
#endif #endif
//It's magic! leave in //It's magic! leave in
@ -194,6 +192,7 @@ void _loop() {
} }
#endif #endif
#ifdef defined(BATTERY_POWERED) && defined(SENSOR_WIND) #ifdef defined(BATTERY_POWERED) && defined(SENSOR_WIND)
if (energySavingMode() == 1) { if (energySavingMode() == 1) {
// Disable expensive tasks // Disable expensive tasks
@ -226,11 +225,6 @@ void _loop() {
#ifdef WEBUPDATER_FEATURE #ifdef WEBUPDATER_FEATURE
setSensorData(currentSensorData); setSensorData(currentSensorData);
#endif #endif
#ifdef HOMEBRIDGE_WEBSTAT
hb_webstat_loop(currentSensorData);
#endif
} }
void logToSerial(float sensorValues[]) { void logToSerial(float sensorValues[]) {

View file

@ -1,30 +0,0 @@
// Port des Web Servers auf 80 setzen
#ifdef HOMEBRIDGE_WEBSTAT
WiFiServer hb_webstat_server(80);
const char *hb_ws_msg_start = "{\"temperature\": ";
const char *hb_ws_msg_mid = "\"humidity\": ";
const char *hb_ws_msg_end = "}";
void hb_webstat_setup()
{
hb_webstat_server.begin()
}
void hb_webstat_send(floar currentSensorDfloar currentSensorData[]ata[])
{
WiFiClient client = server.available();
if (client.available()) {
client.print(hb_ws_msg_start);
client.print(String(currentSensorData[0],2));
client.print(hb_ws_msg_mid);
client.print(hb_ws_msg_end);
}
}
#endif

109
firmware/influxdb.ino Executable file → Normal file
View file

@ -1,103 +1,76 @@
#include <InfluxDbClient.h> // from bib manager #include <ESP8266Influxdb.h> // https://github.com/hwwong/ESP8266Influxdb
// Data point Influxdb _influxdb(INFLUXDB_HOST, INFLUXDB_PORT);
Point sensor("weatherstation");
// Init variables to influxdb config - doesn't talk to database
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN);
void influxdb_begin() { void influxdb_begin() {
// Init variables to influxdb config - doesn't talk to database
// Check server connection _influxdb.opendb(INFLUXDB_DB, INFLUXDB_USER, INFLUXDB_PASS);
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[]) { void pushToInfluxDB(String device, float sensorValues[]) {
uint8_t tries = 0;
boolean addComma = false;
String msg = "weather,device=" + device + " ";
if (!(isnan(sensorValues[SENSOR_TEMPERATURE]))) if (!(isnan(sensorValues[SENSOR_TEMPERATURE])))
{ {
sensor.clearFields(); msg += "temperature=" + String(sensorValues[SENSOR_TEMPERATURE]);
sensor.addField("temperature", sensorValues[SENSOR_TEMPERATURE]); addComma = true;
_writePoint();
} }
if (!(isnan(sensorValues[SENSOR_HUMIDITY]))) if (!(isnan(sensorValues[SENSOR_HUMIDITY])))
{ {
sensor.clearFields(); if (true == addComma)
sensor.addField("humidity", sensorValues[SENSOR_HUMIDITY]); msg += ",";
_writePoint(); msg += "humidity=" + String(sensorValues[SENSOR_HUMIDITY]);
addComma = true;
} }
if (!(isnan(sensorValues[SENSOR_LIGHT]))) if (!(isnan(sensorValues[SENSOR_LIGHT])))
{ {
sensor.clearFields(); if (true == addComma)
sensor.addField("light", sensorValues[SENSOR_LIGHT]); msg += ",";
_writePoint(); msg += "light=" + String(sensorValues[SENSOR_LIGHT]);
addComma = true;
} }
if (!(isnan(sensorValues[SENSOR_WINDSPEED]))) if (!(isnan(sensorValues[SENSOR_WINDSPEED])))
{ {
sensor.clearFields(); if (true == addComma)
sensor.addField("windspeed", sensorValues[SENSOR_WINDSPEED]); msg += ",";
_writePoint(); msg += "windspeed=" + String(sensorValues[SENSOR_WINDSPEED]);
addComma = true;
} }
if (!(isnan(sensorValues[SENSOR_PRESSURE]))) if (!(isnan(sensorValues[SENSOR_PRESSURE])))
{ {
sensor.clearFields(); if (true == addComma)
sensor.addField("pressure", sensorValues[SENSOR_PRESSURE]); msg += ",";
_writePoint(); msg += "pressure=" + String(sensorValues[SENSOR_PRESSURE]);
addComma = true;
} }
if (!(isnan(sensorValues[SENSOR_BAT_VOLTAGE]))) if (!(isnan(sensorValues[SENSOR_BAT_VOLTAGE])))
{ {
sensor.clearFields(); if (true == addComma)
sensor.addField("batvoltage", sensorValues[SENSOR_BAT_VOLTAGE]); msg += ",";
_writePoint(); msg += "batvoltage=" + String(sensorValues[SENSOR_BAT_VOLTAGE]);
addComma = true;
} }
if (!(isnan(sensorValues[SENSOR_ESAVEMODE]))) if (!(isnan(sensorValues[SENSOR_ESAVEMODE])))
{ {
sensor.clearFields(); if (true == addComma)
sensor.addField("esavemode", sensorValues[SENSOR_ESAVEMODE]); msg += ",";
_writePoint(); msg += "esavemode=" + String(sensorValues[SENSOR_ESAVEMODE]);
addComma = true;
} }
if (!(isnan(sensorValues[SENSOR_BATCHARGESTATE]))) if (!(isnan(sensorValues[SENSOR_BATCHARGESTATE])))
{ {
sensor.clearFields(); if (true == addComma)
sensor.addField("batchargestate", sensorValues[SENSOR_BATCHARGESTATE]); msg += ",";
_writePoint(); msg += "batchargestate=" + String(sensorValues[SENSOR_BATCHARGESTATE]);
addComma = true;
} }
} debug(msg);
void _writePoint() {
// wait unitl ready
do { do {
#ifdef DEBUG tries++;
Serial.print("InfluxDB: waiting for write ready\n"); _influxdb.write(msg);
#endif } while (_influxdb.response() != DB_SUCCESS and tries < 5);
} 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
}
} }

0
firmware/sensor_apds9960.ino Executable file → Normal file
View file

0
firmware/sensor_wind.ino Executable file → Normal file
View file

View file

@ -27,8 +27,7 @@ void setupWebUpdater(String device, String ip)
httpUpdater.setup(&httpServer); httpUpdater.setup(&httpServer);
httpServer.on("/", showHTMLMain); httpServer.on("/", showHTMLMain); // oko specific site
httpServer.on("/resetWifiManager", resetWifiManager);
httpServer.begin(); httpServer.begin();
@ -64,23 +63,3 @@ void showHTMLMain(void) {
httpServer.send(200, "text/html", message); httpServer.send(200, "text/html", message);
} }
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.resetSettings()
delay(5000);
ESP.restart();
}