Don't report unreliable data. Also translate Pa -> hPa, which is a more commonly used unit.
This commit is contained in:
parent
0767d1661f
commit
d67511fbb5
|
@ -15,7 +15,6 @@ monitor_speed = 9600
|
|||
platform = atmelsam
|
||||
board = nano_33_iot
|
||||
framework = arduino
|
||||
|
||||
lib_deps =
|
||||
WiFiNINA
|
||||
MQTT
|
||||
|
@ -25,7 +24,4 @@ platform = espressif8266
|
|||
board = d1_mini
|
||||
framework = arduino
|
||||
upload_protocol = esptool
|
||||
|
||||
lib_deps =
|
||||
MQTT
|
||||
|
||||
lib_deps = MQTT
|
||||
|
|
109
src/main.cpp
109
src/main.cpp
|
@ -3,58 +3,41 @@
|
|||
#include <WiFi_functions.h>
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(HAS_WIFI)
|
||||
#error ("This example program has been created for specific WiFi enabled hosts only.")
|
||||
#endif
|
||||
|
||||
WiFiClient client;
|
||||
|
||||
// Buffers for assembling http POST requests
|
||||
// Buffers for assembling http POST requests.
|
||||
char postBuffer[450] = {0};
|
||||
char fieldBuffer[70] = {0};
|
||||
|
||||
// Structs for data
|
||||
// Structs for holding measurement data.
|
||||
AirData_t airData = {0};
|
||||
AirQualityData_t airQualityData = {0};
|
||||
LightData_t lightData = {0};
|
||||
ParticleData_t particleData = {0};
|
||||
SoundData_t soundData = {0};
|
||||
|
||||
// Define the display attributes of data sent to Home Assistant.
|
||||
// The chosen name, unit and icon will appear in on the overview
|
||||
// dashboard in Home Assistant. The icons can be chosen from
|
||||
// https://cdn.materialdesignicons.com/5.3.45/
|
||||
// (remove the "mdi-" part from the icon name).
|
||||
// Definition of the display attributes of data sent to Home Assistant.
|
||||
// The attribute fields are: {name, unit, icon, decimal places}
|
||||
HA_Attributes_t pressure = {"Pressure","Pa","weather-cloudy",0};
|
||||
HA_Attributes_t pressure = {"Pressure", "hPa", "weather-cloudy", 0};
|
||||
HA_Attributes_t humidity = {"Humidity","%","water-percent",1};
|
||||
HA_Attributes_t temperature = {"Temperature", CELSIUS_SYMBOL, "thermometer", 1};
|
||||
HA_Attributes_t illuminance = {"Illuminance","lx","white-balance-sunny",2};
|
||||
HA_Attributes_t soundLevel = {"Sound level","dBA","microphone",1};
|
||||
HA_Attributes_t peakAmplitude = {"Sound peak","mPa","waveform",2};
|
||||
HA_Attributes_t estimatedCO2 = {"Estimated CO2","ppm","chart-bubble",1};
|
||||
HA_Attributes_t equivalentBreathVOC = {"Equivalent breath VOC","ppm","chart-bubble",2};
|
||||
HA_Attributes_t AQI = {"Air Quality Index"," ","thought-bubble-outline",1};
|
||||
HA_Attributes_t AQ_index = {"Air Quality Index", " ", "thought-bubble-outline", 1};
|
||||
HA_Attributes_t AQ_assessment = {"Air quality assessment","","flower-tulip",0};
|
||||
HA_Attributes_t AQ_calibration = {"Air quality calibration","","flower-tulip",0};
|
||||
#if (PARTICLE_SENSOR == PARTICLE_SENSOR_PPD42)
|
||||
HA_Attributes_t particulates = {"Particle concentration","ppL","chart-bubble",0};
|
||||
#else
|
||||
HA_Attributes_t particulates = {"Particle concentration",SDS011_UNIT_SYMBOL,"chart-bubble",2};
|
||||
#endif
|
||||
#ifdef USE_FAHRENHEIT
|
||||
HA_Attributes_t temperature = {"Temperature",FAHRENHEIT_SYMBOL,"thermometer",1};
|
||||
#else
|
||||
HA_Attributes_t temperature = {"Temperature",CELSIUS_SYMBOL,"thermometer",1};
|
||||
#endif
|
||||
HA_Attributes_t particleConcentration = {"Particle concentration", "ppL", "chart-bubble", 0};
|
||||
HA_Attributes_t particleCalibration = {"Particle calibration", "", "chart-bubble", 0};
|
||||
|
||||
|
||||
void setup() {
|
||||
// Initialize the host's pins, set up the serial port and reset:
|
||||
void setup()
|
||||
{
|
||||
SensorHardwareSetup(I2C_ADDRESS);
|
||||
|
||||
connectToWiFi(WIFI_SSID, WIFI_PASSWORD);
|
||||
|
||||
// Apply settings to the MS430 and enter cycle mode
|
||||
// Apply settings to the Metriful MS430 board and enter cycle mode.
|
||||
uint8_t particleSensorCode = PARTICLE_SENSOR;
|
||||
uint8_t cycle_period = CYCLE_PERIOD;
|
||||
TransmitI2C(I2C_ADDRESS, PARTICLE_SENSOR_SELECT_REG, &particleSensorCode, 1);
|
||||
|
@ -63,7 +46,7 @@ void setup() {
|
|||
TransmitI2C(I2C_ADDRESS, CYCLE_MODE_CMD, 0, 0);
|
||||
}
|
||||
|
||||
// Send the data to Home Assistant as an HTTP POST request.
|
||||
// Send data to Home Assistant as an HTTP POST request.
|
||||
void http_POST_Home_Assistant(const HA_Attributes_t * attributes, const char * valueText) {
|
||||
client.stop();
|
||||
if (client.connect(HOME_ASSISTANT_IP, 8123)) {
|
||||
|
@ -81,7 +64,8 @@ void http_POST_Home_Assistant(const HA_Attributes_t * attributes, const char * v
|
|||
client.println("Authorization: Bearer " LONG_LIVED_ACCESS_TOKEN);
|
||||
|
||||
// Assemble the JSON content string:
|
||||
sprintf(postBuffer,"{\"state\":%s,\"attributes\":{\"unit_of_measurement\""
|
||||
sprintf(postBuffer,
|
||||
"{\"state\":%s,\"attributes\":{\"unit_of_measurement\""
|
||||
":\"%s\",\"friendly_name\":\"%s\",\"icon\":\"mdi:%s\"}}",
|
||||
valueText, attributes->unit, attributes->name, attributes->icon);
|
||||
|
||||
|
@ -95,7 +79,7 @@ void http_POST_Home_Assistant(const HA_Attributes_t * attributes, const char * v
|
|||
}
|
||||
}
|
||||
|
||||
// Send numeric data with specified sign, integer and fractional parts
|
||||
// Send numeric data with specified sign, integer and fractional parts.
|
||||
void sendNumericData(const HA_Attributes_t * attributes, uint32_t valueInteger,
|
||||
uint8_t valueDecimal, bool isPositive) {
|
||||
char valueText[20] = {0};
|
||||
|
@ -115,22 +99,24 @@ void sendNumericData(const HA_Attributes_t * attributes, uint32_t valueInteger,
|
|||
http_POST_Home_Assistant(attributes, valueText);
|
||||
}
|
||||
|
||||
// Send a text string: must have quotation marks added
|
||||
// Send a text string: must have quotation marks added.
|
||||
void sendTextData(const HA_Attributes_t * attributes, const char * valueText) {
|
||||
char quotedText[20] = {0};
|
||||
sprintf(quotedText,"\"%s\"", valueText);
|
||||
http_POST_Home_Assistant(attributes, quotedText);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Wait for the next new data release, indicated by a falling edge on READY
|
||||
Serial.println("Waiting for new data ...");
|
||||
void wait_for_new_readings()
|
||||
{
|
||||
Serial.println("Waiting for new data from sensors ...");
|
||||
while (!ready_assertion_event) {
|
||||
yield();
|
||||
}
|
||||
ready_assertion_event = false;
|
||||
}
|
||||
|
||||
void read_sensor_data_from_i2c()
|
||||
{
|
||||
// Read data from the MS430 into the data structs.
|
||||
Serial.println("Reading data from sensors");
|
||||
ReceiveI2C(I2C_ADDRESS, AIR_DATA_READ, (uint8_t *) &airData, AIR_DATA_BYTES);
|
||||
|
@ -138,41 +124,64 @@ void loop() {
|
|||
ReceiveI2C(I2C_ADDRESS, LIGHT_DATA_READ, (uint8_t *) &lightData, LIGHT_DATA_BYTES);
|
||||
ReceiveI2C(I2C_ADDRESS, SOUND_DATA_READ, (uint8_t *) &soundData, SOUND_DATA_BYTES);
|
||||
ReceiveI2C(I2C_ADDRESS, PARTICLE_DATA_READ, (uint8_t *) &particleData, PARTICLE_DATA_BYTES);
|
||||
}
|
||||
|
||||
// Check that WiFi is still connected
|
||||
void make_sure_wifi_is_connected() {
|
||||
uint8_t wifiStatus = WiFi.status();
|
||||
if (wifiStatus != WL_CONNECTED) {
|
||||
// There is a problem with the WiFi connection: attempt to reconnect.
|
||||
Serial.print("Wifi status: ");
|
||||
Serial.print("Wifi diconnected! Status: ");
|
||||
Serial.println(interpret_WiFi_status(wifiStatus));
|
||||
connectToWiFi(WIFI_SSID, WIFI_PASSWORD);
|
||||
ready_assertion_event = false;
|
||||
}
|
||||
}
|
||||
|
||||
void send_data_to_home_assistant() {
|
||||
Serial.println("Send data to Home Assistant");
|
||||
|
||||
uint8_t T_intPart = 0;
|
||||
uint8_t T_fractionalPart = 0;
|
||||
bool isPositive = true;
|
||||
getTemperature(&airData, &T_intPart, &T_fractionalPart, &isPositive);
|
||||
|
||||
// Send data to Home Assistant
|
||||
Serial.println("Send data to Home Assistant");
|
||||
sendNumericData(&temperature, (uint32_t) T_intPart, T_fractionalPart, isPositive);
|
||||
sendNumericData(&pressure, (uint32_t) airData.P_Pa, 0, true);
|
||||
sendNumericData(&pressure, (uint32_t)airData.P_Pa / 100, 0, true);
|
||||
sendNumericData(&humidity, (uint32_t) airData.H_pc_int, airData.H_pc_fr_1dp, true);
|
||||
sendNumericData(&illuminance, (uint32_t) lightData.illum_lux_int, lightData.illum_lux_fr_2dp, true);
|
||||
sendNumericData(&soundLevel, (uint32_t) soundData.SPL_dBA_int, soundData.SPL_dBA_fr_1dp, true);
|
||||
sendNumericData(&peakAmplitude, (uint32_t) soundData.peak_amp_mPa_int,
|
||||
soundData.peak_amp_mPa_fr_2dp, true);
|
||||
sendNumericData(&AQI, (uint32_t) airQualityData.AQI_int, airQualityData.AQI_fr_1dp, true);
|
||||
if (PARTICLE_SENSOR != PARTICLE_SENSOR_OFF) {
|
||||
sendNumericData(&particulates, (uint32_t) particleData.concentration_int,
|
||||
particleData.concentration_fr_2dp, true);
|
||||
sendNumericData(&peakAmplitude, (uint32_t) soundData.peak_amp_mPa_int, soundData.peak_amp_mPa_fr_2dp, true);
|
||||
|
||||
// When the particle sensor is not connected, we get 65535 readings.
|
||||
// We want to skip those. Also skip sending data while the sensor
|
||||
// is warming up. This way, invalid data is not logged in
|
||||
// Home Assistant.
|
||||
sendNumericData(&particleCalibration, (uint32_t)particleData.valid, 0, true);
|
||||
if (particleData.valid != 0 && particleData.concentration_int < 60000)
|
||||
{
|
||||
sendNumericData(&particleConcentration, (uint32_t)particleData.concentration_int, particleData.concentration_fr_2dp, true);
|
||||
}
|
||||
sendTextData(&AQ_assessment, interpret_AQI_value(airQualityData.AQI_int));
|
||||
|
||||
// While the Metriful board is still in its self-calibration
|
||||
// phase, do not send air quality data to Home Assistant.
|
||||
sendNumericData(&AQ_calibration, airQualityData.AQI_accuracy, 0, true);
|
||||
if (airQualityData.AQI_accuracy > 0) {
|
||||
sendNumericData(&estimatedCO2, (uint32_t) airQualityData.CO2e_int, airQualityData.CO2e_fr_1dp, true);
|
||||
sendNumericData(&equivalentBreathVOC, (uint32_t) airQualityData.bVOC_int, airQualityData.bVOC_fr_2dp, true);
|
||||
sendNumericData(&AQ_calibration, airQualityData.AQI_accuracy, 0, true);
|
||||
sendNumericData(&AQ_index, (uint32_t)airQualityData.AQI_int, airQualityData.AQI_fr_1dp, true);
|
||||
sendTextData(&AQ_assessment, interpret_AQI_value(airQualityData.AQI_int));
|
||||
}
|
||||
}
|
||||
|
||||
void log_measurements_to_console() {
|
||||
printAirData(&airData, false);
|
||||
printParticleData(&particleData, false, PARTICLE_SENSOR);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
wait_for_new_readings();
|
||||
read_sensor_data_from_i2c();
|
||||
make_sure_wifi_is_connected();
|
||||
send_data_to_home_assistant();
|
||||
log_measurements_to_console();
|
||||
}
|
Loading…
Reference in New Issue