GyverHUB, обсуждение библиотеки

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
Виноват, погорячился. Не глянул, был уверен, что она работает на прерываниях, уж очень хорошо и мгновенно отрабатывала.
Проверял факт срабатывания по факту выводом в консоль промежуточных результатов. Зря Вы гоните на неё, код срабатывает по факту смены состояния, смотрите обработку флагов, просто и элегантно. Попытаюсь заюзать Вашу библиотеку, спасибо за ссылку. О результатах отпишусь.
 

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
да чего на неё гнать, то... самая примитивная либа для кнопок какую только можно написать. Она бесконечно читает состояние пина в цикле - естественно она будет выдавать его состояние по факту, ну плюс задержка у неё есть антидребезг, не более того. Это ни хорошо, ни плохо это примитивный бесконечный опрос пинов. Соответственно если вы бесконечно опрашивате ее состояние, то ваше условие срабатывать будет бесконечно.

напишите вот так и всё увидите
Код:
if(boiler1RelayI.isPressed()){
   hub.update("IBoiler1Relay").value(1); 
   Serial.println("update Hub value: 1");
}
if(boiler1RelayI.isReleased()){
   hub.update("IBoiler1Relay").value(0);
   Serial.println("update Hub value: 0");
}
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
@vortigont,
Это первое, что я сделал при проверке этой либы... Всё там ОК с реакцией только по факту изменения.

Смотрел Вашу библиотеку, на ней нет поддержки 8266, для меня это необходимо. Сделал на этом говне, 8266, кучу простейших автоматизаций для знакомых: кому домофон из Телеграм открыть, кому удалённо электронагреватель на даче включить и контролировать. Приходится поддерживать этот зоопарк теперь и, по мере накопления опыта, переводить на нормальный код. Сам, естественно, буду впредь юзать только ESP32, мне понравилось грузить оба ядра разными действиями. :).

Разочарован уровнем написания библиотек под ESP. Нам 30 лет назад говорили: "Самое эффективное и оптимальное - использование аппаратных прерываний". Почему бы их не используют в библиотеках, предназначенных имеенно для этого, - работа с портами - хз, я был уверен в том, что все они основны именно на аппаратных прерываниях, схватил одну не глядя... Надо смотреть, всё проверять, уровень там - действительно простейший, вопреки ожиданиям...
Сейчас попытался работать вот с этой:

И вот возникает вопрос... Почему показометр нагрузки процессора wokwi при реализации аппаратного прерывания показывает 65-74%, а при прямом непрерывном опросе пинов: 38-41%. Что за...??? Ещё один пример говнокода, цитируемый во всех советах по "оптимизации" кнопкодавления в интернетах?
Обычный код классического использования прерывания, без всяких библиотек и дебаунсеров выдаёт 30-32% :). Начинаю прозревать.
 
Изменено:

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
Всё там ОК с реакцией только по факту изменения.
не знаю как там может быть "всё ОК", если при "нажатой" кнопке метод button.isPressed() возвращает false и в этом же состоянии button.isReleased() так же возвращает false, то с этой либой явно что-то не так. Кнопка ни нажата ни отжата, посередине зависла? :)
Если автор имел ввиду какую-то другую логику работы этих методов, то с интуитивно понятным названием он явно промахнулся.

Почему показометр нагрузки процессора wokwi
потому что это "показометр". В "ардуно" где крутится бесконечный loop() и в нем есть хоть один вызов загрузка процессора всегда 100%, ничего другого там быть не может. Сколько бы ни было ресурсов, всё будет отдано под этот бесконечный цикл.
 

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
Сейчас попытался работать вот с этой:
а зачем вам прерывания если всё равно в луп воткнут какой-то вызов?
Код:
void loop() {
  // keep watching the push button, even when no interrupt happens:
  button.tick();
}
это все равно что заходить в автобус с проездным и еще покупать билет у водителя )
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
Вот такая вот судьба у порта на прерывании... Выгодней сделать в loop обработку по флагу прерывания, чем тормозить весь процессор, засовывая в функцию прерывания вот это вот всё. Смотрел код уважаемого Гайвера- так он завсегда так делает. И да, с показометром загрузки процессора wokwi - всё ок. Показывает как надо, очень помогает быстро прикинуть оптимальность кода.
 
Изменено:

Rushns

✩✩✩✩✩✩✩
11 Июл 2024
3
0
@gidiara666,Насчет телеграмма я не уверен, когда в Башкортостане заблокировали ватсап и телегу все ESP в которых я использовал телегу жутко тормозили (loop() отрабатывал где то 1 в 10 секунд, считай что устройства просто отказали). Пришлось экстренно вырезать весь телеграмм с кода и оставил только mqtt, благо с ним таких тормозов нет. Телегу использую через wqtt только для оповещения..
 

to0freak

✩✩✩✩✩✩✩
20 Окт 2022
2
0
Всем привет! Кто-нибудь сможет подсказать, как принудительно обновить хаб? Пытаюсь сделать лог через соответствующий виджет. Подключил класс gh::log и нормально с ним работаю, но дело в том, что при длительной работе другой функции и вызова внутри неё команды sendUpdate, та срабатывает не каждый раз - в монитор порта идёт информация, что команда прошла, но отображение виджета не меняется.
Возможно есть флаг, который скажет, что всё обновилось, чтобы программа продолжила цикл?
 

ASM

★★★★★✩✩
26 Окт 2018
1,721
350
@to0freak, если обновить страницу b.refresh();
можно и так
C++:
b.Label_("name", code);

loop(){
// два способа
    hub.sendUpdate("name");
    hub.update("name").value(code);
}
 
Изменено:

to0freak

✩✩✩✩✩✩✩
20 Окт 2022
2
0
@to0freak, если обновить страницу b.refresh();
можно и так
C++:
b.Label_("name", code);

loop(){
// два способа
    hub.sendUpdate("name");
    hub.update("name").value(code);
}
hub.sendRefresh(); помогло. Спасибо за наводку
 

messaf

✩✩✩✩✩✩✩
2 Апр 2020
1
0
Здравствуйте товарищи.
Столкнулся с такой проблемой:
- ESP32 + GSM SIM800C.
Пытаюсь воспользоваться примером использования стороннего моста MQTT: https://github.com/GyverLibs/GyverHub/blob/main/examples/manual/manual_mqtt/manual_mqtt.ino
Использую библиотеку TinyGSM: https://github.com/vshymanskyy/TinyGSM/tree/master/examples/MqttClient
Мой код:
C++:
#define GH_NO_MQTT    // отключить встроенный модуль связи mqtt (для esp)
#include <GyverHub.h>
GyverHub hub;

// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800   // Modem is SIM800
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false

#define SerialAT Serial1
#include <TinyGsmClient.h>
TinyGsm modem(SerialAT);

#include <PubSubClient.h>
TinyGsmClient gsmClient(modem);

class HubMQTT : public gh::Bridge {
   public:
    HubMQTT(void* hub) : gh::Bridge(hub, gh::Connection::MQTT, GyverHub::parseHook), mqtt(gsmClient){}

    void begin() {
        mqtt.setServer("test.mosquitto.org", 1883);
        mqtt.setCallback([this](char* topic, uint8_t* data, uint16_t len) {
            uint16_t tlen = strlen(topic);
            char topic_buf[tlen + 1];
            memcpy(topic_buf, topic, tlen);
            topic_buf[tlen] = 0;

            char data_buf[len + 1];
            memcpy(data_buf, data, len);
            data_buf[len] = 0;

            parse(sutil::AnyText(topic_buf, tlen), sutil::AnyText(data_buf, len));
        });
    }
    void end() {
        mqtt.disconnect();
    }
    void tick() {
        if (!mqtt.connected()) reconnect();
        mqtt.loop();
    }
    void send(gh::BridgeData& data) {
        if (!mqtt.connected()) return;
        mqtt.beginPublish(data.topic.c_str(), data.text.length(), 0);
        mqtt.print(data.text);
        mqtt.endPublish();
    }

   private:
    PubSubClient mqtt;

    void reconnect() {
        while (!mqtt.connected()) {
            String clientId = "hub-";
            clientId += String(random(0xffff), HEX);
            if (mqtt.connect(clientId.c_str())) {
                Serial.println("connected");
                mqtt.subscribe(hub.topicDiscover().c_str());
                mqtt.subscribe(hub.topicHub().c_str());
            } else {
                delay(1000);
            }
        }
    }
};

HubMQTT mqtt(&hub);

// билдер
void build(gh::Builder& b) {
    static int val;
    b.Title(F("Hello!"));
    b.Slider(&val);
}

void setup()
{
    Serial.begin(115200);
   
    // Инициализацию SIM800 тут пропущу... Тут все норм
    // .....
   
    hub.config(F("MyDevices"), F("ESP"), F(""));
    hub.onBuild(build);

    hub.addBridge(&mqtt);
    hub.begin();
}

void loop()
{
   hub.tick();
}
После попадания в функцию "hub.begin();" в терминал выводит:

assert failed: tcpip_send_msg_wait_sem IDF/components/lwip/lwip/src/api/tcpip.c:455 (Invalid mbox)


Backtrace: 0x40083645:0x3ffb1f00 0x400889f5:0x3ffb1f20 0x4008e1d1:0x3ffb1f40 0x400f18ea:0x3ffb2070 0x400fe029:0x3ffb20a0 0x400fe089:0x3ffb20c0 0x400f1621:0x3ffb2110 0x40112532:0x3ffb2130 0x401125ac:0x3ffb2180 0x400dd11a:0x3ffb21a0 0x400d9db7:0x3ffb21c0 0x400d7cc3:0x3ffb2220 0x400e5a9e:0x3ffb2290

Вопрос, что я делаю не так?? Может к то сталкивался?
 
Изменено:

mps33

✩✩✩✩✩✩✩
21 Мар 2019
13
2
Кто спрашивал системное время по кнопке, пользуйтесь.
C++:
#define AP_SSID "SisTime"
#define AP_PASS "administrator"

#include <Arduino.h>
#include <GyverHub.h>
GyverHub hub;
#include <GyverDS3231.h>
GyverDS3231 rtc;


bool system_to_rtc = 0;//флаг записи системного времени

//SDA=>D2 (GPIO 4), SCL=>D1 (D1-GPIO 5)


void setup()
{
  Serial.begin(115200);
  Wire.begin();
  setStampZone(7);//часовой пояс
  if (rtc.begin())Serial.println("RTC ok");
  else
  {
  Serial.println("RTC error");
  rtc.setBuildTime();//записать время компиляции
  }
  if (rtc.begin()) Serial.println("RTC ok");
  else Serial.println("RTC error");
#ifdef GH_ESP_BUILD
  WiFi.mode(WIFI_AP);// режим точки доступа
  WiFi.softAP("SysTime");
  Serial.println(WiFi.softAPIP());    // по умолч. 192.168.4.1
#endif
hub.config(F("MyDevices"), F("SysTime"), F(""));
hub.onBuild(build);
hub.begin();
hub.onUnix(onunix);// время от браузера при обновлении данных b.refresh();
}

void loop()
{
  rtc.tick();
  hub.tick();
  static gh::Timer timer(1000);  // 1 раз в сек.
  if (timer)hub.sendUpdate("time");
}

void onunix(uint32_t stamp)//время из браузера
{
  Serial.print("Sys Time " );
  Serial.println(stamp);//время из браузера в Unix
  if (system_to_rtc)
  {
    rtc.setTime(stamp);//загружаем время в DS3231 (библиотека GyverDS3231)
    Serial.println(rtc.toString());//время из DS3231 уже в  обычном формате
    system_to_rtc = 0;
  }
}

void build(gh::Builder& b) {
  bool flag_1 = 0;
  bool flag_2 = 0;
  {
    gh::Row r(b);
    b.Label_("time", rtc.toString()).label(F("RTC")).fontSize(20).size(3);
    b.Button_("btnn").icon("f0e2").label(F("Sys Time")).size(1).fontSize(20).attach(&system_to_rtc).attach(&flag_1);
  }

  {
    gh::Row r(b);
    b.Button_("btnn2").icon("f0e2").label(F("Old Time")).size(1).fontSize(20).attach(&flag_1).attach(&flag_2);
  }
    if(flag_2)rtc.setTime(1609459200);
    if (flag_1) b.refresh();
}
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
@messaf,
Пример для esp8266. Используйте <WiFi.h> библиотеку. Ох, заметил, что Вы вообще не используете wifi... Вроде именно на это и ругается.