You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
8.5 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Дополнительные фичи
## Время приложения
При открытии ПУ приложение отправляет точное время (время операционной системы, на которой запущено приложение) в unix-формате. Это время можно использовать для синхронизации часов устройства и так далее. Для получения времени нужно подключить обработчик `onUnix`:
```cpp
void onunix(uint32_t stamp) {
Serial.println(stamp);
}
void setup() {
hub.onUnix(onunix);
}
```
## Веб-консоль
В настройках ПУ можно включить текстовую консоль. Сообщения, которые в неё отправляются, можно принять в обработчике `onCLI`:
```cpp
void cli(String str) {
Serial.println(str);
}
void setup() {
hub.onCLI(cli);
}
```
Для отправки сообщений обратно используется `void sendCLI(AnyText str)`
## Информация о билде
Внутри билдера можно узнать, кто и с какой целью вызвал билдер:
```cpp
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();
}
```
Так как билдер динамический, это даёт возможность например показывать некоторые виджеты только определённому клиенту или только по конкретному способу связи:
```cpp
if (b.build.client.id == "abc123") b.Input();
```
А также перехватывать входящие значения без подключения переменной:
```cpp
if (b.Input().click()) Serial.println(b.build.value);
```
## Обработка запроса
Библиотека позволяет получить всю информацию о запросе до того, как он будет применён, и разрешить или запретить его. Это относится ко всем запросам с приложения, что позволяет очень гибко настроить систему. Например разрешить или какие то действия только определённым клиентам или по определённым способам связи, что может быть полезно для "общественных" проектов: у юзеров одни права, а у админа - другие. Длня начала нужно подключить обработчик запроса:
```cpp
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`, чтобы разрешить запрос!
## Модули
Доступ к устройству из приложения можно контролировать при помощи системы модулей: их можно включать и отключать. По умолчанию все модули **включены**. Список модулей:
```cpp
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()` и передать одну или несколько констант через `|`, например:
```cpp
// выключить менеджер файлов и кнопку переименования файлов
hub.modules.clear(gh::Module::ModFiles | gh::Module::ModRename);
// запретить все
hub.modules.clearAll();
// разрешить Info
hub.modules.set(gh::Module::ModInfo);
```
## Перехват скачивания
По умолчанию менеджер файлов и все виджеты с указанием пути к файлу работают с flash-памятью и файл автоматически открывается по указанному пути. Открытие файла можно перехватить в обработчике `onFetch`:
```cpp
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);
}
```
## Окончание загрузки
Также можно отловить момент окончания загрузки файла с приложения в память устройства:
```cpp
void upl(String& path) {
Serial.print("Uploaded: ");
Serial.println(path);
}
void setup() {
hub.onUpload(upl);
}
```
## Свои поля в Info
Во вкладку Info в любой из 4-х блоков можно добавить свои поля:
```cpp
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);
}
```