Strona 1 z 1

skrypt do sprawdzenia

: wtorek 15 wrz 2026, 09:43
autor: wojtek
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.

Re: skrypt do sprawdzenia

: wtorek 15 wrz 2026, 14:34
autor: wojtek
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.");

Re: skrypt do sprawdzenia

: niedziela 20 wrz 2026, 11:28
autor: wojtek
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

Re: skrypt do sprawdzenia

: poniedziałek 21 wrz 2026, 09:59
autor: wojtek
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

Re: skrypt do sprawdzenia

: wtorek 22 wrz 2026, 16:19
autor: wojtek
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