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.

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);
}