W poprzednim wpisie opisałem proste zdarzenia na czujnikach, switch’ach, itp. W Domoticz jest (jak napisałem) możliwość wykorzystania kilku schematów zdarzeń:
– bezpośrednio na samych czujnikach
– schematy blokowe w Blockly
– skrypty Lua lub Python
– dzVents
Dzisiaj skupię się na dzVents – wewnętrznym języku skryptów Domoticz. W sumie bazuje na Lua, czyli załatwiamy po części punkt trzeci 😉 Takie małe skróty.
Warto zainwestować czas w naukę, ponieważ schematy Blockly, mimo że ładne, swoje ograniczenia mają. Nadmieniam – nie jestem w tym temacie (jeszcze) ekspertem – to moje początkowe próby.
Opieram się na wersji 2.2.0, dostępnej w ostatniej stabilnej wersji Domoticz!
Dokumentacja tej wersji dostępna jest pod linkiem:
https://github.com/domoticz/domoticz/blob/9f75e45f994f87c8d8ce9cb39eaab85886df0be4/scripts/dzVents/documentation/README.md
No bo proszę, jakże naturalne jest wpisanie:
Co 10 minut w dni powszednie uruchom akcje:
– Jeżeli to nie wieczór i nie noc, przepisz wartość zmiennej do innej zmiennej, upewnij się, że światła w salonie wyłączone, a do tego, jeżeli czujka ruchu nie odpowiada – wyłącz światło w łazience
return {
active = true,
on = {
timer = {’Every 10 minutes on mon,tue,wed,thu,fri’}
},
execute = function(domoticz)
if (domoticz.time.isDayTime and domoticz.variables(’Zmienna1′).value == 10) then
domoticz.variables(’Zmienna2′).set(15)
domoticz.setScene(’Światła Salon’, 'Off’)
if (domoticz.devices(’CzujkaRuchu’).lastUpdate.minutesAgo > 5) then
domoticz.devices(’Bathroom lights’).switchOff()
end
end
end
}
To tylko jednak przykład. Sam używam kilku innych skryptów, które okazały się bardzo przydatne.
Zacznijmy od tego jak je pisać i gdzie możemy je znaleźć.
Setup -> More Options -> Events. Tam znajdziemy edytor z kilkoma możliwymi typami:
– Blockly
– Lua
– dzVents
– Python
Nas interesuje aktualnie dzVents i taki typ musimy wybrać przy tworzeniu nowego pliku. Nie zapomnijcie również wpisać nazwy oraz zmienić Event active na włączony. Dla wyjaśnienia – skrypty można tworzyć i z poziomu Raspberry Pi, z basha zapisując je w odpowiednim folderze, ale tutaj mamy pewność, że Domoticz sam je sobie w dobrym miejscu osadzi. I będzie mniej problemu przy przenoszeniu systemu.
Mała sugestia – sprawdzajcie log Domoticz, szczególnie na początku tworzenia – często są tam przydatne informacje – czy skrypt się załadował, czy wystartował, jak działa, w jakiej zmiennej się pomyliliśmy, jaka funkcja ma złą nazwę (patrzcie dokładnie ma małe/duże litery – ma to ogromne znaczenie!).
1. Na początek – nie podobało mi się jak barometr Xiaomi jest prezentowany w Domoticz. Pokazuje złe wartości. Oczywistym jest, że ciśnienie 969 Bar nie jest poprawne… Głupota, szczegół? Owszem, ale uważam, że ten szczegół trzeba poprawić.
No to raz, dwa, trzy:
return {
active = true,
on = {
[’timer’] = {’every 30 minutes’}
},
execute = function(domoticz)
local Baro = domoticz.devices(’Xiaomi Baro Kuchnia’).pressure
domoticz.devices(’Baro Kuchnia’).updateBarometer(Baro, domoticz.BARO_NOINFO)
end
}
Zwróćcie uwagę na konstrukcję:
– początek funkcji
– warunek wyzwolenia – tutaj czasowy
– zawartość funkcji
Co zrobiliśmy? Co 30 minut uruchom przepisanie wartości z czujnika do zmiennej, a później zmienną przepisz do osobno założonego czujnika ciśnienia.
I już, działa.
Zauważcie, że czujnik ciśnienia można zaktualizować o parametry, tutaj BARO_NOINFO (czyli nie zmieniamy), ale może on przyjmować również wartości:
BARO_CLOUDY, BARO_CLOUDY_RAIN, BARO_STABLE, BARO_SUNNY, BARO_THUNDERSTORM, BARO_NOINFO, BARO_UNSTABLE
Nie jestem fizycznie w stanie opisać tutaj wszystkich parametrów wszystkich czujników – zapraszam do czytania dokumentacji i własnych prób.
2. Kolejny temat – biegam. Dużo biegam. Wstaję rano, banan, woda i w drogę. Ale lubię wiedzieć jak mam się ubrać. Albo inny przykład – w zimie warto wiedzieć czy jest przymrozek.
Oczywiście – można sprawdzić prognozę pogody albo wyjrzeć za okno, ale często gdy wstanę sprawdzam pocztę i akurat takie podstawowe informacje mi pomagają.
return {
on = {
[’timer’] = {’at sunrise’}
},
execute = function(domoticz)
local Tmp = domoticz.devices(’Temp na zewnątrz’).temperature
function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
domoticz.notify(’Temperatura’, 'O wschodzie słońca było ’ ..round(Tmp,1), domoticz.PRIORITY_NORMAL)
end
}
Tytułem wytłumaczenia – funkcja round() pojawiła się w nowszej wersji dzVents, ja musiałem poszukać innego rozwiązania (Łukasz Rybak – dziękuję).
W sumie przyszło mi do głowy w trakcie pisania, że dobrze byłoby rozwiązanie uczynić bogatszym o dane większej ilości czujników z domu – temperatura w kilku pokojach, status świateł, itp. Zapisuję na liście 'Do zrobienia’ 🙂
3. Jest sobie u mnie w domu ekran do projektora. Wisi (Tak przy okazji to zestaw ekran + projektor to jeden z lepszych zakupów w życiu). Stworzyłem sceny, np. 'Oglądamy film’, które wyłączają światła w salonie, włączają subwoofer, projektor i obniżają ekran. Problem z nim jednak był taki, że nie rozwijam go do końca, tylko musi się zatrzymać w konkretnej pozycji. Jak, po wydaniu komendy 'W dół’, zatrzymać go? dzVents ma funkcję stop().afterSec().
return {
active = true,
on = {
devices = {
'Ekran’
}
},
execute = function(domoticz,switch)
if (switch.state == 'On’) then
switch.stop().afterSec(51)
end
end
}
Czyli start ręcznie w Domoticz, czekamy 51 sekund, stop. Bajka.
4. Kolejny temat – powiadomienia przy pewnych warunkach. Tutaj – zbyt wysoka temperatura sugeruje, że coś złego może się dziać w domu. Oczywiście można na każdym z osobna to 'wyklikać’, ale nie jest to zbyt optymalne.
return {
active = true,
on = {
devices = {
'Temperatura Salon’,
'Temperatura Kuchnia’,
'Temperatura Sypialnia’,
}
},
execute = function(domoticz,device)
if (device.name == 'Temperatura Salon’ and device.temperature >= 45) then
domoticz.email(’Możliwy pożar!’, 'Zbyt wysoka temperatura!’, 'adres@gmail.com’)
end
if (device.name == 'Temperatura Kuchnia’ and device.temperature >= 45) then
domoticz.email(’Możliwy pożar!’, 'Zbyt wysoka temperatura!’, 'adres@gmail.com’)
end
if (device.name == 'Temperatura Sypialnia’ and device.temperature >= 45) then
domoticz.email(’Możliwy pożar!’, 'Zbyt wysoka temperatura!’, 'adres@gmail.com’)
end
end
}
Dodajcie swoje warunki (np. tylko w nocy, bo wtedy na pewno nie świeci słońce na termometr) i do dzieła!
5. Jak do tej pory najciekawsza funkcja, którą zrobiłem to 'Tryb wakacyjny’.
Nie ma się co śmiać, dopiero zaczynam 😉
Mam oto przełącznik w Domoticz, który zowie się 'Wakacje’. I pod niego powoli podpinam różne akcje. Na przykład: gdy wyjedziemy, Domoticz ma włączyć światła o losowej minucie po 22:00 (ale w zakresie 30 minut) i wyłączyć również losowo po 23:30. Taki symulator tego, że ktoś jest w domu.
local RANDOM_DELAY_MINS = 30
return {
active = true,
on = {
[’timer’] = {
’at 22:00′,
’at 23:30′
}
},
execute = function(domoticz,_,triggerInfo)
if (domoticz.devices(’Wakacje’).state == 'On’) then
if (domoticz.devices(’Kinkiety’).state == 'Off’) and (triggerInfo.trigger == 'at 22:00′)
then
domoticz.devices(’Kinkiety’).switchOn().withinMin(RANDOM_DELAY_MINS)
domoticz.email(’Światła włączone!’, 'Światła włączone!’, 'adres@gmail.com’)
else
domoticz.devices(’Kinkiety’).switchOff().withinMin(RANDOM_DELAY_MINS)
domoticz.email(’Światła wyłączone!’, 'Światła wyłączone!’, 'adres@gmail.com’)
end
end
end
}
Mam tam jeszcze kilka innych 'ifów’, ale ważny jest początek i sens funkcjonalności. Rozbudować go można dowolnie – włącz raz na górze, raz na dole, w zależności od dnia tygodnia włącz różne, itp., itd. Ogranicza Was wyobraźnia. No i czas 😀
6. Funkcja z dnia wczorajszego 😉 Powiadomienie, jeżeli drzwi są otwarte zbyt długo, a jeżeli są, to przez jaki czas. Dla drzwi na taras dałem limit 30 minut, bo są częściej i dłużej otwierane. Dla drzwi na inny taras – krótszy okres, bo praktycznie ich nie używamy. Zwróćcie uwagę na drugi warunek – jeżeli czas jest mniejszy niż 3 * limit – czyli w tym przypadku na przykład dla 'Drzwi – czujnik’ jest to 90 minut – przestań wysyłać powiadomienia, bo widocznie tak ma być. Oczywiście po zamknięciu zmienne zostaną wyzerowane.
local devicesToCheck = {
{ [’name’] = 'Drzwi – czujnik’, [’threshold’] = 30 },
{ [’name’] = 'Drzwi mały taras’, [’threshold’] = 10 },
}
return {
active = true,
on = {
timer = {’every 10 minutes’},
},
logging = {
level = domoticz.LOG_DEBUG,
marker = „Door”
},
execute = function(domoticz)
local times = 3
for i, deviceToCheck in pairs(devicesToCheck) do
local name = deviceToCheck[’name’]
local threshold = deviceToCheck[’threshold’]
local state = domoticz.devices(name).state
local minutes = domoticz.devices(name).lastUpdate.minutesAgo
if ( state == 'Open’) then
if (minutes > threshold) and (minutes < 3 * threshold) then
domoticz.notify(’Device ’ .. name .. ’ otwarte ’ .. minutes .. ’ minut.’, domoticz.PRIORITY_HIGH)
end
end
end
end
}
Jak na razie to koniec – mam jeszcze kilka zdarzeń podpiętych, ale nie są aż tak warte opisania. Do tego kilkanaście kolejnych w głowie, które muszę sobie stworzyć.
Dzięki temu system nabiera sensowności. Bo cóż z tego, że sprawdzam temperaturę, jeżeli nic za tym nie idzie? Dopiero obudowanie Domoticz reagowaniem na czynniki zewnętrzne tworzy nam rozwiązanie godne miana 'Smart home’.
Przyjemnego kodowania życzę!