Mis see AI HA kontekstis üldse tähendab, kas kõnesünteesi ja käskluste andmist, tehislik vestluspartner või AI optimeerib tarka kodu ja nt ütled HA ühendatud kõlarisse - "palun lülita boiler Nordpooli elektrihinda jälgima", ja AI ise kribab taustal koodi, jälgib millal peamiselt sooja vett tarbitakse ning millal on tõenäolisemalt odavamad elektrihinna tunnid ja soojendab võimalikult säästlikult vett vajalikuks ajaks - ulme vist
Hetkel enam kiiruga ei leia üles aga kevadel komistasin miski redditi lõime otsa, kus AI ja HA teemal tuliselt vaieldi. Sealsete kasutajate peamine ootus ja rõhuasetus AI-le HA kontekstis oligi välja saamine sellest totakast kodeerimisest, kus HA on peamiselt IT ja inseneri entusiastide pärusmaa ehk nõuab spetsiifilisi programmeerimise oskusi. Ehk AI võiks ise "musta töö" taustal ära teha, kasutaja ainult kirjeldaks mida tahab saada, samamoodi kui tänased AI chat-id kus küsid, kui vastus ei rahulda, täpsustad niikaua kuni jõuad oodatud vastuseni ja kasutades-küsides õpid samas ka "õigesti" küsima.
Osad pidasid seda võimatuks missiooniks, kus tänased keelemudelid õpivad peamiselt internetiinfo pealt, valdav osa HA seotud infot internetis pidavat olema hädas kasutajate läbivalt oskamatu ja vigane kood või koodinäited mis on lihtsalt vananenud. Ka juba hulk 2+ aastat tagasi toimivat koodi ei pidavat enam täna ilma mudimata toimima, HA on pidevalt arenev ja muutuv.
Kui AI õpib vigasest ja vananenud näidetest, ei saa sealt tulla ka pädevat abilist.
Kas AI HA üks sisestusvahend trükkimise ja dashboard heeblitele lisaks, või AI kui sisulist lisaväärtust targa kodu vaatest analüüsimas ja taustal toimetamas.
HA kontekstis hetkel lihtsalt vabas vormis päringute tegemist ja seadmete kontrollimist. Nüüd lisaks lisati timerid (26 juuni - Voice Chapter 7 - Supercharged wake words and timers).
AI (LLM) ise mingeid timereid, analüüse ja agregeerimist teha ei oska. Intent võetakse sealt lausest välja (koos sisendiga) ja vastavalt käivitatakse vastavad AI jaoks tehtud alammoodulid (funktsioonide kogumid), mis täpsed agregeerimised AI väljundi jaoks ära arvutavad.
Avar tehnoruum on rikaste või raha mittelugeda oskajate lõbu icon_razz1.gif
Hea, kui eramutes on normaalselt nõrkvoolgi planeeritud. Entusiast oskab suunata, tavainimene laseb valmis ehitada ja siis tahab normaalset võrku ja/või wifit, aga ups, kaableid polegi.
Võtsin magamistoa kardinatele ka mootori, Somfy Glydea. Hakkasin otsima Fibaro Roller Shutter 3 integreerimiseks aga vaatasin, et uus 4. versioon ka väljas. Fibaro enda lehel mitte mingit piiksugi sellest
Imelik, et paljudes kohtades on juba müügil aga Fibaro ise sellist toodet oma lehel ei tunnista
Edit: Eile oli elektrikatkestus 4h, sai asjad kõik kenasti maha lastud tänu upsidele, aga peale voolu tagasitulekut oli neli ikea pirni kadunud ja ei saanud mingi valemiga neid enam võrku (va remove-add). Kuna kaks neist olid samad tegelased, kes eelmisel korral ka koostööst keeldusid, siis otsustasin kõik välja vahetada. Tundub väga sedamoodi, et pikema voolukatkestuse korral kaotavad oma identiteedi. Nutikodu võlud, peale elektrikatkestust tegeled mitu tundi elustamisega.
Nutiaiandusest veel niipalju, et täitsa pädevad junnid on. Igapäevasest (üle)kastmisest on jäänud alles vaid tünni täitmine ca paari nädala tagant korra.
Igast taimed värgid elavad, ei ole kordagi närbunud välja näinud enam. Väike üleujutus tekkis ühes kastis ainult kogemata ülenäperdamise tõttu.
Nii et vahest pädeb analoogmaailm täitsa hästi Praegu Fibaro switch lülitab hüdrofoori päeval mõneks minutiks taha iga paari tunni tagant, et mingi ahela õnnetuse tõttu kohe tünni tühjaks ei pumpaks.
Siis jääb paari tunni peale mõni liiter kasutamiseks 2 bar peal.
Kuumaasika hind tuleb üle mõistuse aga vähemalt on kõik roheline ja ilus
Elektri edastamine: päev 0,0567€/kWh
Elektri edastamine: öö 0,0328€/kWh
Taastuvenergia tasu 0,0105€/kWh
22% KM
Kellelgi kindlasti need lisatud ehk saab konfi linkida mis kuhu.
Template entity vaja teha, ise valid kas komponendid teed eraldi helperid või defineerid template entity scriptis.
Keeruline osa on ainult päeva ja öö jaoks if'i kirjutamine.
Kuna HA's skriptide kirjutamine on PITA, siis ma tegin HA kõrvale tillukese DietPI VM'i ja treisin oma börsiprogrammi seal valmis PHP'ga. Seal sai siis igasugu "otsuseid" hinna, temperatuuride, kellaaegade jms. baasil palju lihtsamalt teha. Väljundiks on kaks USB releed, mis on ühendatud soojuspumbaga. Plaanis on pumba külge kleepida veel pisike elektrihinnalipikuga display. HA'le söödetakse ette lõplikud numbrid ja see mis seisus releed on. Sisuliselt joonistab ta ainult graafikuid, muud midagi.
Ma loodakski siit foorumist kellegi valmis IF statmentitega lahendust kasutada.
Kodeerida üritamine kipub vererõhku tõstma
Developer Tools > Template, seal saab proovida erinevaid template'e enne kui sellest sensor luua. Genereerid ChatGPT abil põhja ja siis mudid paika väärtused.
ChatGPT suure tõenäosusega defineerib need helperid ise konfiguratsioonis, kuna enne UI's teha ei saanud. Nüüd saab UIs kergemini teha, seega saab ainult value_template osa võtta nt.
{% set nordpool_price = states('sensor.nordpool_price') | float %} ## siin vaja õige nordpooli sensori id panna
{% set transmission_day = 0.0567 %} ## hardcoded näeb välja sedasi
{% set transmission_night = 0.0328 %} ## ideaalis parem on teha number helper, mille väärtust saab UI's sisestada
{% set renewable_energy_fee = 0.0105 %} ## states('input_number.renewable_energy_fee ') | float võib nt 0.0105 asemele panna kui uus number helper luua idga renewable_energy_fee
{% set vat = 1.22 %}
{% set current_hour = now().hour %}
{% set transmission_fee = transmission_day if current_hour >= 7 and current_hour < 23 else transmission_night %} ## siin vaja kellaaeg paika panna, näites on suuremvõrdne 7 või väiksem kui 23
{{ ((nordpool_price + transmission_fee + renewable_energy_fee) * vat) | round(4) }}
Vaja oleks nii, et saaksin sisestada oma öö ja päevase elektrihinna Chelly koodi. Kui jooksval tunnil on börsi hind minu hinnast seatud hinnast kõrgem, siis relee on Off ja kui madalam, siis taas ON.
Misasi on chelly kood ? HA's sellise asja tegemiseks pole mingit koodi vaja, when and(if) then do.
Vaja oleks nii, et saaksin sisestada oma öö ja päevase elektrihinna Chelly koodi. Kui jooksval tunnil on börsi hind minu hinnast seatud hinnast kõrgem, siis relee on Off ja kui madalam, siis taas ON.
Misasi on chelly kood ? HA's sellise asja tegemiseks pole mingit koodi vaja, when and(if) then do.
Oled teadatuntud targutaja... selle asemel võiks kaaskodanukku aidata, mitte, et ma olen kõvamees ja norin terminite kallal.
Shelly nutiseadmele vaja skripti mis juhiks releed. Kui minu öö ja päevane seadistatud hind on börsil kõrgem, siis relee on OFF ja kui madalam, siis ON.
Kas on kellelgi olnud kokkupuuteid EZVIZ seadmetega (mitte kaamerad) vaid näiteks sedalaadi asjaga https://www.oomipood.ee/product/cs_b1_ezviz_cs_b1_valveseadmete_komplekt
ehk siis A3 keskjaam ja erinevad andurid, et kuidas neid seadistada? Kõik võiks nagu olla loogiline, aga käituvad asjad nagu ise tahavad, telefonile enamasti ei jõua ükski teada, kuigi kõik akuoptimeerimised maha keeratud ja muud load antud. Eile isegi mõni teade tuli läbi, täna 0. Keskseade küll vahepeal annab märku, aga ka see tundub sõltuma õhurõhust või tuule suunast. Kas keegi oskab suunata mõne asjalikuma seadistusjuhendini, kui tavapärased kasutusjuhendid, kus ainult üldsõnalised kirjeldused? Või on mõni asjalik foorum või muud õpetused? Sõber googelt proovisin. Muidu paistab kena mänguasi, kõik andurid võttis kenasti külge jne, aga soovi kohaselt toimima ei saa.
endale töötasin välja sellise valemi. Võtab nordpool integrationist ennustuse ja töötleb selle ostu ja müügi hinnaks:
Spoiler
{% set today = state_attr('sensor.nordpool_mwh_ee_eur_3_10_0', 'raw_today') %}
{% set tomorrow = state_attr('sensor.nordpool_mwh_ee_eur_3_10_0', 'raw_tomorrow') %}
{% set km = states('input_number.km') | float(22.0) %}
{% set buy_marginal = states('input_number.el_marginal_buy') | float(0.0) %}
{% set sell_marginal = states('input_number.el_marginal_sell') | float(0.8) %}
{% set aktsiis = states('input_number.el_aktsiis') | float(0.1) %}
{% set taast = states('input_number.el_taastuvenergiatasu') | float(1.13) %}
{% set oo = states('input_number.el_vorgutasu_oo') | float(3.28) %}
{% set paev = states('input_number.el_vorgutasu_paev') | float(5.67) %}
{% set src = namespace(numbers=[]) %}
{% set src.numbers = src.numbers + today + tomorrow %}
{% set data = namespace(numbers=[]) %}
{% for i in src.numbers %}
{% set n = i.start %}
{% set m = n.month%}
{% set d = n.day%}
{% set is_night = n.hour < 7
or n.hour >= 22
or n.weekday() >= 5
or m==1 and d==1
or m==2 and d==24
or m==5 and d==1
or m==6 and (d==23 or d ==24)
or m==8 and d==20
or m==12 and (d==24 or d==25 or d==26)%}
{% set tasud = aktsiis+taast+buy_marginal+(oo if is_night else paev) %}
{% set buy = ((i.value + tasud*10)*km) | round(2) %}
{% set sell = (i.value - sell_marginal*10) | round(2) %}
{% set data.numbers = data.numbers + [{"start": i.start | string, "pool": i.value, "buy": buy, "sell": sell}] %}
{% endfor %}
{{ data.numbers | tojson }}
Pead ei anna et õigesti arvutab kuna minu arvutuste järgi pidi elektriarve tulema 6€ aga tegelikult tuli 26€
Vaja oleks nii, et saaksin sisestada oma öö ja päevase elektrihinna Chelly koodi. Kui jooksval tunnil on börsi hind minu hinnast seatud hinnast kõrgem, siis relee on Off ja kui madalam, siis taas ON.
Misasi on chelly kood ? HA's sellise asja tegemiseks pole mingit koodi vaja, when and(if) then do.
Oled teadatuntud targutaja... selle asemel võiks kaaskodanukku aidata, mitte, et ma olen kõvamees ja norin terminite kallal.
Shelly nutiseadmele vaja skripti mis juhiks releed. Kui minu öö ja päevane seadistatud hind on börsil kõrgem, siis relee on OFF ja kui madalam, siis ON.
Asju võiks nimetada ikkagi õigete nimedega, siis on segadust vähem. Mis targutamisse puutub, siis ma eelistan anda kala asemel õnge, ei pea kõike kohe saama. Kuna jutt pole ilmselgelt enam HA'st, siis jään edasise vastuse võlgu, aga shelly skriptimiseks on mõistlik alustada siit: https://shelly-api-docs.shelly.cloud/gen2/Scripts/Tutorial
Mis oleks lihtsaim viis 2 hetkel tavalist lülitit nö vekslisse ajada?
Soovitavalt ilma mingi keskseadme/pilvelahenduse abita.
Tavalülitid nupplülitiga asendada ja Shelly 1 releed juhtima? Saab need omavahel kuidagi otsesuhtlema ka panna? _________________ Experience is what you get when you don't get what you want.
Mis oleks lihtsaim viis 2 hetkel tavalist lülitit nö vekslisse ajada?
Soovitavalt ilma mingi keskseadme/pilvelahenduse abita.
Tavalülitid nupplülitiga asendada ja Shelly 1 releed juhtima? Saab need omavahel kuidagi otsesuhtlema ka panna?
Olen veerand netti läbi kamminud aga päris enda vajadusele lahendust ei leia. Tõenäoliselt saaks mõnda olemasolevat Chelly koodi ära kasutada aga äkki keegi viitsib aidata?
Paljud lahendused sisaldavad boileri ja muude küttelahenduste taimereid ja muid lisafunktsioone. Mul on oleks vaja ühte konkreetset lahendust.
Vaja oleks nii, et saaksin sisestada oma öö ja päevase elektrihinna Chelly koodi. Kui jooksval tunnil on börsi hind minu hinnast seatud hinnast kõrgem, siis relee on Off ja kui madalam, siis taas ON.
Edasi läheb signaal kontrollerisse, mis ise edasi juhib liitumiskilbi automaadikat.
Siin on pisut rohkemate võimalustega skript, aga seda hinna järgi lülitamist teeb ka.
Olen veerand netti läbi kamminud aga päris enda vajadusele lahendust ei leia. Tõenäoliselt saaks mõnda olemasolevat Chelly koodi ära kasutada aga äkki keegi viitsib aidata?
Paljud lahendused sisaldavad boileri ja muude küttelahenduste taimereid ja muid lisafunktsioone. Mul on oleks vaja ühte konkreetset lahendust.
Vaja oleks nii, et saaksin sisestada oma öö ja päevase elektrihinna Chelly koodi. Kui jooksval tunnil on börsi hind minu hinnast seatud hinnast kõrgem, siis relee on Off ja kui madalam, siis taas ON.
Edasi läheb signaal kontrollerisse, mis ise edasi juhib liitumiskilbi automaadikat.
Siin on pisut rohkemate võimalustega skript, aga seda hinna järgi lülitamist teeb ka.
Shelly seadmele scripti saamine on kõige lihtsam aga, et ebaoluline sealt välja lülitada ja endale kasulik osa töösse jätta. Ei saa hakkama.
Natukene midagi muudan siis muutub kood vigaseks. Koguaeg käivitub kütmise režiim või siis ootab päeva soodsamat aega. Mul ei ole vaja arvestada temperatuuridega. Lihtsalt kui börsi hind on minu seatud hinnast odavam, siis on relee sees. Kui hind kerkib üle, relee väljas. Muu mind ei huvita.
Midagi sain toimima aga vajab veel jälgimist.
Aga kas pean tähelepanu pöörama sellisele veale?
Iga tunni kohta siis arvutatakse välja kas relee on sees või väljas. Arvutus hakkab kell 23:00 aga piiratud mälu tõttu arvutatakse ainult esimesed 20 tundi. Mis siis ülejäänud 4h saab?
Vajab veits planeerimist jah, 20 ajastust on limiit nagu see FAILED ütleb, siis ülejäänuid lihtsalt ignoreeritakse. Lahendus ilmselt oleks uus ajastus (schedule) lisada iga tunniga, sedasi on mälus ainult 1. Kuna ma sisu / toodet ei tea, siis 100% ei saa kindel olla, et see midagi ära ei lõhu.
Kuidas 2012 Nissan Leaf-ist akuprotsendi info kätte saaks? Et saaks vastavalt akuprotsendile saaks laadida öösel noppida välja odavaimaid tunde vastavalt sellele mitu tundi laadida vaja.
OBD2 jubin -> bluetooth -> LeafSpy äpp android emulaatoris -> HA.
Mõistuspärasemat moodust pole?
Elektri edastamine: päev 0,0567€/kWh
Elektri edastamine: öö 0,0328€/kWh
Taastuvenergia tasu 0,0105€/kWh
22% KM
Kas lingil olevat infot saaks kasutada ka nii, et määran öö ja päeva hinna. Ja nutipistik siis jälgib, et kui hind on alla määratud hinna. Relee tõmbab ja kui on üle, siis on väljas. Muud infot, funktsioone vaja ei olekski.
Kellelgi kindlasti need lisatud ehk saab konfi linkida mis kuhu.
Pole step-by-step tutorial aga kui natuke koodi süvened, oskad seda kirjutada siis võiks abiks olla küll. Kõigepealt template nimega nordpool-buy.yaml selline asi. Eeldab, et teed helperid nagu input_number.nordpool_day jne kõikide tasude kohta (vt koodi). Siis on vaja workday sensor plugin installida ja kaks eraldi sensorit teha tänase ning homse jaoks.
Kas keegi on kokku puutunud Atlantic boileri võrku ühendamise probleemiga läbi cozytouch rakenduse?
Kuidagi ei taha õnnestuda ja suppordist abi ei ole. Räägib, et meie regioonis tuleb kasutada google DNSi (8.8.8.8) ja avada tuleb port 804.
Samas NATistatud võrgust tavaolukorras väljaminev liiklus piiratud ei ole ja ma ei usu, et nad eeldavad sissetulevat portforwardi. DNSi sai vahetatud.
Telia fiiber, Mikrotik ruuter, Asuse AP.
Räägib, et meie regioonis tuleb kasutada google DNSi (8.8.8.8) ja avada tuleb port 804.
Samas NATistatud võrgust tavaolukorras väljaminev liiklus piiratud ei ole ja ma ei usu, et nad eeldavad sissetulevat portforwardi. DNSi sai vahetatud.
Milline forward siis veel kui on öeldud, et port 804 vaja avada?
Räägib, et meie regioonis tuleb kasutada google DNSi (8.8.8.8) ja avada tuleb port 804.
Samas NATistatud võrgust tavaolukorras väljaminev liiklus piiratud ei ole ja ma ei usu, et nad eeldavad sissetulevat portforwardi. DNSi sai vahetatud.
Milline forward siis veel kui on öeldud, et port 804 vaja avada?
suppordi poolt (mitmeid kordi) saadetud (leitav ka netist) juhis on veidi imelik. Ei räägita port forwardist vaid "open port" nimelisest asjast. Jutt on pehmelt öeldes segane ja detaile juurde ei lisata. Raiutakse täpselt sama vastust.
Kas siin mõin on, kes on cozytouch rakendusega mõned nende asjad suutnud ära regada ?
!!! When you cannot pass through step connection to server:
Some products cannot be paired because of internet box/router local settings
This case is especially for East Europe countries (Baltic states, Russian Federation, Czech Republic, Poland, Slovenia, Bulgaria, Ukraine, Hungary)
What to change or add in settings:
o DNS, add international address Google (8.8.8.8)
o Open port 804
No see tähendabki, et suunad/avad nimetatud numbriga pordi.
Boilerile pane staatiline ip või lase ruuteril talle konkreetne ip anda. Mõlemad variandid peaks toimima.
Ja siis suunad selle 804 pordi sellele boileri aadressile.
Kas port tegelikult ka lahti on, saab kontrollida nt.: https://portchecker.co/canyouseeme
Sellel suunatud pordil peab siis reaalselt ka mingi teenus vastama.
No see tähendabki, et suunad/avad nimetatud numbriga pordi.
Boilerile pane staatiline ip või lase ruuteril talle konkreetne ip anda. Mõlemad variandid peaks toimima.
Ja siis suunad selle 804 pordi sellele boileri aadressile.
Kas port tegelikult ka lahti on, saab kontrollida nt.: https://portchecker.co/canyouseeme
Sellel suunatud pordil peab siis reaalselt ka mingi teenus vastama.
Üldiselt on IOT seadmele avaliku ligipääsu tekitame üsna riskantne. Tootjad ei tegele nende seadmete turvamisega eriti hästi.
Ja miks viidatakse et just selline ida-euroopa on problemaatiline, kas kesk- ja lääneeuroopas on kõik uksed valla...
Ühesõnaga tundub kahtlane ja hea meelega kuulaks ära kellegi, kes cozytouchiga seadmeid on ühendanud, et teada saada milles päriselt kühvel on..
Ja pordi kasvõi prooviks avamine ei tule kõne allagi? Et äkki hakkab tööle, mis siis küll saab... _________________ Experience is what you get when you don't get what you want.
"Open port" ei tähenda üldjuhul pordisuunamist, vaid seda, et sul ei oleks siseneval liiklusel müüri peal. Cozytouch on täiesti tavaline-tüüpiline pilverakendus, need ei nõua mingeid pordisuunamisi, see oleks nonsens. Kuna 804 kuulub privilegeeritud portide vahemikku, siis vahel tähendab linnuke "firewall" seda, et sisenev 1-1024 on eraldi blokeeritud. Vaata oma Microtiki seaded üle.
Cozytouch on täiesti tavaline-tüüpiline pilverakendus, need ei nõua mingeid pordisuunamisi, see oleks nonsens.
Ükski normaalne ei räägi lõppkliendile portidest. Paned oma kasutaja ja parooli ja kogu moos. Peale väikest googledamist tundub aina enam, et mingi käkerdis.
Kas keegi on kokku puutunud Atlantic boileri võrku ühendamise probleemiga läbi cozytouch rakenduse?
Kuidagi ei taha õnnestuda ja suppordist abi ei ole. Räägib, et meie regioonis tuleb kasutada google DNSi (8.8.8.8) ja avada tuleb port 804.
Samas NATistatud võrgust tavaolukorras väljaminev liiklus piiratud ei ole ja ma ei usu, et nad eeldavad sissetulevat portforwardi. DNSi sai vahetatud.
Telia fiiber, Mikrotik ruuter, Asuse AP.
Cosytouch Bridge abil ühendamine ei vaja Telia ruuteri puhul mitte mingit ruuteri seadistamist. Cosytouch Bridge mõne aasta vanune versioon oli ainult võrgukaabliga ruuteriga ühendatav ja ühendub boileriga raadio teel. Boileril otse ühendamise võimalust, ilma Cosytouch Bridge-ta polnud. Saab seda boilerit üldse ilma Cosytouch Bridge-ta internetiga ühendada?
matukas kirjutas:
Kas keegi on kokku puutunud Atlantic boileri võrku ühendamise probleemiga läbi cozytouch rakenduse?
Kuidagi ei taha õnnestuda ja suppordist abi ei ole. Räägib, et meie regioonis tuleb kasutada google DNSi (8.8.8.8) ja avada tuleb port 804.
Samas NATistatud võrgust tavaolukorras väljaminev liiklus piiratud ei ole ja ma ei usu, et nad eeldavad sissetulevat portforwardi. DNSi sai vahetatud.
Telia fiiber, Mikrotik ruuter, Asuse AP.
Kas keegi on kokku puutunud Atlantic boileri võrku ühendamise probleemiga läbi cozytouch rakenduse?
Kuidagi ei taha õnnestuda ja suppordist abi ei ole. Räägib, et meie regioonis tuleb kasutada google DNSi (8.8.8.8) ja avada tuleb port 804.
Samas NATistatud võrgust tavaolukorras väljaminev liiklus piiratud ei ole ja ma ei usu, et nad eeldavad sissetulevat portforwardi. DNSi sai vahetatud.
Telia fiiber, Mikrotik ruuter, Asuse AP.
Mind ka huvitaks see juhend. Mul varem toimetas cozytouch edukalt ja sellel kevadel suvilas uuesti seisse lükates enam boiler rakenduses online ei tulnud. Kustutasin ära ja proovisin uuesti lisada aga enam ei õnnestu. Ei tea mis nad seal vahepeal käkerdasid.
Kas keegi on kokku puutunud Atlantic boileri võrku ühendamise probleemiga läbi cozytouch rakenduse?
Kuidagi ei taha õnnestuda ja suppordist abi ei ole. Räägib, et meie regioonis tuleb kasutada google DNSi (8.8.8.8) ja avada tuleb port 804.
Samas NATistatud võrgust tavaolukorras väljaminev liiklus piiratud ei ole ja ma ei usu, et nad eeldavad sissetulevat portforwardi. DNSi sai vahetatud.
Telia fiiber, Mikrotik ruuter, Asuse AP.
Mind ka huvitaks see juhend. Mul varem toimetas cozytouch edukalt ja sellel kevadel suvilas uuesti seisse lükates enam boiler rakenduses online ei tulnud. Kustutasin ära ja proovisin uuesti lisada aga enam ei õnnestu. Ei tea mis nad seal vahepeal käkerdasid.
Mina ostsin FEBist Vertigo 80 Wif (https://www.feb.ee/et/vesi-ja-kanalisatsioon/boilerid-ja-varuosad/vertikaalsed-boilerid/atlantic/boiler-vertigo-80-65-l-max-2250w-wi-fi-hobe), seal on ka Juhendite sektsiooni alt saadaval tootja juhend ( https://www.feb.ee/tooted/PLASTOR/2203H/DOKUMENDID/juhend_1.pdf ) kuid see ei ütle errorite kohta midagi. Installid rakenduse ja proovid sealt kaudu ning kui ei õnnestu siis võtad ühendust suppordiga, kes siis vastab, et ida-euroopas justkui oleks see probleem, kasutage DNSi 8.8.8.8 ja avage port 804.
Juhendi lk 9 (või PDF lk 11).
5. Connectivity
This appliance has a Wi-Fi function which allows it to be activated or programmed remotely
via your smartphone or tablet.
To enable this, the following accessories are required:
• An Internet router or hub
• The Cozytouch application, compatible with IOS and Android.
Free download from app stores
iOS version 9.0 minimum Android version 4.1 minimum
After the application is installed, ensure you have the ID and password for your Internet router or hub and open the Cozytouch application. Follow the step-by-step instructions to create your account and then pair your appliance
Kasutan börsi jälgimise funktsiooni ilma kütmise funktsioonita. Kui hind on madalam siis relee on sees, ja kõrgem, siis OFF
Spoiler
Probleem on selles, et arvestus käib ainult korra päevas kell 23:00, kui kogu ajaperioodil on börsi hind soodne nagu tavaliselt nv on, siis viimased 4 arvestus läheb kaduma. Relee on esimesed 20h sees, sest Shelly nutireleel on piirang 20 Schedule korraga. Oleks vaja, et script teeks kalkulatsiooni kaks korda ööpäevas. Kell 23:00 ja kell 11:00
Kuidas seda teha või saaks keegi aidata?
Minu script:
Spoiler
/*
This Shelly script is designed to retrieve energy market prices from Elering and
activate heating during the most cost-effective hours each day, employing various algorithms.
1. Dynamic calculation of heating time for the next day based on weather forecasts.
2. Division of heating into time periods, with activation during the cheapest hour within each period.
3. Utilization of min-max price levels to maintain the Shelly system consistently on or off.
The script executes daily after 23:00 to establish heating timeslots for the following day.
created by Leivo Sepp, 25.12.2023
https://github.com/LeivoSepp/Smart-heating-management-with-Shelly
*/
// timePeriod: duration of each time period in hours, (0 -> only min-max price used, 24 -> period is one day).
// heatingTime: duration of heating in hours during each designated period.
// isFcstUsed: true/false - Using weather forecast to calculate heating duration.
/****** HEATING MODES, YOU CAN MODIFY OR CREATE YOUR OWN ******/
/* Heating schedulers with forecast */
let HEAT24H_FCST = { timePeriod: 24, heatingTime: 0, isFcstUsed: true };
let HEAT12H_FCST = { timePeriod: 12, heatingTime: 24, isFcstUsed: true };
let HEAT6H_FCST = { timePeriod: 6, heatingTime: 0, isFcstUsed: true };
/* 24h heating schedulers */
let HEAT24H_20H = { timePeriod: 24, heatingTime: 20, isFcstUsed: false };
let HEAT24H_12H = { timePeriod: 24, heatingTime: 12, isFcstUsed: false };
let HEAT24H_10H = { timePeriod: 24, heatingTime: 10, isFcstUsed: false };
let HEAT24H_8H = { timePeriod: 24, heatingTime: 8, isFcstUsed: false };
/* 12h heating schedulers */
let HEAT12H_6H = { timePeriod: 12, heatingTime: 6, isFcstUsed: false };
let HEAT12H_4H = { timePeriod: 12, heatingTime: 4, isFcstUsed: false };
let HEAT12H_2H = { timePeriod: 12, heatingTime: 2, isFcstUsed: false };
let HEAT12H_1H = { timePeriod: 12, heatingTime: 1, isFcstUsed: false };
/* 6h heating schedulers */
let HEAT6H_2H = { timePeriod: 6, heatingTime: 2, isFcstUsed: false };
let HEAT6H_1H = { timePeriod: 6, heatingTime: 1, isFcstUsed: false };
/* 4h heating schedulers */
let HEAT4H_2H = { timePeriod: 4, heatingTime: 2, isFcstUsed: false };
let HEAT4H_1H = { timePeriod: 4, heatingTime: 1, isFcstUsed: false };
/* Use only low price component */
let HEAT_LOWPRICE = { timePeriod: 12, heatingTime: 12, isFcstUsed: false };
/****** USER SETTINGS, START MODIFICATION ******/
let s = {
heatingMode: HEAT_LOWPRICE , // HEATING MODE. Different heating modes described above.
elektrilevi: NONE , // ELEKTRILEVI transmission fee: VORK1 / VORK2 / VORK2KUU / VORK4 / NONE
// alwaysOnLowPrice: 10, // Keep heating always ON if energy price lower than this value (EUR/MWh)
alwaysOffHighPrice: 250, // Keep heating always OFF if energy price higher than this value (EUR/MWh)
isOutputInverted: false, // Configures the relay state to either normal or inverted. (inverted required by Nibe, Thermia)
relayID: 0, // Shelly relay ID
defaultTimer: 60, // Default timer duration, in minutes, for toggling the Shelly state.
country: "ee", // Estonia-ee, Finland-fi, Lithuania-lt, Latvia-lv
heatingCurve: 1, // Shifting heating curve to the left or right, check the tables below. Shift by 1 equals 1h.
powerFactor: 1, // Adjusts the heating curve to be either more flat or more aggressive (0 -> flat, 1 -> steep).
}
/****** USER SETTINGS, END OF MODIFICATION ******/
/*
Heating time dependency on heating curve and outside temperature for 24h and 12h (power factor 0.5).
/*
This is the start of the script.
Set the script to start automatically.
Set the default script library
Get old scheduler IDs from the KVS storage
*/
function start() {
setAutoStart();
setKvsScrLibr();
Shelly.call('KVS.Get', { key: "schedulerIDs" + _.sId }, function (res, err, msg, data) {
let si = [];
if (res) {
si = JSON.parse(res.value);
res = null; //to save memory
}
delSc(si);
});
}
/* set the script to sart automatically on boot */
function setAutoStart() {
if (!Shelly.getComponentConfig("script", _.sId).enable) {
Shelly.call('Script.SetConfig', { id: _.sId, config: { enable: true } },
function (res, err, msg, data) {
if (err != 0) {
print("Heating script autostart is not enabled.", msg, ". After Shelly restart, this script will not start and new heating schedules are not created.");
}
});
}
}
/* set the default script library */
function setKvsScrLibr() {
Shelly.call("KVS.set", { key: "scripts-library", value: '{"url": "https://raw.githubusercontent.com/LeivoSepp/Smart-heating-management-with-Shelly/master/manifest.json"}' });
}
/*
Before anything else delete all the old schedulers created by this script.
*/
function delSc(s) {
//logic below is a non-blocking method for RPC calls to delete all schedulers one by one
if (_.cntr < 6 - _.rpcCl) {
for (let i = 0; i < _.rpcCl && i < s.length; i++) {
let id = s.splice(0, 1)[0];
_.cntr++;
Shelly.call("Schedule.Delete", { id: id },
function (res, err, msg, data) {
if (err !== 0) {
print(_.pId, "Schedule ", data.id, " delete FAILED.");
}
else {
print(_.pId, "Schedule ", data.id, " delete SUCCEEDED.");
}
_.cntr--;
},
{ id: id }
);
}
}
//if there are more calls in the queue
if (s.length > 0) {
Timer.set(
1000, //the delay
false,
function () {
delSc(s);
});
}
else {
main(); //start the main logic
}
}
/**
This is the main script where all the logic starts.
This one is called after all the old schedulers are deleted.
*/
function main() {
//wait until all the schedulers are deleted
if (_.cntr !== 0) {
Timer.set(
1000,
false,
function () {
main();
});
return;
}
//all old schedulers are now deleted, start the main flow
//find Shelly timezone
let shEpochUtc = Shelly.getComponentStatus("sys").unixtime;
let shDt = new Date(shEpochUtc * 1000);
let shHr = shDt.getHours();
let shUtcHr = shDt.toISOString().slice(11, 13);
let tz = shHr - shUtcHr;
if (tz > 12) { tz -= 24; }
if (tz < -12) { tz += 24; }
let tzInSec = tz * 60 * 60;
// After 23:00 tomorrow's energy prices are used
// before 23:00 today's energy prices are used.
let addDays = shHr >= 23 ? 0 : -1;
_.heatTime = s.heatingMode.heatingTime;
//if weather forecast used for heating hours
s.heatingMode.isFcstUsed ? getForecast() : getElering();
}
/**
Get Open-Meteo min and max "feels like" temperatures
*/
function getForecast() {
let lat = JSON.stringify(Shelly.getComponentConfig("sys").location.lat);
let lon = JSON.stringify(Shelly.getComponentConfig("sys").location.lon);
_.omUrl = _.openMeteo + "&latitude=" + lat + "&longitude=" + lon;
print(_.pId, "Get forecast from: ", _.omUrl)
try {
Shelly.call("HTTP.GET", { url: _.omUrl, timeout: 5, ssl_ca: "*" }, fcstCalc);
}
catch (error) {
print(_.pId, "Oh no, OpenMeteo ", error);
print(_.pId, "Get forecast failed, checking again in ", _.loopFreq, " seconds.");
_.loopRunning = false;
}
}
/* Calculate heating hours */
function fcstCalc(res, err, msg) {
try {
if (err != 0 || res === null || res.code != 200 || JSON.parse(res.body)["error"]) {
print(_.pId, "Get forecast failed, checking again in ", _.loopFreq, " seconds.");
_.loopRunning = false;
}
else {
let jsonFcst = JSON.parse(res.body); //open-meteo json response
let aTemp = jsonFcst["hourly"]["apparent_temperature"]; //get 6h, 12h or 24h temperatures
let sumFcst = 0;
for (let i = 0; i < aTemp.length; i++) {
sumFcst += aTemp[i];
}
//clear memory
aTemp = null;
res = null;
jsonFcst = null;
let tempFcst = Math.ceil(sumFcst / s.heatingMode.timePeriod); //AVG and round temperature up
_.tsFcst = epoch(); //store the timestamp into memory
print(_.pId, "We got weather forecast from Open Meteo at ", new Date().toString());
// calculating heating hours
let startTemp = 16;
let fcstHeatTime = ((startTemp - tempFcst) * (s.powerFactor - 1) + (startTemp - tempFcst + s.heatingCurve - 2));
fcstHeatTime = fcstHeatTime < 0 || tempFcst > startTemp ? 0 : fcstHeatTime; //heating time can't be negative
_.heatTime = Math.floor(fcstHeatTime / _.ctPeriods); //divide with periods and round-down heating duration
_.heatTime = _.heatTime > s.heatingMode.timePeriod ? s.heatingMode.timePeriod : _.heatTime; //heating time can't be more than period
print(_.pId, "Temperture forecast width windchill is ", tempFcst, " °C, and heating enabled for ", _.heatTime, " hours.");
//if heating is based only on the alwaysOnMaxPrice and alwaysOffMinPrice
if (s.heatingMode.timePeriod <= 0) {
for (let a = 0; a < eleringPrices.length; a++) {
if (eleringPrices[a][1] < s.alwaysOnLowPrice) {
newScheds.push([new Date((eleringPrices[a][0]) * 1000).getHours(), eleringPrices[a][1], 0]);
print(_.pId, "Energy price + transfer fee " + eleringPrices[a][1] + " EUR/MWh at " + new Date((eleringPrices[a][0]) * 1000).getHours() + ":00 is less than min price and used for heating.")
}
}
if (!newScheds.length) {
print(_.pId, "No energy prices below min price level. No heating.")
}
}
//heating periods calculation
let period = [];
let sortedPeriod = [];
//the number of period when the script is executed in case of forecast used
let nmPeriod = Math.ceil((new Date().getHours() % 23 + 2) / s.heatingMode.timePeriod);
// Create an array for each heating period, sort, and push the prices
for (let i = 0; i < _.ctPeriods; i++) {
if (s.heatingMode.isFcstUsed && (i + 1) != nmPeriod) { continue; } //in case of forecast, only one period is calculated
let k = 0;
let hoursInPeriod = (i + 1) * s.heatingMode.timePeriod > 24 ? 24 : (i + 1) * s.heatingMode.timePeriod;
for (let j = i * s.heatingMode.timePeriod; j < hoursInPeriod; j++) {
period[k] = eleringPrices[j];
k++;
}
sortedPeriod = sort(period, 1); //sort by price
let heatingHours = sortedPeriod.length < _.heatTime ? sortedPeriod.length : _.heatTime; //finds max hours to heat in that period
for (let a = 0; a < sortedPeriod.length; a++) {
if ((a < heatingHours || sortedPeriod[a][1] < s.alwaysOnLowPrice) && !(sortedPeriod[a][1] > s.alwaysOffHighPrice)) {
newScheds.push([new Date((sortedPeriod[a][0]) * 1000).getHours(), sortedPeriod[a][1], i + 1]);
}
//If some hours are too expensive to use for heating, then just let user know for this
if (a < heatingHours && sortedPeriod[a][1] > s.alwaysOffHighPrice) {
print(_.pId, "Energy price + transfer fee " + sortedPeriod[a][1] + " EUR/MWh at " + new Date((sortedPeriod[a][0]) * 1000).getHours() + ":00 is more expensive than max price and not used for heating.")
}
}
}
//clearing memory
eleringPrices = null;
sortedPeriod = null;
period = null;
}
listScheds(sort(newScheds, 0));
}
/**
Get all the existing schedulers to check duplications
*/
function listScheds(newScheds) {
Shelly.call("Schedule.List", {},
function (res, err, msg, data) {
if (res === 0) {
// No existing schedulers found
createScheds([], data.s);
}
else {
// Found existing schedulers
createScheds(res.jobs, data.s);
res = null; //to save memory
}
}, { s: newScheds }
);
}
/**
Create all schedulers, the Shelly limit is 20.
*/
function createScheds(listScheds, newScheds) {
//logic below is a non-blocking method for RPC calls to create all schedulers one by one
if (_.cntr < 6 - _.rpcCl) {
for (let i = 0; i < _.rpcCl && i < newScheds.length; i++) {
let isExist = false;
let hour = newScheds[0][0];
let ctPeriod = newScheds[0][2];
let price = newScheds.splice(0, 1)[0][1]; //cut the array one-by-one
let timespec = "0 0 " + hour + " * * *";
//looping through existing schedulers
for (let k = 0; k < listScheds.length; k++) {
let t = listScheds[k].timespec;
let p = listScheds[k].calls[0].params;
//check if the scheduler exist
if (p.id === s.relayID && t.split(" ").join("") === timespec.split(" ").join("")) {
print(_.pId, "#" + ctPeriod, "Skipping scheduler at: ", hour + ":00 for relay:", s.relayID, " as it is already exist.");
isExist = true;
break;
}
}
// only create unique schedulers
if (!isExist) {
_.cntr++;
Shelly.call("Schedule.Create", {
"id": 0, "enable": true, "timespec": timespec,
"calls": [{
"method": "Switch.Set",
"params": {
"id": s.relayID,
"on": !s.isOutputInverted
}
}]
},
function (res, err, msg, data) {
if (err !== 0) {
print(_.pId, "#" + data.ctPeriod, "Scheduler at: ", data.hour + ":00 price: ", data.price, " EUR/MWh (energy price + transmission). FAILED, 20 schedulers is the Shelly limit.");
}
else {
print(_.pId, "#" + data.ctPeriod, "Scheduler starts at: ", data.hour + ":00 price: ", data.price, " EUR/MWh (energy price + transmission). ID:", res.id, " SUCCESS");
_.schedId.push(res.id); //create an array of scheduleIDs
}
_.cntr--;
},
{ hour: hour, price: price, ctPeriod: ctPeriod }
);
}
}
}
//if there are more calls in the queue
if (newScheds.length > 0) {
Timer.set(
1000, //the delay
false,
function () {
createScheds(listScheds, newScheds);
});
}
else {
setKVS();
}
}
/**
Storing the scheduler IDs in KVS to not loose them in case of power outage
*/
function setKVS() {
//wait until all the schedulerIDs are collected
if (_.cntr !== 0) {
Timer.set(
1000,
false,
function () {
setKVS();
});
return;
}
//schedulers are created, store the IDs to KVS
Shelly.call("KVS.set", { key: "version" + _.sId, value: _.version });
Shelly.call("KVS.set", { key: "timestamp" + _.sId, value: new Date().toString() });
Shelly.call("KVS.set", { key: "schedulerIDs" + _.sId, value: JSON.stringify(_.schedId) },
function () {
print(_.pId, "Script v", _.version, " created all the schedules, next heating calculation at", nextChkHr() + ":00.");
_.loopRunning = false;
});
_.schedId = [];
}
/**
Set countdown timer to flip Shelly status
*/
function setShellyTimer(isOutInv, timerMin) {
let is_on = isOutInv ? "on" : "off";
let timerSec = timerMin * 60; //time in seconds
print(_.pId, "Set Shelly auto " + is_on + " timer for ", timerMin, " minutes.");
Shelly.call("Switch.SetConfig", {
"id": 0,
config: {
"name": "Switch0",
"auto_on": isOutInv,
"auto_on_delay": timerSec,
"auto_off": !isOutInv,
"auto_off_delay": timerSec
}
});
}
// Shelly doesnt support Javascript sort function so this basic math algorithm will do the sorting job
function sort(array, sortby) {
// Sorting array from smallest to larger
let i, j, k, min, max, min_indx, max_indx, tmp;
j = array.length - 1;
for (i = 0; i < j; i++) {
min = max = array[i][sortby];
min_indx = max_indx = i;
for (k = i; k <= j; k++) {
if (array[k][sortby] > max) {
max = array[k][sortby];
max_indx = k;
}
else if (array[k][sortby] < min) {
min = array[k][sortby];
min_indx = k;
}
}
tmp = array[i];
array.splice(i, 1, array[min_indx]);
array.splice(min_indx, 1, tmp);
function epoch() {
return Math.floor(Date.now() / 1000.0);
}
/* Next hour for heating calculation */
function nextChkHr() {
let chkT = s.heatingMode.isFcstUsed ? s.heatingMode.timePeriod : 24;
let hr = (Math.ceil((new Date().getHours() + 1) / chkT) * chkT) - 1;
return hr > 23 ? 23 : hr;
}
/**
Getting prices or forecast for today if
* prices or forecast have never been fetched OR
* prices or forecast are not from today or yesterday OR
* prices or forecast needs regular update
*/
function isUpdtReq(ts) {
let nextHour = nextChkHr();
let now = new Date();
let yestDt = new Date(now - _.dayInSec * 1000);
let tsDt = new Date(ts * 1000);
let isToday = tsDt.getFullYear() === now.getFullYear() && tsDt.getMonth() === now.getMonth() && tsDt.getDate() === now.getDate();
let isYesterday = tsDt.getFullYear() === yestDt.getFullYear() && tsDt.getMonth() === yestDt.getMonth() && tsDt.getDate() === yestDt.getDate();
let isTsAfterChkT = new Date(ts * 1000).getHours() === nextHour;
let isChkT = now.getHours() === nextHour;
return (isChkT && !isTsAfterChkT) || !(isToday || isYesterday);
}
/**
This loop runs in every xx seconds
*/
function loop() {
if (_.loopRunning) {
return;
}
_.loopRunning = true;
if (isUpdtReq(_.tsPrices) || (s.heatingMode.isFcstUsed && isUpdtReq(_.tsFcst))) {
start();
} else {
_.loopRunning = false;
}
}
Timer.set(_.loopFreq * 1000, true, loop);
/* --------- WATCHDOG START --------- */
/** This is the watchdog script code */
let watchdog = 'let _={sId:0,mc:3,ct:0};function start(e){Shelly.call("KVS.Get",{key:"schedulerIDs"+e},(function(e,l,t,c){if(e){let l=[];l=JSON.parse(e.value),e=null,delSc(l,c.sId)}}),{sId:e})}function delSc(e,l){if(_.ct<6-_.mc)for(let t=0;t<_.mc&&t<e.length;t++){let t=e.splice(0,1)[0];_.ct++,Shelly.call("Schedule.Delete",{id:t},(function(e,t,c,i){0!==t?print("Script #"+l,"schedule ",i.id," del FAIL."):print("Script #"+l,"schedule ",i.id," del OK."),_.ct--}),{id:t})}e.length>0?Timer.set(1e3,!1,(function(){delSc(e,l)})):delKVS(l)}function delKVS(e){0===_.ct?(Shelly.call("KVS.Delete",{key:"schedulerIDs"+e}),Shelly.call("KVS.Delete",{key:"version"+e}),Shelly.call("KVS.Delete",{key:"timestamp"+e}),print("Heating script #"+e,"is clean")):Timer.set(1e3,!1,(function(){delKVS(e)}))}Shelly.addStatusHandler((function(e){"script"!==e.name||e.delta.running||(_.sId=e.delta.id,start(_.sId))}));'
/** find watchdog script ID */
function createWatchdog() {
Shelly.call('Script.List', null, function (res, err, msg, data) {
if (res) {
let wdId = 0;
let s = res.scripts;
res = null;
for (let i = 0; i < s.length; i++) {
if (s[i].name === "watchdog") {
wdId = s[i].id;
break;
}
}
createScript(wdId);
}
});
}
/** Create a new script (id==0) or stop the existing script (id<>0) if watchdog found. */
function createScript(id) {
if (id === 0) {
Shelly.call('Script.Create', { name: "watchdog" }, putCode, { id: id });
}
else {
Shelly.call('Script.Stop', { id: id }, putCode, { id: id });
}
}
/** Add code to the watchdog script */
function putCode(res, err, msg, data) {
if (err === 0) {
print(_.pId, "Watchdog script has been created.");
let scId = res.id > 0 ? res.id : data.id;
Shelly.call('Script.PutCode', { id: scId, code: watchdog }, startScript, { id: scId });
}
else {
print(_.pId, "Watchdog script creation failed.", msg, ". Schedules are not deleted if heating script is stopped or deleted.");
}
}
/** Enable autostart and start the watchdog script */
function startScript(res, err, msg, data) {
if (err === 0) {
print(_.pId, "Insert code to watchdog script completed.");
if (!Shelly.getComponentConfig("script", data.id).enable) {
Shelly.call('Script.SetConfig', { id: data.id, config: { enable: true } },
function (res, err, msg, data) {
if (err != 0) {
print(_.pId, "Watchdog script autostart is not enabled.", msg, ". After Shelly restart, this script will not start and schedules are not deleted if heating script is stopped or deleted.");
}
});
}
Shelly.call('Script.Start', { id: data.id }, function (res, err, msg, data) {
if (err === 0) {
print(_.pId, "Watchdog script started succesfully.");
}
else {
print(_.pId, "Watchdog script is not started.", msg, ". Schedules are not deleted if heating script is stopped or deleted.");
}
});
}
else {
print(_.pId, "Adding code to the script is failed.", msg, ". Schedules are not deleted if heating script is stopped or deleted.")
}
}
/* --------- WATCHDOG END --------- */
Tere. Kuna paigaldasin remondi käigus juba sonoffi niiskusandurid , siis mõtlesin , et ka põrandaküte võiks olla samas süsteemis ja nutikuse võimalusega. Kuna Sonoffil paistab, et neid termostaate seinale peaaegu pole(erinevalt tuyast). Siis mõtlesin kas Sonoff EliTite 316D temp. Controller+Sonoff WTS01 Veekindel Temperatuurisensor saaksid elektrikütte juhtimisega hakkama? Vannitoas kaabel ja muudes ruumides põrandal küttekile _________________ www.ohutuspartner.ee Teie partner ohutusalal
viimati muutis Level 14.08.2024 23:39:42, muudetud 1 kord
Puhtalt küll minu mõtlemine aga küttesüsteemid võiks olla võimalikult standardsed, et vajadusel saab kontrollerit igal hetkel vahetada. Igasugu spets nutijunnid ei pruugi pooltki põranda elueast vastu pidada. Standardiga on see teema, et sinna leidub iga hetk nii vanemat kui uuemat kraami.
Ehk siis ikka NTC 10k põrandasse ja seinale toos. Ise kasutan Heatit Z-TRM3, enne seda oli tavaline Heber HT115. Kõige enam hoiaks eemale igasugu pilves istuvatest jubinatest.
Jaa see andur on küll väga "standard", iga suvaline termostaat oskab endale sellise külge võtta
Teisest küljest kui kõik kilpi mahub ja on mahavõetav ning asendatav mitte nutika süsteemiga, siis pole suuremat vahet. Samas jälle kilpi tubasteks termostaatideks ei konverteeri.
sa ei või postitada uusi teemasid siia foorumisse sa ei või vastata selle foorumi teemadele sa ei või muuta oma postitusi selles foorumis sa ei või kustutada oma postitusi selles foorumis sa ei või vastata küsitlustele selles foorumis sa ei saa lisada manuseid selles foorumis sa võid manuseid alla laadida selles foorumis
Hinnavaatlus ei vastuta foorumis tehtud postituste eest.