skrypt do sprawdzenia

Projekty użytkowników forum zarówno sprzętowe, jak i związane z programowaniem w dowolnym języku.
Awatar użytkownika
wojtek
Newb
Newb
Posty: 44
Rejestracja: poniedziałek 10 kwie 2023, 15:15

skrypt do sprawdzenia

Postautor: wojtek » wtorek 15 wrz 2026, 09:43

Mógłby ktoś rzucić okiem na skrypt wygenerowany przez AI, błędy wcześniejsze wyłapałem i AI poprawiło
To skrypt do gniazdka smart Shelly S MTR Gen3 który ma za zadania restartować router w razie zaniku internetu (zawieszenia routera) a oprócz tego np o 1 w nocy wymusić restart.
To nieco inne podejście do tematu, który w tym miejscu zacząłem: https://www.microgeek.eu/viewtopic.php? ... 940#p17056

Kod: Zaznacz cały

/* jshint esversion: 6 */
/* global Shelly, Timer */
// Konfiguracja Twojego Watchdoga i Restartu Nocnego
let CONFIG = {
  // Stabilne serwery DNS (Google i Cloudflare) używane do testu HTTP
  endpoints: [
    "http://" + "1.1.1.1",
    "http://" + "8.8.8.8"
  ],
  maxFailures: 5,          // 5 nieudanych prób = brak internetu (5 minut)
  checkInterval: 60000,    // Sprawdzaj internet co 60 sekund (60000 ms)
  relayOffDuration: 60000, // Czas odłączenia prądu: 60000 ms (1 minuta)
 
  // Konfiguracja nocnego restartu (Format: Godzina, Minuta)
  nightRebootHour: 1,      // Godzina 1 w nocy
  nightRebootMinute: 0     // Minuta 00
};

let failureCount = 0;
let isRebooting = false;
let midnightRebootDone = false;

// Funkcja wykonująca twardy reset (wyłącz na 1 minutę, włącz z powrotem)
function doRouterPowerCycle(reason) {
  if (isRebooting) return;
  isRebooting = true;
  print("Uruchamiam restart routera. Powód: " + reason);
 
  // Wyłącz gniazdko
  Shelly.call("Switch.Set", { id: 0, on: false }, function() {
    print("Zasilanie odcięte. Czekam minutę...");
   
    // Odlicz czas i włącz z powrotem
    Timer.set(CONFIG.relayOffDuration, false, function() {
      Shelly.call("Switch.Set", { id: 0, on: true }, function() {
        print("Zasilanie routera przywrócone.");
        // Daj routerowi dodatkowe 5 minut na pełne uruchomienie przed kolejnym testem internetu
        Timer.set(300000, false, function() {
          failureCount = 0;
          isRebooting = false;
          print("Watchdog wznawia monitorowanie.");
        });
      });
    });
  });
}

// 1. Pętla sprawdzająca internet (co minutę)
Timer.set(CONFIG.checkInterval, true, function() {
  if (isRebooting) return;

  // Wybieramy losowo jeden z dwóch bezpiecznych serwerów DNS
  let url = CONFIG.endpoints.at(Math.floor(Math.random() * CONFIG.endpoints.length));
 
  Shelly.call("HTTP.GET", { url: url, timeout: 15 }, function(response, error_code) {
    // Jeśli połączenie się udało (kod błędu 0)
    if (error_code === 0 && response) {
      failureCount = 0; // Internet działa, zeruj licznik błędów
    } else {
      failureCount++;
      print("Brak odpowiedzi z internetu (" + failureCount + "/" + CONFIG.maxFailures + ")");
     
      // Jeśli uzbiera się 5 minut (5 prób x 60s) ciągłego braku sieci
      if (failureCount >= CONFIG.maxFailures) {
        doRouterPowerCycle("Wykryto zawieszenie sieci (Watchdog 5 min)");
      }
    }
  });
});

// 2. Pętla sprawdzająca czas do nocnego restartu (co minutę)
Timer.set(60000, true, function() {
  let sysStatus = Shelly.getComponentStatus("sys");
 
  if (sysStatus && sysStatus.time) {
    let timeParts = sysStatus.time.split(":");
    if (timeParts.length >= 2) {
      // Pobieranie godziny (indeks 0) i minuty (indeks 1) za pomocą bezpiecznej metody .at()
      let currentHour = JSON.parse(timeParts.at(0));
      let currentMinute = JSON.parse(timeParts.at(1));
     
      // Sprawdź czy wybiła dokładnie 01:00
      if (currentHour === CONFIG.nightRebootHour && currentMinute === CONFIG.nightRebootMinute) {
        if (!midnightRebootDone && !isRebooting) {
          midnightRebootDone = true;
          doRouterPowerCycle("Zaplanowany nocny restart profilaktyczny");
        }
      } else {
        // Resetuj flagę po minięciu godziny 1:00, żeby zadziałało kolejnego dnia
        midnightRebootDone = false;
      }
    }
  }
});

print("Skrypt Watchdog + Restart 1:00 został poprawnie zainicjalizowany.");


JSHint nie pokazał błędów.
Ostatnio zmieniony czwartek 24 wrz 2026, 17:22 przez wojtek, łącznie zmieniany 1 raz.

Awatar użytkownika
wojtek
Newb
Newb
Posty: 44
Rejestracja: poniedziałek 10 kwie 2023, 15:15

Re: skrypt do sprawdzenia

Postautor: wojtek » wtorek 15 wrz 2026, 14:34

Po poprawkach innego pomocnika czyli Claude AI:

Kod: Zaznacz cały

/* jshint esversion: 6 */
/* global Shelly, Timer */

// Konfiguracja Twojego Watchdoga i Restartu Nocnego
let CONFIG = {
  // Sprawdzone adresy HTTP, które zwracają kod 200 lub 204
  endpoints: [
    "http://neverssl.com",
    "http://1.1.1.1"
  ],
  maxFailures: 5,          // 5 nieudanych prób = brak internetu (5 minut)
  checkInterval: 60000,    // Sprawdzaj internet co 60 sekund (60000 ms)
  relayOffDuration: 60000, // Czas odłączenia prądu: 60000 ms (1 minuta)

  // Konfiguracja nocnego restartu (Format: Godzina, Minuta)
  nightRebootHour: 1,      // Godzina 1 w nocy
  nightRebootMinute: 0     // Minuta 00
};

let failureCount = 0;
let isRebooting = false;
let midnightRebootDone = false;

// Funkcja wykonująca twardy reset (wyłącz na 1 minutę, włącz z powrotem)
function doRouterPowerCycle(reason) {
  if (isRebooting) return;
  isRebooting = true;
  print("Uruchamiam restart routera. Powód: " + reason);

  // BEZPIECZNIK: Gdyby gniazdko się zawiesiło w pętli restartu, odblokuj po 10 minutach
  Timer.set(600000, false, function () {
    if (isRebooting) {
      isRebooting = false;
      failureCount = 0;
      print("Zadziałał bezpiecznik czasowy. Reset stanu isRebooting.");
    }
  });

  // Wyłącz gniazdko
  Shelly.call("Switch.Set", { id: 0, on: false }, function () {
    print("Zasilanie odcięte. Czekam minutę...");

    // Odlicz czas i włącz z powrotem
    Timer.set(CONFIG.relayOffDuration, false, function () {
      Shelly.call("Switch.Set", { id: 0, on: true }, function () {
        print("Zasilanie routera przywrócone.");
        // Daj routerowi dodatkowe 5 minut na pełne uruchomienie przed kolejnym testem internetu
        Timer.set(300000, false, function () {
          failureCount = 0;
          isRebooting = false;
          print("Watchdog wznawia monitorowanie.");
        });
      });
    });
  });
}

// 1. Pętla sprawdzająca internet (co minutę)
Timer.set(CONFIG.checkInterval, true, function () {
  if (isRebooting) return;

  // Losowy wybór jednego z endpointów
  let idx = Math.floor(Math.random() * CONFIG.endpoints.length);
  let url = CONFIG.endpoints[idx];

  Shelly.call("HTTP.GET", { url: url, timeout: 15 }, function (response, error_code) {
    // Sukces tylko dla kodów 200-299
    if (error_code === 0 && response && response.code >= 200 && response.code < 300) {
      failureCount = 0; // Internet działa, zeruj licznik błędów
    } else {
      failureCount++;
      print("Brak odpowiedzi z internetu (" + failureCount + "/" + CONFIG.maxFailures + ")");

      // Jeśli uzbiera się 5 minut (5 prób x 60s) ciągłego braku sieci
      if (failureCount >= CONFIG.maxFailures) {
        doRouterPowerCycle("Wykryto zawieszenie sieci (Watchdog 5 min)");
      }
    }
  });
});

// 2. Pętla sprawdzająca czas do nocnego restartu (co minutę)
Timer.set(60000, true, function () {
  let sysStatus = Shelly.getComponentStatus("sys");

  if (sysStatus && sysStatus.time) {
    let timeParts = sysStatus.time.split(":");
    if (timeParts.length >= 2) {
      // Bezpieczna konwersja tekstowej godziny/minuty na liczbę
      let currentHour = Number(timeParts[0]);
      let currentMinute = Number(timeParts[1]);

      // Sprawdź czy wybiła dokładnie 01:00
      if (currentHour === CONFIG.nightRebootHour && currentMinute === CONFIG.nightRebootMinute) {
        if (!midnightRebootDone && !isRebooting) {
          midnightRebootDone = true;
          doRouterPowerCycle("Zaplanowany nocny restart profilaktyczny");
        }
      } else {
        // Resetuj flagę po minięciu godziny 1:00, żeby zadziałało kolejnego dnia
        midnightRebootDone = false;
      }
    }
  }
});

print("Skrypt Watchdog + Restart 1:00 został poprawnie zainicjalizowany.");

Awatar użytkownika
wojtek
Newb
Newb
Posty: 44
Rejestracja: poniedziałek 10 kwie 2023, 15:15

Re: skrypt do sprawdzenia

Postautor: wojtek » niedziela 20 wrz 2026, 11:28

No zupełnie fajnie się "współpracuje" z Claude AI, po kolejnych poprawkach i testach czas na finalne testowanie, bo jeszcze był kłopot z wyciekiem pamięci.
Testy lecą na docelowym urządzeniu i podłączonym domowym routerze, tak wygodniej, później przeniosę to na zdalną lokalizację. Ale ładnie to na razie się zachowuje. Poniżej ósma wersja poprawiona.

Kod: Zaznacz cały

/* jshint esversion: 6 */
/* global Shelly, Timer */

// Konfiguracja Twojego Watchdoga i Restartu Nocnego
let CONFIG = {
  // Endpointy zaprojektowane do testów łączności - małe odpowiedzi, bez przekierowań.
  // Oba to duża, komercyjna infrastruktura (Google + Cloudflare), więc powinny
  // być dużo bardziej niezawodne niż małe serwisy typu neverssl.com
  // (który w testach zawodził w ok. 50% prób błędami połączenia niezwiązanymi
  //  z Twoim internetem - patrz logi z 17:31-18:01).
  endpoints: [
    "http://connectivitycheck.gstatic.com/generate_204",
    "http://cp.cloudflare.com/generate_204"
  ],
  maxFailures: 5,          // 5 nieudanych prób = brak internetu (5 minut)
  checkInterval: 60000,    // Sprawdzaj internet co 60 sekund (60000 ms)
  relayOffDuration: 60000, // Czas odłączenia prądu: 60000 ms (1 minuta)

  // Konfiguracja nocnego restartu (Format: Godzina, Minuta)
  nightRebootEnabled: false, // USTAW NA true, ŻEBY WŁĄCZYĆ nocny restart o wyznaczonej godzinie
  nightRebootHour: 1,      // Godzina 1 w nocy
  nightRebootMinute: 0     // Minuta 00
};

let failureCount = 0;
let isRebooting = false;
let midnightRebootDone = false;

// Funkcja wykonująca twardy reset (wyłącz na 1 minutę, włącz z powrotem)
function doRouterPowerCycle(reason) {
  if (isRebooting) return;
  isRebooting = true;
  print("Uruchamiam restart routera. Powód: " + reason);

  // BEZPIECZNIK: Gdyby gniazdko się zawiesiło w pętli restartu, odblokuj po 10 minutach
  Timer.set(600000, false, function () {
    if (isRebooting) {
      isRebooting = false;
      failureCount = 0;
      print("Zadziałał bezpiecznik czasowy. Reset stanu isRebooting.");
    }
  });

  // Wyłącz gniazdko
  Shelly.call("Switch.Set", { id: 0, on: false }, function () {
    print("Zasilanie odcięte. Czekam minutę...");

    // Odlicz czas i włącz z powrotem
    Timer.set(CONFIG.relayOffDuration, false, function () {
      Shelly.call("Switch.Set", { id: 0, on: true }, function () {
        print("Zasilanie routera przywrócone.");
        // Daj routerowi dodatkowe 5 minut na pełne uruchomienie przed kolejnym testem internetu
        Timer.set(300000, false, function () {
          failureCount = 0;
          isRebooting = false;
          print("Watchdog wznawia monitorowanie.");
        });
      });
    });
  });
}

// Funkcja sprawdzająca endpointy PO KOLEI (sekwencyjnie) - Shelly Mini Gen3
// ma ograniczone zasoby i przy dwóch jednoczesnych połączeniach HTTP jedno z nich
// bywa zrywane (Connection error), mimo że internet działa prawidłowo.
// Błąd liczy się tylko, gdy WSZYSTKIE endpointy zawiodą w danym cyklu.
//
// WAŻNE: ta funkcja jest zadeklarowana RAZ, na poziomie głównym skryptu -
// nie wewnątrz cyklicznego Timer.set. Wcześniejsza wersja tworzyła tę funkcję
// od nowa przy każdym tyknięciu (co minutę), co powodowało powolny wyciek
// pamięci (błąd "Script ran out of memory" po kilku-kilkunastu godzinach).
function checkNextEndpoint(index, anySuccess) {
  if (index >= CONFIG.endpoints.length) {
    // Wszystkie endpointy sprawdzone - oceniamy wynik
    if (anySuccess) {
      failureCount = 0; // Choć jeden endpoint odpowiedział - internet działa
    } else {
      failureCount++;
      print("Brak odpowiedzi ze WSZYSTKICH endpointów (" + failureCount + "/" + CONFIG.maxFailures + ")");

      // Jeśli uzbiera się 5 minut (5 prób x 60s) ciągłego braku sieci
      if (failureCount >= CONFIG.maxFailures) {
        doRouterPowerCycle("Wykryto zawieszenie sieci (Watchdog 5 min)");
      }
    }
    return;
  }

  let url = CONFIG.endpoints[index];
  Shelly.call("HTTP.GET", { url: url, timeout: 15 }, function (response, error_code) {
    let ok = (error_code === 0 && response && response.code >= 200 && response.code < 300);

    if (!ok) {
      // Log diagnostyczny - pomaga zrozumieć PRZYCZYNĘ ewentualnego błędu
      let respCode = response ? response.code : "brak";
      print("Test '" + url + "' nieudany. error_code=" + error_code + ", response.code=" + respCode);
    }

    // Przechodzimy do kolejnego endpointu dopiero PO zakończeniu tego zapytania
    checkNextEndpoint(index + 1, anySuccess || ok);
  });
}

// 1. Pętla sprawdzająca internet (co minutę)
Timer.set(CONFIG.checkInterval, true, function () {
  if (isRebooting) return;
  checkNextEndpoint(0, false);
});

// 2. Pętla sprawdzająca czas do nocnego restartu (co minutę)
// WYŁĄCZONE NA CZAS TESTÓW - zmień CONFIG.nightRebootEnabled na true, żeby przywrócić.
Timer.set(60000, true, function () {
  if (!CONFIG.nightRebootEnabled) return;

  let sysStatus = Shelly.getComponentStatus("sys");

  if (sysStatus && sysStatus.time) {
    let timeParts = sysStatus.time.split(":");
    if (timeParts.length >= 2) {
      // Bezpieczna konwersja tekstowej godziny/minuty na liczbę
      let currentHour = Number(timeParts[0]);
      let currentMinute = Number(timeParts[1]);

      // Sprawdź czy wybiła dokładnie 01:00
      if (currentHour === CONFIG.nightRebootHour && currentMinute === CONFIG.nightRebootMinute) {
        if (!midnightRebootDone && !isRebooting) {
          midnightRebootDone = true;
          doRouterPowerCycle("Zaplanowany nocny restart profilaktyczny");
        }
      } else {
        // Resetuj flagę po minięciu godziny 1:00, żeby zadziałało kolejnego dnia
        midnightRebootDone = false;
      }
    }
  }
});

print("Skrypt Watchdog + Restart 1:00 został poprawnie zainicjalizowany.");

// 3. Okresowe logowanie wolnej pamięci systemowej (co 30 minut).
// Dzięki temu w logach zobaczysz TREND w czasie (a nie tylko jednorazowy
// zrzut przy starcie skryptu) - pozwoli to potwierdzić, czy poprawka
// wycieku pamięci faktycznie działa, czy wolna pamięć nadal powoli spada.
function logFreeMemory() {
  let sysStatus = Shelly.getComponentStatus("sys");
  if (sysStatus && typeof sysStatus.ram_free !== "undefined") {
    print("Watchdog - wolna pamiec systemowa: " + sysStatus.ram_free + " / " + sysStatus.ram_size + " bajtow");
  }
}

logFreeMemory(); // Pierwszy odczyt od razu na starcie - punkt odniesienia "zero"
Timer.set(1800000, true, logFreeMemory);


shelly_plug_test.jpg
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
wojtek
Newb
Newb
Posty: 44
Rejestracja: poniedziałek 10 kwie 2023, 15:15

Re: skrypt do sprawdzenia

Postautor: wojtek » poniedziałek 21 wrz 2026, 09:59

Po testach ponad 15 godzin wyszło że pamięć jest stabilna jak również nie zanotowano błędów przy sprawdzaniu łączności z internetem. Wcześniej sam wymusiłem "awarię" wifi i ładnie skrypt wykonał co miał wykonać czyli reset zasilania routera. W załaczeniu plik csv logów z shelly (jak się w wyszukiwaniu wpisze słowo "wolna" i wyszuka wszystko to pokażą się komunikaty o pamięci RAM gniazda wysyłane co poł godziny. Widać ze nie ma wycieków pamięci. Teraz w gram nowy skrypt z poprawkami jeszcze dotyczącymi bezpiecznika 10 minutowego. Ponizej kod nowego skryptu i plik csv z testów.

Kod: Zaznacz cały

/* jshint esversion: 6 */
/* global Shelly, Timer */

// Konfiguracja Twojego Watchdoga i Restartu Nocnego
let CONFIG = {
  // Endpointy zaprojektowane do testów łączności - małe odpowiedzi, bez przekierowań.
  // Oba to duża, komercyjna infrastruktura (Google + Cloudflare), więc powinny
  // być dużo bardziej niezawodne niż małe serwisy typu neverssl.com
  // (który w testach zawodził w ok. 50% prób błędami połączenia niezwiązanymi
  //  z Twoim internetem - patrz logi z 17:31-18:01).
  endpoints: [
    "http://connectivitycheck.gstatic.com/generate_204",
    "http://cp.cloudflare.com/generate_204"
  ],
  maxFailures: 5,          // 5 nieudanych prób = brak internetu (5 minut)
  checkInterval: 60000,    // Sprawdzaj internet co 60 sekund (60000 ms)
  relayOffDuration: 60000, // Czas odłączenia prądu: 60000 ms (1 minuta)

  // Ochrona przed zbyt częstymi restartami przy długiej awarii operatora:
  // pierwsze "quickAttempts" restarty następują normalnie (szybka reakcja
  // na typowe zawieszenie routera), a jeśli to nie pomaga, kolejne próby
  // są podejmowane rzadziej (co "backoffInterval"), żeby nie męczyć routera
  // bez potrzeby, gdy problem leży po stronie operatora.
  quickAttempts: 2,          // Liczba "szybkich" restartów z rzędu, zanim włączy się tryb rzadszych prób
  backoffInterval: 3600000,  // Odstęp między próbami w trybie rzadszym: 3600000 ms (60 minut)

  // Konfiguracja nocnego restartu (Format: Godzina, Minuta)
  nightRebootEnabled: false, // USTAW NA true, ŻEBY WŁĄCZYĆ nocny restart o wyznaczonej godzinie
  nightRebootHour: 1,      // Godzina 1 w nocy
  nightRebootMinute: 0     // Minuta 00
};

let failureCount = 0;
let isRebooting = false;
let midnightRebootDone = false;
let consecutiveReboots = 0; // Ile restartów z rzędu NIE przywróciło internetu
let backoffActive = false;  // Czy jesteśmy w trybie rzadszych prób (po długiej awarii)
let safetyTimerId = null;   // Uchwyt do aktywnego bezpiecznika 10-minutowego (żeby móc go anulować)

// Funkcja wykonująca twardy reset (wyłącz na 1 minutę, włącz z powrotem)
function doRouterPowerCycle(reason) {
  if (isRebooting) return;
  isRebooting = true;
  print("Uruchamiam restart routera. Powód: " + reason);

  // Na wszelki wypadek anulujemy JAKIKOLWIEK poprzedni, jeszcze oczekujący
  // bezpiecznik (nie powinien istnieć w normalnych warunkach, ale to
  // eliminuje ryzyko, że "osierocony" bezpiecznik z poprzedniego cyklu
  // odpali się w środku BIEŻĄCEGO restartu i przedwcześnie go przerwie.
  if (safetyTimerId !== null) {
    Timer.clear(safetyTimerId);
    safetyTimerId = null;
  }

  // BEZPIECZNIK: Gdyby gniazdko się zawiesiło w pętli restartu, odblokuj po 10 minutach
  safetyTimerId = Timer.set(600000, false, function () {
    safetyTimerId = null;
    if (isRebooting) {
      isRebooting = false;
      failureCount = 0;
      print("Zadziałał bezpiecznik czasowy. Reset stanu isRebooting.");
    }
  });

  // Wyłącz gniazdko
  Shelly.call("Switch.Set", { id: 0, on: false }, function () {
    print("Zasilanie odcięte. Czekam minutę...");

    // Odlicz czas i włącz z powrotem
    Timer.set(CONFIG.relayOffDuration, false, function () {
      Shelly.call("Switch.Set", { id: 0, on: true }, function () {
        print("Zasilanie routera przywrócone.");
        // Daj routerowi dodatkowe 5 minut na pełne uruchomienie przed kolejnym testem internetu
        Timer.set(300000, false, function () {
          // Restart zakończył się normalnie - bezpiecznik jest już zbędny, anulujemy go,
          // żeby nie "wisiał" niepotrzebnie i przypadkiem nie zadziałał przy KOLEJNYM cyklu.
          if (safetyTimerId !== null) {
            Timer.clear(safetyTimerId);
            safetyTimerId = null;
          }
          failureCount = 0;
          isRebooting = false;
          print("Watchdog wznawia monitorowanie.");
        });
      });
    });
  });
}

// Decyduje, czy wykonać restart teraz, czy jesteśmy w trybie rzadszych prób
// po kilku nieudanych restartach z rzędu (patrz CONFIG.quickAttempts/backoffInterval).
function triggerReboot(reason) {
  if (backoffActive) {
    // Nadal czekamy w trybie rzadszych prób - nie restartuj teraz
    return;
  }

  consecutiveReboots++;
  doRouterPowerCycle(reason);

  if (consecutiveReboots >= CONFIG.quickAttempts) {
    backoffActive = true;
    print("Watchdog: " + consecutiveReboots + " restarty z rzędu bez efektu - przechodzę w tryb rzadszych prób (co " + (CONFIG.backoffInterval / 60000) + " min), prawdopodobna awaria po stronie operatora.");

    Timer.set(CONFIG.backoffInterval, false, function () {
      backoffActive = false;
      failureCount = 0; // Dajemy nową szansę na normalne wykrycie po przerwie
      print("Watchdog: koniec okresu oczekiwania, wracam do normalnego trybu sprawdzania.");
    });
  }
}

// Funkcja sprawdzająca endpointy PO KOLEI (sekwencyjnie) - Shelly Mini Gen3
// ma ograniczone zasoby i przy dwóch jednoczesnych połączeniach HTTP jedno z nich
// bywa zrywane (Connection error), mimo że internet działa prawidłowo.
// Błąd liczy się tylko, gdy WSZYSTKIE endpointy zawiodą w danym cyklu.
//
// WAŻNE: ta funkcja jest zadeklarowana RAZ, na poziomie głównym skryptu -
// nie wewnątrz cyklicznego Timer.set. Wcześniejsza wersja tworzyła tę funkcję
// od nowa przy każdym tyknięciu (co minutę), co powodowało powolny wyciek
// pamięci (błąd "Script ran out of memory" po kilku-kilkunastu godzinach).
function checkNextEndpoint(index, anySuccess) {
  if (index >= CONFIG.endpoints.length) {
    // Wszystkie endpointy sprawdzone - oceniamy wynik
    if (anySuccess) {
      failureCount = 0; // Choć jeden endpoint odpowiedział - internet działa
      consecutiveReboots = 0; // Internet faktycznie wrócił - resetujemy licznik eskalacji
      backoffActive = false;  // Wracamy do trybu szybkiej reakcji od razu, gdy internet działa
    } else {
      failureCount++;
      print("Brak odpowiedzi ze WSZYSTKICH endpointów (" + failureCount + "/" + CONFIG.maxFailures + ")");

      // Jeśli uzbiera się 5 minut (5 prób x 60s) ciągłego braku sieci
      if (failureCount >= CONFIG.maxFailures) {
        triggerReboot("Wykryto zawieszenie sieci (Watchdog 5 min)");
      }
    }
    return;
  }

  let url = CONFIG.endpoints[index];
  Shelly.call("HTTP.GET", { url: url, timeout: 15 }, function (response, error_code) {
    let ok = (error_code === 0 && response && response.code >= 200 && response.code < 300);

    if (!ok) {
      // Log diagnostyczny - pomaga zrozumieć PRZYCZYNĘ ewentualnego błędu
      let respCode = response ? response.code : "brak";
      print("Test '" + url + "' nieudany. error_code=" + error_code + ", response.code=" + respCode);
    }

    // Przechodzimy do kolejnego endpointu dopiero PO zakończeniu tego zapytania
    checkNextEndpoint(index + 1, anySuccess || ok);
  });
}

// 1. Pętla sprawdzająca internet (co minutę)
Timer.set(CONFIG.checkInterval, true, function () {
  if (isRebooting) return;
  checkNextEndpoint(0, false);
});

// 2. Pętla sprawdzająca czas do nocnego restartu (co minutę)
// WYŁĄCZONE NA CZAS TESTÓW - zmień CONFIG.nightRebootEnabled na true, żeby przywrócić.
Timer.set(60000, true, function () {
  if (!CONFIG.nightRebootEnabled) return;

  let sysStatus = Shelly.getComponentStatus("sys");

  if (sysStatus && sysStatus.time) {
    let timeParts = sysStatus.time.split(":");
    if (timeParts.length >= 2) {
      // Bezpieczna konwersja tekstowej godziny/minuty na liczbę
      let currentHour = Number(timeParts[0]);
      let currentMinute = Number(timeParts[1]);

      // Sprawdź czy wybiła dokładnie 01:00
      if (currentHour === CONFIG.nightRebootHour && currentMinute === CONFIG.nightRebootMinute) {
        if (!midnightRebootDone && !isRebooting) {
          midnightRebootDone = true;
          doRouterPowerCycle("Zaplanowany nocny restart profilaktyczny");
        }
      } else {
        // Resetuj flagę po minięciu godziny 1:00, żeby zadziałało kolejnego dnia
        midnightRebootDone = false;
      }
    }
  }
});

print("Skrypt Watchdog + Restart 1:00 został poprawnie zainicjalizowany.");

// 3. Okresowe logowanie wolnej pamięci systemowej (co 30 minut).
// Dzięki temu w logach zobaczysz TREND w czasie (a nie tylko jednorazowy
// zrzut przy starcie skryptu) - pozwoli to potwierdzić, czy poprawka
// wycieku pamięci faktycznie działa, czy wolna pamięć nadal powoli spada.
function logFreeMemory() {
  let sysStatus = Shelly.getComponentStatus("sys");
  if (sysStatus && typeof sysStatus.ram_free !== "undefined") {
    print("Watchdog - wolna pamiec systemowa: " + sysStatus.ram_free + " / " + sysStatus.ram_size + " bajtow");
  }
}

logFreeMemory(); // Pierwszy odczyt od razu na starcie - punkt odniesienia "zero"
Timer.set(1800000, true, logFreeMemory);


All_2026-9-21-8_50_49.csv
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
wojtek
Newb
Newb
Posty: 44
Rejestracja: poniedziałek 10 kwie 2023, 15:15

Re: skrypt do sprawdzenia

Postautor: wojtek » wtorek 22 wrz 2026, 16:19

To testy zakończone, jeszcze ostatnie poprawki, bo soft się wysypał na zbyt dużej ilości timer.set czego jak się okazuje nie dopuszcza "system" shelly. Po poprawkach testowanie ok, wszystkie funkcje działają.
All_2026-9-22-14_25_18.csv

shelly-watchdog_10.js
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.


Wróć do „DIY”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 1 gość