# Документация GyverHub
На этой странице находится полный список всех классов и функций библиотеки. Более подробно по использованию можно почитать на остальных страницах документации.

## Компиляция
<details>
<summary>Настройки</summary>

**Перед подключением библиотеки** можно объявить настройки, влияющие на компиляцию библиотеки:
```cpp
// BRIDGES
#define GH_NO_STREAM  // отключить встроенный модуль связи stream
#define GH_NO_HTTP    // отключить встроенный модуль связи http (для esp)
#define GH_NO_WS      // отключить встроенный модуль связи ws (для esp)
#define GH_NO_MQTT    // отключить встроенный модуль связи mqtt (для esp)

#define GH_BRIDGE_AMOUNT 5       // количество мостов подключения
#define GH_WS_PORT 81            // websocket порт
#define GH_MQTT_RECONNECT 10000  // период переподключения встроенного MQTT (для esp)

// MODULES
#define GH_NO_PAIRS    // отключить поддержку типа Pairs
#define GH_NO_GET      // отключить отправку на get-топик (mqtt)
#define GH_NO_INFO     // отключить info билдер
#define GH_NO_MODULES  // отключить "модули" (все включены)
#define GH_NO_REQUEST  // отключить поддержку запросов

// FS
#define GH_NO_FS                 // отключить файловую систему (для esp)
#define GH_FETCH_CHUNK_SIZE 512  // размер чанка при скачивании с платы (для esp)
#define GH_UPL_CHUNK_SIZE 512    // размер чанка при загрузке на плату (для esp)
#define GH_FS_DEPTH 5            // глубина сканирования файловой системы (esp32)

// TRANSFER
#define GH_NO_FETCH    // отключить скачивание файлов (для esp)
#define GH_NO_UPLOAD   // отключить загрузку файлов (для esp)
#define GH_NO_OTA      // отключить ОТА обновления (для esp)
#define GH_NO_OTA_URL  // отключить ОТА по ссылке (для esp)
#define GH_REBOOT_DELAY 1500    // задержка перед перезагрузкой после OTA (для esp)

// PORTAL
#define GH_FILE_PORTAL     // загружать сайт из памяти есп (положи файлы в папку /hub/) (для esp)
#define GH_INCLUDE_PORTAL  // включить сайт в память программы, ~50кБ (не нужно загружать файлы в память) (для esp)

// HTTP
#define GH_PUBLIC_PATH "/www"          // путь к папке с файлами с HTTP доступом (для esp)
#define GH_HTTP_PORT 80                // http порт (для esp)
#define GH_CACHE_PRD "max-age=604800"  // период кеширования файлов для портала (для esp)

#define GH_NO_HTTP_TRANSFER       // отключить загрузку/скачивание/ОТА по http (для esp)
#define GH_NO_HTTP_DNS            // отключить DNS сервер (для esp)
#define GH_NO_HTTP_OTA            // отключить ОТА обновления по http (для esp)
#define GH_NO_HTTP_PUBLIC         // отключить доступ к файлам по http c ip/www (для esp)
#define GH_NO_HTTP_FETCH          // отключить скачивание файлов по http (для esp)
#define GH_NO_HTTP_UPLOAD         // отключить загрузку файлов по http (для esp)
#define GH_NO_HTTP_UPLOAD_PORTAL  // упрощённую загрузку файлов с ip/hub/upload_portal (для esp)
```
</details>
<details>
<summary>Платформа</summary>

Библиотека сама определяет, на какой платформе компилируется. Для ESP8266/ESP32 предусмотрен отдельный флаг `GH_ESP_BUILD` (доступен после подключения библиотеки), включюащий сетевые возможности в компиляцию. Для создания кросс-платформенного кода можно "прятать" код для ESP внутри условной конструкции:

```cpp
#include <GyverHub.h>

#ifdef GH_ESP_BUILD
// этот код будет компилироваться только для esp
#endif
```

Также в макросе `GH_PLATFORM` содержится название платформы в виде строки:
- `"ESP8266"`
- `"ESP32"`
- `"ESP32-S2"`
- `"ESP32-S3"`
- `"ESP32-C3"`
- `"Arduino"` для всех остальных
</details>

## GyverHub
<details>
<summary>Примечание по типам данных</summary>

Для удобства в библиотеке используются "универсальные" типы данных. Компилятор сам понимает, что передали в функцию:
- `AnyText` - строка в любом виде (`"строка"`, `F("строка")`, `char*`, `String`)
- `AnyValue` - любой целочисленный и дробный тип данных + строки в любом виде
- `AnyPtr` - указатель (адрес) переменной любого типа (String, char*, все числа) + системные (Colors, Flags, Pos, Button, Log)
</details>
<details>
<summary>Инициализация</summary>

```cpp
GyverHub;
GyverHub(String net);                                        // + имя сети
GyverHub(String net, String name);                           // + имя в списке устройств
GyverHub(String net, String name, String icon);              // + иконка в списке устройств
GyverHub(String net, String name, String icon, uint32_t id); // + вручную задать ID устройства
```

Иконки Font Awesome v5 Solid, бесплатный пак:
- [Список иконок](https://fontawesome.com/v5/search?o=r&m=free&s=solid)
- Вставлять в "строку" сам символ (глиф) `""` или его код `"f6ad"`
- Пустая строка `""` - отключить иконку

</details>
<details>
<summary>Система</summary>

```cpp
// настроить префикс, название и иконку. Опционально задать свой ID устройства вида 0xXXXXXX (для esp он генерируется автоматически)
void config(String prefix, String name = "", String icon = "", uint32_t id = 0);

// установить версию прошивки для отображения в Info
void setVersion(String v);

// установить размер буфера строки для сборки интерфейса (умолч. 1000)
void setBufferSize(uint16_t size);

// установить пин-код для открытия устройства (значение больше 1000, не может начинаться с 000..)
void setPIN(uint32_t pin);

uint32_t getPIN();                  // прочитать пин-код
void begin();                       // запустить
void end();                         // остановить
bool tick();                        // тикер, вызывать в loop

bool addBridge(gh::Bridge* bridge); // добавить мост подключения
```
</details>
<details>
<summary>Статус</summary>

```cpp
bool running();     // вернёт true, если система запущена
bool focused();     // true - интерфейс устройства сейчас открыт на сайте или в приложении
bool canSend();     // доступна ли сейчас отправка (функции updateXxx и sendXxx)
```
</details>
<details>
<summary>Обработчики</summary>

```cpp
// подключить функцию-сборщик интерфейса вида f(gh::Builder& builder)
void onBuild(f);

// подключить обработчик запроса клиента вида f(gh::Request& request)
void onRequest(f);

// подключить функцию-сборщик инфо вида f(gh::Info& info)
void onInfo(f) ;

// подключить обработчик входящих сообщений с веб-консоли вида f(String str)
void onCLI(f);

// подключить обработчик получения unix времени с клиента вида f(uint32_t unix)
void onUnix(f);

// подключить обработчик скачивания файлов вида f(gh::Fetcher& fetcher)
void onFetch(f);

// подключить функцию-обработчик перезагрузки вида f(gh::Reboot res). Будет вызвана перед перезагрузкой
void onReboot(f);

// подключить обработчик загрузки файлов вида f(String& path). Будет вызван при сохранении файла
void onUpload(f);

// безопасная загрузка файлов (загружать во временный файл) (умолч. включен, true)
void safeUpload(bool state);
```
</details>
<details>
<summary>Отправка</summary>

```cpp
// отправить текст в веб-консоль. Опционально цвет
void sendCLI(AnyText str, gh::Colors col = gh::Colors::Default, gh::Client* client = nullptr);

// обновить панель управления в приложении
void sendRefresh(gh::Client* client = nullptr);

// выполнить js код
void sendScript(AnyText script, gh::Client* client = nullptr);

// отправить действие (обновить файл, вызвать Confirm/Prompt)
void sendAction(AnyText name, gh::Client* client = nullptr);

// отправить пуш уведомление
void sendPush(AnyText text, gh::Client* client = nullptr);

// отправить всплывающее уведомление
void sendNotice(AnyText text, gh::Colors col = gh::Colors::Green, gh::Client* client = nullptr);

// показать окно с ошибкой
void sendAlert(AnyText text, gh::Client* client = nullptr);
```
</details>
<details>
<summary>Обновление</summary>

```cpp
// обновить виджет. Указать имя виджета (или список), имя функции, клиента (опционально)
gh::UpdateInline update(AnyText name, AnyText func, gh::Client* client = nullptr);

// обновить виджет. Указать имя виджета (или список), клиента (опционально)
gh::UpdateInline update(AnyText name, gh::Client* client = nullptr);

// отправить value update на имя виджета int/string/bool
void sendUpdate(AnyText name, AnyValue value, gh::Client* client = nullptr);

// отправить value update на имя виджета float
void sendUpdate(AnyText name, double value, uint8_t dec, gh::Client* client = nullptr);

// отправить value update по имени компонента (значение будет прочитано в build). Нельзя вызывать из build. Имена можно передать списком через ;
void sendUpdate(AnyText name, gh::Client* client = nullptr);
```
</details>
<details>
<summary>MQTT</summary>

```cpp
// автоматически отправлять новое состояние на get-топик при изменении через set (умолч. false)
void sendGetAuto(bool state);

// отправить имя-значение на get-топик (MQTT) int/string/bool
void sendGet(AnyText name, AnyValue value);

// отправить имя-значение на get-топик (MQTT) float
void sendGet(AnyText name, double value, uint8_t dec);

// отправить значение по имени компонента на get-топик (MQTT) (значение будет прочитано в build). Имена можно передать списком через ;
void sendGet(String name);

// отправить MQTT LWT команду на включение/выключение
void sendStatus(bool status);

// топик статуса для отправки
String topicStatus();

// общий топик для подписки
String topicDiscover();

// топик устройства для подписки
String topicHub();
```
</details>
<details>
<summary>Чтение билдера</summary>

```cpp
// получить полный JSON пакет панели управления. Флаг enclose true - обернуть в результат в []
String getUI(bool enclose = false);

// получить JSON объект {имя:значение, ...} виджетов (из билдера)
String getValues();

// получить значение компонента по имени (из билдера)
String getValue(AnyText name);
```
</details>
<details>
<summary>Публичные члены</summary>

```cpp
uint8_t menu;   // номер текущего пункта меню
String prefix = "";
String name = "";
String icon = "";
String version = "";
const char* id;
gh::Bridge* bridges[GH_BRIDGE_AMOUNT];
Modules modules;
gh::HubStream stream;
HubMQTT mqtt;
```
</details>

## Билдер
<details>
<summary>Виджеты</summary>

```cpp
// =================== МЕНЮ ====================
// Меню. Передать пункты меню списком "пункт1;пункт2" + attach, click
Widget& Menu(AnyText text);

// =================== СТРУКТУРА ====================
// начать строку. Всегда возвращает true
bool beginRow(uint8_t width = 1);

// закончить строку
void endRow();

// начать столбец. Всегда возвращает true
bool beginCol(uint8_t width = 1);

// закончить столбец
void endCol();

// пустой виджет. Параметры: size, square
Widget& Space();

// =================== ВВОД ====================
// Поле ввода текста. Параметры: value (текст), color, regex, maxLen, disabled, attach, click + параметры виджета
Widget& Input(AnyPtr ptr);
Widget& Input_(AnyText name, AnyPtr ptr);

// Поле ввода текста. Параметры: value (текст), rows, maxLen, disabled, attach, click + параметры виджета
Widget& InputArea(AnyPtr ptr);
Widget& InputArea_(AnyText name, AnyPtr ptr);

// Поле ввода пароля. Параметры: value (текст), color, regex, maxLen, disabled, attach, click + параметры виджета
Widget& Pass(AnyPtr ptr);
Widget& Pass_(AnyText name, AnyPtr ptr);

// Всплывающее окно подтверждения. Параметры: text (подпись), attach, click. Для активации отправь обновление action()
Widget& Confirm(AnyPtr ptr);
Widget& Confirm_(AnyText name, AnyPtr ptr);

// Всплывающее окно ввода. Параметры: value (значение), text (подпись), attach, click. Для активации отправь обновление action()
Widget& Prompt(AnyPtr ptr);
Widget& Prompt_(AnyText name, AnyPtr ptr);

// Дата. Параметры: value(unix), color, disabled, attach, click + параметры виджета
Widget& Date(AnyPtr ptr);
Widget& Date_(AnyText name, AnyPtr ptr);

// Время. Параметры: value(unix), color, disabled, attach, click + параметры виджета
Widget& Time(AnyPtr ptr);
Widget& Time_(AnyText name, AnyPtr ptr);

// Дата и время. Параметры: value(unix), color, disabled, attach, click + параметры виджета
Widget& DateTime(AnyPtr ptr);
Widget& DateTime_(AnyText name, AnyPtr ptr);

// Слайдер. Параметры: value (значение), color, range, unit, disabled, attach, click + параметры виджета
Widget& Slider(AnyPtr ptr);
Widget& Slider_(AnyText name, AnyPtr ptr);

// Спиннер. Параметры: value (значение), range, unit, disabled, attach, click + параметры виджета
Widget& Spinner(AnyPtr ptr);
Widget& Spinner_(AnyText name, AnyPtr ptr);

// Выпадающий список. Параметры: value (номер пункта), text (список), color, disabled, attach, click + параметры виджета
Widget& Select(AnyPtr ptr);
Widget& Select_(AnyText name, AnyPtr ptr);

// Цвет. Параметры: value (цвет), disabled, attach, click + параметры виджета
Widget& Color(AnyPtr ptr);
Widget& Color_(AnyText name, AnyPtr ptr);

// Выключатель. Параметры: value (состояние), color, disabled, attach, click + параметры виджета
Widget& Switch(AnyPtr ptr);
Widget& Switch_(AnyText name, AnyPtr ptr);

// Выключатель. Параметры: value (состояние), icon, color, fontSize, disabled, attach, click + параметры виджета
Widget& SwitchIcon(AnyPtr ptr);
Widget& SwitchIcon_(AnyText name, AnyPtr ptr);

// Вкладки. Параметры: value (выбранная), text (список), color, disabled, attach, click + параметры виджета. text не обновляется
Widget& Tabs(AnyPtr ptr);
Widget& Tabs_(AnyText name, AnyPtr ptr);

// Кнопка. Параметры: icon, color, fontSize, disabled, attach, click + параметры виджета
Widget& Button(gh::Button* ptr);
Widget& Button_(AnyText name, gh::Button* ptr);

// Кнопки выбора. Параметры: value (флаги), text (список), color, disabled, attach, click + параметры виджета
Widget& Flags(gh::Flags* ptr);
Widget& Flags_(AnyText name, gh::Flags* ptr);

// Джойстик. keep - возвращать в центр, exp - экспоненциальные значения. Параметры: color + параметры виджета
Widget& Joystick(Pos* pos = nullptr, bool keep = 0, bool exp = 0);
Widget& Joystick_(AnyText name, Pos* pos = nullptr, bool keep = 0, bool exp = 0);

// Крестовина. Параметры: color + параметры виджета
Widget& Dpad(Pos* pos = nullptr);
Widget& Dpad_(AnyText name, Pos* pos = nullptr);

// Холст
// Холст, рисование. Ширина, длина. Только параметры виджета
Widget& BeginCanvas(uint16_t width = 400, uint16_t height = 300, Canvas* cv = nullptr, Pos* pos = nullptr);
Widget& BeginCanvas_(AnyText name, uint16_t width = 400, uint16_t height = 300, Canvas* cv = nullptr, Pos* pos = nullptr);

// Холст. Ширина, длина. Только параметры виджета
Widget& Canvas(uint16_t width = 400, uint16_t height = 300, Canvas* cv = nullptr, Pos* pos = nullptr);
Widget& Canvas_(AnyText name, uint16_t width = 400, uint16_t height = 300, gh::Canvas* cv = nullptr, Pos* pos = nullptr, bool begin = false);

// завершить холст
void EndCanvas();

// =================== ВЫВОД ====================
// Заголовок. Параметры: value (текст), icon, color, align, fontSize + size виджета
Widget& Title(AnyValue text);
Widget& Title_(AnyText name, AnyValue text);
Widget& Title_(AnyText name, Pairs* pairs);

// Надпись. Параметры: value (текст), icon, color, align, fontSize + параметры виджета
Widget& Label(AnyValue text);
Widget& Label_(AnyText name, AnyValue text);
Widget& Label_(AnyText name, Pairs* pairs);

// Окно с текстом. Параметры: value (текст), rows + параметры виджета
Widget& Text(AnyValue text);
Widget& Text_(AnyText name, AnyValue text);
Widget& Text_(AnyText name, Pairs* pairs);

// Окно с текстом. Параметры: value (путь), rows + параметры виджета
Widget& TextFile(AnyValue text);
Widget& TextFile_(AnyText name, AnyValue text);
Widget& TextFile_(AnyText name, Pairs* pairs);

// Дисплей. Параметры: value (текст), color, fontSize, rows + параметры виджета
Widget& Display(AnyValue text);
Widget& Display_(AnyText name, AnyValue text);
Widget& Display_(AnyText name, Pairs* pairs);

// Картинка. Параметры: value (путь) + параметры виджета
Widget& Image(AnyText text);
Widget& Image_(AnyText name, AnyText text);
Widget& Image_(AnyText name, Pairs* pairs);

// Лог. value(текст), rows + параметры виджета
Widget& Log(gh::Log* ptr);
Widget& Log_(AnyText name, gh::Log* ptr);

// Светодиод. Параметры: value (состояние 1/0), color + параметры виджета
Widget& LED(AnyPtr ptr);
Widget& LED_(AnyText name, AnyPtr ptr);

// Светодиод-иконка. Параметры: value (состояние 1/0), icon, fontSize, color + параметры виджета
Widget& Icon(AnyPtr ptr);
Widget& Icon_(AnyText name, AnyPtr ptr);

// Индикаторная шкала. Параметры: value (значение), range, unit, color + параметры виджета
Widget& Gauge(AnyPtr ptr);
Widget& Gauge_(AnyText name, AnyPtr ptr);

// Индикаторная шкала круглая. Параметры: value (значение), range, unit, color + параметры виджета
Widget& GaugeRound(AnyPtr ptr);
Widget& GaugeRound_(AnyText name, AnyPtr ptr);

// Индикаторная шкала линейная. Параметры: value (значение), icon, range, unit, color + параметры виджета
Widget& GaugeLinear(AnyPtr ptr);
Widget& GaugeLinear_(AnyText name, AnyPtr ptr);

// Таблица. Параметры: value (текст или путь) + параметры виджета
// text: таблица в формате CSV - разделитель столбцов ; разделитель строк \n
// width: ширина, список чисел в процентах (например "30;30;50")
// align: выравнивание, список из left | center | right (например "left;right")
Widget& Table(AnyText text, AnyText width, AnyText align);
Widget& Table_(AnyText name, AnyText text, AnyText width, AnyText align);
```
</details>
<details>
<summary>Параметры виджетов</summary>

```cpp
// ===================== BLOCK =====================
// Ширина (относительно) и высота (px) виджета
Widget& size(uint16_t width, uint16_t height = 0);

// Заголовок виджета
Widget& label(AnyText str);

// Убрать заголовок виджета
Widget& noLabel(bool nolabel = true);

// Дополнительный заголовок виджета справа
Widget& suffix(AnyText str);

// Убрать задний фон виджета
Widget& noTab(bool notab = true);

// Сделать виджет квадратным
Widget& square(bool square = true);

// Отключить виджет
Widget& disabled(bool disable = true);

// Подсказка виджета. Пустая строка - убрать подсказку
Widget& hint(AnyText str);

// ===================== CUSTOM =====================
// int/string/bool поле
Widget& param(AnyText key, AnyValue val);

// float поле
Widget& param(AnyText key, double val, uint8_t dec);

// ===================== VALUE =====================
// привязать переменную как значение
Widget& valueVar(AnyPtr data);

// int/string/bool значение
Widget& value(AnyValue val);

// float значение
Widget& value(double val, uint8_t dec);

// ===================== TEXT =====================
// текст
Widget& text(AnyText str);

// иконка (glyph или unicode) https://fontawesome.com/v5/search?o=r&m=free&s=solid
Widget& icon(AnyText str);

// максимальная длина текста
Widget& maxLen(uint16_t len);

// ===================== MISC =====================
// количество строк поля текста
Widget& rows(uint16_t rows);

// regex для Input и Pass
Widget& regex(AnyText str);

// выравнивание текста для label/title
Widget& align(gh::Align align);

// минимум, максимум и шаг изменения значения (float)
Widget& range(double min, double max, double step, uint8_t dec = 2);

// минимум, максимум и шаг изменения значения (целые числа)
template <typename T>
Widget& range(T min, T max, T step);

// единицы измерения
Widget& unit(AnyText str);

// размер шрифта/кнопки
Widget& fontSize(uint16_t size);

// цвет uint32_t 24 бит
Widget& color(uint32_t color);

// цвет gh::Colors
Widget& color(gh::Colors col);

// Действие (обновить файл, вызвать Confirm/Prompt)
Widget& action(bool act = 1);

// ===================== ACTION =====================
// Проверка на клик по виджету
bool click();

// ===================== ATTACH =====================
// Подключить функцию вида void f()
Widget& attach(void (*cb)());

// Подключить функцию вида void f(gh::Build& build)
Widget& attach(void (*cb)(gh::Build& build));

// Подключить функцию вида void f(gh::Builder& build)
Widget& attach(void (*cb)(gh::Builder& build), gh::Builder& b);

// Подключить gh::Flag* флаг
Widget& attach(gh::Flag* flag);

// Подключить bool* флаг
Widget& attach(bool* flag);
```
</details>
<details>
<summary>Прочие методы</summary>

```cpp
// обновить панель управления (по действию с виджета)
void refresh();

// был ли запрос на обновление панели управления
bool isRefresh();

// включить/выключить вывод виджетов (только для запроса виджетов)
bool show(bool en = true);

// было изменено значение виджета (сигнал на сохранение)
bool changed();

// номер текущего пункта меню
uint8_t menu();

// добавить виджеты из JSON строки
void addJSON(AnyText text);

// добавить виджеты из JSON строки PROGMEM
void addJSON_P(PGM_P text);

// добавить виджеты из JSON из файла
void addJSON_File(AnyText path);
```
</details>

## Canvas
<details>
<summary>Константы</summary>

```cpp
BUTT,
ROUND,
SQUARE,
PROJECT,
BEVEL,
MITER,
START,
END,
CENTER,
LEFT,
RIGHT,
ALPHABETIC,
TOP,
HANGING,
MIDDLE,
IDEOGRAPHIC,
BOTTOM,
SRC_OVER,
SRC_ATOP,
SRC_IN,
SRC_OUT,
DST_OVER,
DST_ATOP,
DST_IN,
DST_OUT,
LIGHTER,
COPY,
XOR,
TXT_TOP,
TXT_BOTTOM,
TXT_CENTER,
TXT_BASELINE,
CORNER,
CORNERS,
RADIUS,
```
</details>
<details>
<summary>Класс</summary>

```cpp
// подключить внешний буфер
void setBuffer(ghc::Packet* pp);

// добавить строку кода на js
Canvas& custom(AnyText text);

// =====================================================
// =============== PROCESSING-LIKE API =================
// =====================================================

// =================== BACKGROUND ======================
// очистить полотно
Canvas& clear();

// залить полотно установленным в fill() цветом
Canvas& background();

// залить полотно указанным цветом (цвет, прозрачность)
Canvas& background(uint32_t hex, uint8_t a = 255);

// ======================== FILL =======================
// выбрать цвет заливки (цвет, прозрачность)
Canvas& fill(uint32_t hex, uint8_t a = 255);

// отключить заливку
Canvas& noFill();

// ===================== STROKE ====================
// выбрать цвет обводки (цвет, прозрачность)
Canvas& stroke(uint32_t hex, uint8_t a = 255);

// отключить обводку
Canvas& noStroke();

// толщина обводки, px
Canvas& strokeWeight(int v);

// соединение линий: CV::MITER (умолч), CV::BEVEL, CV::ROUND
Canvas& strokeJoin(CV v);

// края линий: CV::PROJECT (умолч), CV::ROUND, CV::SQUARE
Canvas& strokeCap(CV v);

// ===================== PRIMITIVES ====================
// окружность (x, y, радиус), px
Canvas& circle(int x, int y, int r);

// линия (координаты начала и конца)
Canvas& line(int x1, int y1, int x2, int y2);

// точка
Canvas& point(int x, int y);

// четырёхугольник (координаты углов)
Canvas& quadrangle(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);

// треугольник (координаты углов)
Canvas& triangle(int x1, int y1, int x2, int y2, int x3, int y3);

// прямоугольник
Canvas& rect(int x, int y, int w, int h, int tl = -1, int tr = -1, int br = 0, int bl = 0);

// квадрат
Canvas& square(int x, int y, int w);

// режим окружности: CV::CENTER (умолч), CV::CORNER
Canvas& ellipseMode(CV mode);

// режим прямоугольника: CV::CORNER (умолч), CV::CORNERS, CV::CENTER, CV::RADIUS
Canvas& rectMode(CV mode);

// ======================= TEXT ========================
// шрифт
Canvas& textFont(const char* name);

// размер шрифта, px
Canvas& textSize(int size);

// вывести текст, опционально макс длина
Canvas& text(String text, int x, int y, int w = 0);

// выравнивание текста
// CV::LEFT, CV::CENTER, CV::RIGHT
// TXT_TOP, TXT_BOTTOM, TXT_CENTER, TXT_BASELINE
Canvas& textAlign(CV h, CV v);

// сохранить конфигурацию полотна
Canvas& push();

// восстановить конфигурацию полотна
Canvas& pop();

// ======================================================
// ================== HTML CANVAS API ===================
// ======================================================

// цвет заполнения
Canvas& fillStyle(uint32_t hex, uint8_t a = 255);

// цвет обводки
Canvas& strokeStyle(uint32_t hex, uint8_t a = 255);

// цвет тени
Canvas& shadowColor(uint32_t hex, uint8_t a = 255);

// размытость тени, px
Canvas& shadowBlur(int v);

// отступ тени, px
Canvas& shadowOffsetX(int v);

// отступ тени, px
Canvas& shadowOffsetY(int v);

// края линий: CV::BUTT (умолч), CV::ROUND, CV::SQUARE
// https://www.w3schools.com/tags/canvas_linecap.asp
Canvas& lineCap(CV v);

// соединение линий: CV::MITER (умолч), CV::BEVEL, CV::ROUND
// https://www.w3schools.com/tags/canvas_linejoin.asp
Canvas& lineJoin(CV v);

// ширина линий, px
Canvas& lineWidth(int v);

// длина соединения CV::MITER, px
// https://www.w3schools.com/tags/canvas_miterlimit.asp
Canvas& miterLimit(int v);

// шрифт: "30px Arial"
// https://www.w3schools.com/tags/canvas_font.asp
Canvas& font(AnyText v);

// выравнивание текста: CV::START (умолч), CV::END, CV::CENTER, CV::LEFT, CV::RIGHT
// https://www.w3schools.com/tags/canvas_textalign.asp
Canvas& textAlign(CV v);

// позиция текста: CV::ALPHABETIC (умолч), CV::TOP, CV::HANGING, CV::MIDDLE, CV::IDEOGRAPHIC, CV::BOTTOM
// https://www.w3schools.com/tags/canvas_textbaseline.asp
Canvas& textBaseline(CV v);

// прозрачность рисовки, 0.0-1.0
Canvas& globalAlpha(float v);

// тип наложения графики: CV::SRC_OVER (умолч), CV::SRC_ATOP, CV::SRC_IN, CV::SRC_OUT, CV::DST_OVER, CV::DST_ATOP, CV::DST_IN, CV::DST_OUT, CV::LIGHTER, CV::COPY, CV::XOR
// https://www.w3schools.com/tags/canvas_globalcompositeoperation.asp
Canvas& globalCompositeOperation(CV v);

// прямоугольник
Canvas& drawRect(int x, int y, int w, int h);

// скруглённый прямоугольник
Canvas& roundRect(int x, int y, int w, int h, int tl = 0, int tr = -1, int br = -1, int bl = -1);

// закрашенный прямоугольник
Canvas& fillRect(int x, int y, int w, int h);

// обведённый прямоугольник
Canvas& strokeRect(int x, int y, int w, int h);

// очистить область
Canvas& clearRect(int x, int y, int w, int h);

// залить
Canvas& fill();

// обвести
Canvas& stroke();

// начать путь
Canvas& beginPath();

// переместить курсор
Canvas& moveTo(int x, int y);

// завершить путь (провести линию на начало)
Canvas& closePath();

// нарисовать линию от курсора
Canvas& lineTo(int x, int y);

// ограничить область рисования
// https://www.w3schools.com/tags/canvas_clip.asp
Canvas& clip();

// провести кривую
// https://www.w3schools.com/tags/canvas_quadraticcurveto.asp
Canvas& quadraticCurveTo(int cpx, int cpy, int x, int y);

// провести кривую Безье
// https://www.w3schools.com/tags/canvas_beziercurveto.asp
Canvas& bezierCurveTo(int cp1x, int cp1y, int cp2x, int cp2y, int x, int y);

// провести дугу (радианы)
// https://www.w3schools.com/tags/canvas_arc.asp
Canvas& arc(int x, int y, int r, float sa = 0, float ea = TWO_PI, bool ccw = 0);

// скруглить
// https://www.w3schools.com/tags/canvas_arcto.asp
Canvas& arcTo(int x1, int y1, int x2, int y2, int r);

// масштабировать область рисования
// https://www.w3schools.com/tags/canvas_scale.asp
Canvas& scale(int sw, int sh);

// вращать область рисования (в радианах)
// https://www.w3schools.com/tags/canvas_rotate.asp
Canvas& rotate(float v);

// перемещать область рисования
// https://www.w3schools.com/tags/canvas_translate.asp
Canvas& translate(int x, int y);

// вывести закрашенный текст, опционально макс. длина
Canvas& fillText(AnyText text, int x, int y, int w = 0);

// вывести обведённый текст, опционально макс. длина
Canvas& strokeText(AnyText text, int x, int y, int w = 0);

// вывести картинку
// https://www.w3schools.com/tags/canvas_drawimage.asp
Canvas& drawImage(AnyText img, int x, int y);
Canvas& drawImage(AnyText img, int x, int y, int w);
Canvas& drawImage(AnyText img, int x, int y, int w, int h);
Canvas& drawImage(AnyText img, int sx, int sy, int sw, int sh, int x, int y, int w, int h);

// сохранить конфигурацию полотна
Canvas& save();

// восстановить конфигурацию полотна
Canvas& restore();
```
</details>
<details>
<summary>Обновление</summary>

```cpp
gh::CanvasUpdate(AnyText name, GyverHub* hub, Client* client = nullptr);

// отправить
void send();
```
</details>

## Типы данных
<details>
<summary>gh::Align</summary>

```cpp
Left
Center
Right
```
</details>
<details>
<summary>gh::Action</summary>

```cpp
UI
Read
Set
Get
None
```
</details>
<details>
<summary>gh::Reboot</summary>

```cpp
None
Button
Ota
OtaUrl
```
</details>
<details>
<summary>gh::Connection</summary>

```cpp
Serial
Bluetooth
WS
MQTT
HTTP
Telegram
System
```
</details>
<details>
<summary>gh::CMD</summary>

```cpp
UI
Ping
Unfocus
Info
Files
Format
Reboot
FetchNext
Data
Set
Get
Read
CLI
Delete
Rename
Create
FsAbort
Fetch
Upload
UploadChunk
Ota
OtaChunk
OtaUrl
Unix
Search
Discover
Unknown
```
</details>
<details>
<summary>gh::Colors</summary>

```cpp
Red = 0xcb2839,
Orange = 0xd55f30,
Yellow = 0xd69d27,
Green = 0x37A93C,
Mint = 0x25b18f,
Aqua = 0x2ba1cd,
Blue = 0x297bcd,
Violet = 0x825ae7,
Pink = 0xc8589a,
Default = 0xffffffff,
```
</details>
<details>
<summary>gh::Module</summary>

```cpp
ModUI
ModInfo
ModSet
ModRead
ModGet
ModData
ModReboot
ModFiles
ModFormat
ModDelete
ModRename
ModCreate
ModFetch
ModUpload
ModOta
ModOtaUrl
```
</details>

## Классы
<details>
<summary>gh::Button</summary>

```cpp
// состояние кнопки изменилось
bool changed();

// состояние кнопки (1 нажата, 0 отпущена)
bool state();

// клик по кнопке
bool clicked();
```
</details>
<details>
<summary>gh::Color</summary>

```cpp
uint8_t r = 0, g = 0, b = 0;

Color(uint8_t gray);
Color(Colors color);
Color(uint32_t hex, bool f);
Color(uint8_t v1, uint8_t v2, uint8_t v3, bool hsv = 0);

// установить RGB цвет
void setRGB(uint8_t nr, uint8_t ng, uint8_t nb);

// установить серый цвет 0.. 255
void setGray(uint8_t gray);

// установить цвет 24-бит RGB
void setHEX(uint32_t hex);

// установить цвет 16-бит RGB
void set565(uint16_t col);

// установить цвет HSV
void setHSV(uint8_t h, uint8_t s, uint8_t v);

// установить цвет по радуге (0.. 255)
void setHue(uint8_t color);

// получить 24-бит RGB цвет
uint32_t getHEX();

// получить 16-бит RGB цвет
uint16_t get565();
```
</details>
<details>
<summary>gh::CSVFile</summary>

```cpp
// создать таблицу (путь, столбцов, строк)
CSVFile(const char* path, uint8_t cols, uint16_t rows = 0);

// добавить int/string/bool
CSVFile& add(AnyValue value);

// добавить float
CSVFile& add(double value, uint8_t dec);

// завершить строку
void endRow(bool close = true);

// получить значение ячейки (столбец, строка)
String get(uint8_t col, uint16_t row);

// очистить таблицу
void clear();

// пересчитать количество строк (после ручного изменения)
void update();
```
</details>
<details>
<summary>gh::CSV</summary>

```cpp
// создать таблицу (столбцов, строк)
CSV(uint8_t cols, uint16_t rows = 0);

// зарезервировать строку
void reserve(uint32_t res);

// добавить int/string/bool
CSV& add(AnyValue value);

// добавить float
CSV& add(double value, uint8_t dec);

// завершить строку
void endRow();

// получить значение ячейки (столбец, строка)
String get(uint8_t col, uint16_t row);

// очистить таблицу
void clear();

// пересчитать количество строк (после ручного изменения)
void update();
```
</details>
<details>
<summary>gh::Flag</summary>

```cpp
bool changed();
```
</details>
<details>
<summary>gh::Flags</summary>

```cpp
Flags();
Flags(uint16_t nflags);

void clear(uint8_t idx);
void set(uint8_t idx);
void write(uint8_t idx, uint8_t val);
uint8_t get(uint8_t idx);
String toString();
```
</details>
<details>
<summary>gh::Log</summary>

```cpp
// начать и указать размер буфера
void begin(int n = 64);

// остановить
void end();

// прочитать в строку
void read(String* s, bool esc = false);

// прочитать строкой
String read();

// очистить
void clear();

// есть данные
bool available();

// запущен
bool state();

// длина
int length();
```
</details>

<details>
<summary>gh::Pos</summary>

```cpp
bool changed();

// расстояние до точки
uint16_t dist(int16_t x1, int16_t y1);

// точка лежит внутри прямоугольника
bool inRect(int16_t rx, int16_t ry, uint16_t w, uint16_t h);

// точка лежит внутри окружности
bool inCircle(int16_t cx, int16_t cy, uint16_t r);

// координата x
int16_t x = 0;

// координата y
int16_t y = 0;
```
</details>
<details>
<summary>gh::Timer</summary>

```cpp
// указать время. Таймер сам запустится в режиме интервала!
Timer(uint32_t ms, uint32_t seconds = 0, uint32_t minutes = 0, uint32_t hours = 0, uint32_t days = 0);

// =========== MANUAL ===========
// установить период
void setTime(uint32_t ms, uint32_t seconds = 0, uint32_t minutes = 0, uint32_t hours = 0, uint32_t days = 0);

// получить период
uint32_t getTime();

// запустить в режиме интервала (передать true для режима таймаута)
void start(bool timeout = false);

// запустить в режиме таймаута
void startTimeout();

// запустить в режиме интервала
void startInterval();

// перезапустить в текущем режиме
void restart();

// остановить
void stop();

// состояние (запущен?)
bool state();

// подключить функцию-обработчик вида void f()
void attach(TimerCallback callback);

// отключить функцию-обработчик
void detach();

// тикер, вызывать в loop. Вернёт true, если сработал
bool tick();
```
</details>

## Системные классы
<details>
<summary>gh::Bridge</summary>

```cpp
Bridge(void* hub, Connection conn, ghc::ParseHook parse);

// настроить
void config(void* hub, Connection conn, ghc::ParseHook parse);

// парсить url=data или url + data отдельно
void parse(AnyText url, AnyText data);

virtual void begin(){};
virtual void end(){};
virtual void tick(){};
virtual void send(BridgeData& data){};

Connection connection();    // тип подключения
void enable();              // включить
void disable();             // выключить
bool state();               // статус включен или выключен
void setFocus();            // установить focus
void clearFocus();          // снять focus
bool getFocus();            // получить focus
```
</details>
<details>
<summary>gh::Build</summary>

```cpp
const Action action;    // тип билда
Client& client;         // клиент
const AnyText name;       // имя компонента
const AnyText value;      // значение компонента
bool isSet();           // билд-действие
bool isUI();            // билд-запрос виджетов
Color valueColor();     // получить значение как Color
Flags valueFlags();     // получить значение как Flags
Pos valuePos();         // получить значение как Pos
```
</details>
<details>
<summary>gh::Client</summary>

```cpp
// тип подключения
Connection connection();

// id клиента
AnyText id;
```
</details>
<details>
<summary>gh::FS</summary>

```cpp
File openRead(String path);
File openAdd(String path);
File openWrite(String path);
bool begin();
void end();
bool mounted();
void format();
bool remove(String path, bool remdir = true);
bool rename(String from, String to);
bool exists(String path);
uint64_t freeSpace();
uint64_t totalSpace();
uint64_t usedSpace();
void mkdir(String path);
void rmdir(String path);
void listDir(String& str, String path, char div);
void showFiles(String& answ, String path, uint8_t levels = 0, uint32_t* count = nullptr);
```
</details>
<details>
<summary>ghc::Modules</summary>

```cpp
uint16_t mods = 0;

void set(uint16_t nmods);
void clear(uint16_t nmods);

void setAll();
void clearAll();
bool read(gh::Module m);
bool read(uint16_t m);
```
</details>
<details>
<summary>gh::Request</summary>

```cpp
Client& client; // клиент
const CMD cmd;  // событие
AnyText name;    // имя
AnyText value;   // значение
```
</details>
<details>
<summary>gh::Fetcher</summary>

```cpp
// отправить файл по пути
void fetchFile(const char* path);

// отправить файл
template <typename T>
void fetchFile(T& file);

// отправить сырые данные
void fetchBytes(uint8_t* bytes, uint32_t len);

// отправить сырые данные из PGM
void fetchBytes_P(const uint8_t* bytes, uint32_t len);

// true - начало скачивания
bool start;

// путь к скачиваемому файлу
AnyText path;
```
</details>
<details>
<summary>gh::Info</summary>

```cpp
// добавить int/string/bool поле в info
void add(AnyText label, AnyValue val);

// добавить float поле в info
void add(AnyText label, double val, uint8_t dec);

const Client& client;
Type type;

// Info::Type
// Version
// Network
// Memory
// System
```
</details>
<details>
<summary>gh::Update</summary>

```cpp
Update(GyverHub* hub, Client* client = nullptr);

// начать обновление по имени виджета (или список) + имя функции
Widget& update(AnyText name, AnyText func);

// отправить пакет
void send();

// текущий виджет для установки значений
ghc::Widget widget;
```
</details>

## Функции
<details>
<summary>Read</summary>

```cpp
// получить текстовое значение типа CMD для вывода в порт
FSTR gh::readCMD(CMD cmd);

// получить текстовое значение типа Connection для вывода в порт
FSTR gh::readConnection(Connection connection);

// получить текстовое значение типа Action для вывода в порт
FSTR gh::readAction(Action action);

// получить текстовое значение типа Reboot для вывода в порт
FSTR gh::readReboot(Reboot reason);
```
</details>
<details>
<summary>Position</summary>

```cpp
// расстояние между двумя точками
uint16_t gh::dist(int16_t x0, int16_t y0, int16_t x1, int16_t y1);

// точка лежит внутри прямоугольника (координаты угла и размеры)
bool gh::inRect(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t w, uint16_t h);

// точка лежит внутри окружности (координаты центра и радиус)
bool gh::inCircle(int16_t x, int16_t y, int16_t cx, int16_t cy, uint16_t r);
```
</details>