2021-01-19 18:26:06 +02:00
/*
П и т а н и е 3 , 3 В
Л о г и ч е с к и е у р о в н и 3 , 3 В
Т о ч н о с т ь и з м е р е н и я в л а ж н о с т и ± 2 %
Т о ч н о с т ь и з м е р е н и я т е м п е р а т у р ы ± 0 , 2 ° C
Р а з р е ш а ю щ а я с п о с о б н о с т ь п о к а з а н и й д а т ч и к а HDC1080 14 б и т
Д и а п а з о н и з м е р е н и я к о н ц е н т р а ц и и CO2 : 400 . . . 8192 ppm
Д и а п а з о н и з м е р е н и я к о н ц е н т р а ц и и л е т у ч и х о р г а н и ч е с к и х в е щ е с т в 0 . . . 1187 ppb
*/
2021-01-14 23:27:49 +02:00
# include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
# include <Preferences.h> //Сохранение настроек хеша прошивки
# include <HTTPClient.h>
2021-01-21 17:54:46 +02:00
# include <ESP32httpUpdate.h> //Библиотека О Т А обновлений
# include "M5Atom.h" //Библиотека атома для функции Led и Кнопки, можно упразднить и убрать
2021-01-19 18:26:06 +02:00
2021-02-09 20:29:13 +02:00
# include <Ticker.h> //Библиотека таймера для Led
# include <WiFiUdp.h> //Udp клиент
# include <NTPClient.h> //NTP запрос времени
# include <TimeLib.h> //Внутреннее время
# include <Wire.h> //Библиотека дял I2C
# include "ClosedCube_HDC1080.h" //Температура влажность
# include "Adafruit_CCS811.h" //eco2 Tvoc
# include <PubSubClient.h> //Mtqq
# include <ArduinoJson.h> //Упакова в JSon - удобная библиотека
# include <ESPmDNS.h>
2021-01-14 23:27:49 +02:00
//Наша кнопочка при нажатии на которую произойдет вызов wifi менеджера и перезагрузка в станцию
# define TRIGGER_PIN 39
2021-02-09 20:29:13 +02:00
unsigned int VersionSW = 21 ; //65536 Версия прошивки
//15 - добавлено то, с е , забыл вообще дописать что до б а вле но Serial
//19 - вывод в консоль всех действий, ошибки с обновлнеием - починил, прияногое мигание светодиодом, тест для поиска metrics.
//21 - убран мак из вывода в топике
2021-01-20 21:27:05 +02:00
2021-01-14 23:27:49 +02:00
WiFiManager wm ; // обьект менеджера
WiFiManagerParameter custom_field ;
2021-02-09 20:29:13 +02:00
Preferences OTApreferences ; //Обьект хранения настроек хеша прошивки
2021-01-14 23:27:49 +02:00
2021-01-19 18:26:06 +02:00
Ticker RGBWTicker ;
Adafruit_CCS811 ccs ;
ClosedCube_HDC1080 hdc1080 ;
String JsonData ;
2021-02-09 20:29:13 +02:00
StaticJsonDocument < 200 > doc , other ;
2021-01-19 18:26:06 +02:00
WiFiClient espClient ;
PubSubClient MqttClient ( espClient ) ;
IPAddress IpMqtt ;
2021-01-20 21:27:05 +02:00
WiFiUDP ntpUDP ;
2021-02-09 20:29:13 +02:00
NTPClient timeClient ( ntpUDP , " 0.ua.pool.ntp.org " , 7200 , 60000 ) ; //Собственно сервер времени смещение и частоат запроса, но он вручную
2021-01-20 21:27:05 +02:00
2021-02-09 20:29:13 +02:00
const PROGMEM char * mqttHostName = " 192.168.89.210 " ; //Хостнейм брокера metrics.local //192.168.89.210
unsigned int mqttPort = 1883 ; //Порт брокера 1883
const PROGMEM char * topicName = " /aastudio " ; // +mac адресс девайса Префикс топика
const PROGMEM char * mqttLogin = " login " , //Логин пароль - необходимо сменить код при connect()
* mqttPass = " password " ;
const char * mqttIPHost ; //тут хранится IP хоста по хостнейму
2021-01-19 18:26:06 +02:00
2021-02-09 20:29:13 +02:00
unsigned long timingUpdate , timingReqSensor , timingSendMqtt ; //Таймеры для millis()
int PROGMEM nextM5Update = 450000 ; //каждые 7.5 минут запрос обновления с сервера
int PROGMEM nextReqSensor = 10000 ; //опрос датчиков раз в 10 секунд
int PROGMEM nextMqttSend = 60000 ; //Отправка
2021-01-19 18:26:06 +02:00
2021-01-21 17:54:46 +02:00
//Поправочные коефициенты для датчиков
2021-01-19 18:26:06 +02:00
//[24A160474D14, 5002919F5450, 5002918A38CC]
//tcoeff[0,1,2]
//hcoeff[0,1,2]
2021-02-09 20:29:13 +02:00
float PROGMEM tcoeff [ 3 ] = { - 11.18 , - 9.62 , - 10.6 } ; //Температура
float PROGMEM hcoeff [ 3 ] = { 13.77 , 14.07 , 15.56 } ; //Влажность
2021-01-19 18:26:06 +02:00
float callibrationT = 0 , callibrationH = 0 ;
2021-01-21 17:54:46 +02:00
String macc = " " ; //Глобальное хранение мас адреса
2021-01-19 18:26:06 +02:00
float TempAv , HumAv , Eco2Av , TvocAv ;
2021-02-09 20:29:13 +02:00
byte errorID = 0 ;
2021-01-19 18:26:06 +02:00
2021-02-09 20:29:13 +02:00
long rssi = 0 ;
//int hall=0;
2021-01-21 17:54:46 +02:00
//Кусок кода поправить - так делать нельзя
2021-01-20 21:27:05 +02:00
# define NUM_AVER 5
2021-01-19 18:26:06 +02:00
float averageT ; // перем. среднего
float valArrayT [ NUM_AVER ] ; // массив
byte idxT = 0 ;
2021-02-09 20:29:13 +02:00
float averageH ; // перем. среднего
2021-01-19 18:26:06 +02:00
float valArrayH [ NUM_AVER ] ; // массив
byte idxH = 0 ;
float averageECO ; // перем. среднего
float valArrayECO [ NUM_AVER ] ; // массив
byte idxECO = 0 ;
float averageTVOC ; // перем. среднего
float valArrayTVOC [ NUM_AVER ] ; // массив
byte idxTVOC = 0 ;
bool mqttSendFlag = false ;
// float arrT[5] = {0}, arrH[5] = {0};
// int arrECO[5] = {0}, tvoc[5] = {0};
int reqCounter = 0 ;
bool flagblink = true ;
2021-01-14 23:27:49 +02:00
2021-01-21 17:54:46 +02:00
//Настройки
2021-01-14 23:27:49 +02:00
void setup ( )
{
2021-01-19 18:26:06 +02:00
M5 . begin ( true , false , true ) ;
delay ( 50 ) ;
2021-02-09 20:29:13 +02:00
Wire . begin ( 25 , 21 ) ; //Пины для I2c на ATOM
2021-01-19 18:26:06 +02:00
2021-02-09 20:29:13 +02:00
pinMode ( 23 , OUTPUT ) ; //Пин датчика для работы
2021-01-19 18:26:06 +02:00
digitalWrite ( 23 , LOW ) ;
2021-01-14 23:27:49 +02:00
WiFi . mode ( WIFI_STA ) ;
Serial . begin ( 115200 ) ;
Serial . setDebugOutput ( true ) ;
delay ( 3000 ) ;
2021-01-21 17:54:46 +02:00
2021-01-14 23:27:49 +02:00
Serial . println ( " \n Starting station " ) ;
2021-02-09 20:29:13 +02:00
pinMode ( TRIGGER_PIN , INPUT ) ;
2021-01-14 23:27:49 +02:00
// wm.resetSettings(); // wipe settings
// add a custom input field
int customFieldLength = 40 ;
// new (&custom_field) WiFiManagerParameter("customfieldid", "Custom Field Label", "Custom Field Value", customFieldLength,"placeholder=\"Custom Field Placeholder\"");
// test custom html input type(checkbox)
// new (&custom_field) WiFiManagerParameter("customfieldid", "Custom Field Label", "Custom Field Value", customFieldLength,"placeholder=\"Custom Field Placeholder\" type=\"checkbox\""); // custom html type
// test custom html(radio)
const char * custom_radio_str = " <br/><label for='customfieldid'>Custom Field Label</label><input type='radio' name='customfieldid' value='1' checked> One<br><input type='radio' name='customfieldid' value='2'> Two<br><input type='radio' name='customfieldid' value='3'> Three " ;
new ( & custom_field ) WiFiManagerParameter ( custom_radio_str ) ; // custom html input
wm . addParameter ( & custom_field ) ;
wm . setSaveParamsCallback ( saveParamCallback ) ;
// custom menu via array or vector
// menu tokens, "wifi","wifinoscan","info","param","close","sep","erase","restart","exit" (sep is seperator) (if param is in menu, params will not show up in wifi page!)
// const char* menu[] = {"wifi","info","param","sep","restart","exit"};
// wm.setMenu(menu,6);
std : : vector < const char * > menu = { " wifi " , " info " , " param " , " sep " , " restart " , " exit " } ;
wm . setMenu ( menu ) ;
// set dark theme
wm . setClass ( " invert " ) ;
//set static ip
// wm.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // set static ip,gw,sn
// wm.setShowStaticFields(true); // force show static ip fields
// wm.setShowDnsFields(true); // force show dns field always
// wm.setConnectTimeout(20); // how long to try to connect for before continuing
wm . setConfigPortalTimeout ( 30 ) ; // auto close configportal after n seconds
// wm.setCaptivePortalEnable(false); // disable captive portal redirection
// wm.setAPClientCheck(true); // avoid timeout if client connected to softap
// wifi scan settings
// wm.setRemoveDuplicateAPs(false); // do not remove duplicate ap names (true)
// wm.setMinimumSignalQuality(20); // set min RSSI (percentage) to show in scans, null = 8%
// wm.setShowInfoErase(false); // do not show erase button on info page
// wm.setScanDispPerc(true); // show RSSI as percentage not graph icons
// wm.setBreakAfterConfig(true); // always exit configportal even if wifi save fails
bool res ;
// res = wm.autoConnect(); // auto generated AP name from chipid
// res = wm.autoConnect("AutoConnectAP"); // anonymous ap
2021-02-09 20:29:13 +02:00
res = wm . autoConnect ( " AirQaPortal " , " 12345678 " ) ; // Подключение к анонимной точке доступа
2021-01-14 23:27:49 +02:00
if ( ! res )
{
Serial . println ( " Failed to connect or hit timeout " ) ;
// ESP.restart();
}
else
{
2021-02-09 20:29:13 +02:00
Serial . println ( " Server AirQaPortal start " ) ;
2021-01-14 23:27:49 +02:00
}
2021-01-19 18:26:06 +02:00
if ( ! ccs . begin ( ) ) //The device's I2C address is 0x5A
{
Serial . println ( " Failed to start sensor CCS811! " ) ;
}
ccs . setTempOffset ( 8.6 ) ;
hdc1080 . begin ( 0x40 ) ; //14 бит температура и влажность
hdc1080 . setResolution ( HDC1080_RESOLUTION_14BIT , HDC1080_RESOLUTION_14BIT ) ;
//Установка коеффициентов каллибровки по MAC адресу
SetCallibrationCoeff ( ) ;
//Запрос IP сервера MQTT и установка сервера
setMqttServer ( ) ;
2021-01-20 21:27:05 +02:00
reqNtpTime ( ) ;
2021-01-19 18:26:06 +02:00
}
2021-01-21 17:54:46 +02:00
//Установка сервера и порта
2021-01-19 18:26:06 +02:00
void setMqttServer ( )
2021-02-09 20:29:13 +02:00
{
Serial . println ( " ======WHERE IS METRICS.LOCAL===== " ) ;
mdns_init ( ) ;
Serial . print ( " MDNS SAY: " ) ;
IPAddress ipaddr = MDNS . queryHost ( " metrics " ) ; // .local omitted
Serial . println ( ipaddr . toString ( ) ) ;
Serial . print ( " HOSTBYNAME SAY: " ) ;
int errtest = WiFi . hostByName ( " metrics " , ipaddr ) ;
Serial . println ( ipaddr . toString ( ) ) ;
Serial . println ( " =======END TEST====== " ) ;
2021-01-19 18:26:06 +02:00
int err = WiFi . hostByName ( mqttHostName , IpMqtt ) ;
if ( err = = 1 )
{
delay ( 50 ) ;
MqttClient . setServer ( IpMqtt , mqttPort ) ;
MqttClient . setCallback ( callback ) ;
2021-02-09 20:29:13 +02:00
Serial . println ( " Set MQTT Server - OK " ) ;
2021-01-19 18:26:06 +02:00
}
else
{
2021-02-09 20:29:13 +02:00
Serial . print ( " Error code hostByName(): " ) ;
2021-01-19 18:26:06 +02:00
Serial . println ( err ) ;
}
}
2021-01-21 17:54:46 +02:00
//Функция получения данных из MQTT если мы подпишемся на топики
2021-01-19 18:26:06 +02:00
void callback ( char * topic , byte * payload , unsigned int length )
{
Serial . print ( " Message arrived [ " ) ;
Serial . print ( topic ) ;
Serial . print ( " ] " ) ;
for ( int i = 0 ; i < length ; i + + )
{
Serial . print ( ( char ) payload [ i ] ) ;
}
Serial . println ( ) ;
2021-01-14 23:27:49 +02:00
}
2021-01-21 17:54:46 +02:00
//Запрос времени NTP и установка локлаьного времени
2021-01-20 21:27:05 +02:00
void reqNtpTime ( )
{
timeClient . update ( ) ;
2021-02-09 20:29:13 +02:00
uint32_t timeEpoch = timeClient . getEpochTime ( ) ;
setTime ( timeEpoch ) ;
Serial . print ( timeEpoch ) ;
Serial . print ( " <=ntp== ==device=> " ) ;
Serial . println ( now ( ) ) ;
if ( timeEpoch < 100000 )
{
errorID = 1 ;
}
2021-01-20 21:27:05 +02:00
}
2021-01-21 17:54:46 +02:00
//Нажатие кнопки для с б р о с а
2021-01-14 23:27:49 +02:00
void checkButton ( )
{
2021-02-09 20:29:13 +02:00
Serial . println ( " Button Pressed to RESET " ) ;
2021-01-21 17:54:46 +02:00
wm . resetSettings ( ) ;
ESP . restart ( ) ;
2021-02-09 20:29:13 +02:00
2021-01-19 18:26:06 +02:00
Serial . println ( " Starting config portal " ) ;
wm . setConfigPortalTimeout ( 120 ) ;
2021-01-14 23:27:49 +02:00
2021-02-09 20:29:13 +02:00
if ( ! wm . startConfigPortal ( " AirQaPortal " , " 12345678 " ) ) //Логин и пароль точки доступа
2021-01-19 18:26:06 +02:00
{
Serial . println ( " failed to connect or hit timeout " ) ;
2021-02-09 20:29:13 +02:00
delay ( 1000 ) ;
2021-01-19 18:26:06 +02:00
// ESP.restart();
}
else
{
2021-02-09 20:29:13 +02:00
Serial . println ( " Clien connected to AP " ) ;
2021-01-14 23:27:49 +02:00
}
}
String getParam ( String name )
{
String value ;
if ( wm . server - > hasArg ( name ) )
{
value = wm . server - > arg ( name ) ;
}
return value ;
}
void saveParamCallback ( )
{
Serial . println ( " [CALLBACK] saveParamCallback fired " ) ;
Serial . println ( " PARAM customfieldid = " + getParam ( " customfieldid " ) ) ;
}
2021-01-21 17:54:46 +02:00
//Обновление прошивки, происходит проверка и загрузка
2021-02-09 20:29:13 +02:00
2021-01-14 23:27:49 +02:00
void OTAUpdate ( )
{
2021-02-09 20:29:13 +02:00
Serial . println ( " OTAUpdate() START " ) ;
2021-01-14 23:27:49 +02:00
bool flagOTA = false ;
String keyOTA ;
String payload ;
OTApreferences . begin ( " ota-config " ) ;
if ( WiFi . status ( ) = = WL_CONNECTED )
2021-01-21 17:54:46 +02:00
{
2021-01-14 23:27:49 +02:00
HTTPClient http ;
2021-01-21 17:54:46 +02:00
String getMacNow = getMacAddress ( ) ;
2021-02-09 20:29:13 +02:00
//const char *clientId = macc.c_str();
2021-01-21 17:54:46 +02:00
String serverPath = " http://meteosence.s-host.net/airqa/airquality.php?meteopas=e93gme9hAt9nSWaV&mac= " + getMacNow + " &meteodata=gethash " ;
2021-02-09 20:29:13 +02:00
Serial . print ( " URL and GET request: " ) ;
Serial . println ( serverPath ) ;
2021-01-14 23:27:49 +02:00
http . begin ( serverPath . c_str ( ) ) ;
int httpResponseCode = http . GET ( ) ;
if ( httpResponseCode > 0 )
{
Serial . print ( " HTTP Response code: " ) ;
Serial . println ( httpResponseCode ) ;
payload = http . getString ( ) ;
2021-02-09 20:29:13 +02:00
Serial . print ( " Data from HTTP request (OTA Hash): " ) ;
Serial . println ( payload ) ;
2021-01-14 23:27:49 +02:00
2021-02-09 20:29:13 +02:00
if ( payload ! = " errno " | | payload ! = " errfi " )
2021-01-14 23:27:49 +02:00
{
2021-02-09 20:29:13 +02:00
keyOTA = OTApreferences . getString ( " md5HashOTA " ) ;
if ( keyOTA . length ( ) < = 0 )
{
OTApreferences . putString ( " md5HashOTA " , " undifined " ) ;
}
2021-01-14 23:27:49 +02:00
2021-02-09 20:29:13 +02:00
Serial . print ( " md5HashOTA in device: " ) ;
keyOTA = OTApreferences . getString ( " md5HashOTA " ) ;
Serial . println ( keyOTA ) ;
2021-01-14 23:27:49 +02:00
2021-02-09 20:29:13 +02:00
if ( payload ! = keyOTA )
{
flagOTA = true ;
OTApreferences . putString ( " md5HashOTA " , payload ) ;
Serial . println ( " flagOTA = true; " ) ;
}
}
else
2021-01-14 23:27:49 +02:00
{
2021-02-09 20:29:13 +02:00
Serial . print ( " Hosting return error: " ) ;
Serial . println ( payload ) ;
errorID = 3 ;
2021-01-14 23:27:49 +02:00
}
}
else
{
2021-02-09 20:29:13 +02:00
Serial . print ( " Error HTTP Response code: " ) ;
2021-01-14 23:27:49 +02:00
Serial . println ( httpResponseCode ) ;
2021-02-09 20:29:13 +02:00
errorID = 2 ;
2021-01-14 23:27:49 +02:00
}
// Free resources
http . end ( ) ;
}
else
{
2021-02-09 20:29:13 +02:00
Serial . println ( " WHY WiFi is Disconnected?? " ) ;
2021-01-14 23:27:49 +02:00
}
if ( flagOTA = = true )
{
flagOTA = false ;
Serial . println ( " flagOTA = false; " ) ;
t_httpUpdate_return ret = ESPhttpUpdate . update ( " http://meteosence.s-host.net/airqa/airatoms.bin " ) ;
2021-02-09 20:29:13 +02:00
2021-01-21 17:54:46 +02:00
//После update ничего не происходит, такая вот особенность.
//Если все прошло хорошо, перезагрузка на новую прошивку
2021-01-14 23:27:49 +02:00
Serial . print ( " ret " ) ;
Serial . println ( ret ) ;
switch ( ret )
{
case HTTP_UPDATE_FAILED :
Serial . printf ( " HTTP_UPDATE_FAILD Error (%d): %s " , ESPhttpUpdate . getLastError ( ) , ESPhttpUpdate . getLastErrorString ( ) . c_str ( ) ) ;
Serial . println ( ESPhttpUpdate . getLastError ( ) ) ;
Serial . println ( ESPhttpUpdate . getLastErrorString ( ) . c_str ( ) ) ;
Serial . println ( " HTTP_UPDATE_FAILD Error " ) ;
delay ( 3000 ) ;
ESP . restart ( ) ;
break ;
case HTTP_UPDATE_NO_UPDATES :
Serial . println ( " HTTP_UPDATE_NO_UPDATES " ) ;
delay ( 3000 ) ;
ESP . restart ( ) ;
break ;
case HTTP_UPDATE_OK :
Serial . println ( " HTTP_UPDATE_OK " ) ;
delay ( 3000 ) ;
ESP . restart ( ) ;
break ;
}
}
OTApreferences . end ( ) ;
}
2021-02-09 20:29:13 +02:00
//Функция для индикации Led
2021-01-19 18:26:06 +02:00
void ledset ( char color , bool blink = false )
{
2021-02-09 20:29:13 +02:00
M5 . dis . setBrightness ( 100 ) ; //Половина яркости
2021-01-19 18:26:06 +02:00
switch ( color )
{
case ' g ' :
M5 . dis . drawpix ( 0 , 0xf00000 ) ; //Зеленый
2021-02-09 20:29:13 +02:00
2021-01-19 18:26:06 +02:00
break ;
case ' r ' :
M5 . dis . drawpix ( 0 , 0x00f000 ) ; //Красный
break ;
case ' b ' :
M5 . dis . drawpix ( 0 , 0x0000f0 ) ; //Синий
break ;
case ' w ' :
M5 . dis . drawpix ( 0 , 0x707070 ) ; //Белый
break ;
default :
M5 . dis . clear ( ) ;
break ;
}
if ( blink = = true )
{ //Таймер для LED
RGBWTicker . attach_ms ( 1000 , ledBlinkTimer ) ;
}
else
{
RGBWTicker . detach ( ) ;
}
}
void ledBlinkTimer ( )
{
2021-02-09 20:29:13 +02:00
2021-01-19 18:26:06 +02:00
if ( flagblink = = true )
{
2021-02-09 20:29:13 +02:00
M5 . dis . setBrightness ( 0 ) ;
2021-01-19 18:26:06 +02:00
M5 . dis . drawpix ( 0 , 0xf00000 ) ;
2021-02-09 20:29:13 +02:00
for ( int b = 0 ; b < = 180 ; b + + )
{
M5 . dis . setBrightness ( b ) ;
delay ( 7 ) ;
}
2021-01-19 18:26:06 +02:00
flagblink = false ;
}
else
{
2021-02-09 20:29:13 +02:00
M5 . dis . setBrightness ( 180 ) ;
M5 . dis . drawpix ( 0 , 0xf00000 ) ;
for ( int b = 180 ; b > = 0 ; b - - )
{
M5 . dis . setBrightness ( b ) ;
delay ( 7 ) ;
}
//M5.dis.clear();
2021-01-19 18:26:06 +02:00
flagblink = true ;
}
}
2021-01-21 17:54:46 +02:00
//Получение мак адреса
2021-01-19 18:26:06 +02:00
String getMacAddress ( )
{
uint8_t baseMac [ 6 ] ;
esp_read_mac ( baseMac , ESP_MAC_WIFI_STA ) ;
char baseMacChr [ 18 ] = { 0 } ;
sprintf ( baseMacChr , " %02X%02X%02X%02X%02X%02X " , baseMac [ 0 ] , baseMac [ 1 ] , baseMac [ 2 ] , baseMac [ 3 ] , baseMac [ 4 ] , baseMac [ 5 ] ) ;
return String ( baseMacChr ) ;
}
2021-01-21 17:54:46 +02:00
//Установка коефициентов калибровки
2021-01-19 18:26:06 +02:00
void SetCallibrationCoeff ( )
{
// Serial.print("Mac: ");
// Serial.println(getMacAddress());
//[24A160474D14, 5002919F5450, 5002918A38CC]
//tcoeff[0,1,2]
//hcoeff[0,1,2]
macc = getMacAddress ( ) ;
if ( macc = = " 24A160474D14 " )
{
callibrationT = tcoeff [ 0 ] ;
callibrationH = hcoeff [ 0 ] ;
}
if ( macc = = " 5002919F5450 " )
{
callibrationT = tcoeff [ 1 ] ;
callibrationH = hcoeff [ 1 ] ;
}
if ( macc = = " 5002918A38CC " )
{
callibrationT = tcoeff [ 2 ] ;
callibrationH = hcoeff [ 2 ] ;
}
}
2021-02-09 20:29:13 +02:00
//Ниже отдельные функции средних арифметических для каждого параместра с историей
2021-01-19 18:26:06 +02:00
float middleArifmT ( float newVal )
2021-01-20 21:27:05 +02:00
{
// Serial.print(newVal);
// Serial.print(" ");
// принимает новое значение
2021-01-19 18:26:06 +02:00
valArrayT [ idxT ] = newVal ; // пишем каждый раз в новую ячейку
2021-01-20 21:27:05 +02:00
// for (int t = 0; t <= 6; t++)
// {
// Serial.print(valArrayT[t]);
// Serial.print(" ");
// }
2021-01-19 18:26:06 +02:00
if ( + + idxT > = NUM_AVER )
idxT = 0 ; // перезаписывая самое старое значение
averageT = 0 ; // обнуляем среднее
for ( int i = 0 ; i < NUM_AVER ; i + + )
{
averageT + = valArrayT [ i ] ; // суммируем
}
averageT / = NUM_AVER ; // делим
2021-01-20 21:27:05 +02:00
// Serial.println(averageT);
return averageT ; // возвращаем
2021-01-19 18:26:06 +02:00
}
float middleArifmH ( float newVal )
{ // принимает новое значение
valArrayH [ idxH ] = newVal ; // пишем каждый раз в новую ячейку
if ( + + idxH > = NUM_AVER )
idxH = 0 ; // перезаписывая самое старое значение
averageH = 0 ; // обнуляем среднее
for ( int i = 0 ; i < NUM_AVER ; i + + )
{
averageH + = valArrayH [ i ] ; // суммируем
}
averageH / = NUM_AVER ; // делим
return averageH ; // возвращаем
}
float middleArifmECO ( float newVal )
{ // принимает новое значение
valArrayECO [ idxECO ] = newVal ; // пишем каждый раз в новую ячейку
if ( + + idxECO > = NUM_AVER )
idxECO = 0 ; // перезаписывая самое старое значение
averageECO = 0 ; // обнуляем среднее
for ( int i = 0 ; i < NUM_AVER ; i + + )
{
averageECO + = valArrayECO [ i ] ; // суммируем
}
averageECO / = NUM_AVER ; // делим
return averageECO ; // возвращаем
}
float middleArifmTVOC ( float newVal )
{ // принимает новое значение
valArrayTVOC [ idxTVOC ] = newVal ; // пишем каждый раз в новую ячейку
if ( + + idxTVOC > = NUM_AVER )
idxTVOC = 0 ; // перезаписывая самое старое значение
averageTVOC = 0 ; // обнуляем среднее
for ( int i = 0 ; i < NUM_AVER ; i + + )
{
averageTVOC + = valArrayTVOC [ i ] ; // суммируем
}
averageTVOC / = NUM_AVER ; // делим
return averageTVOC ; // возвращаем
}
2021-01-21 17:54:46 +02:00
//Запрос данных с датчиков.
2021-01-19 18:26:06 +02:00
void reqSensorData ( )
{
float hdc1080Temp = 0 , hdc1080Hum = 0 ;
int eco2 = 0 , tvoc = 0 ;
if ( ccs . available ( ) )
{
if ( ! ccs . readData ( ) )
{
eco2 = ccs . geteCO2 ( ) ;
tvoc = ccs . getTVOC ( ) ;
}
else
{
eco2 = 0 ;
tvoc = 0 ;
2021-02-09 20:29:13 +02:00
errorID = 4 ;
2021-01-19 18:26:06 +02:00
}
}
2021-02-09 20:29:13 +02:00
else
{
errorID = 5 ;
}
2021-01-19 18:26:06 +02:00
hdc1080Temp = hdc1080 . readTemperature ( ) + callibrationT ;
hdc1080Hum = hdc1080 . readHumidity ( ) + callibrationH ;
2021-02-09 20:29:13 +02:00
if ( hdc1080Temp < - 40 | | hdc1080Temp > 60 ) { errorID = 6 ; }
if ( hdc1080Hum < 0 | | hdc1080Temp > 100 ) { errorID = 7 ; }
// Serial.println("Original data: ");
// Serial.println(hdc1080.readTemperature());
// Serial.println(hdc1080.readHumidity());
// Serial.println("Calibration data: ");
// Serial.print(hdc1080Temp);
// Serial.println(" ");
// Serial.println(hdc1080Hum);
2021-01-20 21:27:05 +02:00
2021-01-19 18:26:06 +02:00
TempAv = middleArifmT ( hdc1080Temp ) ;
HumAv = middleArifmH ( hdc1080Hum ) ;
Eco2Av = middleArifmECO ( eco2 ) ;
TvocAv = middleArifmTVOC ( tvoc ) ;
2021-02-09 20:29:13 +02:00
rssi = WiFi . RSSI ( ) ;
// hall=hallRead();
if ( hdc1080Hum > 50 | | hdc1080Hum < 39 )
{
ledset ( ' r ' , true ) ;
}
if ( hdc1080Temp > 24 | | hdc1080Temp < 19 )
{
ledset ( ' r ' , true ) ;
}
if ( tvoc > 500 )
{
ledset ( ' r ' , true ) ;
}
if ( eco2 > 1000 )
{
ledset ( ' r ' , true ) ;
}
2021-01-19 18:26:06 +02:00
}
2021-01-21 17:54:46 +02:00
//Отправка данных по MQTT
2021-01-19 18:26:06 +02:00
void SendMqttReq ( )
{
2021-02-09 20:29:13 +02:00
//Serial.println("Data in SendMqttReq()");
// Serial.print(TempAv);
// Serial.print(" ");
// Serial.print(HumAv);
// Serial.print(" ");
// Serial.print(Eco2Av);
// Serial.print(" ");
// Serial.println(TvocAv);
2021-01-20 21:27:05 +02:00
2021-01-21 17:54:46 +02:00
char HumidityInt [ 8 ] , TemperatureInt [ 8 ] ;
dtostrf ( TempAv * 100 , 4 , 0 , TemperatureInt ) ;
dtostrf ( HumAv * 100 , 4 , 0 , HumidityInt ) ;
2021-01-20 21:27:05 +02:00
2021-02-09 20:29:13 +02:00
// doc["mac"] = String(getMacAddress());
2021-01-21 17:54:46 +02:00
doc [ " swver " ] = VersionSW ;
doc [ " t " ] = atoi ( TemperatureInt ) ;
doc [ " h " ] = atoi ( HumidityInt ) ;
doc [ " eco " ] = ( int ) Eco2Av ;
doc [ " tvoc " ] = ( int ) TvocAv ;
2021-02-09 20:29:13 +02:00
doc [ " rssi " ] = rssi ;
// doc["hall"]= hall;
doc [ " error " ] = errorID ; //По умолчанию 0
2021-01-21 17:54:46 +02:00
doc [ " time " ] = now ( ) ;
2021-01-19 18:26:06 +02:00
char resultString [ 200 ] ;
String JsonData = " " ;
2021-01-20 21:27:05 +02:00
2021-01-19 18:26:06 +02:00
serializeJson ( doc , JsonData ) ;
Serial . println ( JsonData ) ; //Вывод JSON строки в консоль
JsonData . toCharArray ( resultString , JsonData . length ( ) + 1 ) ;
String finishTopic = " " ;
finishTopic = String ( topicName ) + " / " + macc ;
2021-01-20 21:27:05 +02:00
//Serial.println(finishTopic);
2021-01-19 18:26:06 +02:00
if ( mqttSendFlag = = true )
{
MqttClient . publish ( finishTopic . c_str ( ) , resultString ) ;
2021-01-20 21:27:05 +02:00
//Serial.println("SentToTopic - ok");
2021-02-09 20:29:13 +02:00
errorID = 0 ;
2021-01-19 18:26:06 +02:00
}
}
2021-01-21 17:54:46 +02:00
//Переподключение при петери связи с MQTT
//10 раз проверили и вернулись в общий цикл что бы вдруг что втянуть обновления
2021-01-19 18:26:06 +02:00
void reconnectMqtt ( )
{
2021-01-20 21:27:05 +02:00
2021-01-19 18:26:06 +02:00
//clientId += String(random(0xffff), HEX);
2021-01-20 21:27:05 +02:00
//clientId.c_str()
2021-01-19 18:26:06 +02:00
//MqttClient.connect(macc.c_str(), mqttLogin, mqttPass
2021-01-20 21:27:05 +02:00
byte circle = 0 ;
while ( ! MqttClient . connected ( ) )
2021-01-19 18:26:06 +02:00
{
2021-01-20 21:27:05 +02:00
Serial . print ( " MQTT reconnect... " ) ;
circle + + ;
if ( circle = = 10 )
{
break ;
}
const char * clientId = macc . c_str ( ) ;
//macc += String(random(0xffff), HEX);
if ( MqttClient . connect ( clientId ) )
{
2021-02-09 20:29:13 +02:00
//String finishTopic = "";
// finishTopic = String(topicName) + "/" + macc;
//MqttClient.publish(finishTopic.c_str(), "Reconnect NOW");
Serial . println ( " Reconnect NOW " ) ;
errorID = 8 ;
2021-01-20 21:27:05 +02:00
// client.subscribe("inTopic");
mqttSendFlag = true ;
}
else
{
2021-02-09 20:29:13 +02:00
Serial . print ( " failed с onnect to MQTT, rc= " ) ;
Serial . println ( MqttClient . state ( ) ) ;
2021-01-20 21:27:05 +02:00
mqttSendFlag = false ;
delay ( 1000 ) ;
}
2021-01-19 18:26:06 +02:00
}
}
2021-01-14 23:27:49 +02:00
void loop ( )
{
//Проверка старта сервера
2021-01-19 18:26:06 +02:00
M5 . update ( ) ;
2021-01-20 21:27:05 +02:00
//Если не определен IP то и не будет отправки.
2021-01-19 18:26:06 +02:00
// 40 секунд и происходит с б р о с настроек WIFI
if ( M5 . Btn . wasReleasefor ( 40000 ) )
{
ledset ( ' r ' , true ) ;
checkButton ( ) ;
}
2021-01-21 17:54:46 +02:00
//По таймеру запруск обновления прошивки
2021-01-14 23:27:49 +02:00
if ( millis ( ) - timingUpdate > nextM5Update )
{
2021-01-20 21:27:05 +02:00
reqNtpTime ( ) ;
2021-01-14 23:27:49 +02:00
OTAUpdate ( ) ;
2021-01-19 18:26:06 +02:00
// Serial.print("OTAUpdate() - ");
// Serial.println(millis());
2021-01-14 23:27:49 +02:00
timingUpdate = millis ( ) ;
}
2021-01-19 18:26:06 +02:00
2021-01-21 17:54:46 +02:00
//Таймер запроса данных с датчиков
2021-01-19 18:26:06 +02:00
if ( millis ( ) - timingReqSensor > nextReqSensor )
{
reqSensorData ( ) ;
2021-02-09 20:29:13 +02:00
ledset ( ' b ' , true ) ;
2021-01-19 18:26:06 +02:00
// Serial.print("reqSensorData() - ");
// Serial.println(millis());
timingReqSensor = millis ( ) ;
}
2021-01-21 17:54:46 +02:00
//Таймер отправки данных в брокер
2021-01-19 18:26:06 +02:00
if ( millis ( ) - timingSendMqtt > nextMqttSend )
{
SendMqttReq ( ) ;
2021-02-09 20:29:13 +02:00
ledset ( ' g ' , true ) ;
2021-01-19 18:26:06 +02:00
timingSendMqtt = millis ( ) ;
}
2021-01-20 21:27:05 +02:00
2021-02-09 20:29:13 +02:00
//Тут же проверка подключения к MQTT
2021-01-20 21:27:05 +02:00
if ( ! MqttClient . connected ( ) )
{
reconnectMqtt ( ) ;
2021-02-09 20:29:13 +02:00
ledset ( ' w ' , true ) ;
2021-01-20 21:27:05 +02:00
}
2021-02-09 20:29:13 +02:00
// Serial.println("=============");
// rssi = WiFi.RSSI();
// Serial.println(rssi);
// Serial.println("=============");
2021-01-20 21:27:05 +02:00
MqttClient . loop ( ) ;
2021-01-19 18:26:06 +02:00
}