SuplaDevice wersja 25.08.01

Fryga
Posts: 136
Joined: Tue Oct 13, 2020 5:57 pm
Location: Mińsk Mazowiecki

Post

Potrzeba matką wynalazków.

Ja musiałem oszukać blokadę roamingu w AiMesh, bo u mnie nie mogl złapać sieci tylko przeskakiwał. Wymyśliłem takie cosik z możliwością podania MAC danego BSSID oraz kanału (numeru kanału - dotyczy tylko tych AP co mają na stałe włączone konkretny kanał a nie AUTO na routerze).

Kod powstał poprzez przerobienie innego znanego rozwiązania (bez ograniczeń licencyjnych) aby dostosować do supli.

No i powstalo kombo Supla Schrodingera: lock na BSSID i jednoczesnie mozna odwrotnie failover i szukanie na multi sieci.

Code: Select all

#include "supla/network/esp_wifi.h"  // oryginalny nagłówek

namespace Supla {

// Kandydat SSID
struct WifiCandidate {
  const char* ssid;
  const char* pass;
  const uint8_t* bssid;  // nullptr = bez locka
  int channel;           // 0 = auto
};

// Multi-SSID: dziedziczona od ESPWifi (żeby Matka-Supla widziała ją jako swoja)
class ESPWifiMulti_GMX : public Supla::ESPWifi {
public:
  ESPWifiMulti_GMX(WifiCandidate* list, int count)
    : ESPWifi(nullptr, nullptr, nullptr), list(list), count(count) {}

  void setup() override {
    // rejestruj eventy PRZED pierwszą próbą, bo jak podlaczysz to nie będziesz znał innych sieci
    WiFi.onEvent([this](WiFiEvent_t ev, WiFiEventInfo_t info) {
      switch (ev) {
        case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
          SUPLA_LOG_INFO("WiFi disc. reason=%d", info.wifi_sta_disconnected.reason);
          // nie używamy WiFi.reconnect(); sami sterujemy cyklem wyszukiwania i podłączania
          // krótka pauza, potem kolejna próba
          scheduleTryMillis = millis() + 200;
          break;
        case ARDUINO_EVENT_WIFI_STA_GOT_IP:
          SUPLA_LOG_INFO("WiFi OK, IP=%s", WiFi.localIP().toString().c_str());
          lastOkMillis = millis();
          break;
        default: break;
      }
    });

    WiFi.mode(WIFI_STA);
    WiFi.setSleep(false);
    WiFi.persistent(false);
    if (hostname && *hostname) WiFi.setHostname(hostname); //lepiej działa z hostname

    // pierwsza próba natychmiast - kuj zelazo poki gorace
    scheduleTryMillis = 0;
    tryConnect();
  }

  // Zwracam faktyczny status, ale nie dubluj logiki reconnecttu
  bool iterate() override {
    bool ok = Supla::ESPWifi::iterate();         // standardowe rzeczy Supli
    ok = ok && (WiFi.status() == WL_CONNECTED);  // gotowość sieci

    // failover po 5 min braku "ok"
    if (millis() - lastOkMillis > FAILOVER_MS) {
      SUPLA_LOG_INFO("No internet for 5 min → rotate SSID");
      nextSSID();
      scheduleTryMillis = 0;    // natychmiastowa próba
      lastOkMillis = millis();  // zresetuj strażnik, żeby nie spamować
    }

    // miękki scheduler prób (żeby nie spamować begin() w pętli)
    if (WiFi.status() != WL_CONNECTED && millis() >= scheduleTryMillis) {
      tryConnect();
    }
    return ok;
  }

private:
  WifiCandidate* list;
  int count;
  int idx = 0;

  unsigned long lastOkMillis = 0;
  unsigned long scheduleTryMillis = 0;
  static constexpr unsigned long FAILOVER_MS = 5UL * 60UL * 1000UL; // ustawiany czas po którym przełączymi się na nastepna znana siec

  void tryConnect() {
    // każda próba zaczyna się od czystego rozłączenia NVS + chwilka przerwy (chwila ciszy)
    WiFi.disconnect(true);
    delay(50);

    for (int attempt = 0; attempt < count; attempt++) {
      int i = (idx + attempt) % count;
      SUPLA_LOG_INFO("WiFi try SSID=\"%s\"", list[i].ssid);

      if (list[i].bssid) {
        WiFi.begin(list[i].ssid, list[i].pass, list[i].channel, list[i].bssid, true);
      } else {
        WiFi.begin(list[i].ssid, list[i].pass);
      }

      unsigned long t0 = millis();
      while (millis() - t0 < 8000) {  // 8 s na próbę
        if (WiFi.status() == WL_CONNECTED) {
          idx = i;
          lastOkMillis = millis();
          SUPLA_LOG_INFO("WiFi connected: \"%s\" IP=%s",
                         list[i].ssid, WiFi.localIP().toString().c_str());
          scheduleTryMillis = millis() + 10000;  // następne sprawdzenie za 10 s
          return;
        }
        delay(200);
      }
      SUPLA_LOG_INFO("SSID \"%s\" nie podłączono, bierz nastepna.....", list[i].ssid);
    }

    // wszystkie próby nieudane – spróbuj ponownie za chwilę aby nie zaspamowac sieci
    scheduleTryMillis = millis() + 5000;
    SUPLA_LOG_INFO("Bedzie powtorka szukania");
  }

  void nextSSID() {
    idx = (idx + 1) % count;
  }
};

// Twoja lista SSID (możesz dodać bssid, channel gdy chcesz) - przykład sarkastyczny ciutek
WifiCandidate wifiList[] = {
  { "SSID1", "haslo", nullptr, 0 },
  { "SSID2", "passwordzik", nullptr, 0 },
  { "SSID3", "admin1234", nullptr, 0 },
  { "SSID4", "12345578", bssid, 11 } //11 kanal, bssid mac i tylko ten AP
};

}  // namespace Supla

// Globalny obiekt – musi istnieć PRZED setup(), żeby Supla widziała sieć
static Supla::ESPWifiMulti_GMX wifiki(Supla::wifiList, sizeof(Supla::wifiList) / sizeof(Supla::wifiList[0]));




a BSSID to deklarowane wyżej:

Code: Select all

 uint8_t bssid[] = { 0xEE, 0x99, 0x25, 0x18, 0x02, 0x12 };  // ten właściwy AP
Last edited by Fryga on Wed Sep 03, 2025 8:43 pm, edited 3 times in total.
User avatar
klew
Posts: 13908
Joined: Thu Jun 27, 2019 12:16 pm
Location: Wrocław
Has thanked: 134 times
Been thanked: 137 times

Post

Fryga wrote: Sun Aug 31, 2025 7:11 am Potrzeba matką wynalazków.
Matkę trzeba szanować :)
Najlepsze suple dla Twojego domu :mrgreen:
User avatar
Lector
Posts: 2471
Joined: Fri Nov 17, 2017 2:26 pm
Location: Poznań
Has thanked: 13 times
Been thanked: 25 times

Post

klew wrote: Wed Aug 27, 2025 7:55 am Jest już dostępne kolejne oficjalne wydanie SuplaDevice w wersji 25.08.01.
Czy pojawią się reakcję dla stanu baterii?

Dla bramki dla Pi. Nie wiem czy ich nie było wcześniej.
Niespełniony automatyk. :mrgreen:
https://3d-lamp.photos/
https://pool.lector.top/
User avatar
klew
Posts: 13908
Joined: Thu Jun 27, 2019 12:16 pm
Location: Wrocław
Has thanked: 134 times
Been thanked: 137 times

Post

Lector wrote: Fri Sep 05, 2025 6:49 am Czy pojawią się reakcję dla stanu baterii?

Dla bramki dla Pi. Nie wiem czy ich nie było wcześniej.
Wydaje mi się, że były. Obecnie na oficjalnych serwerach nie mam żadnego urządzenia bateryjnego, a na beta mamy tam coś na pewno popsute w tym zakresie ;P.
Najlepsze suple dla Twojego domu :mrgreen:
User avatar
Lector
Posts: 2471
Joined: Fri Nov 17, 2017 2:26 pm
Location: Poznań
Has thanked: 13 times
Been thanked: 25 times

Post

klew wrote: Fri Sep 05, 2025 7:51 am
Lector wrote: Fri Sep 05, 2025 6:49 am Czy pojawią się reakcję dla stanu baterii?

Dla bramki dla Pi. Nie wiem czy ich nie było wcześniej.
Wydaje mi się, że były. Obecnie na oficjalnych serwerach nie mam żadnego urządzenia bateryjnego, a na beta mamy tam coś na pewno popsute w tym zakresie ;P.
No jestem na 95% pewien ze były, bo sprawdzałem i dlatego przy chwili wolnego czasu zacząłem przerabiać bramki i posuwałem kanały które czytały tylko stan baterii.

I zonk bo zniknęły reakcje przy głównych kanałach.
Niespełniony automatyk. :mrgreen:
https://3d-lamp.photos/
https://pool.lector.top/
Fryga
Posts: 136
Joined: Tue Oct 13, 2020 5:57 pm
Location: Mińsk Mazowiecki

Post

"Strasznie" potrzebuję zmiany tekstu pod kanałem np. wirtualnym. Wiem, że trudno zapanować na kontrolą tekstu wrzucanego do bębna supli ze względów bezpieczeństwa, ale może da się zdefiniować dwa, trzy, cztery alternatywy i zmieniać je na skutek wartości kanału który jest wyświetlany.

Raz mogę ustawić, potem mogę wywolywać metodę - i już niestety nie zmienia się.

Code: Select all

static bool g_physActive[8] = { false };     // ostatni stan fizyczny
static bool g_visActive[8] = { false };      // ostatni stan wysłany do SUPLI
static uint32_t g_latchUntil[8] = { 0 };     // millis() do kiedy trzymać „naruszone”
static bool g_suffixApplied[8] = { false };  // czy dopisano suffix w tytule
np. integracja z INA219

Code: Select all

// --- INA / KPOP ---
String chTitle(uint8_t idx);
void addKPOP(const String& title, const char* unitAfter, uint8_t prec, const char* unitBefore);
static inline String ina219TitleI(uint8_t n) {
  return "INA219_" + String(n + 1) + "_I_ladowania";
}
static inline String ina219TitleV(uint8_t n) {
  return "INA219_" + String(n + 1) + "_U_ladowania";
}
tutaj określiłbym informacje zależną od napiecia i prądu ładowania. A tak kupa.
User avatar
klew
Posts: 13908
Joined: Thu Jun 27, 2019 12:16 pm
Location: Wrocław
Has thanked: 134 times
Been thanked: 137 times

Post

Fryga wrote: Sun Sep 07, 2025 10:00 pm "Strasznie" potrzebuję zmiany tekstu pod kanałem np. wirtualnym. Wiem, że trudno zapanować na kontrolą tekstu wrzucanego do bębna supli ze względów bezpieczeństwa, ale może da się zdefiniować dwa, trzy, cztery alternatywy i zmieniać je na skutek wartości kanału który jest wyświetlany.

Raz mogę ustawić, potem mogę wywolywać metodę - i już niestety nie zmienia się.
Nie sądzę, aby taka funkcja mogła być dodana, bo to by się gryzło trochę z tym czym to pole jest. Mówimy o "nazwie kanału". Nazwa z założenia ma być nazwą :P a nie wartością. Dodatkowo nazwy użytkownik może zmieniać w apce lub w Cloud. A jak by do tego urządzenie zaczęło nazwę nadpisywać, to robi się misz-masz.

Kiedyś była mowa o dodaniu kanału tekstowego (KTXT). W KTXT będzie można przesyłać tekst, który będzie wyświetlany w miejscu wartości kanau. Ale temat utknął w poczekalni.
Kiedyś rozważaliśmy też coś w stylu "czujnika binarnego", ale wielostanowego. Np. 6 stanów, każdy ze swoją wartością i ikonką.

Natomiast z realnych rozwiązań na teraz, to proponuje wstawienie czujnika binarnego i ustawienie sobie odpowiednich ikonek, które będą sygnalizować to co byś chciał sygnalizować.
Chyba, że dwa stany to za mało.

Jak napiszesz coś więcej co byś chciał osiągnąć, to można by coś więcej podpowiedzieć.
Najlepsze suple dla Twojego domu :mrgreen:
Fryga
Posts: 136
Joined: Tue Oct 13, 2020 5:57 pm
Location: Mińsk Mazowiecki

Post

ja to rozumiem, nie wszystko co piękne i łatwe jest opłacalne.

Funkcjonalność którą mi potrzeba zamiast KTOP (tekstowy) to:
1. zmiana ikony przy zmianie wartości - zdefiniowanie kilku - min 3 ikon dla każdego przedziału aby zmieniać ją na skutek wartości z danego przedziału
np. Airly - przekroczenie progów zanieczyszczeń
np. Prąd ładowania akumulatora - przekroczenie od góry bo np. ryzyko zagotowania, od dołu - zakończono ładowanie
np. poziom w zbiorniku - za niski, ok, za wysoki
np. temperatura: za wysoka np. w pomieszczeniu, za niska ryzyko zamarzniecia instalacji


alternatywnie
2. zmiana tła ikony - czerwony, żółty, zielony etc i 3 przedziały.

Z początku myślałem że da się zmienić podpis pod kanałem, ale niestety możesz mieć rację - że to prowadzi do zguby skoro można modyfikować w chmurze.

Co myślisz? Masz na to sposób?
User avatar
klew
Posts: 13908
Joined: Thu Jun 27, 2019 12:16 pm
Location: Wrocław
Has thanked: 134 times
Been thanked: 137 times

Post

Fryga wrote: Thu Sep 18, 2025 8:06 am ja to rozumiem, nie wszystko co piękne i łatwe jest opłacalne.

Funkcjonalność którą mi potrzeba zamiast KTOP (tekstowy) to:
1. zmiana ikony przy zmianie wartości - zdefiniowanie kilku - min 3 ikon dla każdego przedziału aby zmieniać ją na skutek wartości z danego przedziału
np. Airly - przekroczenie progów zanieczyszczeń
np. Prąd ładowania akumulatora - przekroczenie od góry bo np. ryzyko zagotowania, od dołu - zakończono ładowanie
np. poziom w zbiorniku - za niski, ok, za wysoki
np. temperatura: za wysoka np. w pomieszczeniu, za niska ryzyko zamarzniecia instalacji


alternatywnie
2. zmiana tła ikony - czerwony, żółty, zielony etc i 3 przedziały.

Z początku myślałem że da się zmienić podpis pod kanałem, ale niestety możesz mieć rację - że to prowadzi do zguby skoro można modyfikować w chmurze.

Co myślisz? Masz na to sposób?
Takie coś też było kilka razy rozważane. W sumie rozmowy sprowadzały się do czegoś w stylu "kanału enum" z kilkoma predefiniowanymi wartościami.
Ale może tu by się przydały ogólnie jakieś bardziej elastyczne ikonki, gdzie w Cloud można sobie przypisać ikony do różnych zakresów.
Aktualnie tego nie zrealizujesz w Supli.

I nie jest to temat dla SuplaDevice, tylko raczej Cloud + server + apki
Najlepsze suple dla Twojego domu :mrgreen:
User avatar
vajera
Posts: 7290
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 289 times
Been thanked: 161 times

Post

Fryga wrote: Thu Sep 18, 2025 8:06 am ja to rozumiem, nie wszystko co piękne i łatwe jest opłacalne.

Funkcjonalność którą mi potrzeba zamiast KTOP (tekstowy) to:
1. zmiana ikony przy zmianie wartości - zdefiniowanie kilku - min 3 ikon dla każdego przedziału aby zmieniać ją na skutek wartości z danego przedziału
np. Airly - przekroczenie progów zanieczyszczeń
np. Prąd ładowania akumulatora - przekroczenie od góry bo np. ryzyko zagotowania, od dołu - zakończono ładowanie
np. poziom w zbiorniku - za niski, ok, za wysoki
np. temperatura: za wysoka np. w pomieszczeniu, za niska ryzyko zamarzniecia instalacji


alternatywnie
2. zmiana tła ikony - czerwony, żółty, zielony etc i 3 przedziały.

Z początku myślałem że da się zmienić podpis pod kanałem, ale niestety możesz mieć rację - że to prowadzi do zguby skoro można modyfikować w chmurze.

Co myślisz? Masz na to sposób?
Oh my sweet summer child...🤣...przepraszam, ale tak mi się skojarzyło, gdy kolejny raz "młody i gniewny" odkrywa potrzebę kanału tekstowego/wielofunkcyjnego.

Poważnie mówiąc, to taki kanał mógłby być użyteczny nie tylko dla projektów DIY - pytanie, w którym kierunku Supla zamierza podążyć - patrząc na rozwój urządzeń IoT to może się opłacić.
Bramka Zigbee <=> SUPLA
Więcej informacji tutaj:
https://forum.supla.org/viewforum.php?f=127
FAQ https://forum.supla.org/viewtopic.php?t=17277

Return to “supla-dev”