Mоnk
Member
Долго "сидел" на 2.4.2, потому что бинарники, скомпилированные в следующих за ядром 2.4.2 итерациях, через WebUpdate во флеш китайских "умных" розеток не влезали. Не лезет 483к в ESP8285, который к тому же 1Мх128К. Пользуюсь до сих пор IotManager версии 1.5.5, причем без json. Ну нравится мне, и все тут.
Однако все течет, все изменяется. Решил "прикрутить" ТелеграммБот, и понеслось... Бот от Гайвера с BearSSL заработал начиная с 2.5.0. Мелочится не стал, накатил 3.0.2. Бинарник на простом градуснике с часами по рассчета ArduinoIDE получился размером 54%, что и следовало ожидать.
Первое, что перестало работать, ESP8266 sketch data upload. Google изрядно потупел за последние годы, поэтому поиск решения занял немалое время с установкой Питона и другими ненужными танцами. Случайно наткнуля на ссылку https://github.com/esp8266/arduino-esp8266fs-plugin/releases, снес все лишнее, закинул папку ESP8266FS пятой версии сюда => C:\Program Files (x86)\Arduino\tools, и загрузка SPIFFS по кабелю заработала.
Дальше. Почему-то перестали прилетать push уведомления от onesignal.com. Понятно почему (теперь). Потому что теперь после "WiFiClientSecure push_client;" надо добавить "push_client.setInsecure();".
Самое обидное - при обращении к BME280 еспэшка уходила в ребут.
Пройдемся еще раз по тупому Гуглю. Задаём вопрос "esp8266 bme280 без библиотеки", и получаем список ответов типа "...необходимо две библиотеки", "...необходимо установить две специальных библиотеки", "...библиотека под bme280". "Точное соответствие" - по барабану. Тупая американская скотина, одним словом.
Не то, что бы я не любил чужие библиотеки. Просто когда пишешь код сам, понимаешь, как это работает.
Ларчик открывался просто. Накосячил с типом переменной. А Ардуйня все туже затягивает гайки в плане строгого соответствия спецификации языка.
Кабель конечно хорошо, но хочется как и раньше менять прошивки в гараже, в деревне, дома наконец с работы. Что я и делал, пока недобитые фашисты не отключили TeamViewer. Эту проблему я конечно решу. (Решил. Раскопал в недрах своей фалопомойки R-Admin. Конечно не настолько удобно теперь, но работает.) А пока хотя бы WebUpdate в пределах квартиры.
На просторах интернета увидел интересный вопрос возмущенного пользователя, дословно "почему сжатый gzip bin-SPIFFS разворачивается по воздуху пустым"? Та-ак! Идущий да обрящет! Специалисты в один голос утверждают, "должен быть #define ATOMIC_FS_UPDATE", собственно поиски которого приводят на https://arduino-esp8266.readthedocs.io/en/3.0.2/ota_updates/readme.html#compression. Бинго? Фиг вам!
Надо сначала чтобы в устройстве была прошивка с этим ATOMIC_FS_UPDATE! А появилась эта фича только в 2.6.0.
Ну что-же, поехали...
Идея проста. Делаем чистую WebUpdate прошивку с ATOMIC_FS_UPDATE в 3.0.2, заливаем бинарник (смешные 301к) "по воздуху" в устройство, компилим нормальную прошивку для устройства в 3.0.2, сжимаем в gzip 9-м уровнем (максимально), заливаем архив "по воздуху" в устройство.
Ура? Не-а! "Толстый слой шоколада" в виде огромного количества Стрингов (надо же было так назвать "много букв"!) кушает весьма много "оперативки". И несколько проектов даже имея 21К свободного heap отказались посылать push, и уходили в ребут. Чертов SSL!
Лезем опять в Гугль, смотрим, как народ борется с нехваткой памяти. Находим чудесные вещи с лаконичным названием PSTR() и F(), и начинаем их применять.
Память резко освобождается до 32К+. Push начинает работать. Можно продолжать развлекаться.
Однако все течет, все изменяется. Решил "прикрутить" ТелеграммБот, и понеслось... Бот от Гайвера с BearSSL заработал начиная с 2.5.0. Мелочится не стал, накатил 3.0.2. Бинарник на простом градуснике с часами по рассчета ArduinoIDE получился размером 54%, что и следовало ожидать.
Первое, что перестало работать, ESP8266 sketch data upload. Google изрядно потупел за последние годы, поэтому поиск решения занял немалое время с установкой Питона и другими ненужными танцами. Случайно наткнуля на ссылку https://github.com/esp8266/arduino-esp8266fs-plugin/releases, снес все лишнее, закинул папку ESP8266FS пятой версии сюда => C:\Program Files (x86)\Arduino\tools, и загрузка SPIFFS по кабелю заработала.
Дальше. Почему-то перестали прилетать push уведомления от onesignal.com. Понятно почему (теперь). Потому что теперь после "WiFiClientSecure push_client;" надо добавить "push_client.setInsecure();".
C++:
// ================================= Push notifications ==================================
void push(String push_msg)
{
if (WiFi.status() == WL_CONNECTED) // если подключились
{
WiFiClientSecure push_client;
[B]push_client.setInsecure();[/B]
if (!push_client.connect("onesignal.com", 443)) return;
String push_data = F("{\"app_id\": \"8871958c-5f52-11e5-8f7a-c36f5770ade9\",\"include_player_ids\":[\"") + ids + F("\"],\"android_group\":\"IoT Manager\",\"contents\": {\"en\": \"") + push_msg + "\"}}";
push_client.println("POST /api/v1/notifications HTTP/1.1");
push_client.print("Host:");
push_client.println("onesignal.com");
push_client.println("User-Agent: esp8266.Arduino.IoTmanager");
push_client.print("Content-Length: ");
push_client.println(push_data.length());
push_client.println("Content-Type: application/json");
push_client.println("Connection: close");
push_client.println();
push_client.println(push_data);
}
}
// ================================= End Push notifications ==================================
Пройдемся еще раз по тупому Гуглю. Задаём вопрос "esp8266 bme280 без библиотеки", и получаем список ответов типа "...необходимо две библиотеки", "...необходимо установить две специальных библиотеки", "...библиотека под bme280". "Точное соответствие" - по барабану. Тупая американская скотина, одним словом.
Не то, что бы я не любил чужие библиотеки. Просто когда пишешь код сам, понимаешь, как это работает.
Ларчик открывался просто. Накосячил с типом переменной. А Ардуйня все туже затягивает гайки в плане строгого соответствия спецификации языка.
Кабель конечно хорошо, но хочется как и раньше менять прошивки в гараже, в деревне, дома наконец с работы. Что я и делал, пока недобитые фашисты не отключили TeamViewer. Эту проблему я конечно решу. (Решил. Раскопал в недрах своей фалопомойки R-Admin. Конечно не настолько удобно теперь, но работает.) А пока хотя бы WebUpdate в пределах квартиры.
На просторах интернета увидел интересный вопрос возмущенного пользователя, дословно "почему сжатый gzip bin-SPIFFS разворачивается по воздуху пустым"? Та-ак! Идущий да обрящет! Специалисты в один голос утверждают, "должен быть #define ATOMIC_FS_UPDATE", собственно поиски которого приводят на https://arduino-esp8266.readthedocs.io/en/3.0.2/ota_updates/readme.html#compression. Бинго? Фиг вам!
Надо сначала чтобы в устройстве была прошивка с этим ATOMIC_FS_UPDATE! А появилась эта фича только в 2.6.0.
Ну что-же, поехали...
Идея проста. Делаем чистую WebUpdate прошивку с ATOMIC_FS_UPDATE в 3.0.2, заливаем бинарник (смешные 301к) "по воздуху" в устройство, компилим нормальную прошивку для устройства в 3.0.2, сжимаем в gzip 9-м уровнем (максимально), заливаем архив "по воздуху" в устройство.
C++:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#define ATOMIC_FS_UPDATE //---------- Возможность прошить сжатым бинарником
const char* ssid = "Роутер";
const char* password = "Пароль_ВиФи";
const char* ssidAP = "WebUpdate";
const char* passwordAP = "Пароль_ТочкиДоступа_есп";
ESP8266WebServer server(80);
const char* serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";
IPAddress ip(192,168,1,96); IPAddress gateway(192,168,1,1); IPAddress subnet(255,255,255,0); // ориентируясь на свой роутер
void setup(void)
{
WiFi.mode(WIFI_AP_STA);
WiFi.setAutoConnect(false);
WiFi.setAutoReconnect(true);
WiFi.config(ip, gateway, subnet, ip);
WiFi.begin(ssid, password);
int ii = 80;
while (WiFi.status() != WL_CONNECTED && ii){delay(100); ii--;}
if (WiFi.status() != WL_CONNECTED) WiFi.mode(WIFI_AP); // если не подключились
WiFi.softAP(ssidAP, passwordAP);
server.on("/", HTTP_GET, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/html", serverIndex);
});
server.on("/update", HTTP_POST, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
delay(1000);
ESP.restart();
},[](){
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START)
{
WiFiUDP::stopAll();
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if(!Update.begin(maxSketchSpace)) //start with max available size
{Update.printError(Serial);}
}
else if(upload.status == UPLOAD_FILE_WRITE)
{
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize)
{Update.printError(Serial);}
}
else if(upload.status == UPLOAD_FILE_END)
{
if(Update.end(true)) //true to set the size to the current progress
{ }
else
{Update.printError(Serial);}
}
yield();
});
server.begin();
}
void loop(void)
{
server.handleClient();
delay(1);
}
Лезем опять в Гугль, смотрим, как народ борется с нехваткой памяти. Находим чудесные вещи с лаконичным названием PSTR() и F(), и начинаем их применять.
C++:
//------- Обновлялка. Грузилка. Запасной вариант. -------------
server.on("/refit", HTTP_GET, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
const char * serverIndex = PSTR("<html><head><meta charset=utf-8><title>Обновлялка</title>\
<style>body {background-color: #cccccc; font-size: 16pt; Color: #ff0000;}</style></head><body>\
<P>Обновлялка.</P><form method='POST' action='/update' enctype='multipart/form-data'>\
<input type='file' name='update'><input type='submit' value='Прошить'></form>\
<P>SPIFFS Upload</P><form method='POST' action='/edit' enctype='multipart/form-data'>\
<input type='file' name='data'><input class='button' type='submit' value='Upload'></form></body></html>");
server.send(200, "text/html", serverIndex);
});
или
void Tun_ing()
{
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
String tHTML = F("<!DOCTYPE html><html lang=ru><head><meta charset=\"utf-8\"><title>Tuning.</title><style>body {background-color: #cccccc; font-size: 16pt; font-family: arial;}</style></head><body><form method=\"post\" action=\"/tunsave\"><input required id=\"pI\" name=\"_pageId\" maxlength=\"2\" placeholder=\"порядковый номер\" value=\"");
tHTML += String(pageId);
tHTML += F("\"><br><input required id=\"dN\" name=\"_devName\" maxlength=\"10\" placeholder=\"имя в IoTmanager\" value=\"") + devName;
tHTML += F("\"><br><input required id=\"dI\" name=\"_deviceId\" maxlength=\"24\" placeholder=\"идентификатор устройства\" value=\"") + deviceId;
tHTML += F("\"><br><input required id=\"pg\" name=\"_page\" maxlength=\"10\" placeholder=\"закладка в IoTmanager\" value=\"") + page;
...
...