From a138748ff31a4ef298d1af03f6098684bb38c3ff Mon Sep 17 00:00:00 2001 From: Boris Krivonog Date: Fri, 27 Nov 2020 02:02:49 +0100 Subject: [PATCH] [nikobus] discovery for push buttons, (#9134) * removed state update if value didn't change so expiry binding can actually - expire. If expire time was larger than refresh interval of the binding, expiration never happened ... Signed-off-by: Boris Krivonog --- bundles/org.openhab.binding.nikobus/README.md | 82 ++++++++++++- .../org.openhab.binding.nikobus/doc/s2.png | Bin 0 -> 12972 bytes .../org.openhab.binding.nikobus/doc/s4.png | Bin 0 -> 15634 bytes .../org.openhab.binding.nikobus/doc/s8.png | Bin 0 -> 21877 bytes .../discovery/NikobusDiscoveryService.java | 114 ++++++++++++++++++ .../handler/NikobusModuleHandler.java | 8 +- .../handler/NikobusPcLinkHandler.java | 29 ++++- .../nikobus/internal/utils/CRCUtil.java | 12 +- .../binding/nikobus/internal/utils/Utils.java | 58 +++++++++ 9 files changed, 283 insertions(+), 20 deletions(-) create mode 100644 bundles/org.openhab.binding.nikobus/doc/s2.png create mode 100644 bundles/org.openhab.binding.nikobus/doc/s4.png create mode 100644 bundles/org.openhab.binding.nikobus/doc/s8.png create mode 100644 bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/discovery/NikobusDiscoveryService.java diff --git a/bundles/org.openhab.binding.nikobus/README.md b/bundles/org.openhab.binding.nikobus/README.md index 48aa0065795..c23fe401f32 100644 --- a/bundles/org.openhab.binding.nikobus/README.md +++ b/bundles/org.openhab.binding.nikobus/README.md @@ -33,10 +33,6 @@ The bridge enables communication with other Nikobus components: * `rollershutter-module` - Nikobus roller shutter module, * `push-button` - Nikobus physical push button. -## Discovery - -The binding does not support any automatic discovery of Things. - ## Bridge Configuration The binding can connect to the PC-Link via serial interface. @@ -174,6 +170,84 @@ Thing push-button pb1 [ address = "28092A", impactedModules = "switch-module:s1: In addition to the status requests triggered by button presses, there is also a scheduled status update interval defined by the `refreshInterval` parameter and explained above. +## Discovery + +Pressing a physical Nikobus push-button will generate a new inbox entry with an exception of buttons already discovered or setup. + +Nikobus push buttons have the following format in inbox: + +``` +Nikobus Push Button 14E7F4:3 +4BF9CA +nikobus:push-button +``` + +where first line contains name of the discovered button and second one contains button's bus address. + +Each discovered button has a Nikobus address appended to its name, same as can be seen in Nikobus's PC application, `14E7F4:3` in above example. + + * `14E7F4` - address of the Nikobus switch, as can be seen in Nikobus PC software and + * `3` - represents a button on Nikobus switch. + +### Button mappings + +##### 2 buttons switch + +![Nikobus Switch with 2 buttons](doc/s2.png) + +``` + 1 = A + 2 = B + ``` + +##### 4 buttons switch + +![Nikobus Switch with 4 buttons](doc/s4.png) + +maps as + +``` + 3 1 + 4 2 +``` + +so + +``` +1 = C +2 = D +3 = A +4 = B +``` + +##### 8 buttons switch + +![Nikobus Switch with 8 buttons](doc/s8.png) + +maps as + +``` + 7 5 3 1 + 8 6 4 2 +``` + +so + +``` +1 = 2C +2 = 2D +3 = 2A +4 = 2B +5 = 1C +6 = 1D +7 = 1A +8 = 1B +``` + +Above example `14E7F4:3` would give: +* for 4 buttons switch - push button A, +* for 8 buttons switch - push button 2A. + ## Full Example ### nikobus.things diff --git a/bundles/org.openhab.binding.nikobus/doc/s2.png b/bundles/org.openhab.binding.nikobus/doc/s2.png new file mode 100644 index 0000000000000000000000000000000000000000..26f003a1698b1ea5e1b41504713e6cd61b5e0468 GIT binary patch literal 12972 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 C&^Lkr literal 0 HcmV?d00001 diff --git a/bundles/org.openhab.binding.nikobus/doc/s4.png b/bundles/org.openhab.binding.nikobus/doc/s4.png new file mode 100644 index 0000000000000000000000000000000000000000..de0044e2618bceaab9e94f5792b0609acd71e694 GIT binary patch literal 15634 zcmch-bx>SQ(+9fC;!bdP_r={U1ee7jz~b)C5(oqf4#5J!-3bmGL4pQ%cPF@WE6@9W zTHn2Y-l;lu=5+UOW?D|oOjk#1sw-iklc56u04x<{d2IjyC<*`owonlO06>&g=o$ck zX=N`br>P<*N2BTCYGdyN1pt(z(;z4YI=_fM8*8iBg`p~=bw$$&z*2FI5P{|I$|4vN zH7(zuviW!!BF%CY7>w)TDL^37Gw(h)ni2%A8fa?G^y)d4b)uo|wburn2CXjLdF~8{ zzP35Z1xjo5X8bzW3I?DTy+4l_(41*)@*>*D%SRB+2U=MS5VKh4+}@G^p!qKyoo&dt z-l6kqBUfX8Uf3dKlVkyaWT1PxCM^rBl@!n^Pm@B7AdMLwuvq>cEI=gZ#1I9P71xRP zn5RPcsjl03{ zA&QXTjs9jEu9!?9=}$3Q8{6RC%nPCCDwz;TDO+5}^8;d!Px7=wyBaT2suw-QH0B~} zKY)T+22^SJqtr8JiYr@o0wpp_j3Y7eI%nY>RtZ@c1SSSj@Q69n z0i4*#If@Nb`w*u%{k$~J=rtKk2!^Pd_JHcds40tf1ha$4><}~aPpma3k&MDzwu@vDqi1qUJXhF@cfBwxp(PuDq**!n6-GVRPsNzdpLX$BHaZ+Teb{pYX=n$x z$22yvMM+=CLOAG+sgm-WGYDCb&wF3@zA~#Kf)K@|6!2et^Fh0P`jahf!kz4qjN&IB z(`jxGC^wO@Rj4O@_n*$mnEf0Ukg~{#p~sb*swv3V17x?Eyn=wHE;K zX+J0xon@lNe51yVhFQ9q*}asZ639H2%2e;{BR4!K#opU)h4teS!|W1qLfIc|RZzN$ zVM?0xcTv8;I00(Gt2rrein8c&hg47}M;B1lQkXZ6L?MnwbkoKUmkQPow?%cL5+=VP z|8N~EvCjJ?_YCHimQS~o!@!ypia$h>|LzfQA+E7|l*AX7v*O1>g*s2mH~Mn~Mt*|y z^+C4Elz2;hS*_A&PxwiOoaJ>?Iw`inU{0V)%@g!|dwu$G8tzjK;| zE$Zi6qr8LHY)g*IV#`tv{nB6TjJ^bfyE6}!3^9sq$P%H1Ajxxl*5wHz8TzsOgA#Bh zq;QcH(0lZvPcz(T?sc(lhMjtSbw&AH5c>>(kIlGcS9b4FaDSTx22tmkacK_5@{5{0 z(ZE~6sFt)!;IHNom_H?N5BUekTB-QaPw~>Zg?h0E$jFDfH4^%KTrT3A}y^~MA#=f{SOiwF@7{o45(;I zmWhZASij^wa9IoFZRjqNJgku#u;<@R(MZuoC2kIo7E!iEFDZ#8^(5l3L{4bZPa$|q zE9E<-hAS4T>>=`_6&M$0peC+%VQT9NT)2#2?R zY7J}6n0w>IEXi=4sLY^~%+8ufptO;Ku2NjoT(n$dRis*kJt5YBJs)!<^O2@BrFiR= z2a-SW9n0OTJG8cp0*(68Tb&IS*+H*C?LooU_}d7@;S;I?`J&pOa+N8Q191n&=8pl% z0a5p_m6ZAw`!#H)9afX)^aeg_@7npRJFdN_ZLJ2^X z$Td?om#zJhm%m!rGYQ?pp55L@_uk#p-=8@&n+X1*G~PJ7xu-V8K2!NyEZA`_LgUYW;7peQU8rAoDW$8OC=IJay?S^2U4UlmIjHWwFRaz zat5u%u&t9-j;LW!^P+lZcO;O5gOiTan#hq;-N4Hb%qhp= z$q6x}YCdYRG(a*`snR#3Yz*iF+qfItRlU|{uUuSM5*;+M@9J$IX`k&IXPPhhX;V95 zYFxp&D7fg8<{azXlAE?n(vj)Y?9+0@dhHZg|3vnnbL~n=L8(pI?Q7@ecVM?M;K|`r z<=wd{?~Cq}wV`|L)tk9D>@(`QvKBOs52s|Y^)sXC#^vDyitFaJV2!`Mc`yyKmFqaAck2B4`)oKD*_JwB;=45Pv!Oa{fE~i)-8SlHt-04+jUh zild5iiAP){$n>@gHTy%(hlLL(%BKUQNh4YjWqW1YTC@H{;=tO-S&0ST%c}9}@ut0> zd*0(XmL`^4ylPgzc?+}Srz`o#J)qFZ6cuAu%m zD%Hvudv59~>nSl3p&nsZb{6;w&L3_+VZU42@y4A0NyT0MPXgZ=={r(RzG~aiZ2wRq z+nMzFfupK{K-rjSV4$j(YPIvz5%%k~-^p_4Zia@gDIN;F1RS>g5Hfqf`xk zZHEz|QL}H?-Mzx$stc}5YZI@v)iP78+IF_2Q@T@kJ)?(eaI>6uul~kNL3Kh)v6I*p z{X>7&vCZO8OXvda@|T6oy2j?dmJ*wcyPD!=yXuCop1yr2v4P*O`Dfauo#%&^jJt7; zbWQ@Vb#^pnua!<+Mc|T}H;qqYhd5yD^lAF5$-@rvpI8-rO?}sLg*eUpNc@zK&|7XX zY-8#gQOh9feXWCWB&COsgw%)j=>oo#VL9!sKGl0Ud3-QS zOE?&Ks(aX_W{_-s(mXr6qwg(Dpv0h>q=tys2WVeRZSJp+ei)4%>ytY4;|g3^)Vq)R zMtx{5+;w|5mMAsmn{asI#~M0+GrIvPsrBi+4p^SRU-djy`92Z!8%e|8dFLwciSxwP?;4o@ z5sneG_=4dX5$%)6i>C_!0MelbDmH3r05$*sfC@kYz5;*%000mG1OR|!0HlBV0KjV? z`G5Acfh_-)K>z@v>;Z`XmN5eSt0n&X`(JNRawGr+006uK000sB2>&4s6wL?yM<1~D z7bv46r=kJ?0CcQ8pimc2J6Er&0U`ka0D$JEZ0HF95HbFJfGXMyX8-_#r@gL$mx0K&cGB+K~KO$a^ z5_AS?nly5*9#9$qE`BZ^I!SaI8X9pAYa3B*dBuOjJ*;gc=??nIE{@VkEuz&RWR}=p` zn5dp7)I-kI*%|8MCHY?#7yoCb|H1sPb^Z&eY3~PhGLW}-hPrs#yShm7@$&y0^}jj) zC(`i0kYKRze@Ff|&VNJxRY6q4!yfA5_4cm~C3(gFQR{!u{(j3i@ld5 z_}`HKMgBKRocpg^{+pZrVf>4#Ew3nvF3$a*0VRpgy?C$QxbINfj=GNy8?NwqN?kmddiIPxRLusi?1tnWhae;;C&!fQAg2ODE%IBX z2(*XFFj+u9Vcj+NVw%X0k-%WnryVVOnY1vPFZo{k6Y3uB_m}n&OLcESZf9%X;LCy6 zfJQK1*k>Q-g(exIMw<}?{Yw3j;-f4<$H=p6K^HI9bYwvsQ1HXG!rKzH>>cf-nQG&x zvs_VcgwMk6--}!CFenHp;yzp*PJ`4x@c`$_wCF9`Jhow@ty^1L;^E~!BPm2zy2!%= zFoh0Lu7&wVTfDWy+8$)}&*G%F{nViV)eKfpm3A>Y4+jS(34uJCS$7cW9+&T*4F!g@ zI#+5QMnt+e!XOJ$@xKhMjO$3t$kU4@gT(1GI$$BSQj} z5~zSNqbkbEZs2Y0;@7lW>p!Bx_DM4&OL<*E;A;9ax_;@U*|O6APvcNfIvtm&jw**B&do0kig*C_@&9ft7(W9yjV2@ z0TeSyzS62?wf6gqT-a>?G?IRe38_JWJeq}%kKk`pm#4@p<%(JSE*J_96=M3fB&_M< z=wV;Vk}Db(mIAtY&>y6_Wy)h%2A3&91s^#mEG&#=qBJiUo#OJ5CSSa~44sfhY%}J< zRj<1z**{ojv#)5|=1m@UTs8jT8#?vKq|U9w(=)t@T`}KdgpcGx*sV~E;P@EF(3@r4 zzBp2l)5ND0dgIbyh_U*V66qNq@{z-=!*pdKTNDl@g5;wc@!BULCD7r|X`oS#SlV71 zzw@(d-oHHmUJTrVs;3!i--cSw*K_w{u5!?xDmMag@CBBpjnG#1_@`P22t7F)J1FFrG}VIl zQ@{bcpz8|7?d7BfX!}773{I}tBaDAdYDkHND_d+-yUgs@!*#+QsHO5NKX*wVn%U~M zd->i|VY7X}ZaiORiu~oMaSTQ-D z+f0x`PG?oUsFeI&nOZ3d&3EI4i(XHa>y+u$nsvdz{k)z#ZwA2Bl?#NrWje@@*^h9^g^8 z^!)lDDuL@We0T1Il= zX?H6zU<6C&G%i@dAm&0GjNvjS%PDVn=D5;AP6bl)SnPKUnpEyh+X$_E(!o6)Q`_D; zeo0od`jjRkCaA5W6L$VY_Yh;v=;?+U-)GDbwC9WE?*1MtiF9&u;*V6g@7w^JrD3h3 zHJInq47qWRh(NWt`AmJh|MuBJv!mA9Nat*|;baNqb>3mm2oBq9N8cX6pUre{Zsm^!k$4W%7lyS7~s zS@@xuEjp=luD?mk!LiyK&y`g1QBCJEM}8a&wEi#1;+ZMQ5H>Cj&tQG zV3eD>&eeTUiFI1Abf5I)x}!ihkm{EFtzQ^3f@LqmDaO!79r!4GEF>EGaU&+yLKRg* z@(&`HIobWIIuE@C1#9&uX(Z2BD{LX>0@oDx)8Fdj{+_!C@qx)hbyz8Td#}%Ma7s@< z#=Ti6P5XHr|B+fEK<`#~B|*Yrisjb#Kt7$qx(F^_d1@q5}QM+C8bw$ZP z@@y~n#~1*&q^IT}itzFRZ&4O03_AUIw?@PtB`1}uHg!$U&>cae%h08aG)OGwS* zgVc>t&&x^R)JCT50}zKw*rGZq?*6OGB$?#X0~R2rt9U>gFL9DB_M!Z+<%y6b*w)9B{V75*W4%B8#m8ML$%-Q4{QDxc2d3l!A6FVpadU1?O(xaHr@ zY=YDL2+Gebx;b8s5^HJcqV(HaqjhAdPkG#D&Vw^cN`8LCm^9$!V+~MrqEzXHs-Mq? zjBPZ?q1?;5?;M`?Q-{b8{L&e4D6NW!vhXf2g%Y=r3cpbiNoZL1;tTftH5=BIQmNZv zL|uSB2%9GzC^oI#ov-ljN%SEkueRat#u>7;+l#DI82EGAX~j9JL_NOJ8+z7hPLhB+ zP(4LpG}h#?{n`RRKEOh%^{OH6M+UpO`a598#qi=<=o7~I*J|VHXXkmB%{M4x`CIcdps%M@{0`i4#^lZ`w3$&HG?kHdSsnl(Su*fn#cF>a|bYGw;MnC_us z30}rvC8kMO4>>ZnT8+#Z(dT9is_|qFy3h4^7I&OAR_-`i>uzy?Xns*AJ#+mVF3+ZD zt7&FOgt5y;tnY_228D}ml~qN8?=ekA^Q5Rh!8hUHa59273Hfx3qt46i0$V^(8O~CT zsn}Ym?Gwt}<{v6}b(K}<<2uTK$9c>!qmhl}`l0W~tAjhwBI6a_pzNg=IOr@B?2le& zBruV=F;n|M`F*o10Qg=nGXaZ5{l_49;T66P{&@_v>A74Uab6--qBv~$Vjziro&K=k z>!XZVyJvjU=EBlPG(KOvX0JgQmtxsb~{jRdO8=7tw|$ePV{bbRdlqe?By6wJJFiiy4pCZZ|)({R}QmOiV; zd93iHz%i>xw{3%NwB+Dq1#(=>yxEpCqHoz>Xd zwVU)Lz0Vn}4NW=3)T>+Gu$1`-tjmqlv4Z^h@)rbL%_wedY|RTg<_i>6sWuc!%IgWhk1*7`pvY>WP^B8wxgM9Z@@Co+DSruK!D^orNO| z0iAgA*G5G3(9UVTPN~MazHTqeBB114>)4^9|I2$VWD4HINnJ7Y;u{Ju4QCS~-a{mI zc!wKbWMIX1pjImbhUJPLv*du$a!J|jFFEHM5 z^gJ^Qt)SdT;G5iUIu_6n`kizKp94?66+;zgd%?G^ zXXk`vdGkrWl`&9h!>8;XeJELd1pD+hVg7^_}RQCrjbH8!DWT>*&Z_lwWpV&iaDpkp6YEcH2Yx%5z-`}=*SQ|FHG+I{| z=;FGc9(0Z=k-MW&S=~YqIAOciMfqD8;-*bZBYFg zbl!D6-yh<7>#z6%#B`DbgnsphfS3~xLQJZqB2gNM4-%T>ka>0PYPvhT%)NU6v^ZmneVgq=xz z{~3%1pEn-{J~#PrYVubY7{$cKhmUpLObEMG>Q}?k&C=-{w^~m|viRjPg&N~u zVjth1pAXf-nQ7lr^TY>RhidaLI=F;v#-D|jm`mj=6cW*4>vc?6>6K#MB7shR*E|lI zD;Jy6v+MsBHalKu4*P?3o7$8U&mJQ4!5G87EbxuBRO5}Zyt~SY8n~ZPEE+2&7b)E=k5&G+|F0pS`Fxo7=6xImE6d8!@A!P!v{=BM@*_eJ$el_F@Q?(10CYnKbGl`pN z$2ms#Q|+;`|3MQ@Sa=>aV$kLI3H*aL9^BY?BBa+w&AzW{5_ALVKSN`5Ui|vrM0h4c zQ(=k~v;viGuJpZ|SxOB<;8~0D*@gr@cis)S48+QXT^&q=m>5n_K2i!{f9hj)8w{Y# zL`ivyG41gFvHaE*6NJ4rIUjRrP=Achb3C$XW4#J~8q^pJl_&O%t~3MA%fAUF;~MK3@+-5y^P@w5v*T0UL`F{@=EHW@f@4`xLO zgy(Rx?JfyRSxxqy?1N_J>bv`RMz&O=e+d102^=R3l^FkWI{51*DsIe z@jce9w42!_^t}gR=6{ueRvSph9PM>plQlb6>Q^J2EOe0zTi&{@{fx#BvjpaQ&4Uwr z)sMb`nl2{&u+h0<3#^XYvq@79xDDG0WIZNCEbdquLh?tsKvgElk16^?oQCa)a~JLt z1s>OT5YK&%C9|%8q#irS{`PBEqVDHY-H!Vgz9}*SQe>0y8f0xQ^9`n0nNd9aJRN2Y z+EfEuDIeH92^JYYU@$~o4ne_4-0K$i;AIP613^KR!?1zmT#D*JDQTy-ZIIij2^9!+ zowWNrmf=S!<`Z%DP1netnVFCfhr?;1tZrKAb4~$RlZAAk)CUW_RDh%}9?=kDYkDhCE~y2Eg$S`S7m(<+LZI_@!kf0OMB5Y~H1QQTIbYU4`ksd!-KY z<2&GNbER{$Zs>xC<>lMs`zPPkAE(DHtH?1Si8Q37q`0Eq2Z%X5>k<~(GtRI-SDRr6 z9=z}#enY;;zB(bd$~W^3@FS;ot<(F%Fpql~X_^$Xy^zcb(?1`kSwYX=U}8;`p;J@+ z#RR$jTfdWXJlqzkUlAbW`J0b`N=)B?23JaQEZDYf@&n=z&OTkQ^RLad^dmHKs}q9N%%yZH<*QtmF=3z5T2(#(~CAuIm@ z(xBuZ8>SJdz|~*&hYdsh4{aS;h5wZo(mXx@UqSsD)vWiGe~M=WVUrlPd#STs2b7A? zqBHdNPdb#M6S5;@^9vmLvuReWeB`k0o3$029?IY>Bva5k^Pv^)nVZXzu$E+nsb*IA zct>+#Rbk#Hhrx=97`DtyFbz37KO1*=_dFuE>9U$pZVWYK3b@X{rDuU&!VR_s*j$}# za;fyX6|+`)oU7h%os6`Tc;47_3ySASg;IqGEz1fj`ZzH!a-8cgAf{F;eO);y#AE^O zSV=$B)JWl<9%?Uw?{&%Nh?w&vyQ|;3dX5o8`*7X`G3F5}a%I`H zHZnQ}=()83Pb3wX_SAuT&YHPgCF zMt#&}{M|M0Tr;u-$!RsDM^bh)=Z@EnGOr?lI;=9Vf=>nojKs>B zM{ww`&(;`Xv~4@L0Jn4eI_~HqM4|BIzd8vOW_<>)@ghH}b%60wUL;6gQpU!)zJ+3w z0K|hnsVg=MXEW{H)^E1z2?=78P^lO8H(NS@bhv+$oIXE2gl+7M=3=ZrMW?{{Y=aQv z$_YVl)YXwc=ACiXIcE#P4I6EM)2yHsYxqv-@yM_MH&mL`?LF{iyk@EHvCEg*K`8Lr zX-$<|yB5qC$SK;gBD>lqD+(3E! z5cpLsI}xkM$G5rhek}6>X^YQR9mF^HoPTM=$yYPu#>N8rpB9u_NUQ7$xMF);{nc1_ zs!>2yB3%DOuJ;9jtFgfjI&nvEFh9t~D3Zst|0r_%q3e2T3L`PLvAa3PF!Io{cjmbX zS=ePs*g{vAfQK(v`{8;~0WKj<9eDPec3@&Nm;ZghcwuA$qM}~Wng8&8a;+#7j`i2P zpy;d!@ERrZl`##L_QndhE`tueU%Eh&H08+qzg z!C{U)CKP^&d26_;r+-X@Gk6zSt5b@t%;nrv=-OfPiTcOm-Njkx)!;OI@AWubY;pOQ zFRHc1*e4++xsM-9Iuw~JvwoIdgy+)oyG)T76dUPT@uZ~z6TpcV9XED@S*_rFOoAL> z&r!!tg%7|SZDG7J{p>o6$%+GQb51dWSE--YlTepCHLR2Lcemq8XIU+HZ5H#^cy&76 zY4<8yD|VrTUUD?TT~aBqt*i%}$c=myOtZtz8()O^kE_ff8V!~9>>wAYv^k_@qCA@Q zuLJ*orNUo)xBQZGJ0}HCeA94ORtv41Y;xxnQhn8ejvcGsr}k!h^X{CC1YyA2>j#jO z6${xwgRosv&Eo^n{wmdNhB?pO0U!4#Kheb+`RG@v>0Lex`pi0eOQU8cRxBLs3W<3^ zj7iqoyR8RIoJ~Zkq%2u~qw20Lw95jx;T5tc<2dZQTCC%bj6?NCasoiM=y$DhD+UxY z57=g0%Mx&eS$4E~Wr7oX+c!SE{XrWQ5ec}k+ZV}wZ_fR5gloAS@Nj*MkpqUJ|E|$5 z4YctviQQ`SDlnf_>HubNnxYfLrg!+BmNbyf7ap>I+?=T}C7%U45%9eqb3nzxiP8v< z^oo4KcnJW`-Cr+;`MW81r`zgQ`e6PX7*JkIm--5@a_9wUB6)>{>F%8q z7QleO$7pD+kNVb6L}5Jja2C)YZ0xTg&*@Ro!8z9b^&o_rC$tjr8+!ekDn|S znz%_l7PR{Z_SEV~D*;2C@CVTql%`TrZSC?N=G-dy1|%bb?mnT>j-0EmZvD+XKK`EA z_VdF&Vq|~2FUrZ&gX>!0X%EWLa;ebW(LAWBpLV%@5v|H;+CwA@yUVggV33S)g zG0Y*V`c=bx0|6NtO4WyQ4_g)W4-x%gcR6guKbLNY4a86{cN-exy_=9}`?*CJL(5l0hUM zR|nH!$EWQ>mBoK{ha0#}m+w06N{GrdGr`buBacb6_ncii<6+xFNs7UHU!qu$ghWIR z&sw~DXuAsgKN9ljP1hhXXcn@AR;;9(D{opA)jhHvf^Wv>TrJ!k*nKZZb{e*aXf$@H zM$3fkmke?%F|DmNSFg0M86os^oltSv9RA^)XKKt(cK$Vl7U70}b2UH_sy&PLZ z&#QEi+zs(aY6_Fzvue$iX>Nq6z(zjJ-?Pg{SA2$dTqep2(S7lS^-Au<+V+xP9j+YU z3aeZQ6+VPE6jrc3Ub%cMa-p>Y@!E~ARh*u}OimvHIFr({s$NkGT9U{{y?+m6hg4uz z86@p!<@w)}T9i-l8)vI_ObDp04Za{0ILsovDjQD&p8m~9sG6W$9Aw^K*`KPnc{E|j z_c6%*D0`V~fU2$yyrqX7Q1EG{+sgNMtC_RVN8(%2E=9$~R)g-Ms6+Di3Wk>oCs-s} zlkphCC`Es_{)ku02Kt^Xp*j7A_1$p>OqcY>8oPK^m@X@qFco9^r30sHK5x%v1#GiT zjgbl@D+cT6l%udO=qVCF)$9#~uRa`|D18Y$h#AQf!r>Sovs&k2h`8qIolQVdlvl)6 zI+^y!F?v%?!tf|xZ6@vh2a8oHmdV%kV>(66bLqmBgW{zTDGw*8!c^kLu63Ev7+)<* z&^wNo_%UW*1Y07bq40jIy>vl2TNrT(~D zdIDNgPA!Sn@d5jefH@QnMZWa*&IHHjW8TI9gH3~bJ9jEETZduYHC#F+c&R{h-u&9i z+E24VX}}E9-?P)uLH>8(HFo4n?<>NKtXl9I7{w7mV6FI0C)?L$WX?CH9Y+@sA z4#{AhL>+|HlKh^Xh73D)55k5p_p;t*unyTq06sGB2}jd)GR^Svrgw~%eUcsg!l&mO zBZu|R?qMU{TvCN?i>$B!*Iy>_g*I! zT(0tjtaSLgP6h1@XU^PX1b(G3YnLzGJesQq8ALf_3%zxOH%dMcNM3FJ`rg>%Xf$1O zi95{-3iuwV0OEWF+vH$;y#2F@SEXXrkTZ91t^cu*;A=;fsnp#T{*>eO z(frIp+u##i$J<*@z1@&gQ_ z2~^w4MS~8a%n|{ySY%JB=Uc1%97!&T&|OwSi6D{e3BzU&Mz`J=Lb%vz=j5II8U&XyW|aWoahoPQ8V=H<;iN4#b{ zQmxY;@n~8Q=sATiQ7 zTJpkYi6Te>wHP*s?n0VMvfiY&4*lOON5-$+F;a;OTJpd;rH>T9l+bNr3xXky5_p^m zV2i&I;Zt7k`$M1E+S+Cg!$kU}(RPgP{S<~5RaNhwoT5GF#bgsS>+2Wo=e2wbN10gS zF~dQI!f)x%Jp%IIB8EAPyq(6N<|Vw=7h=;jJE4k3vQYTrCayCNljv=T8LK_D^P5)ds zzRODkY@=QiEauP&S6tqO$B=ssRVjgOCi@LR0rtR8<^x-ZrHSgnKN;f8uu zz`gl@W#Z!xill05RkPHZ4)3pehb8##EXqqdS zHF6N2NBvc_g_gZiP@f~fh(itq?(_$l4^Q7f3OzS4dVH9EtTS_-q()*lu5*sqT zdTvFUydprAOUU%slXl! z>1Ibs>Xf}MWGph8=b38bu)L8hq@cABhw9T~H*U9s9w`8}-$@?4(RLINAIxU5v;S_+ z;RJ)b)1s^6^fWlJ*G$WXsd_Z2&D;?nMOdL%I6tb?E`dOBENZo*l<4XdLeIm-hJGu# zSk?Y11n=B;H5jGyr{^dxMeAIv@Y2&wDl0rvh`%ZF@e`+R)lRqLqS)RLW4Da>*=}>w z#jng#E44x9cMg!e-!++Rpu4xy&6S5$?&g0YBZX*o2B{$k)Q5ja+C6Sj?Jm!FgD(^JW$wp8XK^~`w-ov)s5C|s!R(WDxnd4`yOMUBC^#m zZyYjgzG&a~aJfGTU$e*(s2-A-{#v~#>*59qzWQMN_+*LtgmQ_(#K2$>6iaA)IU#nt@w*PG=d*BuH}f9bGzp=*l=;O{J3R|}4veuM z4ElYJWv_yp#P$=MzLGp1u-8hjw762cS-b$HMecU~d`^(_IZ~$(3j;Lvq)fy))8Pt1b@ep4BPL zY6y}-dm?M*i)FUchtX#6kGY~iu``o`s?DTvWxwyxqDixPxhQO4OQVh1sNh3fK(nQn z!V={Z)BXWh)q5HOD&|$xDq*vLedyHTvTr|Vl6&HHNhbBULH%4+Kx%(t;MEaQ9-CeT zAY9fX1g>Ihcj9IKeHET@OOd-hlrAIKu3v4m?y(R>om?u@LjJ?gyxT9SuPb+cwQ^zl zK|{$?7y0~`wEAWQVuN4Mn`^gp4lQt=3eh*aD(aIp|IP%PM8VcO8>8reuxja`UzNE; z4ZUl^lGJK_VX+q~BD?-+PL_1>1}?i7rg4Ef@;C_;ysvyudtO5Ff1YphzMZ1g=%?uZ zLsl(aq2EmAHf2XfDj9H#>c-5+=XA?6AXQ_8R`u%vQvAZ|InI2?L03=4N{@<)OiZL6 z=olzI1G*h#uSKx3bU=tNob=ikV|J_n^X-WZ)$1G|e4_5E#QgLD80&+DhNbXDTZbEP zb5Sw%dYm7pWE2V6K&r`Z96_r@EgLyU(n{2AGcsOUL?U=7oih=MR@jYRDOr&)7gvWp zQr3)#B_bfLk`Z^X=SRrX=WkGq6<2=m1Kk1h(I<4jkC5vcvu5-LE9Qsz)7F%o`n-U1 z*0rvi-=ci;hgOS@%~iG=X?^Lb%f$o2xf`7?B8wJ`lgSt_DQUwK;qeyijC~!7^QP~? zCFKp^d`!QHzlAW(wH@=_hoj44NonRM#h0iGTug(aUp4Y1Kg^tr`oO&pXMo#FmsjL7 za?jz_8p^R;)%NiR)9b5swAC(z7_Yhlb@*Uq>aK+>($%X9WV*b|dv6Ob! z+}UGo;TWtAidS43Z7+FcX4DK-zBi`;6VPT0+M`$LzVE?54$eNSa@F=OhV5$++_YziP7V^(Z>K-Avfc9G!7CUe8OFr(e`Q6c7KV(_ATGGi6T7LkR+^ zsHm_^%{VW@TAH2E;u1Mz|+-_1e)m(*LdQ5p5m;>PXww+qaJp(`dw>Q|LavFw% zK8pk+TU(oNj1?hF(m9g8Zq!qXO?zYYJ;${x;3_d8=Ygwo@X$0g__K(ZhV^t ziB$HHEo=FEzKj444b%l0OFbMlvZUKV>XRnhua0#!_k-DYxWW&6P=5X=y+mzQ4s>V!2saG2gLCqysT-PL?rpBmxEN zM90t%Sa{1cOEC#jf%-|&(b3AKfj1}8^{*w|H{=Hz(2bhe|8j4IKy6Kxx(ez?=@+UC ztJ74U`AWtB`n4+Tu0eI*`=*@`_!#exZU2MfNO+raUc1t7N23$9G|?nomFWpUW2 z;5;VwLDh_Lj<}o`%?=-D$CwJ!YTdGY%v*Mlza6AJ#z14%c6%ko!& z-}ZG6E8BVO zgyxTIOf2GNAr9XMe3!ik=r}n?e#M1=LjCHo{W?E~DEsF%OTnC|mqq@v zhN|r=UtGm*>Ef4PwaWEMRQ`zT(Ak8|t!S%fCMy5PtA0YmJ3tA;n z=4QH!GS?%H+bUm;t8(+v?5@gRG*%93^t{R|*$m>{YJ+U1`736tWN?`-p66e*4V1;F z>R0j4Y@1g7xT8!8@%YwX(0qFEh(De<2umQXyEF|pK_4+A)kMzuo2$WRu*ZeMDKHX^Llxx2(U1v{0RRA+q=cvv006}U007nzp#cB@g}*i(0Dx*_ zCL*FBDI!9qU~gk$W(foUBtjF_5j2#Ca6#HilE3^AC6L-fDL8x+FtuQzO8kp|Q^hD4 z${^A@J8Hr$Fy?AZsbYz#s|(Hhhgj%hdu(VZD9-n(S{AnT`772kn;nteh(_lH`O`f9${re^JGIA84P~fDPy^goN&;Cqa78Ssf}w=@lp`J3 zT~i56%`O_e)AL~&dm{lcW}Y2<2!J)UVpAL>d$Q;=%8<1J;ZSSD zIMXyp60^ri=P!P&@BZQ_{Ju&(78a?zK(OudA*b*RkgZb9N~>uUorZ#~qaoP!dr@}~ zBRpu4XdBVY+cH8eE0G~|^E;|K3XiPPp!D>(?iZ!sH0In3BQ!LLubnpj0#V{s?R9{S}F3qD;TvkG?pVh;;mL zN@fzCADctqO;4#!5}RG0jPnKls!yu#gI+nVI&N5eF8gh_Gt$HBWx9|KQ=EMqf~#nl z9Sck|qS()^wAE_PSa!{HCTDpyytM4h6^4=Mh2$^uYXAo^K1j2DfO-%@xA#SCGUI?@ zQ+gK9zeq(4>n6nv^)(uUtyBJji_$ar>4Tro*}2f9oVElIu+ z-V=u0h4XK*+9qaGtY%PsjrI9Bf|u?8g0&n`+cA#k;+wJV`h^5>iJWb`cg&aY z4DQwT!r*X;(7buMX|B2UO%@b@@2TogLEM+=uN0&p{6%hKeAa2|mc&?5{RZ;%%W#aK zoYuv5SNnan@|ga&*G*&6qVNg88JRaKvm4zA%{P#^hoJg;5sQOFMo z?Ia|gZJ7}8BTw=WmK`C}A2$zWlKL05R^-_a$kfgu_YG~Sa8@2aUY8^DXOqb0pOz8f zeLs&hI6n`V7y&il)FS78%3fr3M3hu9p76`{;(tSN39$HvEZ-0JfbGfIfu|pQ-V3=@ zdtvn^J?|I%cnIs@PuHE*MHxZ4i&^+V3JK@;>F7^?m-s>OiOcQ^C-cTNY3gU^O;lE zN4dwj2R})Pix2!5kT)%l5;XPhGeSLS48Z{&5(01wd@_KuL94i43h<{^61UOD1ZwF^6kva@vaWs|(wF5fGq zvvSX~C*}?y6Z4hRg84qWoddoK9;SsSM(GrOk*&d-BQG~CKPs*ak!cqtmKQL;_ z2s|^@GxEkWWcke|%5FRr(?Xsc)W(5t{=txf^()(wh5g)az}FG>RrU$TX0w1JUAEQH zKFjhYmD)%Xnz5E30yH!{T0AXI$M;F?{o>|uH~&Y}>x%t@F%Nor1_}maTnh#{4M$B@ z1`&D(26au6`ja|C4LD87ay3ojTK9fd6FZH^aw#>svX$jko?$Js_P&;}mWBSQ&r5~9 zCY58l+NBIDoGZ?WR^e8SnTcz7t*OrS&W$Hu?<_s4UkRR-?`(*Ph?R&tTz=WQ9{<`N zbf9-GcWT=abwPGc+g3Ss>`Ofybsl$E-}IbZ}A~1wEq0 zqnD95uSM?n+tJyVIkgIAaPyhC4qXIoG5uJKlpwA4>@C5{T5DgsUTbXLATj%9e=`^t zD@*x)WqXO~s^X?|neXw#b^Oxu#`9?JnEGn@(5WYVi@*Qb;~e)~UZ6w3K8q(yPM>!} zX5+SFVd=+->z(19nV`RZ@di<6kN5ej*9*$){qsBiCT`59D!R?1F9V9XiYq_(QR|R) z5v-9^;Hv#u12_>%{3`+;yXU$wge^sWldp(?Y%{oHL);xuN0RB<%Kth=jC+#*&{UbV{l_KO)jO&UDf=)2J#~ zG7~^?9sKR4o(~UmJG`uIY*K7sS=$U|t3RosCLgb9NK*5;LIsb6K9jR?IH>Q7dlPl0 zZN&GDXl2bYY$DGif>1<$m;KJn6`Dexia+T(!C8`bfOb&ZcMJ>Y!`Ws;Qm>J_V&$TB zQ9fH~Yic8Q^Li|K^gtPeON9&051QsPgBXtt&3tYg(E%2)&SAfQEh};y$=h4O2{H7~ zt)4_AS)ZWGOxXB({s|686{kHtjrF#RJ-}?*?4YPsMxXsv(oXa;n(YGLAD@A(!gM^{ z%?Hk1S;^tg)+DTLxMP zf@Zi#YYEZO`XcL^l># z^4?ND52T%%tc*1JER(P0ET>l0*7r9Snj}Ah3+jJW)HFD_^q+-${JCSFZ=SPS8d=ru zz&KGp^SD#qmtVLOKeyrT5>U9WeVu?{u%ai;QQpo#S_ym6O8e{j??m!2>e=DgiC=&Z zOuXpYq+lLHPvaxS<0&}t=O`Rfh*=Vc3-JW^TNO}gnm0)AjlR#@qhuN;hX#!xKu!CjzD?T}yM)Iqw^#i-Mix z9>#a~K$pGMxy7>6g}BPKCXk)3lZfli(b!8mlMT+=aXbG#`j*_1?rST~{ph*s``OF0 zUSjm|;A_?M0V$P0)2qV8#Uo{3UNkWZ$qcDFU$wi^_3X~k)_BNx_(Z=T#Ff!weMR*t zxSJHB|E>MuaUw==!X+AV=K9rV>3(5by|B``?aqB|`s0Sfxomg(dL!^$X5-Xz!rSLq z?`jZwme#Yp>Gx1QZ8kJ~fS7!5ffTqC1dtSsv%PDQr?`-J*u!iEvhWU>= zVEr%fyRwL+Bme+VHnIl-tsQ>ZI11aMG6DbqBwGnh2LJ$<`tJoLsYG=F06;sKsc1NA z$ja~-*;q0DG`2AWGP+vX{?h?IR~}a@TPvXBPcm04OKS%nSAL3rEO@LPc>ao+D9HXX zakSv4(2!Li6S1)el5sGyGcr>MAd``i@!1=j@F5ZADH97fH#ZYAD-$a#gT1i{gM*v3<4;!xYX{1IIr$GiqCf{Ddox={GaGBNzkYuj z+BiA#Q&9YE=s(N9`U!M3`>&R)9sV7bk&PA8UkwurBQw+g3Fc^K@_&K-)%*+gPh9^h ze1Dzss5$`cMQp6BfYy!z|25)#|FrbKDgUdV{{kwQxdJUUM9r*#)(&Pi)&guS?Egmn zPtE@ksrg?>R#w*kj{I+$|Azb<0*}1C8PMAC=if0DVBz~Gtp82+Kkb!(4mOrff6Y~` z%^U?-{|)&c;(w#~nEp=7f19R%6#tSciT)5k=41NL1tow?-!h>M00;pjMZc@KLY?Zu zrKqZYDrn^mO0b49!&b|tiTMF_(4(BQnBlYuvR`*!S@zkgolN7 z$ap&2wMo$ZeqY;^!$SwhGswem!^zEbL;0DC-|NXSE+mHAVIT1l*GE3%n;*8%+apbt z%|=I;)k-5wPo*vlJkM;UKB=lqmH;sxF7CdnlWM7&*b_&Yx<}&3XLMrt7AFWi@Uv{% zZlV;OI#~1xmq7~DI$K2|i1wb-Ce2HVp4X66M z8+Z&7RG`n>qp88P@fB}p`}AoS6bw8-I+-4BG@XlyS+~Wpi;&A2@QS1M+Kepb=}r7gq?jd!&&|I0W=otD`uU|2 zBgTeSd^{tDA8F|3owl=c{7_=-v@tv}oz;!CO7!vr2z&b{!F*q3Ck#R#$maFgW;2Dw z$QQCOvhYPDuRoGJf`9{Au28QKY3!3fh z2&G@2G%f;9ch(Q~T$#qs69*D*cUTv&UMvaXGm)-iMBMg5-9LMR zp~}=^=T1(S8$VgD;2x4dPX)SE_VsJP)5CZhkV$Rarkxd;xt_Owaa~)k7cz~a%jutN z^AeIL$ofr;aOdgCn{#vXyGP;SeKQn<)R%McZWH;Ap@X7OBuBjacGi0Ct1|_}-5(N3 zKdP|AuR^85gHe0}XIK>IR=5uk$4bHZSku;=X-obH_~@`oyTyRZv2%&RQfxop&jjLide8i9uw-LLInqrMlMn!CO|N0HlKk zqOG_8m5=e@>8F`&?y)zGlN_WYHhSCQxnRudCZ%a}@_Vwb&a>0p$Yvq2M>>h#?~jF3 zrS=@HDn*^kTgw#YX-9hX^u6j;ldAM;4T3X}VL`)Fnf zoYt#|FUI>an*(eD@FcVRk(k?vM~*HQ*Ux7nX#>3c=;g}V?kGoW!{7y~w;GeugXOvD z_xGD?c{o9w)ylF;@>SN!sIfP-`GomWU6d5gOt95ma-ss7nHZPlqVE+UM=U?ZKr}Io z`-d9fM3nJZ8Yi5`)pp;L=F~k98An*m%1UD##E;@-;!T0;^boSuB@&F@%%1N;^i;pO zY!X#rr!S}s5_B0)1huj>Q9PBb%aeDAN}A1i)?mzDM;vN4=xAoQiWN+tHDr&YOP&sp za8o=-jvuiJ3k_z2FhQ<59nkP-c(9}C`p#I7#-u7D;FQ#Fb`;2jT-HPvo819QHSp#s zyz(SE!0`n9Vmactlhx*rtoH-Igb}9maYo+nlNh@E1Cb@mne?Gbx6(MStXTIsmcBmC zCF?_v@egUv21}l;=Kj>Gcs=G=Dss|#B_y7D$1!<|Ya#XM4Z)I_$qjV1H+Y|?;a3cM zhjwukyfC1{9!d-hj^O&^o`CnRY9?KSssRr@AcPGW#w{}*iYvCcJP-HdcGyMLS<_4O zJPf%hM&Q3Ey7+inl4fN(l`DoNXgrA0W!NbBPUUfD*@Zm>JbXUku6DXPy?G+66nWc; z7W6Ib3=calI9t0sC+l#oSQe@b;PgVk2#F-P`h&SyXEvh~IJv*NP={~WG*RMSPY`4F zE}zAX<~9LZ>vB4F*c>4B`Q4^w+DT3}TT0Epc)#w2p;4_Q7JAiyQAj`{_!**-b@E7c z0jcarvS-Iu??jFy54xXAK)&L=`6x~)*}BmukM9-`%U7RcbU33WI=B3~?C8g-4O zbHV7l0kJ1v%(FKNi$HNqC2z0KFtx_hi5D>+crGC4VEEhY!8@xJ-@>9#IuwT}`M;+A zt~e`r!zwUvSSs3L?+T|2^{8M?YBO6_>N%LipCGHuh5ESXZH_Y9u?u)W0|LyKtHw8O zcj@xFY@H?Rd%<}g=vEgz&s~44#inCSa(iw#wLfw@m*&WC?9h{!EPF4BQdjPw;R&~n zcJf5k5Hp>QE0RFxKC7|_K6FzLX!U)5UpkkP5gZ~dU1L-SXY_jH(s1zEArJAo9HD01 zp3)DMk;gwJ>oMC1fN531u*T78E=E14J}A;zUYGb6r;Qu%H3O=eS$1h>+xGned{Z%V z#h{;$J+@-{;t~59#uFs`c1z`{o;i~r5zqUBu6^QZ2;RqC$<+U(e>Kx>4qu@}9~*^= znaE03Og!e;OApsam~VmiHPOxol4+p!8t6(xEa!%ShPsaxr1ZemQ-8swIcP zh>gkQAZTvz2#X&0k7lQuyD||l(6@_wbXb*E#M$|i*^B=p%H{oI_cW%at7uACfg|je*8Qc;5U(E?J5gjpwp4>r5gVP}N41 zL6Lyz5vrXdv~Ut;c~H#j1eYVY^(=F`Y+`$#_`WF1Ti7%Hvuq0SVw)QZStoP`P1s65 zZM?;79(3n-4eZymXgo#&wPHMO`EC|}*>q0wx3D{{_%avB%i}d=q0G{>(47+#s1wmG z;m$}O|CM%^@c1_FC@+H-t1)O0f6!L$fWCC$1EfXld40YGKF&tF0Z7(``n%MLW4`|7 zAs`}_)9Q1XDQjs_apSt{N7iS9-C%}aJ^lCFan~8ijC$J)24M-T0;5>tn)*I4j}3;6 z&1d$Jj_Ukwfkq%01k~O&b^XMo#Y=P??bb3*zqha~&nro)1JBO~(qs544GHly^54@c zJCiOK*LcuJr*zFzq`eO2%hWMkJnoYOY^x2Yll3~~IzI6TEMpDgNMK?Hp^`xF>g2LX zm0v0frM?IsFz`CM!ZtqC$BFX`cixY;hPY+V!3f>8)5v519(ivk#ZmfgaKZTFS%Rcz z_OMM8%3fr_IM~mlw&~`r(g!B^Y>tP_h)nG_xjOxvQ58fWUON6p>$O&>p@UZjZDDWm zf#aS(y(X;XT3_>?qMeUnsmd}aCDLR_67v`WQ9k+eohQ3>0ZVWf;=o}}n z%Zccy(em(LuFE=s>x(JgRAP!!bOAZt)-ssmAM{XBp6L>bn_q!0iBSRp}MxQ z$I@%=vnQ*_yqmzCD-D@?^_64Wgy1s~i_XuPmdJ$ncK8CPlP~&o9`~nk;5j_Oax)Rl zOSJix{$%d-30BNFREZ+SI)5$ov+9>CI{ZiDUtk)CX)tRLXN)rk#azXEjjDj%3v3)Z z5j&#BX_Wcj|1{|IwFT6{IMaz#n8(oZOh26s7;;vL0h*z0>TtjPvly^$!F?i|x}1Sc zX29(#m;%M$h-;R$jnAISQ0kDUHm(KKEUjM6eWFbwKo2Qcl0IlzT6C|fDppQ=5pfrBX%8?o zmnI=?pA9u3hkmw2y&h{c&PavWm#*sdB?cK)1*3<+IW&TKolk^b2#jQHs<->FdXmxu zFX(lK^(>0D4c;D%sB3%*^zr$is!Bm`dO5;wy)%E)F6=9QwDZ`o+5K?eY}v~xN^v*1 z(K6GE2J@w1oa>or!SDO(5j4(oiCF$d-RxmBuUFP~dwvd88=jOq7d~K3wABWY`EH*1 zIp&Y)jS>@&{-7lks2ohwHdXJ}NUn?fU8F|>`vy3(HkwUOxWiv?;ycZddf@`(!F36% zZxxW2Kvtc-FQ=`e2 z{P)L8b30A{r8CCK>G7;YJ)IyK{FJUh?FMT?27qnp9_TAnnZh;)A587hh^{zo-BteB3%;u26Q-j#YcA!PbEeYZ!Ub$++mX z#v{;ecDf`+m(znCjSF}BC{C926IZGxH74<@YKe3sF31&-ul%33C%-?+vA}q#SuIvg z;S7;*FmYKW=yDKpS=+AN&cC&?3O{I1Xubm1D`U)b-G=FAVhSz@x0+-EeR2rOozUjE zjBaaCn^-V&=MznJ(|EN?9#dyb$-eQLun#BWCIjtBkzA7I+sha!lndkTZquHib~|DS zw+z3<6@*x>jTd(!o`H?IPwarh8Ip`k!Lw6q51I@~lB-RUCllVcqGAxOd|RyENss=m z9)z*psokF7=q5uc0-8XF`^u$zXX^0AuFQhRKgN5?Q2h9d^vAuDcY>5VO&wu*HxV2I zkmApsx34HO?Skf&CszxPK%?Dg+UnAJPl z3{{&*!sk;iJ9d_8uVn2W<4)**W+$T#tKZN+hVV|k2L)eqQ?1vzdNR6Khk*^5OLPn*>qd^IlRt*gIzm*AO2O9wv0O<+C*7sdV5~4Q*g6MYB)e%9MI- zUjY}tgWdv0uLaxSe45kaw7tWRWRGvJ+3C2kyz-1Md#Sk&PEL+5Qk5!z-p0H&{)N9^ zuZgacD(x%8**h17QJ*2iLZlMuZYLGW|&eZO1h zn8;5buom2nC%rF$$w(4fv->T!4Gun=DJ+kN=Es~8so%6H8=M;OZ{es^oDlQ2JOM9I z_gwW(jZ1JV#nBu&=d(f7&-Ds#_koT_&MTgx#IiN#7ZQT{2a3Bxa__{Zw^S1NN}Y}q z+DTn`agkFr)+H3CHURnX5ctj9;IU0>`TgnUJ3|11AO^ctVQbJ0$uHI=4KI|=@`LS% zCG(OXoh9C__WNwYcGYPI>QBG{&h_!4>sTE>FQ7=5rK2<(um~1j(94eu%&Td@Gy9NNfzM;tA?**3%PZXNatY)^Ms6X!OfZWfplBRCtgmJH@B&!ed|Qrh(C41SemSH7) z0{!M=_KGAk;W^^y&IAfN(a$*eowWFHSXD|jkp2WLCxf*rXpILt;37oKHR@|->(#to z^yirp4nXlXerv5RP)ug1_cVKI`eSovO)!`8cZX1p^yZuF2|WJTjiPM3^$^)FGC->+$1d@j9Tha_r)B%Q2-5<26H<>KbopQMRLfG_xt8i3g6Sacj8; zPYf;!Nj=R!FmzSofTDWdo%qB;&zDo7(D${`cO6=X8|LT40&(bJa>jiH%gf$&?~5B3 z$$8?MJ^NVsxa5C8=A_5n-Ci!`{)lF4^D<=d^05LHE76rKL=ijM!-_TEYMez7OwlK0 zKK}9^ZCM3!p*2^22@{jmKr5;3ChttiIRAWY{pIjzylR4FzU4_KhoOrVlOEo)7W`!7 zbFQ2Ek??(-x66KS1iHxQ8}Y+JP^YiatcQDTp)C2qa3;#3wJFtfG~=}j|kb~SIu)Yd9Eze!w4{MwmZ#{J}l^aMM^zm z5CQ0w3sG(FLG4{rM*RS{GrR?eElI>P&Pszta4S>$!-tEn{F!4DMtzo^h7h|{I;K2#$R9 z&+E(hoLeVHwO=0b*Yen8y(mSiSC+q^k+Kk(34q>MY#*ohga-1;&(pHYzxmI1I9;nz znN40;8!RyD`t<~%!GU<`EYjB}ar!=fmhl~}^|3!*UZ^;xqjWIQmBvQoS8eo}jTT+H z+Eerh+pYP~s@rSJzM086B{EDU0 zV>HkUbJ6u3#*fdX=+W!`yUFQe&y~o&8(f}vbkNJxO|7Ju-=6h5mlbId{aYr7TU?oW|m=z%C=lzar=QO#PR z!mLG~yH}VcJ_NYrOC)pko?FkxM|b#>h}5j?4D1$h8Y#bJqRToCt=Y_0XY%e+!9J$% zAJ?9@PwY76hef}32cv*6E?%Prvm>GfLFjyr3gfks@mlIk7DId`nGqZ|>qK_-voM?6 zec|K|opha25tOj(MbQTAvo`IooXC*tx`@*vsl*S1wf#MR{*XD4(!;`naOK^`SDP_g zoD-SgKvn~;o#dUMx~9wXh=C2J&Ijmk*_{z7sKf%ODO@&sn|Q=5TkriP%0(1~s%2_I zXR}8eoutO@qXcnyxmvOZ^_5-c+@R5Ewxd@>2eGE*oE z1LCGO-4)er4Y%-t1yv0@pn|-g@Uc^67vH#!B+OjM&~F{!G) z4TmCEILWG1j?g}Dm~_!Vq*{C9+qi6EapY_w6ZJ4%2szaR1Bg~$^fx+U`JM&-lu%Df zU*sbhwvK0DJ+obK<8wRuPx&)yQB|BbJFvQYzP~c~3clTZjM0a3yV~<33hAo#^nQ91 z$L=u5(QpOXk$B5?pv+flWAJ&%{RnF1#A*HBiVQ_AZ#{L~d;p3^(el39uY^|{*#)J0 zdlk40#P86^XP`dLhQ@bkaacg%%aJ6fq;Z%7g3*ZK^MTLDWtC)&mP;Q}1a#fAH=wh$ zs^4o3$;W0K=PTmRzdnWJNBe*@Ml`*=nPRx^Oo%HYSYP>YHya0{%E)}$Uz(1q?*DFp zPG(GfNNI&iL-|s+=b z^{FvIJ-9AwB#A*xXX{U(-%{;J%3a_!t2&=gx94V0^dQfH5bOaFkJSe@li?8BI7mrR zR9a~c^a}>T6Ppx{;YOT3U7^)wK!X0uHm{Dj4rHMcqxt${rY?@vMl&(1 zsV{dWNT9tO^?i%x(V1-G2<36ErR6xP>g6PSno0fk*zlm$TlX%`J7jkRD=6^xZrdBfub5jA3WSziUSPgy^@OHzty z@6PAfTojnAtCwr|NrSKj?BZ^mxG`j+e@8iSSf*8m^(AE8T^CN>se|b^h);lHpjTq! zam*ToR+kOEUYU$mG;^U8t!htB{ky!x**r40>ydqc5mz(PeKiQBgz_1ww$|=)r^E%*03ey--}yU!v#nm_y8rDLB3Y_zR!Gy` z-XijA@nWkuih<6QgIkN&yRAIV&FoNtto`TB$=pZ#P2rmSX;ypobg#}oV#t(1lo>ny zp#pu<5?SvLcABJwg%ATS>qW#=fwzprzZ|PRW8@Q4-ix06E%g56%+kiYkQ!WjQCTvt zb3*gRJVsc-agjxU%=>GI=&#$&fUdI^ipGG#gGn z6AuVwGrmEwwo^naJ!@*YgxaCI3BCI@tz2Tc;nJjR0I}>sw<|mKymMVO%JP9^c5Iu1 zkTeCpV%4HK_v=V5U9H`bbd0MB!57$F-2+P-*^TzHh%XH`E9*`RM-zAqJl2mizqIwL zmBbPnJO-={o^F;=RAs--Kdq7-vD_V#^AvkopzcJ-v3$JbQ$OjZvk(_9QX88 zLJb*T<=2FVsJY~W=6guKbs8?hyt}xPG|b~LEyIrpZ5xnXYOC+1UYm_e6gIq`4D63) zvR(1xRXCNhmtbbGMcO6fQX0%B<{d@}1bwcP&>>A?2p%;ON1COTO2}eVK^Si}QQUax z#gkGezS5F6 zL~6RJZ>XEu_^Tni5YEA8$VBSC)h{LGS~Ba9cAcHwk+dQb#1jQ+s%K^E@7JKe>?g0s zDrgcnJ0&?Hm1e*aBlO{yH#5#XjQwog?2rGm!h(6J!ATR|^KZ^Zr|z0Y{lsuig`CGc17hoYq>*2f>5BNbIYzeFM(Z+!LEd zEfxzD^^v3auA%QU864|=m5l2g8V~}TW6K{SLRI*PiV!IuIm_ty5}OW#56b1Db}Efx z6JN4F0nd0?oi^!7#YHDT+~L}(hm|p*x#_rUWu&|Id&4;i8O`=kbm}a3e9ei(YT3SY zU|;f93K%MEdKE-!)0tO!8u<)goqP$blJL<(M81g#rZT!1@7KLgtD_}!WmKBBB1pRO z{rtw=6-%wl5+I9ey#P63(O4(dg|wP@X8a54=giPn~O^BIu+tb{0B5S?7K!O^$5YK8i%|^ z-eRQ-rGC%aoZ&XO*NsPDOZvXWUn9OiGIl(~sgAOl9=k@f?w@1vYMc)Zv#(41Q#0}G zXVlLmJKTau1>{*QKP~R#Os|!@M#?#xfnBVaI`AhG|4A|pe82)RrnOq|{v*Dx&G5-K z+UdY91o)GQIfN@qwZDuMaV~c2q1u2`z%KeB^{ZwwH?r0EeT&7PxU~bE9q?2;5up+O zMI6-qdxIXXLA*9RJxsUZ=7yo}+U3T9a{N8&dfIMc=KJNQ9ss`jK>z&B}NrDfR${SLOHl8T0 z-sKjh!|m$?nTLCOdp^IyT`h-{+nA8IIDF!ME%+V)|M!3oDw>!VKI3snX0t3$9OfwR zV)jTm=I%hHlnPefV;x zTc)fA_7NcfzQpLfYI>S(tFs?yD4qu9dN*n2EZ5c5KAjl&)aEv40sb(;w#jN7Gb43> zvYuxLEuB1EQk7Rv%4?hLx>Tu9-L^W}^>O>y;{3i6&Co*}l@zMZIq^jU6&7Z`1>Rp( zyAVi5hDs#|kxDQ59pMhdewzpD5;o~f*l{2Pn2tT+URFkV;|yM_$Yp&v$6va^WCbh7?j_kq+PWK zy~u{AV_sDqWp9i!ua$6q zq?leEOSM7^$G%V|)law88LB3DsVVd!(P*(=`A6JJg9VE5#Pu%o2o zb4h0Sh=?$uGc9q*#H7x0ee)@PF!0-z4%^>mY*QBT=o#I$6<4>0xAc8paag^+a#=1a z?2h95p`GJOYrk+-=fYh{pD!Sp&nXwlMvk02j=J40*T>K$BtI@L*PBDRfh`jp6tFA; zfL)}h8jxcQTr2z}ziejAQoWa*`wNquyd>s%!_fp8?Y3@Vm;y}H8XI4guneku4> zdM`%%ef?VSAHKqbHlH8MxmhMnt|Sx|I8BV;O+dmbUh`2C!2L$wmR{Tj& zS@>0g>RDgw;56X<`~E&+!p*d!fnBD5A2FuLR#5-%u5;Qc2P|d$n_>Fn-N*Q=J+(n6 zJD2Akx1#cFXcidg@u2H?1%f!V+Ph8Wot}3nWlhqsYR$hfbg^N&&#P(!L24aN@fkHJ5#8$XC81`)JJ!r&1O=-h+09WT0$~sxH+!+({u_0O*6jf8YMD|! zGP5S@m<;hK(OFtbed`8L?^<(o`o=AqggdCoVxc$Q!5f6}t8j{SB1gp!I4D4GE|2d#OK9}I$sQ^@l&;vK`^jp8V}{UwF`zy73a zK-GZf`$;BR0kOIE4!FDL=)`apdj-s__fKA#1vu;k;rXjEXhU_rs*U&kOu4*7MSMlL zK`4|-{V=F(ORH86+q_Xb0ex=fiZNLotfdv3D~4rv6qf;i@p3%@^EaiCiDjMcAD`CJ z;(q{aEEgJxZT}{EW$Jx9myv{q z==S@=NID&k_{>J1FDHJPKdhCXV@?%jCd^c5b8YgTx4}dh&egAD6ngvq0^z<7)7h&{ zW`Eyin*OOYbF$G%idBD;L0&U^4CMw^7ngi88t4NU9WE9yin;Z+~cV;Ya!WkitCZr>{YTY56 zi#dSdDBb{EMiO$t_v3=~KZYNW5Lx7L$ykjY5VP3Bo=s#@+PED~<_LLHCVbT;V4ZN# zXtXBY-R=`Rh$7|zh#w#QhCvu!5RIh}^W`v~1+-{4U_b3SNljR#+-5r#+KWjb_(m(<+r}#NS?bj=E}jJ|mH9F`pWU+&z-IiMkKI%ol4H zq3?p%TA;ac*V@D!1|9ZCp?KzTlxDlwV&>ne&qMUtjebN2WiVK9W?u*5aD=O?^NE?A zxIS_|UX3vM5usd^Vp28C&uRBtx{nC?|2@l^a}a28j&-hUkE(2N-F*9n@1{2{d+HI&Wx!N?cA2@lJD& zT=}1*(521JtIhXHL+ns9I=|%yg^_w*K!r^tu*Atm_s|`bw7fo z6P?p434i<%1sA}L%j`O6FzAQ)cy%CBoy@2MeFs?}T?Fg$8VsNl`_a8?AUR@iEpE*d zDvnb-%9pap`K+865pM8~_NHohdnw3SMKqcYlCez~a}2-#V4z8j`u1?eS>Y79H@Ea_ zMCgzuCZ(cms8E}3Fnzx?VO{?Ahw)e%hacRZKfWTtXmE_$jBH_kRp2l4IM&Bn1?l|} zU3KznWaj63?0zOhAC4-m z@wt(jv(k58D5dbbZh@CW%0W_3X0(Um@q7E1HYI9JV5aH;IXRi_x#H1u0a>({MY*V% z&!SEwRqQ4D6Qi|Wvat3s!9Fo>gY?hk#$BRk3nM*o(e(KWzn2fG`L(Ocj+tsxxnh`t zuRGCxItRNQAf(1N`%RXNevH^z3pT43x`p42y3}^Y+ z(76+arN3=C8g%=^>5A1R58le}KY?BzuP9{+bOldZWo=bIA?&Gb7Z8!en9 z+8vA)Cj$%U?n$n#pKhjW8I&7PV>XzgK;}5QVvk>{^q=}IDswVMTDZdLb?0susT~7t z(O-kyAq@CS`=~UX4NaXiHUjwZ_b|avf|2j0Buvwi!?OxtVeZF~cR{Gyvhoov^(%uZ z))+)QiI;g*NfQgLy(n7yK3q9%UNG8lWvi{BE1@M;D9h@da>8*Bf0@%+Ib|RL!{uor zFjJwN+_s`VDTCIDR^@atcrjrzA+by?>a?R5L0BFbN}yJ$Nx8oq>7riYUY|1apw9K4 zgj?HR-LC~9pyRj;0+P-CvxI`x?vtV`DyQIS7EwZEKe}WFlo(oSHA7+)+}*)HzqA2e z)?WyWD$4Ya>H;<4p@;r5(>Pu224Ghu>SEUa7jajo#aI>wqA@{ItNBJe-~I$D{08B(0uw&!xCv|4^BQlMaJtK(7lKNE zKB!&->n)d*HuVWP0nu48@pAZwWz9in0%IB6wW9D2q!B-LI^K>gR5~0E) zwpmP-4^hQhs%>9X%T=&a0OwlfXcEkbh!T$t3M0P2E}MTR>tTD_1Fx~-yny?Yb;_Hj zN5`>PHk#alXkrA*8MT)Wm#fu)hK?UbP408%v)`QCTv2thot-+}hx-cXc2)H2Rm(!; zBhJ=ZV9ss6t`ou(=Oi!=jF7#&J)d_;#(#$S^xA>wDkQHOyoo$p^~34%^upL>s>&|D zUua-NWwQe=VaP(gG6(!sxe$=$@y1OikLSCI%vX{~Gvmz#(eC|3rzdj;FUO_6=JzS$ zUBRz%blw2J3iaWS&~_bodGO_Ggvs>^yw(DBf4YXU+gx(9B5G6jnS-Vd<8HDCgZwHM zJsN<3fe%e2V3|UNA_Qsu6}wnGZ`F&!_&TXfXZ{OxMT<-}W_PJN;n3>yaw$G|bGA?< zPuffzk}Wfy%1;PvY|^K1E=l}aYi~aIF=&4@R;Of^mt|t%XsH$<{t+Sm2kuOP^e3H* z1eboEa~@4ckDl7V2FoRXW4_d!8h04b+g5PMS8Z^)F-BKwk|7LfuAtSXMIFcA58p41 z$*MKgt@K=%@98Sr!h#ERof-?OFT2%JY5rFL%@Q*0)4ludyGT~=uDgId>m{~a@r&=* zzdth4uDV;QxXWbv*IySe^_6cIFNAmAb!XgJyt}JR?%K5rxyGm$U+1gDgHp`zm#gag z_obmPAzvV@>$GXpQ1Z-~GhKRl%jBBXeYrmH?zLMU(OBkb$MK58-%zZUPjpk~-WTdQ zwDac8!>xPnxyJ{+5;Ch_Uw%S9h^^Z)@b70JQCin!%a-HK@RXGJ*#xuQUB7M}N;`Dm z5Rhk_`{A|gS|5&5dTSHhYv+lk+x7f4f1N{n?(BI~L?+#9^gM>&HC&r@^@^Nlmnuyv z&$Gvoa`BSIxVwATZdaQ4eM2$(p+oY1e_!-F&{|g)rB<*ESOx;cKq9lQCyvSb)dL6i z`;m{+XU?FsO`A6XeX*{|v=>Lkcvd=PUu*(P*uH%`gd>NK0DZBprY1*@NNGEE?qC&u z!F_s4ZLt!?JS|PXL1>xXv;4hn8zRq~JL`VSs~Gc3>fphHUgZt7#J2AmYH!5qV;P8* zfe^K>v9-872ledPbFn^<_cyNS%;CwCCtX<$GwJM@aoutW?iyabCOx-6gj1(Zp;(@+ z>Xff5e$0MjZ1tLYvbWEa7cX6eaQe*Y*fPc={>V|W*p78I)+9Maxvk=+{wY(Wbk&tC zS!6bj20Q(KR|?;RYvHo$IJR)(ri?|0axpU`+nkkYekD_dn zBt?rAMNFxZC4uI=YqVruUFOoAI<;!na^<>o@sdlN5fh71{yhC6A`ofB)n zV~6a$ymILZFm>A0KnB`3v)>qT$J4*J-!5ms7AjcCm4Rz_!^6W7lT-C~-HIk;&63p> zvtiRlmt0s&t6Wh^-nv;<*!mv0%arAuI3Br6mN8kgWfMXBtK0*WCQTYd6e(O-;x!yF z`j+L&mP1??-Bo)@ceFZ*y!^v?S7s_;oLhhCLgZVfCSm!)kSr;c^RkxUB)8TzI6T{0 zECYUEAiB};Ly`U{qF{l7C?;d3Ou+N!Wrpy`A?X+8&MQ{8dd=#<=`*GS!>@^j@pksr z?9r7kUmhid6_l3MJ(Mn8S|Zt{qGixTv}tUuH*bD5%NDt;B_ z%$B*b`3vU*A9_f3tF~z+J4iqJNUZC!rAvWc2OXu%k|hf=(r*Jx;0_hax%1?KP@rG| zUJ4r4mG-~1+AdnxRjd9$5_%7!buC*~c31xOS7a+Lg?JNa!&}_f0-2H}m$voTQSm|b zht|cCs#lk9jTnMzTf9W1O+I+w0FwQ#tA*;_d+z~Ot0vx|R{beESG*3&WY(;a zJ>=bc_n?qpbagIEBM;6H=v4 z1>IYp6g_Eo+25mYp&mVYqJ+Eexf{r^ zNY|87Zrn&(VvZI%w~aqe->+tE#C`qsH?BLMe)cKk>NUjTy)x<*ApKW3UWIf@*OO6V z>e;t%UzBin!$=K3n*I@D_U+jVWGGlz`pGePNZ_}CHpqNl`qP;5{uCsqbuC$ znWurCj31^}-$Ffl^g#L-heX~r}2b$--Fy+H9Vzjr_4STZp9c<=xA!ce*Ii`ckSE-nf{8dU6a*0ocnbp zh(lmMoZlexe*G0Ge^lGjMEw}HX)9v^*?Z*xo=|^LaTMjcMW2Jut4G4#y?P^l^QO(f z*WP&Dl_q1RjF9iW_g+_wyAT#8WAg3WwFlC=PMP{X1;s_;le*WEe-a(oQ6)U(>exM#I7A;zcm`Ed%jkAnEDTr(O9tQd+u98N{qywgSjiJFW!57PK+p3LbOqPMtb3d-l%w z@xY3eD!H^;{JZpdmg}4(M`*e3C$D;TucRZ8ty@3nO3(d0BSyW9n6Yoa?TV+zUCwsK z&?j`IgPwK)(F!omswzn?o7SfPBR-H>}R1+F@7et&b^9!v;UJmJm+;GAWYYJ0q&z>pFCyC zl!#}&4eB+3T)v{rs5AWd!;cVp_3j1Sy?eJ4i#j{B25N=f4|8iP z(?jMuDyP57@l{uf7zNdEpEW7 ztvH0sm!&7kbBSKoFO&uI7a)dnu#+cGhTOV!Ybn8F4as@(l*uKN+Ih(yG5-IQ_K=;E zZ+Ih4JbL&j?$7-EQ{WqKya6;%PN-L}K4KOum=9z~SnGQJ!g;7sUC$rlOun_Q5pTx+ zwG1Re24WZ)=Byys(1gSjseSuk>IYEf@y8zrZq%J68#iu*+@)(5;14=({Nf8QLgvmD zXG9m*Ns{nvmHq$hhy32e_khzs{up>vJt{yz$fWC&IaA7**hYh$yXGIY9@VQ=N8I>v zE&p@o=LM=`z^ofsvy&@=E|K5C5(Jo zY;~J9ZGc_`?m(7F6DI+?J=q=jx7t|tv7hMN88I!Ii=G_oE}%W+jF~echJmBg z>vf&hZ}Y`2eKJFsq#dB;e^c$4V^=--Heu1qA;$s+4SEi7Z|Df~mCIKkPgQS~>~%k+ zW5}Hz>xB4x`SJl%q>B7+eEQ@W#O&I=6F5jmt$)?i9&qUjciwp?-jF`-W1y5;lqaG?)`d_4Rd*| zr|L$1{`^x$J_ijN1pMu{d5i?I@5+5hWHM*Y9Ej&^-6wlIU`n{HE+>e z;%K!zx2{GxSFVahH!Ps{#B0aaxVJVvEzuR*GP^a;1YqW z&^vbM2>JQvW$d?b;X-o5u<8lhcip*5z6kDZBy-eUyKeig@`7xz3?xzpB0u`^06b0X z!i9^F_v)(D5VEe?PV;>6_ouuM4QK1QY4q~GTxT-b>J#IBAB74@%i2NP+J_&OHBx1` zqBUODAWB`@TGyyi1Cf&^O#)7yB4ebh)td42be``{jFQ*wV)$^esI&=%ixigo)Q~no zuDuCHF79^v{Ik!H|BKH*2lh;8dQ|`b1&c{UK~&T^$tybEyH5A+663C*Sg~SA@R;@_ z9lOd5J}?=v^6W{JR73Y0O_(4v!=Hco1@NqTu3WTmA>_CN_ZxFfc;_diXWq0)Qy};H zxc6F}^-RWEX!fP!uEnFf`d!1B<`XEZ_J%GNY|*8L$k59s^OV zE5`%3sejk4+qOd6Socx}|4G;+DRPBVXC2ABx1oINbDhwb*G5C$y=M>bw5|tYdzn^e zQwtU-fcU4MdKyTt0^En0O#8RK^tDi6^q_XEYuB!bZ+K5b;L4RUE6a1!SN$pTpR`@n zkgX{-2Y%L2narLeJIa4jS5Rllk{R-EI>$@Pzf;erJEQB~IA2go zeQQ+K^WCI0mIIC@>o8l34IOuc%GXWZ#mSGIrDk)#7WdOK02BM4%^V_;- z&z?|`)|EbT>eahTlxE*1n7yfxqRJ}sA7Q|>et~;rW1NL&y0a?!IpHsnzN1VPtaUZn zu(D+!q#20Pcja%I`|Er6?hVCv?AQUEIddkkfX-X`ZEh{3X|c*#1_I208p=JoMu6+; zxC&tGSn)l^RnXSD2KXJ=;w=M#WFQ9X%IbJxH+SbWy0;M`r%av#EKo?+2Kjk~jg)w+ z;O(s7t;&nMADq5QWPMiho`FDg+Ps~W^+w`U*jcI(~^`13D61L<9?Xwjms zT-Lg}sIY=%An`E}t99k0&;$CmzyHQ1{SOWwIvjGn2K9iPDGE++_RLvXOUd(QxYN?v z^NCn*0%wxx#kcb9m60`@o(bT5FL+awO&bgb^sDNi?sui%L#{e<{_lCI0rO_llV<5b zlD$MPi}5~rGRZ=(m%r-DVeYk}e+>FVre_bcXlq?fHmqzJNMsB|nRj*9oxk|qx-;Xo z*I!41Ce4}vc@`M`>vz$eF=fh>MSM>6xgKRLlzXA^irKtnGxE_p>q+&6&)p$x9X;PO z!Bx;Vu3txKqhFOBJoM@iw~w57scbX(fdTGWoile1%6eV@2d39^>&;VP)l`yx+_`U)USz*ipX)cZcj4?d&=Y9PT>g^7^;8&o^slbI z8hG{zy&2F;x+itrtLMsXP+xx8bbn*2RH;14XwxJh1N^^7KN6g!q~BmqRHBc|1q&7+ zF;9yR|| zw+ti#2E1rm*h{Qmzdjy|{k@?>heCeg#TS9}QF!?9VaV)B#&7Hn*<%bG2hOBB1`Ft! zW%Myit4@qDW3)(~m$Pr*KE$)kt5>f^OJgrXjRBs2lUvU^%CB!fkDhJsxt@IQVY)KU z^qF-1x566Q_piZ-o71U&f+s-_`RsZc|zY5}1Mi1Ba$-(bdnirvLx| M07*qoM6N<$f{{xKxc~qF literal 0 HcmV?d00001 diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/discovery/NikobusDiscoveryService.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/discovery/NikobusDiscoveryService.java new file mode 100644 index 00000000000..9e08f79133c --- /dev/null +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/discovery/NikobusDiscoveryService.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.nikobus.internal.discovery; + +import static org.openhab.binding.nikobus.internal.NikobusBindingConstants.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.nikobus.internal.handler.NikobusPcLinkHandler; +import org.openhab.binding.nikobus.internal.utils.Utils; +import org.openhab.core.config.discovery.AbstractDiscoveryService; +import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.thing.ThingUID; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link NikobusDiscoveryService} discovers push button things for Nikobus switches. + * Buttons are not discovered via scan but only when physical button is pressed and a new + * nikobus push button bus address is detected. + * + * @author Boris Krivonog - Initial contribution + */ +@NonNullByDefault +public class NikobusDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService { + + private final Logger logger = LoggerFactory.getLogger(NikobusDiscoveryService.class); + private @Nullable NikobusPcLinkHandler bridgeHandler; + + public NikobusDiscoveryService() throws IllegalArgumentException { + super(Collections.singleton(THING_TYPE_PUSH_BUTTON), 0); + } + + @Override + protected void startScan() { + } + + @Override + protected void stopBackgroundDiscovery() { + NikobusPcLinkHandler handler = bridgeHandler; + if (handler != null) { + handler.resetUnhandledCommandProcessor(); + } + } + + @Override + protected void startBackgroundDiscovery() { + NikobusPcLinkHandler handler = bridgeHandler; + if (handler != null) { + handler.setUnhandledCommandProcessor(this::process); + } + } + + private void process(String command) { + if (command.length() <= 2 || !command.startsWith("#N")) { + logger.debug("Ignoring command() '{}'", command); + } + + String address = command.substring(2); + logger.debug("Received address = '{}'", address); + + NikobusPcLinkHandler handler = bridgeHandler; + if (handler != null) { + ThingUID thingUID = new ThingUID(THING_TYPE_PUSH_BUTTON, handler.getThing().getUID(), address); + + Map properties = new HashMap<>(); + properties.put(CONFIG_ADDRESS, address); + + String humanReadableNikobusAddress = Utils.convertToHumanReadableNikobusAddress(address).toUpperCase(); + logger.debug("Detected Nikobus Push Button: '{}'", humanReadableNikobusAddress); + thingDiscovered(DiscoveryResultBuilder.create(thingUID).withThingType(THING_TYPE_PUSH_BUTTON) + .withLabel("Nikobus Push Button " + humanReadableNikobusAddress).withProperties(properties) + .withRepresentationProperty(CONFIG_ADDRESS).withBridge(handler.getThing().getUID()).build()); + } + } + + @Override + public void setThingHandler(ThingHandler handler) { + if (handler instanceof NikobusPcLinkHandler) { + bridgeHandler = (NikobusPcLinkHandler) handler; + } + } + + @Override + public @Nullable ThingHandler getThingHandler() { + return bridgeHandler; + } + + @Override + public void activate() { + super.activate(null); + } + + @Override + public void deactivate() { + super.deactivate(); + } +} diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusModuleHandler.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusModuleHandler.java index bb7e2eb04f1..85cbb2561b3 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusModuleHandler.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusModuleHandler.java @@ -176,14 +176,16 @@ abstract class NikobusModuleHandler extends NikobusBaseThingHandler { logger.debug("setting channel '{}' to {}", channelId, value); + Integer previousValue; synchronized (cachedStates) { - cachedStates.put(channelId, value); + previousValue = cachedStates.put(channelId, value); } - updateState(channelId, stateFromValue(value)); + if (previousValue == null || previousValue.intValue() != value) { + updateState(channelId, stateFromValue(value)); + } } - @SuppressWarnings({ "unused", "null" }) private void processWrite(ChannelUID channelUID, Command command) { StringBuilder commandPayload = new StringBuilder(); SwitchModuleGroup group = SwitchModuleGroup.mapFromChannel(channelUID); diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusPcLinkHandler.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusPcLinkHandler.java index e05928c2434..bcb2c74a3e6 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusPcLinkHandler.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusPcLinkHandler.java @@ -16,6 +16,7 @@ import static org.openhab.binding.nikobus.internal.NikobusBindingConstants.CONFI import java.io.IOException; import java.io.OutputStream; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; @@ -24,12 +25,14 @@ import java.util.Map; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.nikobus.internal.NikobusBindingConstants; +import org.openhab.binding.nikobus.internal.discovery.NikobusDiscoveryService; import org.openhab.binding.nikobus.internal.protocol.NikobusCommand; import org.openhab.binding.nikobus.internal.protocol.NikobusConnection; import org.openhab.binding.nikobus.internal.utils.Utils; @@ -41,6 +44,7 @@ import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BaseBridgeHandler; import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerService; import org.openhab.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,6 +67,7 @@ public class NikobusPcLinkHandler extends BaseBridgeHandler { private @Nullable ScheduledFuture scheduledRefreshFuture; private @Nullable ScheduledFuture scheduledSendCommandWatchdogFuture; private @Nullable String ack; + private @Nullable Consumer unhandledCommandsProcessor; private int refreshThingIndex = 0; public NikobusPcLinkHandler(Bridge bridge, SerialPortManager serialPortManager) { @@ -113,7 +118,11 @@ public class NikobusPcLinkHandler extends BaseBridgeHandler { // Noop. } - @SuppressWarnings("null") + @Override + public Collection> getServices() { + return Collections.singleton(NikobusDiscoveryService.class); + } + private void processReceivedValue(byte value) { logger.trace("Received {}", value); @@ -133,6 +142,11 @@ public class NikobusPcLinkHandler extends BaseBridgeHandler { Runnable listener = commandListeners.get(command); if (listener != null) { listener.run(); + } else { + Consumer processor = unhandledCommandsProcessor; + if (processor != null) { + processor.accept(command); + } } } } catch (RuntimeException e) { @@ -157,7 +171,6 @@ public class NikobusPcLinkHandler extends BaseBridgeHandler { } } - @SuppressWarnings("null") public void addListener(String command, Runnable listener) { if (commandListeners.put(command, listener) != null) { logger.warn("Multiple registrations for '{}'", command); @@ -168,6 +181,17 @@ public class NikobusPcLinkHandler extends BaseBridgeHandler { commandListeners.remove(command); } + public void setUnhandledCommandProcessor(Consumer processor) { + if (unhandledCommandsProcessor != null) { + logger.debug("Unexpected override of unhandledCommandsProcessor"); + } + unhandledCommandsProcessor = processor; + } + + public void resetUnhandledCommandProcessor() { + unhandledCommandsProcessor = null; + } + private void processResponse(String commandPayload, @Nullable String ack) { NikobusCommand command; synchronized (pendingCommands) { @@ -229,7 +253,6 @@ public class NikobusPcLinkHandler extends BaseBridgeHandler { scheduler.submit(this::processCommand); } - @SuppressWarnings({ "unused", "null" }) private void processCommand() { NikobusCommand command; synchronized (pendingCommands) { diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/utils/CRCUtil.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/utils/CRCUtil.java index a02dc70da89..322d60e4b00 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/utils/CRCUtil.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/utils/CRCUtil.java @@ -56,7 +56,7 @@ public class CRCUtil { } check = check & CRC_INIT; - String checksum = leftPadWithZeros(Integer.toHexString(check), 4); + String checksum = Utils.leftPadWithZeros(Integer.toHexString(check), 4); return (input + checksum).toUpperCase(); } @@ -87,14 +87,6 @@ public class CRCUtil { } } - return input + leftPadWithZeros(Integer.toHexString(check), 2).toUpperCase(); - } - - private static String leftPadWithZeros(String text, int size) { - StringBuilder builder = new StringBuilder(text); - while (builder.length() < size) { - builder.insert(0, '0'); - } - return builder.toString(); + return input + Utils.leftPadWithZeros(Integer.toHexString(check), 2).toUpperCase(); } } diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/utils/Utils.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/utils/Utils.java index db0c62e3897..45830821b70 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/utils/Utils.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/utils/Utils.java @@ -29,4 +29,62 @@ public class Utils { future.cancel(true); } } + + /** + * Convert bus address to push button's address as seen in Nikobus + * PC software. + * + * @param addressString + * String representing a bus Push Button's address. + * @return Push button's address as seen in Nikobus PC software. + */ + public static String convertToHumanReadableNikobusAddress(String addressString) { + try { + int address = Integer.parseInt(addressString, 16); + int nikobusAddress = 0; + + for (int i = 0; i < 21; ++i) { + nikobusAddress = (nikobusAddress << 1) | ((address >> i) & 1); + } + + nikobusAddress = (nikobusAddress << 1); + int button = (address >> 21) & 0x07; + + return leftPadWithZeros(Integer.toHexString(nikobusAddress), 6) + ":" + mapButton(button); + + } catch (NumberFormatException e) { + return "[" + addressString + "]"; + } + } + + private static String mapButton(int buttonIndex) { + switch (buttonIndex) { + case 0: + return "1"; + case 1: + return "5"; + case 2: + return "2"; + case 3: + return "6"; + case 4: + return "3"; + case 5: + return "7"; + case 6: + return "4"; + case 7: + return "8"; + default: + return "?"; + } + } + + public static String leftPadWithZeros(String text, int size) { + StringBuilder builder = new StringBuilder(text); + while (builder.length() < size) { + builder.insert(0, '0'); + } + return builder.toString(); + } }