From f7bfa78835fac47165b85f46fa3fdcdbd95cbe5b Mon Sep 17 00:00:00 2001 From: root Date: Fri, 3 Apr 2026 21:34:23 +1300 Subject: [PATCH] more esphome devices and fixes --- .../integrations/3_day_blinds/dark_icon.png | Bin 0 -> 35668 bytes .../brands/integrations/abode/dark_icon.png | Bin 0 -> 9011 bytes .../brands/integrations/acaia/dark_icon.png | Bin 0 -> 15579 bytes .../integrations/accuweather/dark_icon.png | Bin 0 -> 6245 bytes .../brands/integrations/acomax/dark_icon.png | Bin 0 -> 15439 bytes .../integrations/actron_air/dark_icon.png | Bin 0 -> 2153 bytes .cache/brands/integrations/adax/dark_icon.png | Bin 0 -> 5268 bytes .../brands/integrations/adguard/dark_icon.png | Bin 0 -> 6544 bytes .../integrations/advantage_air/dark_icon.png | Bin 0 -> 6513 bytes .../brands/integrations/aemet/dark_icon.png | Bin 0 -> 9267 bytes .../integrations/aep_ohio/dark_icon.png | Bin 0 -> 11468 bytes .../integrations/aep_texas/dark_icon.png | Bin 0 -> 10292 bytes .../integrations/aftership/dark_icon.png | Bin 0 -> 4255 bytes .../integrations/agent_dvr/dark_icon.png | Bin 0 -> 16313 bytes .../integrations/airgradient/dark_icon.png | Bin 0 -> 3169 bytes .../brands/integrations/airly/dark_icon.png | Bin 0 -> 13133 bytes .../brands/integrations/airnow/dark_icon.png | Bin 0 -> 6277 bytes .../brands/integrations/airobot/dark_icon.png | Bin 0 -> 11953 bytes .../integrations/airpatrol/dark_icon.png | Bin 0 -> 9958 bytes .cache/brands/integrations/airq/dark_icon.png | Bin 0 -> 8056 bytes .../integrations/airthings/dark_icon.png | Bin 0 -> 5293 bytes .../androidtv_remote/dark_icon@2x.png | Bin 0 -> 4418 bytes .../androidtv_remote/dark_logo.png | Bin 0 -> 13311 bytes .../brands/integrations/aosmith/dark_icon.png | Bin 0 -> 3769 bytes .../integrations/brel_home/dark_icon.png | Bin 0 -> 13847 bytes .../brands/integrations/directv/dark_icon.png | Bin 0 -> 21390 bytes .../brands/integrations/esphome/icon@2x.png | Bin 0 -> 3100 bytes .../fireservicerota/dark_icon.png | Bin 0 -> 12702 bytes .../integrations/forecast_solar/dark_icon.png | Bin 0 -> 9676 bytes .../brands/integrations/freebox/dark_icon.png | Bin 0 -> 3831 bytes .../integrations/freedompro/dark_icon.png | Bin 0 -> 4663 bytes .../fressnapf_tracker/dark_icon.png | Bin 0 -> 9373 bytes .cache/brands/integrations/gree/dark_icon.png | Bin 0 -> 2947 bytes .../integrations/microsoft/dark_icon.png | Bin 0 -> 1174 bytes .../brands/integrations/onewire/dark_icon.png | Bin 0 -> 12702 bytes .../brands/integrations/rachio/dark_icon.png | Bin 0 -> 7475 bytes .../brands/integrations/radarr/dark_icon.png | Bin 0 -> 13647 bytes .../rainforest_automation/dark_icon.png | Bin 0 -> 6110 bytes .../integrations/rainmachine/dark_icon.png | Bin 0 -> 5617 bytes .../integrations/raspberry_pi/dark_icon.png | Bin 0 -> 18002 bytes .cache/brands/integrations/rdw/dark_icon.png | Bin 0 -> 5277 bytes .../recollect_waste/dark_icon.png | Bin 0 -> 3231 bytes .../integrations/redgtech/dark_icon.png | Bin 0 -> 4086 bytes .../brands/integrations/refoss/dark_icon.png | Bin 0 -> 10238 bytes .../brands/integrations/rehlko/dark_icon.png | Bin 0 -> 4525 bytes .../remote_calendar/dark_icon.png | Bin 0 -> 1956 bytes .../brands/integrations/renault/dark_icon.png | Bin 0 -> 5043 bytes .../brands/integrations/renson/dark_icon.png | Bin 0 -> 10883 bytes .../brands/integrations/reolink/dark_logo.png | Bin 0 -> 26352 bytes .cache/brands/integrations/reolink/icon.png | Bin 0 -> 2900 bytes .../brands/integrations/rexel/dark_icon.png | Bin 0 -> 19766 bytes .../brands/integrations/rhasspy/dark_icon.png | Bin 0 -> 7215 bytes .cache/brands/integrations/roth/dark_icon.png | Bin 0 -> 612 bytes .../integrations/russound/dark_icon.png | Bin 0 -> 2951 bytes .../brands/integrations/ruuvi/dark_icon.png | Bin 0 -> 3337 bytes .../brands/integrations/script/dark_icon.png | Bin 0 -> 1805 bytes .cache/brands/integrations/script/icon.png | Bin 0 -> 1805 bytes .../integrations/seventeentrack/dark_icon.png | Bin 0 -> 4868 bytes .../integrations/solaredge/dark_icon.png | Bin 0 -> 5692 bytes .cache/brands/integrations/tasmota/logo.png | Bin 0 -> 10215 bytes .../integrations/trafikverket/dark_icon.png | Bin 0 -> 7744 bytes .../waste_collection_schedule/dark_icon.png | Bin 0 -> 10835 bytes .ha_run.lock | 2 +- esphome/esp-entrancebathrmlights.yaml | 18 +- esphome/esp-entranceoutsideledlights.yaml | 392 ++++++-- esphome/esp-garagebtproxy.yaml | 157 ++-- esphome/esp-garageentrylights.yaml | 204 +++-- esphome/esp-garageextcornerlight.yaml | 205 +++-- esphome/esp-gasheater.yaml | 864 ++++++++++++------ esphome/esp-laundrydrypow.yaml | 233 +++-- esphome/esp-laundryenv.yaml | 168 ++-- esphome/esp-laundrylights.yaml | 204 +++-- esphome/esp-laundryplugpow.yaml | 233 +++-- esphome/esp-laundrywashpow.yaml | 235 +++-- esphome/esp-leafbattery.yaml | 181 ++-- esphome/esp-loungebookshelfleds.yaml | 354 +++---- ...tleds2.yaml => esp-loungecabinetleds.yaml} | 330 ++++--- esphome/esp-loungeenvironment.yaml | 189 +++- esphome/esp-loungemiddleswitch.yaml | 179 ++-- esphome/esp-loungenorthswitch.yaml | 197 ++-- esphome/esp-loungepelmetleds2.yaml | 501 +++++----- esphome/esp-loungesouthleftswitch.yaml | 176 ++-- esphome/esp-loungesouthrightswitch.yaml | 172 ++-- esphome/esp-loungewestswitch.yaml | 183 ++-- esphome/esp-mainbathroomlights.yaml | 148 +-- esphome/esp-maindishwasherpower.yaml | 167 ++-- esphome/esp-mainhallwaylights1.yaml | 187 ++++ esphome/esp-mainhallwaylights2.yaml | 193 ++++ esphome/esp-mainkitchenlights.yaml | 187 ++-- esphome/esp-masterbathtowelrail.yaml | 37 +- esphome/esp-officeduallights.yaml | 286 +++--- ...evels.yaml => battery_levels.yaml.oldtemp} | 0 packages/entrance_spot_person_detection.yaml | 177 ++++ ...yaml => gas_heater_operation.yaml.old2026} | 0 packages/openhasp_lounge1_wallplate.yaml | 536 +++++++++-- packages/presense_sense.yaml.old | 98 -- 96 files changed, 4870 insertions(+), 2523 deletions(-) create mode 100644 .cache/brands/integrations/3_day_blinds/dark_icon.png create mode 100644 .cache/brands/integrations/abode/dark_icon.png create mode 100644 .cache/brands/integrations/acaia/dark_icon.png create mode 100644 .cache/brands/integrations/accuweather/dark_icon.png create mode 100644 .cache/brands/integrations/acomax/dark_icon.png create mode 100644 .cache/brands/integrations/actron_air/dark_icon.png create mode 100644 .cache/brands/integrations/adax/dark_icon.png create mode 100644 .cache/brands/integrations/adguard/dark_icon.png create mode 100644 .cache/brands/integrations/advantage_air/dark_icon.png create mode 100644 .cache/brands/integrations/aemet/dark_icon.png create mode 100644 .cache/brands/integrations/aep_ohio/dark_icon.png create mode 100644 .cache/brands/integrations/aep_texas/dark_icon.png create mode 100644 .cache/brands/integrations/aftership/dark_icon.png create mode 100644 .cache/brands/integrations/agent_dvr/dark_icon.png create mode 100644 .cache/brands/integrations/airgradient/dark_icon.png create mode 100644 .cache/brands/integrations/airly/dark_icon.png create mode 100644 .cache/brands/integrations/airnow/dark_icon.png create mode 100644 .cache/brands/integrations/airobot/dark_icon.png create mode 100644 .cache/brands/integrations/airpatrol/dark_icon.png create mode 100644 .cache/brands/integrations/airq/dark_icon.png create mode 100644 .cache/brands/integrations/airthings/dark_icon.png create mode 100644 .cache/brands/integrations/androidtv_remote/dark_icon@2x.png create mode 100644 .cache/brands/integrations/androidtv_remote/dark_logo.png create mode 100644 .cache/brands/integrations/aosmith/dark_icon.png create mode 100644 .cache/brands/integrations/brel_home/dark_icon.png create mode 100644 .cache/brands/integrations/directv/dark_icon.png create mode 100644 .cache/brands/integrations/esphome/icon@2x.png create mode 100644 .cache/brands/integrations/fireservicerota/dark_icon.png create mode 100644 .cache/brands/integrations/forecast_solar/dark_icon.png create mode 100644 .cache/brands/integrations/freebox/dark_icon.png create mode 100644 .cache/brands/integrations/freedompro/dark_icon.png create mode 100644 .cache/brands/integrations/fressnapf_tracker/dark_icon.png create mode 100644 .cache/brands/integrations/gree/dark_icon.png create mode 100644 .cache/brands/integrations/microsoft/dark_icon.png create mode 100644 .cache/brands/integrations/onewire/dark_icon.png create mode 100644 .cache/brands/integrations/rachio/dark_icon.png create mode 100644 .cache/brands/integrations/radarr/dark_icon.png create mode 100644 .cache/brands/integrations/rainforest_automation/dark_icon.png create mode 100644 .cache/brands/integrations/rainmachine/dark_icon.png create mode 100644 .cache/brands/integrations/raspberry_pi/dark_icon.png create mode 100644 .cache/brands/integrations/rdw/dark_icon.png create mode 100644 .cache/brands/integrations/recollect_waste/dark_icon.png create mode 100644 .cache/brands/integrations/redgtech/dark_icon.png create mode 100644 .cache/brands/integrations/refoss/dark_icon.png create mode 100644 .cache/brands/integrations/rehlko/dark_icon.png create mode 100644 .cache/brands/integrations/remote_calendar/dark_icon.png create mode 100644 .cache/brands/integrations/renault/dark_icon.png create mode 100644 .cache/brands/integrations/renson/dark_icon.png create mode 100644 .cache/brands/integrations/reolink/dark_logo.png create mode 100644 .cache/brands/integrations/reolink/icon.png create mode 100644 .cache/brands/integrations/rexel/dark_icon.png create mode 100644 .cache/brands/integrations/rhasspy/dark_icon.png create mode 100644 .cache/brands/integrations/roth/dark_icon.png create mode 100644 .cache/brands/integrations/russound/dark_icon.png create mode 100644 .cache/brands/integrations/ruuvi/dark_icon.png create mode 100644 .cache/brands/integrations/script/dark_icon.png create mode 100644 .cache/brands/integrations/script/icon.png create mode 100644 .cache/brands/integrations/seventeentrack/dark_icon.png create mode 100644 .cache/brands/integrations/solaredge/dark_icon.png create mode 100644 .cache/brands/integrations/tasmota/logo.png create mode 100644 .cache/brands/integrations/trafikverket/dark_icon.png create mode 100644 .cache/brands/integrations/waste_collection_schedule/dark_icon.png rename esphome/{esp-loungecabinetleds2.yaml => esp-loungecabinetleds.yaml} (73%) create mode 100644 esphome/esp-mainhallwaylights1.yaml create mode 100644 esphome/esp-mainhallwaylights2.yaml rename packages/{battery_levels.yaml => battery_levels.yaml.oldtemp} (100%) create mode 100644 packages/entrance_spot_person_detection.yaml rename packages/{gas_heater_operation.yaml => gas_heater_operation.yaml.old2026} (100%) delete mode 100644 packages/presense_sense.yaml.old diff --git a/.cache/brands/integrations/3_day_blinds/dark_icon.png b/.cache/brands/integrations/3_day_blinds/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d465b4084768d4afbd1f6a6a6691d27956931f2c GIT binary patch literal 35668 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 z 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 QrvLx|07*qoM6N<$f@`NFK>z>% literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/abode/dark_icon.png b/.cache/brands/integrations/abode/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ad08a47253ad05e779e257c69303d021a236b614 GIT binary patch literal 9011 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 AA^-pY literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/accuweather/dark_icon.png b/.cache/brands/integrations/accuweather/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a3c7dc12c649a8629bdd17e33efbd747881faa51 GIT binary patch literal 6245 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/adax/dark_icon.png b/.cache/brands/integrations/adax/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f013ea670fddf6433b2b2a5a80be8c3bd2397f88 GIT binary patch literal 5268 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/adguard/dark_icon.png b/.cache/brands/integrations/adguard/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0fed052b4fe3512fbe60c19681ff51543eb1a5ce GIT binary patch literal 6544 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/aemet/dark_icon.png b/.cache/brands/integrations/aemet/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c73f97c1efffc9cb77cc8f6ea2720ca4399904bd GIT binary patch literal 9267 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 OfR>s*wDPHK89vqh71Qtku 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/airgradient/dark_icon.png b/.cache/brands/integrations/airgradient/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..175998b560231dbaf78f6ec6aa46683339fc1979 GIT binary patch literal 3169 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/airnow/dark_icon.png b/.cache/brands/integrations/airnow/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2e9cb470cabb20b1e543253699b2b5e7df9c1145 GIT binary patch literal 6277 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/airobot/dark_icon.png b/.cache/brands/integrations/airobot/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ef572409c842425df427edb034a3af38e40dd3c9 GIT binary patch literal 11953 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/airpatrol/dark_icon.png b/.cache/brands/integrations/airpatrol/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c21ed50a18810b133000c82b5e3c1f1ac364aecf GIT binary patch literal 9958 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 ZAw{HQiEKr- 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/androidtv_remote/dark_icon@2x.png b/.cache/brands/integrations/androidtv_remote/dark_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..05c22bed33895072f50b69f7f7cb5f59e268e7f2 GIT binary patch literal 4418 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 Ae*gdg literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/aosmith/dark_icon.png b/.cache/brands/integrations/aosmith/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..30920c2879b64694123666a6cbb2eb57633df000 GIT binary patch literal 3769 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 Uf##^eVCvs!W@KepqmPgO4;o5ms{jB1 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/brel_home/dark_icon.png b/.cache/brands/integrations/brel_home/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..df2639f2190a373e06a661b432836164e1cfabde GIT binary patch literal 13847 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

I&p>3Qs=f*N z$tTG_HWeusnQP(`Y1Kk!!U%1wL;gUTo2Y%UqBJPtASlKQ^s%2kFjr7aaJuDW&RVAi z<{pnZdd0O2tw&7Z#-V~n$lt6wHeG#rQ=t!T)IVVdW+pufwb;`da-uIQo@2RUVCUjA zUo+XN=syFWN%zymgWZf!30aP6nCvvPCK%^32;sjNL$#gcnJUMQ`$D?8JR|VI06$e% zU;t~zXea)q6P}nAo*s{|j;BdRkXcGF-4Myo!mC9)>7`IYWT$(X3Mec-!g@k8x-M>k zOm`JH*NR7VIrYQ{a5)n0R#Yl!Y3h)bM5H_PQ2RJ5ce^zD?1UJRTDrE( zu$Fg>JR2}`#r+?Dvfcc3TVSzX!*0YNcC@0&pBO!l=wfExCy;nLs7o@Lwk4|%3AwR~V zWca>zDsXWYd#l+P4+i*gyO8+I_KAtly^NIzk5FiT6ZD9$aQnb?<3&;4?i~Mm<+xQ`;>4R!h9m3P!nJQHWSJ0 zpW)nkR=ueNH%NMuZNEr>mQ66*05xQZc|PMeW=}t)l%zR4s1u^ijAqyrZ0^lXr!!kY)W6u2(&52$2cd( zNftrWc*L(5;Dx37mxq>0xBl;+YYtz{oQu zsAl&b@ni>u?wg}WalH!^P80G$z&58B*D<)l{qMeaW2z-hornZ@4u{!^X$kudw2*kz zyUn`40@u^SVdu<4XbGfyy&xxja>Cr0G!94-5yZE>Lq7PM_maz{Q+7==1oEi{Xc|U| zn%v}M=A9pXc>z4J?+x-f-7wENG$;ojZ_JN!eLLm4_jtzXp6~?iMxyKm6@v*t;_V~f zbtg&cTIt}2r`>_KgXg$jVnY~X9@DBon8IC--g#mM?JPY9EUko%L+3%D5n<=_;Cc)6 z`2lf0upH_<3BAPNe?Gf;-8--!$wE(CxG}+{Y_x+HhavF}%y1=rn!a={7{K&AJx!et zx5LI3Nyv@~`67so_Hh5mcSu&VhNqe5xKVR*(Bvp+qmrt_U~I7fhVoW^BvS5XCz+U$ z8I*iCs*!orJVU{a>+CKP5Z&mMSIt3^NIyg8$@vRQ-A_8}u2nYRAlq_g*0JOF z*rrfz=X3>zRLEyW#nCNP=8?io$#BSzaj0k9kdWW>{lj{-DBk|&TeI={d!e9#nih0$ zgV>sxDjFpyAFY+34xDwbOQ2y zcvaG7NqIYl=!u%_DK~pAXWksehRe2g1jQTfFa^3<+Pu3-$B7{Qb!_zXO)Oq4y#4hz zyZfSQkBRPf-2xnhq-!s{Gyc9zOlT*J{oH9x)c~D7TS(j_$fq0L9npL7nbcQ1o0*a> zEJ`s>1hC_jUDCZWlzEe4BeHtjyP_Ts&v21QGBCpm>E=6zQgii+{DfdwXJ$n17fz3~ zm>j{|hrglv;DGet>iROAwb2oh2Q|~`+^F6XWKfZt72mx&dEJhY1xRB~M}rgeFe`2r zHaq0Uuanq9>4MYOo^@uixaL?SG?97tcowkqP*I8nn7|Y3S?H>f9bDD1$>*eqSQs@X z)jOJa9gCR-+wu0{uiqGTQ+qNGQ-NpunHsvsi8OW*jw*Z*bw43)bVmfd3qCPt>DrtO zZeO!A-fV&`$iViq5ewuCgR}3D{5_99)7T(CAwg6#>tg#?eDJ%tQ^?P>R@n&%XNWieH!=~6aY6v0XCC1}i4u1Em|CxR6NIEG z&OO~4&0~Wb9V?QNgkT2NVhb5% zmgBKtY9dcOWtb}AoqI9n4m>joMZxQkKZ1@pLSM{Oc+hOLr2BqoD?%J@`^4w83{wtg z+kWUY$_$jX?uNUAMS6rg&HlZX>k9y=#n6 z6PzpElNCbfjSR#GCvpczaB>sPWPMXsUm1%U-Q-08K~GVNND*|{YG_zfGJ02e*%uSd zNXylb0k@g#p0R!LQSqTx$h-gLS0s@wI6(DLJQBfAM>0cATTZOGbaRfI;}s%&k54P9 zPD3{7(@5X{%$z*^7Uf0qu$YLo)Gi7Ovqe9y108#*v!ow+CcaKw7`o*wqa*AR{O^huD-=g+q5nzcVoaXpGOuQ9Rc0O>!fc@c>B{YG?qzjWkSF+rx=Feiq4q#DwHI(8WM>x=9JgI5>RBj!muF!J2j6NNsJA*9}k$GTYta$z7X6bBBEHbiXGq z^cmWKxWE6IvYL^207}h_Rsv*Ctm+Y*U2AeimwnKYtFuBT52nJ}0D^MhaMzX)}x3R~i$#*lkvlONb5KMBrwXNqe2v4*6UZEjuoV z`}?1M`d_-X>ci%}f)sBQKyqat*^`>g+yE0uu9YMiVxEwlMsFh+ZUthY_kN#C0% zH~2~QLUx`uNHS7)9o z&K{bTj0Hi)Ayc*SfLWHT{s8tH&oPZ2>hrPK0iHGh^o*kRB_f}xOR%6?@P%T<{U#1& z`n-#A<0XFx8fyUa867R%S)KGR)vX>ppay>~E#1{T=%*ld>z0ShuW0q^DmHMxeI6mDLTquI+S)1#NN@^qw{B9#AaxlrB z{i2W$p(+PQU}%tOyJChnnD5uvH^HSJ`vsVW1-nhhl*W5b=pIDhBCq=iscz}-h1Q&E zdjzwwHp-i)hZ^05T4|bC-iiy|Yhro-5BK-}&jc~sd&(2Zj?fp(u^N`_YVJ@WQfUm` zj6FRr=U>~mg8DoW7pr;;%F591%Mr_)6{CC#38gSS8NNyHR?Z&?)yw}fA4>py6<#93Cv;k&9#%ZLOvufQjEA4KcO>97eG{FApPS~ z%Q_N$o0-0D4D&uUs9gbl1=ALY4*6ip^e%|Z(CS9OetdTcYlwTA3m^6{RKxPhQHd)# z-~u}P0&(bIyy`P+?@ee8A=t%{K@>fOPt;7yDRnGesJX~AKA<* zDxi-I@Q43Hp(NzxyRqMW2Aoua2JhK%2d5aJ?@oiB=o+$~HMt37D|ZMBHm{`5#F$F@ z`+D{&s3yoDzB2D#Ufb5nzlbJo(p`<9@Ofq+U6+%{VV+P1&D5j#eB zbfwWDsW{rV3@l8z+s)l$wgtSBz*ku8zvxid5E&grg#rHHzg4oxDe3E%r@n6v7>oS-3>OGpCD~Vk|rneG$4A zxN;zOM!iX}U;8Xw7+<}R&gPIGkE2bl+{21rGr)gIB7}H$yqtV0qgh;1k}C4XcwC}L zstciHC*-#plt~Bm3bLL6Vk75Zx>m<0RS6Oe@{t6`z>k8}hz3K_b1mT_XI_XCo zw~Gsw_qrbTIyzKG=`ohwJ~*3ojr;Har>p?_{1#&orMPQ0<}f~1)I-;;BI{Y}=q)EqbG zoRfGtw}(Rat{3ei@xcJ>PJn)xD;Ij95^t*Z(=JT>U9}O^5%zN1jTK|}n_o9)OToSh zY*0Gx9JD8CCi(B$bMkN+P)P!vTXxbf%xa-gS8KV)8M%}Gsx)5vGqZo^kc&Xr@BK&7 zgtz1w6gEz>D8_3&uLyr?jI+$k|E;8NDa^Qx&!Ac3+>fX>xzQnip@3f7tFz*M$Nzpj z=w(*f4~uo1^QE&ay(rC}h*R6``j(JWuwy#;fNwM`u=56x^Mg$=IU3p!uHvxI28fG95kPq*}u} zCo?@Y`x>VAbBBC;vn1J`4zTMaeZXmftb_N=X|Rd$9oLh@(YW_mk87gekE86=-^n0{ zVrPJ6ni#7>y=JtO+?+(ip0&z83O;eo9@$Mwb#FVfAi0gg=fh;7vF}0kzNx&WfA?Qqm+olOU00yo>ZskX zQ&8Hb89_iXjh?Ks5_|4fzE^%H9ZBDN=x)>0{}v^|4pdac zHC9Ds3n~g^flN_AK$Z$fSu<>cKmufA5ttXxOwXJ-XHIqQx#zw6-F)}n_wM`izyBP2 zi!(*fL=ONcE*qTO0dQpEFolGs!jvyd(1aazcU}vb6=ppMX!)(#yawQLy#9wh+UU2{ zY}f7Uke^u~qao$V=mj!*j+&k$GvzBx`LdaOnOv^^;jNlotfmX(bb*W^9AXG%M#3Q@ zH0H_Z!Xdf{sf^AaqVr`8(I7*BRAwv~G#1F{qCq->B4o=M!a-xkikcOlxoNr zB@`eX)cBF1p~(>wW%!u+qaX2w|Kfin3=JtpItPY328Q4E57+e%m%bl<^?tYnjXi2% zms-%J&TLm_wy84ORCiic+*Va$ljx)#-ZWse09^dSzs-DzZiyp;5)L8s(vC zq>6xQWk9vUw?g4lq42IyxRoN6Zz)x5DV47&lCz5BOA6(S3*~df^4VfJTC;QM(<0Qt zRblR1wgHVsV=|exwze#dur;!qgCtZVu|#})Lc;CaTrQ8t%gQPcS0ZUeB9S44(~)cRYN^(LwoV^{8p<+7_C;yJZDJV{!Vlg;ng_CDB;_mb{l zsCZ`Vu`k_2xBEbCGyUmzajP>XcD#&uICNYY8jJV25#zd9UtuaM@q||WZ5W%*`4nfE z->0xXJ>MrWtqMMSou8EVGxz?dIjv}))Wbi`quV_^G4?v-$3rRB%;t&L?PKA^{DNB7 zt*p%P>wB7Coq4U$+TSqwM#;ZRIrhMcSvhgL#$1}%qq{+_-W|c8YeBkrW0D;Hz_ibg z#(r62QfGd6Ws1jT&SZ)-s&`Ce%zmjD&61vQ`{f;;dUfyh@OO>pWAq>Hy;j?N*fDB8 zC%a%1F{@Gbl$Zy@&#!g!&`c+>4r_16#P%>ckE;hoc-1y+2iRH=F?tVi!VXiovu471 zeQrFS3Y;KtoWa(Hc2f6k6nYg{hqX|s7DUZLp>v?hR1=C3EmI!;LII1IrY9B_7}pa| z_17l){dYDxLwDl;j?*Rbr=XJOK;eW+y6SK(H6_=Ah=xig;@v-JLg_3+P00@6FGMB( zhH>SHB(Vqn0u9vWwrgM{@NG0um-|KobAdl!11a1>4IBo(HG(O?U5p@i4CWZ40?lOG zJXD~2HSr3ygQdn?H5vJaoFmwdFmtiAZd|FAb7r#(Yo<9lORzJR0n_z{UBXPo6NP*o zL|WL?zl=D@CJp$gE0XNIy)H;`dcUD~4Q^EGb<_7k2#HFDamWrc6OVz}yG4?u>TtLYX0>UZB@5QS!-Bwe#6{9~ zNR8EiYs|DGTXju#ywBSu(l~W^$lS)xx8z|fsE#`6}icBPL-=TaO;r9}+ zN>yP4MKm}_=1_=s7^t&_6;z2Y93c(U5Z?qDXE$q*0YYujf55gc;1TAu3P*|k&%iw$ zTJ?!+CFe{q*zN%a&V=T;%dN&kVqxvuzKJGQG>=) z2{mvlay|PHyk3D8V&FKZB5^HNqR%0Nn?9LoM?`>TSHi_p0E9~o2%~JN=wu!yB(p-m z60`M&7BhX;^#&bI5tsq^yO~lT84K#uhI7~|f1D5kdQ>1`hPc5p=hk|tng@k6z*#T_ zFed8mXGoO`TwnRL_l+++X*C^gp+W$5-ed{f)3$wY2M>S%Xn50#l~6b$jJcGEnvS~s zz7o4?2W~%Ui5&pq7XB3HXn5{R2ebJz`3fH-+QZgdF|OGASgC7_dthL2@PBzkx9W<(;u2j8#VxKO9*J`yJu@ zE*<8+vd*-MCY;&pNoQD2>G=^- ipP#>Ux%g3!j~SBmN=`*wknYkv1TO2gIAyNoeE(0Fl`EnE literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/fireservicerota/dark_icon.png b/.cache/brands/integrations/fireservicerota/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd0479e811a38ef190d56ba34dc4a52792d8c4e GIT binary patch literal 12702 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%0AQ81^WP(#{-*Wo#BTVC!~H3wuCzGkNwd!2d;6 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/forecast_solar/dark_icon.png b/.cache/brands/integrations/forecast_solar/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ef2d2792acf3dc0232cdb3500d8b3e5312db0312 GIT binary patch literal 9676 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 z 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 jdL(rE|HrjiJ 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 ZrVI??vhE8t(SH2_I+}(zE8zBF{{y8o@iqVe literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/fressnapf_tracker/dark_icon.png b/.cache/brands/integrations/fressnapf_tracker/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5729a7e14e685a84a74236470310259edb6a9df9 GIT binary patch literal 9373 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 XLo}%VPHI0w00000NkvXXu0mjfE#L1T literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/gree/dark_icon.png b/.cache/brands/integrations/gree/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..88c4f5dc4d73cfa9e120cad27f9a50c9ef1fcb69 GIT binary patch literal 2947 zcmZ8jc{G&$9)D)Tkc_cZ)>%w6WG6c_5i-NrUW8KCP_ie>*s_b>w^!C0iZ(QsN-KHC zR@YKVmh5ZEV3HEXeWuR6=bn4c?>yh{@B4hV=l92Rewj2|OJPANK>z@Rt*y)*0008E z5I_J1mY`}^C$PZ%NmLR5)a40nokZ~7hC5i2f!ZFKPhcNPqc~ZBLx5Vo6A3;mU=#*m z*|bc-EmQC?Dg&T3!6@b60<0^5qYNmO0rpUE@}Fjlx*wzgoyeev)edQnGtA?3ALZLRev|GJrwXlh5;n2LfCOrA|u6?PkLCKYZ008-i7oaA(V zc&QBOB4sR|c7t}s{v|^ErSMfEL)=CD!Lgd4(df3(Cr%?z-VdyOpv!&x+K(vwm%`(s zA|q3P9dEb4>*KS>Df#BO%T@~L%>ONGb-p?miN)Jm?seZJ9!Z-{L_NJ99v&{#aYS;f zoA7PZbHnzluiW;&yPUkXI)f`54SHw?sYpLeEr_^J&50@5dcD|?IKEGRu;RPcmlm733u-mhjZ9G1_$yloM^w}G_p-feN??OMM-hD_^^ zZ#jPaB1H5kgw+zUitu@EPI8QfuHvw2dGH0<@XF3{!rSELnf9&B?je>{^V|Dgduy{d z5mxk!m*3OTvfk`BUy%Vs+8Shx1;NWTdkPCEjn*5zIHP<&UK( zBXz5^synkMF6MTj%l`58Kcq|4(ynTao*rz9kaRVq=Xh=m^z5*=Y2(%v?-n+^Wj;7- zEVZ}$TcktV26xSzP7owA^#y{QyhKYbGOHdil)a=N%*B$l@8d?nIH}C_kS~Atr*qR$3^%cqRK=toT52mu5-Lp#ZgI9u|H?ZL=W_7Q=+O<_fC*qyg z)5-7V@}?05F$fB&CJT>h`xkWLagGkN@Xpr`c3gHp&}ahRINKnUc=$BJRXv`or&g9Z z2X#-Z)Q+7flz`J5q^&;J5q?|=6WRMP4LA_ZdMDW>zvqRgd_!9e&Md2v$L@ zXTs9fe{$X9WFgEAW|}>`ll(#4l^DQvE9J=#7L8kLs`W;b`#`O=WB`N zld*^}gWbZJ#dH%d39`W44*{BDAh+~V%9O7C*JzHuh>B=(}hZTeiSAZbN9-Hsv1qh!H}!~7Ek7%Rvz)X&aN^i8hg9_d7AoUb1W%Y>6` zlb51*dVTO_r;vdNPdKV1GM|NpyGhIW^y?(C(Apz_0YA){(dX(kklk8hM~bL_2(QFK3h3Qm98uba0vEef zJ7P={k>@(+IOh@IPyZwT*p?XI^L2=FYV?f>8MJ?Jt?eJ8#os3HVhwlFNHrI&L?<7q z#CiGubMTsf(vJ<-8s@QGZP(+{0vDD!Vu1v$vqOkPHIsX0Ix!S$Dh#A~$IMzN8i(a2#KdP2|H>}M?s zONbvWY#ft@6)Nb$EEShXzg8p(KXM|hE40u z#|Q#`Vzh>`@>}`s%I5F_hGhaj37(-Ic$+jv2tX_BT+0cy&?yrQSU|%y5eBxJ{D0i> zC194(aEIL@s`rpJDK!LvddY`(RdqS4BQu`K53!~8>BN+V%e5D!p1?^mnP)xj=CVH* zmlGByE%q|RBNiRyPlyejWn{Z1$|lP8X<8?mBU%qmZ8dD%PmVw!{5l}tzKnRUVb2QEc; z?j&ifgb|gS%jbLmwSW1laY+8w`vWx6*1Z>uAH6$&LHErkNpPaNNW4Z$P^-2IXD)?Ss@ok_=zVknogQ(udkEG%F71ulB{8$Y=*L;dOGr zb4wGJuz&hF7)B$9m9_*l)$~Xj(W_uy(Qok=eyZ@B^|T<-@_sPPtuvj#CoO5c9R-YWBSp93e@F|xW3z5Uw=W_~7 zjNMn#XFj7eF%dEvIyWwlcjnX1vDOmw%bLuOSlq|9YRIo*@mhCB(PEUw5GlirSk;h$ z3q4lO0YiEoo;^qAu$yt=6H2Ql;qMAd2Yfb%>qLsgdpB0EFE3eknJ?xQ+d*hb%%G8mT$m@PRsvzlwc}lwtu1WLYsp^8{|18z8ruK> literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/microsoft/dark_icon.png b/.cache/brands/integrations/microsoft/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..29b9b6242d11283c600e9e874002d5d70f64fe55 GIT binary patch literal 1174 zcmc&y{WDZi7=BTsFEx!OrHQecY5O7i(1*Sxlr8OEvW>_pHI-?GjO44an`+BUEip8i zB6cyYWp|R+-tE$~n5jmwW)f1O4>4$WwMue&@9KZ(`Qe=Bea`c|@0oLNHpSoPG|zP& z066i21H%C9klMi<2i(r8BEqqtsF3g=ENvh_2mxFGBt#;?1&D+#g-TE=fd~Q0$IO%` z(Lp8+q#i&qD$#?9@fLI5tf(>!5VhmGeij!%(Ee4U} z5#D^J2^&#Of|`Jaz!QS~(SNA{vKrvZGq`F1X%k4B;aW3fKL=SG8~=UClL%Ll!>dTt zYHURqAdNr_K$?Iw18D*B0!Ta5Z45Y$4;pqpjDHC1SlF|0aBvVEOH9hm%gZl76c?A2 zl(Hz3D-??IN@aC*jYjkEVJ*}6zHeaQ(8AC3-k|9 z?H+k65IFlUd-^d&yLSI>{}X{Bv&emJ(IBtiv8^e0us!vAZ2y)oeZBeIqmfx$O5Ynt z(~j{A=Dt?HwD#WlXx<&X|Kh8T9&c^z;}yxb`Q}M>hxz zw=DF?l3S%^+?VcY-R^Eda{0hzfAPA(iQ%f4*2_ax(SBr|a^*K2B< z@2FQ$VSM4nnw@{oQZf&z_4WqFq;~J;FcAV2jM969rPJhc-p5`hOeJyn+OCA5; dXPcS)R5#?!bZR>NdR#uR3NMHsShMF?)?eg7$Ho8v literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/onewire/dark_icon.png b/.cache/brands/integrations/onewire/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d5b7b7d32ffe1d3ba275025154be0cb712057212 GIT binary patch literal 12702 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/raspberry_pi/dark_icon.png b/.cache/brands/integrations/raspberry_pi/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2d8d0100dc7063e8aac04b39dfb7eb88fd925c8e GIT binary patch literal 18002 zcmV)OK(@b$P)dYki%h?kOGYgWJ0p zVKXApf%&GNaqzV&lY=YqD+E8_GStKMVZ9BksUV48eb65=t=*&4_^!y%B&+bfX8k|2JSKVM1Y&!S zVJJYeNd=~$15ZP?lAo>q{u+0q9Y*Yc`^Q@#+ps?%R*C6ltU~~{w-}ET@Daqy?~rZS zQP_^ch~enK!MF}j;(3#Y@B(Bz_5i}Ly+j?}hiu30#}iil=yL3Za`<5@hY=%ih?6a&2f4dLzJ>^F>(PT>A?^}5)R+1WkzG9gxvZzRr+9dJxZ`s?kHzrD zRtO_<@fyTk#wHGvhC|aOYi^`WNFOe~LEbjY`2>1P$@+L{Ix17frwr@&^*p>h#6vr+ z!(K(iHa_@&cP{CA_IoXOq`%}YijuC=^JG-?U|VIheusw!OI-Z~sXZW7GG>K~C-v^e zesT+j!p&hsFhUT7EPM%Zkah~6fPbFhV`|3Bnn&wp&13a4`-&2&+ACSY3P+2#pT%=E zIn21INY*~yAaw_($?&ic>(|ofWY3F~@u`|59Q6hc!zs7``(hZjbR^+qoR4F0f-{Gy zz9i9{g;6ppX0Xj!Jgp~G=HE~*>z`?qh?23^WvK69$)aw%&&ZRdcUH^hms+I$;51fe zzV_Z%6NZn!wxu)f#aIL(#C2yjMr7b<+=tijI$p)s5NBwonieK4$7JcO5>_-?MzE~( z^6onWP01Z4%kHX{)sNK4+9w+H=kyB-CAB+L{6c)p<)SLa>GicwHpr6Ot0a|9>)~NJ z`@}a*lGP-X%-InnAx~E=Szkvjwp6UfcaVR>lr;Momo!vnU0N*D&M)NqTYmS^u|uSj z8GqfAjk4~kMrk`f+u}MaGhL-ErG5U_HY973Fo|00(bg(rLfUXi?wBk!`={zEVd%sl zz2>A3@G9QGOSlai9Xq=*Vld9c9}qXu6+qoVX|n0X7M?d)t3cpdG` zO-E)*&svQu}0Cc6YUGdZAfp z3yW)st&?e!D(Y10UF*E#?BKFqGyKTNK`gU}OGMcinUpy~ z#v}}pp_77aE%|lEX+JSXn3c5?t$J7ot`6iyw^T~w5gByciPCmLwyfqFoy-EO0o3bC zV)kVv41Dc~ibTQ8)u5||5fOSwC?y->O^KxU+R({C7PI7>D@$bBd4-w`9H@sg+;l=c z36D9_F06Jm;YF5NF5L@O#A-d0EKw`-t}7!U>UWl+)p6!)z4eK^Yozh8bXmYark!NP zeHQJZZMfu)DoJXaEcwe~NYKUl8q~G6G4CTQND{o3_6=KGg5Xj9dd4s=c^KP`F)}%4 zBz0jeeV40%XPw_zBx1u(L=+E-IHYMIR&zSYb#8zvBreodEHvhgme|- zh(D1EJ7I(;o`pDy{iH7Q=u8$Jf~+qj0&PrY10CFYsJC~r%(T0ES)qi{Uzgb|bQ9mE-fCj{x> zX6a|Q6Oa(J;dM5-M<3s6*yrjtg4tg`mwAQ2EXm%r&(hP|-)kVZw~mD~5rT&y_L%nD z7Lr;g>vtmYn(AAZ=6X2Cp5OHNR8* zIYl@a!lXVDS|&;QjBpNnq9kKxxOASHYfb>$3p%64;O|WWdTY_*gq%ALx_TMF9fL)1 zG%kYJ6Hz**&*2^WW?fOC&;H!BBG_KqL_h1on=AA@A$xwLO6s5ww)E|TJf?SkxXaLA zeZ34jVZ?ZR)8Bs(X*euH@9)xyY+<12>AKQ^bkBd-I|nFPmgJ2;Uz>C7VUKOkwasT= z``NbbwQbwB&EvId^H-=j8X-@xKL<>yMo=lH!`Y;fIvr_?xy_{-b(VnQ8-)Dl@}BQZV9>nXTrnRav#Q??QDCYS^D$pwqNG# zc%{_^@*Eg?&X3{zw2XE91lXOO*1dz*91+m)v*ou{l7?U9m=skUgO$5_oRW6G+XnD8L2HUbO&w825g1SrFUs zv%K>Y#b8i)1dnjg2Hk-mF4di?3a$F2e}>uh{zRB%yWh~B?7Nev1UFjFJSTVx04Bm= zHT&l!U4EbD_tX0()y<`Md(!AnfhFhn&PW6dbi}&3|N6Y&#!Xo=*2z<(o-xx$xE$|c zsuI2Cz8YcQ4c2HYQoUBa>|UaIP86~ZeQA|bzImSR5Pom~OgK+Nv4)@n7vJ=~Awv=# zfx0}}fM0`7@9S*DHh(o&$$#+xgm@*9F=~&hDh|E0pOq`x?8JtpG({^wm&a; z324H7H*oIJZe7X`ycZ;vq;IMC@(2R7 z(ZHu8ECFS8e)CkP=bAG0g}RheBWn#fEF5@^V?Uydb+)o^`2D`|b4J0*H!c`*%k$mw zxi>x8paekXIkOf0x9PHc=e)Oc2nQf_wHIZaqy3*<;moO>tlM{uaEo1KI!!rfn?zbc z0;baBJ;xWh^u`L{oM;QcJrIJ994Mo*fKmQgz^~)Z->f;TK#d_J8FJeT4S0q7v!lI$ z#29Q!$UNu0tut-k;gxai2e<+{Vb@@qwq4I?HjwBF8jc{4wnHS9?w)H(ow0c%1ouu> zKmZb1u*hcxa3d)-xd+?B_7#IN)F()-j|WmcZHb0`N6= zz)j0V5Tn5N<_=n(d>0uFN?=eZ`Yq{p&mn46w2|pLge79xrFjB;(YFgwHw7#JRaXvZ zRvnC+fSaBhzp7t-K#UFoVAqYh16s9nfyhQjqYV|W4;@iNJ+IikHvWZMe0CE zOAwqwZ2erXl#t0qbT2sg+;$kCIFuI_b}0yxdL8u8=0gGM}yBFIn*Vef9ET$LC%jI8@vnHH95qjAe3@>J948$ zQZVAOkMuH*jLE;Avk753p8xhvo-}E3Iu2`_PCnd2at%rKbbJ<`Nz_dGt}jS~Il0BFju;43$rthyoXFC4O(pp9LIP z+NBB1Sfq1-^Q9cG&+NT<^;5j3HIF=t@mpjc>_JrF)wKIOvlh$zOV4_{w>s@Ndk zZd;&(e@0>y6+x5SYF8l zf`k6&&ay!O+x$$E43!nrjcD6z-8cF5R=)tSq-TbU$Xj+x1wCVie5$n744(SBhw7Y( zJ}EF_5;zM^gYzU?i=a>?u-ULi+wxFyJPSG^e17H_Q26xxcX$@np0}7M2Nm_mi;Eyg zLvUn*@#=f3nJBFG);Alt!n$wr>mHp*2-WQq-(71GS6^ClP>UH$?dybS5^Q|DA(>kd zC#F!EFc$!am9EBMe?F9QkS6oXc4(ae?>%JDcSlA=CUE@QYj`G6uh45R+LiR`3p%Wz z?G6|y;U&ZsZV}Q-ANVsjq!iE+CaiE{jTN?Bg2p6YP?v*w>u-3ZP76O?+&zO;UTPg11Yu26(i^T%lhaZZ5L!{H+p z4gL34B{9~Tzyaee)SgO!QlG76k9WsIV8$)`3aKv`_+7csZz$jtN`v>QkKa-(lvhLM8zGws6@@-5h=peK=YmZh)Jc5nhsh57y>4PvchC|9kOZ!+b#9 zOagfO>mR8X7`JKJ8vBkoOpxR{_H}p2O-h$to0R=M=)iKwR^MAABq8Gt88>6o<@q}L zEC!Vxo!FV$r`%%{Jp$=J$Vp3zk07P*J9ykS4|R4KJ%tBqbRI0p@KdM z&RYAPvPITi)3Z92{e+DULI{>`nNJbQv@uq~Fr?QE*WG_i*P^jX7^8`sS2zVYC;>zX zfE0-gSgH(?6JVwI6J#k>d;Tr-8ByHT{@Ie%bL96M=llfaRd-d(dq2oNx2q0;f3g_0`Uv zH??b1epH@c1Bq=7e^kpb*fVl&MB?>Z5K@2_jy zGHj*9x@Y=Vt8RcLkXH(7N58qo*^g+W*~3GD#45Z%k3#YZd^Y-qB=?Hjs>n)=AKog! zt>fQaiwKFRKY7`2l})tnnf^6e*-teGkhB!0mPRVdEMwZt&7UF+Mu8{T zCPmlIi)o)=*gs{~qFtF;XHjtt1!+~_niaQK3ND>MVDzCR2+XaU62+Sz%s*+r@qv~A zM)5edZcdnZKp-l~GtxGiL8|iyHT=f=WI-{Ed$>xaK13deK^| zmHpheGoYsXmMZBj=&4=DW4!TKkzbjTyP2EtoJG55;BJ zne@zDf2KQ!{Mk-g7mNOCQ1-7x4lL4C)CL$riAo|1WqMY%^73jFf$yeugH5mMGnqW zjqi!?h9DyXDKbzL$LH&OdEF5!uK^qqmN}Aanl+qBv+$queBjod32CXY_ zgGi#)U$~g*%#0yJRVgf~=RWHmLj)|8tZ_pl4zcywCcs6Z53FPrNPg{8H`g}R-Xp+_ z&69LL_l@V)g4SsSQ=rWNhX@AT&bNXX!l{ah4{tE_tr4MCAFr-lJH zm13diEkF+JiG&0Nt=&YopL)8ePK(rA-MRXLW<|#x#AW)LRv%j8C z27bNgnleG{C2J2@*BCl$k)BE%)G8e2PO-(Ik>KY4i;>!LFcBiT;2oXLj+a|pO}R!T zj=8ui&pq&`d%o|jLBX9}J;|xqI^We3-27CdqUW}Q)h7@TNL`b?CP*Cn)*3`R6qsjX zGJya}@35ie0(Om4b{iv{5`D*l6|dg4(4D%&|K|oP+cZzfU(a?HwoP~E#Z6i`28t}{ zZuB(!PCw)S?VSa5BS+TnS0)){nQ1bd3^RL}In2z=%*pa@;Ds3{%*>q3%EPq$F*7Xl z=IeKV+Uj@w^37P)sP1;%bN)vjk1VNMRktqwua!=f{(sFP5wKv9jqCHQ+gOOO{Wwj`VBv~2168xoL zo#0?WjamM^#mEf7pT~WnkFLmCr)Nf356Wi$xMR7swQH@lYruZij;?*JZSwQxt~I*_ z&*M4YmFI4kpVxP;w4Q36XI)x9)|y?}YE`Am;;sPRR7_I;ONCfM4=jVPi90c&qA|{j;4#5o0weuY z(t@u-=^RKijQGwKf+`8H)ye5xsRC_fDSrZO1nds18N|lNyk~Q=Q9}U=24%BBe*Q|s zBx`6{U0jvGKMRf)80lv+PO#pOMU<5jcyxKzS|dTTvoj;D>$4NA+nT0Z>ze0SPqxgn zUTR%vz03)_K^j7RLxN9md0t;t8xN!5^n2UW9=k}*10zS^A_10n+2N$8#`9<$iLQX*_#IQpY z8rHzd>cVsMyCgly_3!EwD@NVN4IT12d92(G#NtqjlzX;aDNvNd8q_uu%mGsYU4P9v@sY2usS> zdy197YvMjU(A;e;sBCwu2)-;PEULNh1w&JlPj9`_&Erw z-QF~VD1YQOxkiAHI0b(G9w>L zQa_eOqi>qJT%0WWqicuu`FYN-AC1}1hKeON$vxz8e8rw=&4x<~@uT+T`1XO_Yg_~3 zHm8%Ra9-Mcu^@(GlRueL6-P0>KHQx@T!O*1g> z`z-RoY{i6T6U80GFAna*6#%Eo>CC;!1$_Vcj^Aus>@-OD3&A8o48+J3^@UkFpooVE z|29ni5EkF#avEj}Wd+)eugOl}ln(rRAo%)e`wDAmRfiKL zuuG5;L|n|I;BC5JD%E9g$>!f0!sf>heXe!BR-SrAbys3ef3N}nULJ=PC>h2ox-#IY~phrMA z;o_7lAFDGGq5rTGquaxx_q)Ck}Xgb|zJy__^Nogj#i7@4d)5R?=U)qPZ}1-tpz z(757w^V_(veoTC705mECKao6qXKA(LYD_GFFqFWqUX_a)_zOcP7A<)sN~S**gf#eg zX-wg7-|bkI2rGbq=53PJOu4uZSORy+-|h@JCScbfjMVF91jh&>AVvo2rv0X-o2cmz zw9p6TLdRg6#^%=y2F5xa$Y-ZHXhvm=>-$ipvICsbxqw}PTN|hADyp2IL{MZga;fe@ zy1i+7U{U{^fCd;i0`TGeBC9wpGlJKRtrGa2xG`5`$9cXFbPryaov4b1Rt5GQk`nGt zx9WVR&jm9DMHWNmxkG0GQIF2aAHd?_b@5YWfldg7MjPK0GkR0ZlmIb|+nQ%^g8MUD zP;j1*lI{qwTzi|m_T5c0bY~>oE-0cHnX1d1;6w=Ul0_fv_ z!;u4{L62+jIzbV{NQW-D=U1{5eGUHMN?q;Y*zd_zlc0&)om@U zj0CqmtUBE?w(Dv!Sz##N%%)URfs{h|$7Y6YIPKAr=$3%8uW^JmRK6kPPoXC_Dvr$n7 z_~yOm0|GX5Z>Zm^=L&E!*zj8gpUE_!=i3(K*>{hv9Y$6KB! z^K==6W(YzSBadko(|9)j$qiG=x_|Xvv6_5?4+~HK66wM_v2Jhca>>VkQwnPC66NrK z%n*E9PVnbsQ-fy(54OzC2N`c_nr2-m6y!_^hPZQv_}YWZYVCAhq``OeX~zn_Gta5r z&)Qe$c5t332vLlrbm#e9P(K=T&O>p}pZfU6g>U8t9!#Y9rLq_JT`C|q1(%7}H`;qb^p8$ zz4}mhm3}GZx?TX6z$xh{*8zd6#(VsYAT0<w)#KwG!Q>;IQY1%@j}X$|x&NmH%YrvliZPW@+F<};4kmvq!Y5;^Df zwzKJdo+ZfQ-6fk1s{l8GQ?Xb?c`*cjZt(ndUU^ zHB*ZJhWMvm7d)%du5Ig50U6Jz-KeDO7FeK_^!NI}lJ<~jMm6Q+DFU_wjs z^$=(hNe|oPw~1BMy$uaH)p?04#b$Op@D+XmrBM33$5>qTg&UfFFPJC@NsL^g^F{9^ zU-TzmPyjiB?RVeSG~JgfHvICdvg27yp`C^{wyVuBud*$y%}>=GRuk`EG;C6ZSyxJJ zL$%BLgyrI*xNUUfX*F_bf8w&sh zFjWvGF%|&+IC*@APvXmw(&|eKC8dKPR@{Itf*iiy1Ll8E8A{ZnHP>iGnKP;jGfZ#ItDYoAE z3P_dtcFlCz72ovNZ{vNec}}s)w;vV+Bt`}Zo+{?%Cs@Shit^^~o#|Lq+2Q$`IZb<~ zQsV%uGt!hQ))OW^7hLUsRiKfzg1;-~=EoP*FY1YgD?o#d*B0IjGh^(L-LZk{;)J)L zSnFlIV64CgF><{kU$lya(dF5EkNGBzfM3+iVaPMx*Egi$#K*0AfAk-74V?s$je-^^RBGwva2Oy3BI#Oo9EaWpkjc7>pX!G zhf*teRbUkxGzY1wx0pdS5_PVUYR9arYo}E?&I&*UM164uYExxoL)`xTRRT>hQXzQR z#Z6}VEG4lJO8CNTGpVA94TRqx>kUBnpz{j3a#DYGWn655+xA}DQrF#++=okqo8jfw zMYuzdmOyqApb{|hsGH%Dr_}93IVVjx6z9-;&wx%ZG*+0;5jOqx%Y@gp%&|&S&LZLy zMTu_e)NNgkz7o7JGul;4H|^Ztmx@5*ARARVIsGMA6%OwyI7QHh7`evzDczXwN4M*^ zbE=2@yYg=~u-hp3imFbVOEAtLeFveb;|e)in)S{9=m!L83wPQtaExs7-AyFs^~f^Z z-89o_(a|3ioxPFW$N^3_DOz~F3ij-Q(+yfLS3UiYwah7gjlYi*Z(#;@8v9ViKZyX> za%N_P?)AeaMO9&+?ZO-o@G{JB#v}31f*}GUy=0K!U!9DKz9u^!(~c9aPxF@uzSAf$ zqr{SO`q_%`J!6x4thZ6(}(j-)}m} zP2Vnl8H+lnar&XbaTA;nN#5HuGhU~^KDnhf?n>A_0NWf`LKoMM(RKlGJy8S)RuAHD z9X1acImrR*EPlPCv>adJNe)iG(M%H3=k1G4Jpkj(^aG$N^5=H*Phzk`?!(s`CTVqh z!ffnB0d7#t#ttljUkS#T0iT%unr8nkjngpu9iM)fv$~7_tjtLJJ(2=4Bg8ZuWmTSS zop1ZUNdYG{sl0-XLZtrQZeK#M&vD9;N2uI2@AW&%0`9kRyLJ~|{Ww=O=`3Qh1Uj?o zN&WF$G940+=Os=7sCxmEaRD0l45i;#g05a45)lV=2L}uKrHmE)R^tZY zTPYS-S1BM^V71yqnWLwusQa}7C=uM()Sb8(fN}}x>MTfg&bsLlxP1?J6Ezu|cM2*6 z{Z1a&S&T!<>S#yBd~=@%m%rB;@_1Oy5RG|q$#((3ZH+TxRs^N*65cACv#)Ds2notB z=W&euAvJ^d@E&Hk=stp9>jYy6UU^AJDJ`xwV(R+rM2*OAJcED)wVWsbvIa@K7q~S~ zx6UKZ(N_@^fo9Jo$nQuTp;eEWX}cBO@&LV{1lFgskoxLKPhx0ripfD;pKe%!WS1%0Mvdb(dQ+dMNx|zmR$NRxF<#IQ<~?Ah+8u6#!iMw>D09)e_An;qP+^Q~)%5c@F~W*99+dsR=-tJufb1O&`P{gZ!U{#CL%; zrE|~!P4-GQi3;E}9WoB4*=+W4u@Osnu602{R-mT;=kKmc%tC)vZ??TQJ5DYMR*?ob z0=yINv@i8l0T6h+Pp=&N_p(TlUK8Br1R>3tjlo@>=Voj^)0Z;VfF+I{0f6 z(g4F^qbI%D#}VO^D;hZw`EKH#0@UgYxlK~1+k9LL9BLeHO{Hla1#of_6~G4?Gx&TD zzObRs(<{ZqUslaW@n^t2x>g08e8iRY<9Y3P6N9!cgz>lVwPwf3+VM9S{hqiL1Ins( z6u@OkQ~(F20pto@_^fn`uO@g-(Kb)3Xx3%~zP(Aq^ouA|)nfq@*Ly$^1;Bg7 z?cVgry}`=Vxz72O?I_b?DS$irr2?Q_*Ke&$I%j}`=`Cxk2cU#v8~D4RUX8#C5NFnn z=S}wYt_I zQ6^b|oAnu*i;f(Ykzlg^dRnG8hSz_<9rYpsjPbm=I7Ta%~&J}Y$Ld()HeV=)f? z|LrasVUDRC8Y?RRH|L$UCHDNkFhF}N3Wt+54na}q-W*@!-M$S+QHN2>0;?>Q(oq0c zB~byqQ0T(jN-H(_*!432XF4B^jTJ!gP%P-dHmYW)?n>3%5+X=5KHD-s(#mqPN{PCe z6n%DPlyBFDBDqHt3a_i70M1UL0=QFy2m~$Zi}{^X7Qn*Fc2|pgkqQF!M11peuhyt? z-(sM%v>Ni3NV)^|w4Q}k?$*HK%0JPf<@`B}NG<9rfCH1L04~y^qi&kc#`CKQsIT$O zTDf3?UD4e9tJ(ZE)mKr`T$1K=Q=_z_*G zTs-_~zMLkT6&HS~hfcU!aRnZ3o*g+8SGgwk9J)w=UJIIChzS&%KOmTD`Wi`+x)O4yHvpGt?3|hM& zDCaRn`|U>U0ksbZ5-X1uuEtAQ_cW{Yi~qwPJo$s`WMuYtL-uoRWrhMct8OHwwrdle zYk=SbhGfQ8;gcRN;E{4^tgngk|2!}4v6Ptak=}|ITNj|X0#yXK9J@r>Jl!&na&kYF z8F_opv}jmE`{o0+W=zpm2v$ZKu`^19o5fq(ORHY(4fb@isksno>t-mVowU8>wVPF@3^ zN8U#%GvA79@b#&%JEd;#z>1*0*)W;U?un2_b3_;}@-RVSWiP?cHJWlfF|u&t9O>Q+ z)R>ynsZO@FEJEK+{jF?#b)s={IPqnvb*KB03dp?M&}(Ds-cO##^Z7geo`3UtysqNX zbBtPH;9=Aot^w0>b|}TON%a-vG%TSW^||<4?$Ik!sdrXpq+RMA7?xLcxmEyt)@!p9 zbl>Y!L5U#I@|t(8t5g499q6JUpmUO(t}MbGYLoHaZZ|zAGm49!VUAf{JphJeN4_dO z?EF1lZ+%XF6L+UuUEe!m7>9}rf?xci+&|vKetp3Gw4r{-|3mId;Sn1O zo_*b*ntyHp_tQo6f4mw@YX*bp&j!GkQ)HB@oHl)6@`e`hVi9sm-zl4dxC8HRD+Jtx zjq2pxDBzK6;`jW&{am;RACnf|GlZ#TTt$N;*M<9}N>(xBS#*Kt*SD$Q-W{TFRBFpp zs+AIO;u1&H4zbP=E8~L9XzP3dk5uFFdkVTx97-vMj;r$Q$ZH+1MF%q(u#5)@5-+ua zzt(8Y#av{uISiPswZ}e%4y+E|n}y4148I}$^KZ-P!3n}6*#v&i|C6d(S=Ge`Am{A( zRJx*m97?4q!#i?nf%E>C$>&g$hY|};@r|lc&B^IMPXF|OQqXVYDvcWgJ+l)UDrmh4 zUWI!~6yTO)W3)&Bs9C@x|5m(kZb834K{WzkMeobET@LQM3RET$WHlTeNV~+HyUJN1 z(riJ$kv74<>D(Bqxwx6S!M|f_hb8(XB7K)rF@vZv5%GAie7>aK`x#PvwME0);yGA; zlt^p7_IrYqpkK+gIyZ+ClhdwHUBG6=_of0viNx8Nk;D!nOI^NEMd;6zSVk(L-@%Oy zQ@O@IgV6M8%&pW8l723jFX(rY75tUJ(wP?AqXKDt_@l7-Bz5x>6eA@Uc`B|RWr-2r zNaFV}u&kC~F9*&Z8<0+@9q!~cpA+<3IZF3NVOpx7({8D-zTGe-v8N9F{#3ffWo%iG z+6X7s>UZK5BR(@sO1x*wNlk_UOp)1r%^I}bDpvm#zqg>@ zN=op$?hT`=jfl5x3FH*h>r*ZBm}Hy8%}+f5?oS*^IQiUUIU;i}p)#X>f$RzO1fR4o zw~L(s>k4Ki4wHh!s{2(BwAQO&pQ>5FN^{zPbg7`<%TU38>E1MQ!nVo3Ma{lfWtNG9 zqDZ55AhtaG6lKvIRLuJb(aiqRrTD0{c5hZ2es`6TIn}whL;XLw|Gs)JxGpyR^$io< zD7sGtp(K04{@!-DyK z*M8PlWOE0w#{OF{QedQ)+#TdXppj>oP(4#CKdQVQ(Di0B21gD@*A9yV>#lZsR*l9E z4fyicWhdgRyY4K_>2~rt$B_afUyusH$Nrw8rFl+(Z;4Mwig3MR(A_N9B!KRT0+t&Z zrc#?u-+v@FKLnQVwk^dcP0XZXsvuiJa@81K@=Du66pz=yDQks(4?im%zbV**80pj@ z4bj2aimdfm^PDeso$a=}%nk$*6uPBxI%JS2k7DNgV|V&%SON4p1Y4~qI3qKHdIUcU zrT8x3P4MG0K3}-o&&c6^Fw%Ue8gm@eNvVGMCtK#ixu;R1@BjQgPD_eOlB57ODl35N z3uaD1xphP16uYC+cU}g#0n5MSDUR_=L6^Wt0U06qgUg#t9{?vm8`<+1X%xZzO|!@k zhg#~Zy3P^@tg!>Dbq2LM=WXOWCnX$I;}aI-Bya0rr=V0|q<~Zj{@lX`@^vBDeg2o$ zj}5%cI3+LsISH*HNv17i5Ro<%uX+381>neNS2F-N2Q(nIpj1w5qlyPq20BWd6;0u9G`W4AB z*Od5MLx7v1OxeT&OX{M`7>_4^qyHzrW?YEEA{U?e2ZFS~h=ZDdT}}xb@GtQ*Lzz62 z=jiX&A3CW4XvNg$Pb|1TI0e0*{Ndjxl(S3g?;e3eF><5RiN3G3Eef@6o@o6u!j?PC zhXNw97tgfJx7$n;3$Bk?3S+We)OHkY^Q-xOj6ZYp{jL%?6eDv4{}c598tKN@+ZNHd zJ%jPfor9aL^Y(CFYHdQwbhMqNf3RI)@EpD+NYe$_(6qI4A(61n}cs z1qK<4iVM?YEP&o%teD26;c%b`L!11eoBfJ2o2@;G|{(xUNszS6Bo4nCDMbC1b#G<)T=| ztT}o5U4apwZ804hL+x^HCT7n}9mISSWi z3XJ$Hi*!!V+Zv~{;Uc+srd8;%30*LEJ2dM8PGur+LaYEPBTuU9b5byr-jP-SxF(uozpoY;DP~#l z?GbbXR9%3u7VFVsLpR230|bx`WuSK-fx5pIQ6X<6MNr?UhBiIItdKNk8D zR#gokVjERDENxos@f8iW{~6oHpY@W{A6L=P_xDw;zORVWnQNH;e=evJ1SCdE1RD!& zoZ6Cdndi2Mz*_{}faTh50Kj4(eh|0fpdK}4=^zb@=W7j`nsHqM!KBlrR%*HH3s^K7S#K@<_uB*XPYHdwYnZT^euwR!(> z5h5Gt{Y*EIYL15(|hPBaX{?^C#90=XyZoOy!M&1xD-X_K0xGft~^jO9u-o+l5+tasIT;MZ@HW5Y^Sx zoLifsnX)D3a&+xb-Rn3`5V9B#@mqUkHqymE5yVh9qbT>;MxpSiDxD>_e9^`$o zM5u67nGHv%NR>eM&1*!?@Beng6rC6b*jc>O-^k6nQ-kok`C`{cBoKH&jaFbu%Nl^B zV!KiVx!@!Gybo3t({ep2vW&Pv?J`;RcypcFz z=vnY+|S)H=lZ4QKsGG#W}&fd~U{sN2%ulON5>U-HJc(yue72 zAhVBYX}vIFJ0B-}C>J?=ruSzdJ|%zB}D&o5a3iP(%~} z%8ri3)vDT06UPdSL`3QZ-_`x{W~W=#eEDKcnJr9=8H7R@Szb@fAfJ0@;tq8ZX9##a zR{njU{C>Xp^drhMJU{Ty1o_DaMQ#G(8 z=Cjf*e2#vN>Jl004hcw+6o7ICou2$#1a$%<5tPH6`k;@t%nr50*5(BmpqO#{Gg5;4 zi$sD-?ZLYe59)TNi2phIbl*lUcCrYeqPiwKf%H!(aRCO%=GO6^x$J*5M6I7wI|~mFlOtS)_Ev_K;16fJlc+zRCPH0 zjK7U9&9{-SyIGWzE1H-9Lwd-!?mMMab`x+ifDkkYh08t1qGM<*oC;aznT=nVlRt3; zBKm*>o;r6}d{6`gj#yMVr_4AizHs6mi7^dmA^vXHex&7mp?waS8h_^XS;%qjn6DR{!T@kiv~zV zDCXHqu4RPO15gz?PGN$8VxKwUkCUF{cVjEEFf2330SN~7`9rhh*LxKs)sgfD5Tx6x zl&#K&=XqPyJ?A@kwq+jm4fYH|H`tguF{C`krl_Pu)YFCFxT&fRxPx zY%9gKa(dL}!tx<7`eN&Xe7f$-4HNTp$;``@E;n0Trpu8WZyZyPge*yf? z-tg~9I`1KA_Bt;!ic)BMe79RXCddjBC`K}ZyVUq5%P+vz!zl^)IqV8QToritZ)%)s zy(CJAQfDj?yWH1q+ubPOw9IdQ^$5OL17ZK)2GtXgw`^1gAg^f$>|T-gx>?>6zI?2R zDmI?4rNXt=LaAJ2UgEj3xly=Z$xh6t4o?$Bw7*bwF%Pn>w91dP>Q4k`3XJpvSuOZc zT>WJh{A!^-XB_&gZF%-%`;=s}s!bhiHKRTH+&+zIHhR8wfuz{Ru_^5t`f4}!P;?obd-Gr!uR`L@BM*6Xg z6g(vObyV}@2UZWtPuJP3+IyouC?qGy2jx`m{V-7k1R*1IU;kEcdHxVkV#LTe#W3{O zQCX;TEv{>s!=`6Lsgpilu-%h88fVzUL5qdYRS@_*L9<}DV#G+TqImwNVl7sJiHy?T z(xJ=u7k%uKf}9sx7r+8kjC=a2pj%CrGGatah6>&(hROe}hAC1Mvv2Iif$8)?Fu1iW zTz3GgE-f%(#IckKt`ht%q{T`uo6R4`4X$0ZGpf8kjC=Wyf`bH}#fXu4g6{>qVDXVD zUyXQ>&wH6Jv5kQ5<%@!W0wYFzr5(E?$c0OVq3VrKByedcjaDVPL4cW&X9xllBSzK; zei+08rUpO!yneW3sJApu3#wZ34O72wB+QcHn*_i2JNi#Aff|*SDA=XN6Dt~n@bym- zgf2#m%oKd+w;O<;oU{zUcRTkb!0G44|D)hO!CnF*Mv5jSs+{!C{aV~-Wk!-RON=W( zT;r~$85&)B+W0tXz4}IsGzzX(6JsndAWu%CPZE>>e*cqF#@t-u3k}-$1V;%{0wYEu zDFYNK>A!nf>}gdH6lW!{vy06?53WV88~@K$t8R@T7GlK6VAXB-FJ7twug^~46pd9( zAg8MS7*^U=TIprue^&+g>IJbBBSzW<7rHGZN(o@$f#5^UEr>KWC?eIbHB5q?$jzqz z9~D?VOi(3AgcvbWDcD!=f?}JsoM4eK<3P`~qibzsT>`st=@@r&4`{x+Q)N~XEk=y& zEx5?3RnQ@&!Z$WfwONKEb?RgCLjnS&y2FkCw%{n!n{T8)N`sp^0%i+9v_X)qn3HvL zD$4&!`wCci-EabaSzyFSzwa@4*{Kp}l(gE}nURdwh8-8e&rqxSwksY$eEs3&u6Xya z7l;@!Vx&Uwu$v%ZXK9s8y&0wW^n+y%+N9vpNxzg(so9U)`7 z##LnfqV;}Ql}Z~iVnkD_)rj-o`#mF&GGl^>l<0y6`I+C9`#%Hl-vq}Cj2JQEQsxSJ z1Xj$jPL)G@6eC8Al&Q%1-^F0#_Xt)Aj2JQEvoxzr!QV%41V)S)i3lUnN;L^*li(*la_{}C;4Q&5 zg6Yw3(=}qm@Dz3m770!h+#q;P@R?wT;QMMq?%%0+!e1%!jV-D<=`mHSe>59Dxr7`> Z{x7BEw(~InnYsV~002ovPDHLkV1kI+7;JAOrz)EUlCOBa@{u4)JM4 zHZh4r#*Y0X+c%h_>9h3)Kzi*Ne9)!q6S9i2JrTTIx{Oqtfp_45oACda@%1=ZwUEc= z$#96Jpps@C{ecznjPDvu0UXC{w`CI^@_OZakeaUn+?s;?JL7HIHIXOiX^F!a-T#G=bvz#R;c;YNL zL@xg1{Fcj~6UU50nF2n9L){p7&-9;x=3~D>Q{~t1Bjh&!>_C;fEvrU^cwz5)BzSl5 z&fUD4R}sy8x_-#h4R8_D@qA0JDb>2XE!)_OH<2&2tVVj1bVo`?kES*dx(fHi^t+Z> z6*6iDGeCVjT&)#chu?a6DvB_^KOmm9CnEec5#^DiPQ2yr&km1kR-E93`nSYOyuGF= zl@MJ&;*T9wTi)uLi8_)#!(X2h9i`g#U)}FFwvk#?FNB!G;o%f`MrzWSKRONU?LTUN zM@$LuCWD|$02JrIvEO~ir+USuyaNzSyp?Y11DGzUU`Zn|S za@`J0yizR5e;31|5C_~K-TqQ7e2WJHPdq)7J}Izze+FE5T*LmgS*pNmF;N2%0@Cq& zmmb296!$6of%5wOA%8siiJj9p&CqPg$IDch^7k_cZBdCSi$g#%Qz(x|5`^FV38o7S zCp_U+yE$Js;Xgasp{e-AP;yqHJ?RMw@eKF$`LltcT%p~&4Q$iY^{BWge4M@p!^dKJ% zrj%9yW7FahRju)*TW2(_e)fX8UNt4V;vPsn^q)#Rj8#(g9*v_2H7VZ*6&1?N^K}g+ zr}~vV+~wG@2fA*9s~G6)JDOXTJB*O01}+A+57sxJaDXMTeWw5P!X{&gc9Pq-fbLKb z;AJ+#3ioSyo>K4ea%jYTr8wN^QP70yga&_~YFq-?^YDym36c?6a=vbmxHa;4IP`lm zxI`htcXRZS^0)qcfWTWR1{Imd*?SZz*;Vla0>as#?t#Sb1Hgp|euzrFp`mOUKPh$f zk5iFk3q9AR`Mvq#BSO@t?w0Guugx|+ewR`cr{Q{qN+(iSP}imUwk@|uTV@bya9Gfn zZy{Has*+&{9ym*x=~LT#^kuTt+x~QNYPpom!v%ZkOGOsFbH9L+w-c-z~Sm-DA>^0v6h$xl! z$j2IW$a3jianQGu@l75)w@08XPpj6 zv4?9A5>H&KN!u=R!63)A&}dcAuxmdug){_Es!b>5{p%N2MsV+|u&VhE6Q->@%jP8| zDOJ~>Z2=xI*b8q1oYNPapSJFD?0h`UQyWeONeEqb<^jwxA~-f!nxb8fkod9|`SdfJ z7}v@iv^|@wG-_Q5okN+KM9Tx_{*=5dF-qy*;~*WaHvQ%qMR~!#%?uXV;l8k9o`nKP zS@L6x28R_s*mkb1_Ur^DGkK4R6Hx@7;+#ZEQZ~osippU(Fx&;WcN*hJ|5hm?Eh`z> zIU3UQ#HZ8NIQ3Hg${RROQ>$ZiB{E8Yh0SfuXQ{1XbI#;NS?@#SEbLK3B|%^qJ6F1? zt+BrTPh9+CDPk^KDyGyc$N}Xwx?p?I{>o?U$$i)D=O<2SS!o`km;;`n*SO)BAE=kR z+|$n|x8?<)nhl674+0@*OaFF(;oy3GXHmr6JG%Fd)Nen)ZZzmSTqL9UPeUUT4`u`0s@AUn+J*Rw#c%R>6YduLgd8>+y^w!Z%_5M zo!^ySc2Mv$;HkeCvEd#aLPjH85rqhtw-Ux3tKZ&;V$m0me-svkx z?{U`FgLel~*xF@rtx7>rC3K#-;NGuT{P=ZoW-)=POs$t|LHS72ZBW&OF1P->UW{wK zFeG{oJTIqWEH*2-L#I=)9A15&jq438a%IB>tlV8<2a&XY+DPpHU9lc!Qq}#2Xl^Vq($AK zk&9__9J_PPJE;|@lL0bnrLkUG)0E+Aw?t|1ON+lBq5C(t?nSctBo1HZGtRl~S-g9K z`8NX*SEBJ53boi4yk3@O5}s#QH1E$2)bWjawZrU}$9?e0j7LvdJj$tb8Y7e+G4Pu) zU-4FN*x3cqGcW7;^&Om~pjAtXVadgdjhPt+jNi*2_8(pI%2T2Zs)`E`LngBB>RS@} zO~-v-&&52g3)Oytt^FisORcN&Q#E5MIPZ_n;p!}(Dbr-6)hRJMU^t=^LOH+M{;~8 znZo(}3MbqL@tNbaT4&(AUdHJ&2{wKO$=MW@L$pUC0U(usiC>XlH7MeFIKP+VuO9n1 z8Eq@wue+H`RD?27xqy>frS)3A z9r*s)#yh{a>R)M-W^yx&xBVfKI?q_hA-oCHnbqnIDIX#@a>A*(%H8x;Eb|G$;u>aS zCbM~%caw?fh3v~oLnMuZ8$wwbgfGkCWH+fi zE)MtKARjKNUMFIUqYzv%HxA#qymN{dGs9L+C^Jz3mlC2<388jMdV1CtSLgS^a-377 z&STfY^B(%z?-_-c>Wm_1#M|&X=1OLtF;5K`xq;|ripasvMek|>M}kph_|eTOwC0FR zWR5;yo&G!5G%Sj6H}jNc{;z$EAsTB_TlQplOY22Z(Wl@_wA!=c`rt;iM(qP+-JVKP z)FZu%7WJPC*%fd~T-By>MNia2Npc;n15NDMJML}T-u_YJ_xh(jF#)!#DqmVFwc(N; ze}50XUnXQgbvlX+XB|u?74-`LGFv~t1;aRelyNwCZf$wMS2BAMGR2u)>Oc>`RWgmv zI?UdO%qP`SuaK0bmiJ;Xl`j(p{5i3)T z&)24NYu;kPl&CjQW>*kv0Js>YGhxB`2{H(|;G996o|+Q!0!ZqPF%S8?#S&!YYnF*e zVwY}30*sSj8WY*-X43nKrm$j~*UfjR0pXxGl{|tIZ_JHFg8Qo+~ z;eE()oNzXI#k9y&FG_50a;ZgBmz4)jVFN#rAw3@6uBkDpN?9uk_& z-vK{r*5Q>J<`sv6&QnL4rys2BSs7?VQK5Y5UawW|=G6aZR1JP}*XYW4O8{wGqGG0Z z;XA|}c@$U3AHU*M__^Co+|0H4x=ufZL~yRH-#&Sdg-YiU)kyZAzSoRBx&kH?26=X`7UP{?dq0*}l+oCxXEgK`|r@x-+)}weWXr(4jkLT9k{w;h}NE4;>WlNm~oV-{vgs zMaZ=8imb-IzA?;$m7zN2nW96ORA zTlkxTGEj}1SDQ*q#etnM!Q%EQQG4n- z;enpROFd^12(QU2M5cH6TtcS)q>MY_(|k-{O8F?+G6s-|rx8kOQ#Rg?KO>oA?~_>} zUX~2_N=;`OT*cGc%4?s=clf^9(vJ_4oV}rQbBXNWeS}47u#gZ&NPD7E zx*ShJ1qknhzh&)s^<7}K9s73t^s;hC@l6Kp)wji;=DHDI&8wEI>BEa`gN7?A>H9s- z3zp<4w@nszh|^|#j8v_M4^J-OfXs`0%`axES#kaQY`lI1El*M~v*seH_hgtw8ovA2 z#%8wh?b@!grbD$Q^O#x6_>w(Y zudKiy=6aO%3Ow|}yq%vf=r?;A04EWv*7*CwIbv`arXM0iuLDYCzY4OZz7RJ|m!9H| zVH+AKgf>lE$@9H;bkvCj&DGC{T+pS#Of(fl#jo%NPH*PCx{jYZoYT0X-$ZOAFq}Ig znq2VAql_jLnW$CP=MF&%1*y7}(cku+M?^L+2aVN)mC!6=;E(SqHQld_Bwq1|8*ZLc z3htHHD0=%v*=&HcWZ8_52||MNr{X5AEjHAx<6E1tnZ=cf&rBI1ta#r1dx2p}44CDZ z8{uv!RmS$_Y#^F?^e)R(l%UPgnY;oj+k`iEm%^g)lZu?uaQtgs=4s2wLF=Qx-fdCS zazIbWQw72+^`G3sN%?P^A_?_HBqIGZ(@GR9E>!c_zvQQJgmLC4y~kYJRZDoNA(Lo!&#Dq z{f=twV3=ayJDbT|A5HVv$CA-Uyc=#Wu$`IYRcoxFKJ&u;2kzc>;@St1H?8aP=U^V} zVqD|iz9w9ofHn9TT(fYR*HMJDBq$9@r=4K>;K-vJ+@?P$$6LfU;undhi6t|BB1&lI zv@B+KWCiD^&%y0cchT4JOrJ3Ufvr)i()?I;m53t;M#lc*+kkNE`pXA5%A~Lo#HR|N zuUYF|@j@+OWNF(-f)gB&s`e|DRW_}oo+vjWr<6~X=S$h$AL+B*WAM+MU&soQ?vbB& zp8Hv3;ycF;iTab@o`e+@?X=49yyc*BYIPsd*;K z$i;ML7$%DQd2pb)FuRo2p^eS*T{?R8vvBN+^5(Bx$Fzgv4z%|x*i&{x1SwEVWL1GM z3tu{eb!T-=ZEZ3ON~Z#Vt@+BAUD>WSI1p-SV-tERB-gUuMy9Uu)W1FDf$0C`x9$IV cF9TCFnT}f^7hUGSuoH#(#0vjeBabQQYG9xX= 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 czE#{1#yT~1E4gf2T2kc)2iFr|HtH>o*b znlgZRzAy*baOsk9}f6ZmLcz*9JdjePZq!rhkXL}0n9D=^NM z`)t|fOOK+~VY|jxflVy5`nzshCsa}AyW0b9K_8g)0HdIh85B>^@B-AlT-EXeY^nQQ zS50o>`_tyP`;b4+&Z8deM(fnSdk`YRXb_&rhAk-bd&h?Df&5_$QRBU#(Ws!ttMcLf zLIF+N$C((c5peDr3*< z{qLofiIshWiD};7hoop{{YTaC{L%N(-TW$zwN7){%RjWuYPhY3kp!Yz~hvZ2W@S{{#plmGI&po>UiG-B3}MWGt~u|>^2f(ZLw ztBB^Cw^>mES~52FH@_&C2;QMWoDM;dS66}6-GjbO(5`^gRIy+0@R4$NT2o~J$c zNyzxOEVW}}G_)c$wI?BciA9{tZ?lpaR~w2r-@9{Z%l(K`PG&5*y(I`;g1^@N{hyo^ zxw*F2Eflx*fe}o~`s+J*ca|!I-Qa~Ta21N5+D(j;lue*|rFFT2w6O;}cTb1=um4*y zwXu(o=k^E7zp-KZry-d1Bif8sXNGgFJ(qVH#UJ*H#Jrm17DR5 z0OKNeqN8-0t5r($e!`c-e9WN0FiZ`zT|7FoQJKN(ny%|8ub)~ja>q%d^5kACTq$mI z5%SXZy=8{696Jd+IeT~Zb2cuHUzwlnh=(CA2HsyHdQ@b1&RcZ!+r)ouo;Ls^_xjOb zEw@q4XiqyvSdz~KH+?lI-e;m{k{x$~svogaUD=mudD}hRaY-jEzf-f+(@E$bt`JuE zZ_z|-O@4(DfUz$=S%hlQS?tb0Dbfiad4KCB30%R|S&id7EWG}kRhSw1 zf{pJ4cjWWq>(aO7o=zIC8jG@@(}Ibh#9p!)Mg5RX2u2(}?CQ4&%sC0cU(y&WUEqc4 zB`l{e7ld3E;1qy14Yo9#qcG-flMn4r#ZXHu>Aj#xH?@^YrQ!LgG$fLB!p1JKfuQY> z#~2I9ERLdBv}6H*7bNERp_Y5h5=@zM`q#ki3qcN z12J+HDHKR;WEN@TG?x6M$-wK7!ZpXgheYekoXhc3IB*N1RZWOPIF z<5g=BLdlposUE3nPn)D@JGuFsxbtT>4f$z$f7v(5@8k(}ol&SB^j>;7o&r?-{g(n( z(h!iEG4uH${Or=FY!*BN(rExz-Kq8ucA#-h1QwBc{`Spk@+$-F@evB7U;hC|H^{;n zt*#~SOXG3Blii7=bnZ&V6K{0=>vRE`seoqO;8@%%z5$@b$mR#8Y`3aK9k*6)5Ph6L zkxP$GBQf-j=TJ0Iy}%C`X0lI90^VQEMv9B+0PH&?dpCK(IDdYe4pX0n0TtIhnzBD3 z=s^3Xyy(Q>7r*iTJ(_sWg21~pg zXp^HjbZzyT1glov6O8`k6z+o5Ih_8`AhaeCZrUXQ30buAG+wEG7VMS)FX?t1e_dH4 zt!xMbwb^|SbL67Rk)dk{;e>w|BMBP~?yjN%3@KDviisW^&QyGa!acrbPSPK|pC?w3(0W7ZFYp$=N}tS`S&rmGG~+%?105{674?6 zCcv8hS)V-rbF&*8@W?%*y0w&LmX6k81cnF+ILyROj&2Hzv0CkbIgNdRCpG$veCDx*QMraAiN7bDcOmqL6zsO+$Z^o8%KF^SpsaA z?E{-;pgb_>i3`X{8<$*_xQ+AOx${G8xE3kJatA{IL~02?vq2dW^O7F`zAbhvogTIJ zn~Q&wCaN2Xt~8gMsW0dpR}W`_8htnf?c)J z^@&`Cg!@J%&PyS9!D&GGsl`>`=@_?{Y4ev#sv?1{uh6G}7hC#WjAr4fNK-A7R9UJV zmE&h)9MCrg)_iV&k2tO61tyfA_Fc)DX0#roQDaS#;bTZSCUzh!yZ2&Bu*sjAcByde zNj@@)BTuEqfJ!*qcDqeDrdu2jZqVW_{)>_FzcoIG154MQOn9+E09ZR^OI&Yj*{H_e z=zdS-mF20oXa^#1F3Gke&=^qmG2KY6xi!Y>t+R@lGz|W`BlrNkyHa;NH#7%6=Y~dZ z$$pc?(*CBw)nioD-k;7-yPwGwxw4@mz-l`Mm~Tz`z_qxy_EocCdG5pOh@D&P*&6wr zYk|IGfVNWjBqO_?6PDw@!6@)-$aoC@M0x3os zBo=q?F#8`^&0eA@(nHKH#_GzL>&daieYt)`W#=Sp@ z@94+@?F|xfm=wb_i!0ZoUg;|4I$qUba);GF7^Gmi-L_KiL#M6MsWtQ~*TbqaRipTs z6zezTLy+(ftR)A&-ZYE;DGf0%9{OdK)zaE?kv#(Pa>c!6Z7amQ;$6R)Iu^9X$J@DF zUm^Ibg3{={Y6%hj3b_1M?|(3Z>#9e~oISc@Zz&X;w!zUmk_&T#Z2>aP+ zck7{FLI_3Q>pU;FYdM`VhT5zcG0z?1IKPzLL2=jpF>>N9Vw#kWfqGycvz>& z{U)(YR{Z31IMo`@Pq6wnxw}^`2N>?mG&eja?#v^a@b*Geyvw~U>3w>-&L;;K(0$&F z4852yo3d)T?uBDZmiWUVg{quJ9ULqp)5<;SbUAS|uZ0)(yFFB=W9STHoLd;ML?baC z{p^Ib^Yos>xaTFlfxGj{(`#i=Y`l z%F}h&?=w12i8uQW7&2&a@6Pzd`Nq9yle))^)ZT_Ii2{lPnEaQ=k9uEatxil=9ja=V zl-nHp4j$i61`{)%xs;R>Io>*tG5NPeT>WxR?~3E)#w1SmNDFT4MIz!o#6kUsDqit~ zzTpb(0A(3!MBU5OqPY$h?1_eyILXA!AFh$9q=tC~mW45=NY?JDaeluWb7X!GKqJ2& zAFCGVUoUe859IJac*aYj#_0F7td@x{-oNL$jCEf7AKDT{R>7^L;_Jg)KQjdT=VyUO z*K)Js1x=S*KI1mDz|+V^QFlA4UB{|-fjt(IQl{Wbf@^M({~`f8`*$C<+P{A31uwG+ zA#t1~)1amXP$l6`H~Yj$Jo7qZf!;L69wT$>kj%r|*x{vvU)dM@y5u}+*}Fu-J+}U| zVHI2cW7@SdsHw=s7{WCPHiG9e`p=ey&P>|V;k^07!GCvG4jyv4Nl0&?GKWR>NDw4* zsmP$qp_7FS>Tw!GYX4PAwEKHS@4eR`Ti)bdKVxR1YO_^F5%XHIDP&Q0iMmw1Qk!lM zA@B58aFP-B%&VGE@|V67y(4*|0OfRCcnw9t!aqB!c+pw?D4mw!bUPSK;xqED*or@X6FM z(Bat;fg$(d0;qNRj2rp*L{;0dTzTnDhWv?{JCI~bmZt^dY>LkkqJGl)W#yxUHkowe z9TPP-&TK#Kz;=iiYDq z6}YsDu{*pkPbGUYhtKxc++Xjyzf$;<$yq%7iHE+;*Sr+JP3MGO+j5HCxKzf;xf9Y= z@ponL_!VUY^o=)}8YG**$pot6AxU{DexI_;M|!uCKc~^w)xs3{@p^ONMfw4S9moKs zZ*Vho3NLhIP|&)OC460r&nL~Z;!L*qX18Vs2 zlSQ$wHYBicec$7B>C#KWR6K+y)hhkw?GL(GGNce=UtH^u^(Z@4rMgXqx5KknbUFK! zyY#^6*aO8xyy(YlNzl7`bB`E;V*%gxtf8P6Sxm=v*2mrvHMV%Ft-E!h|}3Tg3Jw z?Q;ElrXhZY-)K2VKNP=QedL!o&k3E|6Yn}%;6VKoGEpX2WC&lev!wHFJ&v(2tuJZ3 zR4FJX_!pK)kryLRIZ^?3+F;ZI*WJhx<` z(0}u(V$f;G!p6h?pVzAYGR?~CU)4Y#uBDO6r^5qUJsRp-!m=k7V+RV+cFOG_5BD$m z^zLcEA64wKN|Y4V;n_2o@I&oY))hTd}E5@kz_KCZC0 z<3962Cqy#3OFWH{7hQ%W4R;0Jsx;WnE~XtqNY`gyq*#N;g)h0K+FsBg5B(PBx*_nT z!u2rflw}U`Rd9nx>pO(n*(&HWAkR5$cqIoL8*b0)&#Q>0&3#!>OUBT_@V;A$4?FIQ zR7wLbvif!w^=k-0qX@)Vra$3UyLGp1(_R5@@Ve0q{amzj%`7yqndVhT#I@Xs!Y3y; zgh^s2udRtC;DeI+Ok+D+u_HYB+Xv~_WM0+&Z2s9Onp)3F@zFtX{VRinAMoz!=jY<1 z1E(hKwl=?W!(N)hk+-3lwR5t5Pn2iQ7TXW%=)la>S3-4ec^g#P zy4GI_C5pOh%dE+R-PT)zlH4R}!h8RHuDZ|e3zi+dC+`O2oS+Q%cEElKgt*fJuh)5U z&UOjQ*Ug60K9Y^GHk98(5ZT{NAtvDz6@WBs^-yF9tabA6j7&n=4MpAZ3|SWXc32z} z>5+FR^Y1$JMxZ!wboszvgfq-YYbSz3(cMyx2~Dkk8^ zKx;0;)n+QIyRVChus&VDh0ebWeT`o&wZ2{Kr_c3sYZf0wIN4zhj6b;Oyte5$`QplZ z(FD!b7fNVyhp`KHH=8^X;g@k>Seg~#OJjqBJW zjMN#ED{DKlH|=MfD3ZaQX2uEp!4K%tYgwx7N^)1FZ`2=EIizzBF2>$l1(?<`lK!sg z9bD4wYWB)6X!1=n=F=A4KqFS+l)r6M6K?=<5Rv-e&!snhg&pc5!Io^pZ#`)t`s6d%-A* zAXpIatHwAp7@90vm#~KOctmsq{(qpuhKme%CpD}&h!yO=s zJFsKSHMi=D??G%cdsp~lt&}5ZzchE9>iUFQk(2y=+y)}w?PuKmgZ{E}U3ePai6%N- zz*PMAqdIT)WKjnNP{Pf=39$T2rb_j*&ViuNsj}8qD@BR}t!*Y5SDUY@;})*z7|7Tg z&-#pyV#&4%0$53CVyruBt^yb;qyR>q9qCtxJo!&I24?vwwRy!It_GUhhL!S+&F8^c?dX+?wLy)x>9eMyEV=!{Hj|QmE zUj~)wOJ1VRjHWqDZ;~kRj7B&WHY<gDFvaJ#&5zMFGO`cd!ooQV`;@awN-L4ZZC6uT` zq$$0kR;UhzlY2^M!`E-)Xi|dnLeEE*u0|G&FT6fU8^%}6P;LAY`Hb#e8TEM4Mt9$S zv%cTUN=W{z0asXiDF^R4y7+iuY+WL?1;MwpYk-W@xaxf|OQ+XNBk>9o;yv*Wq2O_2 z%RB!kg_Cq>xTy|d=$Olt$eZ3b1hE|68Sg1#pCs~w7Eyj2P7hNN`z?nmA=qK%VMiTB z5fgR7x53@0DKO=l#OE}%L=p{hI}Zb^cc3DqN;Bxb&VAta{af!a-Mm*JI(zvnNM=6V ziNNu~d;0)6BI?u?fF$6%5Av=ERx>GdcU#sj$G=a!E&+8})Jj5Kep1zR1X~51=8leS z4*on^J6edyoFhxkn3YYs2L9Xp!O)z%K@3<_#&Bevh=8r`vJz2PJj|>6f zo~jV&wml*pQ5lcrlPJD50{i?C7&33tyWumh5jT|yK|Ag>ist$H!$$B!Tks} zK>Z8-GvHj3v4$L*r$D|qP07zU)QmW>alWbO)e)WqD=0o%U?VYkDG5X!*?EH&@fqyS z62_cWqHlJKH_YnZ)ZhnHKjqnMn&=ZAi+%#ST)=0MGywNvsm4T)rE~5n0c*wnp|*$n zva}ss^2fXBJ(FFS&K9P8s2ha!4x{!1Ajl~?tbsVI?VS*g0cs|`p`r9zA&luHHCv0p z1BL6F1FWeXFav(a9GbN1K$+}LeeRZ z`3q7D^B>RBNHl1Pel<8Ku*YXx>-d;t3qm4-CvS2s#Ii?Beha8|x)EH`=W9Ps<`gRa znSh_h4NPMtBYiKtkkc=X+(A)4!5z)kfHSZl^w->eiwrot`=qahx5J+Z@rkad3On|# zkq7j{EUK}FDugP5>83l?q_iuSYLOqJdj39!9>*g6UNiFH8lIjDhrJR~3aL@a`H}kI z><*gHoiw=r4JHYY9zI600a8$S8?aOPmc$TwDA90=aY>Ln+7( zVEfCo*zc1xf(qnCB8_}W|NiDHGC-?(1Z@$OJmVrj!YBRmBN+RuMJ%7*t=4UzL-3W4 z!Vz}*YO)QbS^y_*;)M1Kk6pU3+1WydqTkjYWT6u7saeR2OTD4*{41K2pgMK+BU^u((K;f+qN z2Hwoo>TF`Z4erN@V0V9m8Ybz0T22Xos@MdX`FXf?^w?WrCqX&%>e;Ag!j;m$55oxd$jmwBdXUqK=OW`oLBFjE-B+Zx z7EADq2UP;+8o75*_fJHa#NXZ36%}--8&_oJeE2s8iwInvw*1r}3 zb6J%k078DmigbubUL^;0rF#B5n|}!4Ii$-aE|(EKgLDLyuV0VnhD&-zojmqjYPwB# zLUCqdgjC|O)`H01j~5)&p8}7NO5v>1<-MIVkX|#ppb^ht#nw>!N~6ol@FLlV*O@h? zhNOFFJaZYaBv>aT`OO%28pW!3@kC}mx|gPyW}Xgbzjfj5027=VthU&;>^ndR_qjsK z+bHFKl)~m2CWo#ngylSYJec}NlhM(=>Tb~jf-)WUi(xzn+l33S*`NUu=%rnHUl=HZ zS0_3soXZTd+=H3O<|nA z@^C~FZQt*IWM_o*{MqfJ(r0*1lD@%^-wb{dXfR6`2@*{&WkgxUa|HWJIYomDR&iso z3EUkPg4HYChE#FC3&=ih>)%2cca1eM_7SQD?KgN9@90t1Sv9oM3OC@g_}@I4^0iJG z%a?t6&XnK!cq5SNTCQh3l2P6;%i}(uG**6!W$y4lVlt@T-YrFuL#k0&U zg_!OGy@FlVb&nDk!I^ijKAoY^xxts#zinSZ zcM~DSYzDfqXuYWW4aC<3zDW99(UaVm$0}iycYSpxZ5lxPfUKo;_q)Nz96WCDhZy!E z1gQq;{3pE_*3A*C9K>dblwC-Ps{j0z&}l*Qa)bWXp=fvtC>@8egD)pwcYIV2`-Uh1 ztHt&>1!YFVYC&)O$sztyz%<~QS^=@x;zM1j_F)21?;$isOyCmFz*b;w-@B4mR4Y0L zWarLFr^XP@pM5wQC*ZfM2#x_xgJkFCVW^H2_b0$-Y%rS{sp3Dl+D#eN zC2eK8zL0MqTMza|&Y};a2$H_t;WF^|JuT8QvF7M1*{;cTJ@ z6C(aYRt)^~JXSXN@;@RiSAdIXyuK0+Wu4vy_!e{H_#ukzl&ihb>70aX2MB7f?HvrP zV?=dr;F?iRT>Ou|S~e%ZWkcS9ZMmgua5E89o-`zX9lGl6QdMqBWAOgDS;B+TwGNCs zo_}!cZV3+w;7LdjPl=4W`c2!wCIoZN1D$BkRo3sY&`y2)dv$r!K4a@&fj#)+=r?6V z-&Ojzv1Yp$1m1kI-+KC}2nhWZm0i>f-DZRDByvfHhtB~uBPhK=dkeT*;Mt>WFn#q% zqLIG@OfnL!m(D>ky}xhs-L{mpEJ&~slB^haUmWZew zd<}Tj8T+%U>8fyBlLFbT?JT1vuR}aHFr&5Ut8%bw`84c5 zSg?l|gR+e!=g*Jc(;fH9h98uYK zd8!8Z!5hTLwIH7bEeWR(SO$+1@*v)w=L5%9FUG(CmNPsu4zfq?*T%D!E#y{3{Kp+0 z>WpD(mLg^5tI)M=+b0vxCTJbAfF3^)%#Yks`d&tkbXYtoyvJi}mXt881#hr|G?>JfQvEPla z8ayaAB$h4$!1lQ~ha=v|%*-CW1nNVpt+uW*3IM6fk?PQ;_;0}QR_r5=oyv_6?QONg{Q=N!hl&2FsZF z;B3?h@!{oPd=?mrQabo`kJ)Mf;Lu}n?gQJGXGkQ7(U4@_dT+hb=}-La78>j}m0obw z!9SgKgt0&-`{iwHAjv|vWB>^1=Tv|*GHxwR0Ki`$vchTn@v>mLUDG!1@W9;yc*AS1 zS*hRaK^u|LnM#o1tY)pDS5aeSpK z&WLcuaAB61IEGlCJOpLTH(}0%IN-9d)9bw(#WMIKJo<~%a^rQE)<}p&I^>aHmXc7w ze+wncf2l(LUvJCq_o|HrR~WnY!H2OYusWHB(S`h5bu#eRc}0;i8nWq;sJut^JIM_u zBYVW*yIFxfm@(v8`l6$@s3x?lKwxWqYE@hkb*inH4=*ym0iStPboKxBYRPam)g(W<RdoqAf*R0U@K5jyR@DA~ z_G2w_*9fy)kiOU=PJvL1A1F~JKwZngdl|DgG|%Ha?^FR4$SN; zT2!wQ-aN^@Pi}2#qVRgg50jsd!U+@NP{?gMF`4OulB~bgP|aVD2_+a#6CX`2u=a-T zg&eAbF;HQi;mL^H2xjS@2DC7yhz8bfG2-DI_1VI^SvbOq&r#2?JTIX^iqekDoL?w*xBuFk99)L2WV^RYgDV-M*JVB0m}OT literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/rehlko/dark_icon.png b/.cache/brands/integrations/rehlko/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c586a1f09fdafe223c50bb6a3dc253e6048fae13 GIT binary patch literal 4525 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 V8QA*?{2K;3V`*>k;*?*?{{VwkQFj0U literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/remote_calendar/dark_icon.png b/.cache/brands/integrations/remote_calendar/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9003acac2fa0921c8635f3f76e8b81a759bd7632 GIT binary patch literal 1956 zcma)7c|6o<7=Pyw$uZ=Xb(C7WQrZg9r>U?8jdA9P97EHhRmrU;xmxM4jO`Q&jTt02 z8|{{K&`4>*glt7?M$R!*v+wUW)wa9+vGaL9?>xWn^L)S0_j%`?nWGf)_wuq@vH$>i zlAW~+02mlzfD8`4g|a-|0Km#q9Nlc-BPg8(VlgP21kG?4fubqEnnggk$|gXm5DAK4 zAo>8pN2EaVh-PcVNQx<8iNI+w62qEn5ElWq5Q$l^QuMI~B0|8NLs_T-A_$Qg1Sy^d z>^Za@YVLMa@s^y^v4pWc_7adYiWu%>C1j%QFW|106Uop6f5|LRX z3ZDvKAX?(6L4)_9Jko{i3V0Ybys`SznXJWyf2t&$dN;Qxdj8(9^ms_isFdAl*-N_i zJLBqJ@&nh8+zsz8(w@{>XD!tKqbJ~8j7Og1g~-Dj(oM@&alV~6o2--4%7|AzZ<4e~ z!|SX1)Qzw1I4ym6sL|m0ij0*}X66=_y`8tK&ydI3D%0{qpKaNE+*|XcI631e|;s!hb9E^ zoC1!SwrT{0B^q`ea7`EvS>ro#C@s=3G2ga9h6u0(I>74z%)i5y+vh0md-)yseU&#m ze03W07V9p`6Kh)ZCk6+M7eD+BOLN{Fduo<56V55h3UKzFT2S@FS_At<{YfG1Qq}>3 z3AF9kw;UdpSsP|z!2Bka!6Vp&rxk@O8>;3IyUsY+*raf37CKYvK#!VYy0ByG(E1Ev z(Z#)@<1u_68qa3DN0Y{L9`}~65~Rnl)x3qdF>D3zTK6Wkv~I(jp&6V8n{lnRC%$O? z3j@)ovBt~xSEPsudPWwWS^t*?uo{XHBUINTnLv=Fd$8iRJ&3lP3mIKNIC{Y%)QoOd zvA2{54ET?~i^8Qh`T6aJ(6H(~%+1|l71~7VSQi7A{`vW~SkvE0D?~->T2=Jh(z}Z1 zY?bR=pLfqTj&bpnhWHBXJ?8Lh<4XKMyP1N1xYVj-W5DHj9Cr8F(LgmPj%~_m zFUP$#Pid^#l~xZjah_Y(Jx;~qb#H0K>(LB|@7!7S&GGFx+S4TCxs^06`sC_LCf8JM zU>((~+6!!Y>>s?Y`r1%X(9pI0U7lVq6qjSHI|5_JYr0GNjN%4`=8Wjk@FT#lwKC*- z2Fd=av~~rn_CCfuLFP($EXiZ)*}NUw|A;9lH>iG~L;88r+(p|=N{>Obe?`q{J?YZa zMxc`lAFU|uPR(Y@VKkB(FZg*?&jdw0p)Mf$YYEC6Qpq=Xkyn%eFGA=}S)n|rD+qd2w6r586+Xn?ocepDeYN>dldY=yCSfXt7He2u(8_mzUD$}jkpq$7d}vS$xO;v#JGtJd(q^8A{ghT<^zkc)K>Qme3ECr^}(;5iTFUK|*~ zS17$ct3bnZ6m=Vllv=D3N*tHc4QDw`eBki$dqnLmcyOuILXnWx{KATOo)4;PaFJXE zO0XrdEef2j)VX*+iXPFo4;a;+=7x- z%d`$CW}6von0AwLGcyjHUNowu%}Px_CRm&*j9zbL!s)or_th8oR|TOoh9 NBpb4I*%tq#zW~|KbU*+A literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/renault/dark_icon.png b/.cache/brands/integrations/renault/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..788ea0b39cc776dfa6b1dd435ea165af5799c28a GIT binary patch literal 5043 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 PzuzwUIxuLpwj=643r;9F literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/renson/dark_icon.png b/.cache/brands/integrations/renson/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..86920a4ad36eb422b67e8261c3adb321fd50367e GIT binary patch literal 10883 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 iog#_ttuIN|6J*Tn<^P;eNb}#6V0}jf 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 R9MZ4N=;;`0m)>{~@qaX9(e3~M literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/reolink/icon.png b/.cache/brands/integrations/reolink/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0c9ac17c75ad3e89781923552d4ada1d50253a8a GIT binary patch literal 2900 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/rexel/dark_icon.png b/.cache/brands/integrations/rexel/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..da2aca7e9a041e1c20736b941f52bb770042120b GIT binary patch literal 19766 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/rhasspy/dark_icon.png b/.cache/brands/integrations/rhasspy/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e1c5a2fd445bac482f0997378fd0ca4bc6c280a1 GIT binary patch literal 7215 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⩔DG9%?j^jYSNSNRPj!@RPOin%5@R;0Zcf2;fZyz6ay=0nMM_}Pst ztLM4Gop*)s?hHUbaJD0hQuV3{^hfdt~Ss1EQDNH z0ON}sNX+jo21uNw*jTf6=vC%4YQ~WiZZ)cj|6uDW`Mo#NLAGfc{Fz&@PU}cSla-)E zJn%o9J(vhsjfC~$-O4gvlD1BN@kj#XUe3oT?OJ3tA7bm{s^bwKg%m8m{~7-e^cY)L zZ25SV>c?9zl_DWc#>lOBh>i-)xZRW0xIV#y@F-)(VFY?l3BhWAd=HlC+9crF!hpdB zJJg=JqF@Us3FCJ%)4vQ88n{;Hesr!WAr$P9V9VwlR)w7AjQoPFAB|eOLXb7p*8i~g zHN|3Bl5 zO_wwon~h-GTUz0ZfXt$D&$dP*CQ0_bFkiI9b+zd*n2MI*Ub6F@YR<`DL>!Jvfb1

_lZiojPi{$&hK;P+;Q9ad{Z<@OTJ**jnuku`8l#%Z> zKaD=4MkleZS{^F3lPDpcur#tz0Vym#IcFsBV$(w#zv5^m1XTv+&J4HSd89?-ycM({ zPKq{FfsV}+Z^Oy=VvAhK#8PQ>0+|eg5a2X>sLj-+{3q_|$nFDk_8!^`dv>%#3 zU}kW~Krx6sXR#Osj~Afk__Bp027oL>alhs{W>>w(E(Bya_{w8N0M^!jAv&s!K{PT; zT_xGk4MYkJU*q=8ABlySMe>%j4;D3(tRO$En8$jE-BY=)K=C0?_?P2D`JOfNYwpC@ z<0k~xHgzG+ADQ-Hq2-HPs?ZpoudwA8rRAHV(PXQPtvJl9b2ib_rMd`U_;U>VLgo`( z)(bhUq9Ad?Gw{#np5@)H(E}-z(A#lJIPqaKae_iTZ*(SPjGCM05|dMFXB6#Qxd1mw zmYrE_Hq9kGvpZUOgL`Bql_MEYx$q&dW}(Zdq{E@IX|{KoA1bEDeBsNl@#yRyEhJ9?GDjIoNF|L)C&)6lw)w&e&X7@El#<+k@v(vF*VD#Ud?OhxUiu!K z7P@eDz;LdcTX{TbzZzOq>o(X`QEc7(fWi0I(MNivJoC?$$H`xNGAXkq+G;TtF6huC zVE6Byn&cckiP`{UL@KA5R4Y3TxyP{X%vr;%VqxSagU1GS^O%s(e+o9(Uv52GIsixiqz*K zl8jes+{z0Bk->HfM!P)cs%j&{KQnF52U)uBNm$kG$9Z?0A+q^qO^qB@wI~Z8JTvwn zDXlKJSLWSp(Kx(wfh{Y~Hfs3z0RFEDfX?b9_n-NynjJ2!=W$pSlTol%dK0a{vS@*}T&6D~?U3nxo*Nvac&!NU!tktc^qQpK% zt@*~-m>4%Jx|dLlG|XItDmJv%RYa;h4u2UX=D;0?-~~CEDxP{^#LJ}QhfYnb+w{(|YuiRB5qJZxqzS8dZvOuN0HYxwH~;_u literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/roth/dark_icon.png b/.cache/brands/integrations/roth/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..37fa7b48a7dc3e668417ac82c44bd195738c675b GIT binary patch literal 612 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fo{p?&#~tz_78O`%fY(kgt&J z5#-CjP^HGe(9pub@Czu^@PdJ%)PRBERRRNp)eHs(@q#(K0&Rd2#sNMdu0Z-JgAhr` zxkXMIs7;_G$S;_|VSmB=hV$I3$-F-2pr&ubjBRHn?_6T(*r9ty!Li{Sj}S|Qaq}gcn6Gc| z86Ws1Ipx=qa^4H`9cM8J9)HHu1~mJ^oP(ua!U}q4CFl5aGU=RKz{kn-C2fL&Lpoa~ zlS|KA$tRowPunGza0*;rX4`z8+u+{LBV31X2o*}!uRYRyeEG5F*7YxJPyJ6Vm&b`yVIoi7t>5{Bg4cNm6%a8CClC_q1GtI z78RpRO)oRjhTJ8?ZX~ivMD)mbd6*O%@}PKb`}6(-&vothhjYH?e6Dk@&pFpQ-|M@V z8y-M4n`Q<8)S$rSJOG5aB0w=BR7!npB%w&_eZqVIPVF}zk2n5`rttzepuOSvf-o5C z0(oHoS+fDKT!4>+3wsVAT>xMZ0eF@G*o({X2yX!N9yc`7@5|pEBI@tl|M>pt!2eAL zezNiYI{k0bdExvoL!-}!pC*ClHqyRdmecnfu|a>HI(ds3LasBZY$(2NzmOdy?s5FU zdz*Zhsk$*=Z{%jMu*_X7JvMFkQ7gvSins>@FP<1np1m$C`cF!8SM}bR87?tVvIP;} zxA^Wn(7M0L^oKiXw;tX+Q}Mf+yXNJRrQ7X(^*`t1&AHvTnYuxE=^9=V+@=VxU(0gH zJbUQ$s*WAn_V0Gxk9?H#-@yw78|BJ?van_49{-Atb)D-xTjcb|kBOR8zTc#*b&F>G z+q!@HJ<6x_g!6%3tEXJev;Fh(=NaQP-Kmf_-@actZ%(Iq?K>z$h+jObW#tb&P}Nxhc2H#% zv8v7vVFEZURz}gg&!kRf(y!?8p8>XO@T?9`^Hc(v<0T7T?Z_u zz-743dJzmp1s8Os8L{sq1iOxq;jOYsBLio8P{PUFW<(S=e{RaeQ3v3-@&uLMOMtPv zr|papJ197Ag9-MHLiP}Js~8kAx*F7>NvfA1-qqvZj||4m4XH^o;ffWVolC?{4cON<0~xl3ZsXTZc(1yP)baKW^3{m{-xPO@uh-O^T_y zY8(4_GFP0VugXFO7qo9rB6APu7au{qeI%u~T0tH$5bBO8^K6z}Glv4_k^HGTzx~*(n&ThqR+40`(!dzQjSZ(Pu zW9x8fbt|0VKe&n6vdOpUJ8gBs+K~6CdWA&OQxCOVp=CWB;SFqc#dIk)G3L>5AwoFA z9i!xjxHO=#zETsBaYK!Gn`lX*S-!e8~^ zJ6CK@jn<+JJY`kQTN}_R{t_2zJ$$afd&H>PVTHsf-k7^vf24XPlFJv`vXJLi?1d~u zQHf6wcwDx=_M$1H*`r;UH<_(8ZGSiauN3P!gQNw=^fz)ZQbcPk+BK9M8vFU;`~qi; z#{Sf1lVP<0?I@^h-XTW!R5fRHiAZ7@yRm~+1C8nf3($y>{Is>M#4 zZeV6|oD6x5IP;J7PxG+UnK0b*^jYcXMrf>yh#S2t!OV46-({#ZKVGoJtaL8P1FZQU~jw}oR&D(Wiw$%g_bG@XO2+ih%{i02h8aRCxds#EC9-?wMKGi z4iR<{$lk^SV=T1H+egsyek<~Py=sSy#I}(hl9F^HLuWc^!>zK$NmULgBL`pXi4G!C zzoqElbSXWJ)Ui)h-)zVOb&&87k*E-td!Zs%X#yd=63VY-kV;BI1-?XGX}|e7BHSE& zhnS>`>cnY!3b!OsP(Vit!-bFONVfuaW1&jZgjsf;X!^!Lfz%P{K8RnUBMrOoqeKka zng8GsrSQVR#%O}UI>XAR6zp>E?H(E&Qm2$Lb*jk<+iiEO;TX4%7XUWZS`#^J2oav9 zBRxm>(HsX~2vus&$YD>FR!`K;5enq6{ts^Sss?*(heS^efTk1L`*P?wuFWBEf5AQu z9Z8(YzY`w--YbL;y--FO?mvXI=Bcmbve5K_5JB-@f)$!DJUl|_URKm-AS?^%Z83?> zHyDN~7^Sl|rjN!@+a_qzNjk2fQ$o_6?2WokgUu0rZUNXh>uJ_uCpcQEMTm(C7BU?X zaS=XyDH^$gt1X_2Di=$;GDtdpZ&WW0_-fZ{G{)Jv3FWN4yX}6ya>}wuVVkqtPPgvf ht}KPeaJ;`;s+VW{feGFeoZZF*-;RL&h#NiX!_MTSn2z zlI%`mY=i7Zb|*Dzj-B4l@9+B;yyx@F^W4{U|8!r^^;~xX7Gur_5rqH%z-MV;iUR=9 zuN4IFf`1LaN+&!3aB;BK_)EX!&wu$hf&ZrjEIR|Gf8G6F5DsGpaIJyPe1I5A_G6vk zhX>%jqx%~IM|i#)jPL9o-{KYIKf%4=DfHX7_{T+t6A;sLeY)kJ^M{|cyNUBD zd!ySNuXj&|Aye2mQZOaUX0~o@J?XYXL*>K|TJc-s^oYA1O2n!QA5$}3hDu_ZLKtP5 zauxLGT=E-O?C&q{UwV|rlpR^rFGCyF zDkl)5^`O?au*>Jq=dUzwl%5XowN%uzd+|rL$1SgW1tRLo_-Q%-@OE388sS6TzVs^l zae;)n*-?AkhuyJ4bF4?L6YDWYDUQh>r4o&Lh;z`AS6--uX)h$SYZM(3FZ8f8;8ldD ztHl0{`+c|E<*t7|%zt6ug^@ZZkNGYqmXk=IAnXcu%}&2gpzXaSWHt3i>We1j3-vvv zypG!4L3MA<|9LG!&vjyip6@=|{D5F^cWCCa3fE+5Xigxpott@-}LcG)ovdg=I5pKP?{#F-n!IY~95lc()-_IggYCf-`+BmPE<_c>Q9Ev<3>qR5-bsuzWD$pQ@Il=Veh{^|8rVszr9npUG(=P_Y_W!k{`ldwyk`#}x_h>4>-j`f*_ zUqGwJQSlE1`fk|4zJl8&<)hnKE3fks<2=SJv(L8Tapszb$B=N`h(w=;?VF?A>le#s zVrnqOOo4P|>k(nChNSX4p6qG!>?hu~Q?Xxr2jCN}<3I3k$gOw5_L^-?JXB=^M41W|6q#292S8K@wOzFl*h+d$aH@tx&>v}NL z+uG7p;EF|PO+e1iM8G6W(ua$69D?o?3}1wYWHC?H?i>SpX>qaB7KH#4f=DJI(~avg zwHX{c-c6pg4JcuHd;=_F2P79D^#Jndvo@ow@CS%+UO;Tci#fs&qTGA}>K5{Nnpe(p z!9sgz)nYIMIodU>3JI%po5QcK#@h{(dJs&UM(CE47HtTUbu@#ee5&t{?jMUD-7xmNJexD_3oh<%6JHHIUP<69%STDC^*H+h z3N&Qj#;I+&TmA)|OAcZlNqKG7tfMdF^?8QgX87&5|FQ&8*(NL{$lhzo6xubn3O+U; zWc<_R`?xwDTz-1ukCz&TgD>DAm|Arofz^<5PVcBFuq+4791IoJSVt7UnE)t3W(CXP zRB%43$SHkigrBWlR44ROtEFoN#JyQW<2>%*VYv_;(Dsj9NZrJzmq)_JUQlUq=_G)R zXT-6F?xjq+$A_PM1j(iOp80Zq&<=Bs>r26!xcEyNyJ2#JiPKukvl%&|C2S?2DG39u zm5ToLkWzsc;_h9HceV1=Ddlr$ZIurTm6ig%pWnt^xUPm(=PkJa*Jx=Sb}fHRYccB5 zXs~L|O#_XkkH;%`j_Q`t)$R|9YY?LOc%b z3nr(|m1+{2o@W7<#^KxsJW|0@)ET4?0by?__tn(rOwP2~>7?{5U|W{j9!V;c&m79k z?RWkeke@Xgg$t3*38p34B|z9px7&2B1Yyt9G1-oSQEo;P!#{ao6TdNie&+;@pcmtIDfV5ATCWy2gWH@>tR)ql25SS2=Tm^&vvGf_4pE9vi$hT(_2cRyh1ozK2`u8YOYW+tWu74VJWSb_j!x*NS!sMdIz2KAf=8k+uMQvrir zJW6`m1yT_o${Paro|VO;Ex%>{v1PgEu1hrJ0ss=S_ppo+I5zq}dPWN<`m{q%O&>J) PpAuqu31eDi>=FGRXMe9~ literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/script/dark_icon.png b/.cache/brands/integrations/script/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..50b4e38ce3c06395f9ffb65fd70d2d2139755db1 GIT binary patch literal 1805 zcmZ`(2{e>z82)B4laZ@j`!$i$a<58GsHw3O$`TVMYqqNtB1=L|Gi3>t7D{BRZkfgm zSz9clk|fEvm2E6pLP#28EKPHNGnrfW)_30Xe9yZ*?|aUF{x6+x~tn5u87YGD^A^p5zP3txte90T^7sm;^bK zfW`w19?0Pd$rPYY0ooLxi^(*gPXn3|^JV~T1~7yM5&Gnu0!@TM5lDw2Y|ouXNC#4b z++3jogkmC+&E)~e=tBEiDV#3aL5y>P!d|HTJ0ffpi-^eFIH5t)Aro_mh$7JFe>a(5 zKvX8$;r|F_zYTtMMLLjzFe@$)4Hb_TDSwAhqp<6{;QXpT3JL^*MP3QY&?n9ewY9bb zFgOA!fs({5lvyMzr=+ZkU81JGRAbq4%@r$G{jp~4I&B?YJ^hWFHg7R7HZe8ZVQyh* zWkawf?sjx?cJuVwyU)kh&p#kAC^#fMBJ$`l(s9a(lTpzzv2pQd&L<^bx}1`lo|S#= z`mG!)Etj5`UsQ6xth}PK>fxiu)it%x>R&WA{r#q$-O<_G|88Jtcx3d$*eA{emp3&% zGy9qU<>GRj0kkR1%W}I()?i6e1^~$Q<|fAW;ccVr0lQy~l_=wDmVGmu&Y;?+VWURr6dZp z*+=`b49T|>?2Aee#b#37g_HbquEn6xG!2$WjXP|_`Qm=J7?#y>u#ELukis19SgDny zOKPquFkXZ-?riE)>q@)n44X7pF(m5t&DQM;S7zuV?M$;eePYI%tXK=~*fv&tsO?H=mW}KSJ_~e%K|`!oV8q~s zc3t>}S{QYqlbaiEr1no0m`Xp8JH=Qxu_4@cSyjX)Fzq>9wm8hY$c*xrDy7A+i?%{w zLm|7X%{??L^gy_vRjW(-pb(7 z3u@RLRduD^yv{(1dTrOCp#%9rfY;us*r8K~9(>7DH9E+_cAK(80I`3wkxk|R@MVsH zA>~X2b^GHjXhIGNO>l9Ar7ObEGeVJvEb0*2sl))FQoRM9+|h^3Hfz{McyILxR)sMJ z@85*a0y|9@_1x=i{)pwa*O9M!gWKU)3&#wRTL3m0Eul9SQ;(d1lKpOZ)F=V_*uPUI4Qd6`D<$*62~ z&0}9=Zb*~m-eAxz{xi-VgF9KABh_czrR66unSy>tsphDDQGR!0{AMH?vYhOV literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/script/icon.png b/.cache/brands/integrations/script/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..50b4e38ce3c06395f9ffb65fd70d2d2139755db1 GIT binary patch literal 1805 zcmZ`(2{e>z82)B4laZ@j`!$i$a<58GsHw3O$`TVMYqqNtB1=L|Gi3>t7D{BRZkfgm zSz9clk|fEvm2E6pLP#28EKPHNGnrfW)_30Xe9yZ*?|aUF{x6+x~tn5u87YGD^A^p5zP3txte90T^7sm;^bK zfW`w19?0Pd$rPYY0ooLxi^(*gPXn3|^JV~T1~7yM5&Gnu0!@TM5lDw2Y|ouXNC#4b z++3jogkmC+&E)~e=tBEiDV#3aL5y>P!d|HTJ0ffpi-^eFIH5t)Aro_mh$7JFe>a(5 zKvX8$;r|F_zYTtMMLLjzFe@$)4Hb_TDSwAhqp<6{;QXpT3JL^*MP3QY&?n9ewY9bb zFgOA!fs({5lvyMzr=+ZkU81JGRAbq4%@r$G{jp~4I&B?YJ^hWFHg7R7HZe8ZVQyh* zWkawf?sjx?cJuVwyU)kh&p#kAC^#fMBJ$`l(s9a(lTpzzv2pQd&L<^bx}1`lo|S#= z`mG!)Etj5`UsQ6xth}PK>fxiu)it%x>R&WA{r#q$-O<_G|88Jtcx3d$*eA{emp3&% zGy9qU<>GRj0kkR1%W}I()?i6e1^~$Q<|fAW;ccVr0lQy~l_=wDmVGmu&Y;?+VWURr6dZp z*+=`b49T|>?2Aee#b#37g_HbquEn6xG!2$WjXP|_`Qm=J7?#y>u#ELukis19SgDny zOKPquFkXZ-?riE)>q@)n44X7pF(m5t&DQM;S7zuV?M$;eePYI%tXK=~*fv&tsO?H=mW}KSJ_~e%K|`!oV8q~s zc3t>}S{QYqlbaiEr1no0m`Xp8JH=Qxu_4@cSyjX)Fzq>9wm8hY$c*xrDy7A+i?%{w zLm|7X%{??L^gy_vRjW(-pb(7 z3u@RLRduD^yv{(1dTrOCp#%9rfY;us*r8K~9(>7DH9E+_cAK(80I`3wkxk|R@MVsH zA>~X2b^GHjXhIGNO>l9Ar7ObEGeVJvEb0*2sl))FQoRM9+|h^3Hfz{McyILxR)sMJ z@85*a0y|9@_1x=i{)pwa*O9M!gWKU)3&#wRTL3m0Eul9SQ;(d1lKpOZ)F=V_*uPUI4Qd6`D<$*62~ z&0}9=Zb*~m-eAxz{xi-VgF9KABh_czrR66unSy>tsphDDQGR!0{AMH?vYhOV literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/seventeentrack/dark_icon.png b/.cache/brands/integrations/seventeentrack/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b6754a2281c42bb382b863ff3b9f99496250a1b1 GIT binary patch literal 4868 zcmb_g`#)3vA3vK*uDP`k8Cm64q&`|j+mK5)3Mmr0AjMEVl*u?%hY$b&qNXN>=K%l) zeuV)7{NTrBuN)@;kZdzG#98_d&JC^kSl&o$Su~>uhzVZ$tPc;(zg~dy#vc%P=#~i= zRnE~+a}{|Dm%WpVxj#-Y8b&9ZZUAVuZuKdL*6cTqxy7$N`u-&d_+gM*JPnIe-Fnio zmo4ygIw^^g4jWlrbJOQ}G;dpAALD$*iImD)ivgslg2%Xzq3=KHR6#vP4SirKo>1jV%JSbheBhiQeX>eLBIXEui*K6X0Q4`DdA|bsDh) z3A1f6_8;8>62qDW6-YtwZV!>=QEfn;L}ka29O!g0Be$vady~&#BPt8V1l5&Z z$J|uDZ_70po`!QHJ!amsvs!lEZF$9F3osBBiIYEs7R%mYaTrmZVjT#2M8b0h3w^|s z#o-nS7`pBuX>MdVbA*)d6q5W_nhN*#cnL$0d=!Io(MO%O8b@8A)P5bOck(bo^WayCZs+KlmQ+iV^}?O z43Ql1OUvp*tMS^aYXDm9Hpi+!%j&K>{5Pw12?{f(hGY8iY%*Yh$ae_}L8AGC#=m8X z3Rxbia>$K+?g1kDnP3ktPG$NT#~m$`&u&fjQ`cl^0rGt1gvrDy$J|)5IC+pdnuP>+ zG1A`(%N*;6S=?w(YLX5FcOl9Ny|9DffVY^bQGu320yYyk3Ww^UodtbcZ`LuGx4G)odczDFTDm$G6@X7c?G$o-li z3$zpm)x})<)VGpqy>yr@OtTg1J#oWIN$tJJx$(Xv)o46cuGR}Ko|yV5Cm+e795LFf zow;osZ^IK{Qg8}WJu5RN+!72tEu`|aXI%z-JpwblX7LV4^VwGX;*P*Tw*9X#X&Ine z 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 literal 0 HcmV?d00001 diff --git a/.cache/brands/integrations/waste_collection_schedule/dark_icon.png b/.cache/brands/integrations/waste_collection_schedule/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4db558098e3b358d29787fa846cfd86c17fa5c01 GIT binary patch literal 10835 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 ughGtoWMM|Ih4dP+5}_gf{}oDOsdt}( literal 0 HcmV?d00001 diff --git a/.ha_run.lock b/.ha_run.lock index fcb9b23..3a45f89 100644 --- a/.ha_run.lock +++ b/.ha_run.lock @@ -1 +1 @@ -{"pid": 67, "version": 1, "ha_version": "2026.3.1", "start_ts": 1772875766.7594833} \ No newline at end of file +{"pid": 67, "version": 1, "ha_version": "2026.4.0", "start_ts": 1775105928.9191253} \ No newline at end of file diff --git a/esphome/esp-entrancebathrmlights.yaml b/esphome/esp-entrancebathrmlights.yaml index 0d470e1..196200a 100644 --- a/esphome/esp-entrancebathrmlights.yaml +++ b/esphome/esp-entrancebathrmlights.yaml @@ -6,9 +6,10 @@ # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-entrancebathrmlights.yaml #:########################################################################################:# # VERSIONS: -# v3.8 2026-02-25 Updated yaml to zorruno layout V1.1 -# v3.7 2025-09-34 Upload to this bathroom (as noted in original header) -# v3.5 2025-07-24 YAML tidyups +# V3.9 2026-03-11 Updated yaml to zorruno layout V1.1 +# V3.8 2026-02-25 Updated yaml to zorruno layout V1.1 +# V3.7 2025-09-34 Upload to this bathroom (as noted in original header) +# V3.5 2025-07-24 YAML tidyups #:########################################################################################:# # HARDWARE: # - Zemismart KS-811 Double push button (ESP8266) @@ -33,7 +34,6 @@ # - Accurate time is NOT needed (SNTP not needed). #:########################################################################################:# - #:########################################################################################:# # SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) @@ -47,7 +47,7 @@ substitutions: # Project Naming project_name: "Zemismart Technologies.KS-811 Double" - project_version: "v3.8" + project_version: "v3.9" # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names @@ -144,7 +144,7 @@ logger: status_led: pin: number: GPIO2 - inverted: yes + inverted: true #:########################################################################################:# # BINARY SENSORS @@ -155,7 +155,7 @@ binary_sensor: pin: number: GPIO16 mode: INPUT - inverted: True + inverted: true use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only suppresses a warning. name: "Button 1: ${switch_1_name}" on_press: @@ -163,9 +163,9 @@ binary_sensor: - platform: gpio pin: - number: GPIO05 + number: GPIO5 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - switch.toggle: Relay_2 diff --git a/esphome/esp-entranceoutsideledlights.yaml b/esphome/esp-entranceoutsideledlights.yaml index 7f9f48f..0ae5233 100644 --- a/esphome/esp-entranceoutsideledlights.yaml +++ b/esphome/esp-entranceoutsideledlights.yaml @@ -1,14 +1,19 @@ -########################################################################################## -########################################################################################## -# FRONT ENTRANCEWAY LED LIGHT CONTROLS -# File: esp-entranceoutsideledlights.yaml -# -# v1.0 - 2026-02-23 Initial version (converted from Tasmota) -# -# Hardware: H801 (ESP8266EX) 5-channel PWM MOSFET LED controller -# -########################################################################################### -# NOTES +#:########################################################################################:# +# TITLE: FRONT ENTRANCEWAY LED LIGHT CONTROLS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-entranceoutsideledlights.yaml +#:########################################################################################:# +# VERSIONS: +# V1.2 2026-03-10 Added per-channel maximum ON timers with auto-dim-to-off, restart-on-ON, and moved defaults into substitutions +# V1.1 2026-03-10 Updated yaml to zorruno layout V1.1 +# V1.0 2026-02-23 Initial version (converted from Tasmota) +#:########################################################################################:# +# HARDWARE: +# - H801 (ESP8266EX) 5-channel PWM MOSFET LED controller +#:########################################################################################:# +# OPERATION NOTES: # - H801 PWM outputs (typical / ESPHome Devices): # PWM1 / R -> GPIO15 # PWM2 / G -> GPIO13 @@ -23,43 +28,56 @@ # * Brightness slider 0-100% normalized to the per-channel hard limit # * Ramp time (seconds) for a full 0 -> hard limit transition # * Hard limit (percent) absolute cap for that channel +# * Maximum ON time (minutes) after which the channel dims to OFF +# +# - A fresh ON command restarts the countdown timer for that channel. +# - Setting channel brightness above 0 also restarts that channel timer. # # - Underlying PWM light entities are INTERNAL so HA cannot bypass the hard limit. -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# MQTT COMMANDS: +# - None (no device-specific MQTT commands in this YAML; common_mqtt is included for standardisation) +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Local PWM control continues via HA entities if HA is offline (entities unavailable until HA returns) +# - Device continues running with last commanded PWM states +# - Any already-running max ON timer continues locally on the device +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - No impact unless you rely on MQTT for diagnostics; local control via HA/API continues +# - Any already-running max ON timer continues locally on the device +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT connectivity +# - Outputs remain in their last driven state (until power loss/reboot) +# - Any already-running max ON timer continues locally on the device +# - Accurate time is NOT needed (SNTP not required for operation) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-entranceoutsideledlights" friendly_name: "Front Entranceway LED Light controls" - description_comment: "H801 ESP8266 5-channel PWM LED controller (Entranceway)" + description_comment: "H801 ESP8266 5-channel PWM LED controller (Entranceway) (Layout V1.1)" device_area: "Entranceway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "H801.5CH PWM LED Controller" - project_version: "v1.0" + project_version: "v1.2" # Passwords & Secrets api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-entranceoutsideledlights_ip # unfortunately you can't use substitutions inside secrets names - #mqtt_command_main_topic: !secret mqtt_command_main_topic - #mqtt_status_main_topic: !secret mqtt_status_main_topic # If we are changing IP addresses, you must update the current IP address here, otherwise it remains # Don't forget to switch it back when changed. current_ip_address: ${static_ip_address} - # MQTT LOCAL Controls (optional, kept for consistency with your templates) - #mqtt_local_device_name: "entranceoutsideledlights" - #mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_local_device_name}" - #mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_local_device_name}" - # Device Settings log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE update_interval: "60s" @@ -68,9 +86,28 @@ substitutions: out1_name: "Main Entrance Outside LED Lights" out2_name: "Number 16 LED Light" out3_name: "Spare 3" - out4_name: "Spare 4" + out4_name: "Doorbell Illumination" out5_name: "Spare 5" + # OUTPUT DEFAULT SETTINGS + out1_ramp_default_s: "2.0" + out2_ramp_default_s: "2.0" + out3_ramp_default_s: "2.0" + out4_ramp_default_s: "2.0" + out5_ramp_default_s: "2.0" + + out1_max_limit_default_pct: "100" + out2_max_limit_default_pct: "100" + out3_max_limit_default_pct: "100" + out4_max_limit_default_pct: "100" + out5_max_limit_default_pct: "100" + + out1_max_on_time_default_mins: "240" + out2_max_on_time_default_mins: "240" + out3_max_on_time_default_mins: "10" + out4_max_on_time_default_mins: "4" + out5_max_on_time_default_mins: "10" + # H801 PWM PINS (easy swap here if needed) out1_pwm_pin: "GPIO15" out2_pwm_pin: "GPIO13" @@ -79,10 +116,11 @@ substitutions: out5_pwm_pin: "GPIO4" pwm_frequency: "1000 Hz" -########################################################################################## + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -115,38 +153,43 @@ packages: diag_debug: !include common/include_debug_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -############################################# -# ESPHome -# https://esphome.io/components/esphome.html -############################################# -esphome: - name: ${device_name} - friendly_name: ${friendly_name} - comment: ${description_comment} # appears on the esphome page in HA - min_version: 2025.11.0 - area: ${device_area} - project: - name: ${project_name} - version: ${project_version} -############################################# -# ESP Platform and Framework +#:########################################################################################:# +# ESPHOME: +# https://esphome.io/components/esphome.html +#:########################################################################################:# +esphome: + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # appears on the esphome page in HA + min_version: 2025.11.0 + area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" + + +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp8266.html -############################################# +#:########################################################################################:# esp8266: board: esp01_1m -############################################# -# ESPHome Logging Enable + +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} + level: "${log_level}" baud_rate: 0 # set to 0 for no logging via UART -########################################################################################## -# OUTPUTS (H801 PWM MOSFET CHANNELS) -########################################################################################## + +#:########################################################################################:# +# OUTPUTS: H801 PWM MOSFET CHANNELS +# https://esphome.io/components/output/esp8266_pwm.html +#:########################################################################################:# output: - platform: esp8266_pwm id: out1_pwm @@ -173,9 +216,11 @@ output: pin: ${out5_pwm_pin} frequency: ${pwm_frequency} -########################################################################################## -# INTERNAL LIGHTS (do not expose to HA; use helper entities below) -########################################################################################## + +#:########################################################################################:# +# LIGHTS: Internal raw PWM lights (not exposed to HA) +# https://esphome.io/components/light/monochromatic.html +#:########################################################################################:# light: - platform: monochromatic id: out1_light_raw @@ -212,9 +257,11 @@ light: internal: true restore_mode: RESTORE_DEFAULT_OFF -########################################################################################## -# GLOBALS (store "last non-zero" brightness per channel) -########################################################################################## + +#:########################################################################################:# +# GLOBALS: Store "last non-zero" brightness per channel +# https://esphome.io/components/globals.html +#:########################################################################################:# globals: - id: out1_last_nonzero_pct type: float @@ -241,9 +288,11 @@ globals: restore_value: true initial_value: "100.0" -########################################################################################## -# SCRIPTS (apply normalized brightness + proportional ramping) -########################################################################################## + +#:########################################################################################:# +# SCRIPTS: Apply normalized brightness + proportional ramping + per-channel auto-off timers +# https://esphome.io/components/script.html +#:########################################################################################:# script: ############################################# # OUT1 @@ -319,6 +368,14 @@ script: call.set_transition_length(trans_ms); call.perform(); + - id: out1_auto_off_timer + mode: restart + parameters: + delay_ms: int + then: + - delay: !lambda "return delay_ms;" + - script.execute: out1_turn_off + ############################################# # OUT2 ############################################# @@ -393,6 +450,14 @@ script: call.set_transition_length(trans_ms); call.perform(); + - id: out2_auto_off_timer + mode: restart + parameters: + delay_ms: int + then: + - delay: !lambda "return delay_ms;" + - script.execute: out2_turn_off + ############################################# # OUT3 ############################################# @@ -467,6 +532,14 @@ script: call.set_transition_length(trans_ms); call.perform(); + - id: out3_auto_off_timer + mode: restart + parameters: + delay_ms: int + then: + - delay: !lambda "return delay_ms;" + - script.execute: out3_turn_off + ############################################# # OUT4 ############################################# @@ -541,6 +614,14 @@ script: call.set_transition_length(trans_ms); call.perform(); + - id: out4_auto_off_timer + mode: restart + parameters: + delay_ms: int + then: + - delay: !lambda "return delay_ms;" + - script.execute: out4_turn_off + ############################################# # OUT5 ############################################# @@ -615,9 +696,19 @@ script: call.set_transition_length(trans_ms); call.perform(); -########################################################################################## -# NUMBERS (brightness normalized to limit, plus per-channel ramp and hard limit) -########################################################################################## + - id: out5_auto_off_timer + mode: restart + parameters: + delay_ms: int + then: + - delay: !lambda "return delay_ms;" + - script.execute: out5_turn_off + + +#:########################################################################################:# +# NUMBER: Brightness normalized to limit, plus per-channel ramp, hard limit, and max ON time +# https://esphome.io/components/number/template.html +#:########################################################################################:# number: ############################################# # OUT1 @@ -632,7 +723,7 @@ number: max_value: 30.0 step: 0.1 restore_value: true - initial_value: 2.0 + initial_value: ${out1_ramp_default_s} optimistic: true set_action: - script.execute: out1_apply_target @@ -647,11 +738,24 @@ number: max_value: 100 step: 1 restore_value: true - initial_value: 100 + initial_value: ${out1_max_limit_default_pct} optimistic: true set_action: - script.execute: out1_apply_target + - platform: template + id: out1_auto_off_mins + name: "${out1_name} Max ON Time" + icon: mdi:timer-lock-outline + entity_category: config + unit_of_measurement: "min" + min_value: 1 + max_value: 720 + step: 1 + restore_value: true + initial_value: ${out1_max_on_time_default_mins} + optimistic: true + - platform: template id: out1_brightness_pct name: "${out1_name} Brightness" @@ -667,6 +771,16 @@ number: - lambda: |- if (x > 0.0f) id(out1_last_nonzero_pct) = x; - script.execute: out1_apply_target + - if: + condition: + lambda: |- + return x > 0.0f; + then: + - script.execute: + id: out1_auto_off_timer + delay_ms: !lambda "return (int) (id(out1_auto_off_mins).state * 60000.0f);" + else: + - script.stop: out1_auto_off_timer ############################################# # OUT2 @@ -681,7 +795,7 @@ number: max_value: 30.0 step: 0.1 restore_value: true - initial_value: 2.0 + initial_value: ${out2_ramp_default_s} optimistic: true set_action: - script.execute: out2_apply_target @@ -696,11 +810,24 @@ number: max_value: 100 step: 1 restore_value: true - initial_value: 100 + initial_value: ${out2_max_limit_default_pct} optimistic: true set_action: - script.execute: out2_apply_target + - platform: template + id: out2_auto_off_mins + name: "${out2_name} Max ON Time" + icon: mdi:timer-lock-outline + entity_category: config + unit_of_measurement: "min" + min_value: 1 + max_value: 720 + step: 1 + restore_value: true + initial_value: ${out2_max_on_time_default_mins} + optimistic: true + - platform: template id: out2_brightness_pct name: "${out2_name} Brightness" @@ -716,6 +843,16 @@ number: - lambda: |- if (x > 0.0f) id(out2_last_nonzero_pct) = x; - script.execute: out2_apply_target + - if: + condition: + lambda: |- + return x > 0.0f; + then: + - script.execute: + id: out2_auto_off_timer + delay_ms: !lambda "return (int) (id(out2_auto_off_mins).state * 60000.0f);" + else: + - script.stop: out2_auto_off_timer ############################################# # OUT3 @@ -730,7 +867,7 @@ number: max_value: 30.0 step: 0.1 restore_value: true - initial_value: 2.0 + initial_value: ${out3_ramp_default_s} optimistic: true set_action: - script.execute: out3_apply_target @@ -745,11 +882,24 @@ number: max_value: 100 step: 1 restore_value: true - initial_value: 100 + initial_value: ${out3_max_limit_default_pct} optimistic: true set_action: - script.execute: out3_apply_target + - platform: template + id: out3_auto_off_mins + name: "${out3_name} Max ON Time" + icon: mdi:timer-lock-outline + entity_category: config + unit_of_measurement: "min" + min_value: 1 + max_value: 720 + step: 1 + restore_value: true + initial_value: ${out3_max_on_time_default_mins} + optimistic: true + - platform: template id: out3_brightness_pct name: "${out3_name} Brightness" @@ -765,6 +915,16 @@ number: - lambda: |- if (x > 0.0f) id(out3_last_nonzero_pct) = x; - script.execute: out3_apply_target + - if: + condition: + lambda: |- + return x > 0.0f; + then: + - script.execute: + id: out3_auto_off_timer + delay_ms: !lambda "return (int) (id(out3_auto_off_mins).state * 60000.0f);" + else: + - script.stop: out3_auto_off_timer ############################################# # OUT4 @@ -779,7 +939,7 @@ number: max_value: 30.0 step: 0.1 restore_value: true - initial_value: 2.0 + initial_value: ${out4_ramp_default_s} optimistic: true set_action: - script.execute: out4_apply_target @@ -794,11 +954,24 @@ number: max_value: 100 step: 1 restore_value: true - initial_value: 100 + initial_value: ${out4_max_limit_default_pct} optimistic: true set_action: - script.execute: out4_apply_target + - platform: template + id: out4_auto_off_mins + name: "${out4_name} Max ON Time" + icon: mdi:timer-lock-outline + entity_category: config + unit_of_measurement: "min" + min_value: 1 + max_value: 720 + step: 1 + restore_value: true + initial_value: ${out4_max_on_time_default_mins} + optimistic: true + - platform: template id: out4_brightness_pct name: "${out4_name} Brightness" @@ -814,6 +987,16 @@ number: - lambda: |- if (x > 0.0f) id(out4_last_nonzero_pct) = x; - script.execute: out4_apply_target + - if: + condition: + lambda: |- + return x > 0.0f; + then: + - script.execute: + id: out4_auto_off_timer + delay_ms: !lambda "return (int) (id(out4_auto_off_mins).state * 60000.0f);" + else: + - script.stop: out4_auto_off_timer ############################################# # OUT5 @@ -828,7 +1011,7 @@ number: max_value: 30.0 step: 0.1 restore_value: true - initial_value: 2.0 + initial_value: ${out5_ramp_default_s} optimistic: true set_action: - script.execute: out5_apply_target @@ -843,11 +1026,24 @@ number: max_value: 100 step: 1 restore_value: true - initial_value: 100 + initial_value: ${out5_max_limit_default_pct} optimistic: true set_action: - script.execute: out5_apply_target + - platform: template + id: out5_auto_off_mins + name: "${out5_name} Max ON Time" + icon: mdi:timer-lock-outline + entity_category: config + unit_of_measurement: "min" + min_value: 1 + max_value: 720 + step: 1 + restore_value: true + initial_value: ${out5_max_on_time_default_mins} + optimistic: true + - platform: template id: out5_brightness_pct name: "${out5_name} Brightness" @@ -863,14 +1059,26 @@ number: - lambda: |- if (x > 0.0f) id(out5_last_nonzero_pct) = x; - script.execute: out5_apply_target + - if: + condition: + lambda: |- + return x > 0.0f; + then: + - script.execute: + id: out5_auto_off_timer + delay_ms: !lambda "return (int) (id(out5_auto_off_mins).state * 60000.0f);" + else: + - script.stop: out5_auto_off_timer -########################################################################################## -# SWITCHES (On/Off that respects ramping; brightness slider remains unchanged when off) -########################################################################################## + +#:########################################################################################:# +# SWITCH: On/Off that respects ramping; brightness slider remains unchanged when off +# https://esphome.io/components/switch/template.html +#:########################################################################################:# switch: - platform: template id: out1_switch - name: ${out1_name} + name: "${out1_name}" icon: mdi:lightbulb lambda: |- return id(out1_light_raw).current_values.is_on(); @@ -885,12 +1093,16 @@ switch: value: !lambda "return id(out1_last_nonzero_pct);" else: - script.execute: out1_apply_target + - script.execute: + id: out1_auto_off_timer + delay_ms: !lambda "return (int) (id(out1_auto_off_mins).state * 60000.0f);" turn_off_action: + - script.stop: out1_auto_off_timer - script.execute: out1_turn_off - platform: template id: out2_switch - name: ${out2_name} + name: "${out2_name}" icon: mdi:lightbulb lambda: |- return id(out2_light_raw).current_values.is_on(); @@ -905,12 +1117,16 @@ switch: value: !lambda "return id(out2_last_nonzero_pct);" else: - script.execute: out2_apply_target + - script.execute: + id: out2_auto_off_timer + delay_ms: !lambda "return (int) (id(out2_auto_off_mins).state * 60000.0f);" turn_off_action: + - script.stop: out2_auto_off_timer - script.execute: out2_turn_off - platform: template id: out3_switch - name: ${out3_name} + name: "${out3_name}" icon: mdi:lightbulb lambda: |- return id(out3_light_raw).current_values.is_on(); @@ -925,12 +1141,16 @@ switch: value: !lambda "return id(out3_last_nonzero_pct);" else: - script.execute: out3_apply_target + - script.execute: + id: out3_auto_off_timer + delay_ms: !lambda "return (int) (id(out3_auto_off_mins).state * 60000.0f);" turn_off_action: + - script.stop: out3_auto_off_timer - script.execute: out3_turn_off - platform: template id: out4_switch - name: ${out4_name} + name: "${out4_name}" icon: mdi:lightbulb lambda: |- return id(out4_light_raw).current_values.is_on(); @@ -945,12 +1165,16 @@ switch: value: !lambda "return id(out4_last_nonzero_pct);" else: - script.execute: out4_apply_target + - script.execute: + id: out4_auto_off_timer + delay_ms: !lambda "return (int) (id(out4_auto_off_mins).state * 60000.0f);" turn_off_action: + - script.stop: out4_auto_off_timer - script.execute: out4_turn_off - platform: template id: out5_switch - name: ${out5_name} + name: "${out5_name}" icon: mdi:lightbulb lambda: |- return id(out5_light_raw).current_values.is_on(); @@ -965,5 +1189,9 @@ switch: value: !lambda "return id(out5_last_nonzero_pct);" else: - script.execute: out5_apply_target + - script.execute: + id: out5_auto_off_timer + delay_ms: !lambda "return (int) (id(out5_auto_off_mins).state * 60000.0f);" turn_off_action: + - script.stop: out5_auto_off_timer - script.execute: out5_turn_off \ No newline at end of file diff --git a/esphome/esp-garagebtproxy.yaml b/esphome/esp-garagebtproxy.yaml index f16efed..e38a723 100644 --- a/esphome/esp-garagebtproxy.yaml +++ b/esphome/esp-garagebtproxy.yaml @@ -1,49 +1,66 @@ -############################################# -############################################# -# ESP32 - Garage -# Bluetooth Proxy -############################################# -############################################# +#:########################################################################################:# +# TITLE: GARAGE ENTRANCE BLUETOOTH PROXY +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garagebtproxy.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-03-11 Updated yaml to zorruno layout V1.1 +# V1.0 2025-06-14 Initial Version +#:########################################################################################:# +# HARDWARE: +# - ESP32-WROOM (esp32dev) +# - Bluetooth Proxy (ESPHome bluetooth_proxy + esp32_ble_tracker) +#:########################################################################################:# +# OPERATION NOTES: +# - Provides Bluetooth Proxy coverage at the garage entrance for Home Assistant +# - Uses ESP-IDF framework for BLE stability/performance +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - BLE proxy is unavailable to Home Assistant until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - BLE proxy still works via Home Assistant API +# c) Entire WiFi/Network OFFLINE +# - BLE proxy unavailable until network returns +# - Accurate time is not needed (SNTP not required) +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-garagebtproxy" friendly_name: "Garage Entrance Bluetooth Proxy" - description_comment: "ESP32-WROOM garage entrance with BT Proxy" - device_area: "Garage" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - + description_comment: "ESP32-WROOM garage entrance with BT Proxy (Layout V1.1)" + device_area: "Garage" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + # Project Naming - project_name: "Zemismart Technologies.KS-811-3 (Triple)" # Project Details - project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - #entity_prefix: "Main Bathroom" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. + project_name: "ESPHome.Bluetooth Proxy" + project_version: "v1.1" + + # Passwords & Secrets + api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names + ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + static_ip_address: !secret esp-garagebtproxy_ip # unfortunately you can't use substitutions inside secrets names + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} - # Passwords - api_key: !secret esp-api_key #unfortunately you can't use substitutions in secrets names - ota_pass: !secret esp-ota_pass #unfortunately you can't use substitutions in secrets names - static_ip_address: !secret esp-garagebtproxy_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic - # Device Settings - #relay_icon: "mdi:heating-coil" - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc - ############################################# - # SPECIFIC PROJECT VARIABLE SUBSTITUTIONS - ############################################# - # - # -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -52,6 +69,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -65,69 +83,62 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml - -############################################# -# ESPHome + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + + +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: ${device_name} friendly_name: ${friendly_name} - comment: ${description_comment} #appears on the esphome page in HA - min_version: 2024.6.0 # + comment: ${description_comment} # appears on the esphome page in HA area: ${device_area} + min_version: 2024.6.0 + project: + name: ${project_name} + version: ${project_version} -############################################# -# ESP Platform and Framework + +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# esp32: board: esp32dev framework: #type: arduino - type: esp-idf #Suggested Use ESP-IDF Framework, or Plug Out the UART Cable Might Cause ESP32 Hang. - version: recommended #recommended, latest or dev + type: esp-idf + version: recommended advanced: - minimum_chip_revision: "3.1" # This makes the binary slightly smaller + minimum_chip_revision: "3.1" -############################################# -# ESPHome Logging Enable + +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: ${log_level} -############################################# -# Bluetooth + +#:########################################################################################:# +# BLUETOOTH: # https://esphome.io/components/bluetooth_proxy.html # https://esphome.io/components/esp32_ble_tracker.html -# Remember that this takes a LOT of processing. On the -# ESP32, enable the IDF framework, and disable the -# Web server component. Changing to the IDF framework -# needs to be via cable not OTA to change the -# partition setup. -############################################# +#:########################################################################################:# bluetooth_proxy: active: true esp32_ble_tracker: scan_parameters: - # We currently use the defaults to ensure Bluetooth - # can co-exist with WiFi In the future we may be able to - # enable the built-in coexistence logic in ESP-IDF - active: true - + active: true \ No newline at end of file diff --git a/esphome/esp-garageentrylights.yaml b/esphome/esp-garageentrylights.yaml index 2069b77..9057211 100644 --- a/esphome/esp-garageentrylights.yaml +++ b/esphome/esp-garageentrylights.yaml @@ -1,54 +1,91 @@ -############################################# -############################################# -# GARAGE ENTRY LIGHTSWITCH (OBK Converted, BK7231N) +#:########################################################################################:# +# TITLE: GARAGE ENTRY LIGHTSWITCH (OBK CONVERTED, BK7231N) +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garageentrylights.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V1.0 2025-11-23 Initial -############################################# -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -# -############################################# -############################################# +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Triple push button (OBK converted, BK7231N) +# - ESPHome bk72xx: generic-bk7231n-qfn32-tuya +# - Status LED: P22 +# - Buttons: P17 (Btn1), P26 (Btn2), P24 (Btn3) +# - Relays: P14 (Relay1), P16 (Relay2), P15 (Relay3) +# - Pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - 3 button / 3 relay wall switch +# - Button 1 toggles Relay 1 (Corridor Lights) +# - Button 2 toggles Relay 2 (Patio Lights) +# - Button 3 toggles Relay 3 (Garage Lights) +# - Default relay restore mode is controlled via substitution: relay_restore_mode +# - WiFi package overrides: +# - min_auth_mode removed (WPA2-only not supported on bk72xx) +# - reboot_timeout overridden to 15min +# - fast_connect forced false +# - MQTT keepalive overridden to 15s +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Physical buttons still toggle relays locally +# - MQTT (from common package) continues if broker is reachable +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Physical buttons still toggle relays locally +# - HA/API control remains available (switch entities) +# - MQTT diagnostics/publishes (common_mqtt) will fail while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - Physical buttons still toggle relays locally (standalone operation) +# - No HA API and no MQTT connectivity until network returns +# - Accurate time is not needed (SNTP not required) +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-garageentrylights" friendly_name: "Garage Entry Lightswitch (3)" - description_comment: "BK7231N - Garage Entry Lightswitch using a Zemismart KS-811 Triple Push Button. Corridor Light (1), Patio Lights (2), Garage Lights (3)" - device_area: "Garage" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - - # Project Naming - project_name: "Zemismart Technologies.KS-811 Triple BK7231N" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + description_comment: "BK7231N - Garage Entry Lightswitch using a Zemismart KS-811 Triple Push Button. Corridor Light (1), Patio Lights (2), Garage Lights (3) (Layout V1.1)" + device_area: "Garage" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - # Passwords + # Project Naming + project_name: "Zemismart Technologies.KS-811 Triple BK7231N" + project_version: "v1.1" + + # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-garageentrylights_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # Default relay restore mode # Options: RESTORE_DEFAULT_OFF, RESTORE_DEFAULT_ON, ALWAYS_ON, ALWAYS_OFF relay_restore_mode: "RESTORE_DEFAULT_OFF" - - # Switch Naming - switch_1_name: "Corridor Lights" # Only one light (Garage Side) actually connected to this relay - switch_2_name: "Patio Lights" # Output for pario string hanging lights - switch_3_name: "Garage Lights" # This is virtual only, no power connected to 3rd relay -########################################################################################## + # Switch Naming + switch_1_name: "Corridor Lights" # Only one light (Garage Side) actually connected to this relay + switch_2_name: "Patio Lights" # Output for patio string hanging lights + switch_3_name: "Garage Lights" # This is virtual only, no power connected to 3rd relay + + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -57,6 +94,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -70,86 +108,75 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml - #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - #diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + #diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -# Package item removals + +#:########################################################################################:# +# PACKAGE OVERRIDES: +# These override or remove items from included packages above +#:########################################################################################:# wifi: - min_auth_mode: !remove # The WPA2 only works on esp32/8266 - reboot_timeout: 15min # override the selection from from the common package - fast_connect: false # (optional) force off, in case package vars change + min_auth_mode: !remove # The WPA2-only mode works on esp32/esp8266, not bk72xx + reboot_timeout: 15min # override selection from common package + fast_connect: false # force off, in case package vars change mqtt: - keepalive: 15s # overriding the value from the common package + keepalive: 15s # override value from common package -############################################# -# ESPHome + +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" # Appears on the ESPHome page in HA area: "${device_area}" project: name: "${project_name}" version: "${project_version}" -# on_boot: -# priority: 200 -# then: -# - switch.turn_on: Relay_3 mdns: disabled: true -############################################# -# BUILD FOR BK CHIPSET -# bk72xx + +#:########################################################################################:# +# BK72XX: # https://devices.esphome.io/board/bk72xx/ -############################################# +#:########################################################################################:# bk72xx: board: generic-bk7231n-qfn32-tuya -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# -#esp8266: -# board: esp01_1m -# early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. -# board_flash_mode: dout # Default is dout -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" id: logger_id -############################################# -# STATUS LED + +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -############################################# +#:########################################################################################:# status_led: pin: - number: P22 #GPIO22 + number: P22 inverted: true -############################################# -# BINARY SENSORS + +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -############################################# +#:########################################################################################:# binary_sensor: - platform: gpio pin: @@ -172,8 +199,8 @@ binary_sensor: inverted: true name: "Button 2: ${switch_2_name}" on_press: - - delay: 50ms - - switch.toggle: Relay_2 + - delay: 50ms + - switch.toggle: Relay_2 - platform: gpio pin: @@ -184,26 +211,29 @@ binary_sensor: inverted: true name: "Button 3: ${switch_3_name}" on_press: - - delay: 50ms - - switch.toggle: Relay_3 + - delay: 50ms + - switch.toggle: Relay_3 -############################################# -# SWITCH COMPONENT + +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -############################################# +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" - pin: P14 #GPIO14 + pin: P14 id: Relay_1 restore_mode: ${relay_restore_mode} + - platform: gpio name: "Relay 2: ${switch_2_name}" - pin: P16 #GPIO16 + pin: P16 id: Relay_2 restore_mode: ${relay_restore_mode} + - platform: gpio name: "Relay 3: ${switch_3_name}" - pin: P15 #GPIO15 + pin: P15 id: Relay_3 restore_mode: ${relay_restore_mode} \ No newline at end of file diff --git a/esphome/esp-garageextcornerlight.yaml b/esphome/esp-garageextcornerlight.yaml index f90950c..fb96233 100644 --- a/esphome/esp-garageextcornerlight.yaml +++ b/esphome/esp-garageextcornerlight.yaml @@ -1,54 +1,90 @@ -############################################# -############################################# -# GARAGE LIGHTS -# Controlled by a Sonoff Basic R1 -# +#:########################################################################################:# +# TITLE: GARAGE EXTERNAL CORNER LIGHT +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garageextcornerlight.yaml +#:########################################################################################:# +# VERSIONS: +# V2.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.0 2025-10-22 Latest layout with home MQTT code # V1.0 2025-10-22 Initial Version -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# - Sonoff Basic R1 (ESP8266) +# - Relay: GPIO12 +# - Button: GPIO03 +# - Status LED: GPIO13 (inverted) +#:########################################################################################:# +# OPERATION NOTES: +# - Local button toggles the relay output +# - MQTT control: +# - Command topic: ${mqtt_command_topic} +# Payload: "ON" / "OFF" +# - Status topic: ${mqtt_status_topic} +# Payload: "ON" / "OFF" +# - On MQTT connect, publishes current relay state to the status topic +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Local button still works +# - MQTT commands still work +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Local button still works +# - HA/API control still works +# - MQTT commands will not work while broker is down +# c) Entire WiFi/Network OFFLINE +# - Local button still works +# - No HA/API and no MQTT control until network returns +# - Accurate time is not needed (SNTP not required) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Custom Naming device_name: "esp-garageextcornerlight" friendly_name: "Garage External Corner Light" - description_comment: "Garage External Corner Light :: Sonoff Basic" + description_comment: "Garage External Corner Light :: Sonoff Basic (Layout V1.1)" device_area: "Garage" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. static_ip_address: !secret esp-garageextcornerlight_ip mqtt_device_name: "garage-externalcorner-light" # Project Naming - project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details - project_version: "v2.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - # Passwords + project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details + project_version: "v2.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + + # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings relay_icon: "mdi:lightbulb" - log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + log_level: "ERROR" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc - # Device Naming + # I/O Naming relay_1_name: "Garage External Light" button_1_name: "Power Button" # MQTT Controls - mqtt_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" + mqtt_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" mqtt_status_topic: "${mqtt_status_main_topic}/${mqtt_device_name}" -########################################################################################## + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -57,6 +93,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -70,80 +107,85 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -########################################################################################## -# ESPHome + +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" # Appears on the ESPHome page in HA area: "${device_area}" -# platformio_options: -# build_flags: -# - "-Os" # optimize for size -# - "-Wl,--gc-sections" # drop unused code/data -# - "-fno-exceptions" # strip C++ exceptions -# - "-fno-rtti" # strip C++ RTTI -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## + +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: - board: esp01_1m # The original sonoff basic - restore_from_flash: True # restore some values on reboot + board: esp01_1m # The original Sonoff Basic + restore_from_flash: true # restore some values on reboot + +#:########################################################################################:# +# PREFERENCES: +# https://esphome.io/components/preferences.html +#:########################################################################################:# preferences: flash_write_interval: 5min + +#:########################################################################################:# +# MDNS: +# https://esphome.io/components/mdns.html +#:########################################################################################:# mdns: - disabled: False + disabled: false -########################################################################################## -# ESPHome Logging Enable + +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing + level: "${log_level}" baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 -########################################################################################## -# SWITCH COMPONENT + +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## -# Sonoff Basic R1 Relay Switch is GPIO12 -############################################# +# Sonoff Basic R1 relay is GPIO12 +#:########################################################################################:# switch: - platform: gpio name: "${relay_1_name}" pin: GPIO12 id: relay1 restore_mode: RESTORE_DEFAULT_OFF - icon: "${relay_icon}" + icon: "${relay_icon}" -########################################################################################## -# BINARY SENSORS + +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## -# Sonoff Basic R1 Button is GPIO03 -############################################# +# Sonoff Basic R1 button is GPIO03 +#:########################################################################################:# binary_sensor: - # Actual button input - platform: gpio pin: @@ -166,8 +208,8 @@ binary_sensor: // Relay is OFF: turn it ON id(relay1).turn_on(); } - - # Mimics actual relay status + + # Mimics actual relay status (publishes MQTT state) - platform: template name: "${relay_1_name} Status" lambda: |- @@ -175,34 +217,30 @@ binary_sensor: on_press: - mqtt.publish: topic: "${mqtt_status_topic}" - payload: "ON" + payload: "ON" on_release: - mqtt.publish: topic: "${mqtt_status_topic}" - payload: "OFF" - -########################################################################################## -# STATUS LED + payload: "OFF" + + +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -########################################################################################## -# Sonoff Basic R1 LED is GPIO13 -########################################################################################## +# Sonoff Basic R1 LED is GPIO13 +#:########################################################################################:# status_led: pin: number: GPIO13 - inverted: yes + inverted: true -########################################################################################## -# MQTT COMMANDS -# This adds device-specific MQTT command triggers to the common MQTT configuration. -# Requires you to define: -# substitutions: -# mqtt_command_topic: "" -# mqtt_state_topic: "" -########################################################################################## + +#:########################################################################################:# +# MQTT: Device-specific command triggers +#:########################################################################################:# mqtt: on_message: - # Relay 1 control (only act and publish if a change is needed) + # Relay control (only act and publish if a change is needed) - topic: "${mqtt_command_topic}" payload: "ON" then: @@ -215,7 +253,6 @@ mqtt: - mqtt.publish: topic: "${mqtt_status_topic}" payload: "ON" - #retain: true - topic: "${mqtt_command_topic}" payload: "OFF" @@ -229,7 +266,6 @@ mqtt: - mqtt.publish: topic: "${mqtt_status_topic}" payload: "OFF" - #retain: true # Announce current state whenever MQTT (re)connects on_connect: @@ -237,4 +273,3 @@ mqtt: - mqtt.publish: topic: "${mqtt_status_topic}" payload: !lambda 'return id(relay1).state ? "ON" : "OFF";' - #retain: true diff --git a/esphome/esp-gasheater.yaml b/esphome/esp-gasheater.yaml index 48ec717..61ee0e3 100644 --- a/esphome/esp-gasheater.yaml +++ b/esphome/esp-gasheater.yaml @@ -1,116 +1,160 @@ -########################################################################################## -########################################################################################## -# RINNAI NEO - GAS HEATER CONTROLLER (BUTTON PRESS VIA RELAYS) +#:########################################################################################:# +# TITLE: +# RINNAI NEO GAS HEATER CONTROLLER +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-gasheater.yaml +#:########################################################################################:# +# VERSIONS: +# V1.7 2026-03-26 Added Heater Operation switch; MQTT status now mirrors the Status Text +# entity; preserved Test Mode AUTO test temperature and visible 6-step calibration +# V1.6 2026-03-22 Added richer status text: At Temperature, Operating (Level X), +# Calibrating, and Fault (Room Temperature Lost) +# V1.5 2026-03-22 Added Test Temperature Value slider for Test Mode AUTO; status text +# shows Test Mode state; temperature units set to °C +# V1.4 2026-03-22 Updated yaml to zorruno layout V1.1; boot into BYPASS (Remote Only); +# renamed remote-only mode; refined Test Mode to click real power relay; +# added setpoint text and setpoint up/down buttons +# V1.3 2026-03-22 Refined Test Mode so power relay still clicks; added setpoint text plus +# setpoint up/down buttons; Test Mode can now be used for MANUAL or AUTO testing +# V1.2 2026-03-22 Added Test Mode bench testing override +# V1.1 2026-03-22 Updated yaml to zorruno layout V1.1; forced AUTO on reboot; initialized +# stale-temp timer at boot; cleared Remote Control Only self-power flag +# V1.0 2025-07-21 First setup (replacement of Tasmota) +#:########################################################################################:# +# HARDWARE: +# - Sonoff DEV (ESP8266) +# - 3-relay daughterboard +# - Rinnai Neo gas heater +# - Relay outputs: +# - GPIO12 = ON/OFF button press +# - GPIO13 = Flame UP button press +# - GPIO14 = Flame DOWN button press +# - LED inputs: +# - GPIO4 = Red standby LED +# - GPIO5 = Blue operating LED +#:########################################################################################:# +# OPERATION NOTES: +# - Replaces the RF remote by pressing the heater panel buttons via relays. +# - Heater manages its own ignition, flame safety, and fan control. +# - AUTO mode uses: +# - Local HA setpoint number entity +# - External room temperature via MQTT +# - In Test Mode, AUTO uses the local Test Temperature Value slider instead of MQTT room +# temperature. +# - Setpoint is locally adjustable and also supports two-way MQTT sync. +# - Manual flame control is available via: +# - Flame Level select (1..7) +# - Flame Up step button +# - Flame Down step button +# - Setpoint helper entities are available via: +# - Setpoint Text +# - Setpoint Up (+0.5 °C) +# - Setpoint Down (-0.5 °C) +# - Test Mode is for bench testing before connection to the heater: +# - Forces Mode to MANUAL when enabled +# - Uses an internal powered flag instead of LED monitoring +# - Still clicks the real power relay when Power is turned ON or OFF +# - AUTO may still be selected manually later for testing +# - Heater Operation is a high-level thermostat enable helper: +# - ON = turn Test Mode OFF (if needed) and set Mode to AUTO +# - OFF = turn heater Power OFF and set Mode to BYPASS (Remote Only) +# - On normal ESPHome startup, Mode defaults to BYPASS (Remote Only). +# - On power ON in AUTO, the controller: +# - Applies a warmup lockout +# - Calibrates to level 1 using 6x DOWN +# - Begins auto level adjustment +# - If the heater is turned on externally while in AUTO, the controller will re-baseline +# after warmup and resume automatic control. +# - Fast-ramp mode allows faster flame stepping for a short period after turn-on. +#:########################################################################################:# +# MQTT COMMANDS: +# - Room temperature input: +# viewroad-status/lounge-environment/temperature +# - Setpoint input/output: +# viewroad-status/lounge-environment/temp-setpoint +# - Heater operating status output: +# viewroad-status/lounge-gasheater +#:########################################################################################:# +# OFFLINE NOTES: +# a) HA offline, WiFi/MQTT online: +# - Device continues to operate normally. +# - AUTO control still works if room temperature MQTT is still being published. +# - Setpoint can still be changed via MQTT. # -# Device: Sonoff DEV (ESP8266) + 3-Relay daughterboard -# Project: esp-gasheater Friendly Name: "Rinnai Neo Gas Heater" +# b) MQTT offline (or HA and MQTT offline): +# - No fresh room temperature or setpoint updates are received. +# - Device retains the last local setpoint. +# - If AUTO is active and temperature data becomes stale, the heater will turn OFF after +# temp_stale_timeout_min as a fail-safe. +# - Manual mode and flame tracking still work locally inside the ESP device logic. # -# Purpose: -# - Replace RF remote. Press panel buttons with relays: -# ON/OFF = GPIO12 Flame UP = GPIO13 Flame DOWN = GPIO14 -# - Sense panel LEDs as inputs: -# RED Standby = GPIO4 BLUE Operating = GPIO5 -# - AUTO thermostat uses local setpoint entity (adjustable in HA) and room temp via MQTT. -# Setpoint also listens to MQTT and will adopt an external value when published. -# - MANUAL override with level select and step UP/DOWN buttons. -# - On power ON or boot (if already powered), wait warmup then force level 1 (7x DOWN). -# - Publish status text to /viewroad-status/gasfire -> "Operating" | "Standby" | "Off" -# -# Notes: -# - Heater manages safety, ignition and fan. We only press buttons and watch LEDs. -# - LEDs pull to 0V when ON. Inputs default to inverted=true. Flip if your Tasmota shows -# opposite logic. Pull-ups enabled on inputs. -# - To reduce click noise: press pulses are short and spaced; optional min on/off timers. -########################################################################################## -########################################################################################## -# V1.0 - 2025-07-21 First Setup (and replacement of Tasmota) -# -# NOTES: -# Command the fan with MQTT -# ${mqtt_local_command_full_topic}/speed/set 1,2,3,0,+,- -# ${mqtt_local_command_full_topic}/light/set ON,OFF -# Status of the fan is in MQTT -# ${mqtt_local_command_full_topic}/speed/state 1,2,3,0 -# ${mqtt_local_command_full_topic}/light/state ON,OFF -# -########################################################################################## -########################################################################################## +# c) Entire WiFi/Network offline: +# - No MQTT temperature or setpoint updates are available. +# - Accurate time is not needed. SNTP is not required for this device. +# - If AUTO is active and the heater is ON, stale temperature fail-safe will turn it OFF +# after the configured timeout. +# - Existing heater safety systems still operate normally. +#:########################################################################################:# ########################################################################################## # SPECIFIC DEVICE VARIABLE SUBSTITUTIONS -# If NOT using a secrets file, just replace these with the passwords etc (in quotes) ########################################################################################## substitutions: # Device Naming device_name: "esp-gasheater" friendly_name: "Rinnai Neo Gas Heater" description_comment: "7 Setting controller for Rinnai Neo Gas heater :: Sonoff DEV + Relay Board" - device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + device_area: "Lounge" # Project Naming - project_name: "Sonoff Technologies.Sonoff DEV" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) + project_name: "Sonoff Technologies.Sonoff DEV" + project_version: "v1.7" + + # Passwords & Secrets api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-gasheater_ip - mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic - + current_ip_address: ${static_ip_address} + mqtt_local_command_main_topic: !secret mqtt_command_main_topic + mqtt_local_status_main_topic: !secret mqtt_status_main_topic + # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - - # MQTT LOCAL Controls - #mqtt_device_name: "bedroom3-ceilingfan" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - - # MQTT REMOTE Controls - - # Button Naming & Icons - - # Switch/Relay Naming & Icons - #relay_icon: "mdi:lightbulb-group" - #light_1_name: "Fan Light" - #switch_2_name: "Fan 2 Relay" - #switch_3_name: "Fan 3 Relay" - #switch_4_name: "Fan 4 Relay" + log_level: "INFO" + update_interval: "60s" ######################################################################################## - # TIMING TUNABLES (string values as required by substitutions) + # TIMING TUNABLES ######################################################################################## - relay_pulse_ms: "250" # length of each "button press" - min_click_gap_ms: "1200" # minimum gap between any two clicks - warmup_seconds: "60" # wait after ON before calibration/stepping - control_interval_s: "30" # AUTO control loop cadence - adjust_step_interval_s: "30" # gap between level steps in AUTO - recalibrate_interval_min: "180" # while at level 1, re-baseline every X min - temp_stale_timeout_min: "20" # turn OFF if no valid temp for this long (AUTO only) - fast_ramp_seconds: "180" # fast stepping window after turn-on - fast_ramp_step_s: "8" # step every 8s during fast-ramp - + relay_pulse_ms: "250" + min_click_gap_ms: "1200" + warmup_seconds: "30" + control_interval_s: "10" + adjust_step_interval_s: "10" + recalibrate_interval_min: "180" + temp_stale_timeout_min: "20" + fast_ramp_seconds: "240" + fast_ramp_step_s: "4" # Optional anti short-cycle (set to "0" to disable either one) - min_on_minutes: "5" - min_off_minutes: "5" + min_on_minutes: "1" + min_off_minutes: "0.5" ######################################################################################## # ELECTRICAL POLARITY ######################################################################################## - relay_inverted: "true" # many relay boards are active-low - red_led_inverted: "true" # LEDs pull to 0V when ON -> invert input + relay_inverted: "true" + red_led_inverted: "true" blue_led_inverted: "true" ######################################################################################## - # THERMOSTAT HYSTERESIS (in C) + # THERMOSTAT HYSTERESIS (°C) ######################################################################################## - on_below_c: "0.5" # turn ON when temp <= setpoint - on_below_c - off_above_c: "0.3" # turn OFF when temp >= setpoint + off_above_c + on_below_c: "0.2" + off_above_c: "0.3" ######################################################################################## - # SETPOINT LIMITS FOR HA NUMBER (in C) + # SETPOINT LIMITS FOR HA NUMBER (°C) ######################################################################################## setpoint_min_c: "6.0" setpoint_max_c: "32.0" @@ -118,7 +162,6 @@ substitutions: ########################################################################################## # PACKAGES: Included Common Packages -# https://esphome.io/components/packages.html ########################################################################################## packages: common_wifi: !include @@ -126,19 +169,22 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" + common_api: !include file: common/api_common.yaml vars: local_api_key: "${api_key}" - #common_webportal: !include - # file: common/webportal_common.yaml + common_mqtt: !include file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" + common_sntp: !include file: common/sntp_common.yaml + common_general_sensors: !include file: common/sensors_common.yaml vars: @@ -146,28 +192,26 @@ packages: local_update_interval: "${update_interval}" ########################################################################################## -# ESPHome -# https://esphome.io/components/esphome.html +# ESPHOME ########################################################################################## esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" - # On boot: if heater is already powered, warm up then calibrate to level 1. - # This protects against unknown state after power outages. + on_boot: priority: -100 then: - script.execute: recompute_powered_state - lambda: |- - // Initialize min on/off timers according to current state if (id(powered_state).state) { if (id(last_on_ms) == 0) id(last_on_ms) = millis(); } else { if (id(last_off_ms) == 0) id(last_off_ms) = millis(); } - // Suppress level adjustments during boot warmup window + + id(last_temp_ms) = millis(); id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); - delay: ${warmup_seconds}s - if: @@ -176,149 +220,133 @@ esphome: then: - if: condition: - lambda: 'return id(mode_select).state != "Remote Control Only";' + lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' then: - logger.log: "Boot: heater already powered. Calibrating to level 1." - script.execute: calibrate_to_min else: - - logger.log: "Boot: heater already powered. Remote Control Only -> skipping calibration." - -# platformio_options: -# build_flags: -# - "-Os" -# - "-Wl,--gc-sections" -# - "-fno-exceptions" -# - "-fno-rtti" - - + - logger.log: "Boot: heater already powered. BYPASS (Remote Only) -> skipping calibration." ########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html +# ESP PLATFORM ########################################################################################## esp8266: - board: esp01_1m # The original sonoff basic - restore_from_flash: true # restore some values on reboot + board: esp01_1m + restore_from_flash: true preferences: flash_write_interval: 5min mdns: - disabled: false # Disabling will make the build file smaller (and it is still available via static IP) + disabled: false ########################################################################################## -# Global Variables for use in automations etc -# https://esphome.io/guides/automations.html?highlight=globals#global-variables +# GLOBAL VARIABLES ########################################################################################## globals: - # Current flame level we believe the heater is at (1..7). Kept across reboots. - id: current_level type: int restore_value: yes initial_value: "1" - # Target flame level we want to reach (set by AUTO or manual selection). Not persisted. - id: desired_level type: int restore_value: no initial_value: "1" - # Timestamp (ms since boot) of the last level step (up/down). Used for rate limiting. - id: last_adjust_ms type: uint32_t restore_value: no initial_value: "0" - # Timestamp (ms) of the last calibration-to-min action. Used for periodic re-baseline. - id: last_recal_ms type: uint32_t restore_value: no initial_value: "0" - # Timestamp (ms) when powered_state last went ON. Used to enforce min_on_minutes. - id: last_on_ms type: uint32_t restore_value: no initial_value: "0" - # Timestamp (ms) when powered_state last went OFF. Used to enforce min_off_minutes. - id: last_off_ms type: uint32_t restore_value: no initial_value: "0" - # Local thermostat setpoint (°C). This is the authority; mirrored to MQTT with guard. - id: setpoint_c type: float restore_value: yes initial_value: "21.0" - # Guard to avoid MQTT echo: true while applying a setpoint that came from MQTT. - id: sp_suppress_mqtt type: bool restore_value: no initial_value: "false" - # Timestamp (ms) of last received room temperature via MQTT. Detects stale sensor. - id: last_temp_ms type: uint32_t restore_value: no initial_value: "0" - # Until this ms timestamp we suppress any level changes (post-ON warmup window). - id: warmup_until_ms type: uint32_t restore_value: no initial_value: "0" - # The level chosen on the previous AUTO tick. Used to confirm stable targets. - id: last_level_target type: int restore_value: no initial_value: "1" - # True if desired_level matched last_level_target on consecutive ticks. - id: target_confirmed type: bool restore_value: no initial_value: "true" - # End of the fast-ramp window (ms since boot). Allows faster stepping right after ON. - id: ramp_until_ms type: uint32_t restore_value: no initial_value: "0" - # True when we initiated power ON ourselves (not RF/panel). Helps skip duplicate actions. - id: self_power_on type: bool restore_value: no initial_value: "false" -########################################################################################## -# ESPHome Logging Enable -# https://esphome.io/components/logger.html + # Bench-test logical power state used only when Test Mode is enabled + - id: test_powered + type: bool + restore_value: no + initial_value: "false" + + # Bench-test room temperature used only when Test Mode is enabled + - id: test_temp_c + type: float + restore_value: yes + initial_value: "20.0" + + # True while a calibration sequence is actively stepping down to level 1 + - id: calibrating + type: bool + restore_value: no + initial_value: "false" + + # True when remote MQTT room temperature has gone stale in normal (non-test) mode + - id: room_temp_lost_fault + type: bool + restore_value: no + initial_value: "false" + +########################################################################################## +# ESPHOME LOGGING ENABLE ########################################################################################## logger: - level: "${log_level}" # INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 ########################################################################################## # BINARY SENSORS -# https://esphome.io/components/binary_sensor/ -########################################################################################## -# GPIO MAP (PHYSICAL) -# -# INPUTS: -# GPIO4 -> RED Standby LED (binary_sensor.led_standby_red) -# GPIO5 -> BLUE Operating LED (binary_sensor.led_operating_blue) -# -# OUTPUTS (RELAY COILS - INTERNAL): -# GPIO12 -> ON/OFF button (switch.sw_power_raw) -# GPIO13 -> Flame UP button (switch.sw_up_raw) -# GPIO14 -> Flame DOWN button (switch.sw_down_raw) ########################################################################################## binary_sensor: - platform: gpio @@ -334,7 +362,6 @@ binary_sensor: - delayed_on_off: 50ms entity_category: diagnostic on_state: - - script.execute: publish_status - script.execute: recompute_powered_state - platform: gpio @@ -350,46 +377,37 @@ binary_sensor: - delayed_on_off: 50ms entity_category: diagnostic on_state: - - script.execute: publish_status - script.execute: recompute_powered_state - # Derived powered state (any LED on). Internal helper for min on/off timing. - # NOTE: No lambda or update_interval here — state is pushed by a script. - platform: template id: powered_state internal: true on_press: - lambda: |- id(last_on_ms) = millis(); - // If AUTO, enforce warmup lockout on RF/panel ON too - if (id(mode_select).state == "AUTO") { + if (!id(test_mode_enabled).state && id(mode_select).state == "AUTO") { id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); } - # If heater was powered ON externally (RF/panel) while in AUTO, baseline after warmup - if: condition: - lambda: 'return (id(mode_select).state == "AUTO") && (!id(self_power_on));' + lambda: 'return !id(test_mode_enabled).state && (id(mode_select).state == "AUTO") && (!id(self_power_on));' then: - lambda: |- - // Start fast-ramp window as well id(ramp_until_ms) = millis() + (${fast_ramp_seconds} * 1000UL); - delay: ${warmup_seconds}s - script.execute: calibrate_to_min - script.execute: auto_control_tick - script.execute: adjust_to_desired + on_release: - lambda: |- id(last_off_ms) = millis(); - // Clear self-power flag on any OFF edge so the next RF ON is recognized id(self_power_on) = false; - ########################################################################################## # SWITCH COMPONENT -# https://esphome.io/components/switch/ ########################################################################################## switch: - # Raw coils (do not expose these) - platform: gpio id: sw_power_raw internal: true @@ -414,66 +432,129 @@ switch: number: GPIO14 inverted: ${relay_inverted} - # Power as a logical switch (we press ON/OFF only if a change is needed). + - platform: template + id: test_mode_enabled + name: "${friendly_name} Test Mode" + icon: mdi:test-tube + optimistic: true + restore_mode: ALWAYS_OFF + turn_on_action: + - lambda: |- + // Preserve current logical power state when entering Test Mode + id(test_powered) = id(powered_state).state; + id(room_temp_lost_fault) = false; + - select.set: + id: mode_select + option: "MANUAL" + - script.execute: recompute_powered_state + turn_off_action: + - lambda: |- + id(test_powered) = false; + - script.execute: recompute_powered_state + + # High-level thermostat enable helper. + # ON = thermostat logic active in AUTO + # OFF = force BYPASS and turn heater power OFF + - platform: template + id: heater_operation_switch + name: "Heater Operation" + icon: mdi:radiator + lambda: |- + return id(mode_select).state == "AUTO"; + + turn_on_action: + - select.set: + id: mode_select + option: "AUTO" + + turn_off_action: + - switch.turn_off: power_switch + - select.set: + id: mode_select + option: "BYPASS (Remote Only)" + - platform: template id: power_switch name: "${friendly_name} Power" icon: mdi:power lambda: |- - return (id(led_operating_blue).state || id(led_standby_red).state); + return id(powered_state).state; turn_on_action: - if: condition: - lambda: |- - return !(id(led_operating_blue).state || id(led_standby_red).state); + lambda: 'return id(mode_select).state == "BYPASS (Remote Only)" && !id(test_mode_enabled).state;' then: - - script.execute: press_power - - script.execute: after_power_on_reset_to_auto + - logger.log: "BYPASS (Remote Only): ignoring Power ON." + else: + - if: + condition: + lambda: |- + return !id(powered_state).state; + then: + - script.execute: press_power + - if: + condition: + lambda: 'return id(test_mode_enabled).state;' + then: + - lambda: |- + id(test_powered) = true; + - script.execute: recompute_powered_state + - script.execute: after_power_on_reset_to_auto + turn_off_action: - if: condition: - lambda: |- - return (id(led_operating_blue).state || id(led_standby_red).state); + lambda: 'return id(mode_select).state == "BYPASS (Remote Only)" && !id(test_mode_enabled).state;' then: - - script.execute: press_power + - logger.log: "BYPASS (Remote Only): ignoring Power OFF." + else: + - if: + condition: + lambda: |- + return id(powered_state).state; + then: + - script.execute: press_power + - if: + condition: + lambda: 'return id(test_mode_enabled).state;' + then: + - lambda: |- + id(test_powered) = false; + - script.execute: recompute_powered_state ########################################################################################## -# Sensors -# https://esphome.io/components/sensor/index.html +# SENSORS ########################################################################################## -# MQTT I/O (ROOM TEMP IN, SETPOINT IN/OUT, STATUS TEXT OUT) sensor: - platform: mqtt_subscribe id: room_temp name: "${friendly_name} Room Temperature (MQTT)" - topic: /viewroad-status/lounge-environment/temperature - unit_of_measurement: "C" + topic: "viewroad-status/lounge-environment/temperature" + unit_of_measurement: "°C" accuracy_decimals: 1 on_value: - lambda: |- id(last_temp_ms) = millis(); + id(room_temp_lost_fault) = false; float v = x; if (v < -10.0f) v = -10.0f; if (v > 50.0f) v = 50.0f; if (v != id(room_temp).state) id(room_temp).publish_state(v); - # Setpoint mirror from MQTT -> adopt into local number without echoing back - platform: mqtt_subscribe id: setpoint_from_mqtt internal: true - topic: /viewroad-status/lounge-environment/temp-setpoint - unit_of_measurement: "C" + topic: "viewroad-command/lounge-gasheater/setpoint" + unit_of_measurement: "°C" accuracy_decimals: 1 on_value: - lambda: |- - // Clamp to substitution-defined range float v = x; const float vmin = ${setpoint_min_c}; const float vmax = ${setpoint_max_c}; if (v < vmin) v = vmin; if (v > vmax) v = vmax; - // Guard: applying an MQTT-driven update -> do not re-publish id(sp_suppress_mqtt) = true; id(setpoint_c) = v; - number.set: @@ -482,10 +563,8 @@ sensor: - lambda: |- id(sp_suppress_mqtt) = false; - ########################################################################################## # TEXT SENSOR COMPONENT -# https://esphome.io/components/text_sensor/index.html ########################################################################################## text_sensor: - platform: template @@ -493,25 +572,103 @@ text_sensor: name: "${friendly_name} Status Text" update_interval: 1s lambda: |- - if (id(led_operating_blue).state) return std::string("Operating"); - if (id(led_standby_red).state) return std::string("Standby"); + const bool use_test_temp = id(test_mode_enabled).state; + const float effective_t = use_test_temp ? id(test_temp_c) : id(room_temp).state; + const float at_temp_threshold = id(setpoint_c) + ${off_above_c}; + const std::string mode = id(mode_select).state; + + if (!use_test_temp && id(room_temp_lost_fault)) { + return std::string("Fault (Room Temperature Lost)"); + } + + if (id(calibrating)) { + if (use_test_temp) return std::string("Calibrating (Test)"); + return std::string("Calibrating"); + } + + if (use_test_temp) { + if (mode == "MANUAL") { + if (id(powered_state).state) { + char buf[48]; + snprintf(buf, sizeof(buf), "Manual (Level %d) (Test)", id(current_level)); + return std::string(buf); + } + if (id(led_standby_red).state) return std::string("Manual (Standby) (Test)"); + return std::string("Manual (Off) (Test)"); + } + + if (id(powered_state).state) { + char buf[40]; + snprintf(buf, sizeof(buf), "Operating (Level %d) (Test)", id(current_level)); + return std::string(buf); + } + if (mode == "AUTO" && !isnan(effective_t) && effective_t >= at_temp_threshold) { + return std::string("At Temperature (Test)"); + } + return std::string("Off (Test)"); + } + + if (mode == "BYPASS (Remote Only)") { + if (id(led_operating_blue).state) return std::string("Remote Only (Operating)"); + if (id(led_standby_red).state) return std::string("Remote Only (Standby)"); + return std::string("Remote Only (Off)"); + } + + if (mode == "MANUAL") { + if (id(led_operating_blue).state) { + char buf[32]; + snprintf(buf, sizeof(buf), "Manual (Level %d)", id(current_level)); + return std::string(buf); + } + if (id(led_standby_red).state) return std::string("Manual (Standby)"); + return std::string("Manual (Off)"); + } + + if (id(led_operating_blue).state) { + char buf[32]; + snprintf(buf, sizeof(buf), "Operating (Level %d)", id(current_level)); + return std::string(buf); + } + if (!isnan(effective_t) && effective_t >= at_temp_threshold) { + return std::string("At Temperature"); + } + if (id(led_standby_red).state) return std::string("Standby"); return std::string("Off"); + on_value: + - script.execute: publish_status + + - platform: template + id: setpoint_text + name: "Setpoint Text" + icon: mdi:thermometer + update_interval: 1s + lambda: |- + char buf[16]; + snprintf(buf, sizeof(buf), "%.1f °C", id(setpoint_c)); + return std::string(buf); + + - platform: template + id: test_temperature_text + name: "${friendly_name} Test Mode Temp" + icon: mdi:thermometer-chevron-up + update_interval: 1s + lambda: |- + char buf[20]; + snprintf(buf, sizeof(buf), "%.1f °C", id(test_temp_c)); + return std::string(buf); ########################################################################################## # SELECT COMPONENT -# https://esphome.io/components/select/index.html ########################################################################################## select: - # AUTO or MANUAL (MANUAL is sticky until next power ON) - platform: template id: mode_select - name: "${friendly_name} Mode" - options: ["AUTO","MANUAL","Remote Control Only"] + name: "Mode" + options: ["AUTO","MANUAL","BYPASS (Remote Only)"] optimistic: true - initial_option: "AUTO" - restore_value: true + initial_option: "BYPASS (Remote Only)" + restore_value: false - # Flame level (1..7). Selecting forces MANUAL and adjusts to the chosen level. - platform: template id: flame_level_select name: "${friendly_name} Flame Level" @@ -519,7 +676,6 @@ select: optimistic: true restore_value: true set_action: - # If selection equals our known current level, ignore to avoid loops. - if: condition: lambda: |- @@ -530,9 +686,11 @@ select: else: - if: condition: - lambda: 'return id(mode_select).state != "Remote Control Only";' + lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' then: - - select.set: { id: mode_select, option: "MANUAL" } + - select.set: + id: mode_select + option: "MANUAL" - lambda: |- int target = atoi(x.c_str()); if (target < 1) target = 1; @@ -542,72 +700,112 @@ select: condition: lambda: 'return !id(powered_state).state;' then: - # Power on, respect warmup, calibrate to level 1, then adjust toward desired (still MANUAL) - script.execute: press_power - - lambda: |- - id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); - id(ramp_until_ms) = millis() + (${fast_ramp_seconds} * 1000UL); // fast ramp window - - delay: ${warmup_seconds}s - - script.execute: calibrate_to_min - - script.execute: adjust_to_desired + - if: + condition: + lambda: 'return id(test_mode_enabled).state;' + then: + - lambda: |- + id(test_powered) = true; + - script.execute: recompute_powered_state + - if: + condition: + lambda: 'return !id(test_mode_enabled).state;' + then: + - lambda: |- + id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); + id(ramp_until_ms) = millis() + (${fast_ramp_seconds} * 1000UL); + - delay: ${warmup_seconds}s + - script.execute: calibrate_to_min + - script.execute: adjust_to_desired + else: + - logger.log: "Test Mode active: logical power now ON." + - script.execute: adjust_to_desired else: - script.execute: adjust_to_desired else: - - logger.log: "Remote Control Only: ignoring Flame Level selection." + - logger.log: "BYPASS (Remote Only): ignoring Flame Level selection." - -################################################################################################# +########################################################################################## # BUTTON COMPONENT -# https://esphome.io/components/button/index.html -################################################################################################# +########################################################################################## button: - # Manual step buttons (each press forces MANUAL) - button up - platform: template id: btn_flame_up name: "${friendly_name} Flame Up (step)" on_press: - if: condition: - lambda: 'return id(mode_select).state != "Remote Control Only";' + lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' then: - - select.set: { id: mode_select, option: "MANUAL" } + - select.set: + id: mode_select + option: "MANUAL" - script.execute: step_up_once else: - - logger.log: "Remote Control Only: ignoring Flame Up (step)." + - logger.log: "BYPASS (Remote Only): ignoring Flame Up (step)." - # Manual step buttons (each press forces MANUAL) - button down - platform: template id: btn_flame_down name: "${friendly_name} Flame Down (step)" on_press: - if: condition: - lambda: 'return id(mode_select).state != "Remote Control Only";' + lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' then: - - select.set: { id: mode_select, option: "MANUAL" } + - select.set: + id: mode_select + option: "MANUAL" - script.execute: step_down_once else: - - logger.log: "Remote Control Only: ignoring Flame Down (step)." + - logger.log: "BYPASS (Remote Only): ignoring Flame Down (step)." - # Calibrate - platform: template id: btn_calibrate_min - name: "${friendly_name} Calibrate: Force Level 1 (7x down)" + name: "${friendly_name} Calibrate: Force Level 1 (6x down)" entity_category: config on_press: - script.execute: calibrate_to_min + - platform: template + id: btn_setpoint_up + name: "${friendly_name} Setpoint Up" + icon: mdi:plus + on_press: + - lambda: |- + const float step = ${setpoint_step_c}; + float v = id(setpoint_c) + step; + const float vmax = ${setpoint_max_c}; + if (v > vmax) v = vmax; + id(setpoint_c) = v; + - number.set: + id: setpoint_number + value: !lambda 'return id(setpoint_c);' -################################################################################################# + - platform: template + id: btn_setpoint_down + name: "${friendly_name} Setpoint Down" + icon: mdi:minus + on_press: + - lambda: |- + const float step = ${setpoint_step_c}; + float v = id(setpoint_c) - step; + const float vmin = ${setpoint_min_c}; + if (v < vmin) v = vmin; + id(setpoint_c) = v; + - number.set: + id: setpoint_number + value: !lambda 'return id(setpoint_c);' + +########################################################################################## # NUMBER COMPONENT -# https://esphome.io/components/number/ -################################################################################################# +########################################################################################## number: - # Setpoint number (primary authority). Two-way MQTT sync with loop guard. - platform: template id: setpoint_number name: "${friendly_name} Setpoint" icon: mdi:thermometer + unit_of_measurement: "°C" min_value: ${setpoint_min_c} max_value: ${setpoint_max_c} step: ${setpoint_step_c} @@ -615,29 +813,41 @@ number: lambda: |- return id(setpoint_c); set_action: - # 1) adopt the new value locally - lambda: |- id(setpoint_c) = x; - # 2) unless we are processing an incoming MQTT update, publish out - if: condition: lambda: |- return !id(sp_suppress_mqtt); then: - mqtt.publish: - topic: /viewroad-status/lounge-environment/temp-setpoint + topic: "viewroad-status/lounge-gasheater/setpoint" retain: true payload: !lambda |- char buf[16]; snprintf(buf, sizeof(buf), "%.1f", x); return std::string(buf); + # Bench-test room temperature slider used by AUTO whenever Test Mode is ON. + - platform: template + id: test_temperature_value + name: "${friendly_name} Test Temperature Value" + icon: mdi:thermometer-chevron-up + unit_of_measurement: "°C" + min_value: -10.0 + max_value: 40.0 + step: 0.1 + mode: slider + lambda: |- + return id(test_temp_c); + set_action: + - lambda: |- + id(test_temp_c) = x; + ########################################################################################## # INTERVAL COMPONENT -# https://esphome.io/components/interval/ ########################################################################################## interval: - # AUTO loop tick (only when AUTO is enabled) - interval: ${control_interval_s}s then: - if: @@ -646,30 +856,35 @@ interval: then: - script.execute: auto_control_tick - -################################################################################################# +########################################################################################## # SCRIPT COMPONENT -# https://esphome.io/components/script.html -################################################################################################# +########################################################################################## script: - # Publish textual status to MQTT + # Mirror the already-computed Status Text entity out to MQTT. + # This keeps the HA text entity and MQTT status using the same source of truth. - id: publish_status mode: restart then: - mqtt.publish: - topic: /viewroad-status/gasfire + topic: "viewroad-status/lounge-gasheater" payload: !lambda |- - if (id(led_operating_blue).state) return std::string("Operating"); - if (id(led_standby_red).state) return std::string("Standby"); - return std::string("Off"); + if (id(status_text).state.size() == 0) return std::string("Unknown"); + return id(status_text).state; - id: recompute_powered_state then: - lambda: |- - const bool new_state = id(led_operating_blue).state || id(led_standby_red).state; - id(powered_state).publish_state(new_state); + const bool led_powered = + id(led_operating_blue).state || id(led_standby_red).state; - # Low-level press with enforced pulse and gap + const bool new_state = + id(test_mode_enabled).state ? id(test_powered) : led_powered; + + id(powered_state).publish_state(new_state); + - script.execute: publish_status + + # Low-level relay click helper. + # Handles the button press pulse and enforces a minimum gap between clicks. - id: press_with_gap mode: queued parameters: @@ -696,44 +911,49 @@ script: - switch.turn_off: sw_down_raw - delay: ${min_click_gap_ms}ms - - id: press_power then: - lambda: |- id(self_power_on) = true; - - script.execute: { id: press_with_gap, which: "power" } - + - script.execute: + id: press_with_gap + which: "power" - id: press_up then: - if: condition: - lambda: 'return id(mode_select).state != "Remote Control Only";' + lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' then: - - script.execute: { id: press_with_gap, which: "up" } + - script.execute: + id: press_with_gap + which: "up" else: - - logger.log: "Remote Control Only: ignoring UP press." + - logger.log: "BYPASS (Remote Only): ignoring UP press." - id: press_down then: - if: condition: - lambda: 'return id(mode_select).state != "Remote Control Only";' + lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' then: - - script.execute: { id: press_with_gap, which: "down" } + - script.execute: + id: press_with_gap + which: "down" else: - - logger.log: "Remote Control Only: ignoring DOWN press." + - logger.log: "BYPASS (Remote Only): ignoring DOWN press." - # Single-step level adjusters (track current_level and update the select) + # Step one flame level UP and only update the visible level after the relay click finishes. - id: step_up_once then: - if: condition: lambda: 'return id(powered_state).state;' then: + - script.execute: press_up + - script.wait: press_with_gap - lambda: |- if (id(current_level) < 7) id(current_level)++; - - script.execute: press_up - select.set: id: flame_level_select option: !lambda 'return std::to_string(id(current_level));' @@ -742,15 +962,17 @@ script: else: - logger.log: "Heater is OFF; ignoring manual step up." + # Step one flame level DOWN and only update the visible level after the relay click finishes. - id: step_down_once then: - if: condition: lambda: 'return id(powered_state).state;' then: + - script.execute: press_down + - script.wait: press_with_gap - lambda: |- if (id(current_level) > 1) id(current_level)--; - - script.execute: press_down - select.set: id: flame_level_select option: !lambda 'return std::to_string(id(current_level));' @@ -759,34 +981,40 @@ script: else: - logger.log: "Heater is OFF; ignoring manual step down." - - # Force level 1 certainty (7x DOWN) - skipped in Remote Control Only and if OFF + # Force a visible re-baseline to flame level 1. + # Six DOWN clicks guarantee that even from level 7 we end at level 1. - id: calibrate_to_min then: - if: condition: - lambda: 'return id(mode_select).state != "Remote Control Only" && id(powered_state).state;' + lambda: 'return id(mode_select).state != "BYPASS (Remote Only)" && id(powered_state).state;' then: - - repeat: - count: 7 - then: - - script.execute: press_down - lambda: |- - id(current_level) = 1; + id(calibrating) = true; + - script.execute: publish_status + - repeat: + count: 6 + then: + - script.execute: step_down_once + - script.wait: step_down_once + - lambda: |- id(last_recal_ms) = millis(); + id(calibrating) = false; - select.set: id: flame_level_select option: "1" + - script.execute: publish_status else: - - logger.log: "Skipping calibration (Remote Control Only or heater OFF)." + - logger.log: "Skipping calibration (BYPASS or heater OFF)." - # Move smoothly toward desired_level (rate-limited) + # Moves one step at a time toward desired_level. + # In Test Mode, target confirmation is bypassed so bench testing feels responsive. - id: adjust_to_desired mode: queued then: - if: condition: - lambda: 'return millis() < id(warmup_until_ms);' + lambda: 'return millis() < id(warmup_until_ms) && !id(test_mode_enabled).state;' then: - logger.log: format: "Warmup: suppressing level change." @@ -795,7 +1023,6 @@ script: - if: condition: lambda: |- - // Faster stepping during ramp window, normal otherwise const uint32_t step_ms = (millis() < id(ramp_until_ms)) ? (${fast_ramp_step_s} * 1000UL) : (${adjust_step_interval_s} * 1000UL); @@ -809,10 +1036,9 @@ script: format: "Heater is OFF; not adjusting level." level: DEBUG else: - # Proceed if target is confirmed OR we are still in the ramp window - if: condition: - lambda: 'return id(target_confirmed) || (millis() < id(ramp_until_ms));' + lambda: 'return id(test_mode_enabled).state || id(target_confirmed) || (millis() < id(ramp_until_ms));' then: - if: condition: @@ -826,51 +1052,78 @@ script: then: - script.execute: step_down_once - + # Called after a successful power ON request. + # Handles warmup, optional calibration, and initial AUTO control startup. - id: after_power_on_reset_to_auto then: - if: condition: - lambda: 'return id(mode_select).state != "Remote Control Only";' + lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' then: - - lambda: |- - // Suppress level adjustments during post-power-on warmup - id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); - // Enable a short fast-ramp window for quicker heat-up - id(ramp_until_ms) = millis() + (${fast_ramp_seconds} * 1000UL); - - select.set: { id: mode_select, option: "AUTO" } - - delay: ${warmup_seconds}s - - script.execute: calibrate_to_min - # Immediately compute a level and move toward it (no extra 30s wait) - - script.execute: auto_control_tick - - script.execute: adjust_to_desired - - lambda: |- - // Done with our own ON sequence - id(self_power_on) = false; + - if: + condition: + lambda: 'return id(test_mode_enabled).state;' + then: + - if: + condition: + lambda: 'return id(mode_select).state == "AUTO";' + then: + - lambda: |- + id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); + id(ramp_until_ms) = millis() + (${fast_ramp_seconds} * 1000UL); + - delay: ${warmup_seconds}s + - script.execute: calibrate_to_min + - script.execute: auto_control_tick + - script.execute: adjust_to_desired + - lambda: |- + id(self_power_on) = false; + else: + - lambda: |- + id(self_power_on) = false; + - logger.log: "Test Mode active: staying in MANUAL; no AUTO startup actions." + else: + - lambda: |- + id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); + id(ramp_until_ms) = millis() + (${fast_ramp_seconds} * 1000UL); + - select.set: + id: mode_select + option: "AUTO" + - delay: ${warmup_seconds}s + - script.execute: calibrate_to_min + - script.execute: auto_control_tick + - script.execute: adjust_to_desired + - lambda: |- + id(self_power_on) = false; else: - - logger.log: "Remote Control Only: keeping mode; no auto-calibrate." + - lambda: |- + id(self_power_on) = false; + - logger.log: "BYPASS (Remote Only): keeping mode; no auto-calibrate." - - # AUTO thermostat logic (hysteresis + level mapping) + # Main thermostat logic. + # Uses test_temp_c whenever Test Mode is enabled, otherwise uses MQTT room_temp. - id: auto_control_tick mode: queued then: - lambda: |- - const float t = id(room_temp).state; + const bool use_test_temp = id(test_mode_enabled).state; + const float t = use_test_temp ? id(test_temp_c) : id(room_temp).state; const float sp = id(setpoint_c); const uint32_t now_ms = millis(); - // Fail-safe: if temperature is missing (NAN), optionally turn OFF after timeout. - if (isnan(t)) { - const bool powered = id(powered_state).state; - const bool stale = (id(last_temp_ms) > 0) && - ((now_ms - id(last_temp_ms)) >= (${temp_stale_timeout_min} * 60000UL)); - if (powered && stale) { - ESP_LOGW("gas", "AUTO: temperature stale -> turning OFF as fail-safe"); - id(press_power).execute(); - } else { - ESP_LOGW("gas", "AUTO: temperature missing; skipping control tick"); + if (!use_test_temp) { + const bool temp_lost = (id(last_temp_ms) > 0) && + ((now_ms - id(last_temp_ms)) >= (${temp_stale_timeout_min} * 60000UL)); + id(room_temp_lost_fault) = temp_lost; + if (temp_lost) { + ESP_LOGW("gas", "AUTO: room temperature lost; skipping control tick"); + return; } + } else { + id(room_temp_lost_fault) = false; + } + + if (isnan(t)) { + ESP_LOGW("gas", "AUTO: temperature missing; skipping control tick"); return; } @@ -883,34 +1136,42 @@ script: const float low = sp - ${on_below_c}; const float high = sp + ${off_above_c}; - // Honour minimum on/off durations const bool can_turn_on = (!powered) && ((${min_off_minutes} == 0) || ((now_ms - id(last_off_ms)) >= (${min_off_minutes} * 60000UL))); const bool can_turn_off = ( powered) && ((${min_on_minutes} == 0) || ((now_ms - id(last_on_ms)) >= (${min_on_minutes} * 60000UL))); - // Hysteresis-based ON/OFF if (t <= low && can_turn_on) { ESP_LOGI("gas", "AUTO: below setpoint -> ON"); id(press_power).execute(); + if (id(test_mode_enabled).state) { + id(test_powered) = true; + id(powered_state).publish_state(true); + id(publish_status).execute(); + } id(after_power_on_reset_to_auto).execute(); return; } + if (t >= high && can_turn_off) { ESP_LOGI("gas", "AUTO: above setpoint -> OFF"); id(press_power).execute(); + if (id(test_mode_enabled).state) { + id(test_powered) = false; + id(powered_state).publish_state(false); + id(publish_status).execute(); + } return; } - // Map error to desired flame level when powered. - // Always set desired_level; use target_confirmed to gate normal (non-ramp) steps. if (powered) { - float diff = sp - t; // positive => need more heat + float diff = sp - t; int target = 1; + if (diff > 3.0f) target = 7; - else if (diff > 2.0f) target = 6; - else if (diff > 1.5f) target = 5; - else if (diff > 1.0f) target = 4; - else if (diff > 0.6f) target = 3; - else if (diff > 0.2f) target = 2; + else if (diff > 2.5f) target = 6; + else if (diff > 2.0f) target = 5; + else if (diff > 1.5f) target = 4; + else if (diff > 1.0f) target = 3; + else if (diff > 0.5f) target = 2; else target = 1; id(desired_level) = target; @@ -918,7 +1179,6 @@ script: id(last_level_target) = target; } - - if: condition: lambda: 'return id(powered_state).state;' @@ -929,8 +1189,6 @@ script: return (id(desired_level) == 1) && ((millis() - id(last_recal_ms)) >= (${recalibrate_interval_min} * 60000UL)); then: - - logger.log: "Re-baseline at level 1 (7x DOWN)." + - logger.log: "Re-baseline at level 1 (6x DOWN)." - script.execute: calibrate_to_min - - script.execute: adjust_to_desired - - + - script.execute: adjust_to_desired \ No newline at end of file diff --git a/esphome/esp-laundrydrypow.yaml b/esphome/esp-laundrydrypow.yaml index 461dfbb..09dfe5f 100644 --- a/esphome/esp-laundrydrypow.yaml +++ b/esphome/esp-laundrydrypow.yaml @@ -1,39 +1,82 @@ -############################################# -############################################# -# LAUNDRY DRYER MACHINE POWER +#:########################################################################################:# +# TITLE: LAUNDRY DRYER MACHINE POWER +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-laundrydrypow.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V1.0 2025-05-28 Initial Version -############################################# -# Sonoff POW R1 -# https://devices.esphome.io/devices/Sonoff-POW-R1 +#:########################################################################################:# +# HARDWARE: +# - Sonoff POW R1 +# - ESP8266 based +# - HLW8012 power monitoring +# - Single relay output +# - Blue status LED on GPIO15 +# - Local push button on GPIO0 +# - Relay output on GPIO12 +# - Reference: https://devices.esphome.io/devices/Sonoff-POW-R1 +#:########################################################################################:# +# OPERATION NOTES: +# - Monitors dryer load current, voltage, and power +# - Provides a virtual relay switch that controls the physical relay and LED together +# - Local button toggles the virtual relay switch +# - On boot, the virtual relay is turned ON +# - "Load Running" turns ON when measured power is above 4 W +# - "Load Running" uses delayed_off: 15s to avoid rapid state changes +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - Device continues running normally +# - Local button still works +# - MQTT remains available if your common MQTT package is enabled and broker is reachable # -# NOTES -# - +# b) MQTT offline (or HA/MQTT offline): +# - Device continues running locally +# - Local button, relay control, LED control, and power monitoring still work # -############################################# -############################################# +# c) Entire WiFi/Network offline: +# - Device continues running locally +# - Local button, relay control, LED control, and power monitoring still work +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: - device_name: "esp-laundrydrypow" # Reference name for the device in the system. - project_name: "Sonoff Technologies.POW R1" # Project Details - project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - entity_prefix: "Load" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. + # Device Naming + device_name: "esp-laundrydrypow" friendly_name: "Laundry Dryer Power" - description_comment: "Laundry Dryer Power using a Sonoff Pow R1." - device_area: "Laundry" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - api_key: !secret esp-laundrydrypow_api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-laundrydrypow_ota_pass # unfortunately you can't use substitutions inside secrets names - static_ip_address: !secret esp-laundrydrypow_ip - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + description_comment: "Laundry Dryer Power using a Sonoff Pow R1. (Layout V1.1)" + device_area: "Laundry" -########################################################################################## -# PACKAGES: Included Common Packages + # Project Naming + project_name: "Sonoff Technologies.POW R1" + project_version: "v1.1" + + # Entity Naming + entity_prefix: "Load" + + # Passwords and Secrets + api_key: !secret esp-laundrydrypow_api_key + ota_pass: !secret esp-laundrydrypow_ota_pass + static_ip_address: !secret esp-laundrydrypow_ip + current_ip_address: ${static_ip_address} + + # Device Settings + log_level: "INFO" + update_interval: "60s" + +#:########################################################################################:# +# PACKAGES: +# Included common packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -41,12 +84,13 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include file: common/api_common.yaml - #file: common/api_common_noencryption.yaml + # file: common/api_common_noencryption.yaml vars: local_api_key: "${api_key}" @@ -55,137 +99,154 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml + # common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + # common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + # diag_debug: !include common/include_debug_diag_sensors.yaml + # diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" project: name: "${project_name}" version: "${project_version}" - on_boot: + on_boot: priority: 200 then: - - switch.turn_on: "virtual_button" + - switch.turn_on: virtual_button -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. - board_flash_mode: dout # Default is dout + early_pin_init: false + board_flash_mode: dout -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + # baud_rate: 0 + # esp8266_store_log_strings_in_flash: false + # tx_buffer_size: 64 -############################################# -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -############################################# -#status_led: -# pin: -# number: GPIO2 -# inverted: yes +#:########################################################################################:# +# status_led: +# pin: +# number: GPIO2 +# inverted: true -############################################# -# SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -############################################# +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO0 mode: INPUT_PULLUP - inverted: True - name: Button + inverted: true + name: "Button" on_press: - switch.toggle: virtual_button + - platform: template - name: ${entity_prefix} Running + name: "${entity_prefix} Running" filters: - delayed_off: 15s lambda: |- if (isnan(id(power).state)) { return {}; } else if (id(power).state > 4) { - // Running return true; } else { - // Not running return false; } +#:########################################################################################:# +# SENSORS: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: hlw8012 - sel_pin: 5 - cf_pin: 14 - cf1_pin: 13 + sel_pin: GPIO5 + cf_pin: GPIO14 + cf1_pin: GPIO13 update_interval: 2s current: - name: ${entity_prefix} Current + name: "${entity_prefix} Current" voltage: - name: ${entity_prefix} Voltage + name: "${entity_prefix} Voltage" power: - name: ${entity_prefix} Power + name: "${entity_prefix} Power" id: power - #on_value_range: - # - above: 4.0 - # then: - # - light.turn_on: led - # - below: 3.0 - # then: - # - light.turn_off: led + # on_value_range: + # - above: 4.0 + # then: + # - light.turn_on: led + # - below: 3.0 + # then: + # - light.turn_off: led +#:########################################################################################:# +# SWITCH: +# https://esphome.io/components/switch/ +#:########################################################################################:# switch: - platform: template name: "Relay" - optimistic: true id: virtual_button + optimistic: true turn_on_action: - switch.turn_on: relay - light.turn_on: led turn_off_action: - switch.turn_off: relay - light.turn_off: led + - platform: gpio id: relay pin: GPIO12 - #restore_mode: ALWAYS_ON # Or RESTORE_DEFAULT_ON/RESTORE_DEFAULT_OFF + # restore_mode: ALWAYS_ON +#:########################################################################################:# +# OUTPUT: +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: pow_blue_led pin: number: GPIO15 - inverted: True + inverted: true +#:########################################################################################:# +# LIGHT: +# https://esphome.io/components/light/ +#:########################################################################################:# light: - platform: monochromatic - name: Status LED + name: "Status LED" output: pow_blue_led id: led \ No newline at end of file diff --git a/esphome/esp-laundryenv.yaml b/esphome/esp-laundryenv.yaml index b2c2045..47cc503 100644 --- a/esphome/esp-laundryenv.yaml +++ b/esphome/esp-laundryenv.yaml @@ -1,39 +1,78 @@ -############################################# -############################################# -# LAUNDRY ENVIRONMENT - SONOFF DEV +#:########################################################################################:# +# TITLE: LAUNDRY ENVIRONMENT - SONOFF DEV +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-laundryenv.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V1.0 2025-03-28 Initial Version -############################################# -# Sonoff Dev -# https://wiki.iteadstudio.com/Sonoff_DEV +#:########################################################################################:# +# HARDWARE: +# - Sonoff DEV +# - ESP8266 based +# - DHT temperature and humidity sensor on GPIO14 +# - PIR input on GPIO13 +# - Smoke detector input on GPIO5 +# - Reference: https://wiki.iteadstudio.com/Sonoff_DEV +#:########################################################################################:# +# OPERATION NOTES: +# - Provides laundry temperature and humidity monitoring +# - Provides a PIR motion binary sensor +# - Provides a smoke detector binary sensor +# - Designed as a simple environmental and safety monitoring node +# - No relay or timed control logic is used in this yaml +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - Device continues to read and publish local sensor states +# - PIR, smoke, temperature, and humidity sensing continue locally # -# NOTES -# - +# b) MQTT offline (or HA/MQTT offline): +# - Device continues sampling sensors locally +# - No MQTT-based status publishing will be available # -############################################# -############################################# +# c) Entire WiFi/Network offline: +# - Device continues sampling sensors locally +# - No HA or MQTT connectivity will be available +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: - device_name: "esp-laundryenv" # Reference name for the device in the system. - project_name: "Sonoff Technologies.Sonoff DEV" # Project Details - project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - entity_prefix: "Laundry" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. + # Device Naming + device_name: "esp-laundryenv" friendly_name: "Laundry Environment" - description_comment: "Laundry Environment Sensor, PIR and Smoke Detector using Sonoff DEV" - device_area: "Laundry" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - api_key: !secret esp-laundryenv_api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-laundryenv_ota_pass # unfortunately you can't use substitutions inside secrets names - static_ip_address: !secret esp-laundryenv_ip - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + description_comment: "Laundry Environment Sensor, PIR and Smoke Detector using Sonoff DEV (Layout V1.1)" + device_area: "Laundry" -########################################################################################## -# PACKAGES: Included Common Packages + # Project Naming + project_name: "Sonoff Technologies.Sonoff DEV" + project_version: "v1.1" + + # Entity Naming + entity_prefix: "Laundry" + + # Passwords and Secrets + api_key: !secret esp-laundryenv_api_key + ota_pass: !secret esp-laundryenv_ota_pass + static_ip_address: !secret esp-laundryenv_ip + current_ip_address: ${static_ip_address} + + # Device Settings + log_level: "INFO" + update_interval: "60s" + +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -41,6 +80,7 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### @@ -55,63 +95,68 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" project: name: "${project_name}" version: "${project_version}" -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. - board_flash_mode: dout # Default is dout + early_pin_init: false + board_flash_mode: dout -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + #baud_rate: 0 #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -############################################# -# SENSORS -# https://esphome.io/components/binary_sensor/ -############################################# +#:########################################################################################:# +# SENSORS: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: dht pin: GPIO14 temperature: - name: ${entity_prefix} Temperature + name: "${entity_prefix} Temperature" humidity: - name: ${entity_prefix} Humidity - update_interval: ${update_interval} + name: "${entity_prefix} Humidity" + update_interval: "${update_interval}" +#:########################################################################################:# +# BINARY SENSORS: +# https://esphome.io/components/binary_sensor/ +#:########################################################################################:# binary_sensor: - platform: gpio pin: @@ -119,19 +164,16 @@ binary_sensor: mode: input: true pullup: false - name: ${entity_prefix} PIR + name: "${entity_prefix} PIR" device_class: motion #filters: - # - invert: + # - invert: - platform: gpio pin: - number: GPIO05 + number: GPIO5 mode: input: true pullup: true - inverted: True - name: ${entity_prefix} Smoke Detector - - - + inverted: true + name: "${entity_prefix} Smoke Detector" \ No newline at end of file diff --git a/esphome/esp-laundrylights.yaml b/esphome/esp-laundrylights.yaml index 39d332a..467247a 100644 --- a/esphome/esp-laundrylights.yaml +++ b/esphome/esp-laundrylights.yaml @@ -1,39 +1,90 @@ -########################################################################################## -########################################################################################## -# LAUNDRY MAIN LIGHTSWITCH +#:########################################################################################:# +# TITLE: LAUNDRY MAIN LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-laundrylights.yaml +#:########################################################################################:# +# VERSIONS: +# V3.6 2026-03-11 Updated yaml to zorruno layout V1.1 # V3.5 2025-07-24 YAML tidyups # V3.0 2025-06-05 YAML tidyups # V2.0 2025-06-01 Was initially a 3 button switch, now 2 # V1.0 2025-05-30 Initial Version -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Double push button +# - ESP8266 based +# - pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +# - Relay 1 output on GPIO13 +# - Relay 2 output on GPIO12 +# - Button 1 input on GPIO16 +# - Button 2 input on GPIO5 +# - Status LED on GPIO2 +#:########################################################################################:# +# OPERATION NOTES: +# - Button 1 toggles Relay 1 for the laundry lights +# - Button 2 supports two actions: +# - Single click toggles Relay 2 locally +# - Hold for 2 seconds or more sends MQTT ON/OFF to the remote device +# - Relay 2 is turned ON at boot +# - Remote MQTT status is subscribed to and normalised to ON/OFF/TRUE/FALSE/1/0 +# - If the remote state is unknown, a hold on Button 2 defaults to sending ON +# - This switch is used for: +# - Laundry Lights (1) +# - Laundry Power Enable (2) +#:########################################################################################:# +# MQTT COMMANDS: +# - Remote device command topic: +# - ${mqtt_remote1_command_topic} +# - Remote device status topic: +# - ${mqtt_remote1_status_topic} +# - Hold Button 2: +# - Sends OFF if remote state is known and currently ON +# - Sends ON otherwise +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - Local buttons and local relays continue to work +# - Remote MQTT control/status for Button 2 hold still works if the MQTT broker is online # -# NOTES -# - +# b) MQTT offline (or HA/MQTT offline): +# - Local buttons and local relays continue to work +# - Button 2 single click still toggles Relay 2 locally +# - Button 2 hold cannot control the remote MQTT device # -########################################################################################## -########################################################################################## +# c) Entire WiFi/Network offline: +# - Local buttons and local relays continue to work +# - Remote MQTT control/status is unavailable +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-laundrylights" friendly_name: "Laundry Main Lightswitch (2)" - description_comment: "Laundry Main Lightswitch using a Zemismart KS-811 Double Push Button. Laundry Lights (1), Laundry Power Signal (2)" - device_area: "Laundry" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Laundry Main Lightswitch using a Zemismart KS-811 Double Push Button. Laundry Lights (1), Laundry Power Signal (2) (Layout V1.1)" + device_area: "Laundry" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v3.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" # Project Details + project_version: "v3.6" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-laundrylights_ip + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic @@ -49,14 +100,15 @@ substitutions: # Switch Naming switch_1_name: "Laundry Lights" - switch_2_name: "Laundry Power Enable" # This is virtual only, no power connected to 3rd relay - #switch_3_name: "Fan 3 Relay" - #switch_4_name: "Fan 4 Relay" + switch_2_name: "Laundry Power Enable" # This is virtual only, no power connected to 3rd relay + #switch_3_name: "Fan 3 Relay" + #switch_4_name: "Fan 4 Relay" -######################################################################################### -# PACKAGES: Included Common Packages +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -64,6 +116,7 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### @@ -78,22 +131,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -102,70 +156,70 @@ esphome: project: name: "${project_name}" version: "${project_version}" - on_boot: + on_boot: priority: 200 then: - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: level: "${log_level}" #INFO Level suggested, or DEBUG for testing #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# GLOBAL VARIABLES -# -######################################################################################### +#:########################################################################################:# +# GLOBAL VARIABLES: +#:########################################################################################:# globals: - id: remote1_state type: bool - restore_value: no - initial_value: 'false' + restore_value: false + initial_value: "false" + - id: remote1_known type: bool - restore_value: no - initial_value: 'false' + restore_value: false + initial_value: "false" -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True + inverted: true name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 - platform: gpio pin: - number: GPIO05 + number: GPIO5 mode: INPUT inverted: true name: "Button 2: ${switch_2_name}" @@ -177,18 +231,21 @@ binary_sensor: then: - if: condition: - lambda: 'return id(Relay_2).state;' + lambda: |- + return id(Relay_2).state; then: - switch.turn_off: Relay_2 else: - switch.turn_on: Relay_2 + # HOLD: pressed for 2s or more -> toggle remote; default to ON if unknown - timing: - ON for at least 2s then: - if: condition: - lambda: 'return id(remote1_known) && id(remote1_state);' # known AND currently ON + lambda: |- + return id(remote1_known) && id(remote1_state); // known AND currently ON then: - mqtt.publish: topic: "${mqtt_remote1_command_topic}" @@ -200,10 +257,9 @@ binary_sensor: payload: "ON" retain: false -######################################################################################### -# TEXT SENSORS -# -######################################################################################### +#:########################################################################################:# +# TEXT SENSORS: +#:########################################################################################:# text_sensor: - platform: mqtt_subscribe id: remote1_status @@ -214,11 +270,13 @@ text_sensor: - lambda: |- // copy, trim whitespace, uppercase std::string s = x; + // trim leading/trailing whitespace - auto notspace = [](int ch){ return !std::isspace(ch); }; + auto notspace = [](int ch) { return !std::isspace(ch); }; s.erase(s.begin(), std::find_if(s.begin(), s.end(), notspace)); s.erase(std::find_if(s.rbegin(), s.rend(), notspace).base(), s.end()); - for (auto &c : s) c = (char)toupper(c); + + for (auto &c : s) c = (char) toupper(c); bool recognized = false; if (s == "ON" || s == "1" || s == "TRUE") { @@ -233,15 +291,16 @@ text_sensor: // unknown payload (e.g. "ONLINE", "OFFLINE", JSON, etc.) id(remote1_known) = false; } + ESP_LOGI("remote1_status", "Parsed status='%s' -> known=%s state=%s", s.c_str(), id(remote1_known) ? "true" : "false", id(remote1_state) ? "ON" : "OFF"); -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -251,7 +310,4 @@ switch: - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 - id: Relay_2 - - - + id: Relay_2 \ No newline at end of file diff --git a/esphome/esp-laundryplugpow.yaml b/esphome/esp-laundryplugpow.yaml index d67304b..ad994fb 100644 --- a/esphome/esp-laundryplugpow.yaml +++ b/esphome/esp-laundryplugpow.yaml @@ -1,39 +1,82 @@ -############################################# -############################################# -# LAUNDRY BENCH PLUGS POWER AND SWITCH +#:########################################################################################:# +# TITLE: LAUNDRY BENCH PLUGS POWER AND SWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-laundryplugpow.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V1.0 2025-03-28 Initial Version -############################################# -# Sonoff POW R1 -# https://devices.esphome.io/devices/Sonoff-POW-R1 +#:########################################################################################:# +# HARDWARE: +# - Sonoff POW R1 +# - ESP8266 based +# - HLW8012 power monitoring +# - Single relay output +# - Blue status LED on GPIO15 +# - Local push button on GPIO0 +# - Relay output on GPIO12 +# - Reference: https://devices.esphome.io/devices/Sonoff-POW-R1 +#:########################################################################################:# +# OPERATION NOTES: +# - Monitors plug load current, voltage, and power +# - Provides a virtual relay switch that controls the physical relay and LED together +# - Local button toggles the virtual relay switch +# - On boot, the virtual relay is turned ON +# - "Load Running" turns ON when measured power is above 4 W +# - "Load Running" uses delayed_off: 15s to avoid rapid state changes +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - Device continues running normally +# - Local button still works +# - MQTT remains available if your common MQTT package is enabled and broker is reachable # -# NOTES -# - +# b) MQTT offline (or HA/MQTT offline): +# - Device continues running locally +# - Local button, relay control, LED control, and power monitoring still work # -############################################# -############################################# +# c) Entire WiFi/Network offline: +# - Device continues running locally +# - Local button, relay control, LED control, and power monitoring still work +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: - device_name: "esp-laundryplugpow" # Reference name for the device in the system. - project_name: "Sonoff Technologies.POW R1" # Project Details - project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - entity_prefix: "Load" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. + # Device Naming + device_name: "esp-laundryplugpow" friendly_name: "Laundry Bench Plug Power" - description_comment: "Laundry Bench Plug Power and switch override using a Sonoff Pow R1." - device_area: "Laundry" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - api_key: !secret esp-laundryplugpow_api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-laundryplugpow_ota_pass # unfortunately you can't use substitutions inside secrets names - static_ip_address: !secret esp-laundryplugpow_ip - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + description_comment: "Laundry Bench Plug Power and switch override using a Sonoff Pow R1. (Layout V1.1)" + device_area: "Laundry" -########################################################################################## -# PACKAGES: Included Common Packages + # Project Naming + project_name: "Sonoff Technologies.POW R1" + project_version: "v1.1" + + # Entity Naming + entity_prefix: "Load" + + # Passwords and Secrets + api_key: !secret esp-laundryplugpow_api_key + ota_pass: !secret esp-laundryplugpow_ota_pass + static_ip_address: !secret esp-laundryplugpow_ip + current_ip_address: ${static_ip_address} + + # Device Settings + log_level: "INFO" + update_interval: "60s" + +#:########################################################################################:# +# PACKAGES: +# Included common packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -41,12 +84,13 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include file: common/api_common.yaml - #file: common/api_common_noencryption.yaml + # file: common/api_common_noencryption.yaml vars: local_api_key: "${api_key}" @@ -55,137 +99,154 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml + # common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + # common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + # diag_debug: !include common/include_debug_diag_sensors.yaml + # diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" project: name: "${project_name}" version: "${project_version}" - on_boot: + on_boot: priority: 200 then: - - switch.turn_on: "virtual_button" + - switch.turn_on: virtual_button -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. - board_flash_mode: dout # Default is dout + early_pin_init: false + board_flash_mode: dout -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + # baud_rate: 0 + # esp8266_store_log_strings_in_flash: false + # tx_buffer_size: 64 -############################################# -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -############################################# -#status_led: -# pin: -# number: GPIO2 -# inverted: yes +#:########################################################################################:# +# status_led: +# pin: +# number: GPIO2 +# inverted: true -############################################# -# SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -############################################# +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO0 mode: INPUT_PULLUP - inverted: True - name: Button + inverted: true + name: "Button" on_press: - switch.toggle: virtual_button + - platform: template - name: ${entity_prefix} Running + name: "${entity_prefix} Running" filters: - delayed_off: 15s lambda: |- if (isnan(id(power).state)) { return {}; } else if (id(power).state > 4) { - // Running return true; } else { - // Not running return false; } +#:########################################################################################:# +# SENSORS: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: hlw8012 - sel_pin: 5 - cf_pin: 14 - cf1_pin: 13 + sel_pin: GPIO5 + cf_pin: GPIO14 + cf1_pin: GPIO13 update_interval: 2s current: - name: ${entity_prefix} Current + name: "${entity_prefix} Current" voltage: - name: ${entity_prefix} Voltage + name: "${entity_prefix} Voltage" power: - name: ${entity_prefix} Power + name: "${entity_prefix} Power" id: power - #on_value_range: - # - above: 4.0 - # then: - # - light.turn_on: led - # - below: 3.0 - # then: - # - light.turn_off: led + # on_value_range: + # - above: 4.0 + # then: + # - light.turn_on: led + # - below: 3.0 + # then: + # - light.turn_off: led +#:########################################################################################:# +# SWITCH: +# https://esphome.io/components/switch/ +#:########################################################################################:# switch: - platform: template name: "Relay" - optimistic: true id: virtual_button + optimistic: true turn_on_action: - switch.turn_on: relay - light.turn_on: led turn_off_action: - switch.turn_off: relay - light.turn_off: led + - platform: gpio id: relay pin: GPIO12 - #restore_mode: ALWAYS_ON # Or RESTORE_DEFAULT_ON/RESTORE_DEFAULT_OFF + # restore_mode: ALWAYS_ON +#:########################################################################################:# +# OUTPUT: +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: pow_blue_led pin: number: GPIO15 - inverted: True + inverted: true +#:########################################################################################:# +# LIGHT: +# https://esphome.io/components/light/ +#:########################################################################################:# light: - platform: monochromatic - name: Status LED + name: "Status LED" output: pow_blue_led id: led \ No newline at end of file diff --git a/esphome/esp-laundrywashpow.yaml b/esphome/esp-laundrywashpow.yaml index 69642dc..225ea86 100644 --- a/esphome/esp-laundrywashpow.yaml +++ b/esphome/esp-laundrywashpow.yaml @@ -1,39 +1,82 @@ -############################################# -############################################# -# LAUNDRY WASHING MACHINE POWER +#:########################################################################################:# +# TITLE: LAUNDRY WASHING MACHINE POWER +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-laundrywashpow.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V1.0 2025-03-28 Initial Version -############################################# -# Sonoff POW R1 -# https://devices.esphome.io/devices/Sonoff-POW-R1 +#:########################################################################################:# +# HARDWARE: +# - Sonoff POW R1 +# - ESP8266 based +# - HLW8012 power monitoring +# - Single relay output +# - Blue status LED on GPIO15 +# - Local push button on GPIO0 +# - Relay output on GPIO12 +# - Reference: https://devices.esphome.io/devices/Sonoff-POW-R1 +#:########################################################################################:# +# OPERATION NOTES: +# - Monitors washing machine load current, voltage, and power +# - Provides a virtual relay switch that controls the physical relay and LED together +# - Local button toggles the virtual relay switch +# - On boot, the virtual relay is turned ON +# - "Load Running" turns ON when measured power is above 4 W +# - "Load Running" uses delayed_off: 15s to avoid rapid state changes +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - Device continues running normally +# - Local button still works +# - MQTT remains available if your common MQTT package is enabled and broker is reachable # -# NOTES -# - +# b) MQTT offline (or HA/MQTT offline): +# - Device continues running locally +# - Local button, relay control, LED control, and power monitoring still work # -############################################# -############################################# +# c) Entire WiFi/Network offline: +# - Device continues running locally +# - Local button, relay control, LED control, and power monitoring still work +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: - device_name: "esp-laundrywashpow" # Reference name for the device in the system. - project_name: "Sonoff Technologies.POW R1" # Project Details - project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - entity_prefix: "Load" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. - friendly_name: "Laundry Washing Machine Power" # Friendly name to show in Home Assistant. - description_comment: "Laundry Washing Machine Power using a Sonoff Pow R1." - device_area: "Laundry" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - api_key: !secret esp-laundrywashpow_api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-laundrywashpow_ota_pass # unfortunately you can't use substitutions inside secrets names - static_ip_address: !secret esp-laundrywashpow_ip - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + # Device Naming + device_name: "esp-laundrywashpow" + friendly_name: "Laundry Washing Machine Power" + description_comment: "Laundry Washing Machine Power using a Sonoff Pow R1. (Layout V1.1)" + device_area: "Laundry" -########################################################################################## -# PACKAGES: Included Common Packages + # Project Naming + project_name: "Sonoff Technologies.POW R1" + project_version: "v1.1" + + # Entity Naming + entity_prefix: "Load" + + # Passwords and Secrets + api_key: !secret esp-laundrywashpow_api_key + ota_pass: !secret esp-laundrywashpow_ota_pass + static_ip_address: !secret esp-laundrywashpow_ip + current_ip_address: ${static_ip_address} + + # Device Settings + log_level: "INFO" + update_interval: "60s" + +#:########################################################################################:# +# PACKAGES: +# Included common packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -41,12 +84,13 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include file: common/api_common.yaml - #file: common/api_common_noencryption.yaml + # file: common/api_common_noencryption.yaml vars: local_api_key: "${api_key}" @@ -55,137 +99,154 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml + # common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + # common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + # diag_debug: !include common/include_debug_diag_sensors.yaml + # diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" project: name: "${project_name}" version: "${project_version}" - on_boot: + on_boot: priority: 200 then: - - switch.turn_on: "virtual_button" + - switch.turn_on: virtual_button -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. - board_flash_mode: dout # Default is dout + early_pin_init: false + board_flash_mode: dout -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + # baud_rate: 0 + # esp8266_store_log_strings_in_flash: false + # tx_buffer_size: 64 -############################################# -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -############################################# -#status_led: -# pin: -# number: GPIO2 -# inverted: yes +#:########################################################################################:# +# status_led: +# pin: +# number: GPIO2 +# inverted: true -############################################# -# SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -############################################# +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO0 mode: INPUT_PULLUP - inverted: True - name: Button + inverted: true + name: "Button" on_press: - switch.toggle: virtual_button + - platform: template - name: ${entity_prefix} Running + name: "${entity_prefix} Running" filters: - delayed_off: 15s lambda: |- if (isnan(id(power).state)) { return {}; } else if (id(power).state > 4) { - // Running return true; } else { - // Not running return false; } +#:########################################################################################:# +# SENSORS: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: hlw8012 - sel_pin: 5 - cf_pin: 14 - cf1_pin: 13 + sel_pin: GPIO5 + cf_pin: GPIO14 + cf1_pin: GPIO13 update_interval: 2s current: - name: ${entity_prefix} Current + name: "${entity_prefix} Current" voltage: - name: ${entity_prefix} Voltage + name: "${entity_prefix} Voltage" power: - name: ${entity_prefix} Power + name: "${entity_prefix} Power" id: power - #on_value_range: - # - above: 4.0 - # then: - # - light.turn_on: led - # - below: 3.0 - # then: - # - light.turn_off: led + # on_value_range: + # - above: 4.0 + # then: + # - light.turn_on: led + # - below: 3.0 + # then: + # - light.turn_off: led +#:########################################################################################:# +# SWITCH: +# https://esphome.io/components/switch/ +#:########################################################################################:# switch: - platform: template name: "Relay" - optimistic: true id: virtual_button + optimistic: true turn_on_action: - switch.turn_on: relay - light.turn_on: led turn_off_action: - switch.turn_off: relay - light.turn_off: led + - platform: gpio id: relay pin: GPIO12 - #restore_mode: ALWAYS_ON # Or RESTORE_DEFAULT_ON/RESTORE_DEFAULT_OFF + # restore_mode: ALWAYS_ON +#:########################################################################################:# +# OUTPUT: +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: pow_blue_led pin: number: GPIO15 - inverted: True + inverted: true +#:########################################################################################:# +# LIGHT: +# https://esphome.io/components/light/ +#:########################################################################################:# light: - platform: monochromatic - name: Status LED + name: "Status LED" output: pow_blue_led id: led \ No newline at end of file diff --git a/esphome/esp-leafbattery.yaml b/esphome/esp-leafbattery.yaml index 849bf14..7f1ab8d 100644 --- a/esphome/esp-leafbattery.yaml +++ b/esphome/esp-leafbattery.yaml @@ -1,29 +1,59 @@ -########################################################################################## -########################################################################################## -# Nissan Leaf 12V Battery Monitor -# Monitoring the status of a vehicle 12V battery with -# an esp8266 (D1 Mini). It will obviously only -# transmit when the vehicle is within wifi range. -# Voltage is measured with a resistor voltage divider -# into the analogue GPIO on the esp8266. -# https://zorruno.com/2022/vehicle-12v-battery-monitoring/ -########################################################################################## -########################################################################################## +#:########################################################################################:# +# TITLE: NISSAN LEAF 12V BATTERY MONITOR +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-leafbattery.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-03-22 Updated yaml to zorruno layout V1.1 +# V1.0 2025-??-?? Initial Version +#:########################################################################################:# +# HARDWARE: +# - Generic ESP8266 D1 Mini +# - Nissan Leaf 12V battery monitor +# - Voltage measured with a resistor divider into the ESP8266 analogue pin +# - Device only transmits when the vehicle is within WiFi range +# - Reference: +# https://zorruno.com/2022/vehicle-12v-battery-monitoring/ +#:########################################################################################:# +# OPERATION NOTES: +# - Monitors the Nissan Leaf 12V battery voltage. +# - Device wakes for a short period, publishes voltage, then deep sleeps. +# - Deep sleep is PREVENTED on boot by default. +# - Device waits up to 30 seconds for MQTT to connect. +# - If MQTT does not connect within 30 seconds, it enters a longer fallback sleep period. +# - If MQTT connects, deep sleep can be controlled by MQTT command topic. +# - Battery voltage is read from A0 and calibrated using a linear table. +# - Voltage is published immediately when it changes by 0.05 V or more. +# - Voltage is also republished every 60 seconds while awake. +# +# MQTT COMMANDS: +# - ${mqtt_command_topic}/deepsleep = ON +# - Allow deep sleep when run_duration expires +# - ${mqtt_command_topic}/deepsleep = OFF +# - Prevent deep sleep +# +# MQTT STATUS: +# - ${mqtt_status_topic}/availability = online/offline +# - ${mqtt_status_topic}/batteryvoltage = voltage value +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-leafbattery" friendly_name: "Nissan Leaf 12V Battery Monitor" - description_comment: "Nissan Leaf 12V Battery Monitor (when home)" - device_area: "Garage" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Nissan Leaf 12V Battery Monitor (when home) (Layout V1.1)" + device_area: "Garage" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Generic ESP8266.D1 Mini" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Generic ESP8266.D1 Mini" # Project Details + project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names @@ -32,26 +62,28 @@ substitutions: mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # MQTT LOCAL Controls mqtt_device_name: "leaf-battery" mqtt_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA mqtt_status_topic: "${mqtt_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA # Device Settings - #relay_icon: "mdi:lightbulb-group" log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc wake_interval: "20s" sleep_interval: "300s" - mqtt_fail_sleep: "1h" # If MQTT is unavailable after boot wait, sleep this long + mqtt_fail_sleep: "1h" # If MQTT is unavailable after boot wait, sleep this long -########################################################################################## -# PACKAGES: Included Common Packages +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -60,6 +92,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -73,28 +106,32 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: - name: ${device_name} - friendly_name: ${friendly_name} - comment: ${description_comment} #appears on the esphome page in HA + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # appears on the esphome page in HA + area: "${device_area}" min_version: 2024.6.0 + project: + name: "${project_name}" + version: "${project_version}" on_boot: priority: 600 then: @@ -115,41 +152,41 @@ esphome: - logger.log: "MQTT unreachable after 30s -> entering FALLBACK sleep for ${mqtt_fail_sleep}." - deep_sleep.enter: id: deep_sleep_1 - sleep_duration: ${mqtt_fail_sleep} # override only this cycle + sleep_duration: ${mqtt_fail_sleep} # override only this cycle else: - logger.log: "MQTT connected; awaiting '${mqtt_command_topic}/deepsleep' command." -########################################################################################## -# ESP Platform and Framework +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp8266.html # https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# esp8266: board: d1_mini framework: - version: latest #recommended, latest or dev + version: latest # recommended, latest or dev -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -############################################# -# Enable Over the Air Update Capability -# https://esphome.io/components/ota.html?highlight=ota -############################################# +#:########################################################################################:# +# OTA: +# https://esphome.io/components/ota.html +#:########################################################################################:# ota: - platform: web_server # Uncomment if you want to be able to do OTA with the web interface -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT COMMANDS: # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: # Availability Topic birth_message: @@ -173,19 +210,19 @@ mqtt: - deep_sleep.prevent: deep_sleep_1 - logger.log: "Deep sleep PREVENTED via MQTT." -########################################################################################## -# Deep Sleep +#:########################################################################################:# +# DEEP SLEEP: # https://esphome.io/components/deep_sleep.html -########################################################################################## +#:########################################################################################:# deep_sleep: id: deep_sleep_1 - run_duration: ${wake_interval} - sleep_duration: ${sleep_interval} - -########################################################################################## -# SENSOR COMPONENT + run_duration: ${wake_interval} + sleep_duration: ${sleep_interval} + +#:########################################################################################:# +# SENSOR COMPONENT: # https://esphome.io/components/sensor/ -########################################################################################## +#:########################################################################################:# sensor: - platform: adc pin: A0 @@ -208,8 +245,8 @@ sensor: - 0.32 -> 07.00 - 0.28 -> 06.00 - 0.23 -> 05.00 - - delta: 0.05 # publish immediately if change >= 0.05 V - - throttle: 2s # avoid bursts if noisy + - delta: 0.05 # publish immediately if change >= 0.05 V + - throttle: 2s # avoid bursts if noisy on_value: then: - mqtt.publish: @@ -221,9 +258,10 @@ sensor: snprintf(buf, sizeof(buf), "%.2f", x); return std::string(buf); -########################################################################################## -# INTERVAL COMPONENT -########################################################################################## +#:########################################################################################:# +# INTERVAL COMPONENT: +# https://esphome.io/components/interval.html +#:########################################################################################:# interval: - interval: 60s then: @@ -237,6 +275,3 @@ interval: snprintf(buf, sizeof(buf), "%.2f", v); return std::string(buf); - - - diff --git a/esphome/esp-loungebookshelfleds.yaml b/esphome/esp-loungebookshelfleds.yaml index 4bf157c..9915535 100644 --- a/esphome/esp-loungebookshelfleds.yaml +++ b/esphome/esp-loungebookshelfleds.yaml @@ -1,72 +1,97 @@ -########################################################################################## -########################################################################################## -# Title: LOUNGE BOOKSHELF LEDS -# Repo: https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungebookshelfleds.yaml -# -# v2.0 - 2025-09-15 A bunch of fixes and made it more standard across my devices -# v1.0 - 2025-08-17 First setup (and replacement of Tasmota) +#:########################################################################################:# +# TITLE: LOUNGE BOOKSHELF LEDS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungebookshelfleds.yaml +#:########################################################################################:# +# VERSIONS: +# V2.1 2026-03-11 Updated yaml to zorruno layout V1.1 +# V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices +# V1.0 2025-08-17 First setup (and replacement of Tasmota) +#:########################################################################################:# +# HARDWARE: +# - Magichome LED controller single channel (ESP8266, NOT the later ones with BL602) +# - Reference: +# https://devices.esphome.io/devices/MagicHome-ZJ-WFMN-C-Single-Color +# - Device GPIO (Magichome ESP8266): +# - GPIO2 Blue LED (used for ESPHome status) +# - GPIO12 MOSFET output (0 V when switched) +#:########################################################################################:# +# OPERATION NOTES: +# - General-purpose LED controller. +# - Designed for the Sinilink XY-WFMS board with a MOSFET output (claimed 5A, 5-36 V DC), +# but will suit similar MOSFET boards. +# - In SUBSTITUTIONS there is a maximum output setting to extend LED life. +# - In SUBSTITUTIONS there is a minimum output setting; switches fully OFF at/below the minimum +# to avoid low-PWM flicker. +# - PWM frequency is set to 1 kHz by default. You can increase it, but higher values caused +# resets on the Sinilink device. On ESP32 you can run much higher. +# - Min/max output settings are not exposed in Home Assistant/MQTT by default, but could be. +# - Packages include common items: network settings, diagnostic entities, MQTT, and optional SNTP. +# - Default restart behaviours: +# - Fade up to full +# - Restore Brightness +# - Remain Off +# - The green LED flashes while fading (different patterns for up/down). The red LED follows the +# output (it shares the MOSFET GPIO). This depends on hardware. +# - Fade timing scales with configured values proportionally when starting mid-brightness. +# - Exposed in Home Assistant/MQTT: +# - Startup action (On, Off, Restore) +# - Fade Up / Fade Down / Fade Stop buttons +# - Fade Up/Down toggle switch +# - Normal On/Off switch using quick ramp up/down +# - Fade up/down times (0-60 s) +# - Output % (pre-gamma) and PWM % (post-gamma) +# - Output Set (1-100, respects min/max) +# - Many device diagnostics from the included diagnostics package +# - Maximum ON time before automatic fade-down (1-48 h, 0 = no limit) # -# ------------------------------------------ -# OPERATION (as of v2.0) -# ------------------------------------------ -# 1. General-purpose LED controller. -# 2. Designed for the Sinilink XY-WFMS board with a MOSFET output (claimed 5A, 5-36 V DC), but will suit similar mosfet boards. -# 3. (In SUBSTITUTIONS) setting for MAX % output to extend LED life (ie can ensure it is only ever 95%) -# 4. (In SUBSTITUTIONS) Minimum output setting; switches fully OFF at/below the minimum to avoid low-PWM flicker. -# 5. (In SUBSTITUTIONS) PWM frequency is set to 1kHz by default. You can increase it, but higher values caused -# resets on Sinilink device. On ESP32 you can run much higher (~40 kHz). -# 6. Min/Max output settings are not exposed in Home Assistant/MQTT by default, but could be. -# With a 1 MB flash, space is tight and only minimal optimisation has been done so far. -# 7. (PACKAGES) include common items: network settings, diagnostic entities, MQTT, and SNTP (optional). -# 8. Default behaviours, for recovery from lost power or reset: -# - "Fade up to full": fade from floor to max on boot. -# - "Restore Brightness": fade from floor to the last non-zero brightness on boot (should be no on/off blip/flash). -# - "Remain Off": stays off on boot. -# 9. The green LED flashes while fading (different patterns for up/down). The red LED follows the -# output (it shares the MOSFET GPIO). (Obviously this depends on hardware) -# 10. Fade timing scales with the configured values (proportionally when starting mid-brightness). -# 11. Exposed in Home Assistant/MQTT: -# - Startup action (On,Off,Restore) -# - Fade Up / Fade Down / Fade Stop buttons -# - Fade Up/Down toggle switch (keeps fading up to full, or down to off unless stopped) -# - Normal On/Off switch (quick ramp up/down, up to the level of previous brightness) -# - Fade up/down times (0-60s) -# - Output % (pre-gamma) and PWM % (post-gamma) -# - Output Set (1-100, respects min/max). This also changes with other output so reflects value. -# - Many device diagnostics (from the included 'diagnostics' package) -# - Maximum 'on' time before automatic fade-down (1-48 h, 0 = no limit) -########################################################################################## -########################################################################################## -# Hardware: Magishome LED controller single channel (ESP8266, NOT the later ones with BL602) -# https://devices.esphome.io/devices/MagicHome-ZJ-WFMN-C-Single-Color -# ------------------------------------------ -# DEVICE GPIO (Magichome ESP8266) -# ------------------------------------------ -# GPIO02 Blue LED (used for ESPHome status) - I think... can't see the board -# GPIO12 MOSFET output (0 V when switched) -########################################################################################## -########################################################################################## +# MQTT COMMANDS: +# - ${mqtt_local_command_topic}/light/set = ON +# - ${mqtt_local_command_topic}/light/set = OFF +# - State publishes to: +# - ${mqtt_local_status_topic}/light/state +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - LED control continues locally on the device +# - Direct local MQTT commands still work if the broker is available +# - Stored brightness/ramp settings and restart behaviour continue to work +# +# b) MQTT offline (or HA/MQTT offline): +# - LED control continues locally on the device +# - Physical button control and local ramp logic continue to work +# - No MQTT control/state publishing available +# +# c) Entire WiFi/Network offline: +# - LED control continues locally on the device +# - Physical button control and local ramp logic continue to work +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-loungebookshelfleds" # yaml file should be device_name.yaml friendly_name: "Lounge Bookshelf LEDs" - description_comment: "LED Strip around the bookshelf in the upstairs lounge :: Magichome ESP8266" + description_comment: "LED Strip around the bookshelf in the upstairs lounge :: Magichome ESP8266 (Layout V1.1)" device_area: "Lounge" # Allows the ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Project details. Manufacturer before the dot, device after the dot. - project_version: "v2.0" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version - + project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Project details. Manufacturer before the dot, device after the dot. + project_version: "v2.1" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version + # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) - api_key: !secret esp-api_key # If using HA API + api_key: !secret esp-api_key # If using HA API ota_pass: !secret esp-ota_pass # If passwording OTA updates static_ip_address: !secret esp-loungebookshelfleds_ip # CHANGE THIS - + current_ip_address: ${static_ip_address} + # MQTT LOCAL Controls (This is just my local method of controlling via MQTT, I also use the built in method) mqtt_local_device_name: "lounge-bookshelfleds" mqtt_local_command_main_topic: !secret mqtt_command_main_topic @@ -77,24 +102,25 @@ substitutions: mqtt_local_device_command_OFF: "OFF" # Device Specific Settings - log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE - update_interval: "20s" # Update time for general sensors, etc. - led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM - minimum_led_output: "1" # % If at this value or below, we'll switch it completely off - maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics + log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE + update_interval: "20s" # Update time for general sensors, etc. + led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM + minimum_led_output: "1" # % If at this value or below, we will switch it completely off + maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off - pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts + pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts # Device Specific GPIO (so we can easily update for other devices) - device_status_led: GPIO02 + device_status_led: GPIO2 device_mosfet_out: GPIO12 - device_usr_button: GPIO04 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml + device_usr_button: GPIO4 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml -########################################################################################## -# PACKAGES: Included Common Packages +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -102,6 +128,7 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### @@ -116,22 +143,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -########################################################################################## -# ESPHome CORE CONFIGURATION +#:########################################################################################:# +# ESPHOME CORE CONFIGURATION # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -152,32 +180,32 @@ esphome: # Mode 0: Fade up to full (obeys fade settings; no on/off flicker) - if: condition: - lambda: 'return id(restart_mode) == 0;' + lambda: "return id(restart_mode) == 0;" then: - - lambda: 'id(ramp_switch_target_on) = true;' + - lambda: "id(ramp_switch_target_on) = true;" - script.execute: ramp_on_script # Mode 1: Restore Brightness (deferred to avoid races) - if: condition: - lambda: 'return id(restart_mode) == 1;' + lambda: "return id(restart_mode) == 1;" then: - script.execute: deferred_restore_brightness # Mode 2: Remain Off (no blip; stays off) - if: condition: - lambda: 'return id(restart_mode) == 2;' + lambda: "return id(restart_mode) == 2;" then: - script.stop: ramp_on_script - script.stop: ramp_off_script - - lambda: 'id(ramp_switch_target_on) = false;' + - lambda: "id(ramp_switch_target_on) = false;" - light.turn_off: id: mosfet_leds transition_length: 0s # Boot complete: allow OFF handlers again - - lambda: 'id(booting) = false;' + - lambda: "id(booting) = false;" # NEW: force indicator OFF after boot logic # (Removed: output.turn_off: green_led_out) @@ -193,11 +221,11 @@ esphome: # - -fdata-sections # - -DNDEBUG -########################################################################################## +#:########################################################################################:# # ESP PLATFORM AND FRAMEWORK # https://esphome.io/components/esp8266.html # https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# esp8266: board: esp01_1m restore_from_flash: true # restore some values on reboot @@ -208,10 +236,10 @@ mdns: preferences: flash_write_interval: 2min # enough time to update values for reboots, but not enough to wear flash -########################################################################################## +#:########################################################################################:# # GLOBAL VARIABLES # https://esphome.io/components/globals.html -########################################################################################## +#:########################################################################################:# globals: # Minimum Brightness % for LEDs (will switch off if <=) - id: min_brightness_pct @@ -223,7 +251,7 @@ globals: type: int restore_value: false initial_value: "${maximum_led_output}" # hard cap; never exceed this - # The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever + # The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever - id: max_on_hours type: int restore_value: true @@ -232,23 +260,23 @@ globals: - id: led_gamma_f type: float restore_value: false - initial_value: ${led_gamma} # <-- numeric at compile time + initial_value: ${led_gamma} # numeric at compile time # Default Fading Up Time (Selectable and will be retained) - id: ramp_up_ms # fade-in when turned ON type: int restore_value: true - initial_value: '5000' # 5 s + initial_value: "5000" # 5 s # Default Fading Down Time (Selectable and will be retained) - id: ramp_down_ms # fade-out when turned OFF type: int restore_value: true - initial_value: '10000' # 10 s + initial_value: "10000" # 10 s # Action on Restart. (0=Fade full, 1=Restore brightness, 2=Remain off) - - id: restart_mode + - id: restart_mode type: int restore_value: true - initial_value: '0' # default = Fade Up to Full (so can be deployed with no other setup) + initial_value: "0" # default = Fade Up to Full (so can be deployed with no other setup) # Determine last fade direction. # true when you asked the light to end up ON (Ramp Up) @@ -256,70 +284,70 @@ globals: - id: ramp_switch_target_on type: bool restore_value: true - initial_value: 'false' + initial_value: "false" # Prevent jitter when adjusting the slider - id: suppress_slider_sync type: bool restore_value: false - initial_value: 'false' - # actual 0..100 seen last time, for restart - - id: last_brightness_pct + initial_value: "false" + # actual 0..100 seen last time, for restart + - id: last_brightness_pct type: float restore_value: true - initial_value: '0.0' + initial_value: "0.0" # last published "Output Set (0-100)" integer - id: last_set_pos type: int restore_value: false - initial_value: '-1' - # helper to keep blink time == transition time + initial_value: "-1" + # helper to keep blink time == transition time - id: last_ramp_ms type: int restore_value: false - initial_value: '0' + initial_value: "0" # target for "Restore Brightness" scripted ramp - id: restore_target_pct type: float restore_value: false - initial_value: '0.0' + initial_value: "0.0" # true while a scripted ramp is in progress (to limit flash writes) - id: is_ramping type: bool restore_value: false - initial_value: 'false' + initial_value: "false" # guards OFF persistence during startup caused by restore_mode: ALWAYS_OFF - id: booting type: bool restore_value: false - initial_value: 'true' + initial_value: "true" # true only while we are performing a ramp-down that briefly turns the light ON to hit the floor - id: ramping_for_off type: bool restore_value: false - initial_value: 'false' + initial_value: "false" -########################################################################################## +#:########################################################################################:# # LOGGER COMPONENT # https://esphome.io/components/logger.html # Logs all log messages through the serial port and through MQTT topics. -########################################################################################## +#:########################################################################################:# logger: level: "${log_level}" # INFO Level suggested, or DEBUG for testing baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: ${device_status_led} inverted: true -########################################################################################## +#:########################################################################################:# # MQTT COMMANDS # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: # Light control to ramp up @@ -333,10 +361,10 @@ mqtt: then: - switch.turn_off: mosfet_ramp_switch -########################################################################################## +#:########################################################################################:# # SWITCH COMPONENT # https://esphome.io/components/switch/ -########################################################################################## +#:########################################################################################:# switch: # Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce) - platform: template @@ -356,10 +384,10 @@ switch: - script.stop: ramp_on_script - script.execute: ramp_off_script -################################################################################################# +#:########################################################################################:# # BUTTON COMPONENT # https://esphome.io/components/button/index.html -################################################################################################# +#:########################################################################################:# button: # Start ramping UP (from current level) - platform: template @@ -399,7 +427,7 @@ button: id(ramping_for_off) = false; id(is_ramping) = false; - // Freeze the light at its *current* level by overwriting the transition + // Freeze the light at its current level by overwriting the transition const auto &cv = id(mosfet_leds).current_values; if (cv.is_on()) { auto call = id(mosfet_leds).make_call(); @@ -415,12 +443,10 @@ button: id(last_brightness_pct) = pct; } - - -######################################################################################### +#:########################################################################################:# # SELECT COMPONENT # https://esphome.io/components/select/index.html -######################################################################################### +#:########################################################################################:# select: - platform: template id: restart_action @@ -442,10 +468,10 @@ select: id(restart_mode) = 2; } -######################################################################################### +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio id: btn_gpio12 @@ -462,7 +488,7 @@ binary_sensor: on_press: - if: condition: - lambda: 'return id(ramp_switch_target_on);' + lambda: "return id(ramp_switch_target_on);" then: # Target is currently ON -> press should go OFF (start ramp-down) - lambda: |- @@ -478,10 +504,10 @@ binary_sensor: - script.stop: ramp_off_script - script.execute: ramp_on_script -########################################################################################## +#:########################################################################################:# # SENSOR COMPONENT # https://esphome.io/components/sensor/ -########################################################################################## +#:########################################################################################:# sensor: - platform: template id: mosfet_output_pct @@ -489,7 +515,7 @@ sensor: unit_of_measurement: "%" icon: mdi:percent accuracy_decimals: 0 - update_interval: 2s # consider 200ms if you want fewer updates + update_interval: 2s lambda: |- const auto &cv = id(mosfet_leds).current_values; return cv.is_on() ? (float) (int)(cv.get_brightness() * 100.0f + 0.5f) : 0.0f; @@ -530,28 +556,29 @@ sensor: if (pwm > 1.0f) pwm = 1.0f; return pwm * 100.0f; -########################################################################################## +#:########################################################################################:# # OUTPUT COMPONENT # https://esphome.io/components/light/index.html -########################################################################################## +#:########################################################################################:# # An OUTPUT can be binary (0,1) or float, which is any value between 0 and 1. # PWM Outputs such as "ledc" are float. https://esphome.io/components/output/ledc.html -########################################################################################## +#:########################################################################################:# output: - platform: esp8266_pwm id: mosfet_pwm pin: ${device_mosfet_out} frequency: ${pwm_frequency} + - platform: gpio id: green_led_out # Green LED pin: number: ${device_fading_led} inverted: false -########################################################################################## +#:########################################################################################:# # LIGHT COMPONENT # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: monochromatic id: mosfet_leds @@ -570,14 +597,14 @@ light: payload: "${mqtt_local_device_command_ON}" retain: true - lambda: |- - // Do not flip "intent to ON" when we're inside an OFF ramp's floor-kick + // Do not flip "intent to ON" when we are inside an OFF ramp's floor-kick if (!id(ramping_for_off)) { id(ramp_switch_target_on) = true; } - script.stop: max_on_watchdog - if: condition: - lambda: 'return id(max_on_hours) > 0;' + lambda: "return id(max_on_hours) > 0;" then: - script.execute: max_on_watchdog @@ -587,13 +614,13 @@ light: - output.turn_off: green_led_out - if: condition: - lambda: 'return !id(booting);' + lambda: "return !id(booting);" then: - mqtt.publish: topic: "${mqtt_local_status_topic}/light/state" payload: "${mqtt_local_device_command_OFF}" retain: true - - lambda: 'id(ramp_switch_target_on) = false;' + - lambda: "id(ramp_switch_target_on) = false;" - script.stop: max_on_watchdog - lambda: |- id(last_brightness_pct) = 0.0f; @@ -614,11 +641,10 @@ light: call.set_transition_length(0); call.perform(); - -########################################################################################## +#:########################################################################################:# # NUMBER COMPONENT # https://esphome.io/components/number/ -########################################################################################## +#:########################################################################################:# number: - platform: template id: cfg_ramp_up_s @@ -683,10 +709,10 @@ number: set_action: - if: condition: - lambda: 'return x <= 0.0f;' + lambda: "return x <= 0.0f;" then: # 0 means OFF - - lambda: 'id(suppress_slider_sync) = true;' + - lambda: "id(suppress_slider_sync) = true;" - script.stop: ramp_on_script - script.stop: ramp_off_script - light.turn_off: @@ -698,7 +724,7 @@ number: id(last_brightness_pct) = 0.0f; // persist OFF immediately id(last_set_pos) = 0; - delay: 400ms - - lambda: 'id(suppress_slider_sync) = false;' + - lambda: "id(suppress_slider_sync) = false;" else: # Map 1..100 - [min..max] and set ON - lambda: |- @@ -730,7 +756,7 @@ number: if (out_pct > maxp) out_pct = maxp; id(last_brightness_pct) = out_pct; // persist exact target now - delay: 400ms - - lambda: 'id(suppress_slider_sync) = false;' + - lambda: "id(suppress_slider_sync) = false;" - platform: template id: cfg_max_on_hours @@ -753,27 +779,26 @@ number: id(cfg_max_on_hours).publish_state((float) hrs); - if: condition: - lambda: 'return id(mosfet_leds).current_values.is_on();' + lambda: "return id(mosfet_leds).current_values.is_on();" then: - script.stop: max_on_watchdog - if: condition: - lambda: 'return id(max_on_hours) > 0;' + lambda: "return id(max_on_hours) > 0;" then: - script.execute: max_on_watchdog -########################################################################################## +#:########################################################################################:# # SCRIPT COMPONENT # https://esphome.io/components/script.html # Scripts can be executed nearly anywhere in your device configuration with a single call. -########################################################################################## +#:########################################################################################:# script: - - # Script: ramp up from current level. Obey global max. (LED ON while ramping) + # Script: ramp up from current level. Obey global max. (LED ON while ramping) - id: ramp_on_script mode: restart then: - - lambda: 'id(is_ramping) = true;' + - lambda: "id(is_ramping) = true;" - script.stop: ramp_off_script # Ensure we start at at least the floor without a visible "pop". - if: @@ -785,12 +810,12 @@ script: then: - light.turn_on: id: mosfet_leds - brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' + brightness: !lambda "return id(min_brightness_pct) / 100.0f;" transition_length: 80ms # Ramp from current (>= floor) to cap over a fraction of ramp_up_ms. - light.turn_on: id: mosfet_leds - brightness: !lambda 'return id(max_brightness_pct) / 100.0f;' + brightness: !lambda "return id(max_brightness_pct) / 100.0f;" transition_length: !lambda |- const auto &cv = id(mosfet_leds).current_values; const float floor = id(min_brightness_pct) / 100.0f; @@ -810,7 +835,7 @@ script: if (frac > 1.0f) frac = 1.0f; id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); return (uint32_t) id(last_ramp_ms); - - delay: !lambda 'return (uint32_t) id(last_ramp_ms);' + - delay: !lambda "return (uint32_t) id(last_ramp_ms);" - lambda: |- id(is_ramping) = false; const auto &cv = id(mosfet_leds).current_values; @@ -823,7 +848,7 @@ script: - id: ramp_to_target_script mode: restart then: - - lambda: 'id(is_ramping) = true;' + - lambda: "id(is_ramping) = true;" - script.stop: ramp_off_script # Ensure we start at the floor cleanly. - if: @@ -835,7 +860,7 @@ script: then: - light.turn_on: id: mosfet_leds - brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' + brightness: !lambda "return id(min_brightness_pct) / 100.0f;" transition_length: 80ms # Ramp from current (>= floor) to restore_target_pct over a fraction of ramp_up_ms. - light.turn_on: @@ -866,7 +891,7 @@ script: if (frac > 1.0f) frac = 1.0f; id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); return (uint32_t) id(last_ramp_ms); - - delay: !lambda 'return (uint32_t) id(last_ramp_ms);' + - delay: !lambda "return (uint32_t) id(last_ramp_ms);" - lambda: |- id(is_ramping) = false; const auto &cv = id(mosfet_leds).current_values; @@ -875,7 +900,6 @@ script: id(last_brightness_pct) = pct; // persist final level } - # Script: ramp down from current level to floor, then cleanly cut to OFF. (LED ON while ramping) - id: ramp_off_script mode: restart @@ -886,7 +910,7 @@ script: - script.stop: ramp_on_script - light.turn_on: id: mosfet_leds - brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' + brightness: !lambda "return id(min_brightness_pct) / 100.0f;" transition_length: !lambda |- const auto &cv = id(mosfet_leds).current_values; const float floor = id(min_brightness_pct) / 100.0f; @@ -899,7 +923,7 @@ script: if (frac > 1.0f) frac = 1.0f; id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac); return (uint32_t) id(last_ramp_ms); - - delay: !lambda 'return (uint32_t) id(last_ramp_ms);' + - delay: !lambda "return (uint32_t) id(last_ramp_ms);" - light.turn_off: id: mosfet_leds transition_length: 150ms @@ -916,12 +940,12 @@ script: then: - if: condition: - lambda: 'return id(max_on_hours) > 0;' + lambda: "return id(max_on_hours) > 0;" then: - - delay: !lambda 'return (uint32_t) (id(max_on_hours) * 3600000UL);' + - delay: !lambda "return (uint32_t) (id(max_on_hours) * 3600000UL);" - if: condition: - lambda: 'return id(mosfet_leds).current_values.is_on();' + lambda: "return id(mosfet_leds).current_values.is_on();" then: - lambda: |- id(ramp_switch_target_on) = false; @@ -948,18 +972,18 @@ script: - if: condition: - lambda: 'return id(restore_target_pct) > 0.5f;' + lambda: "return id(restore_target_pct) > 0.5f;" then: - lambda: |- id(ramp_switch_target_on) = true; // reflect our intent - id(suppress_slider_sync) = true; + id(suppress_slider_sync) = true; - script.stop: ramp_off_script - script.execute: ramp_to_target_script - - delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - - lambda: 'id(suppress_slider_sync) = false;' + - delay: !lambda "return (uint32_t) id(last_ramp_ms);" + - lambda: "id(suppress_slider_sync) = false;" else: # Exact last was 0 -> remain OFF - - lambda: 'id(ramp_switch_target_on) = false;' + - lambda: "id(ramp_switch_target_on) = false;" - light.turn_off: id: mosfet_leds transition_length: 0s diff --git a/esphome/esp-loungecabinetleds2.yaml b/esphome/esp-loungecabinetleds.yaml similarity index 73% rename from esphome/esp-loungecabinetleds2.yaml rename to esphome/esp-loungecabinetleds.yaml index 02986bf..dc2bf12 100644 --- a/esphome/esp-loungecabinetleds2.yaml +++ b/esphome/esp-loungecabinetleds.yaml @@ -1,76 +1,95 @@ -########################################################################################## -########################################################################################## -# Title: LOUNGE CABINET LEDS -# Repo: https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungecabinetleds.yaml +#:########################################################################################:# +# TITLE: LOUNGE CABINET LEDS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungecabinetleds.yaml +#:########################################################################################:# +# VERSIONS: +# V2.1 2026-03-11 Updated yaml to zorruno layout V1.1 +# V2.0 2025-09-15 A bunch of fixes, this is now the master for other similar mosfet controllers of mine +# V1.5 2025-09-11 First setup (copied from another template) +#:########################################################################################:# +# HARDWARE: +# - Sinilink MOSFET Board XY-WFMS (ESP8266) - sometimes listed as "XY-VFMS" +# - Reference: +# https://devices.esphome.io/devices/Sinilink-XY-WFMS +# - DEVICE GPIO (Sinilink XY-WFMS) +# - GPIO2 Blue LED, active-low (used for ESPHome status) +# - GPIO4 MOSFET output (0V when switched) and Red LED +# - GPIO12 Toggle button +# - GPIO13 Green LED (used to display fading status) +# - 3D-printed case for Sinilink XY-WFMS: +# https://cults3d.com/en/3d-model/tool/snapfit-enclosure-for-esp8266-sinilink-xy-wfms-5v-36v-mosfet-switch-module +#:########################################################################################:# +# OPERATION NOTES: +# - General-purpose LED controller. +# - Designed for the Sinilink XY-WFMS board with a MOSFET output (claimed 5A, 5-36 V DC), but will suit similar MOSFET boards. +# - In SUBSTITUTIONS there is a MAX % output setting to extend LED life. +# - In SUBSTITUTIONS there is a minimum output setting; switches fully OFF at/below the minimum to avoid low-PWM flicker. +# - In SUBSTITUTIONS PWM frequency is set to 1kHz by default. You can increase it, but higher values caused resets on Sinilink device. +# - On ESP32 you can run much higher PWM frequencies (about 40 kHz). +# - Min/Max output settings are not exposed in Home Assistant/MQTT by default, but could be. +# - With a 1 MB flash, space is tight and only minimal optimisation has been done so far. +# - Included packages provide network settings, diagnostic entities, MQTT, and optional SNTP. +# - Default restart behaviours: +# - Fade up to full +# - Restore Brightness +# - Remain Off +# - The green LED flashes while fading. The red LED follows the output because it shares the MOSFET GPIO. +# - Fade timing scales with the configured values proportionally when starting mid-brightness. +# - Exposed in Home Assistant/MQTT: +# - Startup action (On, Off, Restore) +# - Fade Up / Fade Down / Fade Stop buttons +# - Fade Up/Down toggle switch +# - Normal On/Off switch +# - Fade up/down times (0-60s) +# - Output % (pre-gamma) and PWM % (post-gamma) +# - Output Set (1-100, respects min/max) +# - Many device diagnostics from the included diagnostics package +# - Maximum ON time before automatic fade-down (1-48 h, 0 = no limit) # -# v2.0 - 2025-09-15 A bunch of fixes, this is now the master for other similar mosfet controllers of mine -# v1.5 - 2025-09-11 First setup (copied from another template) -# -# ------------------------------------------ -# OPERATION (as of v2.0) -# ------------------------------------------ -# 1. General-purpose LED controller. -# 2. Designed for the Sinilink XY-WFMS board with a MOSFET output (claimed 5A, 5-36 V DC), but will suit similar mosfet boards. -# 3. (In SUBSTITUTIONS) setting for MAX % output to extend LED life (ie can ensure it is only ever 95%) -# 4. (In SUBSTITUTIONS) Minimum output setting; switches fully OFF at/below the minimum to avoid low-PWM flicker. -# 5. (In SUBSTITUTIONS) PWM frequency is set to 1kHz by default. You can increase it, but higher values caused -# resets on Sinilink device. On ESP32 you can run much higher (~40 kHz). -# 6. Min/Max output settings are not exposed in Home Assistant/MQTT by default, but could be. -# With a 1 MB flash, space is tight and only minimal optimisation has been done so far. -# 7. (PACKAGES) include common items: network settings, diagnostic entities, MQTT, and SNTP (optional). -# 8. Default behaviours, for recovery from lost power or reset: -# - "Fade up to full": fade from floor to max on boot. -# - "Restore Brightness": fade from floor to the last non-zero brightness on boot (should be no on/off blip/flash). -# - "Remain Off": stays off on boot. -# 9. The green LED flashes while fading (different patterns for up/down). The red LED follows the -# output (it shares the MOSFET GPIO). (Obviously this depends on hardware) -# 10. Fade timing scales with the configured values (proportionally when starting mid-brightness). -# 11. Exposed in Home Assistant/MQTT: -# - Startup action (On,Off,Restore) -# - Fade Up / Fade Down / Fade Stop buttons -# - Fade Up/Down toggle switch (keeps fading up to full, or down to off unless stopped) -# - Normal On/Off switch (quick ramp up/down, up to the level of previous brightness) -# - Fade up/down times (0-60s) -# - Output % (pre-gamma) and PWM % (post-gamma) -# - Output Set (1-100, respects min/max). This also changes with other output so reflects value. -# - Many device diagnostics (from the included 'diagnostics' package) -# - Maximum 'on' time before automatic fade-down (1-48 h, 0 = no limit) -########################################################################################### -# Hardware: Sinilink MOSFET Board XY-WFMS (ESP8266) - sometimes listed as "XY-VFMS" -# https://devices.esphome.io/devices/Sinilink-XY-WFMS -# ------------------------------------------ -# DEVICE GPIO (Sinilink XY-WFMS) -# ------------------------------------------ -# GPIO02 Blue LED, active-low (used for ESPHome status) -# GPIO04 MOSFET output (0V when switched) and Red LED -# GPIO12 Toggle button -# GPIO13 Green LED (used to display fading status) -# -# 3D-printed case for Sinilink XY-WFMS -# https://cults3d.com/en/3d-model/tool/snapfit-enclosure-for-esp8266-sinilink-xy-wfms-5v-36v-mosfet-switch-module -# -########################################################################################## -########################################################################################## +# MQTT COMMANDS: +# - ${mqtt_local_command_topic}/light/set = ON +# - ${mqtt_local_command_topic}/light/set = OFF +# - State publishes to: +# - ${mqtt_local_status_topic}/light/state +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online) +# - Local light logic, fades, restart behaviour, and watchdog timing continue to operate. +# - Local MQTT control and status publishing continue if the MQTT broker is online. +# b) MQTT offline (or HA/MQTT offline) +# - Local light logic, fades, restart behaviour, and watchdog timing continue to operate. +# - MQTT control and MQTT state publishing are unavailable. +# c) Entire WiFi/Network offline +# - Local light logic, fades, restart behaviour, and watchdog timing continue to operate. +# - Accurate time is not needed (SNTP not needed). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming - device_name: "esp-loungecabinetleds2" # yaml file should be device_name.yaml + device_name: "esp-loungecabinetleds" # yaml file should be device_name.yaml friendly_name: "Lounge Cabinet LEDs" - description_comment: "LED Strip inside the display cabinet upstairs lounge :: Sinilink XY-WFMS" + description_comment: "LED Strip inside the display cabinet upstairs lounge :: Sinilink XY-WFMS (Layout V1.1)" device_area: "Lounge" # Allows the ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot. - project_version: "v2.0" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version - + project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot. + project_version: "v2.1" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version + # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) - api_key: !secret esp-api_key # If using HA API + api_key: !secret esp-api_key # If using HA API ota_pass: !secret esp-ota_pass # If passwording OTA updates - static_ip_address: !secret esp-loungecabinetleds2_ip # CHANGE THIS + static_ip_address: !secret esp-loungecabinetleds_ip # CHANGE THIS + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # MQTT LOCAL Controls (This is just my local method of controlling via MQTT, I also use the built in method) mqtt_local_device_name: "lounge-cabinetleds" @@ -82,24 +101,24 @@ substitutions: mqtt_local_device_command_OFF: "OFF" # Device Specific Settings - log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE - update_interval: "30s" # Update time for general sensors, etc. - led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM - minimum_led_output: "1" # % If at this value or below, we'll switch it completely off - maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics - max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off - pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts + log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE + update_interval: "30s" # Update time for general sensors, etc. + led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM + minimum_led_output: "1" # % If at this value or below, we'll switch it completely off + maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics + max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off + pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts # Device Specific GPIO (so we can easily update for other devices) - device_status_led: GPIO02 - device_mosfet_out: GPIO04 - device_usr_button: GPIO12 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml - device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml + device_status_led: GPIO2 + device_mosfet_out: GPIO4 + device_usr_button: GPIO12 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml + device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -108,6 +127,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -121,27 +141,31 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - #diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + #diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -########################################################################################## -# ESPHome CORE CONFIGURATION +#:########################################################################################:# +# ESPHOME CORE CONFIGURATION # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" on_boot: # Run later so everything is initialised before we touch states. priority: 200 @@ -198,11 +222,11 @@ esphome: # - -fdata-sections # - -DNDEBUG -########################################################################################## +#:########################################################################################:# # ESP PLATFORM AND FRAMEWORK # https://esphome.io/components/esp8266.html # https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# esp8266: board: esp01_1m restore_from_flash: true # restore some values on reboot @@ -213,47 +237,52 @@ mdns: preferences: flash_write_interval: 2min # enough time to update values for reboots, but not enough to wear flash -########################################################################################## +#:########################################################################################:# # GLOBAL VARIABLES # https://esphome.io/components/globals.html -########################################################################################## +#:########################################################################################:# globals: # Minimum Brightness % for LEDs (will switch off if <=) - id: min_brightness_pct type: int restore_value: true - initial_value: "${minimum_led_output}" # start/finish at X% + initial_value: "${minimum_led_output}" # start/finish at X% + # Maximum Brightness % for LEDs (should never go beyond this) - id: max_brightness_pct type: int restore_value: false - initial_value: "${maximum_led_output}" # hard cap; never exceed this - # The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever + initial_value: "${maximum_led_output}" # hard cap; never exceed this + + # The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever - id: max_on_hours type: int restore_value: true initial_value: "${max_on_default_hours}" + # Compile time Gamma - id: led_gamma_f type: float restore_value: false - initial_value: ${led_gamma} # <-- numeric at compile time + initial_value: ${led_gamma} # numeric at compile time # Default Fading Up Time (Selectable and will be retained) - - id: ramp_up_ms # fade-in when turned ON + - id: ramp_up_ms # fade-in when turned ON type: int restore_value: true - initial_value: '5000' # 5 s + initial_value: "5000" # 5 s + # Default Fading Down Time (Selectable and will be retained) - - id: ramp_down_ms # fade-out when turned OFF + - id: ramp_down_ms # fade-out when turned OFF type: int restore_value: true - initial_value: '10000' # 10 s + initial_value: "10000" # 10 s + # Action on Restart. (0=Fade full, 1=Restore brightness, 2=Remain off) - - id: restart_mode + - id: restart_mode type: int restore_value: true - initial_value: '0' # default = Fade Up to Full (so can be deployed with no other setup) + initial_value: "0" # default = Fade Up to Full (so can be deployed with no other setup) # Determine last fade direction. # true when you asked the light to end up ON (Ramp Up) @@ -261,70 +290,78 @@ globals: - id: ramp_switch_target_on type: bool restore_value: true - initial_value: 'false' + initial_value: "false" + # Prevent jitter when adjusting the slider - id: suppress_slider_sync type: bool restore_value: false - initial_value: 'false' - # actual 0..100 seen last time, for restart - - id: last_brightness_pct + initial_value: "false" + + # actual 0..100 seen last time, for restart + - id: last_brightness_pct type: float restore_value: true - initial_value: '0.0' + initial_value: "0.0" + # last published "Output Set (0-100)" integer - id: last_set_pos type: int restore_value: false - initial_value: '-1' - # helper to keep blink time == transition time + initial_value: "-1" + + # helper to keep blink time == transition time - id: last_ramp_ms type: int restore_value: false - initial_value: '0' + initial_value: "0" + # target for "Restore Brightness" scripted ramp - id: restore_target_pct type: float restore_value: false - initial_value: '0.0' + initial_value: "0.0" + # true while a scripted ramp is in progress (to limit flash writes) - id: is_ramping type: bool restore_value: false - initial_value: 'false' + initial_value: "false" + # guards OFF persistence during startup caused by restore_mode: ALWAYS_OFF - id: booting type: bool restore_value: false - initial_value: 'true' + initial_value: "true" + # true only while we are performing a ramp-down that briefly turns the light ON to hit the floor - id: ramping_for_off type: bool restore_value: false - initial_value: 'false' + initial_value: "false" -########################################################################################## +#:########################################################################################:# # LOGGER COMPONENT # https://esphome.io/components/logger.html # Logs all log messages through the serial port and through MQTT topics. -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" # INFO Level suggested, or DEBUG for testing + level: "${log_level}" # INFO Level suggested, or DEBUG for testing baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: ${device_status_led} inverted: true -########################################################################################## +#:########################################################################################:# # MQTT COMMANDS # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: # Light control to ramp up @@ -332,16 +369,17 @@ mqtt: payload: "${mqtt_local_device_command_ON}" then: - switch.turn_on: mosfet_ramp_switch + # Light control to ramp down - topic: "${mqtt_local_command_topic}/light/set" payload: "${mqtt_local_device_command_OFF}" then: - switch.turn_off: mosfet_ramp_switch -########################################################################################## +#:########################################################################################:# # SWITCH COMPONENT # https://esphome.io/components/switch/ -########################################################################################## +#:########################################################################################:# switch: # Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce) - platform: template @@ -361,10 +399,10 @@ switch: - script.stop: ramp_on_script - script.execute: ramp_off_script -################################################################################################# +#:########################################################################################:# # BUTTON COMPONENT # https://esphome.io/components/button/index.html -################################################################################################# +#:########################################################################################:# button: # Start ramping UP (from current level) - platform: template @@ -404,7 +442,7 @@ button: id(ramping_for_off) = false; id(is_ramping) = false; - // Freeze the light at its *current* level by overwriting the transition + // Freeze the light at its current level by overwriting the transition const auto &cv = id(mosfet_leds).current_values; if (cv.is_on()) { auto call = id(mosfet_leds).make_call(); @@ -420,12 +458,10 @@ button: id(last_brightness_pct) = pct; } - - -######################################################################################### +#:########################################################################################:# # SELECT COMPONENT # https://esphome.io/components/select/index.html -######################################################################################### +#:########################################################################################:# select: - platform: template id: restart_action @@ -447,10 +483,10 @@ select: id(restart_mode) = 2; } -######################################################################################### +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio id: btn_gpio12 @@ -483,10 +519,10 @@ binary_sensor: - script.stop: ramp_off_script - script.execute: ramp_on_script -########################################################################################## +#:########################################################################################:# # SENSOR COMPONENT # https://esphome.io/components/sensor/ -########################################################################################## +#:########################################################################################:# sensor: - platform: template id: mosfet_output_pct @@ -494,7 +530,7 @@ sensor: unit_of_measurement: "%" icon: mdi:percent accuracy_decimals: 0 - update_interval: 2s # consider 200ms if you want fewer updates + update_interval: 2s # consider 200ms if you want fewer updates lambda: |- const auto &cv = id(mosfet_leds).current_values; return cv.is_on() ? (float) (int)(cv.get_brightness() * 100.0f + 0.5f) : 0.0f; @@ -535,28 +571,29 @@ sensor: if (pwm > 1.0f) pwm = 1.0f; return pwm * 100.0f; -########################################################################################## +#:########################################################################################:# # OUTPUT COMPONENT -# https://esphome.io/components/light/index.html -########################################################################################## +# https://esphome.io/components/output/ +#:########################################################################################:# # An OUTPUT can be binary (0,1) or float, which is any value between 0 and 1. # PWM Outputs such as "ledc" are float. https://esphome.io/components/output/ledc.html -########################################################################################## +#:########################################################################################:# output: - platform: esp8266_pwm id: mosfet_pwm pin: ${device_mosfet_out} frequency: ${pwm_frequency} + - platform: gpio - id: green_led_out # Green LED + id: green_led_out # Green LED pin: number: ${device_fading_led} inverted: false -########################################################################################## +#:########################################################################################:# # LIGHT COMPONENT # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: monochromatic id: mosfet_leds @@ -619,11 +656,10 @@ light: call.set_transition_length(0); call.perform(); - -########################################################################################## +#:########################################################################################:# # NUMBER COMPONENT # https://esphome.io/components/number/ -########################################################################################## +#:########################################################################################:# number: - platform: template id: cfg_ramp_up_s @@ -767,14 +803,13 @@ number: then: - script.execute: max_on_watchdog -########################################################################################## +#:########################################################################################:# # SCRIPT COMPONENT # https://esphome.io/components/script.html # Scripts can be executed nearly anywhere in your device configuration with a single call. -########################################################################################## +#:########################################################################################:# script: - - # Script: ramp up from current level. Obey global max. (LED ON while ramping) + # Script: ramp up from current level. Obey global max. (LED ON while ramping) - id: ramp_on_script mode: restart then: @@ -880,7 +915,6 @@ script: id(last_brightness_pct) = pct; // persist final level } - # Script: ramp down from current level to floor, then cleanly cut to OFF. (LED ON while ramping) - id: ramp_off_script mode: restart @@ -938,7 +972,7 @@ script: - id: deferred_restore_brightness mode: restart then: - - delay: 5s # let preferences/globals load and light settle + - delay: 5s # let preferences/globals load and light settle - lambda: |- // Use ONLY the exact last saved brightness. float target = id(last_brightness_pct); @@ -968,4 +1002,4 @@ script: - light.turn_off: id: mosfet_leds transition_length: 0s - # (Removed: output.turn_off: green_led_out) # make sure LED is off if no ramp + # (Removed: output.turn_off: green_led_out) # make sure LED is off if no ramp \ No newline at end of file diff --git a/esphome/esp-loungeenvironment.yaml b/esphome/esp-loungeenvironment.yaml index 2d9b11c..4a54981 100644 --- a/esphome/esp-loungeenvironment.yaml +++ b/esphome/esp-loungeenvironment.yaml @@ -1,31 +1,86 @@ -########################################################################################## -########################################################################################## -# LOUNGE ENVIRONMENT SENSOR -# -# ESP32-C3 SuperMini + BME280 (I2C) -# +#:########################################################################################:# +# TITLE: LOUNGE ENVIRONMENT SENSOR +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungeenvironment.yaml +#:########################################################################################:# +# VERSIONS: +# V1.5 2026-03-22 Updated yaml to zorruno layout V1.1; fixed units to °C; added +# device_class/state_class; retained MQTT publishing and all existing logic +# V1.4 2026-03-22 Updated yaml to zorruno layout V1.1; added MQTT publishing for +# temperature, humidity and pressure; retained all existing sensor logic +# V1.3 2026-03-22 Added MQTT publishing for temperature, humidity and pressure readings # V1.2 2026-02-16 Pressure tendency now 5-state over 3 hours + rate/hour, 1h removed # V1.1 2026-02-16 Added derived min/max sensors and pressure trend text sensors # V1.0 2026-02-16 Initial Version -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# - ESP32-C3 SuperMini +# - BME280 (I2C) +# - SDA = GPIO1 +# - SCL = GPIO3 +# - I2C address = 0x76 +#:########################################################################################:# +# OPERATION NOTES: +# - Reads temperature, humidity and pressure from the BME280 every 20 seconds +# - Publishes each fresh reading to local MQTT status topics: +# - ${mqtt_local_status_topic}/temperature +# - ${mqtt_local_status_topic}/humidity +# - ${mqtt_local_status_topic}/pressure +# - Tracks: +# - Lowest Temp Overnight +# - Highest Temp Today (Daytime) +# - Highest/Lowest Temp This Month +# - Highest/Lowest Temp Last Month +# - Highest/Lowest Temp Last 24 Hours +# - Lowest Humidity Overnight +# - Highest Humidity Today (Daytime) +# - Highest/Lowest Humidity This Month +# - Highest/Lowest Humidity Last Month +# - Highest/Lowest Humidity Last 24 Hours +# - Pressure direction uses a 3-hour tendency: +# - rising rapidly +# - rising +# - steady +# - falling +# - falling rapidly +# - Pressure rate per hour is calculated from the 3-hour pressure delta +#:########################################################################################:# +# OFFLINE NOTES: +# a) HA offline (network + MQTT online) +# - Device continues reading sensors and publishing local MQTT status topics. +# b) MQTT offline (or HA/MQTT offline) +# - Device continues reading sensors and updating local derived values internally. +# c) Entire WiFi/Network offline +# - Accurate time is needed for daily/monthly min/max periods and pressure trend timing. +# - If SNTP is unavailable, the fallback clock can drift and can be reset by power +# cycling at 12pm (midday). +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-loungeenvironment" friendly_name: "Lounge Environment" - description_comment: "Lounge Environment :: ESP32-C3 SuperMini + BME280" + description_comment: "Lounge Environment :: ESP32-C3 SuperMini + BME280 (Layout V1.1)" device_area: "Lounge" # Project Naming project_name: "ESP32-C3 SuperMini.BME280" - project_version: "v1.2" + project_version: "v1.5" # Passwords api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-loungeenvironment_ip + # Layout V1.1 Required + current_ip_address: ${static_ip_address} + + # MQTT Local Status + mqtt_local_status_main_topic: !secret mqtt_status_main_topic + mqtt_device_name: "lounge-environment" + mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" + # General Settings log_level: "WARN" update_interval: "60s" @@ -54,6 +109,7 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" common_api: !include @@ -73,10 +129,10 @@ packages: common_sntp: !include common/sntp_common.yaml diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml ########################################################################################## -# ESPHome +# ESPHOME ########################################################################################## esphome: name: "${device_name}" @@ -292,17 +348,26 @@ sensor: name: "${friendly_name} Temperature" id: lounge_temperature unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 on_value: then: + # Publish current temperature to local MQTT status topic + - mqtt.publish: + topic: "${mqtt_local_status_topic}/temperature" + payload: !lambda |- + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%.2f", x); + return std::string(buffer); + - lambda: |- auto now = id(sntp_time).now(); - // We only need hour buckets and month stats if we have valid SNTP. if (!now.is_valid()) return; const int hour = now.hour; const uint32_t now_ts = now.timestamp; - // Update hourly bucket (rolling 24h) { int idx = hour; if (idx < 0) idx = 0; @@ -314,9 +379,6 @@ sensor: if (isnan(id(g_temp_hour_max)[idx]) || v > id(g_temp_hour_max)[idx]) id(g_temp_hour_max)[idx] = v; } - // Daily window tracking uses current_mins so it still works during fallback. - // Overnight: 23:00 -> 07:00 - // Daytime: 07:00 -> 23:00 const int mins = id(current_mins); const bool in_overnight = (mins >= 1380) || (mins < 420); @@ -330,19 +392,43 @@ sensor: } } - // Month stats if (isnan(id(g_min_temp_this_month)) || x < id(g_min_temp_this_month)) id(g_min_temp_this_month) = x; if (isnan(id(g_max_temp_this_month)) || x > id(g_max_temp_this_month)) id(g_max_temp_this_month) = x; pressure: name: "${friendly_name} Pressure" id: lounge_pressure + unit_of_measurement: "hPa" + device_class: pressure + state_class: measurement + accuracy_decimals: 2 + on_value: + then: + # Publish current pressure to local MQTT status topic + - mqtt.publish: + topic: "${mqtt_local_status_topic}/pressure" + payload: !lambda |- + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%.2f", x); + return std::string(buffer); humidity: name: "${friendly_name} Humidity" id: lounge_humidity + unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 on_value: then: + # Publish current humidity to local MQTT status topic + - mqtt.publish: + topic: "${mqtt_local_status_topic}/humidity" + payload: !lambda |- + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%.1f", x); + return std::string(buffer); + - lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return; @@ -350,7 +436,6 @@ sensor: const int hour = now.hour; const uint32_t now_ts = now.timestamp; - // Update hourly bucket (rolling 24h) { int idx = hour; if (idx < 0) idx = 0; @@ -362,7 +447,6 @@ sensor: if (isnan(id(g_hum_hour_max)[idx]) || v > id(g_hum_hour_max)[idx]) id(g_hum_hour_max)[idx] = v; } - // Daily window tracking uses current_mins so it still works during fallback. const int mins = id(current_mins); const bool in_overnight = (mins >= 1380) || (mins < 420); @@ -376,7 +460,6 @@ sensor: } } - // Month stats if (isnan(id(g_min_humidity_this_month)) || x < id(g_min_humidity_this_month)) id(g_min_humidity_this_month) = x; if (isnan(id(g_max_humidity_this_month)) || x > id(g_max_humidity_this_month)) id(g_max_humidity_this_month) = x; @@ -385,6 +468,9 @@ sensor: name: "Lowest Temp Overnight" id: min_temp_today_overnight unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_min_temp_today_overnight); @@ -394,6 +480,9 @@ sensor: name: "Highest Temp Today (Daytime)" id: max_temp_today_daytime unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_max_temp_today_daytime); @@ -403,6 +492,9 @@ sensor: name: "Highest Temp This Month" id: max_temp_this_month unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_max_temp_this_month); @@ -412,6 +504,9 @@ sensor: name: "Highest Temp Last Month" id: max_temp_last_month unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_max_temp_last_month); @@ -421,6 +516,9 @@ sensor: name: "Lowest Temp This Month" id: min_temp_this_month unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_min_temp_this_month); @@ -430,6 +528,9 @@ sensor: name: "Lowest Temp Last Month" id: min_temp_last_month unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_min_temp_last_month); @@ -439,6 +540,9 @@ sensor: name: "Lowest Temp Last 24 Hours" id: min_temp_today unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); @@ -460,6 +564,9 @@ sensor: name: "Highest Temp Last 24 Hours" id: max_temp_today unit_of_measurement: "°C" + device_class: temperature + state_class: measurement + accuracy_decimals: 2 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); @@ -481,6 +588,9 @@ sensor: name: "Lowest Humidity Overnight" id: min_humidity_today_overnight unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_min_humidity_today_overnight); @@ -490,6 +600,9 @@ sensor: name: "Highest Humidity Today (Daytime)" id: max_humidity_today_daytime unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_max_humidity_today_daytime); @@ -499,6 +612,9 @@ sensor: name: "Highest Humidity This Month" id: max_humidity_this_month unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_max_humidity_this_month); @@ -508,6 +624,9 @@ sensor: name: "Highest Humidity Last Month" id: max_humidity_last_month unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_max_humidity_last_month); @@ -517,6 +636,9 @@ sensor: name: "Lowest Humidity This Month" id: min_humidity_this_month unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_min_humidity_this_month); @@ -526,6 +648,9 @@ sensor: name: "Lowest Humidity Last Month" id: min_humidity_last_month unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_min_humidity_last_month); @@ -535,6 +660,9 @@ sensor: name: "Lowest Humidity Last 24 Hours" id: min_humidity_today unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); @@ -556,6 +684,9 @@ sensor: name: "Highest Humidity Last 24 Hours" id: max_humidity_today unit_of_measurement: "%" + device_class: humidity + state_class: measurement + accuracy_decimals: 1 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); @@ -577,6 +708,7 @@ sensor: name: "Pressure Rate Per Hour (3h)" id: pressure_rate_per_hour_3h unit_of_measurement: "hPa/h" + state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- @@ -584,7 +716,7 @@ sensor: if (!now.is_valid()) return NAN; const uint32_t now_ts = now.timestamp; - const uint32_t target_ts = now_ts - 10800; // 3h + const uint32_t target_ts = now_ts - 10800; float past = NAN; uint32_t best_dt = 0xFFFFFFFF; @@ -610,12 +742,6 @@ sensor: ########################################################################################## text_sensor: # Pressure Direction, Last 3 Hours (5-state tendency over the last ~3 hours) - # Outputs exactly one of: - # - rising rapidly - # - rising - # - steady - # - falling - # - falling rapidly - platform: template name: "Pressure Direction, Last 3 Hours" id: pressure_rising_or_falling_3_hours @@ -625,7 +751,7 @@ text_sensor: if (!now.is_valid()) return std::string("unknown"); const uint32_t now_ts = now.timestamp; - const uint32_t target_ts = now_ts - 10800; // 3h + const uint32_t target_ts = now_ts - 10800; float past = NAN; uint32_t best_dt = 0xFFFFFFFF; @@ -689,7 +815,6 @@ interval: const bool at_0700 = (mins == 420); const bool at_2300 = (mins == 1380); - // Roll overnight window at 07:00 if (at_0700) { id(g_min_temp_today_overnight) = id(g_work_min_temp_overnight); id(g_work_min_temp_overnight) = NAN; @@ -698,7 +823,6 @@ interval: id(g_work_min_humidity_overnight) = NAN; } - // Roll daytime window at 23:00 if (at_2300) { id(g_max_temp_today_daytime) = id(g_work_max_temp_daytime); id(g_work_max_temp_daytime) = NAN; @@ -707,7 +831,6 @@ interval: id(g_work_max_humidity_daytime) = NAN; } - // Month rollover requires real date/time (SNTP valid) auto now = id(sntp_time).now(); if (!now.is_valid()) return; @@ -720,13 +843,11 @@ interval: } if (mon != id(g_current_month) || yr != id(g_current_year)) { - // Copy current month stats to last month id(g_max_temp_last_month) = id(g_max_temp_this_month); id(g_min_temp_last_month) = id(g_min_temp_this_month); id(g_max_humidity_last_month) = id(g_max_humidity_this_month); id(g_min_humidity_last_month) = id(g_min_humidity_this_month); - // Reset current month stats id(g_max_temp_this_month) = NAN; id(g_min_temp_this_month) = NAN; id(g_max_humidity_this_month) = NAN; diff --git a/esphome/esp-loungemiddleswitch.yaml b/esphome/esp-loungemiddleswitch.yaml index d150cdb..20e30bf 100644 --- a/esphome/esp-loungemiddleswitch.yaml +++ b/esphome/esp-loungemiddleswitch.yaml @@ -1,38 +1,90 @@ -########################################################################################## -########################################################################################## -# LOUNGE MIDDLE LIGHTSwITCH +#:########################################################################################:# +# TITLE: LOUNGE MIDDLE LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungemiddleswitch.yaml +#:########################################################################################:# +# VERSIONS: +# V3.6 2026-03-11 Updated yaml to zorruno layout V1.1 # V3.5 2025-07-28 YAML tidyups -########################################################################################## -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Triple push button +# - ESP8266 based +# - pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +# - Relay 1 output on GPIO13 +# - Relay 2 output on GPIO12 +# - Relay 3 output on GPIO14 +# - Button 1 input on GPIO16 +# - Button 2 input on GPIO5 +# - Button 3 input on GPIO4 +# - Status LED on GPIO2 +#:########################################################################################:# +# OPERATION NOTES: +# - Button 1: +# - Online with HA Loss manual override ON and HA Loss Test OFF: +# - Uses Home Assistant last-scene logic +# - If last scene is not "All Off", set "All Off" +# - If last scene is "All Off", set "Bright" +# - Offline/test with HA Loss manual override ON: +# - Toggles Relay_1 locally +# - Button 2: +# - Online with HA Loss manual override ON and HA Loss Test OFF: +# - Sets Home Assistant scene "Movie" +# - Offline/test with HA Loss manual override ON: +# - Toggles Relay_2 locally +# - Button 3: +# - Online with HA Loss manual override ON and HA Loss Test OFF: +# - Sets Home Assistant scene "Reading On/Off" +# - Offline/test with HA Loss manual override ON: +# - Toggles Relay_3 locally +# - On API connect: +# - If HA Loss Test is OFF, Relay_1 and Relay_2 follow HA Loss manual override state +# - If HA Loss Test is ON, relay override is not applied +# - HA Loss manual override defaults ON and persists across restarts +# - HA Loss Test defaults OFF and can force offline/test behaviour even when HA is connected +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network online): +# - Device switches to manual/offline behaviour +# - Buttons still operate local relays if HA Loss manual override is ON +# - Home Assistant scene calls are unavailable +# b) MQTT offline (or HA/MQTT offline): +# - This yaml does not depend on MQTT for its button logic +# - If Home Assistant/API is offline, device falls back to manual/offline behaviour +# - Buttons still operate local relays if HA Loss manual override is ON +# c) Entire WiFi/Network offline: +# - Device operates in local manual/offline behaviour only +# - Buttons still operate local relays if HA Loss manual override is ON +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-loungemiddleswitch" friendly_name: "Lounge Middle Lightswitch (3)" - description_comment: "Lounge Main Lightswitch using a Zemismart KS-811 Triple Push Button. Downlights South (1), Downlights Middle (2), Downlights North (3)" + description_comment: "Lounge Main Lightswitch using a Zemismart KS-811 Triple Push Button. Downlights South (1), Downlights Middle (2), Downlights North (3) (Layout V1.1)" device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "Zemismart Technologies.KS-811 Triple" # Project Details - project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_version: "v3.6" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-loungemiddleswitch_ip - #mqtt_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE @@ -51,10 +103,11 @@ substitutions: switch_2_name: "Downlights Middle" # Lights are connected via DMX dimmer (another esphome controller) (6 Downlights) switch_3_name: "Downlights North" # Lights are directly connected (2 downlights) -######################################################################################### -# PACKAGES: Included Common Packages +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -62,6 +115,7 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### @@ -79,6 +133,7 @@ packages: #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### #common_sntp: !include common/sntp_common.yaml @@ -88,10 +143,10 @@ packages: #diag_debug: !include common/include_debug_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -101,9 +156,9 @@ esphome: name: "${project_name}" version: "${project_version}" -######################################################################################### -# Home Assistant API -######################################################################################### +#:########################################################################################:# +# HOME ASSISTANT API: +#:########################################################################################:# api: on_client_connected: then: @@ -137,38 +192,38 @@ api: level: WARN format: "API disconnected: switching to manual/offline behavior" -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -######################################################################################### +#:########################################################################################:# logger: level: "${log_level}" # INFO Level suggested, or DEBUG for testing #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: - number: GPIO02 - inverted: yes + number: GPIO2 + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: # GPIO16 for KS-811 first button UNLESS # it is a single button KS-811 in which case it is GPIO00 @@ -176,7 +231,7 @@ binary_sensor: pin: number: GPIO16 mode: INPUT - inverted: True + inverted: true use_interrupt: false # This pin doesn't support interrupts so use polling. Only suppresses a warning. name: "Button 1: ${switch_1_name}" on_multi_click: @@ -231,7 +286,8 @@ binary_sensor: then: - if: condition: - lambda: 'return id(Relay_1).state;' + lambda: |- + return id(Relay_1).state; then: - switch.turn_off: Relay_1 - logger.log: @@ -250,9 +306,9 @@ binary_sensor: # GPIO05 for second button (only for KS-811-2 Double or -3 Triple) - platform: gpio pin: - number: GPIO05 + number: GPIO5 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_multi_click: # --- Single short click --- @@ -289,7 +345,8 @@ binary_sensor: then: - if: condition: - lambda: 'return id(Relay_2).state;' + lambda: |- + return id(Relay_2).state; then: - switch.turn_off: Relay_2 - logger.log: @@ -310,7 +367,7 @@ binary_sensor: pin: number: GPIO4 mode: INPUT - inverted: True + inverted: true name: "Button 3: ${switch_3_name}" on_multi_click: # --- Single short click --- @@ -347,7 +404,8 @@ binary_sensor: then: - if: condition: - lambda: 'return id(Relay_3).state;' + lambda: |- + return id(Relay_3).state; then: - switch.turn_off: Relay_3 - logger.log: @@ -363,9 +421,10 @@ binary_sensor: level: INFO format: "BTN3: Single click ignored (override OFF)" -######################################################################################### -# TEXT SENSOR COMPONENT -######################################################################################### +#:########################################################################################:# +# TEXT SENSOR COMPONENT: +# https://esphome.io/components/text_sensor/ +#:########################################################################################:# text_sensor: - platform: homeassistant id: ha_last_scene @@ -376,10 +435,10 @@ text_sensor: format: "HA last scene now: %s" args: ["x.c_str()"] -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: # GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GPIO12 - platform: gpio @@ -436,7 +495,8 @@ switch: - homeassistant.service: service: script.lounge_set_scene data: - scene_name: !lambda 'return id(ha_last_scene).state;' + scene_name: !lambda |- + return id(ha_last_scene).state; - logger.log: level: INFO format: "HA Loss Test OFF: restored last scene: %s" @@ -444,5 +504,4 @@ switch: else: - logger.log: level: WARN - format: "HA Loss Test OFF: cannot restore scene (API not connected or last scene unknown)" - + format: "HA Loss Test OFF: cannot restore scene (API not connected or last scene unknown)" \ No newline at end of file diff --git a/esphome/esp-loungenorthswitch.yaml b/esphome/esp-loungenorthswitch.yaml index ea9b74b..3c2cde1 100644 --- a/esphome/esp-loungenorthswitch.yaml +++ b/esphome/esp-loungenorthswitch.yaml @@ -1,41 +1,86 @@ -########################################################################################## -########################################################################################## -# LOUNGE NORTH SWITCH (Single Switch into hallway) +#:########################################################################################:# +# TITLE: LOUNGE NORTH SWITCH (Single Switch into hallway) +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungenorthswitch.yaml +#:########################################################################################:# +# VERSIONS: +# V4.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V4.0 2025-10-01 Copy from other device -########################################################################################## -# Zemismart KS-811 Single push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Single push button +# - ESP8266 based +# - pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +# - Button input on GPIO0 +# - Relay output on GPIO12 +# - Status LED on GPIO2 +#:########################################################################################:# +# OPERATION NOTES: +# - Single wall switch used for Lounge North / hallway control +# - This device uses Home Assistant scene calls when API is connected +# - Single click: +# - Online and HA Loss manual override ON: +# - If last scene is not "All Off", call scene "All Off" +# - If last scene is "All Off", call scene "Bright" +# - Offline and HA Loss manual override ON: +# - Toggle physical Relay_1 +# - Double click: +# - Online only, calls Home Assistant script for scene "Night Light" +# - Long hold (4s+): +# - Online only, calls Home Assistant script for scene "All Off" +# - Also fires Home Assistant event esphome.lounge_switch_hold +# - On API client connect: +# - Applies override state to Relay_1 +# - HA Loss manual override switch defaults ON and is restored after reboot +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network online): +# - API will disconnect and device switches to manual/offline behavior +# - Single click can still toggle Relay_1 when HA Loss manual override is ON +# - Double click and long hold actions that require Home Assistant are ignored # -# NOTES -# - +# b) MQTT offline (or HA/MQTT offline): +# - This yaml does not currently depend on MQTT for its switch logic +# - If Home Assistant/API is offline, device falls back to manual/offline behavior +# - Single click can still toggle Relay_1 when HA Loss manual override is ON # -########################################################################################## -########################################################################################## +# c) Entire WiFi/Network offline: +# - Device operates in local manual/offline behavior only +# - Single click can still toggle Relay_1 when HA Loss manual override is ON +# - Double click and long hold Home Assistant scene/event actions are unavailable +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-loungenorthswitch" friendly_name: "Lounge North Single Switch (1)" - description_comment: "Main Lounge from hallway Lightswitch using a Zemismart KS-811 Single Push Button. Main Lights (1)" - device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Main Lounge from hallway Lightswitch using a Zemismart KS-811 Single Push Button. Main Lights (1) (Layout V1.1)" + device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Single" # Project Details - project_version: "v4.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Single" # Project Details + project_version: "v4.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-loungenorthswitch_ip - #mqtt_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings - log_level: "DEBUG" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc # MQTT LOCAL Controls @@ -49,14 +94,15 @@ substitutions: #mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}" # Topic we will use to view status locally without HA #mqtt_remote_device_command_on: "On" #mqtt_remote_device_command_off: "Off" - + # Switch/Relay/Button Naming & Icons switch_1_name: "Main Lights" # NOTE there is no physical connection to the lights on this switch, it is connected to the dimmer ESPhome for the pelmet lights - -######################################################################################### -# PACKAGES: Included Common Packages + +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -64,6 +110,7 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### @@ -78,23 +125,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -104,6 +151,9 @@ esphome: name: "${project_name}" version: "${project_version}" +#:########################################################################################:# +# HOME ASSISTANT API: +#:########################################################################################:# api: on_client_connected: then: @@ -125,44 +175,44 @@ api: level: WARN format: "API disconnected: switching to manual/offline behavior" -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: level: "${log_level}" #INFO Level suggested, or DEBUG for testing #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: - number: GPIO02 - inverted: yes + number: GPIO2 + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO0 mode: INPUT - inverted: True + inverted: true name: "Button 1: ${switch_1_name}" on_multi_click: @@ -183,7 +233,7 @@ binary_sensor: scene_name: "Night Light" - logger.log: level: INFO - format: "BTN: Double click → Scene Night Light" + format: "BTN: Double click -> Scene Night Light" else: - logger.log: level: INFO @@ -191,8 +241,8 @@ binary_sensor: # --- Single short click --- # Online (and override ON): use HA's last scene to decide. - # If last != "All Off" → send "All Off" - # If last == "All Off" → send "Bright" + # If last != "All Off" -> send "All Off" + # If last == "All Off" -> send "Bright" # Offline (and override ON): toggle physical Relay_1 - timing: - ON for at most 0.5s @@ -218,7 +268,7 @@ binary_sensor: scene_name: "All Off" - logger.log: level: INFO - format: "BTN: Single click (online) → Last scene was not 'All Off' → Set 'All Off'" + format: "BTN: Single click (online) -> Last scene was not 'All Off' -> Set 'All Off'" else: - homeassistant.service: service: script.lounge_set_scene @@ -226,7 +276,7 @@ binary_sensor: scene_name: "Bright" - logger.log: level: INFO - format: "BTN: Single click (online) → Last scene was 'All Off' → Set 'Bright'" + format: "BTN: Single click (online) -> Last scene was 'All Off' -> Set 'Bright'" else: # OFFLINE path: only act if override ON; toggle physical relay - if: @@ -238,17 +288,18 @@ binary_sensor: then: - if: condition: - lambda: 'return id(Relay_1).state;' + lambda: |- + return id(Relay_1).state; then: - switch.turn_off: Relay_1 - logger.log: level: INFO - format: "BTN: Single click (offline) → Relay_1 OFF" + format: "BTN: Single click (offline) -> Relay_1 OFF" else: - switch.turn_on: Relay_1 - logger.log: level: INFO - format: "BTN: Single click (offline) → Relay_1 ON" + format: "BTN: Single click (offline) -> Relay_1 ON" else: - logger.log: level: INFO @@ -272,16 +323,16 @@ binary_sensor: action: "hold" - logger.log: level: INFO - format: "BTN: Long press → Scene All Off + HA event (hold)" + format: "BTN: Long press -> Scene All Off + HA event (hold)" else: - logger.log: level: INFO format: "BTN: Long press ignored (no HA connection)" -######################################################################################### -# TEXT SENSOR COMPONENT -# -######################################################################################### +#:########################################################################################:# +# TEXT SENSOR COMPONENT: +# https://esphome.io/components/text_sensor/ +#:########################################################################################:# text_sensor: - platform: homeassistant id: ha_last_scene @@ -292,13 +343,13 @@ text_sensor: level: DEBUG format: "HA last scene now: %s" args: ["x.c_str()"] - -######################################################################################### -# SWITCH COMPONENT + +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: -# GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GPIO12 + # GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GPIO12 - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO12 @@ -310,6 +361,4 @@ switch: name: "HA Loss manual override" id: ha_loss_override optimistic: true - restore_mode: RESTORE_DEFAULT_ON - - + restore_mode: RESTORE_DEFAULT_ON \ No newline at end of file diff --git a/esphome/esp-loungepelmetleds2.yaml b/esphome/esp-loungepelmetleds2.yaml index 2c11824..fdc3917 100644 --- a/esphome/esp-loungepelmetleds2.yaml +++ b/esphome/esp-loungepelmetleds2.yaml @@ -1,83 +1,95 @@ -########################################################################################## -########################################################################################## -# Title: LOUNGE - PELMET LEDS (H801, 2x Monochrome PWM) -# Repo: (new) +#:########################################################################################:# +# TITLE: LOUNGE - PELMET LEDS (H801, 2x Monochrome PWM) +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungepelmetleds2.yaml +#:########################################################################################:# +# VERSIONS: +# V2.8 2026-03-11 Updated yaml to zorruno layout V1.1 +# V2.7 2025-09-30 A bunch of fixes for final version +# V2.0 2025-09-30 Based on single MOSFET version; adapted to H801 dual-monochrome (A/B) +# V1.x History from single-channel base maintained in prior comments +#:########################################################################################:# +# HARDWARE: +# - H801 (ESP8266, 5 MOSFET outputs) +# - Used here as 2 independent monochrome PWM channels (A and B) +# - Reference hardware: +# https://devices.esphome.io/devices/Sinilink-XY-WFMS +# - Device GPIO as used here: +# - GPIO02 Blue status LED, active-low (ESPHome status) +# - GPIO15 MOSFET output A (PWM) +# - GPIO13 MOSFET output B (PWM) +# - GPIO05 Red LED (used to display status for Channel A) +# - GPIO01 Green LED (used to display status for Channel B) [UART TX, logger baud=0] +#:########################################################################################:# +# OPERATION NOTES: +# - General-purpose LED controller using an H801 board. +# - Designed for 2 independent monochrome outputs: +# - Channel A +# - Channel B +# - Minimum and maximum output limits are defined in SUBSTITUTIONS per channel. +# - Minimum output allows the light to switch fully OFF at or below the threshold to avoid low-PWM flicker. +# - PWM frequency is set in SUBSTITUTIONS. +# - Restart behaviours: +# - Fade up to full +# - Restore Brightness +# - Remain Off +# - Fade timing scales with the configured values. +# - Exposed in Home Assistant for both A and B: +# - Restart action +# - Fade Up-Down switch +# - Fade up/down times +# - Output percentage +# - Output Set slider +# - Shared maximum ON time +# - Fade Up-Down switch auto-syncs to brightness thresholds and does not itself trigger a ramp during sync. +# - This yaml currently uses Home Assistant API and diagnostics packages. +# - MQTT and SNTP packages are currently disabled in this file. +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network online): +# - Device continues to run its local light logic and stored restart behaviour. +# - Existing light states, watchdog timers, and fades continue locally. +# - No Home Assistant control is available until API connectivity returns. # -# v2.7 - a bunch of fixes for final version -# v2.0-dual - 2025-09-30 Based on single MOSFET version; adapted to H801 dual-monochrome (A/B). -# v1.x (history from single-channel base maintained in comments below) +# b) MQTT offline (or HA/MQTT offline): +# - MQTT is not enabled in this yaml, so MQTT offline has no direct effect on device logic. +# - If Home Assistant/API is also offline, control from HA is unavailable. # -# ------------------------------------------ -# OPERATION (as of v2.x) -# ------------------------------------------ -# 1. General-purpose LED controller. -# 2. Designed here for the H801 5-MOSFET board (ESP8266). Using 2 channels as independent -# monochrome outputs (A and B). The remaining 3 MOSFETs are ignored. -# 3. (In SUBSTITUTIONS) setting for MAX % output to extend LED life (ie can ensure it is only ever 95%) -# 4. (In SUBSTITUTIONS) Minimum output setting; switches fully OFF at/below the minimum to avoid low-PWM flicker. -# 5. (In SUBSTITUTIONS) PWM frequency is set to 1kHz by default. You can increase it, but higher values caused -# resets on some ESP8266 boards. On ESP32 you can run much higher (~40 kHz). -# 6. Min/Max output settings are not exposed in Home Assistant/MQTT by default, but could be. -# With a 1 MB flash, space is tight and only minimal optimisation has been done so far. -# 7. (PACKAGES) include common items: network settings, diagnostic entities, MQTT, and SNTP (optional). -# 8. Default behaviours, for recovery from lost power or reset: -# - "Fade up to full": fade from floor to max on boot. -# - "Restore Brightness": fade from floor to the last non-zero brightness on boot (no on/off blip/flash). -# - "Remain Off": stays off on boot. -# 9. The board LEDs show output on status. Channel A uses the **RED** LED on GPIO5. -# Channel B uses the **GREEN** LED on GPIO1 (UART TX; logger baud=0) -# 10. Fade timing scales with the configured values (proportionally when starting mid-brightness). -# 11. Exposed in Home Assistant/MQTT (duplicated for A and B): -# - Startup action (On,Off,Restore) -# - Fade Up/Down toggle switch -# - Normal On/Off switch (quick ramp up/down) -# - Fade up/down times (0-60s) -# - Output % (pre-gamma) -# - Output Set (1-100, respects min/max). This also changes with other output so reflects value. -# - Many device diagnostics (from the included 'diagnostics' package) -# - Maximum 'on' time before automatic fade-down (1-48 h, 0 = no limit) -# 12. The Fade Up/Down switch auto-syncs to brightness (no ramp is triggered by the sync itself): -# - Stops <33% of cap → switch shows OFF -# - Stops >66% of cap → switch shows ON -########################################################################################### -# Hardware: H801 (ESP8266, 5 MOSFET outputs) -# ------------------------------------------ -# DEVICE GPIO (H801, as used here) -# ------------------------------------------ -# GPIO02 Blue Status LED, active-low (ESPHOME status) -# GPIO12 MOSFET output A (PWM) -# GPIO13 MOSFET output B (PWM) -# GPIO05 Red LED (used to display status for Channel A) -# GPIO01 Green LED (used to display status for Channel B) [UART TX, logger baud=0] -# -########################################################################################## -########################################################################################## +# c) Entire WiFi/Network offline: +# - Device continues to run its local light logic and stored restart behaviour. +# - No HA or MQTT control is available. +# - Accurate time is not needed; SNTP is not required for operation. +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-loungepelmetleds2" # yaml file should be device_name.yaml friendly_name: "Lounge Pelmet LEDs" - description_comment: "Lounge Pelmet LEDs :: H801 dual-channel monochrome" + description_comment: "Lounge Pelmet LEDs :: H801 dual-channel monochrome (Layout V1.1)" device_area: "Lounge" # Allows the ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "H801.5xMOSFET" # Manufacturer before the dot, device after the dot. - project_version: "v2.7" # Project version denotes release of the YAML file + project_version: "v2.8" # Project version denotes release of the YAML file - # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) + # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass - static_ip_address: !secret esp-loungepelmetleds2_ip # CHANGE THIS - + ota_pass: !secret esp-ota_pass + static_ip_address: !secret esp-loungepelmetleds2_ip + current_ip_address: ${static_ip_address} + # Device Specific Settings (shared defaults applied per channel below) - log_level: "NONE" # Use INFO while testing; flip back to NONE later - update_interval: "60s" - led_gamma: "1.6" - pwm_frequency: "1000Hz" + log_level: "NONE" # Use INFO while testing; flip back to NONE later + update_interval: "60s" + led_gamma: "1.6" + pwm_frequency: "1000Hz" max_on_default_hours: "24" # Per-channel output caps (%), internal-only (no HA sliders) @@ -87,49 +99,64 @@ substitutions: maximum_led_output_B: "90" # Device Specific GPIO - #device_status_led: GPIO05 + #device_status_led: GPIO5 device_mosfet_out_A: GPIO15 device_mosfet_out_B: GPIO13 - device_fading_led_A: GPIO05 - device_fading_led_B: GPIO01 + device_fading_led_A: GPIO5 + device_fading_led_B: GPIO1 -########################################################################################## -# PACKAGES -########################################################################################## +#:########################################################################################:# +# PACKAGES: +# Included Common Packages +# https://esphome.io/components/packages.html +#:########################################################################################:# packages: + #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include file: common/network_common.yaml vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" + #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include + #file: common/api_common.yaml file: common/api_common_noencryption.yaml vars: local_api_key: "${api_key}" + #### MQTT #### #common_mqtt: !include # file: common/mqtt_common.yaml # vars: # local_device_name: "${device_name}" - + + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - #common_sntp: !include common/sntp_common.yaml - diag_basic: !include common/include_basic_diag_sensors.yaml - #diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### + #common_sntp: !include common/sntp_common.yaml -########################################################################################## -# ESPHome CORE CONFIGURATION -########################################################################################## + #### DIAGNOSTICS Sensors #### + diag_basic: !include common/include_basic_diag_sensors.yaml + #diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + +#:########################################################################################:# +# ESPHOME CORE CONFIGURATION: +# https://esphome.io/components/esphome.html +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" on_boot: priority: 200 then: @@ -171,9 +198,22 @@ esphome: transition_length: 0s - lambda: 'id(booting) = false;' -########################################################################################## -# ESP PLATFORM AND FRAMEWORK -########################################################################################## +# Only if you want to play with build flags... +# platformio_options: +# build_unflags: +# - -flto +# build_flags: +# - -fno-lto +# - -Wl,--gc-sections +# - -ffunction-sections +# - -fdata-sections +# - -DNDEBUG + +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +# https://esphome.io/components/esp32.html +#:########################################################################################:# esp8266: board: esp01_1m restore_from_flash: true @@ -182,25 +222,29 @@ mdns: disabled: true preferences: - flash_write_interval: 5min # reduce flash churn while testing + flash_write_interval: 5min -########################################################################################## -# GLOBAL VARIABLES -########################################################################################## +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/components/globals.html +#:########################################################################################:# globals: # Per-channel brightness caps (internal; set via YAML substitutions) - id: min_brightness_pct_A type: int restore_value: true initial_value: "${minimum_led_output_A}" + - id: max_brightness_pct_A type: int restore_value: false initial_value: "${maximum_led_output_A}" + - id: min_brightness_pct_B type: int restore_value: true initial_value: "${minimum_led_output_B}" + - id: max_brightness_pct_B type: int restore_value: false @@ -216,123 +260,146 @@ globals: - id: ramp_up_ms_A type: int restore_value: true - initial_value: '5000' + initial_value: "5000" + - id: ramp_down_ms_A type: int restore_value: true - initial_value: '10000' + initial_value: "10000" + - id: ramp_up_ms_B type: int restore_value: true - initial_value: '5000' + initial_value: "5000" + - id: ramp_down_ms_B type: int restore_value: true - initial_value: '10000' + initial_value: "10000" # Restart Action. (0=Fade full, 1=Restore brightness, 2=Remain off) - id: restart_mode type: int restore_value: true - initial_value: '1' # align with select initial_option "Restore Brightness" + initial_value: "1" # align with select initial_option "Restore Brightness" # Per-channel runtime state (A) - id: ramp_switch_target_on_A type: bool restore_value: true - initial_value: 'false' + initial_value: "false" + - id: suppress_slider_sync_A type: bool restore_value: false - initial_value: 'false' - - id: suppress_quick_on_A # guard to prevent quick-to-cap on slider turn-on + initial_value: "false" + + - id: suppress_quick_on_A type: bool restore_value: false - initial_value: 'false' + initial_value: "false" + - id: last_brightness_pct_A type: float restore_value: true - initial_value: '0.0' + initial_value: "0.0" + - id: last_set_pos_A type: int restore_value: false - initial_value: '-1' + initial_value: "-1" + - id: last_ramp_ms_A type: uint32_t restore_value: false - initial_value: '0' + initial_value: "0" + - id: last_nonzero_brightness_pct_A type: float restore_value: true - initial_value: '0.0' + initial_value: "0.0" + - id: restore_target_pct_A type: float restore_value: false - initial_value: '0.0' + initial_value: "0.0" + - id: is_ramping_A type: bool restore_value: false - initial_value: 'false' + initial_value: "false" + - id: last_nonzero_tmp_A type: float restore_value: false - initial_value: '0.0' + initial_value: "0.0" + - id: ramping_for_off_A type: bool restore_value: false - initial_value: 'false' + initial_value: "false" # Per-channel runtime state (B) - id: ramp_switch_target_on_B type: bool restore_value: true - initial_value: 'false' + initial_value: "false" + - id: suppress_slider_sync_B type: bool restore_value: false - initial_value: 'false' - - id: suppress_quick_on_B # guard to prevent quick-to-cap on slider turn-on + initial_value: "false" + + - id: suppress_quick_on_B type: bool restore_value: false - initial_value: 'false' + initial_value: "false" + - id: last_brightness_pct_B type: float restore_value: true - initial_value: '0.0' + initial_value: "0.0" + - id: last_set_pos_B type: int restore_value: false - initial_value: '-1' + initial_value: "-1" + - id: last_ramp_ms_B type: uint32_t restore_value: false - initial_value: '0' + initial_value: "0" + - id: last_nonzero_brightness_pct_B type: float restore_value: true - initial_value: '0.0' + initial_value: "0.0" + - id: restore_target_pct_B type: float restore_value: false - initial_value: '0.0' + initial_value: "0.0" + - id: is_ramping_B type: bool restore_value: false - initial_value: 'false' + initial_value: "false" + - id: last_nonzero_tmp_B type: float restore_value: false - initial_value: '0.0' + initial_value: "0.0" + - id: ramping_for_off_B type: bool restore_value: false - initial_value: 'false' + initial_value: "false" # Guard for startup behaviour - id: booting type: bool restore_value: false - initial_value: 'true' + initial_value: "true" # Compile time Gamma (cached; currently unused since PWM% sensors were removed) - id: led_gamma_f @@ -340,48 +407,51 @@ globals: restore_value: false initial_value: ${led_gamma} -########################################################################################## -# LOGGER -########################################################################################## +#:########################################################################################:# +# LOGGER: +# https://esphome.io/components/logger.html +#:########################################################################################:# logger: level: "${log_level}" baud_rate: 0 -######################################################################################### -# STATUS LED -######################################################################################### +#:########################################################################################:# +# STATUS LED: +# https://esphome.io/components/status_led.html +#:########################################################################################:# #status_led: # pin: # number: ${device_status_led} # inverted: true -########################################################################################## -# MQTT COMMANDS -########################################################################################## +#:########################################################################################:# +# MQTT COMMANDS: +#:########################################################################################:# #mqtt: - # on_message handlers commented for efficiency (S8). Uncomment if you need local MQTT control again. - #on_message: - # - topic: "${mqtt_local_command_topic_A}/lightA/set" - # payload: "${mqtt_local_device_command_ON}" - # then: - # - switch.turn_on: mosfet_ramp_switch_a - # - topic: "${mqtt_local_command_topic_A}/lightA/set"} - # payload: "${mqtt_local_device_command_OFF}" - # then: - # - switch.turn_off: mosfet_ramp_switch_a - # - # - topic: "${mqtt_local_command_topic_B}/lightB/set" - # payload: "${mqtt_local_device_command_ON}" - # then: - # - switch.turn_on: mosfet_ramp_switch_b - # - topic: "${mqtt_local_command_topic_B}/lightB/set" - # payload: "${mqtt_local_device_command_OFF}" - # then: - # - switch.turn_off: mosfet_ramp_switch_b +# on_message handlers commented for efficiency. Uncomment if you need local MQTT control again. +# on_message: +# - topic: "${mqtt_local_command_topic_A}/lightA/set" +# payload: "${mqtt_local_device_command_ON}" +# then: +# - switch.turn_on: mosfet_ramp_switch_a +# - topic: "${mqtt_local_command_topic_A}/lightA/set" +# payload: "${mqtt_local_device_command_OFF}" +# then: +# - switch.turn_off: mosfet_ramp_switch_a +# +# - topic: "${mqtt_local_command_topic_B}/lightB/set" +# payload: "${mqtt_local_device_command_ON}" +# then: +# - switch.turn_on: mosfet_ramp_switch_b +# - topic: "${mqtt_local_command_topic_B}/lightB/set" +# payload: "${mqtt_local_device_command_OFF}" +# then: +# - switch.turn_off: mosfet_ramp_switch_b -########################################################################################## -# SWITCHES -########################################################################################## +#:########################################################################################:# +# SWITCH COMPONENT: +# https://esphome.io/components/switch/ +#:########################################################################################:# switch: - platform: template id: mosfet_ramp_switch_a @@ -417,13 +487,15 @@ switch: - script.stop: ramp_on_script_B - script.execute: ramp_off_script_B -################################################################################################# -# BUTTONS (none) -################################################################################################# +#:########################################################################################:# +# BUTTON COMPONENT: +# No standalone template button entities in this yaml +#:########################################################################################:# -######################################################################################### -# SELECTS -######################################################################################### +#:########################################################################################:# +# SELECT COMPONENT: +# https://esphome.io/components/select/index.html +#:########################################################################################:# select: - platform: template id: restart_action @@ -445,9 +517,10 @@ select: id(restart_mode) = 2; } -########################################################################################## -# SENSORS -########################################################################################## +#:########################################################################################:# +# SENSOR COMPONENT: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: # Channel A: Output % (pre-gamma) - platform: template @@ -456,7 +529,7 @@ sensor: unit_of_measurement: "%" icon: mdi:percent accuracy_decimals: 0 - update_interval: 200ms # show real-time ramp + update_interval: 200ms disabled_by_default: true lambda: |- const auto &cv = id(mosfet_leds_A).current_values; @@ -488,22 +561,21 @@ sensor: id(led_output_set_pct_A).publish_state(pos_i); } } - // Auto-sync fade switch to brightness thresholds (no scripts) if (!id(booting) && !id(is_ramping_A)) { - float cap = (float) id(max_brightness_pct_A); // cap in % - float low_th = cap * 0.33f; + float cap = (float) id(max_brightness_pct_A); + float low_th = cap * 0.33f; float high_th = cap * 0.66f; if (cv_now.is_on()) { - float b = x; // current brightness in % - if (b < low_th - 0.25f) { // hysteresis margin + float b = x; + if (b < low_th - 0.25f) { if (id(ramp_switch_target_on_A)) { id(ramp_switch_target_on_A) = false; - id(mosfet_ramp_switch_a).publish_state(false); // UI-only; no ramp + id(mosfet_ramp_switch_a).publish_state(false); } } else if (b > high_th + 0.25f) { if (!id(ramp_switch_target_on_A)) { id(ramp_switch_target_on_A) = true; - id(mosfet_ramp_switch_a).publish_state(true); // UI-only; no ramp + id(mosfet_ramp_switch_a).publish_state(true); } } } @@ -548,10 +620,9 @@ sensor: id(led_output_set_pct_B).publish_state(pos_i); } } - // Auto-sync fade switch to brightness thresholds (no scripts) if (!id(booting) && !id(is_ramping_B)) { float cap = (float) id(max_brightness_pct_B); - float low_th = cap * 0.33f; + float low_th = cap * 0.33f; float high_th = cap * 0.66f; if (cv_now.is_on()) { float b = x; @@ -569,14 +640,16 @@ sensor: } } -########################################################################################## -# OUTPUTS -########################################################################################## +#:########################################################################################:# +# OUTPUT COMPONENT: +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: mosfet_pwm_A pin: ${device_mosfet_out_A} frequency: ${pwm_frequency} + - platform: esp8266_pwm id: mosfet_pwm_B pin: ${device_mosfet_out_B} @@ -587,27 +660,28 @@ output: pin: number: ${device_fading_led_A} inverted: false + - platform: gpio id: fading_led_out_B pin: number: ${device_fading_led_B} inverted: false -########################################################################################## -# LIGHTS -########################################################################################## +#:########################################################################################:# +# LIGHT COMPONENT: +# https://esphome.io/components/light/ +#:########################################################################################:# light: - platform: monochromatic id: mosfet_leds_A name: "${friendly_name} A" output: mosfet_pwm_A restore_mode: RESTORE_DEFAULT_OFF - default_transition_length: 250ms # quick ramp for normal light toggle + default_transition_length: 250ms icon: mdi:led-strip-variant gamma_correct: "${led_gamma}" on_turn_on: - # Start/refresh Max-On watchdog quietly whenever light turns on - if: condition: lambda: 'return id(max_on_hours) > 0;' @@ -628,13 +702,11 @@ light: on_state: - lambda: |- - // Mirror board RED LED to this channel's on/off const auto &cv_s = id(mosfet_leds_A).current_values; const bool is_on = cv_s.is_on() && (cv_s.get_brightness() > 0.0005f); if (is_on) id(fading_led_out_A).turn_on(); else id(fading_led_out_A).turn_off(); - lambda: |- - // Enforce cap if anyone tries to exceed it const float cap = id(max_brightness_pct_A) / 100.0f; const auto &cv = id(mosfet_leds_A).current_values; if (!cv.is_on()) return; @@ -651,7 +723,7 @@ light: name: "${friendly_name} B" output: mosfet_pwm_B restore_mode: RESTORE_DEFAULT_OFF - default_transition_length: 250ms # quick ramp for normal light toggle + default_transition_length: 250ms icon: mdi:led-strip-variant gamma_correct: "${led_gamma}" @@ -676,7 +748,6 @@ light: on_state: - lambda: |- - // Mirror board GREEN LED to this channel's on/off const auto &cv_s = id(mosfet_leds_B).current_values; const bool is_on = cv_s.is_on() && (cv_s.get_brightness() > 0.0005f); if (is_on) id(fading_led_out_B).turn_on(); @@ -693,9 +764,10 @@ light: call.set_transition_length(0); call.perform(); -########################################################################################## -# NUMBERS -########################################################################################## +#:########################################################################################:# +# NUMBER COMPONENT: +# https://esphome.io/components/number/ +#:########################################################################################:# number: - platform: template id: cfg_ramp_up_s_A @@ -777,7 +849,6 @@ number: id(ramp_down_ms_B) = secs * 1000; id(cfg_ramp_down_s_B).publish_state((float) secs); - # Per-channel position slider (0..100 mapped into [min..max]) - platform: template id: led_output_set_pct_A name: "${friendly_name} A Output Set (0-100)" @@ -788,11 +859,11 @@ number: step: 1 lambda: |- const auto &cv = id(mosfet_leds_A).current_values; - float actual = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; // 0..100 actual + float actual = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; float minp = (float) id(min_brightness_pct_A); float maxp = (float) id(max_brightness_pct_A); - if (maxp <= minp) maxp = minp + 1.0f; // avoid div/0 - if (actual <= 0.0f) return 0.0f; // when OFF, show 0 + if (maxp <= minp) maxp = minp + 1.0f; + if (actual <= 0.0f) return 0.0f; float pos = (actual - minp) * 100.0f / (maxp - minp); if (pos < 0.0f) pos = 0.0f; if (pos > 100.0f) pos = 100.0f; @@ -817,22 +888,19 @@ number: else: - lambda: |- id(suppress_slider_sync_A) = true; - float pos = x; // 0..100 - if (pos < 1.0f) pos = 1.0f; // 0 is OFF + float pos = x; + if (pos < 1.0f) pos = 1.0f; if (pos > 100.0f) pos = 100.0f; id(led_output_set_pct_A).publish_state((int) floorf(pos + 0.5f)); - // Map slider position into absolute % within [min..max] float minp = (float) id(min_brightness_pct_A); float maxp = (float) id(max_brightness_pct_A); if (maxp <= minp) maxp = minp + 1.0f; float out_pct = minp + (pos * (maxp - minp) / 100.0f); if (out_pct > maxp) out_pct = maxp; - // Stash target for the ramp script id(restore_target_pct_A) = out_pct; - // Choose duration by direction (up vs down) const auto &cv = id(mosfet_leds_A).current_values; float curr = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; id(last_ramp_ms_A) = (out_pct > curr) ? id(ramp_up_ms_A) : id(ramp_down_ms_A); @@ -852,11 +920,11 @@ number: step: 1 lambda: |- const auto &cv = id(mosfet_leds_B).current_values; - float actual = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; // 0..100 actual + float actual = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; float minp = (float) id(min_brightness_pct_B); float maxp = (float) id(max_brightness_pct_B); - if (maxp <= minp) maxp = minp + 1.0f; // avoid div/0 - if (actual <= 0.0f) return 0.0f; // when OFF, show 0 + if (maxp <= minp) maxp = minp + 1.0f; + if (actual <= 0.0f) return 0.0f; float pos = (actual - minp) * 100.0f / (maxp - minp); if (pos < 0.0f) pos = 0.0f; if (pos > 100.0f) pos = 100.0f; @@ -881,22 +949,19 @@ number: else: - lambda: |- id(suppress_slider_sync_B) = true; - float pos = x; // 0..100 - if (pos < 1.0f) pos = 1.0f; // 0 is OFF + float pos = x; + if (pos < 1.0f) pos = 1.0f; if (pos > 100.0f) pos = 100.0f; id(led_output_set_pct_B).publish_state((int) floorf(pos + 0.5f)); - // Map slider position into absolute % within [min..max] float minp = (float) id(min_brightness_pct_B); float maxp = (float) id(max_brightness_pct_B); if (maxp <= minp) maxp = minp + 1.0f; float out_pct = minp + (pos * (maxp - minp) / 100.0f); if (out_pct > maxp) out_pct = maxp; - // Stash target for the ramp script id(restore_target_pct_B) = out_pct; - // Choose duration by direction (up vs down) const auto &cv = id(mosfet_leds_B).current_values; float curr = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; id(last_ramp_ms_B) = (out_pct > curr) ? id(ramp_up_ms_B) : id(ramp_down_ms_B); @@ -906,8 +971,6 @@ number: - delay: !lambda 'return (uint32_t) id(last_ramp_ms_B);' - lambda: 'id(suppress_slider_sync_B) = false;' - - # Shared "Max On" hours (0=disabled). When light is turned on, watchdog restarts. - platform: template id: cfg_max_on_hours name: "${friendly_name} Max On (h)" @@ -923,11 +986,10 @@ number: set_action: - lambda: |- int hrs = (int) x; - if (hrs < 0) hrs = 0; + if (hrs < 0) hrs = 0; if (hrs > 48) hrs = 48; id(max_on_hours) = hrs; id(cfg_max_on_hours).publish_state((float) hrs); - # Restart/stop watchdogs appropriately for both channels - if: condition: lambda: 'return id(mosfet_leds_A).current_values.is_on();' @@ -949,9 +1011,10 @@ number: then: - script.execute: max_on_watchdog_B -########################################################################################## -# SCRIPTS -########################################################################################## +#:########################################################################################:# +# SCRIPT COMPONENT: +# https://esphome.io/components/script.html +#:########################################################################################:# script: # Ramps: Channel A - id: ramp_on_script_A @@ -959,7 +1022,6 @@ script: then: - lambda: 'id(is_ramping_A) = true;' - script.stop: ramp_off_script_A - # Single transition to CAP for the full configured time - light.turn_on: id: mosfet_leds_A brightness: !lambda 'return id(max_brightness_pct_A) / 100.0f;' @@ -1000,7 +1062,6 @@ script: id(is_ramping_A) = true; id(ramping_for_off_A) = true; - script.stop: ramp_on_script_A - # Single transition directly to OFF for the full configured time - light.turn_off: id: mosfet_leds_A transition_length: !lambda 'return (uint32_t) id(ramp_down_ms_A);' @@ -1039,7 +1100,7 @@ script: float minp = (float) id(min_brightness_pct_A); float maxp = (float) id(max_brightness_pct_A); if (target > 0.0f && target < minp) target = minp; - if (target > maxp) target = maxp; + if (target > maxp) target = maxp; id(restore_target_pct_A) = target; id(last_ramp_ms_A) = id(ramp_up_ms_A); - if: @@ -1048,14 +1109,14 @@ script: then: - lambda: |- id(ramp_switch_target_on_A) = true; - id(suppress_slider_sync_A) = true; - id(suppress_quick_on_A) = true; + id(suppress_slider_sync_A) = true; + id(suppress_quick_on_A) = true; - script.stop: ramp_off_script_A - script.execute: ramp_to_target_script_A - delay: !lambda 'return (uint32_t) id(last_ramp_ms_A);' - lambda: |- - id(suppress_slider_sync_A) = false; - id(suppress_quick_on_A) = false; + id(suppress_slider_sync_A) = false; + id(suppress_quick_on_A) = false; else: - lambda: 'id(ramp_switch_target_on_A) = false;' - light.turn_off: @@ -1146,7 +1207,7 @@ script: float minp = (float) id(min_brightness_pct_B); float maxp = (float) id(max_brightness_pct_B); if (target > 0.0f && target < minp) target = minp; - if (target > maxp) target = maxp; + if (target > maxp) target = maxp; id(restore_target_pct_B) = target; id(last_ramp_ms_B) = id(ramp_up_ms_B); - if: @@ -1155,18 +1216,16 @@ script: then: - lambda: |- id(ramp_switch_target_on_B) = true; - id(suppress_slider_sync_B) = true; - id(suppress_quick_on_B) = true; + id(suppress_slider_sync_B) = true; + id(suppress_quick_on_B) = true; - script.stop: ramp_off_script_B - script.execute: ramp_to_target_script_B - delay: !lambda 'return (uint32_t) id(last_ramp_ms_B);' - lambda: |- - id(suppress_slider_sync_B) = false; - id(suppress_quick_on_B) = false; + id(suppress_slider_sync_B) = false; + id(suppress_quick_on_B) = false; else: - lambda: 'id(ramp_switch_target_on_B) = false;' - light.turn_off: id: mosfet_leds_B - transition_length: 0s -########################################################################################## -########################################################################################## + transition_length: 0s \ No newline at end of file diff --git a/esphome/esp-loungesouthleftswitch.yaml b/esphome/esp-loungesouthleftswitch.yaml index c7859f8..8764bf3 100644 --- a/esphome/esp-loungesouthleftswitch.yaml +++ b/esphome/esp-loungesouthleftswitch.yaml @@ -1,35 +1,86 @@ -########################################################################################## -########################################################################################## -# LOUNGE SOUTH LEFT LIGHTSWITCH +#:########################################################################################:# +# TITLE: LOUNGE SOUTH LEFT LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungesouthleftswitch.yaml +#:########################################################################################:# +# VERSIONS: +# V4.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V4.0 2025-10-04 Copied from other device -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Double push button +# - ESP8266 based +# - pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +# - Relay 1 output on GPIO13 +# - Relay 2 output on GPIO12 +# - Button 1 input on GPIO16 +# - Button 2 input on GPIO5 +# - Status LED on GPIO2 +#:########################################################################################:# +# OPERATION NOTES: +# - Lounge South Left switch with 2 outputs: +# 1) Wall Washer Left +# 2) Outside Light 1 +# - Button 1 toggles Relay_1 locally +# - Button 2 toggles Relay_2 locally +# - Relay_2 is synchronised with a remote MQTT device: +# - Remote device name: garage-corridor-lights +# - Remote ON/OFF commands are mirrored locally +# - Local Relay_2 ON/OFF changes are published back to the remote topic +# - A guard flag is used to prevent MQTT feedback loops when Relay_2 state changes originate remotely +#:########################################################################################:# +# MQTT COMMANDS: +# - Remote command topic: +# - ${mqtt_remote_command_topic} +# - Remote status topic: +# - ${mqtt_remote_status_topic} +# - Payloads used: +# - ON +# - OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - Local button control continues to operate both relays +# - Relay_2 MQTT sync with the remote device continues if MQTT broker is online # -# NOTES -# - -########################################################################################## -########################################################################################## +# b) MQTT offline (or HA/MQTT offline): +# - Local button control continues to operate both relays +# - Relay_2 sync to the remote MQTT device is unavailable +# +# c) Entire WiFi/Network offline: +# - Local button control continues to operate both relays +# - Relay_2 sync to the remote MQTT device is unavailable +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-loungesouthleftswitch" friendly_name: "Lounge South Left Lightswitch (2)" - description_comment: "Lounge South Left Lightswitch using a Zemismart KS-811 Double Push Button. Wall Washer Left (1), Outside Light 1 (2)" - device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Lounge South Left Lightswitch using a Zemismart KS-811 Double Push Button. Wall Washer Left (1), Outside Light 1 (2) (Layout V1.1)" + device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v4.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" # Project Details + project_version: "v4.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-loungesouthleftswitch_ip + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic @@ -41,19 +92,19 @@ substitutions: # MQTT REMOTE Controls mqtt_remote_device_name: "garage-corridor-lights" mqtt_remote_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}" - mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}" + mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}" mqtt_remote_device_command_ON: "ON" mqtt_remote_device_command_OFF: "OFF" # Switch Naming switch_1_name: "Wall Washer Left" switch_2_name: "Outside Light 1" - #switch_3_name: "Nil" -######################################################################################### -# PACKAGES: Included Common Packages +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -62,6 +113,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -75,23 +127,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -101,64 +153,71 @@ esphome: name: "${project_name}" version: "${project_version}" -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: level: "${log_level}" #INFO Level suggested, or DEBUG for testing #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 +#:########################################################################################:# +# GLOBAL VARIABLES: +#:########################################################################################:# globals: - id: relay2_change_origin_remote type: bool - restore_value: no + restore_value: false initial_value: "false" -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # This pin doesn't support interrupts so use polling. Only suppresses a warning. name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 - platform: gpio pin: - number: GPIO05 + number: GPIO5 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - switch.toggle: Relay_2 +#:########################################################################################:# +# TEXT SENSOR COMPONENT: +# https://esphome.io/components/text_sensor/ +#:########################################################################################:# text_sensor: - platform: mqtt_subscribe id: remote2_status @@ -192,10 +251,10 @@ text_sensor: id(relay2_change_origin_remote) = true; - switch.turn_off: Relay_2 -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -223,7 +282,4 @@ switch: - mqtt.publish: topic: "${mqtt_remote_command_topic}" payload: "${mqtt_remote_device_command_OFF}" - - lambda: 'id(relay2_change_origin_remote) = false;' - - - + - lambda: 'id(relay2_change_origin_remote) = false;' \ No newline at end of file diff --git a/esphome/esp-loungesouthrightswitch.yaml b/esphome/esp-loungesouthrightswitch.yaml index 68cefdd..aa46bf5 100644 --- a/esphome/esp-loungesouthrightswitch.yaml +++ b/esphome/esp-loungesouthrightswitch.yaml @@ -1,37 +1,82 @@ -########################################################################################## -########################################################################################## -# LOUNGE SOUTH RIGHT LIGHTSWITCH +#:########################################################################################:# +# TITLE: LOUNGE SOUTH RIGHT LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungesouthrightswitch.yaml +#:########################################################################################:# +# VERSIONS: +# V4.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V4.0 2025-10-04 Copied from other device -########################################################################################## -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Triple push button +# - ESP8266 based +# - pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +# - Relay 1 output on GPIO13 +# - Relay 2 output on GPIO12 +# - Relay 3 output on GPIO14 +# - Button 1 input on GPIO16 +# - Button 2 input on GPIO5 +# - Button 3 input on GPIO4 +# - Status LED on GPIO2 +#:########################################################################################:# +# OPERATION NOTES: +# - Lounge South Right switch with 3 outputs: +# 1) Spare +# 2) Wall Washer Right +# 3) Breakfast Bar LEDs +# - Button 1 toggles Relay_1 locally +# - Button 2 toggles Relay_2 locally +# - Button 3 single click: +# - Offline and HA Loss manual override ON: +# - Toggles Relay_3 locally +# - Online: +# - No local action is taken +# - On API client connect: +# - Applies HA Loss manual override state to Relay_3 +# - HA Loss manual override defaults ON and is restored after reboot +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network online): +# - API disconnects and device switches to manual/offline behavior +# - Button 1 and Button 2 continue to toggle relays locally +# - Button 3 can toggle Relay_3 locally when HA Loss manual override is ON +# b) MQTT offline (or HA/MQTT offline): +# - This yaml does not currently depend on MQTT for its switch logic +# - Local button control continues to work +# - Button 3 can toggle Relay_3 locally when HA Loss manual override is ON +# c) Entire WiFi/Network offline: +# - Device operates in local manual/offline behavior only +# - Local button control continues to work +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-loungesouthrightswitch" friendly_name: "Lounge South Right Lightswitch (3)" - description_comment: "Lounge South Right Lightswitch using a Zemismart KS-811 Triple Push Button. Spare (1), Wall Washer Right (2), Breakfastbar LEDs (3)" - device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Lounge South Right Lightswitch using a Zemismart KS-811 Triple Push Button. Spare (1), Wall Washer Right (2), Breakfastbar LEDs (3) (Layout V1.1)" + device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Triple" # Project Details - project_version: "v4.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Triple" # Project Details + project_version: "v4.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-loungesouthrightswitch_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings #relay_icon: "mdi:lightbulb-group" @@ -46,12 +91,13 @@ substitutions: # Switch Naming switch_1_name: "Spare" switch_2_name: "Wall Washer Right" - switch_3_name: "Breakfast Bar LEDs" # Connected to another esphome device at the breakfast bar LEDs + switch_3_name: "Breakfast Bar LEDs" # Connected to another esphome device at the breakfast bar LEDs -######################################################################################### -# PACKAGES: Included Common Packages +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -59,6 +105,7 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### @@ -73,23 +120,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -99,6 +146,9 @@ esphome: name: "${project_name}" version: "${project_version}" +#:########################################################################################:# +# HOME ASSISTANT API: +#:########################################################################################:# api: on_client_connected: then: @@ -120,54 +170,54 @@ api: level: WARN format: "API disconnected: switching to manual/offline behavior" -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: level: "${log_level}" #INFO Level suggested, or DEBUG for testing #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # GPO16 pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only suppresses a warning. name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 - platform: gpio pin: - number: GPIO05 + number: GPIO5 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - switch.toggle: Relay_2 @@ -176,7 +226,7 @@ binary_sensor: pin: number: GPIO4 mode: INPUT - inverted: True + inverted: true name: "Button 3: ${switch_3_name}" on_multi_click: - timing: @@ -186,16 +236,17 @@ binary_sensor: - if: condition: and: - - not: api.connected + - not: + api.connected: - switch.is_on: ha_loss_override then: - switch.toggle: Relay_3 else: [] -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -218,5 +269,4 @@ switch: name: "HA Loss manual override" id: ha_loss_override optimistic: true - restore_mode: RESTORE_DEFAULT_ON - + restore_mode: RESTORE_DEFAULT_ON \ No newline at end of file diff --git a/esphome/esp-loungewestswitch.yaml b/esphome/esp-loungewestswitch.yaml index 4845993..27c48e3 100644 --- a/esphome/esp-loungewestswitch.yaml +++ b/esphome/esp-loungewestswitch.yaml @@ -1,38 +1,83 @@ -########################################################################################## -########################################################################################## -# LOUNGE WEST SWITCH (Single Switch from entranceway) +#:########################################################################################:# +# TITLE: LOUNGE WEST SWITCH (Single Switch from entranceway) +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungewestswitch.yaml +#:########################################################################################:# +# VERSIONS: +# V4.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V4.0 2025-10-04 Copy from other device -########################################################################################## -# Zemismart KS-811 Single push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Single push button +# - ESP8266 based +# - pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +# - Button input on GPIO0 +# - Relay output on GPIO12 +# - Status LED on GPIO2 +#:########################################################################################:# +# OPERATION NOTES: +# - Single wall switch used for Lounge West / entranceway control +# - This device uses Home Assistant scene calls when API is connected +# - Single click: +# - Online and HA Loss manual override ON: +# - If last scene is not "All Off", call scene "All Off" +# - If last scene is "All Off", call scene "Bright" +# - Offline and HA Loss manual override ON: +# - Toggle physical Relay_1 +# - Double click: +# - Online only, calls Home Assistant script for scene "Night Light" +# - Long hold (4s+): +# - Online only, calls Home Assistant script for scene "All Off" +# - Also fires Home Assistant event esphome.lounge_switch_hold +# - On API client connect: +# - Applies override state to Relay_1 +# - HA Loss manual override switch defaults ON and is restored after reboot +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network online): +# - API will disconnect and device switches to manual/offline behavior +# - Single click can still toggle Relay_1 when HA Loss manual override is ON +# - Double click and long hold actions that require Home Assistant are ignored # -# NOTES -# - +# b) MQTT offline (or HA/MQTT offline): +# - This yaml does not currently depend on MQTT for its switch logic +# - If Home Assistant/API is offline, device falls back to manual/offline behavior +# - Single click can still toggle Relay_1 when HA Loss manual override is ON # -########################################################################################## -########################################################################################## +# c) Entire WiFi/Network offline: +# - Device operates in local manual/offline behavior only +# - Single click can still toggle Relay_1 when HA Loss manual override is ON +# - Double click and long hold Home Assistant scene/event actions are unavailable +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-loungewestswitch" friendly_name: "Lounge West Single Switch (1)" - description_comment: "Main Lounge from entranceway lightswitch using a Zemismart KS-811 Single Push Button. Main Lights (1)" - device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Main Lounge from entranceway lightswitch using a Zemismart KS-811 Single Push Button. Main Lights (1) (Layout V1.1)" + device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Single" # Project Details - project_version: "v4.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Single" # Project Details + project_version: "v4.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-loungewestswitch_ip - #mqtt_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings log_level: "DEBUG" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE @@ -49,14 +94,15 @@ substitutions: #mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}" # Topic we will use to view status locally without HA #mqtt_remote_device_command_on: "On" #mqtt_remote_device_command_off: "Off" - + # Switch/Relay/Button Naming & Icons switch_1_name: "Main Lights" # NOTE there is no physical connection to the lights on this switch, it is connected to the dimmer ESPhome for the pelmet lights - -######################################################################################### -# PACKAGES: Included Common Packages + +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -64,6 +110,7 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### @@ -78,10 +125,10 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### #common_sntp: !include common/sntp_common.yaml @@ -91,10 +138,10 @@ packages: #diag_debug: !include common/include_debug_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -125,44 +172,44 @@ api: level: WARN format: "API disconnected: switching to manual/offline behavior" -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -######################################################################################### +#:########################################################################################:# logger: level: "${log_level}" #INFO Level suggested, or DEBUG for testing #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: - number: GPIO02 - inverted: yes + number: GPIO2 + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO0 mode: INPUT - inverted: True + inverted: true name: "Button 1: ${switch_1_name}" on_multi_click: @@ -183,7 +230,7 @@ binary_sensor: scene_name: "Night Light" - logger.log: level: INFO - format: "BTN: Double click → Scene Night Light" + format: "BTN: Double click -> Scene Night Light" else: - logger.log: level: INFO @@ -191,8 +238,8 @@ binary_sensor: # --- Single short click --- # Online (and override ON): use HA's last scene to decide. - # If last != "All Off" → send "All Off" - # If last == "All Off" → send "Bright" + # If last != "All Off" -> send "All Off" + # If last == "All Off" -> send "Bright" # Offline (and override ON): toggle physical Relay_1 - timing: - ON for at most 0.5s @@ -218,7 +265,7 @@ binary_sensor: scene_name: "All Off" - logger.log: level: INFO - format: "BTN: Single click (online) → Last scene was not 'All Off' → Set 'All Off'" + format: "BTN: Single click (online) -> Last scene was not 'All Off' -> Set 'All Off'" else: - homeassistant.service: service: script.lounge_set_scene @@ -226,7 +273,7 @@ binary_sensor: scene_name: "Bright" - logger.log: level: INFO - format: "BTN: Single click (online) → Last scene was 'All Off' → Set 'Bright'" + format: "BTN: Single click (online) -> Last scene was 'All Off' -> Set 'Bright'" else: # OFFLINE path: only act if override ON; toggle physical relay - if: @@ -238,17 +285,18 @@ binary_sensor: then: - if: condition: - lambda: 'return id(Relay_1).state;' + lambda: |- + return id(Relay_1).state; then: - switch.turn_off: Relay_1 - logger.log: level: INFO - format: "BTN: Single click (offline) → Relay_1 OFF" + format: "BTN: Single click (offline) -> Relay_1 OFF" else: - switch.turn_on: Relay_1 - logger.log: level: INFO - format: "BTN: Single click (offline) → Relay_1 ON" + format: "BTN: Single click (offline) -> Relay_1 ON" else: - logger.log: level: INFO @@ -272,33 +320,32 @@ binary_sensor: action: "hold" - logger.log: level: INFO - format: "BTN: Long press → Scene All Off + HA event (hold)" + format: "BTN: Long press -> Scene All Off + HA event (hold)" else: - logger.log: level: INFO format: "BTN: Long press ignored (no HA connection)" -######################################################################################### -# TEXT SENSOR COMPONENT -# -######################################################################################### +#:########################################################################################:# +# TEXT SENSOR COMPONENT: +# https://esphome.io/components/text_sensor/ +#:########################################################################################:# text_sensor: - platform: homeassistant id: ha_last_scene entity_id: input_text.lounge_last_scene - # logging: helpful when testing on_value: - logger.log: level: DEBUG format: "HA last scene now: %s" args: ["x.c_str()"] - -######################################################################################### -# SWITCH COMPONENT + +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: -# GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GPIO12 + # GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GPIO12 - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO12 @@ -310,6 +357,4 @@ switch: name: "HA Loss manual override" id: ha_loss_override optimistic: true - restore_mode: RESTORE_DEFAULT_ON - - + restore_mode: RESTORE_DEFAULT_ON \ No newline at end of file diff --git a/esphome/esp-mainbathroomlights.yaml b/esphome/esp-mainbathroomlights.yaml index af77b66..bc1eda0 100644 --- a/esphome/esp-mainbathroomlights.yaml +++ b/esphome/esp-mainbathroomlights.yaml @@ -1,38 +1,81 @@ -########################################################################################## -########################################################################################## -# MAIN BATHROOM LIGHTSWITCH 2 (OBK Converted, BK7231N) +#:########################################################################################:# +# TITLE: MAIN BATHROOM LIGHTSWITCH 2 (OBK Converted, BK7231N) +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-mainbathroomlights.yaml +#:########################################################################################:# +# VERSIONS: +# V2.2 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.1 2026-02-23 Button 3 multi-click publishes MQTT commands to bathroom fan (1x/2x/3x) # V2.0 2026-02-04 Reflash into new switch (old switch electrical failure, now a BK) # V1.0 2025-11-23 Initial -########################################################################################## -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Triple push button +# - BK7231N based switch +# - BK72XX board: generic-bk7231n-qfn32-tuya +# - pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Main bathroom switch with 3 outputs: +# 1) Main Lights +# 2) Shower Lights +# 3) Cabinet Lights +# - Button 1 toggles Relay_2 (as currently coded in the source yaml) +# - Button 2 toggles Relay_2 +# - Button 3 immediate press action turns OFF Relay_2 and Relay_3 +# - Button 3 also sends MQTT commands to the bathroom fan based on click count: +# - 1 click -> command 1 +# - 2 clicks -> command 2 +# - 3 clicks -> command 3 +# - Relay 1 turn_on action also turns ON Relay_2 and Relay_3 +# - Virtual group switch "All Main Bathroom Lights" allows grouped control in Home Assistant +#:########################################################################################:# +# MQTT COMMANDS: +# - Remote device command topic: +# - ${mqtt_remote_device1_command_topic} +# - Button 3 single click publishes: +# - ${mqtt_remote_device1_command1} +# - Button 3 double click publishes: +# - ${mqtt_remote_device1_command2} +# - Button 3 triple click publishes: +# - ${mqtt_remote_device1_command3} +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - Local button control continues to operate the relays. +# - Button 3 MQTT fan commands can still publish if MQTT broker is online. +# - Virtual group switch in HA will be unavailable until HA returns. +# b) MQTT offline (or HA/MQTT offline): +# - Local button control continues to operate the relays. +# - Button 3 fan MQTT commands will not be sent. +# c) Entire WiFi/Network offline: +# - Local button control continues to operate the relays. +# - No MQTT control or status is available. +# - Accurate time is not needed; SNTP is not required for operation. +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-mainbathroomlights" friendly_name: "Main Bathroom Lightswitch (3)" - description_comment: "BK7231N - Main Bathroom Lightswitch using a Zemismart KS-811 Triple Push Button. Main Lights (1), Shower Lights (2), Cabinet Lights (3)" + description_comment: "BK7231N - Main Bathroom Lightswitch using a Zemismart KS-811 Triple Push Button. Main Lights (1), Shower Lights (2), Cabinet Lights (3) (Layout V1.1)" device_area: "Main Bathroom" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "Zemismart Technologies.KS-811 Triple BK7231N" # Project Details - project_version: "v2.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_version: "v2.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names - static_ip_address: !secret esp-garageentrylights2_ip + static_ip_address: !secret esp-mainbathroomlights_ip mqtt_command_main_topic: !secret mqtt_command_main_topic #mqtt_status_main_topic: !secret mqtt_status_main_topic @@ -65,10 +108,10 @@ substitutions: mqtt_remote_device1_command2: "20" mqtt_remote_device1_command3: "30" -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -94,28 +137,31 @@ packages: #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - #diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + #diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -# Package item removals +#:########################################################################################:# +# PACKAGE ITEM REMOVALS / OVERRIDES: +#:########################################################################################:# wifi: min_auth_mode: !remove # The WPA2 only works on esp32/8266 - reboot_timeout: 15min # override the selection from from the common package - fast_connect: false # (optional) force off, in case package vars change + reboot_timeout: 15min # override the selection from the common package + fast_connect: false # optional; force off in case package vars change mqtt: keepalive: 15s # overriding the value from the common package -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -129,36 +175,36 @@ esphome: # then: # - switch.turn_on: Relay_3 -########################################################################################## -# BUILD FOR BK CHIPSET +#:########################################################################################:# +# BUILD FOR BK CHIPSET: # bk72xx # https://devices.esphome.io/board/bk72xx/ -########################################################################################## +#:########################################################################################:# bk72xx: board: generic-bk7231n-qfn32-tuya -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) id: logger_id -########################################################################################## -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -########################################################################################## +#:########################################################################################:# status_led: pin: number: P22 #GPIO22 inverted: true -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - platform: gpio pin: @@ -235,10 +281,10 @@ binary_sensor: topic: "${mqtt_remote_device1_command_topic}" payload: "${mqtt_remote_device1_command3}" -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -261,10 +307,10 @@ switch: id: Relay_3 restore_mode: ${relay_restore_mode} -########################################################################################## -# TEMPLATE COMPONENT -########################################################################################## +#:########################################################################################:# +# TEMPLATE COMPONENT: # Virtual group switch for Home Assistant +#:########################################################################################:# - platform: template name: "All Main Bathroom Lights" id: all_main_bathroom_lights diff --git a/esphome/esp-maindishwasherpower.yaml b/esphome/esp-maindishwasherpower.yaml index 0b28e79..7f469e7 100644 --- a/esphome/esp-maindishwasherpower.yaml +++ b/esphome/esp-maindishwasherpower.yaml @@ -1,34 +1,67 @@ -########################################################################################## -########################################################################################## -# MAIN DISHWASHER POWER -# Controlled by a Athom Smart Plug V3 -# package_import_url: github://athom-tech/athom-configs/athom-smart-plug.yaml -# +#:########################################################################################:# +# TITLE: MAIN DISHWASHER POWER +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-maindishwasherpower.yaml +#:########################################################################################:# +# VERSIONS: +# V3.5 2026-03-11 Updated yaml to zorruno layout V1.1 # V3.4 2025-07-30 Changed to Athom V3 # V1.1 2025-06-12 package added for energy entities # V1.0 2025-06-10 YAML Tidyups -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# - Athom Smart Plug V3 +# - ESP32-C3 based +# - Relay output on GPIO5 +# - Local power button on GPIO3 +# - Power monitoring via Athom V3 common package +# - package_import_url reference: github://athom-tech/athom-configs/athom-smart-plug.yaml +#:########################################################################################:# +# OPERATION NOTES: +# - Controls power to the main dishwasher +# - Uses Athom Smart Plug V3 hardware and Athom V3 common power monitor package +# - Relay is turned ON at boot +# - Local power button toggles the relay +# - Relay status is exposed as a template binary sensor +# - Power/energy monitoring entities are provided by the included Athom V3 package +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT online): +# - Device continues operating normally +# - Relay can still be controlled locally by the hardware power button +# - MQTT remains available if your broker is online +# +# b) MQTT offline (or HA/MQTT offline): +# - Device continues operating locally +# - Relay control and local power monitoring continue to work +# +# c) Entire WiFi/Network offline: +# - Device continues operating locally +# - Relay control and local power monitoring continue to work +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-maindishwasherpower" friendly_name: "Main Dishwasher Power" - description_comment: "Main Dishwasher Power Monitor :: Athom Smart Plug Power Monitor V3" - device_area: "Kitchen" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - + description_comment: "Main Dishwasher Power Monitor :: Athom Smart Plug Power Monitor V3 (Layout V1.1)" + device_area: "Kitchen" + # Project Naming - project_name: "Athom Technology.Smart Plug V3" # Project Details - project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Athom Technology.Smart Plug V3" + project_version: "v3.5" # Passwords - api_key: !secret esp-maindishwasherpower_api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-maindishwasherpower_ota_pass # unfortunately you can't use substitutions inside secrets names + api_key: !secret esp-maindishwasherpower_api_key + ota_pass: !secret esp-maindishwasherpower_ota_pass static_ip_address: !secret esp-maindishwasherpower_ip # If we are changing IP addresses, you must update the current IP address here, otherwise it remains @@ -36,17 +69,18 @@ substitutions: current_ip_address: ${static_ip_address} # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "INFO" + update_interval: "60s" - # Device Settings + # Relay / Load Settings relay_icon: "mdi:dishwasher" - current_limit : "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. - -########################################################################################## -# PACKAGES: Included Common Packages + current_limit: "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. + +#:########################################################################################:# +# PACKAGES: +# Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -54,8 +88,8 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" - local_ota_pass: "${ota_pass}" local_current_ip_address: "${current_ip_address}" + local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -69,34 +103,35 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - diag_debug: !include common/include_debug_diag_sensors.yaml - diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + diag_debug: !include common/include_debug_diag_sensors.yaml + diag_resetcount: !include common/include_resetcount_diag_sensors.yaml - # Device Specific included packages - common_athompowermonV3: !include + #### DEVICE SPECIFIC INCLUDED PACKAGES #### + common_athompowermonv3: !include file: common/athompowermonv3_common.yaml vars: local_current_limit: "${current_limit}" -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" #Appears on the esphome page in HA - area: "${device_area}" - name_add_mac_suffix: False + comment: "${description_comment}" + area: "${device_area}" + name_add_mac_suffix: false min_version: 2024.6.0 project: name: "${project_name}" @@ -108,19 +143,19 @@ esphome: on_boot: priority: 200 then: - - switch.turn_on: "relay" + - switch.turn_on: relay -########################################################################################## -# ESP Platform and Framework +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# esp32: board: esp32-c3-devkitm-1 flash_size: 4MB variant: ESP32C3 framework: - type: esp-idf # "esp-idf" OR "arduino". Suggested ESP-IDF Framework, or Plug Out the UART Cable Might Cause ESP32 Hang. - version: recommended # recommended, latest or dev + type: esp-idf + version: recommended preferences: flash_write_interval: 5min @@ -128,24 +163,24 @@ preferences: esp32_improv: authorizer: none -########################################################################################## -# ESPHome LOGGING +#:########################################################################################:# +# LOGGER: # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing + level: "${log_level}" #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - platform: gpio pin: - number: GPIO03 + number: GPIO3 mode: INPUT_PULLUP inverted: true name: "Power Button" @@ -156,24 +191,22 @@ binary_sensor: - min_length: 20ms max_length: 500ms then: - - switch.toggle: - id: relay - + - switch.toggle: relay + - platform: template name: "Relay Status" lambda: |- return id(relay).state; -################################################################################################# -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -################################################################################################# +#:########################################################################################:# switch: - platform: gpio name: "Power Output" - pin: GPIO05 + pin: GPIO5 id: relay - restore_mode: RESTORE_DEFAULT_ON # Ensures the relay is restored (or off) at boot - #internal: true # Hides the switch from Home Assistant - icon: "${relay_icon}" - + restore_mode: RESTORE_DEFAULT_ON + #internal: true + icon: "${relay_icon}" \ No newline at end of file diff --git a/esphome/esp-mainhallwaylights1.yaml b/esphome/esp-mainhallwaylights1.yaml new file mode 100644 index 0000000..0a77559 --- /dev/null +++ b/esphome/esp-mainhallwaylights1.yaml @@ -0,0 +1,187 @@ +#:########################################################################################:# +# TITLE: MAIN HALLWAY LIGHTSWITCH 1 (BK7231N) +# zorruno.com layout +#:########################################################################################:# +# REPO: +# +#:########################################################################################:# +# VERSIONS: +# V1.0 2026-04-03 Initial +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Single push button +# - BK7231N based switch +# - BK72XX board: generic-bk7231n-qfn32-tuya +# - pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Main bathroom switch with 1 output: +# 1) Main Hallway Lights +# +#:########################################################################################:# +# MQTT COMMANDS: +# - +#:########################################################################################:# +# OFFLINE NOTES: +# +#:########################################################################################:# + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions +# If NOT using a secrets file, just replace these with the passwords etc (in quotes) +#:########################################################################################:# +substitutions: + # Device Naming + device_name: "esp-mainhallwaylights1" + friendly_name: "Main Hallway Lightswitch (1)" + description_comment: "BK7231N - Main Hallway Lightswitch using a Zemismart KS-811 Single Push Button. Main Hallway Lights (1)" + device_area: "Main Hallway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + + # Project Naming + project_name: "Zemismart Technologies.KS-811 Triple BK7231N" # Project Details + project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + + # Passwords + api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names + ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + static_ip_address: !secret esp-mainhallwaylights1_ip + mqtt_command_main_topic: !secret mqtt_command_main_topic + #mqtt_status_main_topic: !secret mqtt_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # Device Settings + log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for for general sensors etc + + # Default relay restore mode + # Options: RESTORE_DEFAULT_OFF, RESTORE_DEFAULT_ON, ALWAYS_ON, ALWAYS_OFF + relay_restore_mode: "RESTORE_DEFAULT_OFF" + + # Switch Naming + switch_1_name: "Main Hallway Lights" + +#:########################################################################################:# +# PACKAGES: Included Common Packages +# https://esphome.io/components/packages.html +#:########################################################################################:# +packages: + #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### + common_wifi: !include + file: common/network_common.yaml + vars: + local_device_name: "${device_name}" + local_static_ip_address: "${static_ip_address}" + local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" + + #### HOME ASSISTANT API (choose encryption or no encryption options) #### + common_api: !include + file: common/api_common.yaml + #file: common/api_common_noencryption.yaml + vars: + local_api_key: "${api_key}" + + #### MQTT #### + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + + #### WEB PORTAL #### + #common_webportal: !include common/webportal_common.yaml + + #### SNTP (Only use if you want/need accurate timeclocks) #### + #common_sntp: !include common/sntp_common.yaml + + #### DIAGNOSTICS Sensors #### + diag_basic: !include common/include_basic_diag_sensors.yaml + #diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + +#:########################################################################################:# +# PACKAGE ITEM REMOVALS / OVERRIDES: +#:########################################################################################:# +wifi: + min_auth_mode: !remove # The WPA2 only works on esp32/8266 + reboot_timeout: 15min # override the selection from the common package + fast_connect: false # optional; force off in case package vars change + +mqtt: + keepalive: 15s # overriding the value from the common package + +#:########################################################################################:# +# ESPHOME: +# https://esphome.io/components/esphome.html +#:########################################################################################:# +esphome: + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # Appears on the esphome page in HA + area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" +# on_boot: +# priority: 200 +# then: +# - switch.turn_on: Relay_3 + +#:########################################################################################:# +# BUILD FOR BK CHIPSET: +# bk72xx +# https://devices.esphome.io/board/bk72xx/ +#:########################################################################################:# +bk72xx: + board: generic-bk7231n-qfn32-tuya + +#:########################################################################################:# +# LOGGER: +# https://esphome.io/components/logger.html +#:########################################################################################:# +logger: + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + id: logger_id + +#:########################################################################################:# +# STATUS LED: +# https://esphome.io/components/status_led.html +#:########################################################################################:# +status_led: + pin: + number: P22 #GPIO22 + inverted: true + +#:########################################################################################:# +# BINARY SENSORS: +# https://esphome.io/components/binary_sensor/ +#:########################################################################################:# +binary_sensor: + - platform: gpio + pin: + number: P17 + mode: + input: true + pullup: true + inverted: true + name: "Button 1: ${switch_1_name}" + on_press: + - delay: 50ms + - switch.toggle: Relay_1 + + +#:########################################################################################:# +# SWITCH COMPONENT: +# https://esphome.io/components/switch/ +#:########################################################################################:# +switch: + - platform: gpio + name: "Relay 1: ${switch_1_name}" + pin: P14 #GPIO14 + id: Relay_1 + restore_mode: ${relay_restore_mode} diff --git a/esphome/esp-mainhallwaylights2.yaml b/esphome/esp-mainhallwaylights2.yaml new file mode 100644 index 0000000..73368b1 --- /dev/null +++ b/esphome/esp-mainhallwaylights2.yaml @@ -0,0 +1,193 @@ +#:########################################################################################:# +# TITLE: MAIN HALLWAY LIGHTSWITCH 2 (BK7231N) +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-mainhallwaylights2.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-04-03 Updated yaml to zorruno layout V1.1; corrected KS-811 single naming and operation notes; updated BK7231N single-switch pin mapping +# V1.0 2026-04-03 Initial +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Single push button +# - BK7231N based switch +# - BK72XX board: generic-bk7231n-qfn32-tuya +# - BK7231N single-switch pin mapping checked against KS-811 BK references +#:########################################################################################:# +# OPERATION NOTES: +# - Main hallway nightlight switch with 1 output: +# 1) Main Hallway Nightlights +# - A single press of the physical button toggles Relay 1 ON/OFF +# - Status LED uses P22 +#:########################################################################################:# +# MQTT COMMANDS: +# - None +#:########################################################################################:# +# OFFLINE NOTES: +# - a) Home Assistant offline (network and MQTT online): +# - Device remains on WiFi and MQTT +# - Physical button still toggles relay locally +# - b) MQTT offline (or Home Assistant and MQTT offline): +# - Physical button still toggles relay locally +# - Remote control/state sync is unavailable until MQTT returns +# - c) Entire WiFi/network offline: +# - Physical button still toggles relay locally +# - Accurate time is not needed; SNTP is not used +#:########################################################################################:# + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions +# If NOT using a secrets file, just replace these with the passwords etc (in quotes) +#:########################################################################################:# +substitutions: + # Device Naming + device_name: "esp-mainhallwaylights2" + friendly_name: "Main Hallway Nightlights (1)" + description_comment: "BK7231N - Main Hallway Nightlights using a Zemismart KS-811 Single Push Button. Main Hallway Nightlights (1) (Layout V1.1)" + device_area: "Main Hallway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + + # Project Naming + project_name: "Zemismart Technologies.KS-811 Single BK7231N" # Project Details + project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + + # Passwords + api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names + ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + static_ip_address: !secret esp-mainhallwaylights2_ip + mqtt_command_main_topic: !secret mqtt_command_main_topic + #mqtt_status_main_topic: !secret mqtt_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # Device Settings + log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for for general sensors etc + + # Default relay restore mode + # Options: RESTORE_DEFAULT_OFF, RESTORE_DEFAULT_ON, ALWAYS_ON, ALWAYS_OFF + relay_restore_mode: "RESTORE_DEFAULT_OFF" + + # Switch Naming + switch_1_name: "Main Hallway Nightlights" + +#:########################################################################################:# +# PACKAGES: Included Common Packages +# https://esphome.io/components/packages.html +#:########################################################################################:# +packages: + #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### + common_wifi: !include + file: common/network_common.yaml + vars: + local_device_name: "${device_name}" + local_static_ip_address: "${static_ip_address}" + local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" + + #### HOME ASSISTANT API (choose encryption or no encryption options) #### + common_api: !include + file: common/api_common.yaml + #file: common/api_common_noencryption.yaml + vars: + local_api_key: "${api_key}" + + #### MQTT #### + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + + #### WEB PORTAL #### + #common_webportal: !include common/webportal_common.yaml + + #### SNTP (Only use if you want/need accurate timeclocks) #### + #common_sntp: !include common/sntp_common.yaml + + #### DIAGNOSTICS Sensors #### + diag_basic: !include common/include_basic_diag_sensors.yaml + #diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + +#:########################################################################################:# +# PACKAGE ITEM REMOVALS / OVERRIDES: +#:########################################################################################:# +wifi: + min_auth_mode: !remove # The WPA2 only works on esp32/8266 + reboot_timeout: 15min # override the selection from the common package + fast_connect: false # optional; force off in case package vars change + +mqtt: + keepalive: 15s # overriding the value from the common package + +#:########################################################################################:# +# ESPHOME: +# https://esphome.io/components/esphome.html +#:########################################################################################:# +esphome: + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # Appears on the esphome page in HA + area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" + +#:########################################################################################:# +# BUILD FOR BK CHIPSET: +# bk72xx +# https://devices.esphome.io/board/bk72xx/ +#:########################################################################################:# +bk72xx: + board: generic-bk7231n-qfn32-tuya + +#:########################################################################################:# +# LOGGER: +# https://esphome.io/components/logger.html +#:########################################################################################:# +logger: + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + id: logger_id + +#:########################################################################################:# +# STATUS LED: +# https://esphome.io/components/status_led.html +#:########################################################################################:# +status_led: + pin: + number: P22 # GPIO22 + inverted: true + +#:########################################################################################:# +# BINARY SENSORS: +# https://esphome.io/components/binary_sensor/ +#:########################################################################################:# +binary_sensor: + - platform: gpio + id: button_1 + internal: true + pin: + number: P24 # GPIO24 + mode: + input: true + pullup: true + inverted: true + filters: + - delayed_on: 20ms + on_press: + - switch.toggle: Relay_1 + +#:########################################################################################:# +# SWITCH COMPONENT: +# https://esphome.io/components/switch/ +#:########################################################################################:# +switch: + - platform: gpio + name: "Relay 1: ${switch_1_name}" + pin: P16 # GPIO16 + id: Relay_1 + restore_mode: ${relay_restore_mode} \ No newline at end of file diff --git a/esphome/esp-mainkitchenlights.yaml b/esphome/esp-mainkitchenlights.yaml index 5742f50..ba25205 100644 --- a/esphome/esp-mainkitchenlights.yaml +++ b/esphome/esp-mainkitchenlights.yaml @@ -1,59 +1,77 @@ -########################################################################################## -########################################################################################## -# Main Kitchen LIGHTSWITCH -# V3.7 2025-09-14 upload to this lightswitch from copy -# -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - Light switch with 2 sets of lights -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# TITLE: MAIN KITCHEN LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-mainkitchenlights.yaml +#:########################################################################################:# +# VERSIONS: +# V3.8 2026-03-11 Updated yaml to zorruno layout V1.1 +# V3.7 2025-09-14 Upload to this lightswitch from copy +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Double push button (KS-811-2) +# - ESP8266 (esp01_1m class) +# - Buttons: GPIO16 (Button 1), GPIO05 (Button 2) +# - Relays: GPIO13 (Relay 1), GPIO12 (Relay 2) +# - Status LED: GPIO2 (inverted) +# - Reference: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - 2 button wall switch controlling 2 relays +# - Button 1 toggles Relay 1 (Main Lights) +# - Button 2 toggles Relay 2 (Benchtop Lights) +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Physical buttons still toggle the relays locally +# - If MQTT is online, any standard MQTT diagnostics from your common package continue to publish +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Physical buttons still toggle the relays locally +# - HA control via API remains available (switch entities still work) +# c) Entire WiFi/Network OFFLINE +# - Physical buttons still toggle the relays locally (standalone operation) +# - Accurate time is not needed (SNTP not required) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-mainkitchenlights" friendly_name: "Main Kitchen Lightswitch (2)" - description_comment: "Main Kitchen lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Bench Lights (2)" - device_area: "Kitchen" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Main Kitchen lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Bench Lights (2) (Layout V1.1)" + device_area: "Kitchen" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v3.7" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" # Project Details + project_version: "v3.8" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-mainkitchenlights_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings - #relay_icon: "mdi:lightbulb-group" - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc - # MQTT LOCAL Controls - #mqtt_device_name: "bedroom2-lights" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - # Switch Naming switch_1_name: "Main Lights" switch_2_name: "Benchtop Lights" - #switch_3_name: "Nil" -######################################################################################### + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -62,6 +80,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -75,73 +94,74 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml + #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -######################################################################################### -# ESPHome + +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" # Appears on the ESPHome page in HA area: "${device_area}" project: name: "${project_name}" version: "${project_version}" -# on_boot: -# priority: 200 -# then: -# - switch.turn_on: Relay_2 # Stays on permanently -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### + +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable -# https://esphome.io/components/logger.html -############################################# -logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# LOGGING: +# https://esphome.io/components/logger.html +#:########################################################################################:# +logger: + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + + +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# BINARY SENSORS + +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True + inverted: true + use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling (suppresses warning). name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 @@ -150,25 +170,16 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - switch.toggle: Relay_2 -# KS-811-2 is a double only -# - platform: gpio -# pin: -# number: GPIO4 -# mode: INPUT -# inverted: True -# name: "Button 3: ${switch_3_name}" -# on_press: -# - switch.toggle: Relay_3 -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -178,12 +189,4 @@ switch: - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 - id: Relay_2 - -# KS-811-2 is a double only -# - platform: gpio -# name: "Relay 3: ${switch_3_name}" -# pin: GPIO14 -# id: Relay_3 - - + id: Relay_2 \ No newline at end of file diff --git a/esphome/esp-masterbathtowelrail.yaml b/esphome/esp-masterbathtowelrail.yaml index 02e2860..189c1c2 100644 --- a/esphome/esp-masterbathtowelrail.yaml +++ b/esphome/esp-masterbathtowelrail.yaml @@ -1,8 +1,12 @@ #:########################################################################################:# # TITLE: MASTER BATHROOM HEATED TOWEL RAIL -# zorruno.com layout v1.0 2026 +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbathtowelrail.yaml #:########################################################################################:# # VERSIONS: +# V2.3 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.2 2026-01-30 Added Morning/Evening Timer enable switches (gate timer windows) # V2.1 2025-06-12 Added select and button to chose modes, added countdown & startup to boost # V2.0 2025-06-05 YAML Tidyups @@ -10,8 +14,8 @@ # V1.0 2025-02-14 Initial Version #:########################################################################################:# # HARDWARE: -# Controlled by a Sonoff Basic -# pinout/schematic: https://devices.esphome.io/devices/sonoff-basic-r4-v1.0/ +# - Controlled by a Sonoff Basic +# - pinout/schematic: https://devices.esphome.io/devices/sonoff-basic-r4-v1.0/ #:########################################################################################:# # OPERATION NOTES: # - It allows the device to work in a standalone timer style operation @@ -21,7 +25,7 @@ # - It uses SNTP for time setting (but obviously only if wifi & networking are working) # - It will default to an internal timer if no wifi. To reset internal timer, reboot the device at 12pm (noon) # - If on a network and there is a MQTT server, you can set the on/off times via MQTT (See below commands) -# - You can set 4 modes ON/OFF/TIMER/BOOST via MQTT. Setting BOOST gives you a oneshot operation +# - You can set 4 modes ON/OFF/TIMER/BOOST via MQTT. Setting BOOST gives you a oneshot operation # - Any new timer times set via MQTT will be remembered though a reboot # - On startup, or a reboot, the device will always turn on for the BOOST Duration (BOOST mode, default 2 hours) # - TIMER mode will always be switched on after BOOST mode is complete @@ -30,7 +34,7 @@ #:########################################################################################:# # MQTT COMMANDS: # Values will be set in place on the update_interval time, not immediately -# Use 00:00 in 24hr format for time setting. (Note there is no weekday/weekend setting) +# Use 00:00 in 24hr format for time setting. (Note there is no weekday/weekend setting) # mqtt_timer_topic/morning-on/06:00 : Time device will go on # mqtt_timer_topic/morning-off/08:00 : Time device will go off # mqtt_timer_topic/evening-on/09:00 : Time device will go on @@ -39,7 +43,7 @@ # mqtt_timer_topic/operation/ON : Device permanently on # mqtt_timer_topic/operation/OFF : Device permanently off # mqtt_timer_topic/operation/TIMER : Device will obey timer settings -# mqtt_timer_topic/operation/BOOST : Turn on for (boost_duration) minutes then BOOST (also on startup) +# mqtt_timer_topic/operation/BOOST : Turn on for (boost_duration) minutes then BOOST (also on startup) # # operation_mode: # 0 = OFF @@ -50,15 +54,14 @@ # OFFLINE NOTES: # a) Home Assistant OFFLINE, but Network and MQTT ONLINE # - The towel rail will stick to its assigned schedule (and should remember on reboot) -# - Shedule times and on/off switching can still occur via MQTT +# - Schedule times and on/off switching can still occur via MQTT # - Other switches such as the IR Heater/Fan combo can still command the towel rail # b) HA/MQTT OFFLINE -# With no automation controllers, the HTR will still remember its timing functions, and will -# turn on once or twice per day. If internet/wifi is still available, timing will be accurate. +# - With no automation controllers, the HTR will still remember its timing functions, and will +# turn on once or twice per day. If internet/wifi is still available, timing will be accurate. # c) Internet/Wifi OFFLINE -# The HTR will still come on once or twice per day (depending on previous settings) however -# timing will likely shift. To make timing more accurate, it can be powered down then up at 12pm. -# Obviously this may drift again over time. +# - The HTR will still come on once or twice per day (depending on previous settings) +# - Timeclocks will drift without SNTP and can be reset by power cycling at 12pm (midday) #:########################################################################################:# #:########################################################################################:# @@ -69,12 +72,12 @@ substitutions: # Device Naming device_name: "esp-masterbathtowelrail" friendly_name: "Master Bathroom Towelrail" - description_comment: "Sonoff Basic controlling ON/OFF/Timer for the Heated Towel Rail in the Master Bathroom" + description_comment: "Sonoff Basic controlling ON/OFF/Timer for the Heated Towel Rail in the Master Bathroom (Layout V1.1)" device_area: "Main Bathroom" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details - project_version: "v2.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_version: "v2.3" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords api_key: !secret esp-masterbathtowelrail_api_key # unfortunately you can't use substitutions inside secrets names @@ -109,8 +112,8 @@ packages: vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" - local_ota_pass: "${ota_pass}" local_current_ip_address: "${current_ip_address}" + local_ota_pass: "${ota_pass}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -606,7 +609,7 @@ sensor: unit_of_measurement: "mins" accuracy_decimals: "0" update_interval: "${update_interval}" - internal: True # No need to show this in Home Assistant + internal: true # No need to show this in Home Assistant lambda: |- return id(current_mins); @@ -787,4 +790,4 @@ interval: //id(mqtt_client).publish("${mqtt_timer_topic}/operation", "TIMER"); } } - - script.execute: evaluate_relay_state + - script.execute: evaluate_relay_state \ No newline at end of file diff --git a/esphome/esp-officeduallights.yaml b/esphome/esp-officeduallights.yaml index 2d860a9..15d1146 100644 --- a/esphome/esp-officeduallights.yaml +++ b/esphome/esp-officeduallights.yaml @@ -1,204 +1,222 @@ -############################################# -############################################# -# OFFICE DUAL LIGHT CONTROL -# - Overhead cool white lights -# - Right hand warm bunker light +#:########################################################################################:# +# TITLE: OFFICE DUAL LIGHT CONTROL +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeduallights.yaml +#:########################################################################################:# +# VERSIONS: +# V2.5 2026-03-11 Updated yaml to zorruno layout V1.1 +# V2.4 2025-06-30 Tidied up MQTT direct relay control (esps can control each other via MQTT) +# V2.3 2025-06-18 Added MQTT direct relay control +#:########################################################################################:# +# HARDWARE: +# - Sonoff Dual R1 +# - ESP8266 based +# - 2 x relay outputs +# - 2 x local push buttons +# - Relay control via UART serial commands +# - Status LED on GPIO13 +#:########################################################################################:# +# OPERATION NOTES: +# - Controls 2 office light circuits: +# - Overhead cool white lights +# - Right hand warm bunker light +# - Local button 1 toggles relay/light 1 +# - Local button 2 toggles relay/light 2 +# - Relay state changes are sent out via MQTT status topics +# - Template binary lights drive the template relay switches +# - Sonoff Dual R1 requires UART serial packets to operate the physical relays # -# Controlled by a Sonoff Dual R1 -# A sonoff dual uses serial data to turn the relays on/off +# MQTT COMMANDS: +# - Command relay 1: +# - ${mqtt_local_command_topic}/relay1/set ON or OFF +# - Command relay 2: +# - ${mqtt_local_command_topic}/relay2/set ON or OFF +# - Relay 1 status publishes to: +# - ${mqtt_local_status_topic}/relay1/state +# - Relay 2 status publishes to: +# - ${mqtt_local_status_topic}/relay2/state +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant offline (network and MQTT still online): +# - Device continues to operate from local buttons +# - Device can still be controlled directly by MQTT +# - Relay status still publishes by MQTT if broker is available # -# V2.4 - 2025-06-30 Tidied up MQTT direct relay control (esps can control each other via MQTT) -# V2.3 - 2025-06-18 Added MQTT direct relay control +# b) MQTT offline (or HA and MQTT both offline): +# - Device continues to operate from local buttons only +# - No direct inter-ESP MQTT control available +# - No MQTT state feedback available # -# NOTES: -# Command the lights on with MQTT -# ${mqtt_local_command_full_topic}/relay1/set ON or OFF -# ${mqtt_local_command_full_topic}/relay2/set ON or OFF -# ${mqtt_local_status_full_topic}/relay1/set ON or OFF -# ${mqtt_local_status_full_topic}/relay2/set ON or OFF -# -########################################################################################## -########################################################################################## +# c) Entire WiFi / Network offline: +# - Device continues to operate from local buttons only +# - No HA control or MQTT control/status available +# - Accurate time is not needed; SNTP is not required for operation +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS -# If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# +# SUBSTITUTIONS: +# Specific device variable substitutions +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-officeduallights" friendly_name: "Office Dual Lights" - description_comment: "Dual Office Lights (Overhead and right hand Bunker) :: Sonoff Dual R1" - device_area: "Office" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Dual Office Lights (Overhead and right hand Bunker) :: Sonoff Dual R1 (Layout V1.1)" + device_area: "Office" # Project Naming - project_name: "Sonoff Technologies.Sonoff Dual R1" # Project Details - project_version: "v2.3" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - # Passwords & Secrets + project_name: "Sonoff Technologies.Sonoff Dual R1" + project_version: "v2.5" + + # Passwords and Secrets api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass - static_ip_address: !secret esp-officeduallights_ip # unfortunately you can't use substitutions inside secrets names + ota_pass: !secret esp-ota_pass + static_ip_address: !secret esp-officeduallights_ip + current_ip_address: ${static_ip_address} mqtt_local_command_main_topic: !secret mqtt_command_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic - + # Device Settings relay_icon: "mdi:lightbulb-group" - log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "NONE" + update_interval: "60s" # MQTT Controls mqtt_device_name: "office-dual-lights" - mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA + mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" + mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Switch Naming - switch_1_name: "Dual L1 Relay" - relay_1_icon: "mdi:lightbulb" - light_1_name: "Light 1 (Right Hand Bunker Light)" - switch_2_name: "Dual L2 Relay" - relay_2_icon: "mdi:lightbulb" - light_2_name: "Light 2 (Cool White Overhead Lights)" + switch_1_name: "Dual L1 Relay" + relay_1_icon: "mdi:lightbulb" + light_1_name: "Light 1 (Right Hand Bunker Light)" -########################################################################################## -# PACKAGES: Included Common Packages + switch_2_name: "Dual L2 Relay" + relay_2_icon: "mdi:lightbulb" + light_2_name: "Light 2 (Cool White Overhead Lights)" + +#:########################################################################################:# +# PACKAGES: +# Included common packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: - #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include file: common/network_common.yaml vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" + local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" - #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include file: common/api_common.yaml - #file: common/api_common_noencryption.yaml + # file: common/api_common_noencryption.yaml vars: local_api_key: "${api_key}" - #### MQTT #### common_mqtt: !include file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml - #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml - #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml - #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + # common_webportal: !include common/webportal_common.yaml + # common_sntp: !include common/sntp_common.yaml -########################################################################################## -# ESPHome + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + # diag_debug: !include common/include_debug_diag_sensors.yaml + # diag_resetcount: !include common/include_resetcount_diag_sensors.yaml + +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" -# platformio_options: -# build_flags: -# - "-Os" # optimize for size -# - "-Wl,--gc-sections" # drop unused code/data -# - "-fno-exceptions" # strip C++ exceptaions -# - "-fno-rtti" # strip C++ RTTI -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: - board: esp01_1m # The original sonoff basic - restore_from_flash: False # restore some values on reboot + board: esp01_1m + restore_from_flash: false preferences: flash_write_interval: 5min mdns: - disabled: True + disabled: true -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGER: +# Sonoff Dual cannot use UART logging because UART is required for relay control # https://esphome.io/components/logger.html -########################################################################################## -# NOTE: Sonoff Dual CANNOT send serial data to log -############################################### +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 -########################################################################################## -# UART Bus +#:########################################################################################:# +# UART BUS: # https://esphome.io/components/uart.html -########################################################################################## +#:########################################################################################:# uart: tx_pin: GPIO01 rx_pin: GPIO03 baud_rate: 19200 - #data_bits: 8 - #stop_bits: 1 - #parity: EVEN -########################################################################################## -# MQTT COMMANDS -# This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# +# MQTT: +# Device-specific MQTT command triggers +#:########################################################################################:# mqtt: - # Direct MQTT control for relays via serial commands on_message: - # Relay 1 control - topic: "${mqtt_local_command_topic}/relay1/set" payload: "ON" then: - switch.turn_on: relay_1 - light.turn_on: light_1 + - topic: "${mqtt_local_command_topic}/relay1/set" payload: "OFF" then: - switch.turn_off: relay_1 - - light.turn_off: light_1 + - light.turn_off: light_1 - # Relay 2 control - topic: "${mqtt_local_command_topic}/relay2/set" payload: "ON" then: - switch.turn_on: relay_2 - light.turn_on: light_2 + - topic: "${mqtt_local_command_topic}/relay2/set" payload: "OFF" then: - switch.turn_off: relay_2 - light.turn_off: light_2 -########################################################################################## -# STATUS LED +#:########################################################################################:# +# STATUS LED: +# Sonoff Dual LED is on GPIO13 # https://esphome.io/components/status_led.html -########################################################################################## -# Sonoff Dual LED is GPIO13 -############################################# +#:########################################################################################:# status_led: pin: number: GPIO13 - inverted: yes + inverted: true -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: +# Sonoff Dual R1 buttons are GPIO04 and GPIO14 # https://esphome.io/components/binary_sensor/ -########################################################################################## -# Sonoff Dual R1 buttons are GPIO04, GPIO14 -############################################# +#:########################################################################################:# binary_sensor: - platform: gpio pin: @@ -218,12 +236,11 @@ binary_sensor: on_press: - switch.toggle: relay_2 -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH: +# Sonoff Dual R1 requires serial data packets to switch the relays # https://esphome.io/components/switch/ -########################################################################################## -# Sonoff Dual R1 requires serial data to switch -############################################# +#:########################################################################################:# switch: - platform: template name: "${switch_1_name}" @@ -234,7 +251,7 @@ switch: turn_on_action: - mqtt.publish: topic: "${mqtt_local_status_topic}/relay1/state" - payload: "ON" + payload: "ON" - if: condition: switch.is_off: relay_2 @@ -245,7 +262,7 @@ switch: turn_off_action: - mqtt.publish: topic: "${mqtt_local_status_topic}/relay1/state" - payload: "OFF" + payload: "OFF" - if: condition: switch.is_off: relay_2 @@ -253,6 +270,7 @@ switch: - uart.write: [0xA0, 0x04, 0x00, 0xA1] else: - uart.write: [0xA0, 0x04, 0x02, 0xA1] + - platform: template name: "${switch_2_name}" id: relay_2 @@ -262,7 +280,7 @@ switch: turn_on_action: - mqtt.publish: topic: "${mqtt_local_status_topic}/relay2/state" - payload: "ON" + payload: "ON" - if: condition: switch.is_off: relay_1 @@ -273,7 +291,7 @@ switch: turn_off_action: - mqtt.publish: topic: "${mqtt_local_status_topic}/relay2/state" - payload: "OFF" + payload: "OFF" - if: condition: switch.is_off: relay_1 @@ -282,30 +300,38 @@ switch: else: - uart.write: [0xA0, 0x04, 0x01, 0xA1] -################################################################################ -# TEMPLATE OUTPUTS: drive the real relays when the light state changes -################################################################################ +#:########################################################################################:# +# OUTPUTS: +# Template outputs drive the relay template switches when the light state changes +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: template id: light_output_1 type: binary write_action: - lambda: |- - if (state) id(relay_1).turn_on(); - else id(relay_1).turn_off(); + if (state) { + id(relay_1).turn_on(); + } else { + id(relay_1).turn_off(); + } - platform: template id: light_output_2 type: binary write_action: - lambda: |- - if (state) id(relay_2).turn_on(); - else id(relay_2).turn_off(); + if (state) { + id(relay_2).turn_on(); + } else { + id(relay_2).turn_off(); + } -########################################################################################## -# LIGHT COMPONENT +#:########################################################################################:# +# LIGHT: # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: binary name: "${light_1_name}" @@ -313,6 +339,6 @@ light: output: light_output_1 - platform: binary - name: "Light 2 (Cool White Overhead Lights)" + name: "${light_2_name}" id: light_2 - output: light_output_2 + output: light_output_2 \ No newline at end of file diff --git a/packages/battery_levels.yaml b/packages/battery_levels.yaml.oldtemp similarity index 100% rename from packages/battery_levels.yaml rename to packages/battery_levels.yaml.oldtemp diff --git a/packages/entrance_spot_person_detection.yaml b/packages/entrance_spot_person_detection.yaml new file mode 100644 index 0000000..c72b277 --- /dev/null +++ b/packages/entrance_spot_person_detection.yaml @@ -0,0 +1,177 @@ +#:########################################################################################:# +# TITLE: ENTRANCE SPOT PERSON DETECTION +# PACKAGE: entrance_spot_person_detection.yaml +#:########################################################################################:# +# PURPOSE: +# - Turn on the entrance illumination when a configured motion/visitor/presence source +# becomes active. +# - Temporarily force the illumination ramp number to 1 second for fast response. +# - Restore the original ramp value after the sequence completes. +# - Restart the timing whenever any configured trigger entity activates again. +# +# HOW THIS PACKAGE IS STRUCTURED: +# - Trigger entities are stored in groups for easy future maintenance. +# - The automation listens for state_changed events and checks whether the changed +# entity is a member of one of those groups. +# - This avoids the limitation of group-state triggers, which would not retrigger +# if the group was already active from an earlier sensor. +# +# TO ADD MORE TRIGGERS LATER: +# - Add more binary sensors under: +# group.entrance_spot_person_detection_binary_sensors +# - Add more device trackers under: +# group.entrance_spot_person_detection_device_trackers +# +# DEVICE TRACKER NOTE: +# - Device trackers often indicate presence using the state "home". +# - If a tracker uses a different detected/present state, change the +# tracker_active_state value below. +#:########################################################################################:# + +group: + entrance_spot_person_detection_binary_sensors: + name: Entrance Spot Person Detection Binary Sensors + entities: + #- binary_sensor.esp_entmulti_outside_entrance_multisensor_moving_target + - binary_sensor.view_road_front_door_visitor + #- binary_sensor.view_road_front_door_motion + - binary_sensor.view_road_front_door_person + + entrance_spot_person_detection_device_trackers: + name: Entrance Spot Person Detection Device Trackers + entities: + - device_tracker.byd_atto3_ibeacon_bur4c2a_bermuda_tracker + +input_number: + entrance_spot_person_detection_saved_ramp: + name: Entrance Spot Person Detection Saved Ramp + min: 0 + max: 720 + step: 1 + mode: box + icon: mdi:timer-cog + +input_boolean: + entrance_spot_person_detection_ramp_saved: + name: Entrance Spot Person Detection Ramp Saved + icon: mdi:content-save-check + +automation: + - alias: Entrance Spot Person Detection + id: entrance_spot_person_detection + description: > + Turn on the front entranceway doorbell illumination when a configured binary + sensor or device tracker activates. Temporarily force the ramp to 1 second, + then restore the previous ramp setting after the sequence completes. + mode: restart + trigger: + # Listen for all entity state changes, then filter below so we only respond + # to configured sensors/trackers becoming active. + - platform: event + event_type: state_changed + + variables: + # Easy-edit entities. + light_switch_entity: switch.front_entranceway_led_light_controls_doorbell_illumination + ramp_number_entity: number.front_entranceway_led_light_controls_doorbell_illumination_ramp + + # Easy-edit groups. + binary_sensor_group_entity: group.entrance_spot_person_detection_binary_sensors + device_tracker_group_entity: group.entrance_spot_person_detection_device_trackers + + # Easy-edit active states. + binary_sensor_active_state: "on" + tracker_active_state: "home" + + # State-change details from the event trigger. + changed_entity_id: "{{ trigger.event.data.entity_id if trigger.event.data is defined else none }}" + old_state_value: > + {{ trigger.event.data.old_state.state if trigger.event.data.old_state is not none else none }} + new_state_value: > + {{ trigger.event.data.new_state.state if trigger.event.data.new_state is not none else none }} + + # Members of the configured groups. + binary_sensor_entities: > + {{ state_attr(binary_sensor_group_entity, 'entity_id') | default([], true) }} + device_tracker_entities: > + {{ state_attr(device_tracker_group_entity, 'entity_id') | default([], true) }} + + # Trigger logic. + binary_sensor_triggered: > + {{ + changed_entity_id in binary_sensor_entities + and old_state_value != binary_sensor_active_state + and new_state_value == binary_sensor_active_state + }} + + device_tracker_triggered: > + {{ + changed_entity_id in device_tracker_entities + and old_state_value != tracker_active_state + and new_state_value == tracker_active_state + }} + + condition: + # Only continue if the changed entity is one of our configured trigger entities + # and it has transitioned into its active/detected state. + - condition: template + value_template: > + {{ binary_sensor_triggered or device_tracker_triggered }} + + action: + # Save the original ramp value only once per active detection cycle. + # Because the automation uses restart mode, repeated triggers will restart + # the sequence without overwriting the original saved ramp value. + - choose: + - conditions: + - condition: state + entity_id: input_boolean.entrance_spot_person_detection_ramp_saved + state: "off" + sequence: + - service: input_number.set_value + target: + entity_id: input_number.entrance_spot_person_detection_saved_ramp + data: + value: > + {{ states(ramp_number_entity) | float(1) }} + + - service: input_boolean.turn_on + target: + entity_id: input_boolean.entrance_spot_person_detection_ramp_saved + + # Force the illumination ramp to 1 second for a fast response. + - service: number.set_value + target: + entity_id: "{{ ramp_number_entity }}" + data: + value: 5 + + # Turn on the entrance illumination. + # The controlled device/light logic is expected to turn itself off later. + - service: switch.turn_on + target: + entity_id: "{{ light_switch_entity }}" + + # Hold briefly, then restore the ramp once activity has stopped retriggering + # the automation for this cycle. + - delay: "00:00:03" + + # Restore the original ramp value that was active before detection. + - service: number.set_value + target: + entity_id: "{{ ramp_number_entity }}" + data: + value: > + {{ states('input_number.entrance_spot_person_detection_saved_ramp') | float(1) }} + + # Clear the saved-state flag ready for the next fresh trigger cycle. + - service: input_boolean.turn_off + target: + entity_id: input_boolean.entrance_spot_person_detection_ramp_saved + + # Optional tidy reset of the helper value. + - service: input_number.set_value + target: + entity_id: input_number.entrance_spot_person_detection_saved_ramp + data: + value: 0 diff --git a/packages/gas_heater_operation.yaml b/packages/gas_heater_operation.yaml.old2026 similarity index 100% rename from packages/gas_heater_operation.yaml rename to packages/gas_heater_operation.yaml.old2026 diff --git a/packages/openhasp_lounge1_wallplate.yaml b/packages/openhasp_lounge1_wallplate.yaml index c87c35a..ee51697 100644 --- a/packages/openhasp_lounge1_wallplate.yaml +++ b/packages/openhasp_lounge1_wallplate.yaml @@ -1,144 +1,546 @@ ############################################################################### -# PACKAGE: OpenHASP Thermostat (MQTT-only, all BUTTON objects) +# PACKAGE: OpenHASP Thermostat / Gas Heater Control # NODE/TOPIC ROOT: hasp/openhasp_1/ +# +# PAGE OBJECTS USED +# - p1b1 = main temperature display +# - p1b2 = alternating Setpoint / Humidity display +# - p1b3 = setpoint down +# - p1b4 = setpoint up +# - p1b5 = heater status text +# - p1b6 = heater operation / flame button ############################################################################### +############################################################################### +# HELPERS +############################################################################### +input_boolean: + hasp_setpoint_hold_active: + name: HASP Setpoint Hold Active + initial: false + input_number: - lounge_setpoint: - name: Lounge Setpoint - min: 10 - max: 30 - step: 0.5 + # How long Setpoint and Humidity are each shown before rotating + hasp_setpoint_humidity_cycle_seconds: + name: HASP Setpoint Humidity Cycle Seconds + min: 1 + max: 60 + step: 1 mode: box - unit_of_measurement: "℃" - initial: 21.5 + unit_of_measurement: s + initial: 10 + + # After the setpoint changes, hold the setpoint screen for this long + hasp_setpoint_hold_seconds: + name: HASP Setpoint Hold Seconds + min: 1 + max: 60 + step: 1 + mode: box + unit_of_measurement: s + initial: 15 + +############################################################################### +# MQTT ENTITIES +############################################################################### +mqtt: + sensor: + - name: "Lounge Environment Humidity MQTT" + unique_id: "lounge_environment_humidity_mqtt" + state_topic: "viewroad-status/lounge-environment/humidity" ############################################################################### # AUTOMATIONS ############################################################################### automation: - # --- PUSH LABEL TEXTS (on buttons) ---------------------------------------- + # ------------------------------------------------------------------------- + # Main temperature display + # - Shows normal lounge temperature + # - If heater test mode is ON, shows the test temperature instead + # - Normalises values so we do not get duplicated °C or long float strings + # ------------------------------------------------------------------------- - id: hasp_temp_to_btn_text alias: "HASP: update temp (p1b1.text)" mode: queued trigger: - platform: state - entity_id: sensor.lounge_environment_lounge_environment_temperature + entity_id: + - sensor.lounge_environment_lounge_environment_temperature + - switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_test_mode + - sensor.rinnai_neo_gas_heater_rinnai_neo_gas_heater_test_mode_temp action: - service: mqtt.publish data: topic: "hasp/openhasp_1/command/p1b1.text" - payload: "{{ states('sensor.lounge_environment_lounge_environment_temperature')|float(0)|round(1) }} °C" - - - id: hasp_setpoint_to_btn_text - alias: "HASP: update setpoint (p1b2.text)" - mode: queued - trigger: - - platform: state - entity_id: input_number.lounge_setpoint - action: - - service: mqtt.publish - data: - topic: "hasp/openhasp_1/command/p1b2.text" - payload: "Set: {{ states('input_number.lounge_setpoint')|float(0)|round(1) }} °C" - qos: 1 - retain: true + payload: > + {% if is_state('switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_test_mode', 'on') %} + {% set raw = states('sensor.rinnai_neo_gas_heater_rinnai_neo_gas_heater_test_mode_temp') %} + {% else %} + {% set raw = states('sensor.lounge_environment_lounge_environment_temperature') %} + {% endif %} + {% set cleaned = raw + | replace('°C', '') + | replace('° C', '') + | replace('C', '') + | trim %} + {% if cleaned not in ['unknown', 'unavailable', '', 'none', 'None'] %} + {{ cleaned | float(0) | round(1) }} °C + {% else %} + -- °C + {% endif %} + # ------------------------------------------------------------------------- + # Heater status text at bottom of screen + # ------------------------------------------------------------------------- - id: hasp_heater_status_to_btn_text alias: "HASP: update heater status (p1b5.text)" mode: queued trigger: - platform: state - entity_id: switch.lounge_heater + entity_id: sensor.rinnai_neo_gas_heater_rinnai_neo_gas_heater_status_text action: - service: mqtt.publish data: topic: "hasp/openhasp_1/command/p1b5.text" payload: > - {% if is_state('sensor.gas_heater_operating','ON') %} - HEAT ON - {% else %} - HEAT OFF - {% endif %} + {% set s = states('sensor.rinnai_neo_gas_heater_rinnai_neo_gas_heater_status_text') %} + {{ s if s not in ['unknown', 'unavailable', ''] else 'HEATER --' }} - # --- BUTTON HANDLING FROM THE PLATE (listens on /state/) ------------------ - - id: hasp_btn_up_increment - alias: "HASP: p1b3 up -> increment setpoint" + # ------------------------------------------------------------------------- + # When setpoint changes: + # - immediately show Setpoint + # - hold it for hold_seconds + # - then allow normal Setpoint/Humidity rotation again + # ------------------------------------------------------------------------- + - id: hasp_setpoint_changed_hold_display + alias: "HASP: show setpoint immediately and hold" + mode: restart + trigger: + - platform: state + entity_id: sensor.rinnai_neo_gas_heater_setpoint_text + action: + - service: input_boolean.turn_on + target: + entity_id: input_boolean.hasp_setpoint_hold_active + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b2.text" + payload: > + {% set s = states('sensor.rinnai_neo_gas_heater_setpoint_text') %} + {{ 'Setpoint: ' ~ (s if s not in ['unknown', 'unavailable', ''] else '--') }} + + - delay: + seconds: "{{ states('input_number.hasp_setpoint_hold_seconds') | int(15) }}" + + - service: input_boolean.turn_off + target: + entity_id: input_boolean.hasp_setpoint_hold_active + + # ------------------------------------------------------------------------- + # Up / Down buttons on the HASP plate + # These call the existing HA button entities + # ------------------------------------------------------------------------- + - id: hasp_btn_up_press + alias: "HASP: p1b4 up -> heater setpoint UP" mode: queued trigger: - platform: mqtt topic: "hasp/openhasp_1/state/p1b4" condition: - condition: template - value_template: "{{ trigger.payload_json.event|default('') == 'up' }}" + value_template: "{{ trigger.payload_json.event | default('') == 'up' }}" action: - - service: input_number.increment + - service: button.press target: - entity_id: input_number.lounge_setpoint + entity_id: button.rinnai_neo_gas_heater_rinnai_neo_gas_heater_setpoint_up - - id: hasp_btn_down_decrement - alias: "HASP: p1b4 up -> decrement setpoint" + - id: hasp_btn_down_press + alias: "HASP: p1b3 up -> heater setpoint DOWN" mode: queued trigger: - platform: mqtt topic: "hasp/openhasp_1/state/p1b3" condition: - condition: template - value_template: "{{ trigger.payload_json.event|default('') == 'up' }}" + value_template: "{{ trigger.payload_json.event | default('') == 'up' }}" action: - - service: input_number.decrement + - service: button.press target: - entity_id: input_number.lounge_setpoint + entity_id: button.rinnai_neo_gas_heater_rinnai_neo_gas_heater_setpoint_down - # --- PUSH INITIAL VALUES ON HA START / PANEL ONLINE ----------------------- - - id: hasp_push_on_ha_start - alias: "HASP: push texts on HA start" + # ------------------------------------------------------------------------- + # Middle flame button + # - Tap toggles heater operation + # ------------------------------------------------------------------------- + - id: hasp_btn_heat_toggle + alias: "HASP: p1b6 up -> heater operation toggle" mode: queued + trigger: + - platform: mqtt + topic: "hasp/openhasp_1/state/p1b6" + condition: + - condition: template + value_template: "{{ trigger.payload_json.event | default('') == 'up' }}" + action: + - service: switch.toggle + target: + entity_id: switch.rinnai_neo_gas_heater_heater_operation + + # ------------------------------------------------------------------------- + # Flame button appearance + # - Operation OFF: solid light grey background, white flame + # - Operation ON, flame OFF: solid dark background, white flame + # - Operation ON, flame ON: solid dark background, continuous red/orange flicker + # ------------------------------------------------------------------------- + - id: hasp_heat_button_state + alias: "HASP: update heat button state (p1b6)" + mode: restart + trigger: + - platform: state + entity_id: + - switch.rinnai_neo_gas_heater_heater_operation + - switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_power + action: + - choose: + # OFF → dark grey (same as your other inactive buttons) + - conditions: + - condition: state + entity_id: switch.rinnai_neo_gas_heater_heater_operation + state: "off" + sequence: + - service: script.turn_off + target: + entity_id: script.hasp_heat_flame_flicker + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text" + payload: "\uE238" + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text_color" + payload: "#FFFFFF" + + # solid dark grey (no gradient) + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_color" + payload: "#2F3240" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_grad_color" + payload: "#2F3240" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.border_color" + payload: "#2F3240" + + # ON (not firing) → theme blue + - conditions: + - condition: state + entity_id: switch.rinnai_neo_gas_heater_heater_operation + state: "on" + - condition: state + entity_id: switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_power + state: "off" + sequence: + - service: script.turn_off + target: + entity_id: script.hasp_heat_flame_flicker + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text" + payload: "\uE238" + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text_color" + payload: "#FFFFFF" + + # MATCH THEME BLUE + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_color" + payload: "#0095D9" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_grad_color" + payload: "#00B6FF" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.border_color" + payload: "#0095D9" + + # ON + flame → blue background + flicker + - conditions: + - condition: state + entity_id: switch.rinnai_neo_gas_heater_heater_operation + state: "on" + - condition: state + entity_id: switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_power + state: "on" + sequence: + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text" + payload: "\uE238" + + # keep blue background + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_color" + payload: "#0095D9" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_grad_color" + payload: "#00B6FF" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.border_color" + payload: "#0095D9" + + - service: script.turn_on + target: + entity_id: script.hasp_heat_flame_flicker + + # ------------------------------------------------------------------------- + # Start / restart display when HA starts + # ------------------------------------------------------------------------- + - id: hasp_start_on_ha_start + alias: "HASP: start display loop on HA start" trigger: - platform: homeassistant event: start action: - - service: script.hasp_push_all_texts + - service: script.hasp_push_static_texts + - service: script.turn_on + target: + entity_id: script.hasp_rotate_setpoint_humidity - - id: hasp_push_on_panel_online - alias: "HASP: push texts when panel goes online" - mode: queued + # ------------------------------------------------------------------------- + # Re-push screen state when panel comes online + # ------------------------------------------------------------------------- + - id: hasp_start_on_panel_online + alias: "HASP: start display loop when panel goes online" trigger: - platform: mqtt - topic: "hasp/openhasp_1/status" + topic: "hasp/openhasp_1/LWT" condition: - condition: template value_template: "{{ trigger.payload == 'online' }}" action: - delay: "00:00:05" - - service: script.hasp_push_all_texts + - service: script.hasp_push_static_texts + - service: script.turn_on + target: + entity_id: script.hasp_rotate_setpoint_humidity ############################################################################### -# SCRIPT: Push all texts to buttons +# SCRIPTS ############################################################################### script: - hasp_push_all_texts: - alias: "HASP: push all texts" + # ------------------------------------------------------------------------- + # Push all current values / colours to the panel + # Useful on HA startup and panel reconnect + # ------------------------------------------------------------------------- + hasp_push_static_texts: + alias: "HASP: push static texts" mode: queued sequence: - service: mqtt.publish data: topic: "hasp/openhasp_1/command/p1b1.text" - payload: "{{ states('sensor.lounge_environment_lounge_environment_temperature')|float(0)|round(1) }} °C" - - - service: mqtt.publish - data: - topic: "hasp/openhasp_1/command/p1b2.text" - payload: "Set: {{ states('input_number.lounge_setpoint')|float(0)|round(1) }} °C" - qos: 1 - retain: true + payload: > + {% if is_state('switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_test_mode', 'on') %} + {% set raw = states('sensor.rinnai_neo_gas_heater_rinnai_neo_gas_heater_test_mode_temp') %} + {% else %} + {% set raw = states('sensor.lounge_environment_lounge_environment_temperature') %} + {% endif %} + {% set cleaned = raw + | replace('°C', '') + | replace('° C', '') + | replace('C', '') + | trim %} + {% if cleaned not in ['unknown', 'unavailable', '', 'none', 'None'] %} + {{ cleaned | float(0) | round(1) }} °C + {% else %} + -- °C + {% endif %} - service: mqtt.publish data: topic: "hasp/openhasp_1/command/p1b5.text" payload: > - {% if is_state('sensor.gas_heater_operating','ON') %} - HEAT ON - {% else %} - HEAT OFF - {% endif %} + {% set s = states('sensor.rinnai_neo_gas_heater_rinnai_neo_gas_heater_status_text') %} + {{ s if s not in ['unknown', 'unavailable', ''] else 'HEATER --' }} + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b2.text" + payload: > + {% set s = states('sensor.rinnai_neo_gas_heater_setpoint_text') %} + {{ 'Setpoint: ' ~ (s if s not in ['unknown', 'unavailable', ''] else '--') }} + + # Push middle flame button state + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text" + payload: "\uE238" + + - choose: + - conditions: + - condition: state + entity_id: switch.rinnai_neo_gas_heater_heater_operation + state: "off" + sequence: + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text_color" + payload: "#FFFFFF" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_color" + payload: "#2F3240" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_grad_color" + payload: "#2F3240" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.border_color" + payload: "#2F3240" + + - conditions: + - condition: state + entity_id: switch.rinnai_neo_gas_heater_heater_operation + state: "on" + - condition: state + entity_id: switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_power + state: "off" + sequence: + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text_color" + payload: "#FFFFFF" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_color" + payload: "#0095D9" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_grad_color" + payload: "#00B6FF" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.border_color" + payload: "#0095D9" + + - conditions: + - condition: state + entity_id: switch.rinnai_neo_gas_heater_heater_operation + state: "on" + - condition: state + entity_id: switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_power + state: "on" + sequence: + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_color" + payload: "#0095D9" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.bg_grad_color" + payload: "#00B6FF" + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.border_color" + payload: "#0095D9" + - service: script.turn_on + target: + entity_id: script.hasp_heat_flame_flicker + + # ------------------------------------------------------------------------- + # Rotate the middle information line between Setpoint and Humidity + # Pauses humidity display while the setpoint hold flag is active + # ------------------------------------------------------------------------- + hasp_rotate_setpoint_humidity: + alias: "HASP: rotate setpoint and humidity" + mode: restart + sequence: + - repeat: + while: + - condition: template + value_template: "{{ true }}" + sequence: + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b2.text" + payload: > + {% set s = states('sensor.rinnai_neo_gas_heater_setpoint_text') %} + {{ 'Setpoint: ' ~ (s if s not in ['unknown', 'unavailable', ''] else '--') }} + + - delay: + seconds: "{{ states('input_number.hasp_setpoint_humidity_cycle_seconds') | int(10) }}" + + - condition: state + entity_id: input_boolean.hasp_setpoint_hold_active + state: "off" + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b2.text" + payload: > + {% set h = states('sensor.lounge_environment_humidity_mqtt') %} + {% if h in ['unknown', 'unavailable', ''] %} + Humidity: Unknown + {% else %} + Humidity: {{ h }}% + {% endif %} + + - delay: + seconds: "{{ states('input_number.hasp_setpoint_humidity_cycle_seconds') | int(10) }}" + + # ------------------------------------------------------------------------- + # Continuous flame flicker while heater operation is ON and flame/power is ON + # Only the icon colour flickers. Background stays fixed. + # Flicker colours are red <-> orange + # ------------------------------------------------------------------------- + hasp_heat_flame_flicker: + alias: "HASP: heat flame flicker" + mode: restart + sequence: + - repeat: + while: + - condition: state + entity_id: switch.rinnai_neo_gas_heater_heater_operation + state: "on" + - condition: state + entity_id: switch.rinnai_neo_gas_heater_rinnai_neo_gas_heater_power + state: "on" + sequence: + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text_color" + payload: "#FF3030" + - delay: "00:00:00.35" + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text_color" + payload: "#FF8C00" + - delay: "00:00:00.20" + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text_color" + payload: "#FF5A36" + - delay: "00:00:00.30" + + - service: mqtt.publish + data: + topic: "hasp/openhasp_1/command/p1b6.text_color" + payload: "#FFA500" + - delay: "00:00:00.18" diff --git a/packages/presense_sense.yaml.old b/packages/presense_sense.yaml.old deleted file mode 100644 index dc691fc..0000000 --- a/packages/presense_sense.yaml.old +++ /dev/null @@ -1,98 +0,0 @@ -# ESPresence Sensing -# https://espresense.com/home_assistant -# - -# In the secrets.yaml file you want something like this to match each one. -# Obviously you don't need to use secrets, but it helps if you are sharing your -# home assistant config with others. -# -# btb09_uID: My_tracked_item_name_(ID)" -# btb09_dID: "known:xxxxxxxxxxxx" -# btb09_name: "My Tracked Item Name (ID)" -# btb09_topic: espresense/devices/known:xxxxxxxxxxxx - -sensor: - - platform: mqtt_room - unique_id: !secret btb01_uID - device_id: !secret btb01_dID - name: !secret btb01_name - state_topic: !secret btb01_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb02_uID - device_id: !secret btb02_dID - name: !secret btb02_name - state_topic: !secret btb02_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb03_uID - device_id: !secret btb03_dID - name: !secret btb03_name - state_topic: !secret btb03_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb04_uID - device_id: !secret btb04_dID - name: !secret btb04_name - state_topic: !secret btb04_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb05_uID - device_id: !secret btb05_dID - name: !secret btb05_name - state_topic: !secret btb05_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb06_uID - device_id: !secret btb06_dID - name: !secret btb06_name - state_topic: !secret btb06_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb07_uID - device_id: !secret btb07_dID - name: !secret btb07_name - state_topic: !secret btb07_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb08_uID - device_id: !secret btb08_dID - name: !secret btb08_name - state_topic: !secret btb08_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb09_uID - device_id: !secret btb09_dID - name: !secret btb09_name - state_topic: !secret btb09_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb10_uID - device_id: !secret btb10_dID - name: !secret btb10_name - state_topic: !secret btb10_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb11_uID - device_id: !secret btb11_dID - name: !secret btb11_name - state_topic: !secret btb11_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home - - platform: mqtt_room - unique_id: !secret btb12_uID - device_id: !secret btb12_dID - name: !secret btb12_name - state_topic: !secret btb12_topic - timeout: 60 - away_timeout: 120 # number of seconds after which the enitity will get status not_home