Обработка обновлений - GyverLibs/GyverPortal GitHub Wiki

В библиотеке есть несколько механизмов, позволяющих автоматически обновлять значения компонентов на странице

AJAX обновления

Данный механизм позволяет обновлять значения конкретных указанных компонентов. Процесс делится на две части:

  • В функции конструктора: указание списка имён компонентов, которые должны обновляться
  • В функции обработки действий: принятие запросов на обновление и ответ на них актуальными данными

Конструктор

  • Список имён в текстовом формате передаётся в GP.UPDATE(), разделитель - запятая
  • К компоненту необязательно должна быть привязана переменная, он получит значение из обновления
int sld;

void build() {
  GP.BUILD_BEGIN();
  GP.THEME(GP_DARK);
  GP.UPDATE("lbl,sld");
  //GP.UPDATE("lbl,sld", 500);  // + период в мс, умолч. 1000
  GP.LABEL("", "lbl");          // без переменной
  GP.SLIDER("sld", sld);        // из переменной sld
  
  GP.BUILD_END();
}

Обработка

Общий сигнал

  • Обработка обновлений происходит в подключенной функции-обработчике действия
  • При запросе обновления любого активного компонента на странице (см. таблицу в документации) функция update() вернёт true
  • Дальнейшую обработку действий рекомендуется поместить в условие, чтобы микроконтроллер не занимался лишней работой:
void action() {
  if (portal.update()) {
    // опрос обновлений
    Serial.println(portal.updateName());
  }
}

При помощи updateName() можно узнать имя компонента, запросившего обновление

Ответ вручную

  • Для определения запроса обновления компонента нужно передать в update() его имя
  • В этом условии нужно "ответить" на обновление актуальным значением через функцию answer()
void answer(const String& s;    // отправить ответ на обновление
void answer(GPcolor col);       // ответ с цветом
void answer(GPdate date);       // ответ с датой
void answer(GPtime time);       // ответ со временем
void answer(int v);             // ответ с числом
void answer(float v, uint8_t dec);          // ответ с float и кол-вом знаков
void answer(int16_t* v, int am);            // массив int размерностью am, для графика
void answer(int16_t* v, int am, int dec);   // + делитель

Пример с лейблом и слайдером выше:

void action() {
  if (portal.update()) {
    if (portal.update("lbl")) portal.answer(random(100));   // просто ответ
    if (portal.update("sld")) portal.answer(sld);           // ответ из переменной
  }
}

Автоматический ответ

Если у компонента есть глобальная переменная, содержащая актуальное значение, то можно обрабатывать обновления при помощи набора функций:

bool updateString(имя, String& f);
bool updateInt(имя, int f);
bool updateFloat(имя, float f, int dec = 2);
bool updateBool(имя, bool f);
bool updateDate(имя, GPdate f);
bool updateTime(имя, GPtime f);
bool updateColor(имя, GPcolor f);

Функция вернёт true в момент обновления.

void action() {
  if (portal.update()) {
    portal.updateInt("sld", sld);
  }
}

См. пример actionUpdate

JQUERY обновления

jQuery обновления работают по другому:

  • Подключается библиотека jQuery
    • Скачивается из интернета (esp должен быть подключен к интернету)
    • Отправляется из памяти микроконтроллера (см. скачивание файлов)
  • Компоненты помещаются в "блок" обновления
  • Значения компонентов должны браться из переменных, которые могут меняться в другом месте программы
  • Страница сама "незаметно" частично перезагружается, что приводит к вызову функции-конструктора, после чего компоненты в блоке получают актуальные значения из переменных в функции конструктора
int sld;
String lbl;

void build() {
  GP.BUILD_BEGIN();
  GP.THEME(GP_DARK);
  
  GP.JQ_SUPPORT();          // поддержка jquery. Файл скачается с https://code.jquery.com/
  //GP.JQ_SUPPORT_FILE();   // поддержка jquery, файл скачается из памяти (/gp_data/jquery.js)
  
  GP.JQ_UPDATE_BEGIN();     // начать обновляемый блок с периодом 1 секунда (один на страницу!)
  GP.LABEL(lbl, "lbl");     // из переменной
  GP.SLIDER("sld", sld);    // из переменной
  GP.JQ_UPDATE_END();       // закончить обновляемый блок
  
  GP.BUILD_END();
}

Блок JQ_UPDATE также "скрыто" обновляет страницу по клику в любом месте страницы внутри блока, помимо обновления по таймеру

См. пример jQupdate

Перезагрузка страницы

  • На страницу добавляется компонент GP.RELOAD(имя)
  • Его имя указывается в списке обновления GP.UPDATE()
  • На указанное имя приходит сигнал update() с указанным периодом
  • Если ответить на него 1 - страница будет перезагружена. Это можно сделать по условию или своему таймеру
void build() {
  GP.BUILD_BEGIN();
  GP.THEME(GP_DARK);
  GP.UPDATE("rel");
  GP.RELOAD("rel");
  GP.BUILD_END();
}

void action() {
  if (portal.update("rel")) portal.answer(1);
}

"Массив" компонентов

Библиотека позволяет создавать и обрабатывать компоненты как "массив", то есть назначить одно и то же имя нескольким компонентам и обращаться к ним по индексу. Синтаксис имени такой: name/sub1/sub2..., то есть вложенных имён может быть сколько угодно, разделитель - /. Создадим "массив" лейблов с именами lbl/номер:

for (int i = 0; i < 5; i++) {
  GP.LABEL_BLOCK("", String("lbl/") + i);
  GP.BREAK();
}

И добавим их в список обновления:

String s;
// формируем список для UPDATE вида "lbl/0,lbl/1..."
for (int i = 0; i < 5; i++) {
  s += "lbl/";
  s += i;
  s += ',';
}
GP.UPDATE(s);

Теперь для поиска сигнала с такого массива нужно использовать updateSub(имя), а внутри условия с ним - updateNameSub(индекс) для получения саб-имени. Из примера выше updateNameSub(0) вернёт lbl, а updateNameSub(1) - строку с номером лейбла после /. Ответим строкой вида `"lbl #0: 123"

if (portal.updateSub("lbl")) {   // начинается с lbl
  // формируем ответ вида "lbl #0: 123"
  String s;
  s += "lbl #";
  s += portal.updateNameSub(1);
  s += ":";
  s += random(10);
  portal.answer(s);
}

image

См. пример dynamicComponents