From 0df4ec243584f9626caf0aa8a3fa05cb8a8839d1 Mon Sep 17 00:00:00 2001 From: MReenen Date: Mon, 24 Oct 2022 22:33:02 +0200 Subject: [PATCH] inital commit --- VersionInfo.h | 7 ++ compile.sh | 6 ++ relayClient | Bin 0 -> 183240 bytes relayClient.service | 26 +++++++ src/conf.h | 19 ++++++ src/gpio.c | 26 +++++++ src/gpio.h | 5 ++ src/main.c | 126 ++++++++++++++++++++++++++++++++++ src/mqtt.c | 162 ++++++++++++++++++++++++++++++++++++++++++++ src/mqtt.h | 24 +++++++ src/test.c | 35 ++++++++++ 11 files changed, 436 insertions(+) create mode 100644 VersionInfo.h create mode 100755 compile.sh create mode 100755 relayClient create mode 100644 relayClient.service create mode 100644 src/conf.h create mode 100644 src/gpio.c create mode 100644 src/gpio.h create mode 100644 src/main.c create mode 100644 src/mqtt.c create mode 100644 src/mqtt.h create mode 100644 src/test.c diff --git a/VersionInfo.h b/VersionInfo.h new file mode 100644 index 0000000..16e878f --- /dev/null +++ b/VersionInfo.h @@ -0,0 +1,7 @@ +#ifndef VERSIONINFO_H +#define VERSIONINFO_H + +#define BUILD_TIMESTAMP "2022-10-16T18:54:22Z" +#define CLIENT_VERSION "" + +#endif /* VERSIONINFO_H */ diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..f4d500e --- /dev/null +++ b/compile.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +gcc src/main.c src/mqtt.c src/gpio.c \ + -lpthread -lpaho-mqtt3a -lbcm2835 \ + -o relayClient \ + -I src diff --git a/relayClient b/relayClient new file mode 100755 index 0000000000000000000000000000000000000000..f466762ef3d9dc5ec4fbe1551a47ceb2aadc5820 GIT binary patch literal 183240 zcmeFadwi6|^*=t(^XzV}hOh}FTz3;dL%@J?7nCL3BBDYFY87RZ5QK6`NP?oEE*D!A zKQ${TD5wi!g%sQP5i59&NG)w`jev-^cDY#nR9jI|iGumP-!t=Uo&-W|U;TVP|NNHM z?97}wbLPyMbIzQZ=gD%%*oosz!w~kz63+_OqU{tUpd0q=GIdFafEX$g@ZD4N5FS8X zNCDm2IzORF+j+dkvyijjP))XV-bLftxy>PSw{AOAHsUq~wR0h7qrS;&M7Kw7Qxxr7 zGJ|$MnUWvXPWITZPWP+R{p|dhX3Wm*`H>7$k)B`cd<@$7v2)_`GwH+X87v28$?9qO z3>OH75(PUF6lRS#`$w+&tJIc{Nm!u(piHC z=2eyFU7+Tj4*Fzu{1sD0=bsPRxy5x;+WL?0>mH5klQQ*Z%f^sz@<4jT;fMHfvZUZ_ zv&YlmACy@lNd(V19n}&U!oRd7#e7t~r=yB%0Xq}CYa96E+Q8>%ex%l)$~NdM13bGm zGU`_Y-u?{mOWU9m1@4*nPi_N$QXB9?ZP58^8}NtPp!1J5@N3(Ehufetp$&L9(D5U+ z{)}h?zkM6jveIfN zu&k=OviueYq^hiXbn)D|CB>z4svO|cyOvg#6<0e4m|0oYx_Wt8RaNngWnyM|McI6T zq2`y)s}L3CRkIgOpI0`oc<$^Q=ZpEp^UJH|mX)DlVRe>R$V%)xDwJRtE`+~K7DR^X>s-J^7&$BRaw~_0cxccw}_dgbIYsB1Sq2&T_Ms+ zF>m2~5?ZJR0h`4$NUm(*>=|NaMdj@I)iXi1bW!p2nX~7Er(4T7D0-H2IBW$Fs1*LZ z;@R^B>J`Pa%Fmy-pt^cMvDy@f!_r_ee&VJ1qo-e(cfk-_hq%S4ZN@}?`aiZR9B1x? zkdob|s2bQg>Y+>aKDRdf0JcX{{2nlV?0w(T8|X2OxJB>pHaud(?@%3Wc>N8EPD3kr zK*JBVf(N-F;*+EIADfO{uhaMj__6mu;_q<469~|sdIvnw1|r|%fOmAjqYij42V8{I zyiAO%Lkrm&?|^F&NqDLQ?u^4S9dKtH;&;I9*ocI39B}8n`a9rBazynt)B#U+zyl7r zbIUJqz*8LflN@jz;>y-*9B^A_*bsEUo%`=B2i)n$Dje`M$GD3eaIFfmHROPIaNw_W zz@6(@WQf5JL)N@mpJNP)R#Hx9Z}!psCPzvm!sYt^}~*OHtMF) zJpQ?;XFKY-sOLNCd8n5->KCHE%uyeV`X)#HBGh*|>X)E?*ip|%-87rWABTFjqdo!k zd`JBX)Jq)oLe!Tz>Q|w@$x*)+^<9qo4X7V>)Jsq|t>*D(qMq%j{}}arM}0o(C60O} z>dPGUn^526sNahEE=T=#)DJuA%TPC6&Ex+B^=wD|Zq)M~^`D_$qUzm5Xm59<4=qu9 z$O<$b?jgc|g+4~0bK=wSjgP@3OFtgpxEcA1{o@3{A1TBq^*H9D-jH>0d}A^2k6A{ofF83?Ykb)7AF@y0v2RrJ(p6a} zN3DJZ_?yr-|JeA(64}>`_2qb{7QZCz=gTC~_%y~0E*m#2V2DAW+aTT_-xxw4ImVhm zNePVb% zvGY(Du~XtjhldaOLOaEx;vGJhxB&AmQvFAS@5k8i3F*-;ft|j1u>f}oMRvKsE(@^$ z{3^H$WkVFf&!!*p1r&X8ad^3$19)XnvEhoFf97AKne`=y&x9EW4^L{R4mwPkA;36(eEPm1D>cClVu;9 zuS_)t+eTq-4*|EIbBs(876SB-E7{69gQfvI#5$6HIlrD_!6A;X=r&sDmv7H0qUO}_ zy_%C;BaBD6-wrxyPC7ZK((MB||$V&~xu z(J1+cK1O@694d^CG=?=@CUzojNRM6?+6i4D&ME_QX8mxF0PS=YWdM7e6NOxx(C5%) zTBo8T!~Xz3h>y@euoD+k?W3T__UMqnPWHh$u;@$Bih|Z0;ND@1PaZqjR1_UKY8clz zg!X7gps^BjKpdBT1pN+!k3-18OPvUc@LQZSY*yLbZ}c3sp3#P2!xA?t!VdvAg1KD) zJ#FeIb|QvSx=Nkzr|k>l3al6UC|l5Q$}$)IZ~{o@c+q}(PN2iG59|Eosiq=9T|IUV zbOZextneP}!O=A6ds?6obNaj(a}pxt?EpGWzY@a`SEjE7Us05!zk)uEF%|@YYX0&?m6h((1dr2$e3Ku$PrE$KP z=ig5?tqsm^DF*{{%z{1|4Pqz#m2*5FV9oku%Tw(K^jk4~3cAA{@&kX*bp?&0LnupL zqV8}%v^^5DJ=?cyy@b6Tf=(QUejc&))9(p?0bUPby(NvHC){1rH{d5Z4t*QepjNhH zO*=Z~%k{OY1C7KZ4t+ayCn!c9h>jLvi?mR8Blow^m6mgpEyq3t zKWn>4xNVoY$Wdj{=tfN2{SkAJ4?RrZpC-h$#*az{7@^tf845G zspl~j^Wa>KU{W}`T!fDxHZnSe_8vxl2zzLJtA4bxBakU^oAGFKR_&>iE!T6Y87eeV zTh5oh(MWFz!eQ;9g*tTsN3#}w;nd$VeQEy3Wr?e@h1F2!!e|BKo?XCCkTh!%_IHh{LwY%OTKSgz=;0u(xt$ZvpBp${b%r+J#&5 z%YM(J&#A?~J)=xzzxwv!U!FFvmNGg`_I_{p&C~ik+w5O580)~d!G;xY-tcdL&$8i9 zm$vdl<&>Q~7V>g$&FT+%_17{A^p`RclwB0%E-KDtoE2#;H*J?TKmEW*^j^sDUL`}| z7ac;Gyoo?scztYMziTNo>>;Jm?p z|KeS)a2EE%@!*kV*y?@3heRXeKff@x`h|&PA-Ry;TkW$LX&$wV+z$~)@NR_r3-=Gi z(1o=3FQ*t=JA>wzfOD(}#)?{LwO>vd6{7)IgNTlAOo#ps2QKt@=jY!wt)=h8eNbK0 zO0Uh2bPQ*qoK@d3d=cf?iU#LMIr?zEz(eJtc*HQiWL5qh#`LACGR8V4wgnn_o&`TL z*5UcC82GX+qT3L63czGvoDqucxNWy?@2d7cpIBYg?0S1?)L?kLwe z%9|bKEvn4<(0BXmJ;Nlgs0aRMMWJ10JI>n2DDOc1xM6-n4CMWkpEeTA2y-otLWbZ4 z@vFM4dU?3@mLIZZPCDq{VD}FSF^Fx1$LK^AoxQE-*!sl&`51eb5CgFX=8~2gKQsKB z@0v0=jv+*g@rYl7u?Xi_E&BO8g`Y(~oBpZADz5wLI& zFFi~#@DTLFp7#^rwH`PnW`{%rbI%vX1gv8Whk7T1nc=Ul%ZL8Gx@CQgPc0Ypea18< zus{0-zHb`Dc`P&4JlNmvt7P@UR_YyPL79`cryqQ3IgEUI=of(^31?EQF5O_1u z4^K%ZWI1r0bNi-rH0HN^OR1jUu3M{ia31XcjA>3#G|*qqZ`Z8@WV<~-yFce>uLtz8 z;c+CZ>)3tS7{4dxRN7U9AIF;J`|CR|jki|a30<&tV2mDn*`gkjHff!aMo!x_2AqM0 z%@1WxdZRHud~I$P_`x06z^n?v7zcKc8SbI``@1&l;XmykY3`q9_s==KKgZ@>n+bXJ zz}Wc%MR)~xDULT+^*n<;idJ?+z2TaaEGm)mVZ4_GIgS+OkGU_{@@g?g;Ot|3^leL< z{~=?vmIrN=vc&ro(x+qzL&}r-P2cjTR%37uSpj7~c*`Tv)|oS|HTZ8!Uv_+}e1=nB z+FWDJ6W6#__wxr@uF;G_2bC$Pc<(QZEv{P$Yo#Kk8E#kXSyF{ zMt|qz_Zjd`UdgBA5xj2%tp~s(?!MsDI>vaM4IU$CqhIh#{#BdPC(z$b2YH zmTAB2pDnTz{kG3*#jAY}V(ZHfmhZJ^m+wXYf_(e^Z^@TDo<+Xxf1rHh{x9S^^X&3H z-1x)w_w7byga2{;C68y3?@sXeL-hAo;P3yr{#Kq{zIXo%^1b7KOTOgsEb=Y>f%3ij z|3bdEpIyEe{tNOw?|)0aP56QGZ94IPpucyYUB2(0_~HKH4e-zX{y**?$m3b$ z`xJQmA^zcs|Db&NJe6m4?#aP=6%$1mUrxgFWF23w((=e&(=ztp9?95+@$$&7qLMN5 z7|gG9or-@BBfew2%zf7xGvBP~Ib$Guza<~pIJ-{gnH^_S*69mH*T8)}z@O+V!lUBF zD!hMq+F7s|@@st-3@i%9;&Qez1|iR+IU3{KfpK`x$M}dWW2_a9 zc)vjNUb4s^qk9x_dC7Bk73L>zs`T6zDs&gD#Ci0kt;?2dTK}ODsbp-%d$iFfXYRv! zZ7=WbOKLn_@|Qfm{xF^k_`tV)*FZifPsS@&SN9Ydvw)WskSk>@z-w7o(f+aI+xIOM z)+*FvXOS%MR+fXdRMi$}(&xHGy<)s_y*UQY5}adD)2+w(em7|0emb`9=YSq?2O5sE zLcE^8={PIUR-i+%GcaR36EU(gCUu@`w`2SjxPQTYN$yfSm*DxJzII%it$DW3e|D_LwUT;+b&_XW z+`&{~?BdRlIrJllXW>EcV0Mk*{yI_!{_DKBpOLUAV4+B1id`2^6dGc4VWO@d#yT!V z5~(8WwsG(r%y21~04xN4t1wmw?+H+rc$O(;Nq9YAhKJ88LWRYElXqKJ4&i=CKn{$D zDTj@a8~cR5Z$jLhR%@ak+Xe0%9zq*wIQ!G)ICnWOv~j)ky_uXp=XVh2x!62`v)``E zd4>ubbe;3$T?FU(2O9_Tu8HR7~R)CYpV5nVJp}55blK>_Eq;P?Fr|obd0^GBqLmvsqSJj;pcdd zI1_7v`JCF37$e=H`Sg(|#nVc@KTRc5pq$ z6QNPVLb&JRe1+&1&fK$TXcRK>TVl{6k9ro$KGCM14n6?`U4L z=k^Y8BADxU=x^)Ksm1Dfhdw(?Ieu5=-ue|}Lpd*j94S}cYkh|kB z-vT_}Cw@I}IA^>&dCZM;t<^33IPN|<-csFXq$vMl7x;;Iue*)Nk9<=m)FWHg)D!9r_X6t5cU5EI7k|5D8_uTD zA$YcAb*jA{G&uL*SJZ*7G26Xb!z14`4dmFe4K_U)a3{Y3T8%XVIG?o8x98+DCF;X-kU{>d%5IP2-ggRg&9-goBmEHd?gaFX zGFgc8`OVOI>Y8o86@U$lgFSh~ytcy*4!{?D*GDu`4)s#LwDXR& z9X0QvR<>Oa+YW#y)53dAt?b*Ru2G)Qi4xd1-UBp!N*`bLC*-2<%%y*gJK@ zZVMW!4RHz9BLjSNsXhLcTBGPG+fF;yeg;@3<}%XC{AAR(O-0}J3E;VjIQERT>j>zF z;A5y4q+Ra{4RMYmn(iG;oHOy@|6a8<^N?P<591Nv=0RXA`uIQEaEA}sqha;9KRSYS zmI%{TTYsaNc~hJ2&Ha}V9r#&Znn3-9w} z%mLpn;~nRo2|n$8;4SDHeL3wfV}#nP?#KDpX?tPRAH#avd*`dLuK?!cgyG#t8Pf$d z&)hpB=yUk?_$l9DU#o|m(3Wm)wO`V{&!juNf33p#e-ZqE-0QPDfzM3XQhIF`^#HUZ zu%*LR2JUbbyo-h(z??eJj<7e@$8@?wZ5r1B{kSi3Z3WiNmd(>xW5&Xi%fh@s*1Q5lCR9Wn!|?On7{ zAMNh3C> zE{r)nd%RRR%D=R8v}tK!mavkt7Wt-RyTs%y;Yu16|4Qd9l(V7R(@&0E;I9eU&tmEX zVE*lfeoiXy>+4*JOJh2*9XhcL>$Du}uveo*uHWhVa94biZAfq)v&Tt$3M=`&#>l z;^WG%L56b8BB!n%!dQ_yQG54We*qgyO$0hzj1ujnlB&XtMshwWUK z;a(w$`_;2k z%Ri)HqVeh>uLDN@e8N5F6~qHh{<6MnDuNHyV|J;HV$64J8rez@PJG=o$X?fF7b-ny z&^XJqUT_Rs7eZPWHrY5@7uKSFYVi*4A2nr&U76FqaYuq@Wad`hr!0gX@VxLC^uP^$ zp)ULeHbOn%v;3XV3!X1dLN_ANi9?7ZpMzdRM~cQxldRkonNkPv&H{BmGrSG+iSQnd zadL)glYUR@$7Zyju+nmmBlaASDh49%YhcVLkh6buxM<{hkwyl1j$)1K;XBnDb*x>3 z{`*kBBSkDIgPxS#cV|pzK5FN_>?5f&U28|Ai0wV0Gbf=lOC37n6LC^!NH>43JGaVo z&xxD^odGY=xba(;fIizoCzU^q*lT_A>cQlx3wXL2;|39L`eVA&v35TC5q1q=)Ms<` z+Rn6(Ll*V0W9?zQGgbzi!+2MWzA}pWLl3rN?ZUn!u^@{3th z*;5RSTCUojOX8=jFvYNR7v5PEVi?ECw9L!=t#}kCM@k+k`;FjrF~%7Jew}=d0S_k< zFjve`@wvWpv%M%jhyN2ke+L`;A$)R-GxIrQuz(Ikk2MWyZD;CSv`4=8rEDl}&M2H~ zNXuTYji?8p1JU6;H+8OU2YzqTy1!A|(B4+{&8Xwv6Kj!PdmJ*w-?6l)Q?9kT&n9hi z#dclW-1Vp<&dK$E(lp4XAApP_+Wsck_}c#PHzBcjxjV`#p40EE!{*?VYZ$8p@%Lap z-rIRZ(O0<75umv+Tg5H`9lMxAvB&yDyvwWc;l6|Wu35hn`|i@hE~x7mL&hGFj>?a4 zUliiJ?xO6!3av>!yNiQax7RIWxPvh|fam(OvA=c*7dGui>nk zhVx;fc#&&l#~&LDwX+_lj{h48;^5v_T${oG=IL=HV}8JoHx#a zH4*G9q2_xjInG*)Lpb+^AlfK1eQzaw#=U5_<-sv&U-muL{;y9zJLFencyV@;vRbCs ziZm%t_G5q2v-y7&G;IFqL-q5A8hLNGL*M`Px8;KSzc197*~!Xxx4aK~iSH9gKTN;N z^-RM$as9GDD~kCE_`f+=O)_R01-?w&O>#eY)xjTm>;E6*ExQ$ON?&9w zBjv?C>ucEXRPe(+>3Q(TecQy{G-dfE;uiZ1^lZKea}O)Ry+QERal@WNj1q#6r)=pn z$a{VeF)R5;dwmMuBT38Mi2aT@Y;XKrwXH^5SHModk8kMFDSXST9-L)Dh4?%2^i5u| z6L%TyanH4YcL2*eUwP|FJoDgvggg9_5za*HHcM!ackozO|nNGE@OSmUI0Ao{rA&eE&?~X+D z{YK#X^9C;moUzre3DwwRGHaKE#)}RfM}e;xeQhfnb${bjyTJl+FKw||o*CgM(Vw!! zd8-Bd3Bd7;V8I5+?4-4!b0X$J9i;4-^In3v&EE*%)t?%VyR#0pjJ3I@hjHe^U0RF# zR>oy&zj#gV7o;H|yNI^wI!*WKL^Te1+xL0XAgOsE4+W^7#?>8uCs(TnGK*y;dFP0h@~QP7-5d|KE8(`16Br z-nE9nJJ8)EEouCu9vB zg*dwdc%h8R3-jTq`&|L76W#?znR8tv*Qv|t>x7t^cS!VwX_#LX?g7-DU}i1tusisn zTzJQM*y@nG6n4n=Obr)+EBy4@Y{<$B_;I??k&V+4egcH&JGIVY|`1;OT z-}!C5wl?qA0Ur4F$|2tX&N~*{_i;}SVlRM>>@|7@euWAcV-xtR0hjFeS@oGJEoPR^cchW-Y!b3Ez_ zp4)nWBk3BV=&O~4~f(%OXe zlyZXo$!F4_N!=no@98dv+_;YRdlLt=&G;4#me1qa_e|?PQom<$RO6c(|1D`-JLUP) zme)=2m-L5tmQX{v9f!~0n$vgkoJ3#Bb3T0u_xKq&rw8D---ACmh&}xs_)&isdw=N^ z+s9KV8}2E3J#A0Q6LXByZS}FUYDd}66g7oHx0T?0QQv`m;XlwhIS_`AF;=Wtzd`szFe>UY3TbnJj;L& zY^UbH_gXP-9mhPNc?qJ8Fq;?p!Z*-%9r!?uQb!-X0r5gGN&d}ll2{U0-2=K-1z*1! zd?_Bg*6u=|YQzYH?~9#dyVkw{xP-OhE%JT4!4~M>Z+1v3g@5IEe2zoh7tHj_(v+Tq zFRn>OxYp(ucQJ}z1>daUICHmvKLYrp@Yk!s|CiS4&X~B25p3CrZ~F}{!C2~!xNGfU z++By!=gSF$h9a(7fW5H&#>S?i*R&4q!`?+*uEL!)eLTxHt-yCqT2^fdct3*Yp0|PC z5j>0ga>58nGYj;%9*h^Fct+x+F#xdoM#d-|V|(9DoI`m&jM<64JF=hk+4n~_AHjdL zQ|pa$Flq1Caf;Mq4P#tTuj84Yo?&jZG4|c1V=1XWe^c}r3)y|AYCJ#rc8nAHNaMm5 zY}^qVm+?uxKHK)zFq`)&pyNMr<&f2Y^Nwi+?)&UL^h?XiU8C*%A;9S;@qAj^IPIJF zi?)4#2ixaf@ngttE$o~8bMHTd`=tkH>z%2yusi6UjMrfcXfb=nB~C8KRL zXbgo;2N)ZJPdq=an-M1_Z?L*twv*4eamSPZ{lfFSTm!IWkRA4%q(_C(2hWGYX6BW* z=HPiU_3em^nfUClQ|(dQ;T-=5))@B=>~|D*ITr7KL8o>9-iV)N-DsPJu{uF6A^HeQbio;;E)zU-!rx0@2j14}cr)mUAF@xM zBM^he)`9l@-=MP|{JkgTL!L8hpVY84z@CTy;J)qTIhcZ&5`6+D<^=oXJ8h8(!x+CV z7>4KahY)`p(t5Vqp`*6#(H2757Ty4!dM2A$d#@f>U`{;Os=MW`wRZtd8S-9-vcARa zltkZn4dy=uHb2}-yUfX7Bq3+834BGjYwa@ZtBXK`bR!dnOFjkKqqwV6v9!`l%40t9 z&<6e-{y8H&3vjM?eat^{56K9Z0M0X!9iJv?e@D5HC(6b?7ujphcsnA`Ma}W{2Ap51 ze`oeN>K={s?6Za}gP*`(mEEt?a>jX4`VsmJTgF#um_0sYX8*}6hw$!;YtK73&h1s? zTx%viOOk#7&ydoDv8p%!_E)5R0-T~V{ay^uQ+90d0DJ}C=NOf$;_heyeltU!>qTxL zS>2HZa7RiXf<=+<&iG*;oRc5CiNG%^{ShJMXCC|6-mgX*;azV=zF*+_Fs~BGU^-<0|4@p#-@&<~j5H9kk$3!z0Z>0CpO3)L z7N@GexoiRRD;VFk5E!>OfU_jVor>{du#kdH`cLqHd$-g0>e-41+((j!fleN36s#X$ z&Gz5?dn}CW`(kaeH{tI>MXe#0?TtPr!f$^{pMc-^!SCG!;m_6IGe7!}eRu5Cu{DrY zi24G%S&FhBvNpx$z44%xy^j0%y1gE;a<5z5jo&d?xz`du*=wZUy*Iz8ARK1`&)ob) zqHFWs1lQ&-JV2hzi<2as+C>!Wt z9oHf&*ctB;c9v(q|H3>tFF($!)ZeA>GhZDM;imzozd3?=F9R$KX&2|5Dn1wRU&J+V z2IPIl7Ql%|d>i*!8yEhMIOV9%L>eWQ75d%s{lz-NjKG$=gcku09&&?8Cx*~}z6E>4 z-~8rA@Z4(C;6USTIN#vi>Du~-L?h=!{j3KM6GTDy(*6bE0@s-EcrhkCF0~*$HoYJ` zCN&ryog4^{g8V4Md|`$uquO(gty{XATYuis+PXQ#wRK~nd+P#>ZOcjd8zn2sN%7Y; zJW2BxwOaBA8SEvGFAo-tMc|Qtr)={$5fkm zyC5g*b>0Kt|CT*X1R7U@mVjTl1Ucoxb)}560$sy*0Y+U*!?@7PL7l+YndaxD zSFP#go<^@rcp+enM<|=Q$a|qq|APL~{-by&(*FIz?-93h53~O+oMq}=D_dw-vuUu@ zJ^0dwXO;~PuQ5CP0e9l^y&s;NPaw`-^Zn@6&wYaP9iA^@E_-R4kKI~z0&#LJVlC(g zz`cmv2w$8Jk;z9k!qRpGY#}FnnQCeO;cUJLDW%K)0md!1` zW%S(HW%H{6$6d8(kJJ$fv94%p<8$?>!b`6hf02Lo{G0H*w=?{bihusXc_n4gZy`pF zF1qx}D=zX^FRYxe8hg#~m(NdR8$V}mpE=V;0R1cE07d2HH_k2d&o8g`S1qi-Z~Kj&GyK)%{;FC01z`P=e4(uIY<6vYfu8}EpYoYAWnNug zF}u`XT3(4?JN7S}Up;%SpFbY#?=?el1_GR}Ld)rums>R)ZM|)_#l>g+B%)PGLkZm9 z5}VCu`EZb{i)UA3Kz~&keph)$m1Ys#;zyrLtMfoyl`sWxUseg3OWtKa;P_{iFRc8* zy@V(vJ(8Y1|3(UzzY2}PD{oTEY|C|A@$9)+7$8Un*r6|qa`j8gXOzX{m#7zFVtG|H zcvPgpqb4o<{FD|itSY<6->WK7=-+|%7gtu!zNu`6YM0Vi?ZBR=ekvMutcJZ1qZMiY zOvxB{DOD`!Ar-H!Cjkxnoq4u`zvGT~75;Od%O_8{@=Vmq7gpmp+=ZAuUuI&=*!-#3UT7pYR?IH< zSInj#qnjv3A!g=+jigsnI`6`v0|rf>J%4sJJ%gXW0I!9mJcSz7#;Yi+oIRbt=kE7c z6wjCe2VWsw$7$`;=a)E9TD0F>IlH(-)|#31SLTfuBKu0rR002{umDcwLkt_=ZCI+_oC-+{nqo7aj%{G^O=9` z_`p>M2LJk|uTy?@#h>ziIsYHsAGzVrm%McQ_r}suuVig3KGZ%u`OOQSTJU+oU6=l@ z_tx3})9Jwa@u@De^kx{E_}+$oyXD|b2^5+EAsx&gAe3ukWb>K^#b@nJ_&gZ;m9{5 zZ$Q2SdFVyZLEaw^>H6ZLIEs80@|u@19`ZnaQ`7s%k0DQog+^WhUF4H?L9Vn|Tz2h7 zUWfc7^5E{KrlGjtOZ^STMLr4n3gi*w>yW$f&|(L2KD>CHaO9sN7r%uZ@MEJhkf-xU zNB3YIkf;6*dVqWd@(A)8rG7s$V0f;*^ImfFOzz(d}EJT(>h`%O*PAg}oV`ocQ$2=X8dibj9UwZYf*QjOR`VGa5paIZiakhtHSGx@=Cz$ zc*Ku-0BJj51<1vy6#v7nN38tS<`sYbU>_uhH9?wz6a@}UEcU^@v{-`lI^a2k>b?bk z{y_F)`v#=_Xn)_)zR=PB0^l`|L#MdGj!NnOu;&rCIb9+60b;-7KgV2=qkYoDiH{`Y zuZ{-^#hagS^xY2s!rZ2DyB>qhekA;UlBj`indHF9U+pp{X+m9rQ-HP?wziZ5+GBH> zh4!OpUjtlwoKi>oO0-{t3;Us}UCMEyqkRk7E70zgvy=WFw68;Z9gnA@QjQr9cYmat zSt}`!zmL(L1OIo8gMN{NemwdG(LT}9KH1TZ=R)EhwAZQjiicAkIp@cY_5!qbg+Fa; zEoY&3chrN%quhs~FaSq#n^C@sx#vG-L#yWU-9qk{Z zz1q=!oumCzw2y#q4>;PPsB(?`fF)xOnT7TuM>}*GVo>@*{qGN)b--Eaz$sX5t}(_Z z0&Rba7?nh|Ktb6|5ctP||2pyUp}kcDR)?3gk|jjJRsyySuy_sQ95(>A1+V~NV^dNe zHXkv@Ip*^M+V`Mc>dg3-?HuQQw113trwtzi%=MIBC*W{BTrf;OV4G34bu<5d^8sVb zYS$X85EFarfSMYlrHb-QG6MbXK|gI@frsNCi5s)pv&KF8e%Axmn6>6QV;VZYebDZH zWpjo6EkXaG|J~FyhU4NxSPfvaTER9076DAoQ{(Lb>~#l>^5R~80<#@vs-e#D6X%9yFpq2ze@HuSS~nJ_`C*?~fQ10lw$);PW1p31--h-e%KQ+v0k9MHIH=P;>HsT1JX?pd z?W?4HNMF@#ANfhmzN#-!KSsZL^gE&Y$?-?iZ_kEFDdz@*QhwVHoJ_>I_aH8=cHoa$ zZC(W&xnGdK5x{vLI8Hx439$WuIb}ElFoD?G_8a|CT?ANvz&0!Tww*Uyd9%ZnOmXhp z&}R$!6ksp6{mK}++R^kY(%)9J@V7v_2I(mJ)iajI{)c{Y@6NwJ@qvV~>s=erIeAUe z+W2*GlOA$E=rQx(edp>wfAHS>F|VCcK?I@`=|Rs!Zua8-9{{-k;{5$M52PyE!H1I{ zNy>lF^$^G=u1OesfBXY+`D;Dv+>_Uv74OYlZ;pQt5#BrR+SKJbuK<{W-55jPIhwxnDu?fE)(y(lg)>JD`uUx5l_HJpV>4RImHkGb z-=f`ESJh9gA%~I*S?w4Pk(Tz=e)OwGzZEzG%|#h}N?n9*0jXKHcs_a^IFpEj5A|&u zVDUI3vCI#349~RWIm+eWL7KuiPCV$~;W9@VHj2I{IR@w@JJxOtm#u)y##I}`l`L9s z&V3JYR`aTjN(mCp#v;;slPh2PUI289u#h2~*+PglFu#!TaOxxN#^0a(K+^ctDQnJI zo479F!T5*bMz8m5aGM*z)_dv|(x1!0bAfIY)UD&7Q-QOgQ%@uvD9cnzN!cFaI9ZbXE?4dcC;; z!5Bn7nyVu1%e?h8!Hoco2GA&Kz&TRsgS1C!iqZ-twef1b%m4{E1wRe_Q{mk{eiORs zu!Vfu!uSWQ`(2~gn%5q9EB|d<)F}Zr(Mr~ujQ)xf54<(%ZCmDN8ogEfgDzr>dS@2K&xDgn z#=S+VL*7ac)|z9f3RiJ$+tPz8-#U;VQ-jt@GMXBsbwv4pj8%uRR!|=J(7&z2mml{f zHp~y$Ho(>a#19TFLDifE$3b12|D-Lo)W3d>3Oil&wkj%`sF}8+47cGR;}J zoE7-VuAto)cQYe!XVaJCk5O^Y7=1qI570!k7oeT%2mYGJmWm1;U1v;zUh3nJnr8@o z)}Rkn>i^}({(ng$kQYB(W`4Hmf?coI1-MN43BtedqcgGl235!3?#Pe*|DW>NH$Mow z>$q1!E$6fteBi0qC0ec@^|94bNXtv*_flb2I4o zP19WsS7!Bv!B{z6rvqd?g^pHk$KEU-fB{?Qci}kJM;v%vrwJ@Shke$1u!}7J5ix=l z>CCb_-ns@Z$l9I7nkW8!e1nI-V$?X6t^XmXQ`>K5`3>}Q$9Z2sIiAlaQay?BIS_cl zcwEMNl9SmW5^e{3p41M%Cl=?r0uGfD8miNy_w8!gdSVIpyZ6AlnP z;W(riH$+xa6S`qqaYJP#GvO<=#|@Jef5KkKChj6x$w^3uONtvVEBzA=vobx1vmBr6ld_(p)iK4{K0Bwnz23#(1$~;Uvaa9T% zJn=`+(K-xpLT1`Lmh&)hLZ|c)%TI&7gwE;rpxkae(5-_IY(kgxbpWL1LE=fJrgwp) z!{*d)(Ko5gY%eQitjtpFsgpq|X`b2T5s5s7$k|Yaq)G)!&4s*@Zq}7;tSr%$4VX^S zQeF9seSV@V_+dejv`Sa*Wu-<}c(hHrUsq1D&qJ!xKF-AjOxkD~WuWVQ8FMhaL%^x& z^+GI`_ac0|ysv?P+uH!R$BW<76LH>ifFAFC5!RC6{Sfd(Vbl7+G=4!^H{eTn5&nYW zW0J~q_;!2W#J9)GCvb7zZ}4q-Q(#A?_e$6({_H|?^mo(vBdOqj_`!ECU>M&22EdGA zbhnJv7}zWKZtq7BsNww@-!88kGfeRg!FN0FIDEJFPQ|y^%Nw5#-YR@|^e)49hBu7w zOfR3JCVG9)$^>s7zB_p@#&?o;BEI9j*Wo+P`!ytBdgH;Pa3VdgHgZR$$R^mI+n+bU&cy9sYoxFp&uHFKC$9v219p_z& zZ?`udrswf?#&@!pr<-%Um*6|iTY)uA_3{~KXRH&VBQJyU4&L?Pp{w^ve0TG{jPLH= zH}UQBP6m$Yor!PDyBOatZw0Qfpj<#4^~xp@mtSW;jbV?)B9Us zyF?maMKF3NC0Og0f<=7NZYCr*F~J&YLsk%y2b}&kgfA%=7p5mz0UPoZAp-y@upuuI zG7ykSHU$4&r!WQqa*Yi+NXTG7f;QwsLWTe`%ZA|1Zea`sq{4=T2^j{+A{){~$VGsJ zY)CRhWDEynrG}(G1R)#wsr`VOVAa{sX;k`g$)hpz1Z#&4eG?)wF4MR*8k)?mX~37h zuSujYp{OUOS^z;3H%jq|4naZ}The1CSle~yj<<05gB~|WGBO?lDPyjx4ZKeEjI(RW!kNOj%acLcW_VGz6MEFILqdFk8FV)$nalA#*%;W}C^Y(uZpqW+n8I2L zf*?VRJ0->i!~oh9^bp;8YCKZn&2clOp_E|xZP&x${R^c&|?w zH+YgrL}cv5moeEB$J()L3BuKe%3xu=Fkp@(JK58XWGBJ+=#0bDilc=ZsY$1_6@xFR-S7kHGM4)LB(9D2{aj#=G>(E4Cbu4am69YS*ORis~ZinBRz31Ky;GB$AGgQ zNpk4%z>gvIo%ByRl(Wu>(T$SsC_U=}kO&}2n!iBd3DUIJuWd<+-XXf!G>@l&x{r^% zP(*HQ=#6bw%{t8^*ZLFCWQ3RV02Lt3GmxUV7k8n zWs+%rN%2h62(Sc_9pJH~$cLiyKqM)iN)+ZJ^|co|M$J|?30D2XW_%1M(Wc6l~X8u zgXG(w1s~%gbEX;*o5o}CXNzJ4?NV3WZX|l#u2j%_3TW4X-yb3Me+d;cT;W@z`~6JY zx!UvKB&7T!x)qxe*-ZAFa~&yB{wqNxgp|h?DStkQ`WDG|LidXC>X3gfncb}s4ADOy zWY6)KzpxqX0g3sL^4JpN@?cwBDru%_;eaF3Yv*ytLHbgf#h`T^l9cANC_IJa>)Dnx z;oahvi}>y1duBmbxKjONwChPb)#H|Q<6))NL7Zia$#4R$O(4}DuVWlw8c0I>BYk z;p)$K_vV$+JWwn}%6S6#01oBK@fPVY(f}Fc&UY6O^Hm7(d8C|0_yXot#2g3_WK%)X zu+YX$NuYC@b9Vm%xEEu51XR zJCZc65)^Jg@?E1l#B|Gcfrw1ZpCC#pv=U8>BB|TRrtn`3>OXb6yMSv+eFKQCv#B3M zVK1pypN;y8cu+T2f?>IB*K1ttA0&Q{J7ErqGg#@>S%@A;au1n+LIIL*e@o)#UEp@I z`BT!Pk2$HE4beb)_qpA_vzc9h?(;~GyTMZ^JV|=#MM`#O6vYZ9ickpDsl|qb(ggu7l5a%IAg$B zra|a`0cnJ$wqVn|Cq_d~dzv1?630j);&#`Q1UJEQbf1GHr@a-0$4PHdOP&%ehXz>T zMIJ8FaxzGv+Q`s=k)XcO?d}eJl+-^2u|qcXUf3wJkbG;-LfzCtT^iEUPu5d|!y)x2 z-R+7=ozpJ{vFk{1md4Sm1pSGvIwiPWk7tSqNj%|B*=&>eCA!y=#Icqs*rr|wlG@6Mgw;=waJE1)do$<;TkO?5=u|*PJg4(Sl?z)QH;rAMr%Ck;e#BDT7Od|1D z-6`{J;*WvMqa@B2N&G$3-XZa>|CD&QzS{hMUM<9ZAj$I<^=+~l@25(~`$blrUb8!= zf#wWNlO1Bn#)ZH&E=0)iH%#A1Q@f0~Qq4`iF@d77VVxh_#JSkLfYSE>K=D2yz6Yyn zLrHTFC-6=HZ$la|w`@K!FXe{v1pr5p)P~YU?Ff&6UJa7kP`WDMxejwB7fNKe%x zLPJ6GJh!_YZJh2Tp%?BPk)%7h6os)!zPY+XY~3C1M7n6_hGHX|qJh+VyWP@1k@|8F zyThjbG78U=`pUCWr#CG$F3_CYs93jQpxp=l-{!m#q`tCg4?7pm70I{xY_#=OC_T(mLf3>kpQ9-ijyWO|jWIqCxBR1Ld z&clv~NA$+qgGjzv zXCtm9yELQ)vQi^s-AH|;J0%asF9mWFh*cuxu|*2xm#A&y5F1(!p||q8q(B&CM07j! zf>iU}-B#FC-$MU4k@DCgsh*RIhXP2x?f-=8n#mjh^x#eKeWlw=zbbhhivInP^4KD& zK7iU9Qmxay^x~<=V6qI~)E@M)9@Y>+lAY-8JQQ9{l6?^bc9LwJP4+9)z9iX`Etze( zO*BiwMzcif2oRs@PPpGD-n9?>7g8QuB+o^t6(af4Tk_l%aT^VL5Q$&sPN7ehoG%8M zn@OB4lK9i8Jw@Vue;DzCn6yJAKGxl?z^{q_8DtKSI9nv~5q)tZkK_xsB(61MC6}$+ z7;TT-sOEweH!JF+b7!;lQSNNVG%1HIFdaLA z+Qjy_{M^KD1b@?!)F!samB+oM0f5(#)F#&8lE>!D&c~jBq&BfP6)*z8Lj=lG(Ow1o z5`fPLl$Tcf6tG_&?t+liCU(FjkKM}vxD|<;*xL&9H&mmj!^^q;3Q! z$jJzgsK8ckeBg5b5!8TiM+PfF8L3?VlIL(vn zUtI1U*oY3d68rpTMxJZ>WAc8sd4OSs}mKqPM%I?#YohV#7DRQ zL+l_)l%xA>lGt!|5|eZ@T>L7{ zci_a@o6Y!7ocvN{#)0u_V)Auq!Z$pcW1I0(R}LSEdz@$M46Ooh|->Yo)#{gV~L^G~Y zpvwmfF%n6caafu0KLGeEl8g`T(X;Z1dRVOSfXls}K^)_QNkj0CDUys2YEZZb$+uZ| z(E8jmKDgUq%?!P4WK*QVs*H6m_X(T&??LP}o4N~;D*wK~SARC@cgo9+{ey32Gyd zeAO+7(DyNSa~_iC&AJ_{MXI$f&&2aI&t>Rej3jy9h{AdjtZPNkanz?dhhp^VN$&}l zZxiW}%YUHz-;nayBDp*lVNy>dpFKBQu*%0NE=l#ErV0-Q>oA^jB{bPoFGv4Nk@DCg zsosg&a#B6klGTNu~LqsV=O*{{{FBSz*j_d5niKR!_<9 zELWf5n8Stgf`6X!QKC2Be=&aK@-&Q9(}vB+kFnvBT+E)==xEO6h3f|x{cR-mh+w*+ z(C=adD@bx4M>P>c)F3V~iuF8}p?wLGoX6WJyouEJghoEoJUnI8kHF+1d;NH)^7nIylvco z)bDmw-bLX6E2~iHI1+FDAoW{^%2g;7BArha%F&FtL@FXTqrKto^9O+ML;KH=`n-(F zUKIYs%G0Q%1n?dcQXcUKy$#4<8k|kXBZ8#!nYWxw(~1j#Jcb?EAWb5K+U-cbg4RNF zn#2l$&k!n zjD0nd)TA-GGY-qtq>Ekd0g#`ZEq;+(+>az@`yvX@BjpiI&h`juhmhoKQ^80IlAP^e z6b7=w+1`M{G$h|OdL-qP_%ehc=UQ)oZy9sVit$oGUh-YZHROc~vJw_i;GW`}u@Ar~0*z1-j6i}mtK!6`a zCW!QMZf+-=&u5@G4>Ze=ayqF#!^pt_0A5E@9K3E7kb_C^$OTB5KPRO>TJjLM6M$b4 z_;+gFpA?Ys>0qSHLs(|x4F&ui0Iv}EG6!lZ8l>iUU&S@8bbHpn$)gh#MKC%wHt{ z__hLGd^w&xA!W+-%;E}m=we{qg6XDj7ars%Y8km(nC)}|7(yW#}A-z zAChmD?w~og!WDQpHQBt|Cb&fpXov_29=F`Txyc~B*DZ&#IZ=e?JYUf1bMZk zC;obj;xSVE&PsMeCUWBAKp-C}k1cZIx1+WM$@ghXvMnag9q(j}YM>9Op0bjzyHHbo z9Q`*U<*`Ll{Q$N1kbJ4|s{H8LYpR^QTBJp~9cNQgZSP8c>OxJ`H3djWd2EqXN1%2Q zl5fo!smeu?59>GUc0)u-HO-YIXJ3lG(@Bv~NpU@D50c`JGg6d%ir%~1fyg?`Q;qn7 zANlvy$c+tm4YvKxIxClcXAg+Igrr=|I%^nR%$OqZjig-6gUTPg0Kl&alrH8W1w3ae zVpJsMV%95Q2>{awlrCn20zL)6lStCVJgi`!p#BkIbTN-AcQWiMT!telcM?&ioqsh9 zA4z$RjSBcJ0LKZGo@0{&UVaT8?;+81Jf=V|qxvF}@*JC;p5x~V<1@4#L6QcuTMG@Z zd7KB4ZL`cZ1F^z1m^DAb^CBdv-+w~k_ej2jy2BYwdj6@wAP%Ab2S}3RF4rL_Lh|(tNc@=XsORp~a!IdR zj|U|uy?V>_SDW5cbf1hQ>D`OMD$-lgia|w>IxhX?%Gj*?(-;57N*n?0mb3mHy8i|# zk1cZ6#x(p?Dv54rMbt5CX^M6`WJ#)ftVBsM2mSd1bsnMp`Ocm($yawqT6ak)^u80J zg|W=?RN(l*kNklI`Yp)f+Jw9Bks3=wC7@C``H-c~5%cmsgn5Gd{KP6eEJJ^Ue( zvbUco;2#0_4U#mipDNg(8z2fKwL{*e^n3>Z+mPgPY`a*ph2@Q&3$E_9%q2t6hs%5Y zbi8VZB$s0?3agQP^}53u^?W&qNwPK;-d&*i)L7<0o9vsQ@<*HOIYB(zMDo3VR?bF7yBRB`+w2xwruQPv)fmvqN0MCq7=>9#lA-%h_!%pV`VXM6 zpA|B65`}MBAwxY&@tzoxFM39XF2xc^e(Yw%Z5lDgPl;tlYBlf;anu&@iXvaz!2mS*KWiUVy;uEWscw)i4nXv=#WRC z9CQ*WO+>nwgIX7Jw4oPs+M;i&R%+)0nDI~{_~OSCL3FI;9*qj067n;~P`R;TKU6pK z&3K@USFU0WMz{}2d7lCW{4D^l5-7dTr3z@2;k8}>rLsjdWkUpdf!LLn`8gm`*)9g& za3m?lQWT1j@`xsDIKPz044^ViI74mM~h>?*b?|o3{jpW zvR@FJj3ha_1%;cDBu5+nKi0klzN+H*|D3xyH!mIm0t5wf6F^YIO~OObMh$|jVnln_Av=0uI$A+!fU zWa@rvGSP37{WDobo)>LSg`jBw*5-U5=K)xo+kxCd3DV}TKt87gY16qLn|c6ib0m%PFSlUU1POH)k zYXm(NGEY^Jb42D%karz`$ND#cyavdR9Z0s`!j+ggL|C!NBiYl<9Flt$PKp35cPfxc zfc&xp%GECm9BAnrMt5f2n2OS!3i^xL&irh-EG1&9faZzikbD_HpE@0``|U0ewiA)x zEghkWtL9)t1MpgExsj}#l76UbsLDR?c<4(j$XS?ZW&q-p!!zq!NWB3lSY=9)*CB}B z)^0W=9FUWs;VSYX38Ggp&Rq0o6ysMg(~+1A$d8#OHZ6y2IBWV6q=_0yb;aO_W@C86e!9lvgOXkCRKwe84 zI1g6*2LF5z&H?aY^LkSoBCIc1`Y3(ayaD;^0DRbdOe5C606uKq2IMtBocN3Bu(|)Q z5ElSGbQXEIuS4>_?E1+F6r`Z41j{c0amwJJx*n-(0r^{u61FR+EZ6wZnJzxjpX+QO z*F zu?w)f1Zcl@(|-Lu2-gDGg=to;-35@)-MH{G_!3gj z1K5Qk4@=%c$osPE0I0++Ooz7>AWj+V!sC%T7LcEJAQvtn>)3?@t*-ZzY~#XNkZ>k| zU3e>yHbBvsWRZz3JcHJ)9aNMq7}8${{eTNUCKvL3{|>6~O_2Gca1g0a96G2HI&q** zIS^2^-3aJ&(*BQCuc695h(tGFyGMWg)qi-pZB$Aht9}qUl#VxAA@f{-uIz&de|qmV z5H5w)Y z<&OmD!M4>fVhg7kBgdZzMjC7@!SqW24~{nixfYPW(ses-qUcyMX+irc{_!)VwQAK2Bsw>b^+FZ6uY(++U&m zT#~UhNrv9>+hLn81wb(z&5#I3bvk&o5pfTS-$^2t3uEap00qOQmD~W2LbL~X?6e}CFm+n_Sr@3aHWH=VKJ-@?(NDMSm~ql` z)<*ii3F=c&_7Q-7A+a`6OvHibVrl^B?zA>?9QEBRLAV5x50D0%7L63F1L%j^bdLq&<0=SQuUbYx}5&*Z^CZjDrO4%DMFGRW&jWKPu6FeUQ z;*`T}Htc+Cx&irPj?}iaL0p$Z;nLIC*jnG=0nUJ0QaGLfZR@U zOA_VE70pXYAoX7UnK+h7pIU&x!aGPH_1^DLehZ-;893IMRrPDUCIrMO zht1lG)D}RWnSts(@FM^c!x5(CuMIGTF&I^s7!5F^9|8?ti{w_22Bd0-3ou6k^m=KA zRds`AJp5W>q`rG3m`VWo%Me@`FF-+^DMj8wzog(>YDlid z^0Z{fT@@)P9&cKAK8nu;=q|9*7Aij&wXceJ%ZQP>z;$4{8o*uPH6WV-`Mr&wZPyA; zBNx$bOE2JQOk874Yb4=!MmoJh!YOnHVB{8e_&c+q>m`xs)WN6~f2;HZq4d&3gwpbEoXw&11{8Z0phM|W9W}X2@LC_h%gRMY z2v)njQ10@GUYS=S|8xK^D=z_Z5hdsv$kRX`2gHe=mz6ocMXv_%vQp$JCq@DHW!GOr zCyuvqU>OaFQwGP|g-Epm^6BCw{n=&@j;N^1EGyfruB{~7EGzGVgxdkUto#(n2Y{mW z$s!Y%mBr-4)<~4Dg3;e7{eTbKPKFQpw6rzCx1|PO44nb`w$z0YJ~f>W!W_ULV(({! zU;rW?E{Q~rxEtg($iEv9Cu;G-puB_BRw_lu1tq2wd_bknhv(^t{0Pk00|0E!Y#>#D zqEQDlr}WY+NH{kVb)O-1_;~l+NZ_8-V%_r2VGpH)u`v?eSgH-~VC~+6lE?KTIgJsH z9ekg~VRc=Ro`q@Mu%rF?&u#l-1^N&j$VwL8TVh0T>m%OHr$Bo;?0N{AuLba7&UPU0 z0OG{PCpz4fmm)zYI>kT+QG!l%rU98k2|BGiAIN!t{AQy>aDY`4M)re7e8eRA5l65b zQTMEfH)xX4>Nd!_1;AQ859B!jEA%ChFDO9@^~U^i5P%gr0Z2I|NTIWU)B*CBgeo)| z3b8(t9dQJ+`pk)VkBdIbA?gYM>+=whwE)&+uK1@R;*Cdxa;u#WQRe|zpWA@k0$_b!1o9juNT1G^w)YBCn6@{#%wmxG!QDz{r*c9Sk= zM7)gq;9jjm`p62Vjk^266=@NTWA_Y^4Ngv=7L4lpu`? zm!nYt`5O{7(qG1PlxZ=^M5i%qxuVT4B3=%nn!E5A2pSDwZRP=K0I)XK0lAtIq|G}( zwo!t#!4H2s|E2_KGXRPHfc&i`TD}QTxsE&>!w((G?lRe!`Osh8D$HTDxSNEc69Bxp zy8_5%B&)1c%d(M~u(+ehr1MQIaMpE#tWlBZmWjGRiL0M(+o{tr&fo_hDVx7oXA1;x z1Pp0x!M8$Z%CzbWc>%Sz9->BkoegOEPMcQVk@2iN()lI0u<9r^!tF^17Ky#jZD0U zB$+Q5W&er%F959U*lV#c1>{dUfU=pTmpG>!1a)a%)h?WF^^GAA-Ek3b$*B-YF1!fh zE&#+Shh6v-QjY;xs~TI9KH*_qn0p=0)&Q*4WFQj&`HK&r6^&WYhP)?i5r;k~;*O7a zMTiRa-t7=`3&|z#eGKG1K%Cgvdqb`VLO|Y|52PNzdM-0nM{p1p@ZR&te+IyMdN&{k zP;~zf>e)wHm_ENZ653%I?;e9A8dH+Un&cezLMFr(MWU;U$wCCBeqbfK?ljpL7DWco zdB{nq{bzuI@98o}5%FyhUI84wwh2p4BLp&fKx{nX4Tg{-{(`KjH#*MAfH>t8zXHl? zq;3VU2ez7$uG2^*2b%c#9{FDb*aN5BgoA28{!YVedvYMyy^EaRI#`}V?&YXtkJX62 z$HFbf2yr9GDX|HAn9cJQScEZB zf6*MS(UEtB5${1vkr)@G8n6o?Pk#x4e+96UNBjX11UQB^AX3D$m@O<0Ujg1L0Ic3; zKz0C%mi!3y4r}zF#6gkhj=0unrYP1%(XR*bgK%;H7a!FQ0s*=Gph%o(i;!*v9Nw)N zZ&t0_m*+xipGf2%Xu2Z`khL8=?*QVIQyeGel^DkX#Xm#hFdzc}+y*&D3}#O-yS+?Q zO+kJIfQ`HmNGkw;gWiMtVzvyvaMf}1;nlx^d?#3L2gHe5ycd*Lka`JF?4jB{K>h*X zYKyFh5)x5hsy*Zu%me_gb|R4RfFh|crRg2|JFG1o625YyIc9F!z+}+cZaW>pd|DUI zK8(H?s}ZxtDB|vMyA#i`x8h6_5SxaA<#xUk3|`_tw`;^Z z8uE{51l!Z#e-dy6eGAjSf$RempN~Y}+i>hcFu_QoFZFT?N&=~)7nuav*8q_i2Jtnn zvvfUJqH=imS!uZF8`v(@Tu>d^mvA318$s~!P&gR7zcw!0|xSkBHwj~(4cz>2p0kL zxylZgkLWgnumQl0-fSde@j$Wmp=oqFtoaT+-00Jgr~ni#G0Z8Aj{crOiwFJPYfjG{ zT_NjbH;Z)GF-R-zk7qPHYTaLUS@&xo{BnR+^L4G}|AO!}fG;IxST%QagXpbp2R^GA zayyz75GN|1)yzSv9*`eP)>Y1GNSo4YNWo{(0<`oxlvircx`ouC52eoitXoXD{_xf& ztp$fVOtXMIK9F7K@|(G5KzJO$2WFd1bvWQ6 z1s*}ezK9-w%AF_(-~+SQfxJqI2a)qHAm0Mw#P5G@O5}JB{Qxcw%I<{L`k)M!j0VIh zLm!kO)e6YpVJf$QBF?AH-Nobp{R-Q#r8&DvcJOmk_dv|;fT9c&K30^>;Uoozj8yPm zH@f=>P6w7H6V4Rx-s{GwUG_oT9)R}lecHPs>y*nOaP6QOyC5uY*?zD6iT;)c~k07a7 zis=Vp_wH)(?kXL-Z4kEtpuKyC_HNo54826;*u7JGcN&Nj0ouE(wRc|x;b{PSx4~4W zoDH3!z+J|>)9yt<0DJdsAa7BEysQ3*_(dX4{JwWZj^~u*uy?DWHG6jw3QPdRDTBSc z6sd~=`K_k%Q1AM&D{N`ba*`eN?gJ2W51?puvZzGw7Nw!!&2Du0;o7bDTkmGnig$0; zu^YJ$<1s{P@3w32o&{nJKznzk_U>aKJV->2-CMMG2SM~<0QT-CQysqjtrHZu)p&O{ z@~Z*tU7H~9-UjN;fH?8{-W55XLqE-p*nO(Tcy~9LcToY#VDAom03$0Pf4iwX)VqG{ z3R{{plVk_ITLCfS0Yw=H_U@lEQE-JD-Eo+9s~@}gE@rc^TcPKlTOsZyfcEZn+PhhQ z!Ws>ry?ed(?k_=@LPYlN4cfb}g77?mz1zWhmwpPsz0r90mk**KfW7+xkoPD--pyQ# z_yxp?-}kP_@%RVj;N5&^&9VD)Fi)le^h-7An<2FQ;c$h&^*3R{{(Kfa#e-G?FO z0YK51WKoH+`>BV5zjLGX`2zYwYxAGmwsE$2_jh_e%=j~M0NT4(YVS6Ja264HWLU1f z`xFR|5RtummGCtU3G(h;pxy?E6Tk0Wk>fe{ zlbkQRo)4|ryWfEMA5?%c*t_wE;SNClVpI7K#ICTRcT)reWA{{usUUHylSL(Zm%iQA zUE)St2WqeSv0GR#-d&<&cQwSV1ZeMGti7AF4ll0(+Pjx%?^c0u8WGvMOSO030^t<^ zdv}eg4wGdz6u8uQx9SlT1h98M1@bW^$h(~%Mf?Kd#P54oh|(d8l{&*cG-kXA8*=diQaNc^FW%Gg(xkcQ435!SmhdmI2zke(biM zCEh(>$8M*`@EJaU_U;ARy9+^RBqGOdtM=}5AUsJ#_U>=AcaL5Vw*c6?8AdDR?8t-y z7aH$2A%8xAy=xQX-TOej3lJxM-@78mb0%f6caMhF9J~9#yq5}4277nt<5kVz@^1GHh+jaQ_28g*e#nY-kqysH}@&L?*?e^&ez^u48lSp za_ly0@4f`WGel(X{z`lI_`l!`2Eg83ZK_jFYdREIV7z+{@>>AxU7H~9{u$K!0CD2? zy(@A&XE(|Dvg_9k#=DWHu~ei2l)>IT29)7|{Pm{tQ14zsZs7H+Pi-2-ZW3VTccxlEyS$>Xz$L_-tD~+2buuw-Pzi^b3v#j zB73(^d-r1y-UYCCcbV!it3{zez47kcXHXEp-u(*5my{sy9{eog7Z4|Y-@76Qvl_|y zvg;IR&9Pet<{BzM8SLGaNc{njPaguHzfkX9OgZdbVZ--uP|F3q`#i)v4JaCzEGp5v z+%Zqbp-_L48eB8%oiE-!UB~W0&*A$(0NT5i+PfEmu$YJ(yECa@w0BS3 zgfEc=uy@Cp>aY{`p!u1`yB8q;JOF#wCdj*wf%<1aocMk3iX7~ONzRvDAAr{E-Hhk4 zR0PB+gS}gh)Nz3P8U3}bq29fO^4Pn=mgejr*+K8tLrgWGXlb&jMDPA44F!MhMz{9U zH4fJgjJwx0;=F~=;(zWQPDe72LfoGK+Pl-Wck^Gs1uXy{3+*&QTxSP~Jq3brz;>)P)nQghg91~G9g~nh0l;=#2IOKu(MH3Z zVh42XSwaSk)<;_9hH-*5!doCN9<5!x2?93&v=L*p5rbcXWq`q~?^vxbpKnbv5^=+m z^c?H<;J{i9=9PdrQ8}>kUd9Lm$Zs$utg+Uk?- z|3+lk07AE90TIS3yBvz=UPigmN}{+>#8M=81prAu`Wmg*TSl_#aPPz+_E6unf}rLtT;N$baV_p;nU{&8o=pomUx zXU<`ZJG=b*iQ3yaI^i7uq6^_)L|uA2U(Vl=^+hq=A1&vu@x}4vq;f9*#VLf3Scnmq zPdT0A^T@65MO}J1q|3e+DEl6lb&jVWIB{Q&x^xFqbG=;T*YI)~Np(*6MJI4Q!3WhY zUH#XbPYfnb=Y-YNE_dqOg*Nw2u5AQgX1z=6H1Z*GR(q$zP-;g${^2h}KQI7~x*~$y zo6@(KoDMeUNeDd=N5?nu3npA;8+|g3Gv{ajit0D)7)JQdZKFG$C;gl`_~5)0F*pd| zjLFPGu}1zOIJfIUy#G8CNq$4+jHBgH><}$us(wHz{$;Q@oFrM$5r6J>{7TALkQ*TP zEWi+qU{_6kCj}ttj#`$+#4WLtjH(fFrI& zViAx9fZ|(`cmc>pzH^m6c@ilHx=)UDh_d{;V~JmqiEZ0TDV*+YI7DrQTi~(Q&92| z0FO6?Tj4rDer`;2ri?f8O3E2W@m^xs{58NRl1q1v$3x7CBx**osJ+HE=*F*IO@4{4 z5zTrV$)Hc0wxj&@0A3SB-@w8hiK6An0{vxx_<}qD@zm*88t#EseB>NRqz^~Ufy7z> z-_dy-$isl5P08W|*K+7>oL+2@cp9&^817Y8yn8Mr((e%p@WStPAkR^PUXILu z3%3FR#q>eGZ-IOX;OoM>jX1a#0n)}td{oLs zHS+a*Yu?4iAHY7|1>_@2koViSXGq*dmj>FT3_Q4+Y85hrWl~ zXMi|mu%pjFY6c+xlLBpJsH1sUVn^>WZ1|}bl5HIQTS)i~fF1o5kjDT;d4)+L#nDV2 zN7L_2!!k;9!pC2euJpD)=Y5Q00DjRw6UYoo(2M>yAlCtSb-Khzz_m0CzV=1`H^~17 zfHf-l0NN0&IDkguXx*?XMW5d;h7h_2&;S9m0DJ>rJ&<*jpc?>tf&2r&`fRfLw30q@ z17PwF++YE)KFfeC1r%*NkUq5F*=-nxJNnOU>wG?h&?TQ2AmA?mzJF5uAzn@ZScSB{ zhS}LbD#-nlCCFb4U={ufnhUNuh|q|Ng+IrP_%#kc$*=Wc+$ z;D?U84+++!#uRd$ncbj?z2FC)3IJ=e2FM+NqD6)|OcVcmKF85Jc>01v`WvGk2;iql z8M>6_eu{ohvgxv41riehd^zn3AeT{sE~mW!WFvspTxY~#Y$rA4YG1$4Fn0l1%`<@f z0#LMRe`-RPadbyyMOl1Vp#JO4>YutYdcKJ0SqYFCy_4kXHfDIQo8%na67O99wD+N{y%Q z_rRiYTr<|4Iiq#nGRty)D+JT`;ePv9jMxDFD%`REgS&nJHnYSO!jK3b+ONXB3HjFn z*vvP9YysrcmoCy@n3=e;jlXepKWF#P3B`U`KVacYtq?`ma0dJh@6Z8!L8k`DOaR}> zxdq70fP%DBbuqq^!%NrPGc={h%KHZL3W^MwR=duGi{Tl9tTmAi6CUY`wG$xg;z;L- z)FN4>4^(a{haLV<3PfJb`N~a_n7RTWgneA7FDE~ zoD5uE?+hlqpP&b2r620hBcq$EI%Q|;A}$D-9Rm`EqePZ35^s9CA-4=c-obUpb|e0d z1&~9ZJnA$wQ1JL(#MF5h*O6m#JW@*MbV+lM%O*uoF~}sS>p+z64ME+8IwuhwHbnAp zH!>)f2;GC?h|nYM9N&x0hNuC(#&(NAO3%2PNbKTvO)t;8{)ApsSzdySo)4b@H}(Q8 zL+dlPTSU_i%F;$bFb-0)-Dy3kbngUCXwc`<3tco!DSPCQ%W&=<$-C+VWaLW*hP6J( zpX{zX!6QwkXP@Ss%61ok#i6ojdn#GljZ5~8qhYi*1A4`nv!7>`p{DB}v_3R^$*AOGSw9qlzAC( z&x;lx8+D`VYY=-y!4N&xLo(a-x~hdSBn!N*(QXHPy2$SoRsZ}oq~!w3@wyaxor>^3 z7WXF>iF-i^P^Aw;L+$7LTg7<}%NtL>JF1@S;%ULa$@g zjd>VqAw|uOfp`j$K*>dgnxeW-*R;VxnP_-=7#>&kqN3{Dn9dkV2^gp)WyLAkEXfX> zoF~byoNSb2PCQylN@kN1#Ttk9(McfUr~Zg~h?fDQRkRS6bn;X`&pjOf;ma&mJTvBH zL=P+QIv|x1EhqpN+67cd`f#Rx- zc-xi%oLT~S43?-zkn(bg4jx=n2tOOtf)Gj zA`&iep*Z?PhRWAfq zE~?1!MwCzkorM2I^gj8P5)CS<8~+`GE5G4R3o|IYpm4mqHlwBF#bGs>YrhzqFasvqrvW87FgdNQ?X zIrPfpmMd4!!ODU{FYgc!6=pE8Ks^s4C~R$1{h6(j7J@f}k;Tsai{t9((vly5|H{=X ziIRy}pk7UoeD4oRegTrpb=<1Ez&%L41qm6z$vtlZM-%DBzavRlh@P(oq}|HW-e+mI zvb6Vt(%OGm+BT7f_gG-H(D&T=^zXmmyU@BMW=8bg*HGV-Eoi3_&FiIe(ox9FjM1OE>zbX`CpqU0%} z7==DfRp=U4=nJjTHDFZ=iGV`a`3ijzqR^E|3LS4+?;}(-Nc{l*NSPN1;RsQT>J@qll-MPVrQSd@ofFeymjw{m#4l3xl<*b^yF zUFgPi(04<>`kr+BrGI0u{F_3(!5uW5j!7! zbTj7DJoRUYLNWtM3Ne!ePhKH@JrqL{>3g{j*pxvi8s~8s92j2U{&G(jNx0Av2zn8W=4l54!elnvS;F2MjCBBH=0Q%HJS;s|Dw@uVbeZf({ABLvpAWF#DCvt=xrg5_GfOi7Xyv9 zmK$wzpwaf|IR7d3q%_)Uwrm?)wpuqD68mekjofJ4enO+&8ro=UxY6E_Mq9&;W|B#b z_P3vIB$i~<(;i^cUSZQ7;6}4JH5wBCeWTqI+Gw|PqrDqwv{l?_+XIdE$xpW@rP0>0 zWt-Ttb-K}z*k7Y<43vIM(xzYX>XtWjFXuAT9w)LmmlhSCL*s^tO*(Tj+NbIlCKH)}N_Y)fJ zFA0q{!pv#QxY53rMq7sJM<|m7PjF6q@uwSU8tqj!?LIc`Rc1Y=0#Tf4tvS$YBm_(#Ex#agEz8!fKSp8g~2n!7V~(+G2H3 zH>0H659cgK4J@^D;T)=qmD!ET#;D~H_zve$8R|>a;i;=gA3gzqAHQIIWV7I9COPr4 zh|3!@I(z8s4e0CjFZKpO(cXlkWq^47y#d&K6nZ^*3*z;MKfuymTa3Ll zM{RoluD9ythtL*2Q$0)v6||+Nn4umSi55e-y;?cirD8CmSO(GG)Dv57v@EJ#f*+#l z-(lQ=je788h1N8iA~C)99~4y=BAhbK-h36PX8Fd@?`u8Y0fK%)c zK1hAX_{E4LjqC1`tSk;^px=9tgxI2nL|2%BR56vDpd7l)b$krTSR7 z9M-L+rt01ef8^pPaS-UKryMHwEVPKK2W@_ITvR>Bv_B=#HZko1OY`z@9_sZggNWxj z>;AB;&B%gR|GC)pveoaD?gvq|8)-A7B$)$UE>)z_KA$BL)yJG2)W6`{Om)%u=pnB9 zH)P{9_3w+zqSL7buS_jhf>RcCp_=Zw1+gg3Fml00Eo@wYmZLEB)ZN^2Zz51es5=l$ z-e8-(ET?`?E)Ebztu`pPGD%(S4&}lf5jjhFc`=PR zeSoK0Q&PQ7Hl&$A~c?kQcqC=5qVVQhvX2I&*p9jVme1azY9sJ;_e=3T~ zh!aV}nNBu6x_DXiP?wM&2+P%(ig7Q49zE$F-XdV8B&<+Vi#%0``Gvd09{4jGqO=&y zunLXXQx^ey(E!Y-a{P!A*=iRzKtC@>Z9b39&Ig%aFcf=zqiz`uga1PVlpOJMhom`2 z{YC1!UN>EY-*m(vbcYd|rLHkqy}bOWx(7!>nd%J;K3Jmgaj=n^tsY4ukM*4Zhjl~4 zLHK#&sQ%bE?&vtFi>s8J2R6NIO5FuAP78)~Wju$D!8?j7G-EiL5 zYMeA*9$u3TLSx`nQJ!kiBNV+{0A(BvkY~rb9n_uL>@#wWx+#r@pwG^u_5+T^MHc(~ zCfJyzK2v37cr6B^dXGJ+kBRfun7G%s0PpFd>NwXrA5nHA#6{Gd=ixR#hDo?ML*c_X zF2dYt?z&>9V8hUCz9EaZFuiQhs>C`!> zOs^kbc_%Cxv(#I@8D(ByHI^nidMVIX(YpY~c~Le$!K`*DoTYZ@V2bpDA^2z{S=9!` z^VO{|WQ2MjOc`o7T#2TB@B*46)mC=FJ#3Vht3J?%|3Mp0qfJ+}1GFgCMD*6KQ?yS| z#{}zsv<`Ryc6L0)eQBHRgjBpszq6#tZs%Gi~=p^Vj z`USJfbh}T$l^gJ2<*(FZ2wrqnRfzD^-Sv5j+hBKnkQ~k3mHwf(FdyrHx7jrAY@#AG zm@%u~E<}gfFfNGV1shl*a5hGl@6L6-L)66{8@v~jnH{nYJd&YfUJEH%YK@L})E$BQ zuM%Tcd+)y;DlyXXJh}&7c?+7t0sC0c{wc3Q~&0*M*)S0YN8d&r67B1 z2}Tm)LsP4cyn2gF)PtEBt7P5rPYgW4f$S%&*x=8lo*Cp=%nz;DR4dqNz(c5G=>S)~ zjj({2+jX;`C%l7T%ushAZSI~B!X1j15m1%KE*=Cx-v(};&VFOE>>}s17)$Z9Slcp2gi3!hqiZj=RXFiPqvWJ_SNBc~K8^xJy0S;&y5r3Z<#Y7A?c+q z)Sw_r5Efu5=8ZGOegWN)ijYBf`!=JGU@m~4ALRb}5_~>F-ADb1T7mW0!Y171myz=V z^1!Q{xjH=aHO{2CHrsSv5^euFjkxMw8Wt!)3Ls%N&2oRAqcMV$ke)cLi(o$Ji6(F> zyqqf5o$V3Uyprx`_*+HwKIEZeZ#)+#u)zanSc787+2H3Cy^9Nx$m%Z=Nso9N6w`SgU6`_aJqKyaX5L(D`!vVq2b_Sa(B06 zr{5a%EnQ{9NcApz{gz-3c^xi#4><~leFzd>vcd<4#^YX^cIpnYn@}0OzQOi8r3Ii2 zmhYGVqv{gibgNHAkInTu6W$p&0lhTLL<1-*#tS#>nFf&5d`WQ~F|IWYLjkSx(sJ-| z0z4p#9uPi)9K8ZIWT;*6mZDKGO3S%4G!|Y51g$GX2QW75Nw(pmFdGu0h)wxD^vzNq z5VJk3mu1+6P=})CU~F#?02%7@bK(gRLn{iDhl6*W6F9Xe7pQ+hp|t3c-a)XCJas_J z`ogkhiI$b6t`6Y&@6jVU6z@FOKS)jp#b6>SNGGa2I!GrXNMkC8I{L5T-bA{$vjqKP zqS^TkiE<8QQ7flzNGkw3YK#?#=L{+nd9Zq1G1QEnsUcEu3CxK zKt;K9S(M!cJKhP}QHVE225+RnNhqFK7u4f4%P<8k;_ch%9wof@wQRin;-&VNH(9 zsI<5q!DfBJ6&6s>x&cM96tSk^v>{8a*spy%Q3%a|7A}U%{~P}9*c1cnKMWsXeM{2!F3yiWUBWT znULkvEO4gWTTFbXJ|e1qMr)K4an=j&iy#EAH?0q-`e)&4Pd$ph-~xw9z~j{3YUKs~ z;bQ?^E7y0`VKeEt--CSQ{fm7asAmMf)e6+0YtuEOHho%fqHbmNJc@fgIY!VluDUE8 z+m8MijJ{fg=pLl5gcIWe#=+bv*(qSu_RTHv^fY(H*at_*}C&hHKLh#y;QHV^;LinPqZA;YY z?sP;0zdu1F6b}F&TE7@xLcNFx*q^ChhDx5=m=1@#w3_r3KIOq!-atG#w=19HQ>Z+H zGI{DTSOgj9e%(p$b%~DTw~5cfj|l!?4y_b%_PPl>z6)=Bg)$J@fo9Wh zaD)?BiPBji6uvCORl7rTmS>QwbJg{W#-T<#-cvN3792OgrT&9@ped^A64S4tXsV)? zy2_8t#7Te+P=7(eU{G+G^$BG{EBq~#>xgresOmZnhS(S%rei%*T}Lid``~gN-O*uu z8baq-h;#{hKGJe|PYNP>MoeP6H5e=W+KzkW|3Y6}6JdwZDK?)3f$}}m_XX)?bQJq< z(6iJ#hK}~6mvD4lr5_Co6m$9`PIRVxGi-`t^PQ!(iX6=CYiXD;~w z>2y45c|kNLZBags|2cD#gb3cyQcW;US|+G3co0TXcuZM5t$Ar8*!% z6m(mI*FmV{1@PsmhwzdcB@0mSSyPadmQPZ32FoKD2I1-!W<&uL1BWj2bW$0ZNcu(9 zqg)ADRMHJc5-5wG$fiZHdZcBXoI8_rC;;g%8R-uuNDpX~YQ}xqjOW-4(vgJBxCiyovX*YUkv1NVJ@s=KGCx6ZVSdpJ z_^==vrwcj^G$1eDxCjdy92U*OyctyoQ9{k4<;+2hVK~92D;LYf$ap;Sy^a*Q1$5zo zi3LQ1NSniRb2fccZ!oC~ppN6mr;5YvaaQ2)LT4w-JURbVZj2Q z(&&WULP*X#$U$dVMOkV)>P7I}O2@7K3W*2CcUi(M$r5-m#AkRItQmk zn=o=|20px)`Su)`5ArTLki3+eHT$3=^+kM+Em2Rs&-t89xHd71-Sa=lDM7<2wHv3; zoz&Ox1Kw4^4JB$h#yyYDheqkZbu$#cc8M&V?etVI-rqAI*X;bsI#t!wAP=Sh1sjQg4c|WdM4mKAttCl zX1Z!~XwF)c;;Bo$ypUFH@@kqCrqTT)Q;IJ(bw`BV2t}YDYm#TDXA# zCy^PvPN2Dy*|h868I~AuOp@EP)NN!@@?sQHHZ3gkb))rhw)zi;S^vZ^3%t)MK=sJ{ zFge@;ELhb-_G!Tbe+((=_v{ihGq-ag7R)lvu*5f5VxSKuO7w>!db0%$UT6M5uirmE zAHt-p(C>midfk$nFs_Zn0EW$Bruq;~;i`6c*Nb8>Ll;Th7J|;}X1=tNq2302p1OnC zF=U%zjaJXyq3#RZ;C4vUo%YXA0SB(ZEVDIShaB{VH;|R3?t#oq^(^G~P>%wSsJ9ru zE0f-~5RNS)9sE6>srPpDJqnp>J2S090i0A}u>;#$4i<0|5djV z68c{)v@)S(yLo-aANtQ!-S#W5kZ%&AJnltuZU3U1gH}Z1e)&6UOLdjj$KDviko66z zqpm}HVoc5)fN%ErEE6WB4pz8=zc4Vvqbi&)pm2h-5_=LY=+1IUO)L>2(JtI>xCzGF zoy)MS#KL(mmZm(IUq)+oG#RY0O$N=DV0nnoyPE~99cz22R$8vAZ(y@O*2WnlrM7sj2Ag#*w7=};e=EqY*SP7kPR-n6(SF?>~ue-SSO0|S=g zUUV>>UOmIkf%ZC#{10y*tB2e_K>@tq z1Eh6SA5qI=@RyE3Zo}tT)L$Z4`-1D4^Zk<(8lb?Aw>qYZ4D~#I#Dx}bk6^Kzt=e(g z)SWi`KU5hQ%o|41fKRYiw#48dq*%G9$W-+tYC8?QyfA#S1*4n4FvKfcX!3++-@xn} zNIBkH1sJIno1P9ae)@c?hqx#A-bjjr`nOIb8Nju?6f1EK+* zTZ@xS$m?H*(S8Lf2XndI$kvi$br(X%{5v%nJeZEi z$U=jqM_woQPqh?%B)0sac}akfVY{&4&TI?}{}?~kA_wZSGGZclvj z9S^!#4S)XWf^o=oapi$tx?sd{!0D|E-DZM#YNuS>cC0D%v!(+bNUGv63U5f$AqK9;`M7efku8v7fOND1mp0qC+oefVDz8zv;|Fop^gsb>RhzFA=YN zAH85Y)Ta^RB-|gyiw-mj$V2H8L8oFbEkC*tdUQsxK@VK)qF&~nNG#*0C$JQ|M~h_h zK^+7j7R1?=XI3?Z@(d0u7-mOlm>s1@h7}(kMm*Z;JiD=ee&wv%d5MIk z+UCl}sv4&f#?G->O^x-H%?qmLHO;DB;LNUVu5GFJjc=@7P+v*q_^a;Fj?KR3_G9nh z(h%JShdE(zm=o}Yjj7E(ILrxyk49tGRn_}eRyWK?6U?n|XsB=U?Su9;wP&`>26xK> zgkD3-T)#+F%c4s10EK~xze=IO?vdoGQS}S!Yv7#9O8R=d;RtBqq}W(cTUCR9v+=EX zwF@d2G=-=?B+Mm4!dx;W%q2s@;$ldcONN96J^G>5cV2z7Q$4q)sj?wCICKopZE0w( zx9p8)&*jFiscNorX4TJ{@0>7lB7GyF>EqKzRh}|>v?WeH@uU+*OgXXggefCS!ic5L zysCNgn;L3s8*LRFsZ|T0O=_zT)xB$O)q*+jenQowr<^#Ua_q^IraDb^^|P9tsnbW! z^P7c*QqMssquGL5co+d;m7YQ)+1RO-r%WDo;^fK+Q%)E?cJh>|R!mK8L)AIXEFHhn zSWOhSM6ayGmq=D)jH+yEm_Khe;%{M9LrbkK&F1PMO3G4To{5-D4fK&!4b=%z-Mol{ zVL|O&bR~Rmqt$ur;E|P+PaHAjl#?q@oILrI$(5r-ve2{hT4Vf zQR+~zK=-B6BY{f8O8C(Hfqec#NgArEn(Oh)*fpjTiiI>XHP+QGsA|wXE->+6u%StY zJ7#0E-&oYotLy3;r_?soR{POHiX&L2G+;UyQB#AqYjW@fm5nKip%GK#8pKlTlz>u| zH1|1`I(VC$>iKgU5$2YYeNx@9AYqg?nj|!j*lP=LXQ4jKJtkl_Mg(C#v#GiynD8~^ zh?-bmy#OO+_568|B4x-saKj1p&8IA&(XMu0)tL>L4RuQ$ITS6G+C@uCX>xCFX+qpL zRLyQ0?2BvW25`__=FO{Z@LPnZ4Qca0jGZ#xsj6o#(HL$ZFvfkpqoudhxR8K zx%DV{(#g|eBTJ8pm6pT@$4g^_O9q#gl$Msn2F-1#Z*Fd=9R#uURr8RpI{c^NuOPmj=4yMdI)3TX*M`3cGi1oPByr>SnDP`1~ zG-A{gTSmNQ=esjGKm((Y=^#Ohj>{lLcatDxI1lhmn3H*zfF-z9gxj4b{D~u`jJK+Y zcd&Gw4du-j9ouZtRQrKq&sH}~wh=*!UUmj4Nou2%KfqF?(fpEZz3IPJOlhU*!a<7e z#X*XW_aG&ya>&u^y&#Y7(Lu`5fpN?(SZF|#zRJOuGFYP9TW`xOJYw2(TZ$qD8vxUf zD`~*RkcqBWDqjP7RGF3C=IAMBf*6(1t0wDZW7WxBL{@Jg*~;lf|Yu zh&Bka8lxUqjWvXW(oI-Sh{Wm!eQBGx3-TVd3DWeM-IBD5y^`mJ| zZ0F4#M=>`kPw|qM(0$isa1j~2fm!O(->O?faYz`c@4s!_& z*vWi|9cNY}zD2wl<0fW(t1?F-uWRwe;#eVK`40!gD8!o=R?fqk#=%;kc8-=sFr?;&BN-N;Ou-%y3~sdH=znHlHOtRB&)#g5|&;$vfG zXj+|lDkt+l?UGn*h^{k9(2FdoLeNc?R4wRsOPaLDpc(k>B>LkDBoQ-2R3PX8OR5mG z+>)vV9c4+AmKb!YPZD&wB~@=V=r&85BI0i+p52~i59pxhvCkNo{QltDXKQnjExEori#Lk%g-!S7SG2Sp1mZ#de_+Xa{* z=uSi0f8k^yo2`%vL0`9|$%1YT$gOCX)DFv7A?W9pG+EG~P8BHzNw>Sf6kKBkRBSM) z=;b;;UPUoeo>Wb870PMKZI?>KQYK0%d5V&v+Gr!4h<19#tNwr^b|{)Ea)UdBDodqlA2)|D+H~!q{)H?b=rSuO$ zgNj}V4M9aO*V&JXL4OfWjhkEr9GufGm54+phLt9oC^y_!^8eZw$yGp~n02_gl!?ho z>hzZB`nk(IF>VOjXkOsDPK}@v1qX^3k?7ds6@u1T(riJ45>s0{S!a_8Kwb$cBkttkmg-jN7k|j+N zw84@lFEQv!pCqX0iZ&A+Kk&JdeFr_<43jNRLl+UZNIf7Wmvr1#Q_g3?Zz8Au%`j{M z^?!t7Bqz0GMQX`Z#q?SuL6MmGMZyW@3Finp)sm_OO*3Ji?p)+#{ipLm?Lt^&GBRk! z<(wskvNE}d5bjSYB9wK>MTD^4WMJ(e=q5wbT})CE_*TyZn~|U;s~EM&*cru-1mXug z+mkgHdYFt8br4hMn~mj%u8XDVk-^P zTJzMZ>@cZa2~_d*+5`n9B@X`~1s!jLk-E`5F=dE4@+1Q#dz)dSmz2q@)6L@MMYbD;N`1q*RF!)M%av zoGuhlshmOXQGWFZ0ZIMRP*MGiB(b_#lZEOqN~UfauPM9DQ#rrNXqUtuL&Ps=F0x^m z(Jth@ewnoPya`%RZ}Vh9(@kPVkSK}ShL|LMks&Yk%cQlhFo_#{Vn+LVli27J)7mBR ziXp;3I}MtHpW~xHsFs%EbM2m;#-wsvdRDVRxBDa!m}UgJ&MYlC_@4yknlfW-+1X1C zy2B@lxC|?9c2JOy4>e`V%rnzzbUOS8e+RXXG9k`QGR7KIA!w`dV8ppKLAh;!v4!P~5- zD+CpvQc=Gyjp@GVQ$>RfHdcM< ztW}HG)>y8(9R~GdC*`mdP9*06BH}^g<77wD5wCblp6T!wJk{G~h#NCaMqjr**@?DH zvIhfYlKn?@_cJajvaY$*ZI^_2*LCUz6-QH9@$@F^={cz$oRjQ9Dw*oSITC~NOiOau zRO59jF8E^GD02jr+A#A9D(yriMY=qrK%_~go0v;;vhdSAQhJ4{LsO-kJj2RkfJiPJ zvgD%BkQ$p!&6sPYxj-fXE*e1=HbX4+kPen{{@5m$!xb=G~e zb{KTGPZHJb({;Q}CVRWjw%4GdVMs4@ybPnZ&y*4oW)4JcYYg)S-&R3o>4H8ds6Q@- ztzyIzGCYNN#Bqiix0RV^*zP0UaaS6BL_b(6)7vhqYD&C1>8n%9r5KOxsk_^-rCBXz zl^b+|PqM8ch&v{QDMh@3coEy%mnFl*W}hTd?bF?4GJU2L@s`YJMX=Cs27syQHM1&^Y1u)KaCX zq{vn_S+UlGG$?X^o)b1kETZ@dG3ZDvD}GQ7Zg7!RXjv6`LdIK66Bl z#coEsB+`st%DFVndPX$Fj#*Gqj|)pe6a=53qAT--tC&okWK^DE^rH>3K`Sk(LeOSQ zsuOgnB~=Kz+LG!7z0Z;=1eN$eje-XJ(ILbib;iFX;D{ zR3T^w+nV))cDAGnL1UIwFKC%1RR}5;Vhx&O8o$g2XN91?G4;u|=+RpYkU+u+DX7$d zm|ARo=nG64Hu=DgmiPD*vC^B+4R#tE(rg3PNHeeVNrJ97B;_o*pj{Fhd_J*R0ybnC z#t^DE8D^eJ)``}=sY*4}m`WO~2ETRNB_XkjCIE~-KB8rwJxf{N~83vgNH zi_$xcHpDCVUh9r(K}7?M;(|(xh1C)bG*yF%SG}NLXVeuPHI>^o@Gq=90y4QUNP$9( zQkY1MOHIx6E@hdix6M4m-mip}#n_cx6r|KzBaYOz%D2~PZI}8)b=V8)k13BHlUz7# zK?PB3OpQ;PCtmVMC^XvWFi2v}QgVYWS(jQeWw@dhtd!X4TZ{dLR3|QjwIREXu<|f1 zxp0WJJP5e7V~~1fR75BUDx)ICUP1R+`|5Mda3Mn=3JO}}kA{hELdqRzGJPgP@L6d; zf|0?M+GH$76@toG4BZ43g}^0UtG8`6(-ZwV95>Ho`b;T`(Aj^9p-wPQ3}i7=a;O!b zvaJg*IVZJbXcv&W>P($zer$`Rx=E&5O%0gDCRc4xIj2$df#v&(uR0>myc-ic%Fs!m3!7@QmS&txS z1YK)u4O?;qlsD*f=(`QN%&#i=iV~pq-wu%ESMrZn5 z%?1^BqAgSGbQT-h5?d~{l}xEEV+}G+KWU?CP{+J~q^@GnT=UesCP}RdFs3S#R8g9( zs6x;&mQ*XKh^C4v+9g$EE2eh_Owd+o?*Vwqv)Ppq}b|xl~W@IX7X_~D_q%vo+ zP`!c-5t|&Ia7awhBq%iwwBD+f5~HkXDKAySN^&nqF1w$u5pkrxp}xhKyroKsi2YCA$>kBD z$%R9MHsVT+6RgE`%?4fSlajrR-vx1$JIOFi^%?67+TfE!Oq)+i7Uw!qM}*BVZ17c% zjb2fSiK(UUH)S>i%O6D!Vyg9Ub*n*_`6NMC7*YfQBe(<{&b8T+z(3wYn!_&NLFokTB&@_fkhD4lrr4EH5exnLg%i59keydv8$eOCHlO~=Odl5>lM#u^)EM<6f z(w3(%rOd7v>D+CGZMQE=#`mGNccqGVOH8KElp>y91d7-UUzT*J^*$-p?sX>9XG#%I zg;tK%MK_oydcB~-ZEwcKo6t>_<7_s?KDNat3mWsgH8-e)-? zZo3hSyS2IPk`O(ytx498`I24AqrMgCm$n9fVtr7ZEHK32L~)|j|CfeZ<1HuZ=MM8k ziwgR!B~2DI!zis+ddW8H^e3j+F7t$v9oi)!g5buzCSPPSU$RKO>=2QDX{(V)NvHc> z8MsO=gf#2llu;v5sHpZsdWyhMJt=~6j6rqgN%P+lgRc(Il5GqxJ2<55;Lv_GFsWYb z$&#xL*`|>bl1oOMBSUIEGNo41IJqq5oDKM3P?Eixnrtyeb8`6~>n&QRB$xdub%&Mz z|Ec@Oc{>Vsi`HX|j{+rc@JY$O!jjQs`b;SiO*>~1Tj$G?603buvUoaWkP^~((7m{Io87ZN`<{Ra*eXj`G!H^C# z(>sPI!xpa)RK#E@BWO_K{y(YGTCUq=i+Q4<1RXj;XSq&;pxZ}klGajEq8Au-cG!QZ zXji$;#fn7G;YKR%ip~_g%+ju$Dfn(nyK1K3e%+zl9I8ud-eGH=EU4IpU8ta96qz`= zT~dBE)mr_q|Eo*|1C5^8*$G-=NI0#T*)9pOHJv{Ckx|mST?k@uI(_zoGKAo(QJbs) z4R87{Sq%(wY3(73)a*x*qWvj?jATVvwp5(_+*qzDVlQ5N3M!Ur(+BRaMr0({820wm zR=nNRxYIll&4NmebRk)Akxic(5`4EGWQzp%-JUXviQA=SF%a8WL8UhS%uRW!sr(5a z&_x5kwv>Ho#9Atd)Vs*#UOY27}-4vu!b`Z&Atsp~w(AlGNa1VxZ39l-MfcMqmh$-b+J>;3X$$8CdrTI?9qJ z2`W!;2|CGe;XMV;G)+RD2q{6gS!p$b?y{swg31#W2)Z{|fh6RK3IyF}`5N7JN%XV+ zt&wK9!6ymYW=WF-U2RD9|V(`Xl2*iUzt)k8bU&Ozy+JFhMs2gbAKz>?C2Arw9|%XIpPflTl=u zB~2Ez?SQf*_x=D^s``?<#fmo{6!6{XB2xX7pdA-Fu@QVCSw@sq`)Gp(;G z#4j1P{tAgv-wD=Y(G~-ppuXZMo6<@Jd47Lu_=9AaY&+sH;MR>n5A*EZ532_>xb9>O+hXn}q2EfBGQ;jM+7O^hQl zrU^-y37(ekQ5(=eza-XCr%|GiH|wrw|u z7g74eTiQx}`)Q??kFpV$!41?DMD0sURsz z1OJ^}oNsuF#2HQJ*z=~+lG2i9MC<^{>CSbC>sBQx7QRYuct)|ODm-9E2HP5T!-g4> zvAcnuoS<@o<9m81EG3dAPbDHVV;Ql?AfutMKY9+*lNC_sZmz4+dA{=b$xRgGwyhdh zw!vq#L)@ukNk2APqu4@nQRN($a$G^DxL%3MO)Ll|JtOZ>St{9&Ba2y^s#!|Sej4!T zODeFj(ip{N&sChuk)+D~%3j1~p9ifq^0K!%C>Mvt&nAmBG3@FE0ij1aWr{~#XKry6fV<+_cD&no04rVE?LnU9@ z=$YR@!xCm~@>)_;CkR|ZIVUZfkD<(Zl%b`ja{pdKmTM-&oa(X<7dz8%J4Wz_pm3_EBs#`{QdR^K7&krMx|2qr*6- zDdvr;ZyDkZtJ;BhU{w?=n|0pmETR$eS)dH^E{Gg(cQ)=zos(-8f-- zKy^aS&+>9=&9?1OKX=M0lW9N23aIGKw(Y^4&z=Tk^14Z~gLQk%MDAd@SgVo%- zeoSxilMx-zV;`RCgsZDrcZ(EBCt%x^a?hFr+Mn0{D>p(eJP^|il-Xy!7 zViqcWcET3VGQ>BMza!2eK!st=P<#(m@)38>d<_~c){bJUvHQ94`4k#9c*cpywNKP; zaJfxSzJ&~iNcgN5KD3NU;EI<(Xz8ZF_7Zx}LdrF9ijnaBCOo?;c78{__iAc3=@;X$ zZ<17v*HJkRx>XMCV!Bxs*Ug%Fh9j09J62Y9TweuZ3PddAY!V|2IaS2yLQdT^6tG|+ zr}B5r;BC)(!yg}LX@WabN!CyfYX-Vs-6?awJaw_TcD@nj%_g|FlQ6PiaMW;i z3B%#c!AUF)7SC$=CNS=tB+jbY8}Ma@>kq*t59H)s1ScNzpGSDyIN0FNc(f-xtFoX? z3dSxFPkMIoU16;4q8;|F&Uq2#!gWBqt@tie{atL1IUF1}95$mL^J1OwtfUGr#8rVA zSvLP9vozq={i0Ryty;XyR268q7gq&&3@p@tS*!}=D3;L)6UkbA+{@@>jFn#ll{Z<+ zum}_k*z$R*A2Mr%H`hypo=@o!_${DtOng-zec}eaGM<2GtEopW1@Wp?X^>1=*ZNt1{L2VI z_x6DDAnPmM5RnxPn^%fdBhD&*86ewruoVoXvU#e18=GUwC5xe#QQR`%S|u$5zFljp zU#`-C{l8hX4!%|VLO{FqxH^>2Q~ig<>Oc;gkw1A)#N-{f5cpjFm@f?&i9;uDX2e-N z>y4}Mkbur@#n*u9?-r}Uon$131W+(<8R|`5N+&%txk1shQYT}aF=beT!jmz`*@(_A zNm^1jF4CvQ*va=*A&*CNcj6naU#@fPqNXAxo zQ}ZV^UIEIyrnq5LeH44JyYxFnHy5M`HR!5gi_yu&kaH*J864 zm0PAReWYwf+6DGHPy07MM8RMob(o?{9-H?u`OY)Fc1&U!Ce&$4?7f%OiA{b&<1$c| z1B$CqN!(ZF**J?B$qND*Zy3fj#i(;SVZW}x?ZCL_DE`2x(gD(FG+mCpnnE&WFQc0x zb2*`Q@ni2u$VNU6LeNbUJVTL5JP@1-Iphl@a=LsVO6sVlUrc_- zM9xxVkP7t?pM>?pSDNryiZxK33cjfO9Og?clZ&BbLO`7%vpX=^728i_kGno0v|Avt zd$^rhTTk!eLaD6d+&vpM4HkzCu`$b03~S`k%N3Vk+fS?-o<$N<#~15cyh1*mH&P7HQb>w7coVeC{CE?o6kvOh>YQ z-(q5>V9ziy^lF^e`H5wrvR#T9;cA@Hm-}A&PSN%=?bF3%8w48|rGEmH;|awrsEQ3q zx^EiyG)2-#1t>-tla42AAJaSX5GV;zZ2Gv~B)3FRWc*?|l5y8CrYTk%#w^7sV|NZ>n;Ko_+LO zFrIyG_NB*5j~^>34H$31#LX;2T(zoO5LsBM5V^0J82*`=d@1cJJS~4}#pCzNCQCsH zJ(!N%bis_6j;P#z$&e^1LrRr4wGoJuR^@sIVMUGwRWPZwri~Drt*R3uiKQasX7xqo z#|Vzsz|-=l&U*Z@6`=>yk?u1irV~>U=8$UC(iBh@5QZi-XPaS0Oqh0xl_tp?MG~tp?J;2zPF36dyCH z6v=JY-uEe(br8&eat$b711Xzl}wMQhren7H6&VGDLPo<^ywWK=ndCHkz!mWWEQD zys5J{ne_R4v7Xq-uQ0ORNw3(Qf~p@sCQBl#a2u78ug|e>b*68F%(>O1=kIe_{dPfO z$x^i-v1Hy{SLsy3jIrfxfn9jg#Pp5_>Y`i_Fq-upU^KgX21v)QB;S>RRG5;aLXi<3 zka3~Ek?^(PeI#a{1sip#?cb8)B~o;?-Zvsl7f=d63vt1!Sa6OHvATkKOqjY1UWItw zs%%I|vU@tckm;*lNdKbIv02a(<38SThYQ;x1Gy!Gxr?_BL{S;dGmOX zcY6_9GT$iPL{V6$6TxJl9{j;JL!OYImsI+wuab|cKj9_U4luFfQaFn2wp? zMb<$aDNY(IfA*A2V52qiR=|>A3Pv1}a?YSKc3<4gvWpq(T5rZitfxH22O;Pi?f`mo zM-=Q8QpWBTRncQ5BqK`cC|);3$&jeoy248e`z;s$TH;L zuqxdv`&Z9=`Z7nkKtM4jU1pMS31tq^tYL<1dRguJ0g-QbYvMlix^66r-l_voqY8_Ap7e$V{gux}}1GR7>s`DSH8h|I{ zChGhC+F#n_QL}ewsrN}eteb!`<;&;UI0vQ7;}(disGYlmRhtP~-*(qGX5VQh`ZE5T zN~SbOozb*;VBDEXoR$B9ewpDK16R?9dH8|-PweHvv`%_*N5wh+PKlGAU3@p#$;qOf z^{xC5?#lvNy?!U1rLhg{f69NtP|`{|`&?XSeK!9ljM9KCvqd}WTYbV?R?7_6uiQyz zeag6dWn8PIdu3d^_&v)`E*0&pZ}rKT&ISSP7QyD+F+}yRVY94TdJ@^c#|=lZj84Q@ z`4j78jFrE`%Op5st;FX|_3tO=t$MK4fPNUW%qfU1Rs|aaa)gH8G%)VDKyg-nkB=Fy zUjSE;rKHRl+ra)(a@@0uUrJ8I*fqy2IqGo8LftkUZkT7KYEY@T;Tq>F=fy04{@~Jp(bkG~*SCsa#%Q++HfI^5`ggH8b{Qjw&B$MRPQ>Kx zPwJB~R&isOk!}^Ofp7Jx*rl9y8}T)u`ac${0Xb|&{*8(!0@o_xhQAoInD3{^WxCr) zDZol1d=2wlR@$OUvj#&@7x`RoSxo3#WD$=tZJgJw@)tGA@SwP8RDBeeq0%SpY^@o? z6va)W>Z2H#pVE@g;Jm%4qcfWWWF@ED6yI(b+bKpF<3Ed(?B)SL%Tse+ zdY6|n)Dh=U)E_O7!$xnXNZR{@Gm1C71If?K8%T=RXT8%tb)pJafa>I98#05(osj6> zWnno2)PsVppMq8@>{2EVUsB#}LVA?an<>1>gj8*r$TE7Ps<8(7W<;keV*l#>O>ZuG zGAJpMP_KV3Wy0v4M#O&(l-l~9v7=WWcMBgTfPu;;^9k?zlX30x78%!MCdJ*{W>=yr;`P^o95{ao-a6RFlj@)j4}E#|%j0=a-xJ02bO`gD+z z2HKdRp_3#dcd;Z{H_rySrIIdTXy;Z^f485M*8AR*EM#O}Zz@TZ^!90;`TQ^ zT}QWvY?GkE)HhABCbA>a^K8{yLyFNz{;^2zdWK77gfQ-%8Uxc#_7>A5mISU5Pf=(= zEcGn)_X%(|O*5iz9ur-@l7=oc9MKh)hITPzC4p;{+!fdIh_1NiG11v?Vg=sM)|q$6 zDTOBDF_%`=@qr;(B>8lcA}bW%l@j9`$(B3DA~%vWCJklWf~BCxE(sK8 zp^8r<>YO*uX^K&2f0ip}TE1?bCn3&Qm9mV!^r6-FZ6^&m?h7weTz_7kI!cwL^^UKK z)+bH-p57Y6oTAtdm7Zm6jaWm9oTEjPW@R zl%oK}C8+eUW9x=Bq_|sPNajKugw29+zew@dj4I6_+eVdm6d)n9#eidzOdN1*GiR8y z$u7{mFnP5y=$9Kcx|qA63zkqfe$>%TqQKG3ghzq5G?Pu#|A`W1}@nI0}%MDaL0@nj+aUhnWv)=@w9C8O3rWg>x;m zDoj686q^eS$y|u*;17&@AH|bKm1f8$qwP;eE;nY!piENoJ^!Z)zJms!e(As_` z90f?s6yvicO_6L_#_h+oRAn+wQEY`uk59I;){x>mK_-kU z@hCt-W{UyGCYd){r7+sx~BZA@;*wEhnU?8VstjTsu-N##2C{7v z=OV@L8&#S?YD|#CqW}q+Ee0H$Wa5Bhn>oXrO?H9iEDw?I1>C67#oP^Du!OqtqmFJ8 z1&+*s$fLkpnn@Mve?%tCf#%6a0a|jO%eqQ2X7`gX;V3||H8XH7vb^QV14lmdhrKmQ zI0}%MDaL0@nj+b9r)_*tOO+<$6vbAk^yFbHWeq7#6d01Z5X)iHY~1@OK5tZM1{pUh zZ%N`&fP~Bz(}qnlaoVuWoMFx;yFl~8X25o=9yS+aIomFuZy#l3r4Usg-jRf;i% z8#IY{g;PfXCQ@z9{4RK&fqdUhcgyxO;V3|2rWl_sX^LdaGS*;xb^_%nKyeBxJwDl5 zw1yPd3k=Czh;6W$Fzy#Ae$A-T46R$2N0@Ih*VP%?p#a?*-hb z(Z$>iU9g0@@uQAz5(SQKCOitfrJ1at{zqiO9B7_=6rd&dxvZ-cV|G9J5{?2S>#?JR zyVTlc5JnnuB9mU7Z{Sc5O0IO#<*Xk_(7veGf0n7T`Z*GU3~Hc8z*rL zI5&9?I5IP5n6t?)(AE!LyDZK#f}24aGNmheH6cDRB47>F)D9K;!%Kv%ofvzO)_!Xu+5xd&L+D+ zbC!pwW*H-9O>$YX&RG>bh-y~cyQlSKwPanT7*n`wCK0c2>L|cOx~!Ss1#7v)MBJoK5eDSz1D`R(RbX9BY7=XRZ13u$%=-iWI+LRB4KbP{n6m$T(%)DUwEh z7@A^~G5(HqxkVgIGlsF9B56v3&rysrwkPy@0ZglgF-39Ts4^7E7;{*bNA$t|Hc(2w zl+%^)g8SC-g^aiJ%M)*x)M;5~-lG#c1gg~+;@fNVCRw{F)rHnV)Y^8s&%JG8cCaCl+hn|f%Dn` zXYgLVK}{5hCygpivCgQn6hCfMX^Kry={~X5Y7A2p`;96~F<;>8BwNsA=7;EkdUpb` z+VJKmG7G&k*=jb1X^L$|m7^HVsdz=16YC|rg<_rI%}`_(DyQ~&wo=Bhog#}PUrC}E z%_(`+s03G);Y?HH&XN?_&kk!vkzvHDp!jT*C}FP#P2*o|43!(JEW6xlRAy)}r`YFr z`ui%43=F8RXvcJw{mPn%UcX904(nZKOz(Wm`(d&svxvaz-Y_9j6g%Ii?TW1nbYC^@ zX^JwBR|AMk(BQWzxo#bfYs~4Q?;)L?>kdl z{gHQvUo2v*dJ`*0u>q<`zNfJv%V8YB!rT~*@F-dsiNqOoQ{n^XE zwGK18yX~;;G6!4namP3bPnF)oj(RcSSR*`(Bqn)9e2Z7er}Ji}9wR-7I}Mb>KE+w6^vc85qBX=YD}YIC{uN`E_B~@3 zX+=U`CV)4CY?6m>2H9ptFfT|)8l@3tn^il#7fhnwu8Q|G{jr{2e{>E^Y{P^|QQU+| z*OskaYv}euwb!xvJH{;SdwRL3VPk!n0N-eXiae|>+svp)ZT+m;>AhnTjjgTkY5HS5 zz5ayVkw1GNuP_%SQWPIGs&RDX4VCS%X5%!e-Fes>d3#MJB25I1DUl^79W#YTZpvq%l8?NW~=hW8PBe za*~v}=_kvvWkZ=v$*2tryUo@NqOO_fDT?b*>FTkyX${E{MeQE!XF-+ZQ~47nyw9kMdFqY@=yY@#~licf2-1xht3wm|j6@>33v z=nLET*S`ABN-ci4t|WNp+vjQ21LKdXUX7_g+H5S)SRa}v(%AY%rDl+}0v`#!_?0&v z|Kh|q{>zl$55Ezdsh;Py4r4PKyz%(xSEDwa*v2H6izX?ZEY=58i4TQc8dL8k&s4wh zcrl-QpgcA48{d1I(CS`Bt77Gf=d@f8l$}R$(x@^NuR>L9Dm1|6EKo*H0?q z180D-0eK%oE!u9pX6Rdht-v-Q z?>gx~yA#+0%mVuz96_76z)Yg;#-D|L4!8uo2D}d30J{FSpx*>;0k?s>K;GHq`q#W) zYifb@zy@F|a1b~G%mc@PSAdg1-oAIQ@p!Y~6!>O=E+6ggHb3&Zw;Q_r8;E-gxC7h; z-Ue2FKzmjJtAVw^CSWs=x8L4tJl^bE2EKA&9gy){{v^Mn@+U9z=iT4#?Zj@p3FI>g zoCeMSmw-2c8^Bw@P2d)A2gol8+-p33C1DqQ`#_hEc6XZ}c@K`rx8Z|2Vk58x*b3x# zhw^BT1FrxlfpfqGAiw0}_UBIH^?)Y}><3N(8PDZU@;fSj@-lyZ$7~7llKQia?K{BR zz&#+p;aHDvEH(fefla`(z!o6Cis<(5PUG>5kNi4i2Y6jR+TCq_GIDY?ksQ- zxCFcgyan6@ZUJ|I2f*NQ9f4mZzSnqb;JX1_2krt*JSRYs-%WIUHY$?vHA$;|+x*DuJ_gF=Pa$px zFbnJl@@Z?cXwLz!0vCZRz%}3|@LuChz<&}r1zZ9$p39%)cU1o5W&Sr1XC0W-p8(H# zECZebRsi`-$TqZ7zz$$1unU+4^5Knc|L!y%9~H?5Q0Bqw^3m>Y^CPeOut}GH8F8-z zZvfYUH-Y=W1K=UB4440_fHlA-;JwD%2LBFl7g+AZbNQ3}j>@0B%)b_K>W=6SKaJ~v zT^Fzi$WN^JL6n>CEbQihOTcSDe)7VPSzP};*c|}*oa_LfhVW6frCIk_?yoMcm4S(%^~dFUnp?xcVM>*+z0Zv7Tg~taQ*p<2K@N|;#vHR zz)|*mpnsA*e}SPDd~LuEAb%5N1npVi0?>`$0=>(Zg8pv#uECFZ9qkq1DsT;W19%g- z0p!mXxxX&t=6@9bt-Iu7+&%d10}p}xL8-C^oe6)==@i-(KsWDt=-r3Rn%S z0oDTf+wn*F)4mRV{8{)U|19kKfg`{?a2&V+){EZxfi*pPG;84C;U_z*b-fu;0N+wB7s{puYwzZ`2mmK-Zpj*I`e) z2G|o@6Z}`;M_fgF4d}*8vRjA!K9G64{xis97I+o709*%d0Jnj+6R`TDIzn9nHhfHP zZw0#fEP?lW0)H8J%Yl`^q`0++!?zej3|nnl$4A z(B-EcaTb0H3AhaXY69MZewY4;d+mt$NpTm!lN5Ii+ZosG-vPFlAwIDZ?GfN)LVi`y z*Ct>i^vwy_3B4PK`^C-IjZ+8zq&O|u&NwdL9=7iT4}rlav}GBv5!eJg3v2=Af%nQ^ z1^*ggEwB~X0d)E4SB>p;z@zeYdAs131t#@p4%-)itH9g9J>Wj@5Lo|7H*?)i;@g1V zCU6TFfag>KAN_8@ej9jHelBk%_^W|Q`FCJ@7qA~V2%G^fI=F_mTa_EouLEy7xPkU2 z@YJU?Lk-a7qumzlY1fosPrDu1)21>hpk&DZtYhTRTu7r2+; zpJZ2dR!2$!vp_dK?P?sm@dSI?oyB(A%_P__LQh;mdl|R_ya{yk+lT&;+i|;P8L%A4 zdre*cX>6YXUIVTHv!Br(d7$f0yDiwKU`IdKo_5=?Cmx_(1ONJjc(gl&eE_>tzzSd` zuo_6-MzouOZhkY+&jN1%H-RI~+G7If`qOS7_Fb@}pKE^ryYkQKEfv68;0|yP==!^U zm55gdYy&b6*FOv1eqbIr1uTPqIq)oyye=R8uEKuDw*=YUs% z3&3sQK5*|`pkFOO2WVIMwBE1wbfc3x*U?;F2I0;+=y8R&!@vY)(Mf^5k3dsCs67oy(OX@Fq zX2CZHTuR_i;u(Q`9yku105Wg#E<=AExC*=hTnD=K-+=xWa0|E%+yRz7=X&aP4fM6Z zIv~Hh!2ACBodNd?11{@z_^$%jfa|~wVDy!wL9Xc_3{N4quHPrz6Si01q5IMEg{$&V+Gh65^3}6MmKO zs{+;n&jJU*!+yB^rCl@ZTY#;=E?^$G3cLk$`I2~2u%C5s4($ctB5)a4h5YLh>Oo#N z&vE!q0NuE3yZLXzeh zl3-7}M%Xt4TZr)M0`>s234G*fg8$hB-Ztn*fa4BMp?wv&2z2vs`|rk0!LI|@pMZnV zyK!B9@)0}X*OkEQ`Y*$dxQg}~(6wisub|%3z`2C_uS35J>}=DF{lF1m9_YrS-);Es z1IuAw0jva)cM$Dy;1tm1C(kKtuL3qYe$!~r0vCZU-!k;qfvdm`;3jYzxC`6|x_q1G zwT8Hj_6~3tcmNDu)b^FYW#Agn<#+k^z_ai0-Yb7K;--Lm%;P0D6Wy-G_BvoQ@J{_Z zVSfd<4K#6`u(a=jUG^^h8D|E5v%opvRp0_}5x4}r23!VmKix#zNjI2)eiAqh{M(9O zh5c3yYyq|cJAi}0m3G~On?Scew3~wcH0-V>*wbzi_OxRhm!Eb^u)hXe17;CtBq1K{ zwqQ>?=IO?x-7f5jhiF%%v`0PA^>^(mkXLm=ehuJh1J=N0dl{){N&vN|2FUt zIOW7+T;iSb?ShYZul)3@L|$va8^CqoCeY1~e)ZVSdAgY}9^C!Z2EQI)9ykG<1hQ^! z{NQD+DFZeD8-dNhPT=I{wf!v6<)d95_O!c}U{AYo@&l)VGvom-0+)cR4z8hn3%CW` z2D&nDXB*+KgdSlOYO+0V6v{?e`*_BFs-U_J0GunpJ=ocNrMGX-?} zbEmwm;LC%Dye?lC?8bqOuy0O?PrF&z)2=JQei3%pfTv(btU$XONFL_x=DQ4@>kh7< zOr^`KoHwl@IJ z0-J%Y4z{740*(XS{K|h^YwCgHz)7HMpMt&v*aaK}-f(ao?M>hoa2x3ISN&wU*W9te6KbhSZnEI1WR#OfamwjYYKe_L=Prs&6lhl0&meMQjRAII}>u=Glt z{*hqer%SvI$AY&9OR@UOU^!O*j$q*{aXjw~c4PIA1~p%ev#$ykV)Z}d<){?Lf_Ek8 ze>g#3ouL1b1pT`c^zTW~*LZr>%d+4ve&BApk6W$x$Kf}N#(f|dbjCS(ZaU-k&x-Oq7&JKf-$wqf{(nN>s4%PlsFU{l6i^oEHU;m@v-*fmik3a7|AM*HmZU1nv z>darQw|VL;gW$68#El1S|4^{))Su&IKQ_;YgPK7yYrImFzbaUA>dd%vJ%v1s+w+b> zJ^Q=v#C<&>E_qsC!8dt@>MAmtum$rIo`$q%*x{THa!FNLYM}ryEALg*H3YMMy^1b`?IH#WW z|0Cq73a-Px3;_^D+slTIl&pM9t8D4Emn;X+;b4&x;-^ zXf*VS{^0_RZj6Cv4{tii^Rv+RV13TR_m`pHz?;4bjE65A*Y#O*)~iL>FFJYtmgp;_ z&hB~Rs_0ey$DR6r8$5hyT@&*8Q`k>9_Wup~end$BedA=^=>yc9byz3n7dE88)Zs(z2ey8SX1^?$oug05O&kL}>@o1s_ zfaq1-_?u_a&G7ZJp*g9NfixA7`*Vhy5|1<1oKBSZ3JpFU% zEA#;(m`1J-oY4JBIs5TZ(TD5OlZ8A_!oI<=KNs3Z3IOr*3HmYc^f){dq5XqF#j~1V z1w1p*4`O}Zgnl0Sks7UNfc`h2uf%w(hkgzEphYV<-u@W+nOd#K=HSoC{{gLMJp)-M zRegFst@RZef*RcEFavR{uuf937ka0m8J zKwp6l9YFtC==r6GLFiwGo)_OHq3;j%Xhh)4uR@=ZZW3{6MIG zFi2sd^viKey*>^7Hg+KE(*ga$bJ}iBLvV@qr?sL7`U&V;pie>nb(z*}UOgy!HO?36 zHNg^i9)rH85(?x~2mLL~_bfJl0{XoVYX!&WkBMHbldVqNFNF4Rj=%uyn;rWvh4v2y z`Oj$MQ`o=11pNq(3+e}$)N2v?Ra~0u)aqb`Jnz+t9q9i6`i2^t!JLIp&rf=`1J(+zZAV%{}+%C zUH-M`YuJe3cSD{BgX)L1atqtO2Yv7nt!PC({|b6OYn^$1ORo3Dtq-RX^mUBzWKvCpC#lu0DVV;RvbY8Q=uM>2>c@Kw;$I^^8CXD``?27#(8bu zfI9pE^Z{-H+QD)8`_Lbto|CZuOXw?c9BE@tPhK7yeR6Q%!jpZO%#*#nqnZAXH9j#o zFm!qRiN2xBPo8Ob^7Lu^^S8d78O@(LJsi|#gWB=nO;HKcfG}lx2M4=f&Go+0eR1eb z6AmfD(fnBc^2Lj%GeI^tn(G@F%jZVB^Ow3agTq6)v7oy4tcV?u!FM1Kqu&qrIvzISjdQDs+t!}Z* z7nok^9T<{)E`2ed7w8)q7#6sYx%5=iM?PvLmEl2zjzXe>W6 zIy@pOcywQQEuZTi&3!31I+p9s_g)yxnN4FO1Kk%S`tYc9K9JU#?y-?vE*lIymC=5$ z_R8kVV?l24;u9*-)59-I`p>mLeg4_*XJ2gT?v_?T2eLtT%a6bK^!XRg6>b^JOQNEB z{>9IAKidk1)|U35`}ww)o_V^h`=#fed->Up?vAIQX?wOikj`XAUTc27?S*H~bw73b z%*Vx5hGC{VGj=&FZg4)`(ed=yYeSjt?7*1xdnlL52g5@zU%oJw86CJ_J1IL%dL#ufz6nnJ0KR0A6mzR?EW+PdQd4W|CUmYFD zJ5++3LH`+TWyGv>nTnwjqv_Kb!M+ygUe&A9; zO?3sMF3g&B6VA*lCT7^n-sqT7BiHQ*In+?49D0UBy!%q`nAJymp(fl==F&(s9ZY3C z9Mx(U-AHb!u-y?VA*q)h_Wn!@hhE`S3(IB_r6QN zx<_q4)F@SDlcSi-2tEI!Yb3LleI&DRxL_W#7TMfjuR3J)T^b%TD+o7Ypu9ZT`=#8| z+3aX;%m!!8OwBJ8)>kd5x`&e9*l>4$?@-n`HmP|Z9+0~GzZ_f~%jI5)7O?li@Mu1& z=zifP$uK)GBu6Y+I+$d1l!o(uPJHy0nYUgjJ%v1l)ai79_*C`{Ixx6yz%s~F7 z@Z^Si6*W9^UmEL^^RqA69U^Cc;k1ezD^0F)R5)WAVKQp;_Npa9tzU(kyp<%hV*;|@ zgG-l(oE^ojircVp*o3thvIQ;B%Y1GzCqSIgQMzuKID>{WTq;!ox+8>PkD{kH;b0<( zDy7~XX1OzTp{F`@T=w=vW^h1GeT}8C*b;_|%K3rJsGP#eVKK7wnqZOi?DDRXwu4ZO zSWdn|t&9;lf8rUcI*-E!>gRc_H~#Zqz4 z$lS;joCSn+DyV9x2}e=%$g5J&YlrO+&mS1Xc&Zb@izA~0L-~tw$%J;{q>(ciI&=J+ zf~e!gsOsQ3y}zQvDF{xFy>?07GYIBKHTF}Iu({EZ;PlXNK6hH)44%Gld0;U6#6T9R zr=NM@iF|Kg5N_-59qSKHXI~oCFdS8w5Qna145$om=b zcHV@*+kMkkm+RzGtMTXkj>KAHsf9A9tu7Nq{dr#`vBt4?{aa-F|Ng-bhME5y1R}4m z$j2Drs~kvpQ3ScPX7XQwKXDJ&J>+t=+>aLo^sf?Gy*@Ahm7ei=KPK@%IR$f?f%;hM z2a)`F-zKp`wyPKOXB^@yvhA-U{=C1FSfiZfrSey?nZMGh*O%qLsww$+A1JXL2{S(Z z+5buSKO-2vOCqTF z^ymGt#4PGhdpG{SaQt~6EpZmt`RMP)Uy}`Qlm86E`-T>NT6?(mY!h#anfi!^{=6@D z=??uj#g}taMdbZV%kbY*#gP}s7vplj{F!W1CXCPfm=?aGyn>)rgZWE;;`d}r)SveQ z@4~+c@ku~G;-5SI{Jgg2tJ-6NjzIcR{l7#|I+H)Hi!Z>xhK4}b|Nn|!rP$!u(H|dA zn62y%@t6pdjgbi7{;F=dysqsd3I1=u|2Ki;cKzR-;Q#9?F?s!oGvHnS`UL- +#include + + +void gpio_init(unsigned int p){ + bcm2835_init(); +} + +void gpio_set_dir(unsigned int gpio, int out){ + printf("DEBUG: set gpio pin %d to an %s\n", gpio, (out) ? "output" : "input"); + bcm2835_gpio_fsel(gpio, (out) ? BCM2835_GPIO_FSEL_OUTP : BCM2835_GPIO_FSEL_INPT); +} + +void gpio_put(unsigned int gpio, int value){ + bcm2835_gpio_write(gpio, (value) ? HIGH : LOW); +} diff --git a/src/gpio.h b/src/gpio.h new file mode 100644 index 0000000..aebeb90 --- /dev/null +++ b/src/gpio.h @@ -0,0 +1,5 @@ + + +void gpio_init(unsigned int p); +void gpio_set_dir(unsigned int gpio, int out); +void gpio_put(unsigned int gpio, int value); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c8faf35 --- /dev/null +++ b/src/main.c @@ -0,0 +1,126 @@ +#include +#include +#include + +#include "conf.h" + +#include "MQTTAsync.h" +#include "mqtt.h" +#include "gpio.h" + +// 4: relay displays +// 17: led strip +// 22: relay2 +// 27: relay3 + +void onConnect(void* context){ + MQTT_subscribe("coolhaven/relayClient", 1); +} + +const int gpio_pin[] = {4, 17, 22, 27, -1, -1, -1, -1, -1, -1}; +typedef enum action_e {TURN_ON, TURN_OFF, TOGGLE} action_t; +void action(int relay, action_t acct){ + if(gpio_pin[relay] == -1){ + printf("WARING: invalid relay number"); + return; + } + switch (acct) { + case TURN_ON: + printf("ACTION: turn relay%d on\n", relay); + gpio_put(gpio_pin[relay], 0); + break; + case TURN_OFF: + printf("ACTION: turn relay%d off\n", relay); + gpio_put(gpio_pin[relay], 1); + break; + case TOGGLE: + // printf("ACTION: Toggle relay%d\n", relay); + printf("WARNING: Toogle not suported yet\n"); + break; + } +} + +void relayClient(MQTTAsync_message* message){ + //message->payloadlen, (char*)message->payload + if(message->payloadlen < 6){ + printf("ERROR: playload to short\n"); + return; + } + if(!strncmp(message->payload, "relay", 5)){ + printf("ERROR: invalid playload\n"); + return; + } + char relay = *((char*)(message->payload + 5)); + if(relay < '0' && relay > '9'){ + printf("ERROR: invalid playload\n"); + return; + } + relay -= '0'; + if(message->payloadlen == 6){ + action(relay, TOGGLE); + return; + } + if(*((char*)(message->payload + 6)) != '='){ + printf("ERROR: invalid playload\n"); + return; + } + if(message->payloadlen == 9 && strncmp(message->payload + 6, "on", 2)){ + action(relay, TURN_ON); + return; + } + if(message->payloadlen == 10 && strncmp(message->payload + 6, "off", 3)){ + action(relay, TURN_OFF); + return; + } +} + +void onMessage(char* topicName, int topicLen, MQTTAsync_message* message){ + char* topic = "coolhaven/relayClient"; + char result = 1; + for (int i = 0; i < topicLen && i < strlen(topic); i++) { + if(*(topicName+i) != *(topic+i)){ + result = 0; + printf("topic corect until char %d\n", i); + break; + } + } + if(result){ + relayClient(message); + return; + } + // if(strncmp(topicName, "coolhaven/relayClient", topicLen)){ + // relayClient(message); + // return; + // } + printf("invlid topic (%.*s; %d)\n", topicLen, topicName, topicLen); + return; +} + +int main(int argc, char* argv[]){ + printf("==============================\n" + "=== relayClient ==============\n" + "==============================\n\n"); + + gpio_init(5); + for(int i=0; i<10; i++){ + if(gpio_pin[i] == 0) + continue; + gpio_set_dir(gpio_pin[i], 1); + } + + clientConf_t* client = MQTT_connect(&onConnect, &onMessage); + if(client == NULL){ + return -1; + } + + char ch = 0; + while(ch != 'Q' && ch != 'q'){ + ch = getchar(); + switch (ch) { + case 'q': + case 'Q': + MQTT_disconnect(client); + return 0; + } + } +} diff --git a/src/mqtt.c b/src/mqtt.c new file mode 100644 index 0000000..2ebe9c5 --- /dev/null +++ b/src/mqtt.c @@ -0,0 +1,162 @@ +#include +#include +#include + +#include "conf.h" + +#include "MQTTAsync.h" +#include "mqtt.h" + +clientConf_t* client; + +void reconnect(){ + int rc; + + if(client->last_reconn.t + RECON_TIMEOUT > time(NULL)){ + if(client->last_reconn.c < 10){ + printf("Wait %d seconds until reconect. reconect counter on %d\n", RECON_TIMEOUT, client->last_reconn.c); + SLEEP(RECON_TIMEOUT); + } else { + printf("Wait one hour until reconect. reconect counter on %d\n", client->last_reconn.c); + SLEEP(3600); + } + } + + printf("Reconnecting to MQTT server\n"); + rc = MQTTAsync_connect(client->client, &(client->conn_opts)); + if (rc != MQTTASYNC_SUCCESS){ + printf("ERROR: Failed to reconnect, return code %d\n", rc); + client->last_reconn.t = time(NULL); + client->last_reconn.c++; + } else { + client->last_reconn.c = 0; + } +} + +void connlost(void *context, char *cause){ + printf("\nERROR: Lost connection to MQTT\n"); + if(cause){ + printf(" cause: %s\n", cause); + } + + reconnect(); +} + +int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message){ + printf("Message arrived\n"); + printf(" topic: %s\n", topicName); + printf(" message: %.*s\n", message->payloadlen, (char*)message->payload); + + (*(client->onMessage))(topicName, topicLen, message); + + MQTTAsync_freeMessage(&message); + MQTTAsync_free(topicName); + return 1; +} + +void onConnectFailure(void* context, MQTTAsync_failureData* response){ + printf("Connect failed, rc %d\n", response->code); + reconnect(); +} + +void onConn(void* context, MQTTAsync_successData* response){ + printf("connected to MQTT server\n"); + (*(client->onConnect))(client); +} + + +clientConf_t* MQTT_connect(void (*onConnect_cb)(void* context), void (*onMessage)(char* topicName, int topicLen, MQTTAsync_message* message)){ + client = (clientConf_t*) malloc(sizeof(clientConf_t)); // keep this util i say so + int rc; + int ch; + + rc = MQTTAsync_create(&(client->client), ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); + if (rc != MQTTASYNC_SUCCESS){ + printf("Failed to create client, return code %d\n", rc); + free(client); + return NULL; + } + + client->onMessage = onMessage; + client->onConnect = onConnect_cb; + client->last_reconn.c = 0; + client->last_reconn.t = 0; + + rc = MQTTAsync_setCallbacks(client->client, client, &connlost, &msgarrvd, NULL); + if (rc != MQTTASYNC_SUCCESS){ + printf("Failed to set callbacks, return code %d\n", rc); + MQTTAsync_destroy(&(client->client)); + free(client); + return NULL; + } + + MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; + client->conn_opts = conn_opts; + client->conn_opts.keepAliveInterval = 20; + client->conn_opts.cleansession = 1; + client->conn_opts.onSuccess = onConn; + client->conn_opts.onFailure = onConnectFailure; + client->conn_opts.context = &client; + printf("connecting to MQTT server (%s)\n", ADDRESS); + rc = MQTTAsync_connect(client->client, &(client->conn_opts)); + if(rc != MQTTASYNC_SUCCESS){ + printf("Failed to start connect, return code %d\n", rc); + MQTTAsync_destroy(&(client->client)); + free(client); + return NULL; + } + + return client; +} + + + +void onDisconnectFailure(void* context, MQTTAsync_failureData* response){ + printf("Faild to discontect from MQTT, rc %d\n", response->code); + MQTTAsync_destroy(client->client); + free(client); +} + +void onDisconnect(void* context, MQTTAsync_successData* response){ + printf("disconnected from MQTT server\n"); + MQTTAsync_destroy(client->client); + free(client); +} + +void MQTT_disconnect(){ + int rc; + MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer; + disc_opts.onSuccess = &onDisconnect; + disc_opts.onFailure = &onDisconnectFailure; + rc = MQTTAsync_disconnect(client->client, &disc_opts); + if (rc != MQTTASYNC_SUCCESS){ + printf("Failed to start disconnect, return code %d\n", rc); + MQTTAsync_destroy(client->client); + return; + } +} + + + +void onSubscribe(void* context, MQTTAsync_successData* response){ + // printf("Successful subscribed to %s\n", (char*) context); + printf("Successful subscribed\n"); +} + +void onSubscribeFailure(void* context, MQTTAsync_failureData* response){ + printf("ERROR: Subscribe failed, rc %d\n", response->code); +} + +void MQTT_subscribe(char* topic, int qos){ + int rc; + + printf("Subscribing to topic %s (QoS%d)\n", topic, qos); + MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; + opts.onSuccess = &onSubscribe; + opts.onFailure = &onSubscribeFailure; + opts.context = topic; + rc = MQTTAsync_subscribe(client->client, topic, qos, &opts); + if (rc != MQTTASYNC_SUCCESS){ + printf("ERROR: Failed to start subscribe, return code %d\n", rc); + } +} diff --git a/src/mqtt.h b/src/mqtt.h new file mode 100644 index 0000000..3d46ccf --- /dev/null +++ b/src/mqtt.h @@ -0,0 +1,24 @@ +#if !defined(MQTT_H) +#define MQTT_H + +#include +#include "MQTTAsync.h" + +typedef struct clientConf_s { + MQTTAsync client; + MQTTAsync_connectOptions conn_opts; + struct lastReconn_s { + int c; + time_t t; + } last_reconn; + void (*onConnect)(void* context); + void (*onMessage)(char* topicName, int topicLen, MQTTAsync_message* message); +} clientConf_t; + + +clientConf_t* MQTT_connect(void (*onConnect)(void* context), void (*onMessage)(char* topicName, int topicLen, MQTTAsync_message* message)); +void MQTT_disconnect(); + +void MQTT_subscribe(char* topic, int qos); + +#endif diff --git a/src/test.c b/src/test.c new file mode 100644 index 0000000..239b46f --- /dev/null +++ b/src/test.c @@ -0,0 +1,35 @@ +// A simple C program to demonstrate callback +#include + +#include "mqtt.h" + + +typedef struct data_s { + int num; + void (*cb)(int num); +} data_t; + +void a(void* context){ + int num = ((clientConf_t*)context)->last_reconn.c; + printf("Hi, this is a. you gave me the number %d\n", num); +} + +clientConf_t b(int num, void* cb){ + clientConf_t data; + data.last_reconn.c = num; + data.onConnect = cb; + return data; +} + +void fire(clientConf_t* data){ + (*(data->onConnect))(data); +} + +int main(){ + printf("callback test\n"); + + clientConf_t d = b(5, &a); + + fire(&d); + +}