Kod wygląda tak:
Code: Select all
/*
Copyright (C) AC SOFTWARE SP. Z O.O.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define SUPLA_COMM_DEBUG //Zakomentuj tą linię by wyłączyć DEBUGOWANIE
#include <SPI.h>
#include <SuplaDevice.h> //https://github.com/SUPLA/arduino/tree/develop
#include <ArduinoJson.h> //Benonit Blanchot 6.14.0
#include <EEPROM.h>
#include <supla/control/relay.h>
#include "supla/sensor/therm_hygro_press_meter.h"
#include <supla/sensor/general_purpose_measurement.h>
#include <supla/network/html_element.h>
#include <supla/network/web_sender.h>
#include <supla/storage/config.h>
#include <supla/storage/storage.h>
#include <supla/storage/littlefs_config.h>
#include <string.h>
#include <supla/network/html/protocol_parameters.h>
#include <supla/device/supla_ca_cert.h>
#include <supla/network/esp_wifi.h>
Supla::LittleFsConfig configSupla;
//******************************************************************WIFI SETUP************************************************************************************************
Supla::ESPWifi wifi;
//*****************************************************************SUPLA SETUP************************************************************************************************
//*****************************************************************AIRLY SETUP************************************************************************************************
String lat = "51.00000"; //Swoją lokalizację można pobrać z https://mapy.google.pl klikajac na swoj dom. Na dole ekranu pojawią się współrzędne
String lon = "16.00000";
String distance = "5.0"; //Określamy promień od naszej lokalizacji, gdzie AIRLY będzie szukać najbliższego nam czujnika
String apiKey = "jfhjkfhjgdfjvhfhcvhgf"; //api key dostajemy po zalozeniu konta na https://developer.airly.eu/api
//Dla PM1 nie liczy się stężenia w %, każda wartość jest groźna!
#define norma_WHO_PM25 25 //Norma PM2.5 wg. WHO
#define norma_WHO_PM10 50 //Norma PM10 wg. WHO
Supla::Sensor::GeneralPurposeMeasurement *gpm1 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm2 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm3 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm4 = nullptr;
int timer = 0;
float current_PM1_value = 0;
float current_PM25_value = 0;
float current_PM10_value = 0;
float procent_PM25_value = 0;
float procent_PM10_value = 0;
float current_PRESSURE_value = 0;
float current_HUMIDITY_value = 0;
float current_TEMPERATURE_value = 0;
float current_CAQI_value = 0;
float current_WIND_value = 0;
float CAQI_old = 0;
String city_ = "";
String street_ = "";
String number_ = "";
String Device_name = "";
String Device_name_old = "";
String zmienna = "Airly";
byte r_new = 0;
byte g_new = 0;
byte b_new = 0;
byte r = 0;
byte g = 0;
byte b = 0;
byte Led_max = 0;
byte Led_max_old = 0;
byte licz_sprawdzenie_adresu_stacji = 0;
class odczyt_temp_wilg : public Supla::Sensor::ThermHygroPressMeter {
public :
double getTemp() {
return temperatura;
}
double getHumi() {
return wilgotnosc;
}
double getPressure() {
return cisnienie;
}
void setTemp(double val) {
temperatura = val;
}
void setHumi(double val) {
wilgotnosc = val;
}
void setPressure(double val){
cisnienie = val;
}
void onInit() {
pressureChannel.setNewValue(getPressure());
channel.setNewValue(getTemp(), getHumi());
}
void iterateAlways() override {
if (millis() - lastReadTime > 5000) {
lastReadTime = millis();
pressureChannel.setNewValue(getPressure());
channel.setNewValue(getTemp(), getHumi());
}
}
protected:
double temperatura;
double wilgotnosc;
double cisnienie;
double value;
uint64_t lastReadTime = 0;
};
odczyt_temp_wilg *czujniczek = nullptr;
//****************************************************************************************************************************************************************************
void setup() {
// Replace the falowing GUID with value that you can retrieve from https://www.supla.org/arduino/get-guid
char GUID[SUPLA_GUID_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// Replace the following AUTHKEY with value that you can retrieve from: https://www.supla.org/arduino/get-authkey
char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//auto r1 = new Supla::Control::Relay(12);
czujniczek = new odczyt_temp_wilg();
Serial.begin(115200);
Serial.println(" ");
//Odczytaj_zakres_eeprom(100, 200);
Device_name = zmienna.c_str();
Serial.print("Set device name to: ");
Serial.println(Device_name);
SuplaDevice.setName(Device_name.c_str());
Device_name_old = Device_name;
// cfg->setDeviceConfigChangeFlag();
auto cfg = Supla::Storage::ConfigInstance();
if (cfg)
{
char buf[100];
if (!cfg->getGUID(buf))
{
Serial.println("[Main] setting config.");
// PODMIEN SOBIE NA RZECZYWISTE WARTOSCI
const char serverVariable[] = "twoj.server.srv";
const char emailVariable[] = "twój mail";
const char wifiSSID[] = "Twój SSID";
const char wifiPass[] = "Hasło do Twojego wifi";
cfg->setGUID(GUID);
cfg->setAuthKey(AUTHKEY);
cfg->setWiFiSSID(wifiSSID);
cfg->setWiFiPassword(wifiPass);
cfg->setSuplaServer(serverVariable);
cfg->setEmail(emailVariable);
}
else
{
Serial.println("[Main] Can load guid.");
}
}
else
{
Serial.println("[Main] Config not found.");
}
gpm1 = new Supla::Sensor::GeneralPurposeMeasurement();
gpm2 = new Supla::Sensor::GeneralPurposeMeasurement();
gpm3 = new Supla::Sensor::GeneralPurposeMeasurement();
gpm4 = new Supla::Sensor::GeneralPurposeMeasurement();
// Default channel config values are initialized only once. They can be
// modified later, but they won't change corresponding used configurable
// parameters.
// Below lines are optional, just remove them if you don't want to set
// them.
gpm1->setDefaultUnitBeforeValue("PM1");
gpm1->setDefaultUnitAfterValue("μg/m³");
gpm1->setDefaultValuePrecision(2); // 0..4 - number of decimal places
gpm1->getChannel()->setDefaultIcon(16);
gpm1->setValue(0);
gpm2->setDefaultUnitBeforeValue("PM2,5");
gpm2->setDefaultUnitAfterValue("μg/m³");
gpm2->setDefaultValuePrecision(2); // 0..4 - number of decimal places
gpm2->getChannel()->setDefaultIcon(17);
gpm2->setValue(0);
gpm3->setDefaultUnitBeforeValue("PM10");
gpm3->setDefaultUnitAfterValue("μg/m³");
gpm3->setDefaultValuePrecision(2); // 0..4 - number of decimal places
gpm3->getChannel()->setDefaultIcon(18);
gpm3->setValue(0);
gpm4->setDefaultUnitBeforeValue("CAQI");
gpm4->setDefaultValuePrecision(2); // 0..4 - number of decimal places
gpm4->getChannel()->setDefaultIcon(8);
gpm4->setValue(0);
//gpm1->saveConfig();
SuplaDevice.setSuplaCACert(suplaCACert);
SuplaDevice.setSupla3rdPartyCACert(supla3rdCACert);
SuplaDevice.begin();
/*(GUID, // Global Unique Identifier
SERVER_SUPLA, // SUPLA server address
Email_adres, // Email address used to login to Supla Cloud
AUTHKEY); // Authorization key
*/
}
//****************************************************************************************************************************************************************************
void loop() {
SuplaDevice.iterate();
++timer;
if(timer == 10000){
++licz_sprawdzenie_adresu_stacji;
if(licz_sprawdzenie_adresu_stacji==1){
Odczytaj_ulice_z_Airly();
Device_name = "";
Device_name = "Airly: " + city_ + " " + street_ + " " + number_;
}
if(licz_sprawdzenie_adresu_stacji==100){
licz_sprawdzenie_adresu_stacji==0;
}
Odczytaj_dane_z_Airly();
}
if(timer >= 180000){ //Dane z serwera pobierane są co około 180 sekund. Limit dzienny zapytań dla serwera AIRLY wynosi 1000 zapytań.
//AIRLY sugeruje odpytywać serwer nieczęśniej niż co 90 sekund
timer = 0;
}
delay(1);
}
//****************************************************************************************************************************************************************************
double get_pressure(int channelNumber, double last_val) {
double pressure= 0;
pressure = current_PRESSURE_value;
return pressure;
}
void Odczytaj_dane_z_Airly(){
ESP.wdtFeed();
const char* host= "airapi.airly.eu";
const int httpPort = 443;
String url = "/v2/measurements/nearest?lat=" + lat + "&lng=" + lon + "&maxDistanceKM=" + distance;
char json[1024] = {};
bool begin = false;
begin = false; WiFiClientSecure client; client.setInsecure();
if (!client.connect(host, httpPort)) {
Serial.println("Blad polaczenia z ");Serial.print(host);return;
}else{
Serial.println("Polaczono z airly");
client.print("GET " + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: ESP8266\r\n" +
"Accept: application/json\r\n" +
"apikey: " + apiKey + "\r\n" +
"Connection: close\r\n\r\n");
byte licz_znak = 0; int licz_znaki = 0; char c = 0; int index = 0; memset(&json[0], 0, sizeof(json));delay(500);
for (licz_znaki = 0; licz_znaki < 30000; ++licz_znaki) {
ESP.wdtFeed();
delay(1);
c = client.read();
if (c == '{') {
begin = true;
}
if(begin) {
json[index] = c;index++;
}
if (c == ']') {
++licz_znak;
if(licz_znak == 2){ //Szukamy drugiego znaku ] który pojawi się w transmisji i ją przerywamy, potem są już tylko dane historyczne wysylane przez serwer
json[index] = 125;index++; //Dodaje znak }
json[index] = 125;index++; //Dodaje znak } i kończe odbieranie reszty danych. Udaje w ten sposób że transmisja była znacznie krótsza niż w rzeczywistości
goto Koniec;
}
}
}
Koniec:
client.stop();
Serial.println("Koniec polaczenia");
Serial.println(json);
DynamicJsonDocument doc(1024); DeserializationError error = deserializeJson(doc, json); if (error) return;
JsonObject current = doc["current"];
JsonArray current_values = current["values"];
Serial.println(" ");
current_PM1_value = current_values[0]["value"];
Serial.print("PM1: ");
Serial.print(current_PM1_value);
Serial.println("ug/m3");
current_PM25_value = current_values[1]["value"];
procent_PM25_value = current_PM25_value * 100 / norma_WHO_PM25;
Serial.print("PM25: ");
Serial.print(current_PM25_value);
Serial.print("ug/m3 ");
Serial.print(procent_PM25_value);
Serial.println("%");
current_PM10_value = current_values[2]["value"];
procent_PM10_value = current_PM10_value * 100 / norma_WHO_PM10;
Serial.print("PM10: ");
Serial.print(current_PM10_value);
Serial.print("ug/m3 ");
Serial.print(procent_PM10_value);
Serial.println("%");
current_PRESSURE_value = current_values[3]["value"];
Serial.print("PRESSURE: ");
Serial.print(current_PRESSURE_value);
Serial.println("hPa");
current_HUMIDITY_value = current_values[4]["value"];
Serial.print("HUMIDITY: ");
Serial.print(current_HUMIDITY_value);
Serial.println("%");
current_TEMPERATURE_value = current_values[5]["value"];
Serial.print("TEMPERATURE: ");
Serial.print(current_TEMPERATURE_value);
Serial.println("*C");
current_values = current["indexes"];
current_CAQI_value = current_values[0]["value"];
Serial.print("CAQI: ");
Serial.print(current_CAQI_value);
Serial.println(" ");
czujniczek->setTemp(current_TEMPERATURE_value);
czujniczek->setHumi(current_HUMIDITY_value);
czujniczek->setPressure(current_PRESSURE_value);
gpm1->setValue(current_PM1_value);
gpm2->setValue(current_PM25_value);
gpm3->setValue(current_PM10_value);
gpm4->setValue(current_CAQI_value);
}
return;
}
void Odczytaj_ulice_z_Airly(){
ESP.wdtFeed();
const char* host= "airapi.airly.eu";
const int httpPort = 443;
String url = "/v2/installations/nearest?lat=" + lat + "&lng=" + lon + "&maxDistanceKM=" + distance; + "&maxResult=1";
char json[1024] = {};
bool begin = false;
begin = false; WiFiClientSecure client; client.setInsecure();
if (!client.connect(host, httpPort)) {
Serial.println("Blad polaczenia z ");Serial.print(host);return;
}else{
Serial.println("Polaczono z airly");
client.print("GET " + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: ESP8266\r\n" +
"Accept: application/json\r\n" +
"apikey: " + apiKey + "\r\n" +
"Connection: close\r\n\r\n");
byte licz_znak = 0; int licz_znaki = 0; char c = 0; int index = 0; memset(&json[0], 0, sizeof(json));delay(500);
//while (client.available()) {
for (licz_znaki = 0; licz_znaki < 30000; ++licz_znaki) {
ESP.wdtFeed();
delay(1);
c = client.read();
if (c == '{') {
begin = true;
}
if(begin){
json[index] = c;index++;
}
if (c == '}') {
++licz_znak;
if(licz_znak == 4){ //Szukamy czwartego znaku ] który pojawi się w transmisji i ją przerywamy
goto Koniec;
}
}
}
Koniec:
client.stop();
Serial.println("Koniec polaczenia");
Serial.println(json);
DynamicJsonDocument doc(1024); DeserializationError error = deserializeJson(doc, json); if (error) return;
Serial.println(" ");
String city = doc["address"]["city"];
String street = doc["address"]["street"];
String number = doc["address"]["number"];
city_ = city;
street_ = street;
number_ = number;
Serial.print(city_);Serial.print(" ");Serial.print(street_);Serial.print(" ");Serial.println(number_);
Serial.println(" ");
}
}