Arduino Mega Server для ESP32

Модератор: Alex

serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Arduino Mega Server для ESP32

Сообщение serghei » Пт май 04, 2018 8:23 pm

Alex писал(а):
Вс июн 18, 2017 5:38 pm
Arduino Mega Server для ESP32 с SD картой памяти..
... поскольку в драйверах не реализован сервер и обновление прошивки по воздуху, то этого функционала нет и в АМС
Уже есть. Реализовано:

1. Загрузка файлов по воздуху
2. Обновление прошивки по воздуху
3. Редактирование страниц в браузере с сохранением результата " на лету" без перезагрузки сервера

В скетч добавляем вкладку HTTP с текстом
СпойлерПоказать

Код: Выделить всё

/*
  Modul HTTP for ESP_32
  part of Arduino Mega Server project

*/

#ifdef HTTP_FEATURE

#include "WebServer.h"
#include "Update.h"

#define HTTP_PORT 8080
WebServer HTTP(HTTP_PORT);

File fsUploadFile;

String getContentType(String filename){
  if(HTTP.hasArg("download")) return "application/octet-stream";
  else if(filename.endsWith(".htm")) return "text/html";
  else if(filename.endsWith(".html")) return "text/html";

  else if(filename.endsWith(".css")) return "text/css";
  else if(filename.endsWith(".csv")) return "text/plain";
  else if(filename.endsWith(".cfg")) return "text/plain";
  else if(filename.endsWith(".js")) return "application/javascript";
  else if(filename.endsWith(".png")) return "image/png";
  else if(filename.endsWith(".gif")) return "image/gif";
  else if(filename.endsWith(".jpg")) return "image/jpeg";
  else if(filename.endsWith(".ico")) return "image/x-icon";
  else if(filename.endsWith(".xml")) return "text/xml";
  else if(filename.endsWith(".pdf")) return "application/x-pdf";
  else if(filename.endsWith(".zip")) return "application/x-zip";
  else if(filename.endsWith(".gz")) return "application/x-gzip";
  return "text/plain";
}

bool handleFileRead(String path){
  Serial.println("handleFileRead: " + path);
  if(path.endsWith("/")) path += "index.htm";
  String contentType = getContentType(path);
  String pathWithGz = path + ".gz";
  if(SD.exists(pathWithGz) || SD.exists(path)){
    if(SD.exists(pathWithGz)) 
      path += ".gz";
    File file = SD.open(path, "r");
    HTTP.streamFile(file, contentType);
    file.close();
    return true;
  }
  return false;
}

void handleFileUpload() {
  if(HTTP.uri() != "/edit") return;
  HTTPUpload& upload = HTTP.upload();
  if(upload.status == UPLOAD_FILE_START){
    String filename = upload.filename;
    if(!filename.startsWith("/")) filename = "/"+filename;
    fsUploadFile = SD.open(filename, "w");
    filename = String();
  } else if(upload.status == UPLOAD_FILE_WRITE){
    if(fsUploadFile)
      fsUploadFile.write(upload.buf, upload.currentSize);
  } else if(upload.status == UPLOAD_FILE_END){
    if(fsUploadFile)
      fsUploadFile.close();
  }
} // handleFileUpload()

void handleFileDelete() {
  if(HTTP.args() == 0) return HTTP.send(500, "text/plain", "BAD ARGS");
  String path = HTTP.arg(0);
  if(path == "/")
    return HTTP.send(500, "text/plain", "BAD PATH");
  if(!SD.exists(path))
    return HTTP.send(404, "text/plain", "FileNotFound");
  SD.remove(path);
  HTTP.send(200, "text/plain", "");
  path = String();
} // handleFileDelete()

void handleFileCreate() {
  if(HTTP.args() == 0)
    return HTTP.send(500, "text/plain", "BAD ARGS");
  String path = HTTP.arg(0);
  if(path == "/")
    return HTTP.send(500, "text/plain", "BAD PATH");
  if(SD.exists(path))
    return HTTP.send(500, "text/plain", "FILE EXISTS");
  File file = SD.open(path, "w");
  if(file)
    file.close();
  else
    return HTTP.send(500, "text/plain", "CREATE FAILED");
  HTTP.send(200, "text/plain", "");
  path = String();
} // handleFileCreate();

void handleFileList() {
  if(!HTTP.hasArg("dir")) {HTTP.send(500, "text/plain", "BAD ARGS"); return;}
  String path = HTTP.arg("dir");
  if(path != "/" && !SD.exists((char *)path.c_str())) {HTTP.send(500, "text/plain", "BAD PATH"); return;}
  File dir = SD.open((char *)path.c_str());
  path = String();
  if(!dir.isDirectory()){
    dir.close();
    HTTP.send(500, "text/plain", "BAD DIR");
    return;
  }
  dir.rewindDirectory();
  HTTP.setContentLength(CONTENT_LENGTH_UNKNOWN);
  HTTP.send(200, "text/json", "");

  HTTP.sendContent("[");
  for (int cnt = 0; true; ++cnt) {
    File entry = dir.openNextFile();
    if (!entry)
    break;

    String output;
    if (cnt > 0)
    output = ',';
    output += "{\"type\":\"";
    output += (entry.isDirectory()) ? "dir" : "file";
    output += "\",\"name\":\"";
    output += String(entry.name()).substring(1);
    output += "\"";
    output += "}";
    HTTP.sendContent(output);
    entry.close();
    Serial.println(output);//============== вывод в сериал
 }
 HTTP.sendContent("]");
 dir.close();
} // handleFileList()


String Fail = "<!DOCTYPE html><html><head><meta http-equiv='Content-type' content='text/html; charset=utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'></head><style>body{background:#FFA07A;}</style><body><h3>Firmware update:</h3><h2>&emsp;&ensp;FAIL</h2><h3>&ensp;&ensp;Restart ESP</h3></body></html>";

String Ok = "<!DOCTYPE html><html><head><meta http-equiv='Content-type' content='text/html; charset=utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'><meta http-equiv='refresh' content='15;update.htm'></head><style>body{background:#E0EEE0;}</style><body><h3>Firmware update:</h3><h2>&emsp;&ensp;OK!</h2></body></html>";
void updateInit() {
  HTTP.on("/update", HTTP_POST, [](){
  HTTP.sendHeader("Connection", "close");
  HTTP.send(200, "text/html", (Update.hasError()) ? Fail : Ok);
  delay(500);//=================================
  ESP.restart();
  },[](){
    HTTPUpload& upload = HTTP.upload();
    if(upload.status == UPLOAD_FILE_START){
      uint32_t maxSketchSpace = 0x140000;
      if(!Update.begin(maxSketchSpace)){
        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)){
        Serial.printf("Update Success: %u B\nDownload time: %d sec.\nRebooting...\n", upload.totalSize);
      } else {
        Update.printError(Serial);
      }
    }
    yield();
  });
} // updateInit()

void initHttp() {
  HTTP.on("/list", HTTP_GET, handleFileList);
  HTTP.on("/edit", HTTP_GET, []() { if (!handleFileRead("edit.htm")) HTTP.send(404, "text/plain", "FileNotFound"); });
  HTTP.on("/edit", HTTP_PUT, handleFileCreate);
  HTTP.on("/edit", HTTP_DELETE, handleFileDelete);
  HTTP.on("/edit", HTTP_POST, []() { HTTP.send(200, "text/plain", ""); }, handleFileUpload);
  HTTP.onNotFound([]() { if (!handleFileRead(HTTP.uri())) HTTP.send(404, "text/plain", "FileNotFound"); });

  updateInit();
  HTTP.begin();
  timeStamp();
  printValue("HTTP port", String(HTTP_PORT));
  moduleHTTP = ENABLE;
  started(F("Http"), true);
} // initHttp()

void httpWork() {
  HTTP.handleClient();
}

#endif // HTTP_FEATURE 
Не забываем про инициализацию
СпойлерПоказать

Код: Выделить всё

#define HTTP_FEATURE
----------------------------
byte moduleHTTP      = NOT_COMPILLED;
----------------------------
  #ifdef HTTP_FEATURE
    initHttp();
  #endif
  --------------------------
    #ifdef HTTP_FEATURE
     httpWork();
    #endif
    -------------------------

На карту памяти добавляем файлы ( с заменой)
Вложение SD_edit.zip больше недоступно
Необходимая библиотека
SD_edit.zip
(181.09 КБ) 137 скачиваний
Работа с обновлением по воздуху ничем не отличается от подобного c ESP8266.
За это сообщение автора serghei поблагодарил:
Andrey64 (Ср май 09, 2018 3:23 pm)
Рейтинг: 1.16%
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Arduino Mega Server для ESP32

Сообщение serghei » Пт май 04, 2018 8:46 pm

Проверяем в монитор-порту ,что новый модуль стартанул
СпойлерПоказать
  • Module SD...
    Init: OK
    Type: SDSC
    Size: 942 MB
    Check: ........................................
    .........
    Files: 495
    Total: 13436222 B
    Empty: 3
    Index: found
    ===========
    Module NTP...
    Server: 37.247.53.178
    Port: 123
    ===========
    Module Time...
    Provider: network
    NTP request: OK
    ===========
    2018-05-04 19:44:56 Module Server... started
    2018-05-04 19:44:56 Module Upload... started
    2018-05-04 19:44:56 Module Send... started
    2018-05-04 19:44:56 2018-05-04 19:44:56 Found 4 devices
    2018-05-04 19:44:57 #0: 40 26 27 42 7 0 0 151 tempSTR
    2018-05-04 19:44:57 #1: 40 67 255 28 7 0 0 171 tempHOM
    2018-05-04 19:44:57 #2: 40 239 16 29 7 0 0 176 tempWRM
    2018-05-04 19:44:57 #3: 29 187 48 10 0 0 0 163 tempB2
    2018-05-04 19:44:57 Module Temp... started
    2018-05-04 19:44:57 Module Keys... started
    2018-05-04 19:44:57 Module DHT... started
    2018-05-04 19:44:57 Module BME... started
    2018-05-04 19:44:57 Module Electro... started
    2018-05-04 19:44:57 Module TLog... started
    2018-05-04 19:44:57 HTTP port: 8080 // порт 8080
    2018-05-04 19:44:57 Module Http... started // старт модуля
    GLOBAL Init DONE (34s)

    AMS WORK
    2018-05-04 19:44:57 : 112064 (39%) 112064
    2018-05-04 19:44:57 tempSTR: 22.62
    2018-05-04 19:44:57 tempHOM: 33.38
    2018-05-04 19:44:57 tempWRM: 36.00
    2018-05-04 19:44:57 tempB2: ID problem or not present

    *** workCount ***
    2018-05-04 19:44:57 count1: (0)39017.11 (1)19558.94
    2018-05-04 19:44:58 count2: (0)39017.11 (1)19558.94
    2018-05-04 19:44:58 count3: (0)39017.11 (1)19558.94
    2018-05-04 19:44:58 count4: (0)39017.11 (1)19558.94
    2018-05-04 19:44:58 count5: (0)39017.11 (1)19558.94
    *** workCount ***
Открываем страницу IP:8080/edit.htm и видим картину
СпойлерПоказать
Вложение Editor.jpg больше недоступно
Для загрузки прошивки - IP:8080/update.htm Выбираем предварительно скомпилированый .bin файл и жмем волшебную кнопку
СпойлерПоказать
Вложение Update.jpg больше недоступно
После успешной загрузки увидим картинку
СпойлерПоказать
Editor.jpg
Editor.jpg (352.25 КБ) 3789 просмотров
Замечания после суток теста. Так как библиотека молодая , наблюдается сильная задержка при загрузке файлов.
Файл 160 000 КБ закачался за неполные 5 часов. Жертв нет.
Остался вопрос - что проверялось? Похоже моя WiFi сеть тоже.
Вывод : файл неограниченного в пределах разумного размера можно смело грузить "по воздуху" - то есть прошивать.
Прошивка за 30 секунд.

В результате экспериментов кто то поломал файловую систему на карте - была FAT16 , стала FAT. При этом карта виделась и работала , а файлы не сохранялись.Пришлось переформатировать.
НЕ РАБОТАЕТ С ХРОМОМ! Винда 10. Пользуйтесь FF.

PS Код придумал НЕ я ! Я только озвучиваю !!!!

PSS Ну вот НЕ правильно работает форум - теряются вложения. Это вообще тихий ужос !!! куда делись картинки??????
За это сообщение автора serghei поблагодарил:
Andrey64 (Вс июл 08, 2018 12:50 pm)
Рейтинг: 1.16%
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Arduino Mega Server для ESP32

Сообщение serghei » Пт май 04, 2018 8:51 pm

Вложения
СпойлерПоказать
EDIT.jpg
EDIT.jpg (269.1 КБ) 3786 просмотров
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Arduino Mega Server для ESP32

Сообщение serghei » Пт май 04, 2018 8:52 pm

Еще
СпойлерПоказать
32_update.jpg
32_update.jpg (104.97 КБ) 3785 просмотров
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Arduino Mega Server для ESP32

Сообщение serghei » Пт май 04, 2018 9:40 pm

Не , ну это не серьёзно! Файлы на карту. Добавить с заменой файла.
SD_edit.zip
(181.09 КБ) 149 скачиваний
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Arduino Mega Server для ESP32

Сообщение serghei » Пт май 04, 2018 9:43 pm

Библиотека сервера
WebServer.zip
(315.91 КБ) 145 скачиваний
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Arduino Mega Server для ESP32

Сообщение serghei » Сб июн 16, 2018 12:10 am

Alex писал(а):
Пн июн 11, 2018 8:18 am
У вас уже много полезных наработок — было бы неплохо, если бы вы их оформляли в виде статей тут или даже на своём сайте.
Сайта у меня нет , к сожалению. Всё, чего я достиг за два года въезжания в тему AMS - это благодаря пяти великим программистам на этом форуме , без преувеличения.
Но не ожЫданно столкнулся с проблемой на ESP32 - подключил Мажерика на Апельсине ( привет Alexsis_76..............)
Мега , Дуя и ESP8266 влетели без проблем. ESP32 стала отправлять Гет запросы сама себе........ То есть к Алисе конектится , А в модуле "Send" наблюдаю картину маслом ))

Код: Выделить всё

void sendHttpRequest(byte ip[], int port, WiFiClient cl) {
  String s = "";
  if (cl.connect(ip, port)) { 
    timeStamp();
    Serial.print(F("Host "));
    //Serial.print(stringIp(SELF_IP));// вставляет свой IP и Алиса его НЕ видит !!
    Serial.print(stringIp(MAJOR_IP));// Заменил и всё ОК-еюшки ))
    Serial.print(F(" "));
    Serial.println(buf);
    
    s += String(buf);
    s += '\n';
    s += "Host: ";
   // s += stringIp(SELF_IP);

     s += stringIp(MAJOR_IP);// тут тоже самое
    s += '\n';
    cl.println(s); 
    delay(100);
    cl.stop();
  } else {
      timeStamp();
      Serial.print(F("Host "));
     // Serial.print(stringIp(SELF_IP));// а так отправляет сама себе !!!!!

      Serial.print(stringIp(MAJOR_IP));// и тута то же
      Serial.print(F(" not connected ("));
      Serial.print(buf);
      Serial.println(F(")"));
    }
}
Но это еще пол-беды. На Апельсине с последним образом от Immortal не захотела нормально работать ( то есть свойство V = 1 в упор не видит ) . Вспомнил про древние версии МД и о ч Ю до! - Всё взлетело с полпинка! ( правда это на винде ))

С учетом всех предыдущих мыслей я теперь в диком шоке. Это что бы достигнуть уровня AMS-Pro надо ещё сильно попотеть!
СпойлерПоказать
ESP32.jpg
ESP32.jpg (190.73 КБ) 3489 просмотров
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
alexsis_76
Сообщения: 791
Зарегистрирован: Пт янв 22, 2016 10:08 am
Благодарил (а): 6 раз
Поблагодарили: 63 раза

Re: Arduino Mega Server для ESP32

Сообщение alexsis_76 » Чт июн 21, 2018 9:03 am

serghei тебе удалось добиться двухядерности?
serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Arduino Mega Server для ESP32

Сообщение serghei » Чт июн 21, 2018 11:49 am

У меня конкретно это реализовано только в Веб-радио. Но звуковой процессор запустил только на 8266. Плату пришлось всю перепаивать. К 32 пока не подключал.
Вообще по правильному весь AMS для ESP32 надо переписывать для работы с RTOS. Единственную правильную реализацию под мою плату видел только у Olmoro ( он и автор платы )). Посмотри его сайт.
У меня получилось от туда забрать только реконнект к сети. Критерием правильного кода будет отсутствие вкладки Таймеры. А сама структура скетча - это ОДНА вкладка .ino и куча хедеров. Начало выглядит так
СпойлерПоказать

Код: Выделить всё

/*
 * U32maxi
 * Ol.Moro
 * 2018.05.10
 * IDE: ARDUINO 1.8.5  
 * Arduino core for the ESP32 09.03.2018 https://github.com/espressif/arduino-esp32
 * Complete Project Details http://randomnerdtutorials.com
 * http://microsin.net/programming/arm/freertos-part1.html
 */

#include "pcb.h"            // Choose pcb here
#include "server.h"
#include "temp.h"
#include "fsm.h"
#include "irms.h"

#include <WiFi.h>

// Replace with your network credentials
const char* ssid     = "************";
const char* password = "********";


int fire = 1;        // X5-2


void setup()
{    
  // initialize serial port
  Serial.begin(115200); 

  // initialize temp sensors
  initTemp();
  initFsm();
  initFsm();
//  initServer();

  // initialize tasks
  xTaskCreate( initServTask,  "InitServer",  5000, NULL, 1, NULL );
  xTaskCreate( servTask,      "Server",     10000, NULL, 1, NULL );
  xTaskCreate( tempTask,      "Dallas",      5000, NULL, 1, NULL );
  xTaskCreate( fsmTask,       "FSM Test",    5000, NULL, 1, NULL );
  xTaskCreate( irmsTask,      "Irms",        5000, NULL, 1, NULL );
  xTaskCreate( reconnectTask, "Reconnect",   5000, NULL, 1, NULL );
}

void loop()
{
  fire = checkFire();
  vTaskDelay( 200 / portTICK_PERIOD_MS );
}

void servTask( void * parameter )
{
  while(1)
  {
    workServer();
    vTaskDelay( 50 / portTICK_PERIOD_MS );
  }
  vTaskDelete( NULL );
}

void tempTask( void * parameter )
{
  while(1)
  {
    workTemp();
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); 
  }
  vTaskDelete( NULL );
}

void fsmTask( void * parameter )
{
  while(1)
  {
    workFsm();
  }
  vTaskDelete( NULL );
}

void irmsTask( void * parameter )
{
  while(1)
  {
    workIrms();                
    vTaskDelay( 500 / portTICK_PERIOD_MS ); 
  }
  vTaskDelete(NULL);
}

void reconnectTask( void * parameter )
{
  while(1)
  {
    if (WiFi.status() != WL_CONNECTED ) 
    {
      WiFi.reconnect();
    }
    vTaskDelay( 30000 / portTICK_PERIOD_MS ); 
  }
  vTaskDelete(NULL);
}

void initServTask( void * parameter )
{
  while(1)
  {
    initServer();                
    vTaskDelay( 5000 / portTICK_PERIOD_MS ); 
  }
  vTaskDelete(NULL);
}

И уже после этого можно замахнуться на двухядерность. В моём понимании на одном ядре работает сервер , а на другом все датчики. А может я и не прав.
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
alexsis_76
Сообщения: 791
Зарегистрирован: Пт янв 22, 2016 10:08 am
Благодарил (а): 6 раз
Поблагодарили: 63 раза

Re: Arduino Mega Server для ESP32

Сообщение alexsis_76 » Чт июн 21, 2018 12:07 pm

тут применение нашлось для его двухъядерности.
Ответить