From df29f89977911c61d9ebcfad6921f4056d01c05c Mon Sep 17 00:00:00 2001 From: Thomas Peterson Date: Sat, 24 Jan 2026 18:31:31 +0100 Subject: [PATCH] Fixes --- .../index/EthSetting.cpp.4B55389D58A8AEB7.idx | Bin 4470 -> 4628 bytes .../clangd/index/Gui.cpp.BDF53DB313293DD9.idx | Bin 3036 -> 3232 bytes .../WidgetConfig.cpp.FD56F9F36C29A5DA.idx | Bin 8238 -> 8394 bytes .../WidgetManager.cpp.D8CE609DC911F13E.idx | Bin 34274 -> 28674 bytes .../WidgetManager.hpp.8559171B7B8A010C.idx | Bin 3974 -> 5564 bytes .../index/main.cpp.7C677863E2582AB3.idx | Bin 5988 -> 6252 bytes dependencies.lock | 9 +- main/Gui.cpp | 19 +- main/Gui/EthSetting.cpp | 3 +- main/Gui/WifiSetting.cpp | 16 +- main/Touch.cpp | 4 +- main/WidgetManager.cpp | 190 ++++++++++++++---- main/WidgetManager.hpp | 29 ++- main/idf_component.yml | 3 +- main/main.cpp | 17 +- main/widgets/ButtonWidget.cpp | 39 ++-- main/widgets/ButtonWidget.hpp | 1 + sdcard_content/webseite/index.html | 12 ++ 18 files changed, 265 insertions(+), 77 deletions(-) diff --git a/.cache/clangd/index/EthSetting.cpp.4B55389D58A8AEB7.idx b/.cache/clangd/index/EthSetting.cpp.4B55389D58A8AEB7.idx index d99c21a07c3a4cccf1e5e606b1744ff5e58057e2..b04cf21f556c3e6da79914ec7c9a7137da1554a9 100644 GIT binary patch literal 4628 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 I;4Z-Y57PZoy#N3J literal 4470 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 T*tFhp@^e>5!3h8|fyw^^@1R-K diff --git a/.cache/clangd/index/WidgetManager.hpp.8559171B7B8A010C.idx b/.cache/clangd/index/WidgetManager.hpp.8559171B7B8A010C.idx index c2e8389c867107036151d0637f4f137f1dd7059a..bc686a7bcb3136780182739fea778d249a3ab9ba 100644 GIT binary patch literal 5564 zcmY+H2Ur!y8itq6L0DK0OF7g-U5?TPqzQr|MGyfM6|f(gNQo3d5W`i26)S2iL`5-b zEJ##T#Da<%yAU;&C&k1VByvL%3rbAx%$o0TWB7ehgFk>BaF=X4QC^zFhslwyGxg?yl%{!^a-Z$or~s z*u#(%+cR1NFYSJ{$bVpOm&xLJjr;n)RF^L(s_!aa-F0ojs6*yQ-kAH>OpAJwT5#)! z<}#mmooeH62H3h^xaR9vm4D@C-L-C=*tF`KDMweBam_JxzNs7AQth(8E;h3Ct1ak_ z_gAb5b}4Let1pwk+O#t2R@vF^y9+j2u3j7^o*%T{pmnqM?Gfpo7LUh&=AT%X)fel;Jb)Y@h5RhRFrHOgHvxoW%h;cC68_3h`^5BtJPHOH4pO39C} zcebiiHnwNnSn`-V(J8yL{MfJOE>E}k^zh?n-ML+3hP)wZ>5&~C_5ZcUm0=t)p$6SF_8tMl|G z!SwH)Th6{t8ae*np9}ri$o#orap&{o_YbDEcAQp~J%9IQ-OUv%;%)999G&Xgpj`QG zl&k(q-^NF7dkP;1g>dk-D`=ev)fq=80 z%u@dxK2@i|Xwy^G{UR#MQ|7mqyM7w{FaBZ-~Pr#ngk_EN7C z=PkBvH4@lBBzNUpjbUqVDOpjx`KqnJ4ud_48>N6nb@LOQts4c(#=kV4wM|vV&`S>88za#11hGv62Gp z8&%`)tk3Xq7g!r4pU6$rOs%c#qqTF5_jwvJteg>t>JBxQ0>hCdG%(W=wY|1~Ub$dq zxsM_90ckKycbFiBz6OJimQHwPS{NX`oERVrFp>hscgUFE@2ivMq2_D?nV!GQUt0>W zZC@W5P(8zKsDjld_B5MmE>eJ?4<*XO63+072Qh@za{?J^D!t`)~HNwl8 za3-d(*+lQk+`79Xz+*G$~b{F zLGnZ{QL}PawbZ}Q%e0RdSS9QPF2NkVtG+nB=9~C433A4TXT(UONGmD8-W_w&d&Vm5 z2?85}-lMtEn%+INdwNT^M@*Eneq?I7e6FPw(0fzIt24%pMrwgINADCaMYGqdqQXxo zrrV^+S%LIUtT6Fbl(&{_(x4fDI($C$=v3v4)Mp2Q_- zW**`8a%O|ygKP!ckMs^w26;*Wy>D;;zt6NgluCH4T=W}KNB?2@V5<~f(g6v){@Bzd+`wzU*syEYB?j2)O&BCrF| z+mUlLfW4t?Nn`J(k~sov2z#={WGC1aF0Jl$$J*z}Sr3vtkI%D~0_@WvnHx%O4=WYe zAoNyoD$RCSn50S{_{e{*z*@l`&y822_qV6s9W%AauaL7AB)M9yR!9N%+{L?p8GIsU zp`7(6b`GDTlmcwUZ`-xzZ2Y5A&cuX=YLVO)$L!Z!|E}NsMk-=L<-UY zz%b;5sH<*&yV<>GnVcC(`bU^XSV#f=L)=d$?wtSeayb)C>=6bdjHLiOEM|mI+A^X_ zU=?_^3ETut2_G8lURqULLhSxz?mh}1TPdLTe-}N=Z#}=_llQi_p|^!d1MD}!p9k-I z*+J~#NS@3kYwV|jt?gfDdN=>yH=ATU$rimm8&^Hp*Li2VoQWYbk2Z)lk^<~QKOeXe zar*goIXi+(EsM{xl>+Q#$q#&{*S78wSWk={%f)Iw>C$NJk|8$h4hrlj*p{574SFZp zhlShkztr3pJ+)Ps` zz9JxUL zxrggM=^j4ZW?7rS4u!4cl$v9+Xvfj&C{@f|fwhJm$HiHpx9K+L5|5sP_XIWowhQN? z*$yK&e_hc#x#_XMn!+B#jnS0w{D@u7713L|1lA3F`(89^didJ=)4LO>u|oJ1awK^~+v z#SV@94{;Eg;s#`p21!B*1F~;OtKR*xiKZX$qM4(aGmbJ|3{nJH8#F>{eb(wo7(H)$!sa z*(3o)#*35nCY#}y1huew60IOFFGlD_nBYVKyO23iWz#nHOD6 zT&?k4c`;HqQUD$B;u!NWcG%UtIM!mUJ*txz6U`EBK_NgLvKAC^FoRe3W49!xeHp36 zi}`l>Di9C;CG(}&gVxv@WYsC|K<340<7g4b9Y!Q0QQko#@D7nF=Rn4rkdY|l;9vsZ zkk*uI&>CDrT2rWjtP0K2?dCJ5lifW{F-?h&z>B%ETz&N6#XMP_J}y!q5E+1?4>AFL z$N-dkAa_g+y?eFrd^%aCZ1?PexavVdq&3ALv<3kYnc@#*kPne5_CN;lkex(v2Qo;9 zOpp=|WYj82Lh%MN$cD%iYaoMYND@jikWv0brUV1I@@V7zGj4nHwRzFQ&m#oqIH^(p z_|U!@Esz!Pctu_;loj&W-n>{OE8=lrX;w*30wIh75F&$90D_FlCNc#d$oO95#VGYa z2Jn#96m%d1bcjp=2QmPM><@1zZ#Uffyy)ZQ697celb{D(E*7qvzy0RC3R)P>`GZgp zU?DOc3PNZN1|l*AAnf8LJ+05ijd@+k@nVQgh!c(!UYwwqpai+_Vv=c+H9j{lrpi+F zu?=}KO_rvQdxsa(W$F6re-3_L%#da1V+-sevK)O(7PHjVdyii4|9i{u zBCpR|;Na%}b)55}zqY^T_Tc|@^pRf{0V2~hfjjEjlLl=>j!7$iw3^5Nz1 zWr$2s53O$(bWPc_Xw?of6AwoZPm~r_{Ag}gH`(enb4{y-2lX)9pc}dyn z`IzAQ@uFI$Hb8~mA95ilL|t%;?g1`ejy(V;En?elGc;~(HgZ#){6olWUwERDfpq%3o~-nwAzXa(~73i u2PYcd|FOpd!#MUms`?(q1D%}K#N%CSbR3;j_71jojBTH3*Z1hq_xL}XUH7yA literal 3974 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 B#sB~S diff --git a/.cache/clangd/index/main.cpp.7C677863E2582AB3.idx b/.cache/clangd/index/main.cpp.7C677863E2582AB3.idx index 7dcb36616d17b9fcdb0f53e0f39a377efad90191..f919c2c9ecf8f34f2f92e99e8acce33f9032f2f3 100644 GIT binary patch literal 6252 zcmcInX*d*I8=iwQ7)y3p1`UlZglvOs*_A|#Eg}*nlt?tTknBp6sH_PQQ3|0ViMJ8i zy-3#QBhN|pF!lZ}z^iAe05j{J8d4xQsQ@1m6^!^s{P07|8`o4C9<&pn*ynE2x5z>FgwrcFdm=(by^ZEJ+4|JVV8SmzF0^1;jdpDv?*s($y%D{ z<_?xH8z0%af6RpS7x&e2@_xCnxCTQWz56A<@`vgx#+L77BpV5L7LBW9FAU8_@Qkiv z?#G+#i@clWH+x6#;1mA3}1CAzpr+~Wl&euN8NiXc&%i8(eM5g*rD*Bch= zlDB3o*XWX?D}M@yUY=1tZX4e4ulDwcvqY(c?do%Nt& z#OwARxzjnjb*sfS zKeEfFb`GB{jK6T~5pTPI<*TlH+xtg`w)YRH$mdLV$!51$Zu3?NA^LZjc&i8%Pb51? zzVV9^@Z}OnPt&*l{8o1ywO4TddE1++A@tDu{_Sc_>9mrBdNt4t%tAL zWxDh_c9M=I4W0JfP$^P7wmv1`4llni#r~X;i%JKTqsMAd-=y57y?ueT^tfRl(}4{e z&o=~)#fChv3Y90gNZDMrUmg@QjpZ4*ers%Z(#f(CzGTrj|4|R(#!F5oGKSjJl6)w; z>{-$&zHcRk_!eB!GYdbrG}@<6_lbU4(^_b7+W0|iWNpN?orMW%op;p&>ol~z&fRie zZ*uX}eH*UEBDSNYf6aUNkcQ_$ z`5X`);tsBvHP;_!rPdAmRNuipHQVT_wWV~Ymj&s)!J#ETV|UL>&lZQy zxj)<^m+fgj;4t;RF64V+m4EYV^RX;^BSFrAVjfu)rywnwMRw$3d%HKD!|QzN4c@zj z)w1nB#(Yh0zK{03nEE4DQDaWSu6|s3V70x>#xHNXIVj^UTAy~8H|Vk&NU0BzBLp5y z#|l0im=Dhl&+&R4%O;>vko49vMrJ6dW3_(%!H8dXBa(@qUwAf_=S4cEOl11Zizvly zj~c)DVpDxvtCn(&zT3H~qTFjS4pSc!_f`HNwBG8O`B$a4?(8E|>oQ4M)wb!L6IM%$ zCm(U;?B{VObRLS3TQ*B0bCSB#PMOPHRsM8H-RlNkjC<4Tn;)eux-{nGY%go$mk;ae zdnpt2=Ty(BMIZVeq($M&ZkEF%u!Y`rlZ;}iCsjbhMw-TR_W=#rS-n?~p%qM{~`#?*wtlhA4Ako}Z zdx-5x?P2^|U_F7e*wJ?=`Jz~~rC~F>sY$;E$9SNJ7ZQhglZ=_k@zr{-B@74=Au9~E9w!qd$yJVO- zo#@)0oqgl5({zjT(@;m-NFML_!YP-@+P)GE_v+Dm*W5HHW?OA;)-@a)4%>WS*mC#W zlvU8jlbyfbRKG9Jdbg+AQMp`w?R-utkEna?t(V%`k4aKyCxINNqke!tt1d7b;!7epr^K^AM@%Z z@q6?&QgGR$Y31Atc(;?kqGIQaqX#E`RTib~8Qi5)+T;Ig`bm%4?Xk|hu7#9Aqj>qZ zUssivE}beE5Qrb^JyV)wRvS7IXyNH_->0y&bj$6tgo;u~ zvpw`Z*InCHBlG$n=JVP~@-y;x>}00;E3$fBo!uXY^V?)w`HvT_n(x^DAl?7+?$;7d za$5yE6@rXs++q?RJPHc+_s{~g`_o{kB6>S3k%#F8XaN{1z_Z~w|BSTT_4jA&aU1{M z`gi-dn1=pPoYDW}pUE`RXkHhr;Ho}MFTFxAVP$ImZA5&v_!=sJBVrh676%2^^$qec4gN7=#Abw}0yrYdb2hW7pHtHB zxR?h1P+YJsG-u(6D1l!4gI;iAFm~_qH97AttpY4mK$ImKqkOt9aU8h2Aj1yjnj1A8 zki0gDxi}|AksZ*MRKu#RLGt{gFH3_1Rd7(gj&q#=lDECf8#|OR8w?8^793P zF`xU_@-oV+EK^@%YTocN(d;N<71tv^gSsOA*+}#G7$LZv3yTXYidgJx`iyKyn=qr> z#tP4G&+1p(X+CSmUf$D%JYEJ>X|+oD?IUIGwNBnR8W!(SAXAZqI_x zj4UHxw5qoEUjT^EzU~HHeH0G*&&2+xS5et%G*7H24)r7TsOY3)Rj?w=h8$K-2vv^; z^{{#?aKd6ZZR-z`=4x7&46p_~$T|(0;!OEb$IzfT)|`h9!jS2pJ=UK7TMrhG6;D!+ zS%hAVo783u@WanO8QJ6FBq*ovAFjcvimh7R#*BOisoPP?&0Us^e2RLjm6m9=4I_Wq zPD0$pkm$t7ANVpCU>2(B%E%vNse5aeG`9CIred@0f@<`I8h6H}`9VTe8Re!2ES5S} zor|tm+F0!sh>jx`8chZ(!-0TA#oJ3-!qhH*w>l(r)j+80H<{ z-afI!7$3$kHz{mOH*%`=g)Oa#)s#UVT8BqP)Q^5X4CNML7HX)kc(n)h-Ytp*FxnYA zVYEM_faA#Tt%21QLw2@p(^{qJVt9m+&s+MbbRlK&H(v*Rqw~Yt?#Z;i} z2xwJ+R|Bf7_~Z>m%uvEn7=j6>2_Fi18FW5zc}+V07hS@*CkriJhzo;Dt4XREplqOf z3O1oF)|LagMDrZpRj7ZMZM^lmx~s`hT??;8Lh2uUGqHT}Tv1Tn0&BsG)M>lhO3+FS z!Jbz-oyN`5nrmk5F;KKnhfP~ z!g2~o?!VYvJsW;F^)DunO0H4x<6WHwU8O&`EC(FZ&6)Kw{^HWMqqg||RPqHFH9VhD zJ2j7v9-ZfPqQH{@9^*((gYev@gYclHgYck6@JeEy@6jgqtI#+s8Iq&d3A}OW-y}4e zCC+l?79hVU6PzRMD1_=J0w&_9;)$I6uLbI*OBpMRo;1ufJ^@SMMirz%C7co;g0w~9 zD+je-oXoS$7f)d;pf&o}#hmweiT)|y3fO+aSYck|Gz~i790ZXwd`bmbpM~+2&`AND z01u*R$ebooW}0q7xe$*KKa#HwD!!ug>Us?mZ8><2BClu=UZV)w1!-<3%hlCDbuFyc zN|%bC>8E4AIm;&bfyF(S-&xi zTdIYN60t-)awanSSZ)2ojN4Eyg_Byj(|aTe6CN3k+<|fvNfQFfNnZF!OmEiG9mamP zr-WD>4{fT4Db-!CtBCB=pc9J|8@i1e?Nm~f>{T0~**z?KI8a^rygq#iz?U>JnhgUr z14iVGhktRKB$54p@aNV%gf0i(NT$MGYscI+Npxh2?w+3aPC;S=v3Fl{>Fj7l` z<$5HiL1z|cR&+9&?iD%`c1-puWA9ybd!^W%NBZZtSqZy!Nc~I;w{TF-nI0%t;#ZPJ zZiM%EtW}Q>?}c)BfS|e$$ZYU^w|}_zFJ@-s`;6x_`C1=b8a}Gg(wZ4bA-sma`hRa9 zK4D2Dr_mgQ90&-uN!l^csV|AzCcBIb=Ur(v-CEc~2E9YO-X5`r@p&0C*_ta$^~?fC3Oky-SM z0jf)3rB=++Vu!zzQ0zCvvt#WQq&`4(Jz>3-?X&39o^=_YI`e;y6n(jtQ%+%@W*Bod zvGc-lDhT`ZJ10Jx$52qwK~g^Ntgd`!O7g)6M_+Zw{!yy<~q@jLX9Y?nj^vw1elM7d!^tpac8^o`O#B3_JlnfVRZ5|Frh` zd-|=S!A5W&GyrC%HN1jC!Xj%$#l$7>l4n3FNCT0+2mSW@9Pl?W-C}HJWNv9|Wo=_| zB=Be)hz2nr76cqR?6iB&E;(m6R~Itado1L5XvE2|6XEs-n{^!3^Fa|v2Zf*jB!d*N zLrQubVW*;+lB&G2Rus_Qq@bazxj`=hsBF|H;E}j8F1>2Vh;rE` zjpIr4Xj*7&S8P`sHeA8naW$wjEGXm?ae{bhR|7*LTb}NYp9`%9yLhvreN9Wp`$O5I zvFL?9gEun+fg8_%`98wL6?1ItM&$g(Djhb-&r^Z5 z+N~Fp!h3!^P*%C>vb`}w>%z0%2wxlWvMIroZ>R%`Tf`^TOB8%n1UMJ9k%v% z>`jXEqsHe3&JjC4><s>%TT^A?itGuUr|M@AkSzo^F4@odbG1M$6@O z0FfxM5sPQ@Y1MW=?jms@rsqL2&K_7hX^d5{-W@-M%@m)fIQpMvBt3N;Z(;4^G>F+v zcFM;tUVqy)nALsHwFP~io#;G|#opIWIXRaPOJCnHp%g{Xp@ryXt36hzq!*&5LUDyoR}c!}8vX0tOcbh6k^-Xy>_JJ>q4? zv(u~eW{lJB*CAx9%iX3w&B-qI$DXrrWc>cb#e@4juu|x9X@f_ms>ej|QU8u|uX^({ zDj@obaDM2&S^PgmSqv~g>x_GH;@pHM38P`bNSc!pxht%C9t(2-^jSpW|eWwe^L3x9PqwHxr z)FV0C?e2o=b+RX5Y!+QVGKc+Ui}f@Z;1rv+@pJSsOaPXMp#=xd^+-uB$`T zMb271caYJvEthM_7ZW+H8OE}&qQFa8z2yfhU-M<9>6W)ye4AK2G>2Z@m5{bz-!vAq z7G<)OU)zN7&kX$#JyD+^s%x@sXy~VhY+{0_pz*^FhSr=4-K`x1cJ_B8S0^we?)N*> zO4$NlPjK6?n%HgK_54BKu4p6aO*f?y8hgcM_j#X~(+n#s^lVH0xZ{E&`N`$vTSC~h zL(BsjHU0cM(->-4t=+iXpJYGgb3U=9Gp#;hNiP0)VPckT>;e^Ggm4{&m zC$IN-<=EO~cUL!`Jfc+m$wNqSzfY9J!Z&SROt$G}ftDTJmOgHMxuxnZb!F|tZfU*A z{0{>Ujxp;`Y_F7<8e4sJOO%HJFWD&DHq`np{bw$5U&}e6NW#GYf16cu$#6(H<^7(# zEW-ZCwOG<@WK7%mT2)b^!=SxJ$vvOn;hoi+?~Qil&rYSZ>7UVyk)C>C)`^b%@B~`=S<|!4IBu%GmpIrMcC(L!5 z0TmGHVi<;3fC5lGzy@Q3`#Vza)jyvAouSGYE0!(X3@`suaI84a z9)OIHGWw*Q??A)MK@7v-Uy3E0C07qXMo7WF5Iei+u5u6us)g#d2khnEEBJSW45sPT zn@+JFQ5c5)zecRkR_r|h86oAjjrm4Z-mEeV!=t|x3l0n39)OIHf(d7w>S|xEVPSaq z#}EGoex4qHjF6$DS{&eC_i~V%Vc@S34OR_~9)OIH(#L8%xjMON2E*|BFU1;dO$`MZ zAqC~{emJ0?I>U0NK$Y|U3Nv8p0b&wj2C!T%E9^(^FOk>~TuxEW7UH$ZjKw*zGHihA zQyMMJ1Mz~OiPAuSc@6}}bK?0S-aeB*bTs7_Ct^ojN!%IY88-xC7hiA0(&M*HQYTO~ zAF&KnJK|_@Nyw+0E<@;fL&=E6A?~c1tXW{n!r#;8BtqH+>BBaV?z{Iz`=$`RJJ>*s zR6BZTJswzHs%pYv!VgupzdZ$4=h4r{eyfk-iS*VkuwhkS{!$?!QJLaRH^b>$-WMoz z~06jAT=bSiPRV8-w#z)Mk}wYSr42EVo6wnImDm;als5B9@2q#<)sw(Fu=RuxFcw99oV9L&B;LYRxPQ`O))7!}Sk` z++aWcr>oIQ!jNxap~kH0taqHAk1bs&T}oO0!&gKribDRP8`Bp9i?P6enIqgffLc%F zY=>(k^6r)lYA7)XiCL3VlNauSt@ZlbOyxX-5!_V5bSuPvgRV~J51J?bWo#(d^SI@# z_%Otmw3xIGtOLApkiODK>$Afcs3{<~4r~cVGY_q&&#I%5>GA}5O*p-GN~4Pr=Xx5! zr8uO-AzoF9>Uge;LNuwg?Cyk1npHPi{RW2~EX;X+8*W}j}fki&c z$@hW3VN)snqQEBwa(@Yhf539G1E0Yp5v*()cAh?Nu$wtWE5Kw$gW2&r%fodPQ zfM6I@6}f<*Y8jxa8!c5=gG`r4%ddBiNaRz$iR|tgBq<3F3EEo8h{zCOt*C!hz$*}- z3X?-FN7@GymFB?Yzy)`>U-Iscdhsi@h*L4N7y$+ol^I;y(0cJ6f(vm7t>1>dqJ@cV zdT;6xTvJR_9OjrG@g}xEeWjkh<*c(q$R|RZ8<1V8B&j3=?Ne1tCQDX$$~Rfcr^s3> zG$Cd!m@L@gLh`yVeDx!gG}D_612qHs(HC3)WhW;``~2d|t7%1I5at%$Y+GnTUP_M|Lq>*#XivubIQc{r@ueH$UeNy^p^667hw+ zOQA2-i^(Bay|vc}PR5bNA>J-##;6y|J&5E;`;LX}fOH-528Ufpo$iEoVuxK2C(4tW2Ry4PClDOjp)icVK=D|yGkTMV9V9&H{%~r} z`F^pTQ-AEB@$9gqjTy`*zv*9kkKi^;Hk|OiJ4dGM=?>xfh~S32hInWPzN3-u6+#QG z+o5KMe0_k~-4e-+vz8`)My4wZDz7*BvghOUtAy0K|7YWCOSPPG3|p9^ug3V^tP?Ll z*aBi!&QmTJW)TxW^qeuhwn)#fbmnHM6TPs4@bx+Lu`mnjw;OL)q+|j92LnbBp_lq? z3VvE?(87meITBlpqB9W-($jr@W}?xv9+)5z^K@>3f5+5cqF16ID`WHeHx^0-<- z8)yf;pbtC-Pr(!L40M4`@Eml27l7*G`Tu4e^f~0sNL3p_Gk5?P8F;V)I6;tr1yNo{y$^dH@!4r;WMHhn%f#Gtw;B1ke^5M#0kI$s`1u}l+~;5~<+R_$IT{=Y z4mlBeGBPZj`p+F*4ZH2vK_R#RZh!)C9;5&p;-<~wdu5bl6}HN$od)VE(#ktjw`nB; zc|~o_T;S@K2XeqEV0#Ye1spu&eij5?10D&$!qRHb8ITSxflQDFE&|Cd5~Rx@17w3_ zkPohcEN}%BfjgiC+yu8k6{rN|pcGVqYH%BrfxDm<+ylknKB%MS$il?Dft`aB!^O?Z T$B$-Zs|Wvq8qfeh6F~hR_BQCu diff --git a/dependencies.lock b/dependencies.lock index 9d3cef8..9b88a30 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -42,7 +42,7 @@ dependencies: version: 1.1.4 espressif/esp_hosted: component_hash: - b6422e810fe97acd87ac184f7da1653e69e885fd209e13c5b1ae20c5787d914d + 49424510d8cf3659aa4bcf787e7b4abbf11848a25e7e5f133cf7f3324860d066 dependencies: - name: idf require: private @@ -50,7 +50,7 @@ dependencies: source: registry_url: https://components.espressif.com type: service - version: 2.11.1 + version: 2.11.3 espressif/esp_lcd_touch: component_hash: 3f85a7d95af876f1a6ecca8eb90a81614890d0f03a038390804e5a77e2caf862 @@ -377,7 +377,7 @@ dependencies: 17e68bfd21f0edf4c3ee838e2273da840bf3930e5dbc3bfa6c1190c3aed41f9f dependencies: [] source: - registry_url: https://components.espressif.com/ + registry_url: https://components.espressif.com type: service version: 9.4.0 waveshare/esp_lcd_jd9365_10_1: @@ -408,8 +408,7 @@ direct_dependencies: - espressif/esp_tinyusb - espressif/esp_wifi_remote - idf -- lvgl/lvgl - waveshare/esp_lcd_jd9365_10_1 -manifest_hash: 77a45d81439c2b8bff313cb08784154731b4451f54eecd31bcd4c2fc83b0f096 +manifest_hash: 4224a9627ef40f4e86cf66ea3d5037d4b4dbfca46c368078b42e6988300c7f2f target: esp32p4 version: 2.0.0 diff --git a/main/Gui.cpp b/main/Gui.cpp index 57e3afe..c9c86ab 100644 --- a/main/Gui.cpp +++ b/main/Gui.cpp @@ -1,5 +1,6 @@ #include "Gui.hpp" #include "esp_lv_adapter.h" +#include "esp_log.h" #include "Gui/WifiSetting.hpp" #include "Gui/EthSetting.hpp" #include "WidgetManager.hpp" @@ -14,15 +15,27 @@ static void screen_long_press_handler(lv_event_t * e) } } +static void widget_manager_timer_cb(lv_timer_t* timer) +{ + (void)timer; + // Debug: Log every 100th call to verify timer is running + static uint32_t callCount = 0; + if (++callCount % 100 == 0) { + ESP_LOGI("Gui", "Timer tick %lu", callCount); + } + WidgetManager::instance().loop(); +} + void Gui::create() { // Initialize WidgetManager (loads config from SD card) WidgetManager::instance().init(); if (esp_lv_adapter_lock(-1) == ESP_OK) { - // Add long press handler for settings - lv_obj_add_event_cb(lv_scr_act(), screen_long_press_handler, - LV_EVENT_LONG_PRESSED, NULL); + // TEMP: Disabled long press handler for testing + // lv_obj_add_event_cb(lv_scr_act(), screen_long_press_handler, + // LV_EVENT_LONG_PRESSED, NULL); + lv_timer_create(widget_manager_timer_cb, 10, nullptr); esp_lv_adapter_unlock(); } diff --git a/main/Gui/EthSetting.cpp b/main/Gui/EthSetting.cpp index 504cb3c..fd1d650 100644 --- a/main/Gui/EthSetting.cpp +++ b/main/Gui/EthSetting.cpp @@ -20,6 +20,7 @@ void EthSetting::show() { if (esp_lv_adapter_lock(-1) == ESP_OK) { createUI(); visible_ = true; + esp_lv_adapter_unlock(); } } @@ -64,7 +65,7 @@ void EthSetting::createUI() { lv_obj_set_size(closeBtn, 40, 40); lv_obj_align(closeBtn, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_set_style_bg_color(closeBtn, lv_color_hex(0x804040), 0); - lv_obj_add_event_cb(closeBtn, onCloseClick, LV_EVENT_CLICKED, nullptr); + //lv_obj_add_event_cb(closeBtn, onCloseClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* closeLbl = lv_label_create(closeBtn); lv_label_set_text(closeLbl, "X"); diff --git a/main/Gui/WifiSetting.cpp b/main/Gui/WifiSetting.cpp index a5d44e2..9d9c890 100644 --- a/main/Gui/WifiSetting.cpp +++ b/main/Gui/WifiSetting.cpp @@ -86,7 +86,7 @@ void WifiSetting::createUI() { lv_obj_set_size(closeBtn, 40, 40); lv_obj_align(closeBtn, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_set_style_bg_color(closeBtn, lv_color_hex(0x804040), 0); - lv_obj_add_event_cb(closeBtn, onCloseClick, LV_EVENT_CLICKED, nullptr); + //lv_obj_add_event_cb(closeBtn, onCloseClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* closeLbl = lv_label_create(closeBtn); lv_label_set_text(closeLbl, "X"); @@ -111,7 +111,7 @@ void WifiSetting::createUI() { disconnectBtn_ = lv_btn_create(statusSection); lv_obj_set_size(disconnectBtn_, 100, 40); lv_obj_align(disconnectBtn_, LV_ALIGN_RIGHT_MID, 0, 0); - lv_obj_add_event_cb(disconnectBtn_, onDisconnectClick, LV_EVENT_CLICKED, nullptr); + //lv_obj_add_event_cb(disconnectBtn_, onDisconnectClick, LV_EVENT_CLICKED, nullptr); lv_obj_add_flag(disconnectBtn_, LV_OBJ_FLAG_HIDDEN); lv_obj_t* disconnectLbl = lv_label_create(disconnectBtn_); @@ -140,7 +140,7 @@ void WifiSetting::createUI() { lv_obj_t* scanBtn = lv_btn_create(availableHeader); lv_obj_set_size(scanBtn, 100, 35); lv_obj_align(scanBtn, LV_ALIGN_RIGHT_MID, 0, 0); - lv_obj_add_event_cb(scanBtn, onScanClick, LV_EVENT_CLICKED, nullptr); + //lv_obj_add_event_cb(scanBtn, onScanClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* scanLbl = lv_label_create(scanBtn); lv_label_set_text(scanLbl, "Scannen"); @@ -198,7 +198,7 @@ void WifiSetting::refreshNetworkList() { (const char*)ap.ssid, barSymbols[bars - 1], ap.rssi); lv_obj_t* btn = lv_list_add_btn(settings.networkList_, LV_SYMBOL_WIFI, signalStr); - lv_obj_add_event_cb(btn, onNetworkSelect, LV_EVENT_CLICKED, nullptr); + //lv_obj_add_event_cb(btn, onNetworkSelect, LV_EVENT_CLICKED, nullptr); size_t ssidLen = strlen((const char*)ap.ssid); char* ssidCopy = (char*)lv_malloc(ssidLen + 1); @@ -237,7 +237,7 @@ void WifiSetting::refreshSavedNetworks() { lv_obj_set_size(deleteBtn, 80, 30); lv_obj_align(deleteBtn, LV_ALIGN_RIGHT_MID, 0, 0); lv_obj_set_style_bg_color(deleteBtn, lv_color_hex(0x804040), 0); - lv_obj_add_event_cb(deleteBtn, onDeleteSavedClick, LV_EVENT_CLICKED, nullptr); + //lv_obj_add_event_cb(deleteBtn, onDeleteSavedClick, LV_EVENT_CLICKED, nullptr); char* ssidCopy = (char*)lv_malloc(ssid.size() + 1); strcpy(ssidCopy, ssid.c_str()); @@ -312,7 +312,7 @@ void WifiSetting::createPasswordDialogUI() { lv_obj_set_size(cancelBtn, 150, 50); lv_obj_align(cancelBtn, LV_ALIGN_TOP_LEFT, 20, 150); lv_obj_set_style_bg_color(cancelBtn, lv_color_hex(0x606060), 0); - lv_obj_add_event_cb(cancelBtn, onCancelClick, LV_EVENT_CLICKED, nullptr); + //lv_obj_add_event_cb(cancelBtn, onCancelClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* cancelLbl = lv_label_create(cancelBtn); lv_label_set_text(cancelLbl, "Abbrechen"); @@ -322,7 +322,7 @@ void WifiSetting::createPasswordDialogUI() { lv_obj_set_size(connectBtn, 150, 50); lv_obj_align(connectBtn, LV_ALIGN_TOP_RIGHT, -20, 150); lv_obj_set_style_bg_color(connectBtn, lv_color_hex(0x408040), 0); - lv_obj_add_event_cb(connectBtn, onConnectClick, LV_EVENT_CLICKED, nullptr); + //lv_obj_add_event_cb(connectBtn, onConnectClick, LV_EVENT_CLICKED, nullptr); lv_obj_t* connectLbl = lv_label_create(connectBtn); lv_label_set_text(connectLbl, "Verbinden"); @@ -332,7 +332,7 @@ void WifiSetting::createPasswordDialogUI() { lv_obj_set_size(keyboard_, LV_PCT(100), 300); lv_obj_align(keyboard_, LV_ALIGN_BOTTOM_MID, 0, 0); lv_keyboard_set_textarea(keyboard_, passwordInput_); - lv_obj_add_event_cb(keyboard_, onKeyboardReady, LV_EVENT_READY, nullptr); + //lv_obj_add_event_cb(keyboard_, onKeyboardReady, LV_EVENT_READY, nullptr); ESP_LOGI(TAG, "Password dialog created"); } diff --git a/main/Touch.cpp b/main/Touch.cpp index ef5836d..9d86415 100644 --- a/main/Touch.cpp +++ b/main/Touch.cpp @@ -62,6 +62,7 @@ esp_lcd_touch_handle_t Touch::getTouchHandle() const { void Touch::lv_indev_read_cb(lv_indev_t *indev, lv_indev_data_t *data) { + Touch* self = static_cast(lv_indev_get_user_data(indev)); if (!self) { data->state = LV_INDEV_STATE_RELEASED; @@ -76,7 +77,8 @@ void Touch::lv_indev_read_cb(lv_indev_t *indev, lv_indev_data_t *data) data->point.x = x[0]; data->point.y = y[0]; data->state = LV_INDEV_STATE_PRESSED; - WidgetManager::instance().onUserActivity(); + // TEMP: Disabled to test if this causes the freeze + // WidgetManager::instance().onUserActivity(); } else { data->state = LV_INDEV_STATE_RELEASED; } diff --git a/main/WidgetManager.cpp b/main/WidgetManager.cpp index 5610379..4ce50a8 100644 --- a/main/WidgetManager.cpp +++ b/main/WidgetManager.cpp @@ -22,6 +22,10 @@ WidgetManager& WidgetManager::instance() { WidgetManager::WidgetManager() { // widgets_ is default-initialized to nullptr + uiQueue_ = xQueueCreate(UI_EVENT_QUEUE_LEN, sizeof(UiEvent)); + if (!uiQueue_) { + ESP_LOGE(TAG, "Failed to create UI event queue"); + } createDefaultConfig(); activeScreenId_ = config_.startScreenId; lastActivityUs_ = esp_timer_get_time(); @@ -182,6 +186,8 @@ const ScreenConfig* WidgetManager::activeScreen() const { } void WidgetManager::applyScreen(uint8_t screenId) { + ESP_LOGI(TAG, "applyScreen(%d) - start", screenId); + ScreenConfig* screen = config_.findScreen(screenId); if (!screen) { ESP_LOGW(TAG, "Screen %d not found", screenId); @@ -189,17 +195,40 @@ void WidgetManager::applyScreen(uint8_t screenId) { } if (modalContainer_) { + ESP_LOGI(TAG, "Closing modal first"); closeModal(); } - // First destroy C++ widgets (which deletes LVGL objects) - destroyAllWidgets(); - - if (esp_lv_adapter_lock(-1) == ESP_OK) { - lv_obj_t* root = lv_scr_act(); - createAllWidgets(*screen, root); - esp_lv_adapter_unlock(); + ESP_LOGI(TAG, "Acquiring LVGL lock..."); + if (esp_lv_adapter_lock(-1) != ESP_OK) { + ESP_LOGE(TAG, "Failed to acquire LVGL lock!"); + return; } + ESP_LOGI(TAG, "LVGL lock acquired"); + + // Reset all input devices BEFORE destroying widgets to clear any + // pending input state and prevent use-after-free on widget objects + ESP_LOGI(TAG, "Resetting input devices..."); + lv_indev_t* indev = lv_indev_get_next(nullptr); + while (indev) { + lv_indev_reset(indev, nullptr); + indev = lv_indev_get_next(indev); + } + ESP_LOGI(TAG, "Input devices reset"); + + // Now destroy C++ widgets (which deletes LVGL objects) under LVGL lock + ESP_LOGI(TAG, "Destroying widgets..."); + destroyAllWidgets(); + ESP_LOGI(TAG, "Widgets destroyed"); + + ESP_LOGI(TAG, "Creating new widgets for screen '%s' (%d widgets)...", + screen->name, screen->widgetCount); + lv_obj_t* root = lv_scr_act(); + createAllWidgets(*screen, root); + ESP_LOGI(TAG, "Widgets created"); + + esp_lv_adapter_unlock(); + ESP_LOGI(TAG, "applyScreen(%d) - complete", screenId); } void WidgetManager::showModalScreen(const ScreenConfig& screen) { @@ -207,11 +236,18 @@ void WidgetManager::showModalScreen(const ScreenConfig& screen) { closeModal(); } + if (esp_lv_adapter_lock(-1) != ESP_OK) return; + + // Reset all input devices BEFORE destroying widgets + lv_indev_t* indev = lv_indev_get_next(nullptr); + while (indev) { + lv_indev_reset(indev, nullptr); + indev = lv_indev_get_next(indev); + } + // Destroy any existing widgets before creating modal widgets destroyAllWidgets(); - if (esp_lv_adapter_lock(-1) != ESP_OK) return; - lv_disp_t* disp = lv_disp_get_default(); int32_t dispWidth = disp ? lv_disp_get_hor_res(disp) : 1280; int32_t dispHeight = disp ? lv_disp_get_ver_res(disp) : 800; @@ -299,28 +335,40 @@ void WidgetManager::showModalScreen(const ScreenConfig& screen) { void WidgetManager::closeModal() { if (!modalContainer_) return; + if (esp_lv_adapter_lock(-1) != ESP_OK) return; + + // Reset all input devices BEFORE destroying widgets + lv_indev_t* indev = lv_indev_get_next(nullptr); + while (indev) { + lv_indev_reset(indev, nullptr); + indev = lv_indev_get_next(indev); + } + // First destroy C++ widgets (which deletes their LVGL objects) destroyAllWidgets(); - if (esp_lv_adapter_lock(-1) == ESP_OK) { - if (modalDimmer_) { - lv_obj_delete(modalDimmer_); - } - lv_obj_delete(modalContainer_); - esp_lv_adapter_unlock(); + if (modalDimmer_) { + lv_obj_delete(modalDimmer_); } + lv_obj_delete(modalContainer_); + esp_lv_adapter_unlock(); modalContainer_ = nullptr; modalDimmer_ = nullptr; modalScreenId_ = SCREEN_ID_NONE; } void WidgetManager::showScreen(uint8_t screenId) { + ESP_LOGI(TAG, "showScreen(%d) called", screenId); + ScreenConfig* screen = config_.findScreen(screenId); if (!screen) { ESP_LOGW(TAG, "Screen %d not found", screenId); return; } + ESP_LOGI(TAG, "Found screen '%s', mode=%d", screen->name, + static_cast(screen->mode)); + if (screen->mode == ScreenMode::MODAL) { showModalScreen(*screen); return; @@ -335,18 +383,25 @@ void WidgetManager::showScreen(uint8_t screenId) { void WidgetManager::handleButtonAction(const WidgetConfig& cfg, lv_obj_t* target) { if (cfg.type != WidgetType::BUTTON) return; + ESP_LOGI(TAG, "handleButtonAction: button=%d action=%d targetScreen=%d", + cfg.id, static_cast(cfg.action), cfg.targetScreen); + onUserActivity(); switch (cfg.action) { case ButtonAction::JUMP: - navPending_ = true; + ESP_LOGI(TAG, "JUMP action: scheduling navigation to screen %d", cfg.targetScreen); navAction_ = ButtonAction::JUMP; navTargetScreen_ = cfg.targetScreen; + navPending_ = true; + navRequestUs_ = esp_timer_get_time(); break; case ButtonAction::BACK: - navPending_ = true; + ESP_LOGI(TAG, "BACK action: scheduling navigation back"); navAction_ = ButtonAction::BACK; navTargetScreen_ = SCREEN_ID_NONE; + navPending_ = true; + navRequestUs_ = esp_timer_get_time(); break; case ButtonAction::KNX: default: { @@ -393,14 +448,22 @@ void WidgetManager::enterStandby() { } void WidgetManager::loop() { + bool didUiNav = false; if (navPending_) { - navPending_ = false; - if (navAction_ == ButtonAction::JUMP) { - showScreen(navTargetScreen_); - } else if (navAction_ == ButtonAction::BACK) { - goBack(); + int64_t now = esp_timer_get_time(); + // Increased delay to ensure touch events are fully processed + if (now - navRequestUs_ >= NAV_DELAY_US) { + navPending_ = false; + ESP_LOGI(TAG, "Executing navigation: action=%d target=%d", + static_cast(navAction_), navTargetScreen_); + if (navAction_ == ButtonAction::JUMP) { + showScreen(navTargetScreen_); + } else if (navAction_ == ButtonAction::BACK) { + goBack(); + } + didUiNav = true; + ESP_LOGI(TAG, "Navigation complete"); } - return; } if (standbyWakePending_) { @@ -409,9 +472,13 @@ void WidgetManager::loop() { activeScreenId_ = standbyWakeTarget_; applyScreen(activeScreenId_); } - return; + didUiNav = true; } + processUiQueue(); + + if (didUiNav) return; + if (!config_.standbyEnabled || config_.standbyMinutes == 0) return; if (standbyActive_) return; if (config_.standbyScreenId == SCREEN_ID_NONE) return; @@ -464,39 +531,88 @@ void WidgetManager::createAllWidgets(const ScreenConfig& screen, lv_obj_t* paren } void WidgetManager::onKnxValue(uint16_t groupAddr, float value) { - if (esp_lv_adapter_lock(100) != ESP_OK) return; + UiEvent event = {}; + event.type = UiEventType::KNX_VALUE; + event.groupAddr = groupAddr; + event.value = value; + enqueueUiEvent(event); +} +void WidgetManager::onKnxSwitch(uint16_t groupAddr, bool value) { + UiEvent event = {}; + event.type = UiEventType::KNX_SWITCH; + event.groupAddr = groupAddr; + event.state = value; + enqueueUiEvent(event); +} + +void WidgetManager::onKnxText(uint16_t groupAddr, const char* text) { + UiEvent event = {}; + event.type = UiEventType::KNX_TEXT; + event.groupAddr = groupAddr; + if (text) { + strncpy(event.text, text, sizeof(event.text) - 1); + } else { + event.text[0] = '\0'; + } + enqueueUiEvent(event); +} + +bool WidgetManager::enqueueUiEvent(const UiEvent& event) { + if (!uiQueue_) return false; + return xQueueSend(uiQueue_, &event, 0) == pdTRUE; +} + +void WidgetManager::processUiQueue() { + if (!uiQueue_) return; + if (uxQueueMessagesWaiting(uiQueue_) == 0) return; + + if (esp_lv_adapter_lock(-1) != ESP_OK) return; + + UiEvent event = {}; + static constexpr size_t kMaxEventsPerLoop = 8; + size_t processed = 0; + while (processed < kMaxEventsPerLoop && + xQueueReceive(uiQueue_, &event, 0) == pdTRUE) { + switch (event.type) { + case UiEventType::KNX_VALUE: + applyKnxValue(event.groupAddr, event.value); + break; + case UiEventType::KNX_SWITCH: + applyKnxSwitch(event.groupAddr, event.state); + break; + case UiEventType::KNX_TEXT: + applyKnxText(event.groupAddr, event.text); + break; + } + processed++; + } + + esp_lv_adapter_unlock(); +} + +void WidgetManager::applyKnxValue(uint16_t groupAddr, float value) { for (auto& widget : widgets_) { if (widget && widget->getKnxAddress() == groupAddr) { widget->onKnxValue(value); } } - - esp_lv_adapter_unlock(); } -void WidgetManager::onKnxSwitch(uint16_t groupAddr, bool value) { - if (esp_lv_adapter_lock(100) != ESP_OK) return; - +void WidgetManager::applyKnxSwitch(uint16_t groupAddr, bool value) { for (auto& widget : widgets_) { if (widget && widget->getKnxAddress() == groupAddr) { widget->onKnxSwitch(value); } } - - esp_lv_adapter_unlock(); } -void WidgetManager::onKnxText(uint16_t groupAddr, const char* text) { - if (esp_lv_adapter_lock(100) != ESP_OK) return; - +void WidgetManager::applyKnxText(uint16_t groupAddr, const char* text) { for (auto& widget : widgets_) { if (widget && widget->getKnxAddress() == groupAddr) { widget->onKnxText(text); } } - - esp_lv_adapter_unlock(); } // Helper function to parse hex color string diff --git a/main/WidgetManager.hpp b/main/WidgetManager.hpp index 278117b..c30f8e7 100644 --- a/main/WidgetManager.hpp +++ b/main/WidgetManager.hpp @@ -3,6 +3,8 @@ #include "WidgetConfig.hpp" #include "widgets/Widget.hpp" #include "lvgl.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" #include #include @@ -35,7 +37,7 @@ public: // User activity (resets standby timer) void onUserActivity(); - // KNX value update (called from KnxWorker) + // Thread-safe KNX updates (queued to UI thread) void onKnxValue(uint16_t groupAddr, float value); void onKnxSwitch(uint16_t groupAddr, bool value); void onKnxText(uint16_t groupAddr, const char* text); @@ -54,10 +56,32 @@ private: WidgetManager(const WidgetManager&) = delete; WidgetManager& operator=(const WidgetManager&) = delete; + static constexpr size_t UI_EVENT_QUEUE_LEN = 16; + static constexpr size_t UI_EVENT_TEXT_LEN = MAX_TEXT_LEN; + + enum class UiEventType : uint8_t { + KNX_VALUE = 0, + KNX_SWITCH = 1, + KNX_TEXT = 2, + }; + + struct UiEvent { + UiEventType type; + uint16_t groupAddr; + float value; + bool state; + char text[UI_EVENT_TEXT_LEN]; + }; + void loadFromSdCard(); void saveToSdCard(); void destroyAllWidgets(); void createAllWidgets(const ScreenConfig& screen, lv_obj_t* parent); + bool enqueueUiEvent(const UiEvent& event); + void processUiQueue(); + void applyKnxValue(uint16_t groupAddr, float value); + void applyKnxSwitch(uint16_t groupAddr, bool value); + void applyKnxText(uint16_t groupAddr, const char* text); void createDefaultConfig(); void applyScreen(uint8_t screenId); @@ -69,6 +93,7 @@ private: const ScreenConfig* activeScreen() const; static constexpr const char* CONFIG_FILE = "/sdcard/lvgl.json"; + static constexpr int64_t NAV_DELAY_US = 200 * 1000; // 200ms delay for touch release GuiConfig config_; uint8_t activeScreenId_ = 0; @@ -81,6 +106,7 @@ private: bool navPending_ = false; ButtonAction navAction_ = ButtonAction::KNX; uint8_t navTargetScreen_ = 0xFF; + int64_t navRequestUs_ = 0; int64_t lastActivityUs_ = 0; // Runtime widget instances (indexed by widget ID) @@ -88,4 +114,5 @@ private: lv_obj_t* screen_ = nullptr; lv_obj_t* modalContainer_ = nullptr; lv_obj_t* modalDimmer_ = nullptr; + QueueHandle_t uiQueue_ = nullptr; }; diff --git a/main/idf_component.yml b/main/idf_component.yml index ac6a67f..1f26b62 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -15,8 +15,7 @@ dependencies: # # All dependencies of `main` are public by default. # public: true waveshare/esp_lcd_jd9365_10_1: '*' - lvgl/lvgl: ^9.4.0 - espressif/esp_lvgl_port: ^2.3.0 + espressif/esp_lvgl_port: ^2.7.0 espressif/esp_lcd_touch_gt911: '*' espressif/esp_lvgl_adapter: '*' espressif/esp_wifi_remote: '*' diff --git a/main/main.cpp b/main/main.cpp index 3e9a689..b6641c2 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -17,6 +17,14 @@ #define TAG "App" +static void knx_task(void* arg) { + KnxWorker* worker = static_cast(arg); + worker->init(); + while (true) { + worker->loop(); + vTaskDelay(pdMS_TO_TICKS(10)); + } +} // This is a simple wrapper for the application logic class Application { @@ -63,7 +71,11 @@ public: } ESP_LOGI(TAG, "Creating UI"); - knxWorker.init(); + BaseType_t knx_ok = xTaskCreatePinnedToCore( + knx_task, "knx", 4096, &Gui::knxWorker, 5, nullptr, 1); + if (knx_ok != pdPASS) { + ESP_LOGE(TAG, "Failed to start KNX task"); + } gui.create(); // Start WebServer for widget configuration @@ -72,8 +84,6 @@ public: ESP_LOGI(TAG, "Application running"); while (true) { vTaskDelay(pdMS_TO_TICKS(10)); - knxWorker.loop(); - WidgetManager::instance().loop(); } } @@ -82,7 +92,6 @@ private: Touch touch; Gui gui; Nvs nvs; - KnxWorker knxWorker; }; extern "C" void app_main(void) diff --git a/main/widgets/ButtonWidget.cpp b/main/widgets/ButtonWidget.cpp index a1bbdcb..a63ab4a 100644 --- a/main/widgets/ButtonWidget.cpp +++ b/main/widgets/ButtonWidget.cpp @@ -1,5 +1,13 @@ #include "ButtonWidget.hpp" #include "../WidgetManager.hpp" +#include "esp_log.h" + +static const char* TAG = "ButtonWidget"; + +// Free function instead of static member +static void button_event_cb(lv_event_t* e) { + ESP_LOGI(TAG, "button_event_cb called"); +} ButtonWidget::ButtonWidget(const WidgetConfig& config) : Widget(config) @@ -7,32 +15,33 @@ ButtonWidget::ButtonWidget(const WidgetConfig& config) { } +ButtonWidget::~ButtonWidget() { + // Remove event callback BEFORE the base class destructor deletes the object + if (obj_) { + lv_obj_remove_event_cb(obj_, button_event_cb); + } + label_ = nullptr; +} + void ButtonWidget::clickCallback(lv_event_t* e) { - ButtonWidget* widget = static_cast(lv_event_get_user_data(e)); - if (!widget) return; - lv_obj_t* target = static_cast(lv_event_get_target(e)); - WidgetManager::instance().handleButtonAction(widget->getConfig(), target); + // Not used currently + (void)e; } lv_obj_t* ButtonWidget::create(lv_obj_t* parent) { obj_ = lv_btn_create(parent); + lv_obj_set_pos(obj_, config_.x, config_.y); + lv_obj_set_size(obj_, config_.width > 0 ? config_.width : 100, + config_.height > 0 ? config_.height : 50); - if (config_.isToggle) { - lv_obj_add_flag(obj_, LV_OBJ_FLAG_CHECKABLE); - } + // Test: free function callback + lv_obj_add_event_cb(obj_, button_event_cb, LV_EVENT_CLICKED, NULL); - lv_obj_add_event_cb(obj_, clickCallback, LV_EVENT_CLICKED, this); - - // Create label inside button label_ = lv_label_create(obj_); lv_label_set_text(label_, config_.text); lv_obj_center(label_); - lv_obj_set_pos(obj_, config_.x, config_.y); - if (config_.width > 0 && config_.height > 0) { - lv_obj_set_size(obj_, config_.width, config_.height); - } - + ESP_LOGI(TAG, "Created button '%s' at %d,%d", config_.text, config_.x, config_.y); return obj_; } diff --git a/main/widgets/ButtonWidget.hpp b/main/widgets/ButtonWidget.hpp index 638a444..6f8b322 100644 --- a/main/widgets/ButtonWidget.hpp +++ b/main/widgets/ButtonWidget.hpp @@ -5,6 +5,7 @@ class ButtonWidget : public Widget { public: explicit ButtonWidget(const WidgetConfig& config); + ~ButtonWidget() override; lv_obj_t* create(lv_obj_t* parent) override; void applyStyle() override; diff --git a/sdcard_content/webseite/index.html b/sdcard_content/webseite/index.html index fafdc27..cd00114 100644 --- a/sdcard_content/webseite/index.html +++ b/sdcard_content/webseite/index.html @@ -908,6 +908,18 @@ if (!screen.bgColor) screen.bgColor = '#1A1A2E'; if (!Array.isArray(screen.widgets)) screen.widgets = []; + // Modal defaults + if (!screen.modal) { + screen.modal = { x: 0, y: 0, w: 0, h: 0, radius: 12, dim: true }; + } else { + if (screen.modal.x === undefined) screen.modal.x = 0; + if (screen.modal.y === undefined) screen.modal.y = 0; + if (screen.modal.w === undefined) screen.modal.w = 0; + if (screen.modal.h === undefined) screen.modal.h = 0; + if (screen.modal.radius === undefined) screen.modal.radius = 12; + if (screen.modal.dim === undefined) screen.modal.dim = true; + } + screen.widgets.forEach(normalizeWidget); }