GyverPortal

gorlanovmax

✩✩✩✩✩✩✩
26 Окт 2022
69
6
@AlexGyver,
Я прочитал, т.е. на текущий момент, реализовать вывод информации о обновлении невозможно, без организации перехода на отдельную страницу
 

gorlanovmax

✩✩✩✩✩✩✩
26 Окт 2022
69
6
@AlexGyver,
А сейчас редирект получается идет на GPota_update
В этом наверное "собака порылась"

Просто на 3.2 у меня после обновления перекидывало на страницу с результатами
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
@gorlanovmax,
А сейчас редирект получается идет на GPota_update
это url, по которому осуществляется POST запрос с файлом, как и было раньше

Просто на 3.2 у меня после обновления перекидывало на страницу с результатами
@gorlanovmax,
Мы считали что это баг и его исправили =) Сейчас если обновление инициируется с компонента ОТА апдейт - редирект идёт на эту же страницу. Если со страницы /ota_update - то остаётся там же и показывает статус
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
я сделал вывод ошибки обновления в любое удобное место, появится в v3.4
1668439602379.png
 

gorlanovmax

✩✩✩✩✩✩✩
26 Окт 2022
69
6
Заметил следующий баг.
При реализации реальной многостраничности и включении в блок навигационных ссылок страницы OTA
После перехода на страницу ota_update, кнопка с адресом ota_update не становится черной
1668447335809.png
1668447477051.png
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
Это не баг, /ota_update зарезервирован и обрабатывается другой лямбда-функцией. Можно подключить свой ота-билдер и настроить вывод об окончании прошивки или ошибке на свой вкусч см. класс customOTAupdate
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
@gorlanovmax, нету. Надо создать функцию вида void f(bool UpdateEnd, const String& UpdateError),и подключить её в portal.OTA.attachUpdateBuild(f). И в ней сделать разметку под обновление, как в файле customota строка ~124 функция defBuild
 

gorlanovmax

✩✩✩✩✩✩✩
26 Окт 2022
69
6
Надо создать функцию вида void f(bool UpdateEnd, const String& UpdateError)
Сделал, подключил. Но текущая страница в навигационных ссылках все равно не выделяется

C++:
void setup() {
  portal.attachBuild(build);
  portal.attach(action);
  portal.uploadAuto(true); //автоматическая загрузка
  portal.enableOTA();
  portal.OTA.attachUpdateBuild(customBuild);
  portal.start();
}

void customBuild(bool UpdateEnd, const String& UpdateError) {
    GP.BUILD_BEGIN_FILE(600);
    GP.THEME_FILE(F("GP_DARK"));

    GP.UPDATE("string_serial,string_version", 500); // прописываем перечень компонентов, которые должны обновляться, и период обновления в мс
    GP.BOX_BEGIN();
    GP.IMAGE("/gp_data/logo.png", "20%");
    GP.TITLE(GP_NAME); // заголовок страницы
    GP.BOX_END();
    GP.NAV_TABS_LINKS("/,/manual,/ota_update", "Настройки,Скачать,Обновление");

        GP.BLOCK_TAB_BEGIN(F("Обновление программного обеспечения"));
        if (!UpdateEnd) {
            GP.OTA_FIRMWARE(F("Обновить прошивку"), true);
            GP.OTA_FILESYSTEM(F("Обновить файлы"), true);
        } else if (UpdateError.length()) {
            GP.LABEL(String(F("<b>Ошибка обновления:</b><br>")));
            GP.BOLD(UpdateError);
            GP.BUTTON_MINI_LINK(F("/ota_update"), F("Вернуться"));
        } else {
            GP.LABEL(F("<b>Обновление выполнено!<br>Перезагрузка...</b>"));
           GP.BUTTON_MINI_LINK(F("/"), F("К настройкам..."));
        }
    GP.BLOCK_END();
   
    GP.BUILD_END();
}
 

gorlanovmax

✩✩✩✩✩✩✩
26 Окт 2022
69
6
@AlexGyver,

Спасибо, победил

Если для кого-то понадобится, могу сделать пример в библиотеку

В билде основной страницы:
void build() {
  GP.BUILD_BEGIN_FILE(600);
  GP.THEME_FILE("GP_DARK");

  GP.TITLE("Тест кастомной страницы результата обновления"); // заголовок страницы

  GP.NAV_TABS_LINKS("/,/update", "Главная,Обновление");

  //Блок Главная
  if (portal.uri("/")) {
  GP.BLOCK_BEGIN(GP_TAB, "100%", "Настройки устройства");
    GP.BOLD("Здесь можно настроить ESP32");
  GP.BLOCK_END();

  //Блок Обновление
  } else if (portal.uri("/update")) {
  GP.BLOCK_BEGIN(GP_TAB, "100%", F("Обновление программного обеспечения"));
      GP.OTA_FIRMWARE(F("Обновить прошивку"), true);
      GP.OTA_FILESYSTEM(F("Обновить файлы"), true);
  GP.BLOCK_END();
    
  GP.BLOCK_BEGIN(GP_TAB, "100%", "Перезагрузка устройства");
    GP.BUTTON_MINI("restart","Перезагрузить"); //, "", PSTR("#6ecced"), "", false, false
  GP.BLOCK_END();

  GP.BUILD_END();
}
В setup():
void setup() {
  portal.attachBuild(build);
  portal.attach(action);
  portal.uploadAuto(true); //автоматическая загрузка
  portal.enableOTA();
  portal.OTA.attachUpdateBuild(customBuild);
  portal.start();
}
Добавляем кастомную страницу на которую перейдет ESP после попытки обновления:
void customBuild(bool UpdateEnd, const String& UpdateError) {
  GP.BUILD_BEGIN_FILE(600);
  GP.THEME_FILE(F("GP_DARK"));

  GP.TITLE("Тест кастомной страницы результата обновления"); // заголовок страницы
  GP.NAV_TABS_LINKS("/,/update", "Главная,Обновление");
        
  GP.BLOCK_BEGIN(GP_TAB, "100%", F("Обновление программного обеспечения"));
    if (!UpdateEnd) {
      GP.OTA_FIRMWARE(F("Обновить прошивку"), true);
      GP.OTA_FILESYSTEM(F("Обновить файлы"), true);
    } else if (UpdateError.length()) {
      GP.LABEL(String(F("<b>Ошибка обновления:</b><br>")));
      GP.BOLD(UpdateError);
      GP.BUTTON_MINI_LINK(F("/update"), F("Вернуться"));
    } else {
      GP.LABEL(F("<b>Обновление выполнено!<br>Перезагрузка...</b>"));
      GP.BUTTON_MINI_LINK(F("/"), F("К настройкам..."));
    }
  GP.BLOCK_END();
    
  GP.BLOCK_BEGIN(GP_TAB, "100%", "Перезагрузка устройства");
    GP.BUTTON_MINI("restart","Перезагрузить"); //, "", PSTR("#6ecced"), "", false, false
  GP.BLOCK_END();

  GP.BUILD_END();
}
Единственный нюанс, что после обновления, мы попадаем на страницу с результатам обновления (из функции customBuild).
И на этой странице все равно кнопка в навигационных ссылках не выделяется
 
Изменено:

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
Ой, оставь это. В 3.4 будет возможность вывести результат обновления в любое место, например рядом с кнопкой
 

Samoswall

✩✩✩✩✩✩✩
16 Ноя 2022
6
2
Всем привет!
Помогите, ни как не въеду как сделать!
Что вместо GP.SEND() надо использовать, чтобы было имя и лишние теги не вставлялись?

C++:
void build() {
  String ss1;
  ss1 = "<div class='battery' style='--charge: ";
  ss1 += bat_lvl;
  ss1 += ";'><span/></div>";
  GP.BUILD_BEGIN(600);
  GP.THEME(GP_LIGHT);
  GP.UPDATE("test_led,mdate,mtime,ss1");
  GP.NAV_TABS("Главная,Настройки,Тест");
  GP.NAV_BLOCK_BEGIN();
    GP.BLOCK_BEGIN(GP_TAB,"","Инфо");
      GP.BOX_BEGIN();
        GP.LABEL("00:00:00", "mtime");
        GP.LABEL("00.00.00", "mdate");
      GP.BOX_END();
      GP.HR();
      GP.BOX_BEGIN();
        GP.LABEL("Заряд АКБ");
        GP.SEND(ss1);
      GP.BOX_END();
    GP.BLOCK_END();
  GP.NAV_BLOCK_END();
GP.BUILD_END();
}

void action() {
  if (portal.update()) {
     String valDate=ntp.dateString();
     String valTime=ntp.timeString();
     portal.updateString("mdate", valDate);
     portal.updateString("mtime", valTime);
     Как тут прописать обновление переменной в style своего кода?
     }
}
 
Изменено:

gorlanovmax

✩✩✩✩✩✩✩
26 Окт 2022
69
6
@AlexGyver,
:geek: Ну уже сделал.
Выйдет 3.4 переделаем.
Здесь еще вопрос в том, что в каждой новой версии, добавляется функций.
Соответственно потихоньку растер размер библиотеки, а если доп. функции не нужны, зачем занимать больше места на ESP?
 

Сергей Эл

✩✩✩✩✩✩✩
17 Ноя 2022
7
1
Привет, умные люди. Подскажите, пожалуйста, каким способом в Портале можно выводить одиночные значения на экран. Например нужно постоянно показывать ток или температуру. Окно лога или график не очень хорошо подходят.
 
  • Лойс +1
Реакции: tatum

gorlanovmax

✩✩✩✩✩✩✩
26 Окт 2022
69
6
Вот так например:

В конструкторе страницы:
C++:
  GP.UPDATE("current_temp", 500);

  GP.BLOCK_BEGIN(GP_TAB, "100%", "Текущая температура с датчика");
    GP.LABEL_BLOCK("", "current_temp");
  GP.BLOCK_END();
В обработке действия:
C++:
void action() {
    // обновляем отображение текущей температуры
    if (portal.update("current_temp")) {
      portal.answer(String(Temperature));
    }
}
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
@Samoswall,
Что вместо GP.SEND() надо использовать, чтобы было имя и лишние теги не вставлялись?
GP.SEND() не добавляет теги

@gorlanovmax,
Соответственно потихоньку растер размер библиотеки, а если доп. функции не нужны, зачем занимать больше места на ESP?
Эм, ну компилятор как бы не дурак, он неиспользуемые функции не добавляет в прошивку... Да и даже если бы добавлял - на есп слишком много места, чтобы об этом беспокоиться
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
C++:
      uint32_t colorled = 0x00FFFF;            //начальные настройки
-----------------------------------
      String colorled;                         //переопределяю для парсера
      portal.copyString("webcolor", colorled); //парсинг успешный
      colorled.replace("#", "0x");             //конвертация успешна
      Serial.println(colorled);                //выводится значение правильно 0x00ffff
      mem.updateNow();                         //сохраняю в память
после сохранения цвет не возвращается, а показывает изначальный)
в eeprom же не сохраняется тип переменной?) или не хватает размера памяти?)
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
@ASM, я часом не тебя случайно на гитхабе отправил изучать самые базовые уроки?)
 

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
@AlexGyver, уроки тут не причем) uint32_t это целые числа, тогда логично использовать copyInt(), но он парсит нуль)
Тогда пришлось использовать copyString(), в Serial выдает верно. Единственное, что формат вывода у него не под FastLED, пришлось конвертировать)
Если записать нуль, то цвет показывает черным, без всяких конвертаций. Надо попробовать записать без первых знаков...
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
@ASM,
уроки тут не причем)
Как насчёт того что ты глобально создаёшь число, затем локально создаёшь строку с таким же именем переменной, и ждёшь каких то изменений от глобальной переменной? Я поэтому и отправил в уроки. Разобраться наконец с типами переменных, почему они всё таки существуют разные и как они между собой совмещаются. И как работает возврат функции. А также с областью определения - локальная и глобальная, и что происходит если у переменных одинаковые имена.

uint32_t это целые числа, тогда логично использовать copyInt()
Логично, но только вот цвет с браузера идёт в формате web color, это строка вида #RRGGBB. И её нельзя парсить как инт. Поэтому специально был сделан GPcolor, который может отдавать и int 24-бит, и три цвета отдельно, и web color. На все случаи жизни

Надо попробовать записать без первых знаков...
Опять же - изучать базовые уроки. Строка, даже если она содержит число - не является числом. Это всё ещё строка, и передавать её туда, где ожидают численный тип - нельзя. Это база.

формат вывода у него не под FastLED
Может стоит посмотреть документацию на GPcolor?
C++:
// переменные
uint8_t r, g, b;

// методы
uint32_t getHEX();          // получить 24 бит цвет
В FastLED можно передать условно как leds[i] = color.getHEX(). А также использовать CRGB(color.r, color.g, color.b)
 
Изменено:
  • Лойс +1
Реакции: ASM

ASM

★★★★★✩✩
26 Окт 2018
1,599
311
кучу вариантов использовал, но на часах либо розовый, либо зеленый цвет, а не синий)

еще непонятно, почему такой вариант выдает розовый)
C++:
CRGB ledColor = CRGB(0, 255, 255);
п.с. может профили меняются местами, по типу ленты, GRB?)
проверяю...
оказывается вот в чем была проблема, из-за профиля ленты... столько проблем из-за RGB COLOR))

Если запишу так, то все ок)
C++:
GPcolor color(0, 255, 255);
CRGB ledColor = CRGB(color.g, color.r, color.b);
а если так, то цвет розовый))
C++:
GPcolor color(0, 255, 255);
CRGB ledColor = CRGB(color.g, color.r, color.b);
EEManager mem5(ledColor);
 
Изменено:

Samoswall

✩✩✩✩✩✩✩
16 Ноя 2022
6
2
@Samoswall
Отвечу сам на свой вопрос!
Вдруг кому понадобиться обновлять элементы стиля.

void build() {:
  String ss1, ss2;
  ss1 = "<div class='battery' style='--charge: 100;'><span/></div>";
  ss2 = "<label id='myss2' style='display: none;'>100</label>";
  ss2 += "<script>setInterval(function(){";
  ss2 += "var valbatt=document.getElementById('myss2').innerHTML;";   
  ss2 += "document.querySelector('.battery').style.setProperty('--charge',valbatt);";
  ss2 += "},2000);</script>";
  GP.BUILD_BEGIN(600);
  GP.THEME(GP_LIGHT);
  GP.UPDATE("test_label_on_off,test_led,mdate,mtime,myss2");
  GP.SEND(ss2);
  GP.NAV_TABS("Главная,Настройки,Тест");
  GP.NAV_BLOCK_BEGIN();
    GP.BLOCK_BEGIN(GP_TAB,"","Инфо");
      GP.BOX_BEGIN();
        GP.LABEL("00:00:00", "mtime");
        GP.LABEL("00.00.2000", "mdate");
      GP.BOX_END(); 
      GP.HR();
      GP.BOX_BEGIN();
        GP.LABEL("Имя устройства");
        GP.LABEL("Test 1");
      GP.BOX_END();
      GP.HR(); 
      GP.BOX_BEGIN();
        GP.LABEL("Заряд АКБ");
        GP.SEND(ss1);
      GP.BOX_END();
    GP.BLOCK_END();
void action() {:
  if (portal.update()) {
     String valDate=ntp.dateString();
     String valTime=ntp.timeString();
     portal.updateString("mdate", valDate);
     portal.updateString("mtime", valTime);
     sval_batt = String(bat_lvl);
     portal.updateString("myss2", sval_batt);
  }
В 3 строке скрытый label, значение которого обновляем стандартным методом.
В 4-7 скрипт, который читает значение в скрытом label и записывает в элемент стиля --charge:
Получилось то, что хотел:
1668870250462.png
 
  • Лойс +1
Реакции: Daber