GyverPortal

pingemall

✩✩✩✩✩✩✩
22 Мар 2020
25
0
Родина
www.mj2cnc.kh.ua
@ASM, Это намного красивее (y), значение "width" - это чья ширина задается, подвигал его но визуально ничего.

p.s.: &nbsp помог если не хватает символов для выравнивания o_O, пока другого решения не знаю.
1665340494134.png
1665340549665.png
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@ASM, таблица это + пару килограмм кода, не Москву пишу :D
На самом деле всё гораздо проще. Вчера минут за 15-20 написал и опробовал custom функции создания таблиц. Есть одна прелесть в таблицах - объединение ячеек по вертикале и по горизонтали. Так же классная вещь - вертикальное выравнивание. Вёрстка таблицами очень простая, и очень быстрая. Наверное есть ещё один факт - для задания ширины столбцов, достаточно её указывать только в первой строке, столбцы следующих строк автоматом подтянут ширину. Прелесть портала в том, что есть файл custom.h, где можно без проблем делать свои функции, при загрузке новой либры, главное не забыть перекинуть этот файл и всё дальше будет работать.

И ещё, Вы создаёте бокс шириной 50 px, в него пихаете нумбер шириной 80 px, как то не правильно, плюс как выход - надо размерность кинуть в отдельный блок и сделать для него фиксированную ширину... Тогда правый блок у Вас будет фиксированной ширины
 
Изменено:

juri4

✩✩✩✩✩✩✩
11 Сен 2022
15
0
Подключаю стили из файлов, но что-то идет не так.2022-10-10_07-54.png
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@juri4, Включен ли автодовнлоад? как инициируете запуск портала? Загрузили ли файлы на флеш память через утилиту? Вместо картинок лучше код дайте из loop или из setup... там где Вы пишите portal.start(); Где то в этой теме я уже отвечал как правильно это делать, на всякий вот вкратце:
C++:
#define AP_SSID ""
#define AP_PASS ""

#include <LittleFS.h>

#include <GyverPortal.h>
GyverPortal portal(&LittleFS);

// конструктор страницы
void build() {
//для подключения скриптов из файла /gp_data/scripts.js
  GP.BUILD_BEGIN_FILE();
//для подключения файла css и js в папке с проектом надо создать папку data, в ней надо создать gp_data и туда положить файл GP_DARK.css
// с помощью инструментов залить файлы на ESP32
  GP.THEME_FILE("GP_DARK")
// Если используется обновление через jquery
  GP.JQ_SUPPORT_FILE(); // Загрузка jquery /gp_data/jquery.js (он по факту 1 раз грузанёт и закешет, но его тоже надо положить в папку)
//тут Ваш код конструктора

  GP.BUILD_END();
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(AP_SSID, AP_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP());

  if (!LittleFS.begin()) Serial.println("FS Error");

  portal.attachBuild(build);
  portal.attach(action);
  portal.start();
  portal.downloadAuto(true); //включите автодовнлоад
}

void action() {
    // код обработчика
}

void loop() {
  portal.tick();
}
 
Изменено:

juri4

✩✩✩✩✩✩✩
11 Сен 2022
15
0
Видно что файлы с флэш загружаются, но почему-то не работают.

C++:
void setup()
{
    // delay(2000);
    Serial.begin(115200);
    LittleFS.begin();
    portal.downloadAuto(true);
    portal.uploadAuto(true);
    if (!digitalRead(D2))
        nvsFlashErase();
    Serial.println();
    preferences.begin("WiFiLPI", false);
    ssid = preferences.getString("ssid");
    pass = preferences.getString("pass");
    APssid = preferences.getString("apssid");
    APpass = preferences.getString("appass");
    IPadress = preferences.getString("wifistaip");
    APIPadress = preferences.getString("wifiapip");
    chkAP = preferences.getBool("chkap");
    chkSTA = preferences.getBool("chksta");
    Serial.println("chkAP" + String(chkAP));
    Serial.println("chkSTA" + String(chkSTA));
    if (chkAP == 1 && chkSTA == 1) {
        WiFi.mode(WIFI_MODE_APSTA);
        wifiAPConnect();
        wifiStaConnect();
    } else if (chkSTA) {
        WiFi.mode(WIFI_MODE_STA);
        wifiStaConnect();
        APIPadress = "не получен";
        if (WiFi.status() != WL_CONNECTED) {
            WiFi.mode(WIFI_MODE_AP);
            wifiAPConnect();
        }
    } else {
        WiFi.mode(WIFI_MODE_AP);
        wifiAPConnect();
        IPadress = "не получен";
    }
    portal.enableOTA();
    portal.attachBuild(buildLP);
    portal.attach(actionLP);
    portal.start();
    preferences.putString("wifistaip", IPadress);
    preferences.putString("wifiapip", APIPadress);
    if (!LittleFS.begin())
        Serial.println("FS Error");
}
void loop() { portal.tick(); }
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@juri4,
Вот эту строку я не вижу, это обязательно!
GyverPortal portal(&LittleFS);

Видно что просто прилетает 933 байта, скорее всего это просто ответная страница подтип 404 о том, что файл не найден.
В строке браузера введите http://192.168.1.193/gp_data/GP_LIGHT.css
при правильной настройке у вас должен открыться css файл
 
  • Лойс +1
Реакции: juri4

juri4

✩✩✩✩✩✩✩
11 Сен 2022
15
0
@DAK,
строка
GyverPortal portal(&LittleFS);
раньше сетапа идет.
- весь код
C++:
//#include <EEPROM.h>
#include <GyverPortal.h>
#include <LittleFS.h>
#include <Preferences.h>
#include <nvs_flash.h>
#define D2 14
int timeConnect = 0;

String ssid;
String pass;
String APssid = "SAM";
String APpass = "12345678";
String IPadress;
String APIPadress;
bool chkAP = 1;
bool chkSTA = 1;

Preferences preferences;
GyverPortal portal(&LittleFS);

void wifiStaConnect()
{
    // WiFi.mode(WIFI_STA);
    WiFi.begin(ssid.c_str(), pass.c_str());
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
        if (timeConnect > 10)
            break;
        else
            timeConnect++;
    }
    if (WiFi.status() == WL_CONNECTED) {
        IPadress = WiFi.localIP().toString();
    } else {
        APIPadress = WiFi.softAPIP().toString();
        IPadress = "не выдан";
    }
    Serial.println();
    Serial.println("STA ssid:     " + ssid);
    Serial.println("STA IP адрес: " + IPadress);
    preferences.putString("wifistaip", IPadress);
}

void wifiAPConnect()
{
    WiFi.softAP(APssid.c_str(), APpass.c_str());
    APIPadress = WiFi.softAPIP().toString();
    Serial.println();
    Serial.println("AP ssid:     " + APssid);
    Serial.println("AP IP адрес: " + APIPadress);
    preferences.putString("wifiapip", APIPadress);
};

void buildLP()
{
    // BUILD_BEGIN();
    GP.BUILD_BEGIN_FILE();
    //GP.THEME(GP_DARK);
    GP.THEME_FILE("GP_LIGHT");
      //GP.JQ_SUPPORT();      // поддержка jquery. Файл скачается с https://code.jquery.com/
    GP.JQ_SUPPORT_FILE();   // поддержка jquery, файл скачается из файла /gp_data/jquery.js
    GP.NAV_TABS_LINKS("/,/settings,/updates", "Главная,Настройки,Обновление");
    if (portal.uri("/settings")) {
        GP.BUTTON_LINK("/login", "WiFi");
        GP.BUTTON_LINK("/", "Back");
    }
    if (portal.uri("/login")) {
        GP.FORM_BEGIN("/login");
        GP_MAKE_BLOCK_TAB("Авторизация -клиент",
                          GP_MAKE_BOX(GP.LABEL("Логин"); GP.TEXT("lg", "Логин", ssid););
                          GP_MAKE_BOX(GP.LABEL("Пароль"); GP.PASS("ps", "Пароль", pass););
                          GP_MAKE_BOX(GP.LABEL("Включить"); GP.CHECK("chksta", chkSTA););
                          GP.LABEL("IP адрес " + IPadress););

        GP_MAKE_BLOCK_TAB("Авторизация -точка доступа",
                          GP_MAKE_BOX(GP.LABEL("Логин"); GP.TEXT("aplg", "Логин", APssid););
                          GP_MAKE_BOX(GP.LABEL("Пароль"); GP.PASS("apps", "Пароль", APpass););
                          GP_MAKE_BOX(GP.LABEL("Включить"); GP.CHECK("chkap", chkAP););

                          GP.LABEL("IP адрес " + APIPadress););
        GP.SUBMIT("Подтвердить");
        GP.FORM_END();
    }

    else {
        GP.FORM_BEGIN("/");
        GP.BUTTON_LINK("/save", "Form");
        GP.BUTTON_LINK("/clicks", "Clicks");
        GP.BUTTON_LINK("/updates", "Updates");
        GP.FORM_END();
    }
    BUILD_END();
}

void actionLP(GyverPortal& p)
{
    if (p.form()) {
        if (p.form("/login")) { // кнопка нажата
            p.copyString("lg", ssid); // копируем себе
            p.copyString("ps", pass);
            p.copyString("aplg", APssid); // копируем себе
            p.copyString("apps", APpass);
            p.copyBool("chkap", chkAP);
            p.copyBool("chksta", chkSTA);
            if (chkAP == 0 && chkSTA == 0)
                chkAP = 1;
            preferences.putString("ssid", ssid);
            preferences.putString("pass", pass);
            preferences.putString("apssid", APssid);
            preferences.putString("appass", APpass);
            preferences.putBool("chksta", chkSTA);
            preferences.putBool("chkap", chkAP);
            Serial.println("start ");
            Serial.println("Connect to: ");
            Serial.println(ssid);
            wifiStaConnect();
            Serial.print("Restart ");
            preferences.end();
            ESP.restart();
        }
    }
}

void nvsFlashErase()
{
    Serial.println("erase nvs");
    nvs_flash_erase(); // erase the NVS partition and...
    nvs_flash_init(); // initialize the NVS partition.
    while (true)
        ;
    ESP.restart();
}

void setup()
{
    // delay(2000);
    Serial.begin(115200);
    LittleFS.begin();
    portal.downloadAuto(true);
    portal.uploadAuto(true);
    if (!digitalRead(D2))
        nvsFlashErase();
    Serial.println();
    preferences.begin("WiFiLPI", false);
    ssid = preferences.getString("ssid");
    pass = preferences.getString("pass");
    APssid = preferences.getString("apssid");
    APpass = preferences.getString("appass");
    IPadress = preferences.getString("wifistaip");
    APIPadress = preferences.getString("wifiapip");
    chkAP = preferences.getBool("chkap");
    chkSTA = preferences.getBool("chksta");
    Serial.println("chkAP" + String(chkAP));
    Serial.println("chkSTA" + String(chkSTA));
    if (chkAP == 1 && chkSTA == 1) {
        WiFi.mode(WIFI_MODE_APSTA);
        wifiAPConnect();
        wifiStaConnect();
    } else if (chkSTA) {
        WiFi.mode(WIFI_MODE_STA);
        wifiStaConnect();
        APIPadress = "не получен";
        if (WiFi.status() != WL_CONNECTED) {
            WiFi.mode(WIFI_MODE_AP);
            wifiAPConnect();
        }
    } else {
        WiFi.mode(WIFI_MODE_AP);
        wifiAPConnect();
        IPadress = "не получен";
    }
    portal.enableOTA();
    portal.attachBuild(buildLP);
    portal.attach(actionLP);
    portal.start();
    preferences.putString("wifistaip", IPadress);
    preferences.putString("wifiapip", APIPadress);
    if (!LittleFS.begin())
        Serial.println("FS Error");
}
void loop() { portal.tick(); }
 
Изменено:

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@juri4, тогда не знаю, может просто неправильно написали каталог, букавка русская где нить оказалась. В Вашем пректе должна лежать папка data, в этой дате должна лежать папка gp_data и уже в ней файлы из библиотеки. Работает как часы, ну как вариант перезагрузите браузер через сочетание ctrl+F5
 
  • Лойс +1
Реакции: juri4

juri4

✩✩✩✩✩✩✩
11 Сен 2022
15
0
@DAK,
Папку просто скопировал из библиотеки вместе со всеми файлами.
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@juri4,

Вы точно папку записали на Микроконтроллер через пункт меню в инструментах? Пробовали через браузер по адресу заходить, что вам броузер ответил? выдал css? На всякий случай сделайте скрин исходного кода страницы.
 
  • Лойс +1
Реакции: juri4

juri4

✩✩✩✩✩✩✩
11 Сен 2022
15
0
Спасибо!
Проблему нашел.
- библиотека LittleFS не подходила, хотя все и компилировалось и вроде работала(не работала)).
Немного пришлось все поправить в названиях.
У Вас наверное 8266 потому заработало с полпинка)

PS.
То что смог съесть arduino ide , Platformio не смог - рассыпается веером ошибок.
ХЗ как теперь быть привязанным к arduino ide.
 
Изменено:

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
Ну в ишью уже было это, платформио заноза в задинице(слова Алекса) при работе с esp
 
  • Лойс +1
Реакции: juri4

pingemall

✩✩✩✩✩✩✩
22 Мар 2020
25
0
Родина
www.mj2cnc.kh.ua
Кто подскажет почему в примере "webSerial" теряется плюс:
C++:
if (portal.click("btn")) {
    // отправляем обратно в "монитор" содержимое поля, оно пришло по клику кнопки
    portal.log.println(portal.getString("btn"));
1665604621401.png
если в uart кидать тоже самое.
C++:
Serial.println(portal.getString("btn"));
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
а если открыть инструменты администрирования и посмотреть какие данные уходят запросом из браузера. Чтобы понять где теряется плюс, при преобразовании в portal.h или при обработке явой для дальнейшей отсылки?
 

vitek1658

✩✩✩✩✩✩✩
27 Май 2022
5
0
Здравствуйте! После долгих мучений, так и не получилось у меня с html, а вот с led результат есть. На тему radiobuttons. Сделал на кнопках, с текстом клики работать упорно не хотели. Поэтому: уважаемые разработчики, добавьте пожалуйста доп цвет формата GP_цвет, чтоб кнопки можно было сделать в цвет фона; и, если кто знает, пожалуйста объясните как заменить кнопки на текст. Заранее благодарю!
C++:
const char* ssid     = "ESP8266-Access-Point";
const char* password = "123456789";

#include <GyverPortal.h>
GyverPortal portal;
bool led = false;
bool led1 = false;
bool led2 = false;
bool led3 = false;

void build() {
  GP.BUILD_BEGIN();
  GP.THEME(GP_DARK);
  GP.UPDATE("led,led1,led2,led3");
  GP.TITLE("Title", "t1");
  GP.HR();
  GP.LED_RED("led", led);
  GP.BUTTON("btn1", "Button1", "", GP_GRAY);
  GP.BUTTON("btn2", "Button2", "", GP_GRAY);
  GP.HR();
  GP_MAKE_BOX(GP.UPDATE("led1"); GP.LED_RED("led1", led1); GP.BUTTON("btn3", "Button1", "", GP_GRAY););
  GP_MAKE_BOX(GP.UPDATE("led2"); GP.LED_RED("led2", led2); GP.BUTTON("btn4", "Button2", "", GP_GRAY););
  GP_MAKE_BOX(GP.UPDATE("led3"); GP.LED_RED("led3", led3); GP.BUTTON("btn5", "Button3", "", GP_GRAY););
  GP.BUILD_END();
}

void setup() {
Serial.begin(115200);
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  // подключаем конструктор и запускаем
  portal.attachBuild(build);
  portal.attach(action);
  portal.start(WIFI_AP);
}


void action() {
  if (portal.update()) {
  if (portal.update("led")) portal.answer(led);
  if (portal.update("led1")) portal.answer(led1);
  if (portal.update("led2")) portal.answer(led2);
  if (portal.update("led3")) portal.answer(led3);
  }
  // был клик по компоненту
  if (portal.click()) {
    // проверяем компоненты и обновляем переменные
   if (portal.click("btn1")) {
    Serial.println("Button1 click");
   led = true;
   }
   if (portal.click("btn2")) {
    Serial.println("Button1 click");
   led = false;
   }
   if (portal.click("btn3")) {
    Serial.println("Button1 click");
   led1 = true; led2 = false; led3 = false;
   }
   if (portal.click("btn4")) {
    Serial.println("Button1 click");
   led1 = false; led2 = true; led3 = false;
   }
   if (portal.click("btn5")) {
    Serial.println("Button1 click");
   led1 = false; led2 = false; led3 = true;
   }
  }
}

void loop() {
  portal.tick();
}
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@vitek1658, Убейте меня, не понял ничего. Самое главное, что я не понял, это зачем в 4 раза вызываете UPDATE, когда достаточно 1 раза.Что конкретно вы хотите сделать?

Будет в первой строке светодиод и 2 кнопки, включить и выключить, ниже будет 3 светодиода, 3 кнопки на включение того или иного диода... А как надо? Чтобы счелчок по светодиоду давал события клика для дальнейшей обработки?
 
Изменено:

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@juri4, в смысле не может, он так и делает! События прилетают в action, там их обрабатываешь. События типа клик обрабатываешь и меняешь переменные (можно сделать глобальные переменные, можно класс задействовать), потом эти переменные можно отдавать по событию update

С точки зрения организации у @vitek1658, сделано всё верно, только мне кажется, что он хочет, чтобы по клику на radio уходили события, а они не уходят, так как клики по радио тяжело обрабатывать, зачастую криво косо получается, поэтому с них события в портале не обрабатываются. Обработка этих событий вызвала бы кучу проблем у многих пользователей. Но всегда есть кастом, можно допилить функционал под себя.
 

juri4

✩✩✩✩✩✩✩
11 Сен 2022
15
0
@DAK, не успел удалить. имелось ввиду -из програгаммы .
Update пробегает за указанное время все переменные и если нужно - обновляет их.
Если к примеру нужно будет обновлять поле ввода из программы и иметьвозможность вносить пальцами, из за обновления - внести данные в это поле пальцами не получится.
А у Vitek1658 совсем не про то - потому хотел сообщение удалить - было не в тему.
 
Изменено:

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@juri4, :)
Это логично, не надо в update пихать поля, через которые планируется текствоый ввод данных... Так же, при использовании jquery update между началом секции обновления и концом не должно быть текстовых и цифровых полей ввода.

upd:
вообще всё зависит от задачи, надо понять конкретную задачу, чтобы посоветовать конкретное решение.
 

vitek1658

✩✩✩✩✩✩✩
27 Май 2022
5
0
Да да, с update я перестарался, каюсь. Задача была оч простая, сделать выборку как в андроиде - radiobutton. Мне ранее сказали (2-3 страницы назад), что радиобаттон упразнили в лед, но в лед нет подписей у светодиодов, чтоб сделать список. Использование кнопок меня не пугает, но текст красивее.
Первые две кнопки так и должны работать, я просто хотел показать алгоритм своих мыслей. А три последние кнопки в режиме некого "radiobutton".

upd: а на счет кнопки в цвет фона, мне будет достаточно и значения в формате "#rrggbb", благо эта функция в настройках кнопки доступна.
Заранее благодарю!

upd: и, существует ли возможность менять размер шрифта на элементах (кнопки, текст, и т.д.)? Крупнее и мельче.
 
Изменено:

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
radio никогда не имело подписей, только значения, даже в стандартном html, но это не суть важно. Я в таком случае использую селект... При этом выпросил функцию автоматической перезагрузки страницы после изменения селекта. как вариант ещё минибутон разного цвета, я использую кнопки разного цвета, щёлкнул на кнопку, она покраснела, счёлкнул на другую, одна позеленела, другая покраснела. У мини кнопок и просто кнопок тоже есть функция перезагружать всю страницу после клика. То есть вы коикаете, уходит собвтие в обработчик, а параллельно браузер направляет запрос на перезагрузку через неколе кол-во мс ( что то вроде 150, но это можно утсановить через функцию конструктора). Я только этим и спсаюсь, очень полезно при сложном интерфейсе. С radio же всё сложнее, им надо давать одинаковое имя, они реагируют в основном на change, а при click-е не всегда ясно что оно отдаст...., это удобно использовать в формах, но если честно, я сколько чего не писал, но радио везде поменял на select, даже в простом LAMP с ними приходится хлебнуть горя.

Если кому интересно, могу подробнее, но уже не сегодня... А вообще в вики там есть пару слов про это
 
  • Лойс +1
Реакции: juri4

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@juri4, Короче, ниже маленький пример с автоматическим ребутом после нажатия кнопки (за основу взял ваш код, допихал в него малость, поубирал немного, прошу заметить, что update полностью выпилен, однако всё будет работать). Можно в принципе и jquery update подключить, при этом поставить в нём секунд 10. jquery update после прихода события клика обновляет часть кода, которая стоит между тегами обновления, но так же автоматом обновляет компоненты по заданному интервалу. Просто я не знаю что у вас залито на файловую систему, а чего не залито... Код ниже проверил, у меня работает.
C++:
const char* ssid     = "ESP8266-Access-Point";
const char* password = "123456789";

#include <GyverPortal.h>
GyverPortal portal;
bool led = false;
bool led1 = true;
bool led2 = false;
bool led3 = false;
int sel = 0;

void build() {
//Устанавливаем время в мс, то есть после нажатия на кнопки через заданное кол-во мс будет перезагрузка страницы
  GP.setReloadTimeout(150);
  GP.BUILD_BEGIN();
  GP.THEME(GP_DARK);
  GP.TITLE("Title", "t1");
  GP.HR();
  GP.LED_RED("led", led);
//Кнопка в режиме триггера, хотя я бы юзал switch, просто для примера
  GP.BUTTON_MINI("led","0","",led?GP_RED:GP_GREEN,"",false,true);
  GP.HR();
//3 кнопки в режиме третичного триггера
  GP_MAKE_BOX(
    GP.BUTTON_MINI("led1","-1-","",led1?GP_GREEN:GP_RED,"",false,true);
    GP.BUTTON_MINI("led2","-2-","",led2?GP_GREEN:GP_RED,"",false,true);
    GP.BUTTON_MINI("led3","-3-","",led3?GP_GREEN:GP_RED,"",false,true);
  );
  GP.SELECT("sel","btn1,btn2,btn3", sel,false,false,true);
  GP.BUILD_END();
}

void setup() {
Serial.begin(115200);
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  // подключаем конструктор и запускаем
  portal.attachBuild(build);
  portal.attach(action);
  portal.start(WIFI_AP);
}


void action() {
  // был клик по компоненту
  if (portal.click()) {
    // проверяем компоненты и обновляем переменные
    if (portal.click("led")) {
      Serial.println("Button1 click");
      led = !led;
    }
    if (portal.click("led1")) {
      Serial.println("Button1 click");
      led1 = true; led2 = false; led3 = false;sel=0;
    }
    if (portal.click("led2")) {
       Serial.println("led2 click");
       led1 = false; led2 = true; led3 = false;sel=1;
    }
    if (portal.click("led3")) {
      Serial.println("led3 click");
      led1 = false; led2 = false; led3 = true;sel=2;
    }
    if (portal.click("sel")) {
      Serial.println("sel click");
      sel=portal.getInt("sel");
      if (sel==0){
        led1 = true; led2 = false; led3 = false;
      } else if (sel==1){
        led1 = false; led2 = true; led3 = false;
      } else if (sel==2){
        led1 = false; led2 = false; led3 = true;
      }
    }
  }
}

void loop() {
  portal.tick();
}
 
  • Лойс +1
Реакции: juri4 и vitek1658