Interwał czasowy odporny na restarty systemu

Szukam sposobu na trigger, który będzie uruchamiał urządzenie regularnie co 48 godzin i będzie odporny na restart HA, zanik prądu itp
Jedyne co znalazłem w sieci to “varidelay” ale nie za bardzo potrafię go zastosować do mojego konkretnego przypadku gdzie chodzi o regularny, dwudniowy interwał.
Na razie mam po prostu ustawiony inject wg dni tygodnia ale tydzień ma 7 dni i zawsze w końcu wychodzi odstęp 24h raz na tydzień…

Zmienną kontekstową przechowuj w pliku.
Zapamiętuj timestamp ostatniego uruchomienia procesu i przez porównanie z obecnym czasem wykrywaj upływ 48h. Może i jest jakiś gotowy nod… ale po co?

O ile mogę się domyślać jak zapisać i odczytać payload z pliku, o tyle napisanie funkcji porównującej te wartości i na ich podstawie wykrywającej interwał czasowy - leży poza moimi możliwościami…

Myśle, że jest zupełnie odwrotnie :wink:
O ile odjęcie dwóch liczb calkowitych jest proste, to już zapaniętenie mniej.
Nod inject podaje w ms czas do poczatku czasu unix, ktory rozpoczął sie coś ok 1970 roku.
Wystarczy zapamiętacz timestamp wystąpienia zdarzenia i odejmowanie od czasu obenego.
Jeśli różnia jest większa od 48h w milisekundach.

Dziękuję, że poświęcasz mi czas ale ja to akurat rozumiem co mam zrobić. Nie znam za to kodu i nie napiszę nawet tak prostego skryptu.

Nie jest to niewiadomo ile roboty, wiec poczekaj.
Gdy będę miał możliwość to coś sklece…

Myślę, że można w ten sposób …
w przykładzie uruchamiam co minutę i sprawdzam czy upłynął zaplanowany czas …

var lastTimestamp = flow.get('lastTimestamp');
var currentTime = Date.now();
var result;

if (lastTimestamp) {
    if ((currentTime - lastTimestamp) >= 60000) {
        result = "Minęła jedna minuta od ostatniego uruchomienia.";
    } else {
        result = "Jeszcze nie minęła jedna minuta od ostatniego uruchomienia.";
    }
} else {
    result = "To jest pierwsze uruchomienie skryptu.";
}


flow.set('lastTimestamp', currentTime);

msg.payload = result;
return msg;

1 polubienie

@MariuszAK… jeszcze opisz jak zapamiętać zmienną na dysku. Pamietam, że gdzieś już to tłumaczyłeś

bez modyfikacji konfigu NR … zapamiętywanie zmiennej w “memory_only”

flow.set('lastTimestamp', currentTime);

odczytywanie zmiennej zapamiętanej

flow.get('lastTimestamp');

… jeśli ktoś modyfikował konfig w NR i ma możliwość zapisywać zmienne “do pliku” wtedy jest też taka możliwość ale zapis wygląda trochę inaczej.

A jak się mają do tego nody write file i read file?
Bo to akurat udało mi się uruchomić samemu :smiley:

Podobnie jak flow.get flow.set ,które zapisują w pamięci. Jeśli potrafisz odczytać/zapisać do pliku liczbę i ją później użyc, to może byc inny sposób osiągnięcia celu.

Udało mi się zapisać do pliku timestamp. Jedyne co mnie zastanawia to kropka na końcu ale wiem, że można dość łatwo taki ostatni znak pominąć (jak się zna javę :D).
Mając powyższe wskazówki chyba mogę już spróbować stworzyć flow.

EDIT:
Tak jak myślałem, działa ale nie odejmuje z powodu tej kropki na końcu.

Zmieniłem pierwszą zmienną na msg.payload. Wcześniej dałem nod odczytujący z pliku timestap jako msg.payload. Problemem jest tylko ta kropka - jak się jej pozbyć?

EDIT 2:
Nie… to jednak bardziej skomplikowane niż problem z kropką. Nie potrafię użyć msg.payload jako zmiennej.

EDIT 3:
Upór się opłacił. Zmodyfikowałem kod do takiej postaci i działa. Dam nod “switch” i będzie mi uruchamiał urządzenie po zadanym interwale czasu.

var lastTimestamp = msg.payload;

var czas = lastTimestamp.slice(0, lastTimestamp.length - 1);

var currentTime = Date.now();
var result;

if (czas) {
    if ((currentTime - czas) >= 172800000) {
        result = "START";
    } else {
        result = "JESZCZE NIE";
    }
} else {
    result = "FIRST START";
}


flow.set('czas', currentTime);

msg.payload = result;
return msg;

Jak na nieznajomość java to jest ok :wink:
Trochę pokombinowane.
Jesli piszesz o jakimś problemie to podawaj więcej info, Twoja kroka jest zastanawiająca.

Ta kropka to nawet może być moim urojeniem bo ja jej teraz już nie widzę, może coś zmieniłem - pisanie takich procesów w stanie absurdalnego niewyspania w nocy to nie jest najlepszy pomysł… konkludując - dzisiaj pomidory podlewały się 3 godziny zamiast pół… ale już poprawiłem, uprościłem i sprawiłem, że działa. Kropki nie ma, slice nie jest potrzebne - uprościłem kod pobierając od razu msg.payload jako zmienną. Na początku nie miałem bladego pojęcia od czego zacząć ale dzięki Twojej podpowiedzi mogłem ruszyć z procesem - dziękuję.

Jedyna niedoskonałość tego procesu, to że muszę ręcznie zatrzymać inject po pierwszym uruchomieniu.

[{"id":"ed9d3579ddc53491","type":"inject","z":"ee09838ef0f1eab3","name":"5:00","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 05 * * 2","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":280,"wires":[["7a62cfb36a84a6bc","0247dbf0bcc2b15b"]]},{"id":"7a62cfb36a84a6bc","type":"api-call-service","z":"ee09838ef0f1eab3","name":"Podlewanie ON","server":"9fb271c8.95f17","version":5,"debugenabled":false,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.sonoff_a480066ed1"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":480,"y":260,"wires":[[]]},{"id":"0247dbf0bcc2b15b","type":"file","z":"ee09838ef0f1eab3","name":"Zapisz do pliku","filename":"/homeassistant/www/podlewanie.txt","filenameType":"str","appendNewline":false,"createDir":true,"overwriteFile":"true","encoding":"none","x":440,"y":200,"wires":[[]]},{"id":"8484a8a5b1bb15a9","type":"switch","z":"ee09838ef0f1eab3","name":"Switch","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"START","vt":"str"},{"t":"eq","v":"JESZCZE NIE","vt":"str"},{"t":"eq","v":"FIRST START","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":590,"y":340,"wires":[["2789ab66b8173ba1","7a62cfb36a84a6bc","8018db79993114c7"],[],[]]},{"id":"2789ab66b8173ba1","type":"function","z":"ee09838ef0f1eab3","name":"timestamp do payload","func":"var timestamp = Date.now();\nmsg.payload = timestamp\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":280,"wires":[["0247dbf0bcc2b15b"]]},{"id":"7505d2772b872454","type":"function","z":"ee09838ef0f1eab3","name":"48 godzin","func":"var czas = msg.payload;\nvar currentTime = Date.now();\nvar result;\n\nif (czas) {\n    if ((currentTime - czas) >= 172800000) {\n        result = \"START\";\n    } else {\n        result = \"JESZCZE NIE\";\n    }\n} else {\n    result = \"FIRST START\";\n}\n\nmsg.payload = result;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":340,"wires":[["8484a8a5b1bb15a9"]]},{"id":"8018db79993114c7","type":"debug","z":"ee09838ef0f1eab3","name":"debug 7","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":780,"y":340,"wires":[]},{"id":"f8791a58d82f21fd","type":"file in","z":"ee09838ef0f1eab3","name":"Odczytaj z pliku","filename":"/homeassistant/www/podlewanie.txt","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":300,"y":340,"wires":[["7505d2772b872454"]]},{"id":"dbe522647a9109f2","type":"inject","z":"ee09838ef0f1eab3","name":"raz na minutę","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":340,"wires":[["f8791a58d82f21fd"]]},{"id":"9fb271c8.95f17","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

A co niby miało zatrzymać to podlewanie ?

Nie wiem o który inject chodzi ale można go tak ustawić aby uruchomił się tylko raz podczas startu procesu

A co niby miało zatrzymać to podlewanie ?

Stwierdziłem, że najprostszy i najskuteczniejszy będzie osobny proces uruchamiany co 24h. Zawsze zadziała i to tylko 2 nody o banalnej konfiguracji i to działało ale… problem był w tym procesie sprawdzającym co minutę… zły kod sprawił, że zawsze wynikiem był START i tak przez 3 godziny aż wstałem i to ręcznie wyłączyłem.

Nie wiem o który inject chodzi ale można go tak ustawić aby uruchomił się tylko raz podczas startu procesu

Jeśli dobrze rozkminiam to można go uruchomić tylko raz ręcznie ale jakoś mi się nie chce budzić o 5 rano, żeby to zrobić :smiley:

Patrząc na ten proces nie mogę w doszukać się logiki.
Napisz dokładnie krok po kroku co chcesz uzyskać i załącz export flow w pliku yaml to łatwiej będzie można zrobić poprawki

Przepraszam, szukam wszędzie i nie potrafię zapisać flow w formie yaml, moja wiedza jest niepełna. Wyeksportowałem cały proces jako jako json, myślałem że to wystarczy, żeby go sobie zaimportować i zobaczyć.

Co do samego procesu to on już działa poprawnie. A logika? No… taka jak miała być od samego początku:

  1. inject generuje timestamp o wybranej przeze mnie godzinie uruchamiając urządzenie (w tym przypadku zawór wodny)
  2. nod write file zapisuje ten timestamp do pliku
  3. równolegle inny inject co minutę wysyła msg do noda read file ażeby odczytywał tą zapisaną wiadomość (msg.payload jest tym zapisanym wcześniej timestam’em}
  4. funkcja odejmuje ten odczytany z pliku timestamp od teraźniejszego czasu
  5. jeśli wartość różnicy jest >= zadanej przeze mnie wartości - generuje msg.paylod START
  6. nod switch po wykryciu START puszcza dalej msg uruchamiając znowu zawór i jednocześnie aktualizując timestamp w pliku na dysku i zabawa się zaczyna od nowa.

Zamykanie zaworu jest realizowane przez osobny proces raz na dobę - jest to proste i pewne.

Tak jak pisałem - jedyna “niedoskonałość” jest taka, że jak już pierwszy raz cały ten proces wystartuje to w ciągu tygodnia muszę pamiętać, żeby noda inject wyłączyć bo za tydzień znowu o 5 rano mi wyśle timestamp a to będzie akurat dzień bez podlewania.

Jasne, że w json… palnąłem :wink:
Poszczególne funkcje to znam… bardziej chodziło mi o opis funkcjonalny argorytmu.
Co kiedy i na jak dlugo ma się zalączać?