Compare commits
47 Commits
bme688
...
standalone
Author | SHA1 | Date | |
---|---|---|---|
|
832e5def65 | ||
|
2efa4a576c | ||
|
ca8da3c608 | ||
|
2c884710c1 | ||
|
a3be4f19a1 | ||
|
ae6c53d39b | ||
|
3224224251 | ||
|
fc5444f8b3 | ||
|
5955ca1a5c | ||
|
2b930a6902 | ||
|
128d5a0b3b | ||
|
c26ee6342c | ||
|
32e868b176 | ||
|
797a6dbe05 | ||
|
fc185b4bca | ||
|
d6e34a8e75 | ||
|
db10de101c | ||
|
24e6bfd6f9 | ||
|
dadee863b8 | ||
|
5ece74b0e6 | ||
|
6af6a6ac76 | ||
|
e3fe70dff2 | ||
|
fd8277b702 | ||
|
81e4f9901c | ||
|
5e27d3ebf4 | ||
|
b91317fae2 | ||
|
3e89b3e040 | ||
|
e52300b792 | ||
|
f3d439cbc3 | ||
|
95b6fcef06 | ||
|
1c35094cfa | ||
|
b2db51d9a9 | ||
|
1cf8c781eb | ||
|
c39ebc8e54 | ||
|
1e15d85d6f | ||
|
afff1275da | ||
|
d910d0b945 | ||
|
41ebed2b27 | ||
|
81adc9bd61 | ||
|
ca811a9abe | ||
|
73f637d6ec | ||
|
29beff5e82 | ||
|
49312a203d | ||
|
7567a4ef07 | ||
|
595fbbc3da | ||
|
8e24c171ec | ||
|
9807aa9818 |
20
Readme.md
20
Readme.md
@@ -3,7 +3,7 @@ located in IKEAs Vindriktning
|
|||||||
|
|
||||||
after this upgrade it will measure:
|
after this upgrade it will measure:
|
||||||
* air quality
|
* air quality
|
||||||
* temperatur
|
* temperature
|
||||||
* pressure
|
* pressure
|
||||||
* altitude
|
* altitude
|
||||||
|
|
||||||
@@ -39,10 +39,10 @@ VCC | GND
|
|||||||
```
|
```
|
||||||
|
|
||||||
The following pins are used:
|
The following pins are used:
|
||||||
* GPIO4 PM1006 particle sensor
|
* GPIO4 PM1006 particle sensor PIN REST on Vindriktning board
|
||||||
* GPIO2 WS2812 stripe out of three LEDs, replacing the orignal LEDs at front
|
* GPIO2 WS2812 stripe out of three LEDs, replacing the original LEDs at front
|
||||||
* GPIO15 Red LED (optional)
|
* GPIO15 Red LED (optional)
|
||||||
* GPIO12 Green LED (optional)
|
* GPIO12 Green LED (optional) Used as 3.3V Supply for the I2C sensor
|
||||||
* GPIO13 Blue LED (optional)
|
* GPIO13 Blue LED (optional)
|
||||||
* GPIO13 VCC of I2C (3.3 V)
|
* GPIO13 VCC of I2C (3.3 V)
|
||||||
* GPIO14 I2C clock
|
* GPIO14 I2C clock
|
||||||
@@ -54,5 +54,15 @@ The following pins are used:
|
|||||||
* BMP280 sensor
|
* BMP280 sensor
|
||||||
* some wire
|
* some wire
|
||||||
|
|
||||||
|
# Webserver
|
||||||
|
|
||||||
|
This version has a webserver activated, if MQTT server is set to **localhost**.
|
||||||
|
|
||||||
|
Every 20 seconds a measurement is performed.
|
||||||
|
This is shown in a diagram via chart.js
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
* [https://github.com/amkuipers/witty Witty pinout]
|
For the Witty board
|
||||||
|
* [https://github.com/amkuipers/witty Witty pinout]
|
||||||
|
* [https://arduino.ua/products_pictures/large_AOC361-5.jpg Schematics]
|
||||||
|
* [https://www.chartjs.org/docs/latest/getting-started/integration.html]
|
||||||
|
37
data/chart.htm
Normal file
37
data/chart.htm
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||||
|
<title>IKEA Home Sensor Diagram</title>
|
||||||
|
<script src="/chart.min.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function onBodyLoad(){
|
||||||
|
|
||||||
|
const xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.responseType = 'json';
|
||||||
|
xhttp.onload = function() {
|
||||||
|
var jsonResponse = this.response;
|
||||||
|
console.log("JSON received");
|
||||||
|
const ctx = document.getElementById('myChart');
|
||||||
|
const myChart = new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: jsonResponse,
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("Diagram generated");
|
||||||
|
}
|
||||||
|
xhttp.open("GET", "/diagram", true);
|
||||||
|
xhttp.send();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body id="body" onload="onBodyLoad()">
|
||||||
|
<canvas id="myChart" width="100%" height="100"></canvas>
|
||||||
|
</body>
|
||||||
|
</html>
|
13
data/chart.min.js
vendored
Normal file
13
data/chart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
96
data/standalone.htm
Normal file
96
data/standalone.htm
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||||
|
<title>IKEA Home Sensor</title>
|
||||||
|
<style type="text/css">
|
||||||
|
tr.heading td {
|
||||||
|
background-color: black; color: white;
|
||||||
|
}
|
||||||
|
tr.d0 td {
|
||||||
|
background-color: #ffffff; color: black;
|
||||||
|
}
|
||||||
|
tr.d1 td {
|
||||||
|
background-color: #b8b8b8; color: black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function mySensorTimer(){
|
||||||
|
const xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.responseType = 'json';
|
||||||
|
xhttp.onload = function() {
|
||||||
|
var jsonResponse = this.response;
|
||||||
|
document.getElementById("temp").innerHTML = jsonResponse.temp
|
||||||
|
document.getElementById("altitude").innerHTML = jsonResponse.altitude;
|
||||||
|
document.getElementById("pressure").innerHTML = jsonResponse.pressure;
|
||||||
|
document.getElementById("particle").innerHTML = jsonResponse.particle;
|
||||||
|
if (jsonResponse.gas) {
|
||||||
|
document.getElementById("gas").innerHTML = jsonResponse.gas;
|
||||||
|
} else {
|
||||||
|
document.getElementById("rowGas").hidden = true;
|
||||||
|
}
|
||||||
|
if (jsonResponse.humidity) {
|
||||||
|
document.getElementById("humidity").innerHTML = jsonResponse.humidity;
|
||||||
|
} else {
|
||||||
|
document.getElementById("rowHumidity").hidden = true;
|
||||||
|
}
|
||||||
|
console.log(this.responseText);
|
||||||
|
}
|
||||||
|
xhttp.open("GET", "/sensors", true);
|
||||||
|
xhttp.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onBodyLoad(){
|
||||||
|
setInterval(mySensorTimer, 5000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body id="body" onload="onBodyLoad()">
|
||||||
|
<h1>Room Sensor</h1>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr class="heading">
|
||||||
|
<td>Sensor</td>
|
||||||
|
<td>Value</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="d0">
|
||||||
|
<td>Temperatur</td>
|
||||||
|
<td id="temp">temp</td>
|
||||||
|
<td>°C</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="rowHumidity" class="d1">
|
||||||
|
<td>Humidity</td>
|
||||||
|
<td id="humidity">humidity</td>
|
||||||
|
<td>%</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="rowGas" class="d0">
|
||||||
|
<td>Gas</td>
|
||||||
|
<td id="gas">gas</td>
|
||||||
|
<td> KOhms</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="d1">
|
||||||
|
<td>Altitude</td>
|
||||||
|
<td id="altitude">altitude</td>
|
||||||
|
<td>m</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="d0">
|
||||||
|
<td>Pressure</td>
|
||||||
|
<td id="pressure">pressure</td>
|
||||||
|
<td>hPa</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="d1">
|
||||||
|
<td>Particle</td>
|
||||||
|
<td id="particle">particle</td>
|
||||||
|
<td>micro gram per quibik</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h1>Diagram</h1>
|
||||||
|
<p>
|
||||||
|
Can be found on the <a href="chart.htm">next page</a>.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -27,7 +27,7 @@ usage: ota_updater.py [-h] -l BROKER_HOST -p BROKER_PORT [-u BROKER_USERNAME]
|
|||||||
[-d BROKER_PASSWORD] [-t BASE_TOPIC] -i DEVICE_ID
|
[-d BROKER_PASSWORD] [-t BASE_TOPIC] -i DEVICE_ID
|
||||||
firmware
|
firmware
|
||||||
|
|
||||||
ota firmware update scirpt for ESP8226 implemenation of the Homie mqtt IoT
|
ota firmware update script for ESP8226 implementation of the Homie mqtt IoT
|
||||||
convention.
|
convention.
|
||||||
|
|
||||||
positional arguments:
|
positional arguments:
|
||||||
|
@@ -7,5 +7,6 @@ if [ $? -ne 0 ]; then
|
|||||||
fi
|
fi
|
||||||
codespell -w ../src/*
|
codespell -w ../src/*
|
||||||
codespell -w ../include/*
|
codespell -w ../include/*
|
||||||
codespell ../Readme.md
|
codespell -w ../*.md
|
||||||
|
codespell -w *.md
|
||||||
exit 0
|
exit 0
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
#ifndef HOMIE_SETTINGS
|
#ifndef HOMIE_SETTINGS
|
||||||
#define HOMIE_SETTINGS
|
#define HOMIE_SETTINGS
|
||||||
|
|
||||||
#define HOMIE_FIRMWARE_NAME "Vindriktning"
|
#define HOMIE_FIRMWARE_NAME "RoomSensor"
|
||||||
#define HOMIE_FIRMWARE_VERSION "1.2.1"
|
#define HOMIE_FIRMWARE_VERSION "2.2.0"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -12,11 +12,17 @@
|
|||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
board = d1_mini
|
board = d1_mini
|
||||||
framework = arduino
|
framework = arduino
|
||||||
build_flags = -D PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
build_flags = -D PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -DBMP280
|
||||||
|
; build_flag needs define the Bosch sensor...
|
||||||
|
; -D BMP280
|
||||||
|
;or
|
||||||
|
; -D BME680
|
||||||
|
|
||||||
; the latest development branch (convention V3.0.x)
|
; the latest development branch (convention V3.0.x)
|
||||||
lib_deps = https://github.com/homieiot/homie-esp8266.git#develop
|
lib_deps = https://github.com/homieiot/homie-esp8266.git#develop
|
||||||
EspSoftwareSerial
|
EspSoftwareSerial
|
||||||
NeoPixel
|
NeoPixel
|
||||||
|
adafruit/Adafruit BMP280 Library @ ^2.4.2
|
||||||
adafruit/Adafruit BME680 Library @ ^2.0.1
|
adafruit/Adafruit BME680 Library @ ^2.0.1
|
||||||
|
|
||||||
upload_port = /dev/ttyUSB1
|
upload_port = /dev/ttyUSB1
|
484
src/main.cpp
484
src/main.cpp
@@ -18,30 +18,39 @@
|
|||||||
#include <Adafruit_NeoPixel.h>
|
#include <Adafruit_NeoPixel.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <Adafruit_Sensor.h>
|
#include <Adafruit_Sensor.h>
|
||||||
|
#ifdef BME680
|
||||||
#include "Adafruit_BME680.h"
|
#include "Adafruit_BME680.h"
|
||||||
|
#else
|
||||||
|
#ifdef BMP280
|
||||||
|
#include "Adafruit_BMP280.h"
|
||||||
|
#else
|
||||||
|
#error "Decition, which BMx??? is used missing"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#define GPIO_WS2812 D4 /**< GPIO2 */
|
#define GPIO_WS2812 D4 /**< GPIO2 */
|
||||||
#define SENSOR_PM1006_RX D2 /**< GPIO4 */
|
#define SENSOR_PM1006_RX D2 /**< GPIO4 */
|
||||||
#define SENSOR_PM1006_TX -1 /**< Unused */
|
#define SENSOR_PM1006_TX -1 /**< Unused */
|
||||||
#define WITTY_RGB_R D8 /**< GPIO15 */
|
#define WITTY_RGB_R D8 /**< GPIO15 */
|
||||||
#define WITTY_RGB_G D6 /**< GPIO12 */
|
#define WITTY_RGB_G D6 /**< GPIO12 Used as 3.3V Power supply for the I2C Sensor */
|
||||||
#define WITTY_RGB_B D7 /**< GPIO13 */
|
#define WITTY_RGB_B D7 /**< GPIO13 */
|
||||||
#define PM1006_BIT_RATE 9600
|
#define PM1006_BIT_RATE 9600
|
||||||
#define PM1006_MQTT_UPDATE 5000 /**< Check the sensor every 10 seconds; New measurement is done every 20seconds by the sensor */
|
#define PM1006_MQTT_UPDATE 30000 /**< Check the sensor every 30 seconds; New measurement is done every 20seconds by the PM1006 sensor */
|
||||||
#define PIXEL_COUNT 3
|
#define PIXEL_COUNT 3
|
||||||
#define GPIO_BUTTON SENSOR_PM1006_RX /**< Button and software serial share one pin on Witty board */
|
#define GPIO_BUTTON SENSOR_PM1006_RX /**< Button and software serial share one pin on Witty board */
|
||||||
#define SENSOR_I2C_SCK D1 /**< GPIO14 - I2C clock pin */
|
#define SENSOR_I2C_SCK D5 /**< GPIO14 - I2C clock pin */
|
||||||
#define SENSOR_I2C_SDI D5 /**< GPIO5 - I2C data pin */
|
#define SENSOR_I2C_SDI D1 /**< GPIO5 - I2C data pin */
|
||||||
|
|
||||||
#define PM1006_BIT_RATE 9600
|
|
||||||
#define PM1006_MQTT_UPDATE 5000 /**< Check the sensor every 10 seconds; New measurement is done every 20seconds by the sensor */
|
|
||||||
|
|
||||||
#define SEALEVELPRESSURE_HPA (1013.25)
|
#define SEALEVELPRESSURE_HPA (1013.25)
|
||||||
|
|
||||||
|
#define BUTTON_MAX_CYCLE 10000U /**< Action: Reset configuration */
|
||||||
|
#define BUTTON_MIN_ACTION_CYCLE 55U /**< Minimum cycle to react on the button (e.g. 5 second) */
|
||||||
|
#define BUTTON_CHECK_INTERVALL 100U /**< Check every 100 ms the button state */
|
||||||
|
|
||||||
#define LOG_TOPIC "log\0"
|
#define LOG_TOPIC "log\0"
|
||||||
#define MQTT_LEVEL_ERROR 1
|
#define MQTT_LEVEL_ERROR 1
|
||||||
#define MQTT_LEVEL_WARNING 10
|
#define MQTT_LEVEL_WARNING 10
|
||||||
@@ -62,6 +71,8 @@
|
|||||||
strcat(topic, "/"); \
|
strcat(topic, "/"); \
|
||||||
strcat(topic, test);
|
strcat(topic, test);
|
||||||
|
|
||||||
|
#define PERCENT2FACTOR(b, a) ((b * a.get()) / 100)
|
||||||
|
|
||||||
#define NUMBER_TYPE "Number"
|
#define NUMBER_TYPE "Number"
|
||||||
#define NODE_PARTICLE "particle"
|
#define NODE_PARTICLE "particle"
|
||||||
#define NODE_TEMPERATUR "temp"
|
#define NODE_TEMPERATUR "temp"
|
||||||
@@ -70,10 +81,29 @@
|
|||||||
#define NODE_GAS "gas"
|
#define NODE_GAS "gas"
|
||||||
#define NODE_HUMIDITY "humidity"
|
#define NODE_HUMIDITY "humidity"
|
||||||
#define NODE_AMBIENT "ambient"
|
#define NODE_AMBIENT "ambient"
|
||||||
|
|
||||||
|
#define NODE_BUTTON "button"
|
||||||
|
|
||||||
|
#define PORTNUMBER_HTTP 80 /**< IANA TCP/IP port number, used for HTTP / web traffic */
|
||||||
|
|
||||||
|
#define SERIAL_RCEVBUF_MAX 80 /**< Maximum 80 characters can be received from the PM1006 sensor */
|
||||||
|
#define MEASURE_POINT_MAX 1024 /**< Amount of measure point, that can be stored */
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* TYPE DEFS
|
* TYPE DEFS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
typedef struct s_point {
|
||||||
|
long timestamp;
|
||||||
|
float temp;
|
||||||
|
#ifdef BME680
|
||||||
|
uint32_t gas;
|
||||||
|
float humidity;
|
||||||
|
#endif
|
||||||
|
float pressure;
|
||||||
|
int pm25;
|
||||||
|
} sensor_point;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* FUNCTION PROTOTYPES
|
* FUNCTION PROTOTYPES
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -87,34 +117,61 @@ void log(int level, String message, int code);
|
|||||||
bool mConfigured = false;
|
bool mConfigured = false;
|
||||||
bool mConnected = false;
|
bool mConnected = false;
|
||||||
bool mFailedI2Cinitialization = false;
|
bool mFailedI2Cinitialization = false;
|
||||||
|
AsyncWebServer* mHttp = NULL;
|
||||||
|
long mLastButtonAction = 0;
|
||||||
|
|
||||||
/******************************* Sensor data **************************/
|
/******************************* Sensor data **************************/
|
||||||
HomieNode particle(NODE_PARTICLE, "particle", "number"); /**< Measuret in micro gram per quibik meter air volume */
|
HomieNode particle(NODE_PARTICLE, "particle", "number"); /**< Measuret in micro gram per quibik meter air volume */
|
||||||
HomieNode temperatureNode(NODE_TEMPERATUR, "Room Temperature", "number");
|
HomieNode temperaturNode(NODE_TEMPERATUR, "Room Temperature", "number");
|
||||||
HomieNode pressureNode(NODE_PRESSURE, "Pressure", "number");
|
HomieNode pressureNode(NODE_PRESSURE, "Pressure", "number");
|
||||||
HomieNode altitudeNode(NODE_ALTITUDE, "Altitude", "number");
|
HomieNode altitudeNode(NODE_ALTITUDE, "Altitude", "number");
|
||||||
|
#ifdef BME680
|
||||||
HomieNode gasNode(NODE_GAS, "Gas", "number");
|
HomieNode gasNode(NODE_GAS, "Gas", "number");
|
||||||
HomieNode humidityNode(NODE_HUMIDITY, "Humidity", "number");
|
HomieNode humidityNode(NODE_HUMIDITY, "Humidity", "number");
|
||||||
|
#endif
|
||||||
|
HomieNode buttonNode(NODE_BUTTON, "Button", "number");
|
||||||
|
|
||||||
/****************************** Output control ***********************/
|
/****************************** Output control ***********************/
|
||||||
HomieNode ledStripNode /* to rule them all */("led", "RGB led", "color");
|
HomieNode ledStripNode /* to rule them all */("led", "RGB led", "color");
|
||||||
|
|
||||||
/************************** Settings ******************************/
|
/************************** Settings ******************************/
|
||||||
HomieSetting<bool> i2cEnable("i2c", "BME280 sensor present");
|
HomieSetting<bool> i2cEnable("i2c",
|
||||||
HomieSetting<bool> rgbTemp("rgbTemp", "Show temperatur via red (>20 °C) and blue (< 20°C)");
|
#ifdef BME680
|
||||||
|
"BME680 sensor present"
|
||||||
|
#else
|
||||||
|
#ifdef BMP280
|
||||||
|
"BMP280 sensor present"
|
||||||
|
#else
|
||||||
|
"No I2C sensor specified in the project"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
);
|
||||||
|
HomieSetting<bool> rgbTemp("rgbTemp", "Show temperature via red (>20 °C) and blue (< 20°C)");
|
||||||
|
HomieSetting<long> rgbDim("rgbDim", "Factor (1 to 200%) of the status LEDs");
|
||||||
|
|
||||||
static SoftwareSerial pmSerial(SENSOR_PM1006_RX, SENSOR_PM1006_TX);
|
static SoftwareSerial pmSerial(SENSOR_PM1006_RX, SENSOR_PM1006_TX);
|
||||||
Adafruit_BME680 bme(&Wire); // connected via I2C
|
#ifdef BME680
|
||||||
|
Adafruit_BME680 bmx(&Wire); // connected via I2C
|
||||||
|
#else
|
||||||
|
#ifdef BMP280
|
||||||
|
Adafruit_BMP280 bmx; // connected via I2C
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
Adafruit_NeoPixel strip(PIXEL_COUNT, GPIO_WS2812, NEO_GRB + NEO_KHZ800);
|
Adafruit_NeoPixel strip(PIXEL_COUNT, GPIO_WS2812, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
// Variablen
|
// Variablen
|
||||||
uint8_t serialRxBuf[80];
|
uint8_t serialRxBuf[SERIAL_RCEVBUF_MAX];
|
||||||
uint8_t rxBufIdx = 0;
|
uint8_t rxBufIdx = 0;
|
||||||
int spm25 = 0;
|
int mParticle_pM25 = 0;
|
||||||
int last = 0;
|
int last = 0;
|
||||||
unsigned int mButtonPressed = 0;
|
unsigned int mButtonPressed = 0;
|
||||||
bool mSomethingReceived = false;
|
bool mSomethingReceived = false;
|
||||||
|
bool mConnectedNonMQTT = false;
|
||||||
|
|
||||||
|
sensor_point* mMeasureSeries;
|
||||||
|
uint32_t mMeasureIndex = 0;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* LOCAL FUNCTIONS
|
* LOCAL FUNCTIONS
|
||||||
@@ -170,18 +227,34 @@ void onHomieEvent(const HomieEvent &event)
|
|||||||
{
|
{
|
||||||
switch (event.type)
|
switch (event.type)
|
||||||
{
|
{
|
||||||
case HomieEventType::MQTT_READY:
|
case HomieEventType::WIFI_CONNECTED:
|
||||||
mConnected=true;
|
|
||||||
digitalWrite(WITTY_RGB_R, LOW);
|
digitalWrite(WITTY_RGB_R, LOW);
|
||||||
if (!i2cEnable.get()) { /** keep green LED activated to power I2C sensor */
|
if (!i2cEnable.get()) { /** keep green LED activated to power I2C sensor */
|
||||||
digitalWrite(WITTY_RGB_G, LOW);
|
digitalWrite(WITTY_RGB_G, LOW);
|
||||||
|
log(MQTT_LEVEL_INFO, F("I2C powersupply deactivated"), MQTT_LOG_I2CINIT);
|
||||||
}
|
}
|
||||||
digitalWrite(WITTY_RGB_B, LOW);
|
digitalWrite(WITTY_RGB_B, LOW);
|
||||||
strip.fill(strip.Color(0,0,128));
|
strip.fill(strip.Color(0,0,128));
|
||||||
strip.show();
|
strip.show();
|
||||||
|
if (mHttp != NULL) {
|
||||||
|
strip.fill(strip.Color(0,64,0));
|
||||||
|
mConnectedNonMQTT = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HomieEventType::MQTT_READY:
|
||||||
|
mConnected=true;
|
||||||
if (mFailedI2Cinitialization) {
|
if (mFailedI2Cinitialization) {
|
||||||
log(MQTT_LEVEL_DEBUG, F("Could not find a valid BME680 sensor, check wiring or "
|
log(MQTT_LEVEL_DEBUG,
|
||||||
"try a different address!"), MQTT_LOG_I2CINIT);
|
#ifdef BME680
|
||||||
|
"Could not find a valid BME680 sensor, check wiring or try a different address!"
|
||||||
|
#else
|
||||||
|
#ifdef BMP280
|
||||||
|
"Could not find a valid BMP280 sensor, check wiring or try a different address!"
|
||||||
|
#else
|
||||||
|
"no I2C sensor defined"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
, MQTT_LOG_I2CINIT);
|
||||||
} else {
|
} else {
|
||||||
log(MQTT_LEVEL_INFO, F("BME680 sensor found"), MQTT_LOG_I2CINIT);
|
log(MQTT_LEVEL_INFO, F("BME680 sensor found"), MQTT_LOG_I2CINIT);
|
||||||
}
|
}
|
||||||
@@ -198,30 +271,175 @@ void onHomieEvent(const HomieEvent &event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bmpPublishValues() {
|
void updateLEDs() {
|
||||||
|
#ifdef BME680
|
||||||
// Tell BME680 to begin measurement.
|
// Tell BME680 to begin measurement.
|
||||||
unsigned long endTime = bme.beginReading();
|
unsigned long endTime = bmx.beginReading();
|
||||||
if (endTime == 0) {
|
if (endTime == 0) {
|
||||||
log(MQTT_LEVEL_ERROR, F("BME680 not accessable"), MQTT_LOG_I2READ);
|
log(MQTT_LEVEL_ERROR, "BME680 not accessible", MQTT_LOG_I2READ);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
temperatureNode.setProperty(NODE_TEMPERATUR).send(String(bme.readTemperature()));
|
#endif
|
||||||
pressureNode.setProperty(NODE_PRESSURE).send(String(bme.readPressure() / 100.0F));
|
|
||||||
altitudeNode.setProperty(NODE_ALTITUDE).send(String(bme.readAltitude(SEALEVELPRESSURE_HPA)));
|
|
||||||
gasNode.setProperty(NODE_GAS).send(String((bme.gas_resistance / 1000.0)));
|
|
||||||
|
|
||||||
humidityNode.setProperty(NODE_HUMIDITY).send(String(bme.humidity));
|
|
||||||
|
|
||||||
if ( (rgbTemp.get()) && (!mSomethingReceived) ) {
|
if ( (rgbTemp.get()) && (!mSomethingReceived) ) {
|
||||||
if (bme.readTemperature() < TEMPBORDER) {
|
if (bmx.readTemperature() < TEMPBORDER) {
|
||||||
strip.setPixelColor(0, strip.Color(0,0,255));
|
strip.setPixelColor(0, strip.Color(0,0,255));
|
||||||
} else {
|
} else {
|
||||||
strip.setPixelColor(0, strip.Color(255,0,0));
|
strip.setPixelColor(0, strip.Color(255,0,0));
|
||||||
}
|
}
|
||||||
strip.show();
|
strip.show();
|
||||||
|
} else {
|
||||||
|
#ifdef BME680
|
||||||
|
bmx.performReading();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bmpPublishValues() {
|
||||||
|
// Publish the values
|
||||||
|
temperaturNode.setProperty(NODE_TEMPERATUR).send(String(bmx.readTemperature()));
|
||||||
|
pressureNode.setProperty(NODE_PRESSURE).send(String(bmx.readPressure() / 100.0F));
|
||||||
|
altitudeNode.setProperty(NODE_ALTITUDE).send(String(bmx.readAltitude(SEALEVELPRESSURE_HPA)));
|
||||||
|
#ifdef BME680
|
||||||
|
gasNode.setProperty(NODE_GAS).send(String((bmx.gas_resistance / 1000.0)));
|
||||||
|
humidityNode.setProperty(NODE_HUMIDITY).send(String(bmx.humidity));
|
||||||
|
#endif
|
||||||
|
log(MQTT_LEVEL_DEBUG, String("Temp" + String(bmx.readTemperature()) + "\tPressure:" +
|
||||||
|
String(bmx.readPressure() / 100.0F) + "\t Altitude:"+
|
||||||
|
String(bmx.readAltitude(SEALEVELPRESSURE_HPA))), MQTT_LOG_I2READ);
|
||||||
|
if ( (rgbTemp.get()) && (!mSomethingReceived) ) {
|
||||||
|
if (bmx.readTemperature() < TEMPBORDER) {
|
||||||
|
strip.setPixelColor(0, strip.Color(0,0,PERCENT2FACTOR(127, rgbDim)));
|
||||||
|
} else {
|
||||||
|
strip.setPixelColor(0, strip.Color(PERCENT2FACTOR(127, rgbDim),0,0));
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate JSON with last measured values
|
||||||
|
* For the update interval, please check @see PM1006_MQTT_UPDATE
|
||||||
|
* @return String with JSON
|
||||||
|
*/
|
||||||
|
String sensorAsJSON(void) {
|
||||||
|
String buffer;
|
||||||
|
StaticJsonDocument<500> doc;
|
||||||
|
|
||||||
|
if (mMeasureIndex > 0) {
|
||||||
|
int lastIdx = mMeasureIndex - 1;
|
||||||
|
doc["temp"] = String(mMeasureSeries[lastIdx].temp);
|
||||||
|
#ifdef BME680
|
||||||
|
doc["gas"] = String(mMeasureSeries[lastIdx].gas);
|
||||||
|
doc["humidity"] = String(mMeasureSeries[lastIdx].humidity);
|
||||||
|
#endif
|
||||||
|
float atmospheric = mMeasureSeries[lastIdx].pressure;
|
||||||
|
float altitude = 44330.0 * (1.0 - pow(atmospheric / SEALEVELPRESSURE_HPA, 0.1903));
|
||||||
|
doc["altitude"] = String(altitude);
|
||||||
|
doc["pressure"] = String(atmospheric);
|
||||||
|
doc["particle"] = String(mMeasureSeries[lastIdx].pm25);
|
||||||
|
}
|
||||||
|
doc["cycle"] = String(mMeasureIndex);
|
||||||
|
serializeJson(doc, buffer);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate JSON with all available sensors
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
String sensorHeader(void) {
|
||||||
|
String buffer;
|
||||||
|
StaticJsonDocument<500> doc;
|
||||||
|
doc.add("milli");
|
||||||
|
doc.add("temp");
|
||||||
|
#ifdef BME680
|
||||||
|
doc.add("gas");
|
||||||
|
doc.add("humidity");
|
||||||
|
#endif
|
||||||
|
doc.add("altitude");
|
||||||
|
doc.add("pressure");
|
||||||
|
doc.add("particle");
|
||||||
|
serializeJson(doc, buffer);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate JSON with all sensor values
|
||||||
|
* Array of JSON with all measured elements to show in the web browser.
|
||||||
|
* Example:
|
||||||
|
* <code>
|
||||||
|
* dynamicData = {
|
||||||
|
* labels: [ "0", "-30", "-60", "-90", "-120", "-160" ],
|
||||||
|
* datasets: [{
|
||||||
|
* label: 'temp',
|
||||||
|
* data: [24, 22, 23, 25, 22, 23],
|
||||||
|
* borderColor: "rgba(255,0,0,1)"
|
||||||
|
* }, {
|
||||||
|
* label: 'pressure',
|
||||||
|
* data: [1000, 1002, 1003, 999, 996, 1000],
|
||||||
|
* borderColor: "rgba(0,0,255,1)"
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
String diagramJson(void) {
|
||||||
|
int i;
|
||||||
|
String buffer;
|
||||||
|
String bufferLabels = "\"\"";
|
||||||
|
String bufferDataTemp = "\"\"";
|
||||||
|
String bufferDataPressure = "\"\"";
|
||||||
|
String bufferDataPM = "\"\"";
|
||||||
|
String bufferDatasets;
|
||||||
|
String bufferData;
|
||||||
|
if (mMeasureSeries == NULL) {
|
||||||
|
buffer = "{ \"error\": \"Malloc failed\" }";
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
long now = millis();
|
||||||
|
if (mMeasureIndex > 0) {
|
||||||
|
bufferLabels = "[ \"" + String((now - mMeasureSeries[0].timestamp) / 1000) + "s";
|
||||||
|
bufferDataTemp = "[ \"" + String(mMeasureSeries[0].temp);
|
||||||
|
bufferDataPressure = "[ \"" + String(mMeasureSeries[0].pressure);
|
||||||
|
bufferDataPM = "[ \"" + String(mMeasureSeries[0].pm25);
|
||||||
|
}
|
||||||
|
for(i=1; i < mMeasureIndex; i++) {
|
||||||
|
bufferLabels += "\", \"" + String((now - mMeasureSeries[i].timestamp) / 1000) + "s";
|
||||||
|
bufferDataTemp += "\", \"" + String(mMeasureSeries[i].temp);
|
||||||
|
bufferDataPressure += "\", \"" + String(mMeasureSeries[i].pressure);
|
||||||
|
bufferDataPM += "\", \"" + String(mMeasureSeries[i].pm25);
|
||||||
|
}
|
||||||
|
if (mMeasureIndex > 0) {
|
||||||
|
bufferLabels += "\" ]";
|
||||||
|
bufferDataTemp += "\" ]";
|
||||||
|
bufferDataPressure += "\" ]";
|
||||||
|
bufferDataPM += "\" ]";
|
||||||
|
}
|
||||||
|
/* Generate label */
|
||||||
|
buffer = "{ \"labels\" : " + bufferLabels + ",\n";
|
||||||
|
buffer += "\"datasets\" : [";
|
||||||
|
|
||||||
|
/* generate first block for Temperature */
|
||||||
|
buffer += "{\n \"label\" : \"Temp\",\n \"data\" : " + bufferDataTemp + ",\n \"borderColor\" : \"rgba(255,0,0,1)\" \n}";
|
||||||
|
|
||||||
|
/* generate second block for Pressure */
|
||||||
|
buffer += ", ";
|
||||||
|
buffer += "{\n \"label\" : \"Pressure\",\n \"data\" : " + bufferDataPressure + ",\n \"borderColor\" : \"rgba(0,0,255,1)\" \n}";
|
||||||
|
|
||||||
|
/* generate third block for PM2.5 values */
|
||||||
|
buffer += ", ";
|
||||||
|
buffer += "{\n \"label\" : \"PM 2.5\",\n \"data\" : " + bufferDataPM + ",\n \"borderColor\" : \"rgba(0,255,0,1)\" \n}";
|
||||||
|
|
||||||
|
/* TODO, next ones ... */
|
||||||
|
|
||||||
|
buffer += "]\n }";
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Main loop, triggered by the Homie API
|
* @brief Main loop, triggered by the Homie API
|
||||||
* All logic needs to be done here.
|
* All logic needs to be done here.
|
||||||
@@ -237,16 +455,18 @@ void loopHandler()
|
|||||||
{
|
{
|
||||||
static long lastRead = 0;
|
static long lastRead = 0;
|
||||||
if ((millis() - lastRead) > PM1006_MQTT_UPDATE) {
|
if ((millis() - lastRead) > PM1006_MQTT_UPDATE) {
|
||||||
int pM25 = getSensorData();
|
mParticle_pM25 = getSensorData();
|
||||||
if (pM25 >= 0) {
|
if (mParticle_pM25 >= 0) {
|
||||||
particle.setProperty(NODE_PARTICLE).send(String(pM25));
|
if (!mConnectedNonMQTT) {
|
||||||
|
particle.setProperty(NODE_PARTICLE).send(String(mParticle_pM25));
|
||||||
|
}
|
||||||
if (!mSomethingReceived) {
|
if (!mSomethingReceived) {
|
||||||
if (pM25 < 35) {
|
if (mParticle_pM25 < 35) {
|
||||||
strip.fill(strip.Color(0, 255, 0)); /* green */
|
strip.fill(strip.Color(0, PERCENT2FACTOR(127, rgbDim), 0)); /* green */
|
||||||
} else if (pM25 < 85) {
|
} else if (mParticle_pM25 < 85) {
|
||||||
strip.fill(strip.Color(255, 127, 0)); /* orange */
|
strip.fill(strip.Color(PERCENT2FACTOR(127, rgbDim), PERCENT2FACTOR(64, rgbDim), 0)); /* orange */
|
||||||
} else {
|
} else {
|
||||||
strip.fill(strip.Color(255, 0, 0)); /* red */
|
strip.fill(strip.Color(PERCENT2FACTOR(127, rgbDim), 0, 0)); /* red */
|
||||||
}
|
}
|
||||||
strip.show();
|
strip.show();
|
||||||
}
|
}
|
||||||
@@ -254,11 +474,38 @@ void loopHandler()
|
|||||||
|
|
||||||
/* Read BOSCH sensor */
|
/* Read BOSCH sensor */
|
||||||
if (i2cEnable.get() && (!mFailedI2Cinitialization)) {
|
if (i2cEnable.get() && (!mFailedI2Cinitialization)) {
|
||||||
bmpPublishValues();
|
updateLEDs();
|
||||||
|
if (!mConnectedNonMQTT) {
|
||||||
|
bmpPublishValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: add the measured data into the big list
|
||||||
|
if (mMeasureSeries != NULL) {
|
||||||
|
mMeasureSeries[mMeasureIndex].timestamp = millis();
|
||||||
|
mMeasureSeries[mMeasureIndex].temp = bmx.readTemperature();
|
||||||
|
#ifdef BME680
|
||||||
|
mMeasureSeries[mMeasureIndex].gas = (bmx.gas_resistance / 1000.0);
|
||||||
|
mMeasureSeries[mMeasureIndex].humidity = bmx.humidity;
|
||||||
|
#endif
|
||||||
|
float atmospheric = bmx.readPressure() / 100.0F;
|
||||||
|
mMeasureSeries[mMeasureIndex].pressure = atmospheric;
|
||||||
|
mMeasureSeries[mMeasureIndex].pm25 = mParticle_pM25;
|
||||||
|
mMeasureIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean cycles buttons */
|
||||||
|
if ((!mConnectedNonMQTT) && (mButtonPressed <= BUTTON_MIN_ACTION_CYCLE)) {
|
||||||
|
buttonNode.setProperty(NODE_BUTTON).send("0");
|
||||||
}
|
}
|
||||||
|
|
||||||
lastRead = millis();
|
lastRead = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if the user sees something via the LEDs, inform MQTT, too */
|
||||||
|
if ((!mConnectedNonMQTT) && (mButtonPressed > BUTTON_MIN_ACTION_CYCLE)) {
|
||||||
|
buttonNode.setProperty(NODE_BUTTON).send(String(mButtonPressed));
|
||||||
|
}
|
||||||
|
|
||||||
// Feed the dog -> ESP stay alive
|
// Feed the dog -> ESP stay alive
|
||||||
ESP.wdtFeed();
|
ESP.wdtFeed();
|
||||||
}
|
}
|
||||||
@@ -268,35 +515,40 @@ void loopHandler()
|
|||||||
bool ledHandler(const HomieRange& range, const String& value) {
|
bool ledHandler(const HomieRange& range, const String& value) {
|
||||||
if (range.isRange) return false; // only one switch is present
|
if (range.isRange) return false; // only one switch is present
|
||||||
|
|
||||||
mSomethingReceived = true; // Stop animation
|
Homie.getLogger() << "Received: " << (value) << endl;
|
||||||
|
if (value.equals("250,250,250")) {
|
||||||
int sep1 = value.indexOf(',');
|
mSomethingReceived = false; // enable animation again
|
||||||
int sep2 = value.indexOf(',', sep1 + 1);
|
ledStripNode.setProperty(NODE_AMBIENT).send(value);
|
||||||
if ((sep1 > 0) && (sep2 > 0)) {
|
|
||||||
int red = value.substring(0,sep1).toInt(); /* OpenHAB hue (0-360°) */
|
|
||||||
int green = value.substring(sep1 + 1, sep2).toInt(); /* OpenHAB saturation (0-100%) */
|
|
||||||
int blue = value.substring(sep2 + 1, value.length()).toInt(); /* brightness (0-100%) */
|
|
||||||
|
|
||||||
uint8_t r = (red * 255) / 250;
|
|
||||||
uint8_t g = (green *255) / 250;
|
|
||||||
uint8_t b = (blue *255) / 250;
|
|
||||||
uint32_t c = strip.Color(r,g,b);
|
|
||||||
strip.fill(c);
|
|
||||||
strip.show();
|
|
||||||
ledStripNode.setProperty(NODE_AMBIENT).send(String(r) + "," + String(g) + "," + String(b));
|
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
mSomethingReceived = true; // Stop animation
|
||||||
|
|
||||||
|
int sep1 = value.indexOf(',');
|
||||||
|
int sep2 = value.indexOf(',', sep1 + 1);
|
||||||
|
if ((sep1 > 0) && (sep2 > 0)) {
|
||||||
|
int red = value.substring(0,sep1).toInt();
|
||||||
|
int green = value.substring(sep1 + 1, sep2).toInt();
|
||||||
|
int blue = value.substring(sep2 + 1, value.length()).toInt();
|
||||||
|
|
||||||
|
uint8_t r = (red * 255) / 250;
|
||||||
|
uint8_t g = (green *255) / 250;
|
||||||
|
uint8_t b = (blue *255) / 250;
|
||||||
|
uint32_t c = strip.Color(r,g,b);
|
||||||
|
strip.fill(c);
|
||||||
|
strip.show();
|
||||||
|
ledStripNode.setProperty(NODE_AMBIENT).send(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* GLOBAL FUNCTIONS
|
* GLOBAL FUNCTIONS
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
SPIFFS.begin();
|
SPIFFS.begin();
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.setTimeout(2000);
|
Serial.setTimeout(2000);
|
||||||
@@ -310,15 +562,18 @@ void setup()
|
|||||||
Homie_setFirmware(HOMIE_FIRMWARE_NAME, HOMIE_FIRMWARE_VERSION);
|
Homie_setFirmware(HOMIE_FIRMWARE_NAME, HOMIE_FIRMWARE_VERSION);
|
||||||
Homie.setLoopFunction(loopHandler);
|
Homie.setLoopFunction(loopHandler);
|
||||||
Homie.onEvent(onHomieEvent);
|
Homie.onEvent(onHomieEvent);
|
||||||
i2cEnable.setDefaultValue(false);
|
i2cEnable.setDefaultValue(true);
|
||||||
rgbTemp.setDefaultValue(false);
|
rgbTemp.setDefaultValue(false);
|
||||||
memset(serialRxBuf, 0, 80);
|
rgbDim.setDefaultValue(100).setValidator([] (long candidate) {
|
||||||
|
return (candidate > 1) && (candidate <= 200);
|
||||||
|
});
|
||||||
|
memset(serialRxBuf, 0, SERIAL_RCEVBUF_MAX);
|
||||||
|
|
||||||
pmSerial.begin(PM1006_BIT_RATE);
|
pmSerial.begin(PM1006_BIT_RATE);
|
||||||
Homie.setup();
|
Homie.setup();
|
||||||
|
|
||||||
particle.advertise(NODE_PARTICLE).setName("Particle").setDatatype(NUMBER_TYPE).setUnit("micro gram per quibik");
|
particle.advertise(NODE_PARTICLE).setName("Particle").setDatatype(NUMBER_TYPE).setUnit("micro gram per quibik");
|
||||||
temperatureNode.advertise(NODE_TEMPERATUR).setName("Degrees")
|
temperaturNode.advertise(NODE_TEMPERATUR).setName("Degrees")
|
||||||
.setDatatype("float")
|
.setDatatype("float")
|
||||||
.setUnit("ºC");
|
.setUnit("ºC");
|
||||||
pressureNode.advertise(NODE_PRESSURE).setName("Pressure")
|
pressureNode.advertise(NODE_PRESSURE).setName("Pressure")
|
||||||
@@ -327,73 +582,127 @@ void setup()
|
|||||||
altitudeNode.advertise(NODE_ALTITUDE).setName("Altitude")
|
altitudeNode.advertise(NODE_ALTITUDE).setName("Altitude")
|
||||||
.setDatatype("float")
|
.setDatatype("float")
|
||||||
.setUnit("m");
|
.setUnit("m");
|
||||||
|
#ifdef BME680
|
||||||
gasNode.advertise(NODE_GAS).setName("Gas")
|
gasNode.advertise(NODE_GAS).setName("Gas")
|
||||||
.setDatatype("float")
|
.setDatatype("float")
|
||||||
.setUnit(" KOhms");
|
.setUnit(" KOhms");
|
||||||
humidityNode.advertise(NODE_HUMIDITY).setName("Humidity")
|
humidityNode.advertise(NODE_HUMIDITY).setName("Humidity")
|
||||||
.setDatatype("float")
|
.setDatatype("float")
|
||||||
.setUnit("%");
|
.setUnit("%");
|
||||||
|
#endif
|
||||||
ledStripNode.advertise(NODE_AMBIENT).setName("All Leds")
|
ledStripNode.advertise(NODE_AMBIENT).setName("All Leds")
|
||||||
.setDatatype("color").setFormat("rgb")
|
.setDatatype("color").setFormat("rgb")
|
||||||
.settable(ledHandler);
|
.settable(ledHandler);
|
||||||
|
buttonNode.advertise(NODE_BUTTON).setName("Button pressed")
|
||||||
|
.setDatatype("integer");
|
||||||
|
|
||||||
strip.begin();
|
strip.begin();
|
||||||
/* activate I2C for BOSCH sensor */
|
|
||||||
Wire.begin(SENSOR_I2C_SDI, SENSOR_I2C_SCK);
|
|
||||||
|
|
||||||
mConfigured = Homie.isConfigured();
|
mConfigured = Homie.isConfigured();
|
||||||
digitalWrite(WITTY_RGB_G, HIGH);
|
digitalWrite(WITTY_RGB_G, HIGH);
|
||||||
if (mConfigured)
|
if (mConfigured)
|
||||||
{
|
{
|
||||||
|
mMeasureSeries = (sensor_point *) malloc(sizeof(sensor_point) * MEASURE_POINT_MAX);
|
||||||
|
memset(mMeasureSeries, 0, sizeof(sensor_point) * MEASURE_POINT_MAX);
|
||||||
if (i2cEnable.get()) {
|
if (i2cEnable.get()) {
|
||||||
strip.fill(strip.Color(0,128,0));
|
#ifdef BME680
|
||||||
strip.show();
|
printf("Wait 1 second...\r\n");
|
||||||
|
delay(1000);
|
||||||
|
#endif
|
||||||
|
/* activate I2C for BOSCH sensor */
|
||||||
|
Wire.begin(SENSOR_I2C_SDI, SENSOR_I2C_SCK);
|
||||||
|
printf("Wait 50 milliseconds...\r\n");
|
||||||
|
delay(50);
|
||||||
/* Extracted from library's example */
|
/* Extracted from library's example */
|
||||||
mFailedI2Cinitialization = !bme.begin();
|
mFailedI2Cinitialization = !bmx.begin();
|
||||||
if (!mFailedI2Cinitialization) {
|
if (!mFailedI2Cinitialization) {
|
||||||
bme.setTemperatureOversampling(BME680_OS_8X);
|
strip.fill(strip.Color(0,PERCENT2FACTOR(64, rgbDim),0));
|
||||||
bme.setHumidityOversampling(BME680_OS_2X);
|
strip.show();
|
||||||
bme.setPressureOversampling(BME680_OS_4X);
|
#ifdef BME680
|
||||||
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
|
bmx.setTemperatureOversampling(BME680_OS_8X);
|
||||||
bme.setGasHeater(320, 150); // 320*C for 150 ms
|
bmx.setHumidityOversampling(BME680_OS_2X);
|
||||||
|
bmx.setPressureOversampling(BME680_OS_4X);
|
||||||
|
bmx.setIIRFilterSize(BME680_FILTER_SIZE_3);
|
||||||
|
bmx.setGasHeater(320, 150); // 320*C for 150 ms
|
||||||
|
#endif
|
||||||
|
#ifdef BMP280
|
||||||
|
/* Default settings from datasheet. */
|
||||||
|
bmx.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||||
|
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||||
|
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||||
|
Adafruit_BMP280::FILTER_X16, /* Filtering. */
|
||||||
|
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
|
||||||
|
#endif
|
||||||
|
printf("Sensor found on I2C bus\r\n");
|
||||||
} else {
|
} else {
|
||||||
printf("Faild to initialize I2C bus\r\n");
|
printf("Failed to initialize I2C bus\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strip.fill(strip.Color(0,0,0));
|
strip.fill(strip.Color(0,0,0));
|
||||||
for (int i=0;i < (PIXEL_COUNT / 2); i++) {
|
|
||||||
strip.setPixelColor(0, strip.Color(0,0,128));
|
for (int i=0;i < (PIXEL_COUNT / 2); i++) {
|
||||||
}
|
strip.setPixelColor(0, strip.Color(0,128,0));
|
||||||
strip.show();
|
}
|
||||||
digitalWrite(WITTY_RGB_B, HIGH);
|
mHttp = new AsyncWebServer(PORTNUMBER_HTTP);
|
||||||
} else {
|
mHttp->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
strip.fill(strip.Color(128,0,0));
|
request->send(200, "text/plain", String(ESP.getFreeHeap()));
|
||||||
for (int i=0;i < (PIXEL_COUNT / 2); i++) {
|
});
|
||||||
strip.setPixelColor(0, strip.Color(0,0,128));
|
mHttp->on("/sensors", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
}
|
request->send(200, "application/json", sensorAsJSON());
|
||||||
|
});
|
||||||
|
mHttp->on("/header", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
request->send(200, "application/json", sensorHeader());
|
||||||
|
});
|
||||||
|
mHttp->on("/diagram", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
request->send(200, "application/json", diagramJson());
|
||||||
|
});
|
||||||
|
mHttp->serveStatic("/", SPIFFS, "/").setDefaultFile("standalone.htm");
|
||||||
|
mHttp->begin();
|
||||||
|
Homie.getLogger() << "Webserver started" << endl;
|
||||||
strip.show();
|
strip.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
Homie.loop();
|
if (!mConnectedNonMQTT) {
|
||||||
|
Homie.loop();
|
||||||
|
} else {
|
||||||
|
/* call the custom loop directly, as Homie is deactivated */
|
||||||
|
loopHandler();
|
||||||
|
}
|
||||||
/* use the pin, receiving the soft serial additionally as button */
|
/* use the pin, receiving the soft serial additionally as button */
|
||||||
if (digitalRead(GPIO_BUTTON) == LOW) {
|
if (digitalRead(GPIO_BUTTON) == LOW) {
|
||||||
mButtonPressed++;
|
if ((millis() - mLastButtonAction) > BUTTON_CHECK_INTERVALL) {
|
||||||
|
mButtonPressed++;
|
||||||
|
}
|
||||||
|
if (mButtonPressed > BUTTON_MIN_ACTION_CYCLE) {
|
||||||
|
digitalWrite(WITTY_RGB_R, HIGH);
|
||||||
|
digitalWrite(WITTY_RGB_B, LOW);
|
||||||
|
strip.fill(strip.Color(0,0,0));
|
||||||
|
strip.setPixelColor(0, strip.Color((mButtonPressed % 100),0,0));
|
||||||
|
strip.setPixelColor(1, strip.Color((mButtonPressed / 100),0,0));
|
||||||
|
strip.setPixelColor(2, strip.Color((mButtonPressed / 100),0,0));
|
||||||
|
strip.show();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mButtonPressed=0U;
|
mButtonPressed=0U;
|
||||||
|
digitalWrite(WITTY_RGB_R, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mButtonPressed > 10000U) {
|
if (mButtonPressed > BUTTON_MAX_CYCLE) {
|
||||||
mButtonPressed=0U;
|
|
||||||
if (SPIFFS.exists("/homie/config.json")) {
|
if (SPIFFS.exists("/homie/config.json")) {
|
||||||
|
strip.fill(strip.Color(0,PERCENT2FACTOR(127, rgbDim),0));
|
||||||
|
strip.show();
|
||||||
printf("Resetting config\r\n");
|
printf("Resetting config\r\n");
|
||||||
SPIFFS.remove("/homie/config.json");
|
SPIFFS.remove("/homie/config.json");
|
||||||
SPIFFS.end();
|
SPIFFS.end();
|
||||||
|
delay(50);
|
||||||
|
Homie.reboot();
|
||||||
} else {
|
} else {
|
||||||
printf("No config present\r\n");
|
printf("No config present\r\n");
|
||||||
|
strip.fill(strip.Color(0,0,128));
|
||||||
|
strip.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -414,4 +723,5 @@ void log(int level, String message, int statusCode)
|
|||||||
Homie.getMqttClient().publish(logTopic, 2, false, buffer.c_str());
|
Homie.getMqttClient().publish(logTopic, 2, false, buffer.c_str());
|
||||||
delete logTopic;
|
delete logTopic;
|
||||||
}
|
}
|
||||||
|
Homie.getLogger() << (level) << "@" << (statusCode) << " " << (message) << endl;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user