ESP8266WebServer.h Не Выводить страницу в HTML
В меня плата NodeMCU. По Всем традициях начинающих программировать под ESP8266 пишу свою метеостанцию. Хочу чтобы когда модуль при неудачном подключении к интернету (неправильный пароль или имя точки доступа) переходил в режим точки доступа и запускал WebServer. В отдельности сама метеостанция и WebServer работают прекрасно. Но когда все объединяю в один скетч сам WebServer запускается но в браузере страница не появляется. Такое впечатление что не выдерживает само железо. При компиляции ресурсом скетч занимает относительно немного. RAM: [=== ] 35.0% (used 28640 bytes from 81920 bytes), Flash: [==== ] 40.7% (used 424676 bytes from 1044464 bytes). Помогите разобраться. Текс скетча в файле main.txt
#include <NTPClient.h>
#include <LiquidCrystal_I2C.h>
#include <WiFiUdp.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <WiFiClientSecureBearSSL.h>
#include <ArduinoJson.h>
#include <SPI.h>
IPAddress My_AP_IP(192,168,4,1); // Адреса точки доступа
ESP8266WebServer My_HTTP_Server(80); // Web интерфейс для устройства
LiquidCrystal_I2C lcd(0x27, 16, 2); // Парамеетри lcd 1602 екрана (адреса екрана, кількість символів в рядку, кількість рядків)
# define ss_id "One_Home" // Імя точки доступу до вайфай
# define password_id "1ljcneg1" // Пароль точки доступу до вайфай
# define _ssidAP "WiFi"
// String _ssidAP = "WiFi"; // SSID AP точки доступа
# define _passwordAP ""
//String _passwordAP = ""; // пароль точки доступа
# define b_host "https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5"
//const char* b_host = "https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5"; //адреса сайта з якого беруться дани курсу валют
# define host "api.openweathermap.org"
//const char* host = "api.openweathermap.org"; //Адреса сайта з якого беруться дані про погоду
# define PERIOD 3600000
//const unsigned long PERIOD = 3600000; // Період з яким буде запускатись фукція My_timer_setup() - 30хв
WiFiUDP ntpUDP;
// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
# define Server_time "europe.pool.ntp.org"
NTPClient timeClient(ntpUDP, Server_time, 7200, 60000); //Сервер часу з зміщення по часу +2 год (7200)
String json_valuta;
String json_pogoda;
void My_date_time(); // Функція виводу реального часу і дати на екран з інтернету (з NTP сервера - europe.pool.ntp.org)
void My_valuta_json(); // Функція зєднання з сервером і отримання даних курс валют в форматі json
void My_valut_lcd(); // функція виводу курсів валют взятих з інтернету (з сайту приват банка) на екран монітора LCD
void My_pogoda_json(); // Функція зєднання з сервером і отримання даних про погоду з інтернету в форматі json
void My_pogoda_lcd(); // Функція виводу погоди на екран монітора LCD
void My_timer_setup(); // Функція яка буде запускати дві попередні функції (My_valuta_json(), My_pogoda_json()) через певний проміжок часу
void My_WIFIinit(); //Функція ініціалізації і спроба підєднатись до вказаної точки доступу Wifi
bool My_StartAPMode(); //Функція ініціалізації і запуск модуля esp8266 в режимі точки доступа
void My_HTTP_init(); //Функція ініціалізації і запуск HTTP (запуск web server)
void My_handleRoot(); //Функція Відображеення головної сторінки
void setup() {
lcd.init(); //инициализация LCD (подготовка к работе)
lcd.backlight(); // Підсвітка LCD дисплея
Serial.begin(115200); //инициализация та швидкість серійного порта (подготовка к работе)
Serial.println(F(""));
Serial.println(F("Start 1-WIFI"));
//My_WIFIinit(); //Функція ініціалізації і спроба підєднатись до вказаної точки доступу Wifi
//My_HTTP_init(); //Запускаем Web server
My_handleRoot();
//WiFi.begin(_ssid, _password); //Підєднання до інтернету через WiFi роутер
//while ( WiFi.status() != WL_CONNECTED ) {
// delay ( 500 );
// Serial.print ( "." );
//}
timeClient.begin();
}
void loop() {
My_HTTP_Server.handleClient();
My_timer_setup(); // Функція яка буде запускати дві попередні функції (My_valuta_json(), My_pogoda_json()) через певний проміжок часу
//lcd.clear();
My_date_time(); // Функція виводу реального часу і дати на екран з інтернету (з NTP сервера - europe.pool.ntp.org)
delay(5000);
//lcd.clear();
My_pogoda_lcd(); // Функція виводу погоди на екран монітора LCD
delay(5000);
//lcd.clear();
My_valut_lcd(); // функція виводу курсів валют взятих з інтернету (з сайту приват банка) на екран монітора LCD
delay(5000);
//lcd.clear();
}
void My_WIFIinit(String &_ssid, String &_password) { //Функція ініціалізації і спроба підєднатись до вказаної точки доступу Wifi
// Спроба підключитись до точки доступу
WiFi.mode(WIFI_STA);
byte tries = 11;
WiFi.begin(_ssid.c_str(), _password.c_str());
//WiFi.begin(_ssid, _password);
while (--tries && WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(1000);
}
if (WiFi.status() != WL_CONNECTED)
{
// Если не удалось подключиться запускаем в режиме AP
Serial.println(F(""));
Serial.println(F("WiFi up AP"));
My_StartAPMode(); //Функція ініціалізації і запуск модуля esp8266 в режимі точки доступа
Serial.println(F("Start 2-WebServer"));
My_HTTP_init(); //Запускаем Web server
}
else {
Serial.println(F(""));
Serial.println(F("WiFi connected"));
Serial.println(F("IP address: "));
Serial.println(WiFi.localIP());
My_pogoda_json(); // Функція зєднання з сервером і отримання даних про погоду з інтернету в форматі json
My_valuta_json(); // Функція зєднання з сервером і отримання даних курс валют в форматі json
}
}
bool My_StartAPMode() //Функція ініціалізації і запуск модуля esp8266 в режимі точки доступа
{
WiFi.disconnect();
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(My_AP_IP, My_AP_IP, IPAddress(255, 255, 255, 0));
WiFi.softAP(_ssidAP, _passwordAP);
//WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str());
return true;
}
void My_HTTP_init() { //Функція ініціалізації і запуск HTTP (запуск web server)
My_HTTP_Server.on(F("/"), My_handleRoot); // Главная страница http://192.168.4.1/
// Запускаем HTTP сервер
My_HTTP_Server.begin();
}
void My_handleRoot() { //Функція ака перекидає з головної сторінки на сторінку введення даних
String _ssid = ss_id; // Імя точки доступу до вайфай
String _password = password_id; // Пароль точки доступу до вайфай
if(My_HTTP_Server.hasArg(F("MY_SSID")) && My_HTTP_Server.hasArg(F("PASSWORD"))){
String my_ssid;
String my_password;
my_ssid = My_HTTP_Server.arg (F("MY_SSID"));
my_password = My_HTTP_Server.arg (F("PASSWORD"));
Serial.println();
Serial.println(F("ID Wifi: "));
Serial.print (my_ssid);
Serial.println(F("Pass WIFI: "));
Serial.print (my_password) ;
My_WIFIinit(my_ssid, my_password);
}
else
{
My_WIFIinit(_ssid, _password);
}
String content = F("<html><body><form action='/' method='POST'>Please enter your hotspot name and password to connect to the Internet<br>");
content += F("User:<input type='text' name='MY_SSID' placeholder='user name'><br>");
content += F("Password:<input type='password' name='PASSWORD' placeholder='password'><br>");
content += F("<input type='submit' name='SUBMIT' value='Connect'></form>" "<br></body></html>");
My_HTTP_Server.send(200, F("text/html"), content);
//HTTP.stop();
//Serial.println("Stop HTTP WebServer");
//My_HTTP_Server.send(200, "text/plain", "hello from esp8266!");
}
void My_date_time() // Функція виводу реального часу і дати на екран з інтернету (з NTP сервера - europe.pool.ntp.org)
{
const String arr_days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; // Дні тижня
unsigned long times =0;
if (millis() - times >= 1000) {
times = millis();
//Serial.println("millis: " + millis());
//Serial.println();
//Serial.println("times: " + times);
while (!timeClient.update()) {
timeClient.forceUpdate();
}
//timeClient.update();
String date_time = timeClient.getFormattedDate();
int index_date = date_time.indexOf(F("T"));
String date = date_time.substring(0, index_date);
Serial.println(date);
Serial.println();
int day = timeClient.getDay();
Serial.println(F("'"));
Serial.print(arr_days[day]);
Serial.print(F("'"));
Serial.print(F(", "));
Serial.println(timeClient.getFormattedTime());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("DATE: "));
lcd.print(date);
lcd.setCursor(9, 1);
lcd.print(arr_days[day]);
lcd.setCursor(0, 1);
lcd.print(timeClient.getFormattedTime());
//delay(1000);
}
}
void My_valuta_json() { // Функція зєднання з сеервером і отримання даних в форматі json курс валют
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
client->setInsecure();
HTTPClient https;
if (https.begin(*client, b_host)) {
Serial.println(F("[HTTPS] GET..."));
int httpCode = https.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
//Serial.print(F("[HTTPS] GET... code: %d\n"));
//Serial.print(httpCode);
// file found at server?
if (httpCode == HTTP_CODE_OK) {
json_valuta = https.getString();
Serial.println(F("vivod: "));
Serial.print(json_valuta);
My_valut_lcd(); // Запуск функції розбору даних отриманих з сервера в форматі json
}
} else {
Serial.print(F("[HTTPS] GET... failed, error: %s\n\r"));
Serial.print(https.errorToString(httpCode).c_str());
}
https.end();
} else {
Serial.print(F("[HTTPS] Unable to connect\n\r"));
}
}
void My_valut_lcd() { // Функція розбору даних отриманих з сервера в форматі json
////////////// Парсимо обєкт даних отриманий з сервера та виводимо дані в масив
StaticJsonBuffer<2000> jsonBuffer;
JsonArray& root = jsonBuffer.parseArray(json_valuta);
// Test if parsing succeeds.
if (!root.success()) {
Serial.println(F("parseObject() failed"));
return;
}
Serial.print(F("rozmir masuva: "));
Serial.println(root.size());
Serial.print(F("kilkist sumvolis v massuvi: "));
Serial.println(root.measureLength());
Serial.println();
root.printTo(Serial);
//Serial.println();
//Розподіляємо обект root на окремі масиви
String value0 = root.get<String>(0);
Serial.println(F("value0: "));
Serial.print(value0);
String value1 = root.get<String>(1);
Serial.println(F("value1: "));
Serial.print(value1);
//////////////// Парсимо перший окремий масив (дані про курс долара) та виводимо дані в послідовни порт
JsonObject& v_USD = jsonBuffer.parseObject(value0);
if (!root.success()) {
Serial.println(F("parseObject() failed valuta USD"));
return;
}
String ccy_USD = v_USD[F("ccy")];
String base_ccy_USD = v_USD[F("base_ccy")];
float buy_USD = v_USD[F("buy")];
String st_buy_USD = String(buy_USD, 2);
float sale_USD = v_USD[F("sale")];
String st_sale_USD = String(sale_USD, 2);
Serial.print(F("Kod valuty: "));
Serial.println(ccy_USD);
Serial.print(F("Kod nacionalnoyi valuty: "));
Serial.println(base_ccy_USD);
Serial.print(F("Kurs kupivli: "));
Serial.println(String(buy_USD, 2));
Serial.print(F("Kurs prodagu: "));
Serial.println(String(sale_USD, 2));
///////////////////////////////////////////////////////////////////
////////////////// Парсимо другий окремий масив (дані про курс долара) та виводимо дані в послідовни порт //////
JsonObject& v_EUR = jsonBuffer.parseObject(value1);
if (!root.success()) {
Serial.println(F("parseObject() failed valuta EUR"));
return;
}
String ccy_EUR = v_EUR[F("ccy")];
String base_ccy_EUR = v_EUR[F("base_ccy")];
float buy_EUR = v_EUR[F("buy")];
String st_buy_EUR = String(buy_EUR, 2);
float sale_EUR = v_EUR[F("sale")];
String st_sale_EUR = String(sale_EUR, 2);
Serial.print(F("Kod valuty: "));
Serial.println(ccy_EUR);
Serial.print(F("Kod nacionalnoyi valuty: "));
Serial.println(base_ccy_EUR);
Serial.print(F("Kurs kupivli: "));
Serial.println(String(buy_EUR, 2));
Serial.print(F("Kurs prodagu: "));
Serial.println(String(sale_EUR, 2));
///////////////////////////////////////////////////////////////////
///////////////////Вивід на lcd дисплей 1602 /////////////////////////////// Початок
byte s_evro[] = { // Малюємо символ євро для відобажння на екрані lcd 1602
B01110,
B10001,
B11100,
B10000,
B11100,
B10001,
B01110,
B00000
};
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("$K-"));
lcd.print(st_buy_USD);
lcd.print(F( "|P-"));
lcd.print(st_sale_USD);
lcd.createChar(0, s_evro);
lcd.setCursor(0, 1);
lcd.print(char(0));
lcd.setCursor(1, 1);
lcd.print(F("K-"));
lcd.print(st_buy_EUR);
lcd.print(F("|P-"));
lcd.print(st_sale_EUR);
}
void My_pogoda_json() { // Функція зєднання з сервером і отримання даних про погоду з інтернету в форматі json
// Use WiFiClient class to create TCP connections
WiFiClient client;
const byte httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println(F("connection failed"));
return;
}
client.println(F("GET /data/2.5/weather?id=707471&appid=6a4ba421859c9f4166697758b68d889b HTTP/1.1"));
client.println(F("Host: api.openweathermap.org"));
client.println(F("Connection: close"));
client.println();
delay(1500);
// Read all the lines of the reply from server and print them to Serial
while (client.available()) {
json_pogoda = client.readStringUntil('\r');
}
Serial.print(json_pogoda);
Serial.println();
Serial.println(F("closing connection"));
My_pogoda_lcd();
}
void My_pogoda_lcd() // Функція виводу погоди на екран монітора LCD
{
byte c_gradus[] = { // Малюємо символ градуса цельсія для відобажння на екрані lcd 1602 температури
B01100,
B10010,
B10010,
B01100,
B00000,
B00000,
B00000,
B00000,
};
StaticJsonBuffer<2000> jsonBuffer; /// буфер на 2000 символов
JsonObject& root = jsonBuffer.parseObject(json_pogoda); // скармиваем String
if (!root.success()) {
Serial.println(F("parseObject() failed")); // если ошибка, сообщаем об этом
//My_pogoda(); // пинаем сервер еще раз
return; // и запускаем заного
}
/// отправка в Serial
//Serial.println();
String name = root[F("name")]; // достаем имя,
Serial.print(F("name:"));
Serial.println(name);
float tempK = root[F("main")][F("temp")]; // достаем температуру из структуры main
float tempC = tempK - 273.15; // переводим кельвины в цельси
Serial.print(F("temp: "));
Serial.print(tempC); // отправляем значение в сериал
Serial.println(F(" C"));
/*
float tempKmin = root[F("main")][F("temp_min")]; // и так далее
float tempCmin = tempKmin - 273.15;
Serial.print(F("temp min: "));
Serial.print(tempCmin);
Serial.println(F(" C"));
float tempKmax = root[F("main")][F("temp_max")];
float tempCmax = tempKmax - 273.15;
Serial.print(F("temp max: "));
Serial.print(tempCmax);
Serial.println(F(" C"));
int pressurehPa = root[F("main")][F("pressure")];
float pressure = pressurehPa / 1.333;
Serial.print(F("pressure: "));
Serial.print(pressure);
Serial.println(F(" mmHc"));
int humidity = root[F("main")][F("humidity")];
Serial.print(F("humidity: "));
Serial.print(humidity);
Serial.println(F(" %"));
*/
float windspeed = root[F("wind")][F("speed")];
Serial.print(F("wind speed: "));
Serial.print(windspeed);
Serial.println(F(" m/s"));
//int winddeg = root[F("wind")][F("deg")];
//Serial.print(F("wind deg :"));
//Serial.println(winddeg);
//Serial.println();
//Serial.println();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(name);
lcd.setCursor(0, 1);
lcd.print(F("t:"));
lcd.print(tempC, 1);
lcd.createChar(1, c_gradus);
lcd.setCursor(7, 1);
lcd.print(char(1));
lcd.setCursor(8, 1);
lcd.print(F("w_s:"));
lcd.print(windspeed, 0);
lcd.print(F("m/s"));
}
void My_timer_setup()
{
unsigned long timer = 0;
if (millis() - timer >= PERIOD) {
// ваше действие
My_valuta_json();
My_pogoda_json();
Serial.println(F("ВІДБУВСЯ ПЕРЕЗАПУСК ФУНКЦІЙ І ОБНОВИЛИСЯ ДАНІ З ІНТЕРНЕТУ"));
do {
timer += PERIOD;
if (timer < PERIOD) break; // переполнение uint32_t
} while (timer < millis() - PERIOD); // защита от пропуска шага
}
}