// базовый пример работы с библиотекой, основные возможности. Загрузи и изучай код // логин-пароль от роутера #define AP_SSID "Alex" #define AP_PASS "alexpass" #include #include GyverHub hub; // GyverHub hub("MyDevices", "ESP", ""); // можно настроить тут, но без F-строк! // обработчик кнопки (см. ниже) void btn_cb() { Serial.println("click 4"); } // обработчик кнопки с информацией о билде (см. ниже) void btn_cb_b(gh::Build& b) { Serial.print("click 5 from client ID: "); Serial.println(b.client.id); } // билдер void build(gh::Builder& b) { // =================== КОНТЕЙНЕРЫ =================== // основной контейнер страницы - столбец, т.е. виджеты будут располагаться на новых строках b.Button(); b.Button(); // СПОСОБ 1 // вот так можно сделать горизонтальный контейнер b.beginRow(); // начать b.Button(); b.Button(); b.endRow(); // ВАЖНО НЕ ЗАБЫТЬ ЕГО ЗАВЕРШИТЬ // СПОСОБ 2 // для красоты и удобства можно обернуть контейнер в блок {} // функции beginRow() и beginCol() всегда возвращают true if (b.beginRow()) { b.Button(); b.Button(); b.endRow(); // завершить } // СПОСОБ 3 // есть ещё такой трюк - контейнер сам себя закроет в рамках блока {} // назвать его можно как угодно, передать во внутрь аргумент билдера { gh::Row r(b); // контейнер сам создастся здесь b.Button(); b.Button(); } // контейнер сам закроется здесь // СПОСОБ 4 // и ещё вот такой макрос. Ширина контейнера 1 по умолчанию GH_ROW(b, 1, b.Button(); b.Button();); // для вертикального контейнера справедлив такой же синтаксис: // beginCol(), endCol(), gh::Col(), GH_COL() // =================== ШИРИНА =================== // ширина виджетов задаётся в "долях" - отношении их ширины друг к другу // виджеты займут пропорциональное место во всю ширину контейнера // если ширина не указана - она принимается за 1 { gh::Row r(b); b.Slider().size(3); // слайдер шириной 3 b.Button().size(1); // кнопка шириной 1 b.Button(); // тоже 1 b.Button(); } // посмотрим, как работает задание ширины контейнеру { gh::Row r(b); { // этот контейнер будет в 2 раза шире... gh::Row r(b, 2); b.Button(); b.Button(); } { // ...чем этот gh::Row r(b, 1); b.Button(); b.Button(); } } // =================== ПАРАМЕТРЫ ВИДЖЕТА =================== if (b.beginRow()) { // параметры виджета можно задавать цепочкой. Например: b.Button().label(F("my button 1")).color(gh::Colors::Red); // также можно продолжить настраивать ПРЕДЫДУЩИЙ виджет, обратившись к widget: b.Button(); // кнопка без параметров b.widget.label(F("my button 2")); // настраиваем кнопку выше b.widget.color(gh::Colors::Blue); // её же b.endRow(); } // =================== ДЕЙСТВИЯ ВИДЖЕТА =================== // с активных виджетов можно получить сигнал о действии - клик или изменение значения if (b.beginRow()) { // СПОСОБ 1 // проверить условие click() - он вернёт true при действии // click() нужно вызывать ПОСЛЕДНИМ в цепочке!!! if (b.Button().click()) Serial.println("click 1"); // СПОСОБ 2 // подключить bool переменную - флаг bool flag = 0; b.Button().attach(&flag); if (flag) Serial.println("click 2"); // СПОСОБ 3 // подключить gh::Flag переменную - флаг // данный флаг сам сбросится в false при проверке! gh::Flag gflag; b.Button().attach(&gflag); if (gflag) Serial.println("click 3"); // здесь gflag уже false // СПОСОБ 4 // подключить функцию-обработчик (см. выше) b.Button().attach(btn_cb); // СПОСОБ 5 // подключить функцию-обработчик с инфо о билде (см. выше) b.Button().attach(btn_cb_b); // attach() может быть НЕ ПОСЛЕДНИМ в цепочке, также их может быть несколько: // b.Button().attach(f1).attach(f2).label("kek"); b.endRow(); } // =============== ПОДКЛЮЧЕНИЕ ПЕРЕМЕННОЙ =============== if (b.beginRow()) { // библиотека позволяет подключить к активному виджету переменную для чтения и записи // я создам статические переменные для ясности. Они могут быть глобальными и так далее // таким образом изменения останутся при перезагрузке страницы static int sld; static String inp; static bool sw; // для подключения нужно передать переменную по адресу // библиотека сама определит тип переменной и будет брать из неё значение и записывать при действиях // библиотека поддерживает все стандартные типы данных, а также некоторые свои (Pairs, Pos, Button, Log...) b.Slider(&sld).size(2); b.Input(&inp).size(2); // внутри обработки действия переменная уже будет иметь новое значение: if (b.Switch(&sw).size(1).click()) { Serial.print("switch: "); Serial.println(sw); } b.endRow(); } // ==================== ОБНОВЛЕНИЕ ==================== // библиотека позволяет обновлять значения на виджетах. Это можно делать // - из основной программы (см. ниже) // - из билдера - но только при действиях по виджетам! // для отправки обновления нужно знать ИМЯ компонента. Его можно задать почти у всех виджетов // к функции добавляется подчёркивание, всё остальное - как раньше if (b.beginRow()) { b.Label_(F("label")).size(2).value("default"); // с указанием стандартного значения if (b.Button().size(1).click()) { hub.update(F("label")).value(random(100, 500)); } b.endRow(); } // в самом низу сделаем заголовок, текст будем обновлять из loop() (см. ниже) b.Title_(F("title")); // =================== ИНФО О БИЛДЕ =================== // можно получить информацию о билде и клиенте для своих целей // поставь тут 1, чтобы включить вывод =) if (0) { // запрос информации о виджетах 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(); } } void setup() { Serial.begin(115200); #ifdef GH_ESP_BUILD // подключение к роутеру WiFi.mode(WIFI_STA); WiFi.begin(AP_SSID, AP_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.println(WiFi.localIP()); // если нужен MQTT - подключаемся hub.mqtt.config("test.mosquitto.org", 1883); // hub.mqtt.config("test.mosquitto.org", 1883, "login", "pass"); // ИЛИ // режим точки доступа // WiFi.mode(WIFI_AP); // WiFi.softAP("My Hub"); // Serial.println(WiFi.softAPIP()); // по умолч. 192.168.4.1 #endif // указать префикс сети, имя устройства и иконку hub.config(F("MyDevices"), F("ESP"), F("")); // подключить билдер hub.onBuild(build); // запуск! hub.begin(); } void loop() { // =================== ТИКЕР =================== // вызываем тикер в главном цикле программы // он обеспечивает работу связи, таймаутов и прочего hub.tick(); // =========== ОБНОВЛЕНИЯ ПО ТАЙМЕРУ =========== // в библиотеке предусмотрен удобный класс асинхронного таймера static gh::Timer tmr(1000); // период 1 секунда // каждую секунду будем обновлять заголовок if (tmr) { hub.update(F("title")).value(millis()); } }