GyverPortal

ASM

★★★✩✩✩✩
26 Окт 2018
776
150
@ALEX8989YT,
Так прочитай описание конструктора, надо сделать опрос нажатия кнопки)
if (portal.form("/update"))
@ALEX8989YT, формы лучше работают)
 

ALEX8989YT

✩✩✩✩✩✩✩
4 Авг 2022
6
0
@ASM, добавить form и сделать примерно это?
C++:
if (portal.form("/update")) {
  GP.PAGE_BEGIN();
  GP.PAGE_BLOCK_BEGIN();
  *_GP += F("<input type='button' onclick='window.location.reload()'  value ='обновить' />");
  GP.PAGE_BLOCK_END();
  GP.PAGE_END();
  //примерно так?
}
 

ASM

★★★✩✩✩✩
26 Окт 2018
776
150
@ALEX8989YT, как-то всё странно смотрится, типа того, экспериментируй) я сам так делаю, но дал бы главный совет) завязывай с движком, если что-то делаешь своё) сам планирую избавляться от него, когда отлажу работу кода, проблем много с ним) пиши страницы сам, потом дизайн сделаешь)
 

DAK

★★✩✩✩✩✩
8 Окт 2020
360
93
@aidar_i, как бы Вам надо сделать форму. В форме может быть ввод GP.TEXT или GP.PASS. Есть так же варианты с маленькой кнопкой, то есть при нажатие на эту кнопку проходит обновление только определённого компонента. Вы сперва делаете GP.PASS и по клику на кнопку вы должны отправить данные этого поля и перерисовать компонент как GP.TEXT. Сам не пробовал, но скоро (в течении месяца наверное) буду этот портал мучить, пока изучаю документацию, там в принципе всё подробно описано.
 

aidar_i

✩✩✩✩✩✩✩
1 Май 2021
20
6
@DAK,Спасибо за ответ. Так пробовал , но не совсем это то. Есть код, как его вставить ?
C++:
<script src="https://snipp.ru/cdn/jquery/2.1.1/jquery.min.js"></script>
<script>
$('body').on('click', '.password-checkbox', function(){
    if ($(this).is(':checked')){
        $('#password-input').attr('type', 'text');
    } else {
        $('#password-input').attr('type', 'password');
    }
});
</script>
 

ASM

★★★✩✩✩✩
26 Окт 2018
776
150
@aidar_i, посмотри в библиотеке, где вставляются скрипты.
На примере графиков, AJAX.
 
Изменено:

DAK

★★✩✩✩✩✩
8 Окт 2020
360
93
@aidar_i, Вы должны понимать, чтобы данный код работал, устройство, которое подключается должно иметь доступ к Интернету, это первое. Дальше идём в тот же гитхаб и читаем 11 пункт, скорей всего вам надо пойти по пути внесения вашего кода в шапку. вместо BUILD_BEGIN() можно использовать 3 функции:
C++:
GP.PAGE_BEGIN();
GP.AJAX_CLICK();
GP.PAGE_BLOCK_BEGIN();
между 1 и 2 надо вставить Ваш код
C++:
GP.PAGE_BEGIN();
*_GP += F("some HTML code");
GP.AJAX_CLICK();
GP.PAGE_BLOCK_BEGIN();
Только вот ссылку на jquery лучше использовать не с Бог знает какого сайта, тут более подробно.
В принципе файл не такой и тяжёлый, можно попробовать залить его на flash память и потом выводить целиком его код, это на случай если контроллер будет работать в сети без доступа к Интернету.
 

DAK

★★✩✩✩✩✩
8 Окт 2020
360
93
Пишу отдельным постом (Модераторы, не бейте меня, это иная проблема)
Допустим мне надо сделать циклом создать ряд пунктов меню с помощью GP.BUTTON_LINK()
Функция конструктора GP.BUTTON_LINK()
C++:
void BUTTON_LINK(const char* url, const char* value) {
        *_GP += F("<input type=\"button\" value=\"");
        *_GP += value;
        *_GP += F("\" onclick=\"location.href='");
        *_GP += url;
        *_GP += F("';\">\n");
    }
мне надо передать туда uri и имя реле. Массив с именами реле у меня глобальный:
char NameRelay[40][32];
Для того, чтобы всё правильно работало мне приходится проделывать следующее:
C++:
    char linkrelay[30];          //Подготавливаю строку нужной длины (вернее массив символов)
    char numlinkrelay[2];        //Делаю ещё одну для того, чтобы в неё передать переменную из цикла
    char nlink[]="/settings/system/relay/";    //ещё одна строка, это как бы начало ссылки
    for (byte h=0;h<RelayCount;h++){
      itoa(h, numlinkrelay, DEC);             //сперва инт впихиваю в одну строку
      strcpy(linkrelay,nlink);                  //в буфер кладу начало ссылки
      strcat(linkrelay,numlinkrelay);          //к началу добавляю то, что сгенерировал цикл
      GP.BUTTON_LINK(linkrelay, NameRelay[h]); GP.BREAK();
    }
Можно как то проще проделать то же самое?
Я просто сегодня еле осуществил сиё действие, по мне проще дописать функцию в библиотеку....
 

zoland

✩✩✩✩✩✩✩
7 Авг 2022
1
0
к вопросу об использовании favicon.ico

 

ASM

★★★✩✩✩✩
26 Окт 2018
776
150
@DAK,
Эта статья может чем-то поможет?)
Как я понял, нужно объединить две строки и получить полную ссылку?
 

DAK

★★✩✩✩✩✩
8 Окт 2020
360
93

@ASM,
Скажем так, бывает массив символов char, бывают строки. Можно наверное отработать со строками а потом уже строку в чар переделывать. Но блин в 1000 раз проще в библиотеку дописать 5 строк и всё.

UPD:
Надоел мне этот изврат, не смог себя удержать от правки библиотеки, как бы мне этого не хотелось делать
C++:
    void BUTTON_LINK(const char* url, const char* value, int sub = INT32_MAX, bool sub_visible=false) {
        *_GP += F("<input type=\"button\" value=\"");
        if (sub_visible) {
            *_GP += sub;
            *_GP += F(". ");
        }
        *_GP += value;
        *_GP += F("\" onclick=\"location.href='");
        *_GP += url;
        if (sub != INT32_MAX) {
            *_GP += sub;
        }
        *_GP += F("';\">\n");
    }
Немного переделал 1 функцию, но сразу стало легче. Теперь всего то
C++:
 for (int h=0;h<RelayCount;h++){
      GP.BUTTON_LINK("/settings/system/relay/", NameRelay[h], h, true); GP.BREAK();
    }
И у меня выводится 40 кнопок, к имени кнопки спереди добавляется номер "0. ИмяНулевогоРеле"
Теперь думаю в класс добавить 1 метод для отслеживания нажатия форм созданных на сгенерированных страницах
 
Изменено:

Michael_074

✩✩✩✩✩✩✩
16 Дек 2021
4
0
Доброго дня!
Подскажите, как "включать-выключать" светодиод. Вроде на 1-й странице был подобный вопрос.
Нужно по событию в программе изменять состояние, "светится-не светится"
Если делаю так, при объявлении, то работает
void build()
{
BUILD_BEGIN();
....
if(...)
add.LED_GREEN("web_led", 1);
else
add.LED_GREEN("web_led", 0);
...
А как потом в void loop() {... управлять светодиодом?
 

Олег Поляков

★✩✩✩✩✩✩
18 Янв 2022
18
13
www.1812.ru
@Michael_074, создайте в web-форме элемент SWITCH с переменной состояния этого элемента (вкл./выкл.).
Отслеживайте событие Click для этого элемента и, в зависимости от значения переменной состояния, включайте или выключайте светодиод.
Посмотрите внимательно примеры к гайверовской библиотеке. Там есть как управлять светодиодом.
 

DAK

★★✩✩✩✩✩
8 Окт 2020
360
93
@Michael_074,
При запуске портал вы должны подключить функции конструктора и обработчика событий, например
portal.attachBuild(build);
portal.attach(action);
Логика следующая, функция
void build() "рисует интерфейс"
а в функцию
void action() приходят все события, которые произошли в интерфейсе
Так что управлять светодиодом надо не в loop, а в action
В loop надо опрашивать портал через portal.tick()
Посмотрите в примерах на гитхабе


UPD:
Может кому пригодится.
На Esp32 есть такая штука, как "многозадачность". Можно создать пару задач, запихать их на разные ядра. Тогда опрос портала не будет влиять на основной код программы. Как это использовать пусть каждый решит сам, но мне очень понравилось так делать.
C++:
#include "GyverPortal.h"

TaskHandle_t Task1, Task2;
GyverPortal portal;

void action(GyverPortal& portal) {
    //тут обработчик событий пришедших с портала
}
void build() {
    //тут конструктор форм портала
}
void taskCore0(void * pvParameters) {
    for (;;){
        //Тут код первой задачи
        //Здесь можно основной код Вашего алгоритма работы
    }
}
void taskCore1(void * pvParameters) {
    for (;;){
        //Тут код для опроса портала
        //Это будет работать параллельно первой задачи. Сюда больше не надо писать ничего
          portal.start();
        portal.attachBuild(build);
          portal.attach(action);

          Serial.println("Portal run");
          while (portal.tick());
    }
}
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_AP);                 //В примере запуск Esp32 в режиме AP
  WiFi.softAP("PRIMER");            //Тут кому как хочется

    xTaskCreatePinnedToCore(taskCore0,"Task1",10000,NULL,1,&Task1,0);   //Запускаем 2 задачи
    delay(500);
      xTaskCreatePinnedToCore(taskCore1,"Task2",10000,NULL,1,&Task2,1);

}

void loop() {
// тут никакой код писать не надо
}
 
Изменено:
  • Лойс +1
Реакции: ASM

Michael_074

✩✩✩✩✩✩✩
16 Дек 2021
4
0
Именно так и делаю
portal.attachBuild(build);
portal.attach(action);
portal.start();
Просмотрел 16 примеров и 3 проекта, которые идут с библиотекой. Не нахожу никак управление светодиодом, именно управление.
Если вдруг кого нибудь не затруднит, ткните меня носом.
Объявлен GP.LED_GREEN("web_led", 0);
Какой командой его "зажечь"?
 

DAK

★★✩✩✩✩✩
8 Окт 2020
360
93
Просто как пример. Должно работать.


@Michael_074,
C++:
#define AP_SSID "NameSSID"
#define AP_PASS "password123"
#define Led_Pin 5              //Введите свой пин на светодиод

#include <GyverPortal.h>
GyverPortal portal;


// конструктор страницы
void build() {
  BUILD_BEGIN();
  GP.THEME(GP_DARK);

  GP.TITLE("Primer");
  GP.HR();
  GP.BUTTON("btn_on", "Включить");
  GP.BUTTON("btn_off", "Выключить");

  BUILD_END();
}

void setup() {
  Serial.begin(115200);
  pinMode(Led_Pin,OUTPUT);
  WiFi.mode(WIFI_STA);
  WiFi.begin(AP_SSID, AP_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP());

  // подключаем конструктор и запускаем
  portal.attachBuild(build);
  portal.attach(action);
  portal.start();
}

void action() {
  // был клик по компоненту
  if (portal.click()) {
    // проверяем компоненты и обновляем переменные
    if (portal.click("btn_on")) digitalWrite(Led_Pin, 1);
    if (portal.click("btn_off")) digitalWrite(Led_Pin, 0);
  }
}

void loop() {
  portal.tick();
}
 

Michael_074

✩✩✩✩✩✩✩
16 Дек 2021
4
0
Оформи код соответствующим тэгом
Спасибо!
Но только или я не правильно спрашиваю или меня не понимают :(
Нужен "светодиод" который на WEB-интерфейсе.
Вот фрагменты моего кода. Если синхронизация с NTP серверами прошла успешно - хочу чтобы "светодиод горел"

void build() {
...
GP.LABEL("Date: ");
GP.DATE("web_date", rtc_date);
GP.BREAK();
GP.LABEL("Time: ");
GP.TIME("web_time", rtc_time);
GP.BREAK();

GP.LABEL("NTP Server: ");
GP.TEXT("web_ntp_server", "pool.ntp.org", ntp_server);
GP.BUTTON_MINI("web_button_ntp_sync", "Sync");
GP.LED_GREEN("web_led_ntp", 0);
GP.BREAK();

GP.LABEL("UTC: ");
GP.NUMBER("web_utc", "0", utc);
GP.BREAK();
...
void action(){
...
if(portal.click("web_button_ntp_sync"))
{
bitSet(flag, FLAG_GET_NTP_SYNC);
...
void loop() {
...
// где-то здесь запускаю timeClient.update() и если удачно - как "зажечь" GP.LED_GREEN ?
 

DAK

★★✩✩✩✩✩
8 Окт 2020
360
93
Определите глобальную переменную bool flag_synk=false
Надо сделать так, чтобы при синхронизации данная переменная стала true, при ошибке синхронизации опять false
Далее в конструкторе
GP.LED_GREEN("web_led_ntp", flag_synk);


И не забудьте добавить авто обновление GP.AJAX_UPDATE("web_led_ntp") сразу после BUILD_BEGIN(); GP.THEME(GP_DARK);

Остальное не хочу комментировать.