8.5 KiB
Дополнительные фичи
Время приложения
При открытии ПУ приложение отправляет точное время (время операционной системы, на которой запущено приложение) в unix-формате. Это время можно использовать для синхронизации часов устройства и так далее. Для получения времени нужно подключить обработчик onUnix
:
void onunix(uint32_t stamp) {
Serial.println(stamp);
}
void setup() {
hub.onUnix(onunix);
}
Веб-консоль
В настройках ПУ можно включить текстовую консоль. Сообщения, которые в неё отправляются, можно принять в обработчике onCLI
:
void cli(String str) {
Serial.println(str);
}
void setup() {
hub.onCLI(cli);
}
Для отправки сообщений обратно используется void sendCLI(AnyText str)
Информация о билде
Внутри билдера можно узнать, кто и с какой целью вызвал билдер:
void build(gh::Builder& b) {
// это запрос виджетов
if (b.build.isUI()) {
Serial.println("=== UI BUILD ===");
}
// это действие с виджетом
if (b.build.isSet()) {
Serial.println("=== SET ===");
// можно напрямую получить имя и значение виджета
Serial.print("name: ");
Serial.println(b.build.name);
Serial.print("value: ");
Serial.println(b.build.value);
}
// инфо о клиенте
Serial.print("client from: ");
Serial.println(gh::readConnection(b.build.client.connection()));
Serial.print("ID: ");
Serial.println(b.build.client.id);
Serial.println();
}
Так как билдер динамический, это даёт возможность например показывать некоторые виджеты только определённому клиенту или только по конкретному способу связи:
if (b.build.client.id == "abc123") b.Input();
А также перехватывать входящие значения без подключения переменной:
if (b.Input().click()) Serial.println(b.build.value);
Обработка запроса
Библиотека позволяет получить всю информацию о запросе до того, как он будет применён, и разрешить или запретить его. Это относится ко всем запросам с приложения, что позволяет очень гибко настроить систему. Например разрешить или какие то действия только определённым клиентам или по определённым способам связи, что может быть полезно для "общественных" проектов: у юзеров одни права, а у админа - другие. Длня начала нужно подключить обработчик запроса:
bool req(gh::Request& r) {
Serial.print("Request: ");
Serial.print(gh::readConnection(r.client.connection())); // подключение
Serial.print(',');
Serial.print(r.client.id); // id клиента
Serial.print(',');
Serial.print(gh::readCMD(r.cmd)); // команда (см. доку)
Serial.print(',');
Serial.print(r.name); // имя виджета
Serial.print(',');
Serial.print(r.value); // значение виджета
Serial.println();
return 1;
}
void setup() {
hub.onRequest(req);
}
Из функции нужно вернуть true
, чтобы разрешить запрос!
Модули
Доступ к устройству из приложения можно контролировать при помощи системы модулей: их можно включать и отключать. По умолчанию все модули включены. Список модулей:
gh::Module::ModUI // разрешить ПУ
gh::Module::ModInfo // разрешить вкладку инфо
gh::Module::ModSet // разрешить установку виджетов
gh::Module::ModRead // разрешить чтение виджетов
gh::Module::ModGet // разрешить чтение из билдера
gh::Module::ModData
gh::Module::ModReboot // разрешить перезагрузку из инфо
gh::Module::ModFiles // разрешить вкладку менеджера файлов
gh::Module::ModFormat // разрешить форматирование FS
gh::Module::ModDelete // разрешить удаление файлов
gh::Module::ModRename // разрешить переименование файлов
gh::Module::ModCreate // разрешить создание файлов
gh::Module::ModFetch // разрешить скачивание
gh::Module::ModUpload // разрешить скачивание
gh::Module::ModOta // разрешить ОТА
gh::Module::ModOtaUrl // разрешить ОТА по URL
Для включения нужно вызвать hub.modules.set()
, для выключения - hub.modules.clear()
и передать одну или несколько констант через |
, например:
// выключить менеджер файлов и кнопку переименования файлов
hub.modules.clear(gh::Module::ModFiles | gh::Module::ModRename);
// запретить все
hub.modules.clearAll();
// разрешить Info
hub.modules.set(gh::Module::ModInfo);
Перехват скачивания
По умолчанию менеджер файлов и все виджеты с указанием пути к файлу работают с flash-памятью и файл автоматически открывается по указанному пути. Открытие файла можно перехватить в обработчике onFetch
:
const char* fetch_bytes = "fetch bytes";
const char fetch_pgm[] PROGMEM = "fetch pgm";
void fetch(gh::Fetcher& f) {
// например по имени файла можно отправить данные из памяти программы или из PROGMEM
if (f.path == "/fetch_bytes.txt") f.fetchBytes((uint8_t*)fetch_bytes, strlen(fetch_bytes));
if (f.path == "/fetch_pgm.txt") f.fetchBytes_P((uint8_t*)fetch_pgm, strlen_P(fetch_pgm));
// или отправить другой файл
if (f.path == "/fetch_file.txt") f.fetchFile("/fetch_file123.txt");
// также можно отправить например кадр с камеры:
if (f.path == "frame.jpg") {
// start == true - начало загрузки
if (f.start) {
frame = esp_camera_fb_get(); // получить кадр
if (frame) f.fetchBytes((uint8_t*)frame->buf, frame->len); // начать отправку
// start == true - конец загрузки
} else {
esp_camera_fb_return(frame); // освободить кадр
}
}
}
void setup() {
hub.onFetch(fetch);
}
Окончание загрузки
Также можно отловить момент окончания загрузки файла с приложения в память устройства:
void upl(String& path) {
Serial.print("Uploaded: ");
Serial.println(path);
}
void setup() {
hub.onUpload(upl);
}
Свои поля в Info
Во вкладку Info в любой из 4-х блоков можно добавить свои поля:
void info(gh::Info& info) {
switch (info.type) {
case gh::Info::Type::Version:
info.add("Module", "v123");
break;
case gh::Info::Type::Network:
info.add(F("5G"), "50%");
break;
case gh::Info::Type::Memory:
info.add(F("SD"), "10 GB");
break;
case gh::Info::Type::System:
info.add(F("Battery"), 3.63, 2);
info.add("ur mom", "120kg");
break;
}
}
void setup() {
hub.onInfo(info);
}