Osobiście nie lubię terminu 'inteligentny dom’. Inteligentny może być człowiek, dom może być umiejętnie sterowany na podstawie pewnych zdarzeń. Chociaż oglądając ostatnie poczynania Google Duplex zaczynam powoli zastanawiać się nad zmianą mojej opinii 😉
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ę!