@b_LKfB`U&oJ30*q@Liye6y6&JJua zP;F`kpEbPuTx~&JONSkN2ALhCd8f8FV@Xk6-bYwKKM^P!gzy)kcNpDP$V+{At(29X z`Z{uW%~N4gjs@v@g`X?-E?lJ4g9%^;2Dne^LZ zy9|@9)4&gY*K6NEn}I8XpP(N^I6kLyH3mKJ-@v48ni09~46|h147>WE8*`&em>V)_ zdam4lCmwqxx$>;re@AKGG 2GOIk<`i|iUJGjCk%t+XO4Yf9w{`9i*y9v$2^!gVFbg8v zR5vf`Q`n-a?2$ckz#>j-`nu4#X$^ysZ(P)LPd?iS?c006DYC(glnr?#vxSu_aeIT4 zLd&h~i{H&~PUd{l= lz=Z_ih-qf1=)_nz@13zH)!;CCs4>@F+8 zJFSWE&R@{)*t}kcUoW7;zb_uq0ejTFe9ziSl#%PnL6X0yNv7wRh+igdtunHY=w)1N zwhFJbA+5U$Fq!26BYued_1-}s>V@dx*9lI^J9SETplzX?(R?G g$#VucrFjzecYlG=nHg_V&Rgm#=LE$2@~&! zcDwU}hYm(;h{v-6F=zn=r|=W>KqtM8>Zlu9jo_|9z-vyqKp}e>8R}FK-i}Ra_T{ub zyH7)$>~7s3@lByz_soUq$N13$?=;gJpcBV45Us*dcBur1S%z+H;7S*9IaL%PhtyDn z;yB_zIPS)p|qf{SIAajPZ$izwA-jA&F|jJ{UwF>6D2@DP71gNp(UYD81Er{yZWA- zsXk1Iy|$n36#mr!`o7>nRe-TAZ(C^eV92V5pnlU-bj6sQojBL)hs3A T zdL@sy1`QvMCbf-Ij)G_UK{j$rv!;y4Z+KZ>D@zah!&c @~aK&IQoZsWAqzgVZd}^EuLbRNGFDEnR<}>(>2Pz;_>e7TP-)+a@)kxLB6C z9^@4?y?Q?k$m5P#qdbDCmnB>_KvE{OF7KC4V-OA&O7_9gQXj;DhCq^ 6dwX?)Uvza!t_pex`<+#3`E&j=36^G0!5R#IPy6x{H6~ze}BGZTQtsR>A zHX9bSO @E5i44GU4&J<}|qK u7ihv;`8ZpVw1pQ-ge8wbL!K}K_0 z&M+NAb_v&@TfqUw9A4$(L+e|IB((L2LEez_sldy$S)Qea-?0!qK^BK|D5jeUN9SG( zciXG5Qs*U|Y*RuY4RWTr#H*6`O@3A%D-<9d*FPlJ>lf~FY45D-Z6Pa5XiLP`fQ){6 zW5APK#^k+08A$ZI^X|i_c?M!&(W~B3v)xGCY!Vq|j$O@V>D`uz+PY$OfaD|mywz!T zX@wk*FT@uy2#{C!nMb`8mJIm#MKJ(9%B1=GTD~knv385N_7-S#H$b5`%$T00(6lq2 zdS~ni!IG)3^2hP6L&6W =D-`04bJfpz9y8Soxdb5~sEK#nB0?WI)7qsvb z$W^yB91WU@qVH?jiIfwVsN;H6sz7)7ZZxWs#1UVNYbERr@swiu-C_ ffiqFk%~$u!`i*-Aq!%6H zjWn`HauNSEfdA|1Z(2)MHmGDudWc)Szj%k)2am&qmE+GLOQ?B21eTEBrw&TMLIUY4 zUeF$6?oPCSr5Hb@tPU^#)R9UKdF2NxeoE8S^{2wviW`tSz#TJis^_<9}*r2iP2 zbjrRvYXAIw{Q>It2rL{^1$3BjUplf9wDyd@k3OGM0aGSnUf)SgHtKx+b0fTU5tz<( zr0;ubuSepJmO-fe*ZBE>5Sil7uFappoP)qFlC)!kX8y_0zE9< ~6z4T&+MpJz#`hIITg0ZIez-C$G?4rg5g$t@boBwrVoYBV1|aXlpqs zE|LwhAnb{q)etOlS;i7Z{-+3B1TbS 7k3&QfD5Wy2U^b|K@Qoo)27U(k){4*<%s7Q7J{kYxh zFq lq~&T97vn4RH_o7BcqyB^aBdQ;8sT~|Hn z1cM^5m}|ZVMwPSMVAiJQE=vj4T2(V*yT*K%Qed2s9Gh$r`R&OCpwpQ4_=}r>JG^e; zM6X`>0xuBJc@%-<*~BK+D!XB9YAw*zlD?F$B!-vcgqWFADv6?xF<)(;wA>ad;WEDf zDL&OUK6SoaK}_Gz<3=tFv4A(J?ax{1{wl{);pr@RqwNgB$?S%9wW4D>dyi7mq*Bx5 z0$c@GeDCt@*4a<%2Vh7e1LA)Vp*t$Zh=n>aRer7;E6VY^oK;3GHQ=UtP!SW&(p#0N z`e)*qw|d0%oKO6uH(6~sFdd}B%wYYR--)54j{v&gmC^Crg15Cg?}%i*p0GYP5Nsc> ziCf9VKjJ>66ntycC=`&FNu_tsvo-u-)QdQc1^4YK_HTad@3gw=7f0Aq*%FPKkV6jj z^g0=1WK~zwuIuZx*0Pr^Tch0c_+n0UO!g{6p``NNldGEEz|4r?2-gO#AuhN R|Ekwtco!=!f;4@DNSPDpLCZD%}!TdJ}>in;`dyPVKN- z%VjL8)==NuL&$f@*cX;a8HE?AR*k&*ZI;46A4H&i>mQz0H`Lfdxoh~k#O&70*=Ohg zY;!SzjLxz;SdCu88bd?N3>u#sf`U!*3G#SA@aL9LO78YIQ p4Gl>e8xjlj&ysM%-FjNoy5|#p5)*v{=@5D)0FM}|S)U7yOm4W= zzSfl)Y1ZQLf=E;Rz&qAp7I#=moyFScKT>rflJRTKUuJYS|G#E*Le6>y*7hb=mj6!L z{bfcc3m5oFkR-m34;EY;GMM}et!)}RFk+@ZzZI^xQyVzwF4sa%YYaIA61O{uellJd zDyg6O*=X{ZXLCGXYZEu?8+COReuzaP#2Ac(Vo#+nm(N~-z5X;p@Vs;@&^5*54ASuN zEZyah {dTle16JS)Z0A{Y#+DM@v`#CiUTR1XpO@HL9+r%p!_FH{Jc=2XLGBoF z32dN*l~F*$d1ObY3xP|+O)rp ;szS7{_ew9}ERg)9eAk|NNuiVjTr zdqd$<1_%;+Q*U7Zo@pIy<-c+Nf)C*<+sgdE&BI8VSeV%Vg`t7If&M?ROo*BI3(J71 z0RD#DVz3Y0w-Auh8sT-5B{V6?QcSQ{2o`JT`W2M>2922JtMBflyOJi;zfzZojSi$I z-5HuZKAk;)t$lNS7*SLcRT5Q|?8{G75Jj`dlmn1`^h-2QrzblKk%m`B6IePfD(=iC zErQ5z8yBtF9fp+MBg52|lzh5l&Y!6$j@DGygJ|pdwZu u+l1Fc+o;jniKnk*iP+uXr#+z>gSsP#~=03Qls z>%;+b#&l}Ty2|K$)ai+ickbA{YHZV$2yIN@Rk*?-+R1|$0v0{g!HVJtz*v3m^H}Kk z4)U#>%r@fR@hqWns2u;olljY&3hzJSDfaioS_D8!W|bGt19FgBOpJ_bzmC_(cTQkk zK!(sd8_6FD0v{ffm2Gl#nY2d7DZ=%9^CX8So2OKl85gBjxP+$d_F!V%ZTJ24@)7r& zR?V*VTn|cLy?82lbnXbc^qSgG*JDQ|ZoqF%3HX47G?8hSx;|h{vPE5V*V5H%S0^<$ zHQS4fnF_unT$?auG>A )40^u`S4`_`ktq%*mv^DV?bFPs-d&2!Gn7&gpoOVAE(PmJ3I z@*%b6-gJlW4Y161lXT|Zqbx2Xi6ZJH*CB}*`$(K5dlI$>Y5|?P$wWdT{3h@}SBwcU z?JgV~NjT7}Q<=;Z#(&x%a9Nnh-IED~1Y(QxK&)&+h3L#ORjXT^8GIh|q2zij?h1mu zso0x%70ktyO$Clt$KGcEhEL`^?{G4;6kdkWJ2|IHLo%lWN7dUC5|^N$5NWk~UIN5a zkfh}F=S=!~AX{a$SMUW$VeC-mm-@yfM#r-ShktnrT~q!>3_;=K+}yHA%_@4rMtOO{ zPXxH9>>!svTtBLu>iLbcGrt@Lf&M)dqA9tP4!%O*_A4Czv#Ru8o~!>0UrA3#kl&6V z-2acSWS~BDR(XG|;D4DyzHi0mj&J{ePV%-*fxp$06Q-!Jz}~z3vy~Ba}%pgva kMVi%gq4{nmz^I4~K#Z%#wWY{U4r{Xx?CgtY4F~@b&x8 z+U|c%l%RvPxrv^Ry@7;*%RdQFmP5La7b$&0IoaQzmp3;LAFhYlp3ej!`dgSUuXuh$ z9X;mqY4z_sYotiNfFB5;TfeZp17WVs;gF`M+o#UbQXU_k-?zcLsg b3C}K zg-yEZ*z`&7a%=R9Tg1oW2(iTMh=sr7L9^Tpi$-JLYialVE=~4ni@A2el5}=9plT8p zx9nG$aOOz?8AVjW8B2RlAt_2+IHTR`Tasb&I`7_s%I$Z);Vl3$^MW|buZK9`MYZ@G zOGWacltHvmB<;ejiNx}t=9MSS7HtvKgfS>pF%_}NjHcFM8!f1K;9AmTmd`oTKLVjs zF9tN+um$}5<6T~=M>l7xpI-2f#mH0y&tddyA=3U|nuq=i2*6)n!GG07{bh^#uiZp~ zg2k74C>j?_nmIpM;w%D1zPKVGc!IWt2N@poVD8d4s*v$`N35jkz=GpKOJ?lni%;u9 zt(O5D*1ReMdy-IFBr~8Df?Hng+;%HYCR^yf%0u!>z2$o% z9~Fx!)3ek_D%y+r)ynzdgo?zm6VZXv)xcFpNgsY0HZ4o`dyTT1EVnnm(*unmM!U!w zv-jlH_$l(k(+N!mtqN-7Cqyug!WlTYRiKz6;XDfvGK;gbG$xngL2Mw`jasUvZWH#p zfe9jA@N^3G#+D7wc0G1Qy`r37sZ4n_2CRwcuOroMMh!m>0`rFFV)^3zNQOj}r)G)v z%hN6r7gq=D4P~8T?1k@9%^Z}Z3tv%7Go7Fpvk^=zqwO-boc5$ZayXnyn%-Q$P18_( zD{CmZ@J_u!$@==sUJhjT!;AAi5)+B6ldKvvJpMVzay_nlcZWQF 197dehD z^>n^1AJK5>D+dv#_37d+AA1XN)|#!=c|t718mIN>SIsEBgUq-kbU1 % zT7u;j_<=>h6VQMA`5`@W3Ql1t-w%3$=#o~;mA#BR>%V!U)Fm%z#Q6p@Cv;B-r_tq| zrn2Ll`*l;#HsuAi!UGnv3`Q~5hrWU({t!(g_&uxSdg1f$i&%`@Q;GB!FK>PwFG&95 ze&!#P@bAM#^n^4J9a4Y{ywNxKYtWvo2+W_Tj=SPuA()8JA;QGeOY=G5M19@`Xm>Lj zPv5xXuP1qlg$G4hCfFX$F1a3WPv3#N* R8cX(9PUf> zL7T2Y**VYF&tvYZlq^{0@`2 iLenSx_?Xw#7RBRCVI1I1y(2F{qMT)>|F*8Wr|T7A zk8@f>9leokCuBbOfpTndCg=&?7Q<2&FBfvrVfA-Nwg)Pot-s({`l?)|`agk0>`SRh z$oMZ{G8Clbzp7R}1o%-B6@f@Yb9223xAo+9jJ$#4mE@3fAOKibjADbd%_#%x;6$jO zaiD*0wqUPBR39Ya_;hPrmohGvFBYpd@6H}^wYt8O?zqs ioId)t<8IoLgCpf%EJ?z3J#O*+9NoOnv1G0iYDbx~AxmCD9hO z55YF$TF+l8_tL^?B;2e*9nV)&qrHp)LhhC7$a5j8K )G@ZQg}eo@jp?AWDm !wWsi^?fNA)hG7E$Ld>X1w9> zI V{y*nz@fzL!zGH5a83kZI*mc;edKa z`&MqSmD~VACrGP2{1EB1B9{*rcpOG{=d(~BLOSlre*!rxa`d4&!c@Nm^rAAOL{YCN zQ|i(jc#5*x2WGiM%(+HLVQ|{GoDqrJb0qeM)T6^dy-TXu;uK~-`JVb>CUuaNIJ!Yn zR4&XX>+hjU+1EsU{KY15U#Fx0?418EHu?9K_^-hIci76WTF&vpWk{KW2Jy}@O0^^b z$k|G|X*grZ5%~G}Lw(~_T%2YTmWOLrCt7p8=EZ*z;(XBxgv|n-62C8o^VQ_|^0M6l z{^!&4IR|`4?x6v_@n#`D7u5`3NM^!ObPUlmB{*`Pn$wQfljV_!MmOw%)v ~XNf6mEdV+<+br)(hZ>6&U(nZX6BU zK@YvT&U#0BD#12kZ!O`Y hr3Snw Z~)zB^{A zxd5q8bs?F&TbUL$*o)Koi&wMiNpkzSSQHcmoc<83TPJ?2rq=5Iq|^p}gH}zvF!690 zmL*Qo56Zxq4`|p3;5T#-oxCR~DiAkFFKM4MBoSy<3SQT4H1n4G1eGw4oL;6}{Pi9e zRHZBsi)~G0oNcL8=zNH_4*x&eOph?EOpjoV(RR31+m$|UplkQ>ZFEzU%?-*j6q~ BJR#}|yqHTGkbATFrtbt>z141w%c+(7bP?|vn@1Y2Ej }FjFVe?sVqpazxv3&j1R(#1INUXAASOtB z%nnpV$CV{G2T?S!L!H5%oI6m5gRu4BUl(1roNY)TAXvGmY=>tDZ|;Yyb+4z7QCZ&% zujyeC^~4n*hIQJ%fg*}amUfhekRew3yir4r-Z`}R^vqi{j;(nIP(7XxGC%I6`;@QU z?B3M-)Xa<4udyyUuHxp~7i_H|o6mh7RZ=Wx-;1{)7Dv1A-0l1NJd5`x*98ovfzXG| z5cgoH+zWIrSXf!lXk+?-V7O2k({GnKSTW>zV^k~kMu!b}56~6uJJbKzNAJ~S&v2}= zi*L1BjPfw)E=&KWmedQYZijlPl}8=hTGBYj;eL6ib0-d8hfVBEiijOJDN^sB+CQTI z{WfB74M^yIk?7XZw0utQm)4^?UYsVM<7<~H>-YyvXK2)k7I5l`3VsfZY|CRc>WQ4P zv-|R5p6y9;5t4OkaltfXZnF1c^I9mgl%%?|KRRTRw(4-6b`EZo)VP|nZxKr7c1r*% zDcm*q&`7r^&>s+C#C-;Bhz;;$5$uQzk +@rSU-qg(Ka@;CAlp|V*$pH;! z*v){`gxgCarK@I4(WSfWy`vd1 *uIoCk Wv z%IgOWP9LOSV0E6B%#uGg<{jh(&`WcUYHak^hkz?YWEZ&eoP*2sk&81+>bC!J#%jBg z-hTd~zc|SMn~?su2Wf_qx}Cft(uZU0f&U#6L_DCLTr`GI3JeUn;AaDJJz%t;K{Tva ztX53M%~slVQp`fG2a?5#q4VjROebsj&0ctZE(6Te2b5RfZn4?9|B?iIp=6O;RmWtL z<>rc;l;`Jb(&jg;ZspVIki}eQ2$4MFo*L3#=L`ocW3;`#v~uo^aJ=*_gJyJ4o7g0I z4C&h@2DxzUcqS`4ZA$S$qvyU=j7g!HK%3vh&TLaBPR=e#Ns#Rtf3%H(?Ba(#{4*y+aolsv?*u?WdeAFSQs{NUEA(gX zt(!KKCQBXHbUxGGadAMHfs*PlNf7AAkr?P )*$& zIK_sX^~mhci~1cVSM`UKLa;0=;}UsaXP0gVM6S~erKawF*479)5_FoaJa2r;=q8I> zAPuhlU{z2j0*tU!+-1{f_Bm;Y)3H(=rsN}=$XbO4Qdo55IF_pPmsPY*Ymq2v=}Er` zi?~HiXYtxnfdEkvbjD mVTyVAKMg3Xiv2JQ01ZQk=|l3E#|m=nrRn?Qg|JP*3fF zliVt#EJmeMm87+E`8K1J2e%cW2cJMVsCmEw7h68p5{`o9ZR>85OEPz2jp~D_js|cV z>JoS5c%((WW=BkhkE5IOcTG6+^f+$ViFHnrd+T8!fBHmF=pI+2?_?M22nRvR1VzP0 zsw#B_vH561D^}{^Br$yza{{{;??P0bJb~e!vikqV&f1dqsTjMI^9sSh)0|A0UbNO6 zg4S5DL2R;j4`jp6vV+&!l5iD=mPYf*fQFNauXHz#h*zV7Im{>WFda{1k0Rjil=Px! zAgb$ZMb??)Ab`Gs3#XGz+sAXhL4a;wa&EsMgle0mQ2m${lfM`3W0e1{6l7xe`vo{I zR3VL0_gZLIfB0@m_Z Py5 Fn=nRiQg$NF;k|b*mRFX$j_#@3V&^?Ti4Xgkft|=iHMsgGA+g<^lfHklqNa< z*Spma3>c@x><=LEx%8t>*cegjUsriR=lM*MzqFw=M+JMTA=|za)o|qGqwVYw^VR;I zSC9o-7oA0gAgui5PdvLWkv|Id5kBp~NaV>sC*VIeZMlmH5W&&T=*HHM6_13#g0O(( z;;rkpu&>F7 LCLTO+vrIYjBV%vT|(0y`)S@9 zCTI#@O%Nkq!7B*pp=V}*#}g9dQ8VEZ3CIuurG~>pEinc*(Z52dWevcZoK40WVw4gI z8`SbSi1({9dGHX)y9C8>)jT=WL0nE3hHx8Zh>^>?#W{W?zq!!C%_NysS&;$A!l(Um zAGqm;81pzP*>(f_1RBAF`+zio21WGJRn`^(qlu;G9RYE6RC4vb1RvKtKmI_rI7F!~ zP_J3ZEH^hWr^?GqOCe---c%YyY!?}IzUeZXt;BGPuv~E{y#Z->BQ|g`n`t;MF<8wj zMHD}gcOX{cyZ
6k+E8%rlAl)R#*({in%{lI_}CJmf*}*zkej|ly6eK&xX*(L3bh9PD8}&uMDbAg zcNstN@L*i$^1qeMURz;oQ1r{SUk-6%$&U?ru;y$NcKzgr&q8|Y-$!J5?9U5PMwHqm zze`jZ7iARb8_ADBYDT -;ApTw_AsHl~|{1tBb-w6x6h1>%AcQHoaAhR~4m z`24pS;YzPro(7pJ)+LyTvOgmHy#-CH{3*dmyT0Y|MM&&*v5!LIT|U` gR_9Md^0mfq{BS53=w`!CEHwGVq)dGwtar^<%+Sn96MAGig6nLh$wj`oFsPv z6a^)cuFNMb7Eun>-jT+vO%x}hunglGUq{h?H+pIJog&awp>_QtTCt!oPuyAceu?$a zphPcMp&Sz#Quqj8R&!`}(_AnH8Gv$%hy)(vW`^nX=;yWbAFv_G^^O>oS<(C(rRW?I zq=JWdO4PdtK?3aUc$=CUgKb4@VHt9SsF;||XVFYGb%0i^MC2QQs;N0M@;-)CPga*4 zD{q_HmoXKEfw>7?S?<<%iSj;q TPu{R|0K8ZNoA*Sp{50--ZnZ~h{P;P@%h@kV>jwm2NUat2jn1mfw zq?JISe_}7kf4_(qC(Vp2qqxDPPAcol0iCP>iY-&iK@A6kP&KU9w}~X3R#%}Hu_69i zW7({jk$jSUt~7Dj^<%4{rAY75#g1|2C+a>~y~EL;MA`wG+6?1o>vNH)ZTZED9*coA z+Sm>`HS!m_U0RvM$W4x&8U@ze*(JS1eZKc&(df#VQS)cTV*}#N#+EURAj7BjsO}ZK zQo-iqyx~l%=EGw ~k$QfD5) zq|KL8Stiy=Hqy{Hsk|PhN75o}Z?^h0unLG(U+L8hi(b?bDg&Z8evY8j@gi4BR80d) zAxrPpv5qAx4l`@nuo0tDmM5+!uvoawjqQl*#y+X3Uj0~+Dw$gGYtVR-$%M=2eyo}G ziG>~;EQVpw&Cl$b0`UJl(^2SV0vskR#u7>elDN|!qlxu6WG8}5oz-wIrR>qd@DKcX zv}ZGOCXbB!c)-YSXXS GI$FcyciLem0iY5$ z!aV9p05W-_QMT_;DH;ywM0pN(+Hu(j^&oOEuYTArd^AG>2`B^^h;e9uh`7RIdSRe( zJs>@U^jO1Y>Rkh0YQ$$UWO}ir5qhDd65BxP1lz(w*)siBYQ9ktJhFuXHB+Pv^wvMV zzF9;J4k<(m)za8JBEq-qwB9w;_a|#D^y;#ydMDG@Q_b>2hgU9qs)kvpJrTl1AzudD z#ba1Ry&AE-^eM4T`={}Cm%9R!nB5y>q^aX`2A%0u<1_iYc$|`uQn~jaA|2GIq709f z`&!WQ&0o%=^e(E^fQapck 5$h5LSdr%-5K3E zVS|U1{s #mbV06B0QnMc^=_2Xf1yA!vXx+ zdsR)ks9rXode!Xr?&yZKJ+0w_!^T+TY(Xob!*)-v{^d$O)m(9DVq!V~ImY$YRUT5< zO-%8DYxHYJfZNQkNgy2^fnog%+x_G)_ 2aABczj2LsI88ZjA@ul&vB#`{&{2+oz@;ttwEAE)kyq|l*4WZ znNeU^zZnhDDbi2c-gP^A9$lyvTBe3VDhAb{;7;}+3%f|m sxAK)4u!g^PNY8up79UdmWzZ>jvtLx7=FV{ti^|iF`k~ kilMQH;)?N!#-ALf0LkcN(D^d`~MQZCA0{ z#jUs>C%~i#XAV!$EHx)`!Owe(`Zp>18THSkN46S#Cjn@Iv S zha Gg!GbRb49otUck`YVq=H zp @lQiKwdA(bZ;oD3ijIi*X<2Nq>gW3#9@&pI?;q>zd7hd zfdEp*GALa;S2HZZgWldZb?%@Y&-gVzot}rGoM-4(1~-DdxcwDm`;|jEUmDu<&R{sp zDf(w~k*4KFOZL*BWcS93m Vuv6-s;LN_%Wn{LZVx0nm|Y80IWw1&l} ne+1T9*+eZz&d`6^ND2y*a+&B#rC|9j7a?4Q+$hZcLo|0{#L>I0yv|G?m zrji0~uhQJA7cHoG9GA%3-brG((`)a=5XO=|$DtKF2$bEU+^WXl_1FwpVoiDwIniz$ zfn;3?3KX!46hQMQ?pa7lZI?rFFdx!qVz;+HI8A4kb2CHR)S$?|BV`*Wckg+Q7sIrS zuA?Y5NZ7Cjs{z<0EXdfn64OoW7K+eafH%U)kRhu|vKQs1%_xF(3a1O7JXBJGvc=1D z5GZ8a7=(vWF6c;hfAeE!X&Iq$4Z^Jt*}h1n2MwtbW_2^)?Gm32RX8IwZIii!%j{Zm z`e8exXytX`4&do>%N(t`dxBPNwK-$cY*D%6UT%RtQFxMaw-XLL#iWPe-m+gKrbHwa zfL9Icwv$&lOD${_)#C8PQC!=#V01;RU$wf!TMcJCC7g9v8K8O+z-~9)kZ!~eSqo Mf0f?B(?%Q$9+R>`N-e zQ?1?0j$ztB$4y9d&RJ7Ab;RFsYlsXBaHFP?aFQF%9*Yf2%kZnWsB80+%V|#U5q`ig z&Q+2dB*l~sbj@#XierT-m-Us+Z_l4xsp;LWj5aWS9mc|n1b70`ZGpbeR7>?iU+(ti zkvhZ9|1`2Sf*tFTLqchv;^t`nwI=#Ryk`EGmef)dYLS86DN%mYgv)@r{{2x$5{%ZC zzkHbqLi^i<8ah<7+2G~SGLu`zRf=dFkVwhS>)FZBa+pkYWrm>akGg(~*4)XR-9OFj zMT7I(bBrqAWt4Xro=8enMq{g>PA5%e92&(a%hj MFzs&Fdh=8+;|-Q~00}8|(CQ z7`K$ln0-3qrVJ5GK|+UTg7|e1k+G5Kq43Zn+0lJm0KP(iP!#k4WO|Hq`oa2XPI1(o zt_r2@8EF&s3f&tjCX0sAdRZTE4<9AFn)D|6WUD%hf^zd2V+Z4M8{>L*MoT>C)4lV? zckwOmKwD@hECFPxBc4&Rq1v6Kr=hYoi-9Tl&7u4C+I~y?V}6YTqyo_Gvfr~oX|=0i zbE>+k83q eu=!p~{M1|DTa;*plK5T-9PAuB;*)421K0#7tZN85wAuZha;f8a>QU zdY|7V-GV8CC~-E8l0Ez>p-ODP;3fSTlz_)E# ;<)yNZfnMe=)pat{M2^uC|c7CxbnA+Dz#gnrK@FE$TRJ6vAo+x zvE#xX|9;vnO-K*w*bSySb`YJP7$hk+QN%)oY$sT17;`L#KhoO{9dcWqVG4)<2Yd6-TQGybq0w%(K|DbuwN23sD=*Zrh zX7tA+aJ(LedJ*!Pl%f51oWSS@2NM4dQ#ocs%@0liYA>9_o2IxVX|oe626Y12LCC}Q z2an_~+{3o=BlA%Wruok?;AMZna{54yIam;VTAyFxN}G90r)g U@q zB|B)J87-i4LOeish-Uz5_*5!!z_DT^pT9=$QMWBsWk+S ;$ >CVg%U*SZUVd(NBmfY~m znm>5}?uq3i2IDQaPIna4S|f+yilco|m!!49@@8z 2;B_Hf^TyXJ z>Y L7vIWZ5jXI#T1Z6x3s}0rusSbPc_%wUa-$Hdokw5|O%p=%D1QN(P3ujMi`m zkXEIlVn _?X doL@86jJ0RrYGa zLp=d~P~!bL(tS6au5G&9BOuBg*RBl?f!HwDxPcD5{{7J9kxaO`xAn$48RIz~1B`{7 z)w_Q~1w$&ci{S#oGFFGxo!JLz8_be-=t9A6p6Z3&r^9lPmUC*Pb9s<)4iWhD ;R`C}{rGSdU9ULSl@+44>3fk!%`e)EA$)aXY}6A5fYj zh3lTysFzZ^UeP9x-_>j66$op* lV=~R>)=heg@ignw$F6VW4)Dy9 zP1tNGMXf_T#iB#pj{#-;Vpdn8D2u_(IMg{BRY{IyW`%{$r%&FGA`pb8wO=y7tC5TM zCJ2E$uaJ3Hq|emp>8YLPm+uZw#Si)um`_yKYN>MQZU@kstWtj{{;Ls}=dV98i;;Tk z{P374h0)c~{@6o>0aTm~S5T`cnR-Etuxw&b5_k}XDlh>eG*7= z7h=o7Ux?_SUyNe!6W#3qDjdKR?tT5JH~7gpOu}^CFoq@>xcddxz_f|N1k$xsh)$kE z){u5c6*D|DI0amqZ=u6RlBmW}nK}SFLFge$o9{Fwg9!Uc(8@Z=c0CD$7CT0RYTelK zVi-;%p=clBJ Jq z*xV-ePPh6>gkOGzD&c?BaQwGQ_ uE^U0on? zb3{Z(V5oxpdiIPL8|t@jUyU9)sQhJh( DEmweV2+9*zjCmk=|%)r|pA3&+)Ru4ye1V^GG);IGO-$PbB zoj3-a2iD NkyY#ZNL3=1Xh~5?1%!f=yHs)}*n{ zi}DB`)dBKTg+xg#J6XVDE7=9u=6&cfG+1m@p>stYm{Y1{=z}{kwtGh{`<-uXDld3k z@H6=gZdSpQTD6k@0L%ZyS-^M!Ve+ki9W4QkfzD8Gd>}apX!3H~9wKyDqMGK^pjebs z $gYcY)iwjCdu#f2}30#K+F+wkc|jA%=kdtJWeA zjWWdIX5wrwZF9WwziKV4p@+zat7T^K*?zGpWLI><13wSmYtHCJ&rOOz<*#my7|POV zZhD3r>2YA))C47@qN}W7UQZX;sm1sAN1z=U!m$hQNkuHz!3Ba@tU7m_2a9cH4eeY^ z)E@Rizft=I8cIJyvT$B-4D$L{UfP?~(%0n$bBq-8fTYLFJe1L=`}a^#B~;&_L=g}& z(PKlYtqdwT!1d=CY_{2VIX+NPm$ZOEn8(G7l@dCDtax?(@T;3xNPv{ai}DJ?0Y{S( zq}n=$Am~e8MD5<7TLwZ_90(R-9IN(IwK3^c=@s?1g*eKIYp>lTDk z^Qnb6BksGNB`bqvbN`OiVOQh5#$N6(wg1Dhw!T7J93rnA#O;XKoXbqeBtvZg*$h*O z5T#;C)HRjo@1L9yEu#M37jk)DDE{Z9ftb93j;)@tj;^`Ee}8@dt!C>H@8kU{l__bc zX+VzhHR7YW7?4MFr4-D?iA7x+q_b2(T(=a@s`v}K*huIA-LPT$GoHTjA)ed&j+Y Up`^`2_KUgLmA_1{%|+H z;Q4vMbcpf1z1w3Eeu>k9M??J*3czb21pdn>>^ppYTW4u=TSLV{=mLJjphbz01b;Mj z%~yhL{lfBbUUPN5q5*bweSYP_v8h$}A>HkAO_EpuW4`6{`SbJbkmu6wbS1xsV2p@0#r+P5n?Z*tgghV&Edng-)muA_xQnGamSlucep=Z zM0`3)rg`>h@1}fjT9b;Z##SB;&Ow3R!$Q3h_Pye!VE3mnZ=PdN3!Wljt#*dUJ@MUm z5=N%>ZWATFsHbWCd%Iq(A-do|J_Qy& UBBN@E?us^aoa}6RpFy*30Wp6&|p{(2;kt5 ziE#gheb$$c6RQlm;ba^Tc&1My&jLy)beRdI;C7dHF3slm+1Q6gE>Rd~&PJe-DgrE1 z$RD%&7UgkZ9fzOF^~N8(=lJEUbn3GLRuN7#rG`ylorDBNI-4hhdz@9QA{^+8nS}CO z-8~57MUTMwSC{O}#!U#3&Py$12K#0z=O=2Ml`ZgVyBZHC^=p~Y7w=b40)3&%!9kQ4 zX(VTu4c}<^&S%^nPOke^8dvTKFOefP>0sgAJ96}$+BW9%MB@B?zx4HM9XZW499BSy z2ZhZsz}tfAl!Ks0yY76fGnEVhvh*lMWdVpBDh}8=&P81CFlbYI9R)Ncn@ou@6K;>E z*!cXG|D&<9fU0Wg0x+PYAkqy=cc+8`(%mWD-Q6jvbax}&AuS-y1tj#+(k&87{g?OT z=XoE# t?mGLMIs43+GqGoH@g2-)M+46inT7|s@Y5(^PT#r%x71tfDS&dHbr7Wh zxpR5FN$~~TvFlpaszJ$#D+bP-OwK5}J@=VIP0Tw1HdW~rEoQ{;#i-2Qm0?*>a7yLp zvj*q5nP+^!Lfna1&yH3Vp{(LXM;-vGJM K@V8y0Df+H9Xu*>;wBJ-mUk+x3o+%~w z5l* PH0Yi8RV@~(x6^NJjK#z!(o{c6rDZDEm|il)tj)HVAQhIU z6c#`DT0(~LfopI8ljd?&Me2ByXIW8Q2kR? { zVQlPHJ_0HU1gX5M3m9ylh{YWHnoSdh*iEKlxuh+hr`EaVx829gv4Wkgk %R>hP `T&Q{9i zqs!scYwaJix$kyBG0K9y6jbF6tjz4QWXB$f2neE5%-m1PWy62|LJ)bH?*aKsr$pSL z$wxwxf)ox&?tm;^q9)d4!71}oG@kM-jeL7UTuhVn=V#Exx!-Z!4stzqCkjI`O{U?U z4vKORExu&;;Ap%eM3e7j{i^Uh#|)uRF$W;PBh%o83ZV5nF;$cZV^x=wVCC^=Fmdpg zosHmq*W)oNKjZR{LP
A{5)AKCmIm#;gnNQGyy1EyqYMWjZ)SN+gefK-47M<8w>QbY3coy$P}A|a*WL6 zij;bWs4W2|G_|G^kyvazLHYsF<^iz5uHw@qro6JV9ua;uQhcdScEvP NPmI z1e3)MoQ|pd&~ (Cq|asV6fH6$%r*2yve{Xq{#$F9rvn;CrCrsJqp8yQY2CFQ*d?j5s%4rcPb z%4vNT#I?d=axvhXtVnSB!lW4rhe{Z^MRJu<$Hez;J3clw;+S(C4gKZa{7Jgce$9BF zKe5-NoTI(54n005vxHPG7_NuK^NT1tL}P2%5K-^|KK2+)RxQkz` 8LmBa@#q z N**d7BcRQLw?^Iyh8yTn> <7!N@)$LeWnVIUH%{R4H+6peibVkF6N6jV(nF8}{1_&aZDo_(^gG| GBp_;0eL9M8 aho)$UUfAo6(5MI`GZb8(zD6&4US2bL&GxOdG5d{#l|Ktx0%6 zrb;PeEzj#z3O0i)^)RSSeUrzSMCPTwCvj8_Jq%m|Y?pq`1twMpocUN44-stce9W;3 zPcCWcsMScrQQD%I8y+)=u$nrLbm@D~fcut^J2gDPpXWemY6H7xX_Kk;6Hn}$Ixl&% zCGoaXl3;YB9H@tntc2(%#oF5U=^+qy7r3VE+zADISxI3AXW?H%kELMi*Rutc+P1OT zVHt$;PJSqjV6qE_`m!eRp!<-SGcRo+ vJ2N4;&!~y^kR5&e`tm|9D&e-0`?;1KVeW2-{DY y)uE}g9}^Z!3137#0#*Yz80;QqHe@gueC=jnNsz{0vc^M5 zIwT?v))IN*NmRWK3pa|V`r=t9vm4shdap@dh7HHD!gfwZR`6VB+Bf@efX|$gdkbja zBs}8hx)r|B@Cdf`*nh(Vl6kM|OL_Pm*(V;Ypr 0tf;<2CRWAyP{$Oz@2^}6kmFC74@F?c7F)j6ry{@(Qdn|9; zdZ(&U;%WyQ`U}fp5L@CAtCI_~`QN}!4J!?Yt$q`()7_8`vZv3{4C0UF4HUR~T;`6@ z`0lx2B49+AEi=hjj?ZT!Z&>1DztrwPbrV;b0-G~f4IwgTiHACX`uja&rsj{+#azK$ z54YEQ6(1bBL6>J`f6QLRG}~R=d@$0f&;^sBVV{hl;Md $B zjb!j847^i&urRh=KFK|<)7&iW&MxI2t^vAU6^UX{NIapKnifOv6c9NP6&eiXs5mA} zg?$F(XQP;Cvf-92;vzJ?$Q!w0Nb8@`H2O)}#l?{J&b||(?_84bNJy5;k$+ZD;lRLW zd6w-OINy*x&0}yTO?5fCp9UBZA0P8a=$@i&qHqe7QR5)0u%eIIqPI8rBzGJeXDDN+ z*}}N9$$Yk1Wvh~q_j1RN*|XGSn@PjpofauR8A~Q+5q}j$#QE4gA=k9lAyrwTcTQOk zc)U?kuasP`l-_l2K3{j9Gv71PKsy&@|Fnx+S!#^?*wB$(JHPs)Of+!Wh4=xNHM#Q^ zx!5jf4+?R82l1M&T{^#_A+w7DuFwc)C}GOd+RU =h9 z*2>cQS16Y8srynE3# zv*HgK8>DK1t`(<=r%tI9fY -a}-`>cH4t5ws| zRz;RU7j9? SM Ed1!L R5NnZp;eXNP7+X5ZB1kX|7Xd zn$L b^fmTOtpQf9gy%h! z7pm8a?qoj+elW5 >N|eJYtf~|F 3g)dCUPrpJoNGSxjiO4P|7`o{<>Q*pp~g z-8*fR5hUZ9D&!7T9XFE4CB4GgTO_IPfIGE~f{t_HR-9CYefg9mqt5)rXn$uTP`$iG zS qM?^C#ZM|%nFL;$Oh44%iD`QFp}*;TTaa_HWL^H zzdv22Dd2k6+WGweZ@MtG!?OSJF}2{azYd*o70dY#d!~pT?Dof7T(5UrCkvTrIL{s~ zrlPpNbdq(p4V#aPryGh{+lg8A&!id3G_=tcN)NTJB3Z%I6lx8Hd3d} ZE=1kj z6;fxyHIpRWW9Hjifb~65`o?|h@$1boq$ia0>R%?+F6usy;Lb9k@SbqGSxKNgq`9Zr znSr~Uaj>j(xtd);zT0hi9@K`iH;VA(9Bk$$Gz$fn6b1sq7BnFNviO9swlik1w=iR{ zv~_S`Z~$#XX87I2O`Nj10-7 &jb9m!7lo1??AINamN7bF+R7nz=Ovt&UAzMM<$Tzgz2?!)%O?(A3Z z&M#yjjQ91icM{Eo@x~CCbx+eG2s^ZZab555F~8`1(3N|5^5spOptSmz71=kR^%Cox zSB_hO$#zQeI#iT2s`C5KADfur=&NOND>1Gu=WXlpIL}ut#TRYao>6*9L@EGZuY}I% z`mT!U^OdU^Dqtm=3{o#dp|K@6Mc0**{)1Av#ZO*VkoruWl9?NE2yl1 zD2|fc=f)tr#FlX=-v
RT>E(WEjNZNoJ|*B 9P>+YPqDP8(Pv>Y?7Z=#Ck zN0@Q>a-B~dR1(8I%@!>s_tmkxg>npVzSoc~6VsLQvb0FA8xDMkb_jDT-4JLsFmM<* zwC -{g(HP^WTr=N87 ;cmfZtMzbO^ixFLKM}RHFXB-VPwByjZ(WKi znV|+8H45=sB5}NdCaYJ5Xy$=fSC|_%S(_B~Rm%_Sp3;%8mr_^%G1s76Bca(*
= zr^49Z`K~5)GAy1y9>XJRLBiKw3k9thfEyZnsC4e=p6NQ;8y YIeo31ig|8SFvSBymQrnYg8`tzYXaerfp`>dMG%C>BG zlvbH)5q=&X2UXOksA=o{qteG;x|aJ_o=}S&PGJdCV+q^fU+e}Jmtxs6pnpZOfGD5n z+H==;X{AqiKLG5jt_aZPk7 ywd%G$f$0gw3pW@9-r?fT!c-i50{ZJq+(+nrINE{`i47RC&k*#o~KBEfNE6 z`$hBU%+ROb#*xVQKkSNf>xE`;22;_5!KYj<(@d}SzPOV0`Mi*pwGejMRw+_;macn7 zQg~c-h2!+X-}}PvgX}AN)*4(S9vpf6nEVK-WQ!Q1VZiFg!Yc9l9LWU;Pzb27d+Y_= zO#NJ-m$04Ii;i>=TR=SQw#|qhUN65H^5GD Y%^+JrRf3Xc)hfUFTJ z{}@`ewp*is*Ni8m9h(46QWxqGLo}|K7KO1$Tkl7rj=a!G!*s1I2dI9DRQdhZizzR$ zj%jaMEjgOZOsNhf=qZ=`9sVj7(nDLh5Z$czGzH!0V>Y`uqteuyrHQ^1*rNt}a|M&a znwy#*kjxyg=rL8b9-=g*8r;`v2r+3PK$_l$ )RrWmlo}P5hV-GbD1L4aX{FL`LBpX+ZGQ(sh`a=!huAFSsn)@d z1zeIH0p=&guizfJ0`qi}&Ar~g#5FscEBle)d4_bRwG-&vkgkitRca74?RA0zbM}y@ zYxmQc(asrY*RIO$0~I)gWfBj`nuw-liu1h^zHZ~=k_)iyS$1wQf(xJ(0!Gln91`eV zqi<+oVPj%#Wk_#qYGi-nP+cL3uJcI8CBD7AqodNG4^>W1j*F{NB7y$n!~`oF+rj=m zHZCr`dQD+jSy^+lhPrxFP7Vn#?@L)(SuHI-a;o^=S#1%Kf|eFu9=3zgEWwC~2s{oe z1NZ%T0hwM^1zuXdbl2~fpFXJvp)m;RWk+P^Y>A8O>FY~KNYGGID-z63m1?Z5t}1J4 z0>{Tmo;(4Jj#fBsDSLTcPM=)i +2^;_b5wih`X^B_Ffeq5J3h?sAtxtiVq#KL zQyVXknXfU82@jXFv$F%0N!xkqbG>!g*TVwIB)cEqHVg;ihf+AKcaqs)U|>31pENt~ zNsEe#N=O`@9P6sqjZ93`l$O%*JaIa>x~hyqSrH19dv;l_Rvq;E^~lkPx2NaDhYzAb z nObhpj6G$vz8KAt6KwWGqWBdw!>~+{H<7rx4Y9cz* zcg@-(3X|=FGL#-o!TvQNv91;E4i6nckyfk-jyIxE!!@ncOU|b>9X+vE6nBpvxCd4; zf3-`NUaRE@N2pjrn=)rrG%>MwqmQO%s8<2=f44Lc5EycD%AmXd|AY+sOG-$QpH56# zn88xl$ 0j7`-}!! zj}%9MfS~*naT{w(dKXKJQY8)RaYl5n`SMrP>2LH-m`4>|3E_}T3-9GZF0nbjn;@%X z`MeSI=!&4%36 v1G{*K3^p}Bs>u{yK0d$R zK(<7g0+!Q5Cr4u*MYaBhF&qk3Ruzk)5(hHTe7Yg5E{a~(bj98FiA_lRbR9fICE|h= zWM{N#ag^{1mI4(~zyt>u`>qdlJ)Dydnz4NKS-8nPMP&5?b@@;opQmizD=wfI9QOB} zZ4m`eRg@EP7c9w9@FTU#L<7%g1R`i{Q!1Eouq3UM*&b*6g(~^ArH$ye=O_^%hAaRT zYmqE?=p%N%l0It}ML{efpfNFRyoyHY$57&DMMioh L@zbZ z%<1W8-+Z_~UTa@u_tf)`}VL7fI8;$%qwNQ@TgtnZ7jPAC5&n<|T|1& H5ea+UM+*2*kJZA)b^RBRSvm zH~x-Y{rHpsQGxOc=5{BnL}d@@wL}^*8QZ!7wuaB_siqZM!S;0!Ecf*tMxE|i?dBVi z#hJcjH*#`ofo?E~$WX!Mx|c>cnnYXJgEiNYzEGGou;Y`3b-yqEWbJc$h^b)(W23MR zqhhvd%Fd{Skq%%thG`q`32n3g_D9&uCgMW5Ge;N1<~rjsbh!`ns$zOo`uN9MpCGq# z&*H;ls`{i#c9GlI->%FdhCDm=)_-b~G2#R2j%__ M0S1ZDAE~D-)im`ytMo)J|TXoBn8HUW9 zc-r{tRlKwLF5MpwIce-vyC*Tv_`qiQSf8W0xDUm~Cdr4VzV~8PzKUskX+$x4>{g)Z z*g%LZSNkJ0G0ulgsmZhL^OdnY{G)oo9|V#AG$Oiw@-yp;9~*%lC_~V}@TU)!jh(fP zp`C-Np}m5W%#Z|~IIWnJoM^G)z7(y*(6YP}O~0azgp@oZs|q7)1#?9OGn1mt36dNm zGb8h=I72@J$p2yG5QF#>&2Zn6I4yObq=Y0rB*F@2eC&EWdS1R=TplKd@#@+P?t0Q@ zlFhXbEl4Qzd!R=jl)#%S_`klr{`ClAhyVKX|BctJ7#svT=vwu0U%T6ZPIv`6(67(@ znR0!v-M#!@Op0GxOjt-kkzPvpmH?6fYbQY)n}4S3j0Zq}Uk}#)O9B*j_a72FKPCQd zD{n6lJfG`V^WW(@A2iSl` LHqzFqEfmCR10B~k6*no@w;ogz zeviF2YWl_P9XL3puZgPwgct|a h5rp|i;Jd3t5e?+Q7f_wL zcGVfLVoxopf+D& ^3GR;gmgX+^Uo (<*m5R~r91I&>t zI1b$X=PeFH fGw4 5LDQ}l1%6yWX_Zqe2je~7;O27(*w--1KE{t*1TRu|mB`WDUPdl&kq zRl7B}2ETXU7QnZ}CBOe7-enIA&IY$ly=CVH+{ON_r7AcW+>Y}W3<$gne4_?1t4?q% z_=?OeRxAE4?C;iRz`5YFZ@1k3RIs_YThV_Hf39b1{!Wh|uC6|&|6?3;Gk0^_zXu;X zUC-X!3PWZ5OBmEA_&JyJd&rX;2569Rb;a>}h~+=#c5ZNY&+gn1bA6ru1ov~U=T=Q{ se~l8shqkxWk?h}I>1`peskZ}NSqW%Ruk_j=o*u&gAq0e9&h>x)1K~$xvH$=8 diff --git a/mqtt-sn-core/pom.xml b/mqtt-sn-core/pom.xml index b8f1e568..ad2a0afd 100644 --- a/mqtt-sn-core/pom.xml +++ b/mqtt-sn-core/pom.xml @@ -31,7 +31,7 @@ org.slj mqtt-sn -0.2.1 +0.2.2 mqtt-sn-core @@ -50,13 +50,6 @@javax.json 1.1.4 -- org.slj -mqtt-tree -0.5.4 -system -${basedir}/lib/mqtt-tree-0.5.4.jar -diff --git a/mqtt-sn-core/src/main/resources/logback.xml b/mqtt-sn-core/src/main/resources/logback.xml index 93b4f4d5..58ab83aa 100644 --- a/mqtt-sn-core/src/main/resources/logback.xml +++ b/mqtt-sn-core/src/main/resources/logback.xml @@ -47,9 +47,9 @@ - - - + + + diff --git a/mqtt-sn-gateway-connector-aws-iotcore/pom.xml b/mqtt-sn-gateway-connector-aws-iotcore/pom.xml index e69e3df3..e99b069e 100644 --- a/mqtt-sn-gateway-connector-aws-iotcore/pom.xml +++ b/mqtt-sn-gateway-connector-aws-iotcore/pom.xml @@ -31,7 +31,7 @@ org.slj mqtt-sn -0.2.1 +0.2.2 mqtt-sn-gateway-connector-aws-iotcore diff --git a/mqtt-sn-gateway-connector-google-iotcore/pom.xml b/mqtt-sn-gateway-connector-google-iotcore/pom.xml deleted file mode 100644 index 5b31e44b..00000000 --- a/mqtt-sn-gateway-connector-google-iotcore/pom.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - -- \ No newline at end of file diff --git a/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreAggregatingGatewayInteractiveMain.java b/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreAggregatingGatewayInteractiveMain.java deleted file mode 100644 index 93b19955..00000000 --- a/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreAggregatingGatewayInteractiveMain.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2021 Simon Johnson4.0.0 - -- - -org.slj -mqtt-sn -0.2.1 -mqtt-sn-gateway-connector-google-iotcore - -- - -2.4.3 -- - -- -org.slj -mqtt-sn-core -${mqtt-sn.version} -- -org.mqtt-sn -mqtt-sn-codec -${mqtt-sn.version} -- -org.slj -mqtt-sn-gateway -${mqtt-sn.version} -- -org.slj -mqtt-sn-gateway-connector-paho -${mqtt-sn.version} -- -io.jsonwebtoken -jjwt -0.9.1 -- -joda-time -joda-time -2.10.13 -- -mqtt-sn-google-iotcore-gateway-${version} -- - -- - -org.apache.maven.plugins -maven-shade-plugin -2.3 -- - -- -package -- -shade -- -- - -- -org.slj.mqtt.sn.gateway.connector.google.iotcore.GoogleIoTCoreAggregatingGatewayInteractiveMain -- -- -*:* -- -META-INF/*.SF -META-INF/*.DSA -META-INF/*.RSA -- * - * Find me on GitHub: - * https://github.com/simon622 - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.slj.mqtt.sn.gateway.connector.google.iotcore; - -import org.slj.mqtt.sn.gateway.cli.MqttsnInteractiveGatewayLauncher; -import org.slj.mqtt.sn.gateway.cli.MqttsnInteractiveGatewayWithKeystore; -import org.slj.mqtt.sn.gateway.impl.MqttsnGatewayRuntimeRegistry; -import org.slj.mqtt.sn.gateway.impl.gateway.type.MqttsnAggregatingGateway; -import org.slj.mqtt.sn.gateway.spi.connector.MqttsnConnectorOptions; -import org.slj.mqtt.sn.gateway.spi.gateway.MqttsnGatewayOptions; -import org.slj.mqtt.sn.impl.AbstractMqttsnRuntimeRegistry; -import org.slj.mqtt.sn.model.MqttsnOptions; -import org.slj.mqtt.sn.spi.IMqttsnStorageService; -import org.slj.mqtt.sn.spi.IMqttsnTransport; - -public class GoogleIoTCoreAggregatingGatewayInteractiveMain { - public static void main(String[] args) throws Exception { - MqttsnInteractiveGatewayLauncher.launch(new MqttsnInteractiveGatewayWithKeystore() { - protected AbstractMqttsnRuntimeRegistry createRuntimeRegistry(IMqttsnStorageService storageService, MqttsnOptions options, IMqttsnTransport transport) { - - IMqttsnStorageService namespacePreferences = storageService.getPreferenceNamespace(GoogleIoTCoreMqttsnConnector.DESCRIPTOR); - MqttsnConnectorOptions connectorOptions = new MqttsnConnectorOptions(); - storageService.initializeFieldsFromStorage(connectorOptions); - namespacePreferences.initializeFieldsFromStorage(connectorOptions); - - return MqttsnGatewayRuntimeRegistry.defaultConfiguration(storageService, (MqttsnGatewayOptions) options). - withConnector(new GoogleIoTCoreMqttsnConnector(GoogleIoTCoreMqttsnConnector.DESCRIPTOR, connectorOptions)). - withBackendService(new MqttsnAggregatingGateway()). - withTransport(createTransport(storageService)); - } - }, true, "Welcome to the Google IoT Core version of the gateway. You will need to connect your gateway to your Google IoT via the credentials available in your Google console."); - } -} diff --git a/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreMqttsnConnection.java b/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreMqttsnConnection.java deleted file mode 100644 index bf4ba8b1..00000000 --- a/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreMqttsnConnection.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2021 Simon Johnson - * - * Find me on GitHub: - * https://github.com/simon622 - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.slj.mqtt.sn.gateway.connector.google.iotcore; - -import io.jsonwebtoken.JwtBuilder; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import org.eclipse.paho.client.mqttv3.MqttClient; -import org.eclipse.paho.client.mqttv3.MqttConnectOptions; -import org.eclipse.paho.client.mqttv3.MqttMessage; -import org.joda.time.DateTime; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slj.mqtt.sn.gateway.connector.paho.PahoMqttsnBrokerConnection; -import org.slj.mqtt.sn.gateway.spi.ConnectResult; -import org.slj.mqtt.sn.gateway.spi.DisconnectResult; -import org.slj.mqtt.sn.gateway.spi.PublishResult; -import org.slj.mqtt.sn.gateway.spi.Result; -import org.slj.mqtt.sn.gateway.spi.connector.MqttsnConnectorException; -import org.slj.mqtt.sn.gateway.spi.connector.MqttsnConnectorOptions; -import org.slj.mqtt.sn.model.IClientIdentifierContext; -import org.slj.mqtt.sn.spi.IMqttsnMessage; -import org.slj.mqtt.sn.spi.IMqttsnMessageFactory; -import org.slj.mqtt.sn.utils.MqttsnUtils; -import org.slj.mqtt.sn.utils.TopicPath; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; - -/** - * @author simonjohnson - * - * Uses the AWS SDK (which in turn uses PAHO) to connect to the AWS IoT Core - */ -public class GoogleIoTCoreMqttsnConnection extends PahoMqttsnBrokerConnection { - - private Logger logger = LoggerFactory.getLogger(GoogleIoTCoreMqttsnConnection.class); - - static final String ALG_RSA = "RS256"; - static final String ALG_ES = "ES256"; - - static final int TOKEN_EXPIRY_MINUTES = 60; - - public GoogleIoTCoreMqttsnConnection(MqttsnConnectorOptions options) { - super(options); - } - - @Override - protected String createClientId(MqttsnConnectorOptions options) { - final String mqttClientId = - String.format( - "projects/%s/locations/%s/registries/%s/devices/%s", - getGoogleIoTProjectId(options), - getGoogleIoTCloudRegion(options), - getGoogleIoTRegistryId(options), - getGoogleIoTGatewayId(options)); - - return mqttClientId; - } - - @Override - public ConnectResult connect(IClientIdentifierContext context, IMqttsnMessage message) throws MqttsnConnectorException { - if(isConnected()){ - logger.info("attaching {} device by clientId", context.getId()); - IMqttsnMessageFactory factory = backendService.getRegistry().getCodec().createMessageFactory(); - //-- tell IoT core we are attaching a device & register for device changes - String topicPath = String.format("/devices/%s/attach", context.getId()); - IMqttsnMessage publish = - factory.createPublish(1, false, false, topicPath, new byte[0]); - if(!super.publish(context, new TopicPath(topicPath), 1, false, new byte[0], publish).isError()){ - logger.info("device {} attached, subscribing or config changes", context.getId()); - topicPath = String.format("/devices/%s/config", context.getId()); - IMqttsnMessage subscribe = factory.createSubscribe(0, topicPath); - subscribe(context, new TopicPath(topicPath), subscribe); - } - return new ConnectResult(Result.STATUS.SUCCESS); - } - return new ConnectResult(Result.STATUS.NOOP); - } - - @Override - public DisconnectResult disconnect(IClientIdentifierContext context, IMqttsnMessage message) throws MqttsnConnectorException { - if(isConnected()){ - logger.info("detaching gateway device " + context.getId()); - IMqttsnMessageFactory factory = backendService.getRegistry().getCodec().createMessageFactory(); - String topicPath = String.format("/devices/%s/detach", context.getId()); - IMqttsnMessage publish = - factory.createPublish(1, false, false, topicPath, new byte[0]); - super.publish(context, new TopicPath(topicPath), 1, false, new byte[0], publish); - return new DisconnectResult(Result.STATUS.SUCCESS); - } - return new DisconnectResult(Result.STATUS.NOOP); - } - - @Override - public PublishResult publish(IClientIdentifierContext context, TopicPath topicPath, int qos, boolean retained, byte[] data, IMqttsnMessage message) throws MqttsnConnectorException { - return super.publish(context, topicPath, qos, retained, data, message); - } - - @Override - public boolean canAccept(IClientIdentifierContext context, TopicPath topicPath, byte[] data, IMqttsnMessage message) { - return MqttsnUtils.in(topicPath.toString(), new String[] { - String.format("/devices/%s/state", context.getId()), - String.format("/devices/%s/events", context.getId()) - }); - } - - @Override - protected void onClientConnected(MqttClient client){ - try { - ///devices/{gateway_ID}/errors - { - String topic = String.format("/devices/%s/errors", getGoogleIoTGatewayId(options)); - logger.info("subscribing to Google gateway error topic {}", topic); - client.subscribe(topic, 0); - } - - ///devices/{gateway_ID}/config - { - String topic = String.format("/devices/%s/config", getGoogleIoTGatewayId(options)); - logger.info("subscribing to Google gateway error topic {}", topic); - client.subscribe(topic, 0); - } - } catch(Exception e){ - logger.error("error subscribing to error topic", e); - } - } - - @Override - protected String createConnectionString(MqttsnConnectorOptions options) { - return "ssl://mqtt.googleapis.com:8883"; - } - - @Override - protected MqttConnectOptions createConnectOptions(MqttsnConnectorOptions options) throws MqttsnConnectorException { - try { - MqttConnectOptions connectOptions = super.createConnectOptions(options); - connectOptions.setUserName("unused"); //per the GGL documents - connectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1); - - String alg = System.getProperty("algorithm"); - if(alg == null || alg.equals(ALG_ES)){ - connectOptions.setPassword( - createJwtEs(getGoogleIoTProjectId(options), - options.getPrivateKeyFileLocation()).toCharArray()); - } else { - connectOptions.setPassword( - createJwtRsa(getGoogleIoTProjectId(options), - options.getPrivateKeyFileLocation()).toCharArray()); - } - return connectOptions; - } catch(Exception e){ - throw new MqttsnConnectorException(e); - } - } - - /** Create a Cloud IoT Core JWT for the given project id, signed with the given RSA key. */ - private static String createJwtRsa(String projectId, String privateKeyFile) - throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { - DateTime now = new DateTime(); - // Create a JWT to authenticate this device. The device will be disconnected after the token - // expires, and will have to reconnect with a new token. The audience field should always be set - // to the GCP project id. - JwtBuilder jwtBuilder = - Jwts.builder() - .setIssuedAt(now.toDate()) - .setExpiration(now.plusMinutes(TOKEN_EXPIRY_MINUTES).toDate()) - .setAudience(projectId); - - byte[] keyBytes = Files.readAllBytes(Paths.get(privateKeyFile)); - PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); - KeyFactory kf = KeyFactory.getInstance("RSA"); - return jwtBuilder.signWith(SignatureAlgorithm.RS256, kf.generatePrivate(spec)).compact(); - } - - /** Create a Cloud IoT Core JWT for the given project id, signed with the given ES key. */ - private static String createJwtEs(String projectId, String privateKeyFile) - throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { - DateTime now = new DateTime(); - // Create a JWT to authenticate this device. The device will be disconnected after the token - // expires, and will have to reconnect with a new token. The audience field should always be set - // to the GCP project id. - JwtBuilder jwtBuilder = - Jwts.builder() - .setIssuedAt(now.toDate()) - .setExpiration(now.plusMinutes(TOKEN_EXPIRY_MINUTES).toDate()) - .setAudience(projectId); - - byte[] keyBytes = Files.readAllBytes(Paths.get(privateKeyFile)); - PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); - KeyFactory kf = KeyFactory.getInstance("EC"); - return jwtBuilder.signWith(SignatureAlgorithm.ES256, kf.generatePrivate(spec)).compact(); - } - - protected String getGoogleIoTProjectId(MqttsnConnectorOptions options){ - final String projectId = System.getProperty("projectId"); - if(projectId == null){ - throw new IllegalArgumentException("please specify -DprojectId= "); - } - return projectId; - } - - protected String getGoogleIoTGatewayId(MqttsnConnectorOptions options){ - final String gatewayId = System.getProperty("gatewayId"); - if(gatewayId == null){ - throw new IllegalArgumentException("please specify -DprojectId= "); - } - return gatewayId; - } - - protected String getGoogleIoTRegistryId(MqttsnConnectorOptions options){ - final String registryId = System.getProperty("registryId"); - if(registryId == null){ - throw new IllegalArgumentException("please specify -DregistryId= "); - } - return registryId; - } - - protected String getGoogleIoTCloudRegion(MqttsnConnectorOptions options){ - final String cloudRegion = System.getProperty("cloudRegion"); - if(cloudRegion == null){ - throw new IllegalArgumentException("please specify -DcloudRegion= "); - } - return cloudRegion; - } - - @Override - public void messageArrived(String s, MqttMessage mqttMessage) throws Exception { - logger.info("received message from google iot {} -> {}", s, new String(mqttMessage.getPayload())); - super.messageArrived(s, mqttMessage); - } -} diff --git a/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreMqttsnConnector.java b/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreMqttsnConnector.java deleted file mode 100644 index 573958d7..00000000 --- a/mqtt-sn-gateway-connector-google-iotcore/src/main/java/org/slj/mqtt/sn/gateway/connector/google/iotcore/GoogleIoTCoreMqttsnConnector.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2021 Simon Johnson - * - * Find me on GitHub: - * https://github.com/simon622 - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.slj.mqtt.sn.gateway.connector.google.iotcore; - -import org.slj.mqtt.sn.cloud.MqttsnConnectorDescriptor; -import org.slj.mqtt.sn.gateway.impl.connector.AbstractMqttsnConnector; -import org.slj.mqtt.sn.gateway.spi.connector.MqttsnConnectorException; -import org.slj.mqtt.sn.gateway.spi.connector.MqttsnConnectorOptions; - -public class GoogleIoTCoreMqttsnConnector - extends AbstractMqttsnConnector { - - public static final MqttsnConnectorDescriptor DESCRIPTOR = new MqttsnConnectorDescriptor(); - static { - DESCRIPTOR.setClassName(GoogleIoTCoreMqttsnConnector.class.getName()); - DESCRIPTOR.setCompanyName("Google"); - DESCRIPTOR.setProtocol("MQTT"); - DESCRIPTOR.setDescription("This connector is deprecated"); - DESCRIPTOR.setName("AWS IoT Core Connector (Deprecated)"); - DESCRIPTOR.setDeveloper("Goodle"); - } - - public GoogleIoTCoreMqttsnConnector(MqttsnConnectorDescriptor descriptor, MqttsnConnectorOptions options) { - super(descriptor, options); - } - - @Override - public GoogleIoTCoreMqttsnConnection createConnection(MqttsnConnectorOptions options, String clientId) throws MqttsnConnectorException { - try { - GoogleIoTCoreMqttsnConnection connection = new GoogleIoTCoreMqttsnConnection(options); - connection.connect(); - return connection; - } catch(Exception e){ - throw new MqttsnConnectorException("error creating connection;", e); - } - } - - @Override - public String getConnectionString() { - return String.format("%s@%s:%s", - options.getClientId(), - options.getHostName(), - options.getPort()); - } -} diff --git a/mqtt-sn-gateway-connector-paho/pom.xml b/mqtt-sn-gateway-connector-paho/pom.xml index 10513d1d..9662486d 100644 --- a/mqtt-sn-gateway-connector-paho/pom.xml +++ b/mqtt-sn-gateway-connector-paho/pom.xml @@ -31,7 +31,7 @@ org.slj mqtt-sn -0.2.1 +0.2.2 mqtt-sn-gateway-connector-paho diff --git a/mqtt-sn-gateway-console/dependency-reduced-pom.xml b/mqtt-sn-gateway-console/dependency-reduced-pom.xml index ee803d09..1fd323ab 100644 --- a/mqtt-sn-gateway-console/dependency-reduced-pom.xml +++ b/mqtt-sn-gateway-console/dependency-reduced-pom.xml @@ -3,7 +3,7 @@mqtt-sn org.slj -0.2.1 +0.2.2 4.0.0 mqtt-sn-gateway-console diff --git a/mqtt-sn-gateway-console/pom.xml b/mqtt-sn-gateway-console/pom.xml index c4ad5117..63103b2d 100644 --- a/mqtt-sn-gateway-console/pom.xml +++ b/mqtt-sn-gateway-console/pom.xml @@ -29,7 +29,7 @@mqtt-sn org.slj -0.2.1 +0.2.2 4.0.0 diff --git a/mqtt-sn-gateway/pom.xml b/mqtt-sn-gateway/pom.xml index b2c3dde3..87671c52 100644 --- a/mqtt-sn-gateway/pom.xml +++ b/mqtt-sn-gateway/pom.xml @@ -31,7 +31,7 @@org.slj mqtt-sn -0.2.1 +0.2.2 mqtt-sn-gateway @@ -50,11 +50,11 @@mqtt-sn-core ${mqtt-sn.version} -- + + + + +com.google.guava -guava -32.0.0-jre -com.fasterxml.jackson.core jackson-databind diff --git a/mqtt-sn-gateway/src/main/java/org/slj/mqtt/sn/gateway/impl/gateway/type/MqttsnAggregatingGateway.java b/mqtt-sn-gateway/src/main/java/org/slj/mqtt/sn/gateway/impl/gateway/type/MqttsnAggregatingGateway.java index 22399ac2..5385ff3d 100644 --- a/mqtt-sn-gateway/src/main/java/org/slj/mqtt/sn/gateway/impl/gateway/type/MqttsnAggregatingGateway.java +++ b/mqtt-sn-gateway/src/main/java/org/slj/mqtt/sn/gateway/impl/gateway/type/MqttsnAggregatingGateway.java @@ -24,7 +24,6 @@ package org.slj.mqtt.sn.gateway.impl.gateway.type; -import com.google.common.util.concurrent.RateLimiter; import org.slj.mqtt.sn.cloud.MqttsnConnectorDescriptor; import org.slj.mqtt.sn.gateway.impl.backend.AbstractMqttsnBackendConnection; import org.slj.mqtt.sn.gateway.impl.backend.AbstractMqttsnBackendService; @@ -37,7 +36,10 @@ import org.slj.mqtt.sn.impl.metrics.MqttsnCountingMetric; import org.slj.mqtt.sn.impl.metrics.MqttsnSnapshotMetric; import org.slj.mqtt.sn.model.IClientIdentifierContext; -import org.slj.mqtt.sn.spi.*; +import org.slj.mqtt.sn.spi.IMqttsnMessage; +import org.slj.mqtt.sn.spi.IMqttsnRuntimeRegistry; +import org.slj.mqtt.sn.spi.MqttsnException; +import org.slj.mqtt.sn.spi.MqttsnIllegalFormatException; import org.slj.mqtt.sn.utils.MqttsnUtils; import org.slj.mqtt.sn.utils.TopicPath; @@ -56,7 +58,7 @@ public class MqttsnAggregatingGateway extends AbstractMqttsnBackendService { private Thread publishingThread = null; private final Object monitor = new Object(); private final Queuequeue = new LinkedBlockingQueue<>(); - private volatile RateLimiter rateLimiter = null; +// private volatile RateLimiter rateLimiter = null; private static final long PUBLISH_THREAD_MAX_WAIT = 10000; private static final long MANAGED_CONNECTION_VALIDATION_TIME = 10000; private static final long MAX_ERROR_RETRIES = 5; @@ -71,7 +73,7 @@ public void start(IMqttsnRuntimeRegistry runtime) throws MqttsnException { super.start(runtime); double limiter = ((MqttsnGatewayOptions)runtime.getOptions()). getMaxBrokerPublishesPerSecond(); - rateLimiter = limiter == 0d ? null : RateLimiter.create(limiter); +// rateLimiter = limiter == 0d ? null : RateLimiter.create(limiter); stopped = false; connectOnStartup(); initPublisher(); @@ -82,10 +84,10 @@ public void start(IMqttsnRuntimeRegistry runtime) throws MqttsnException { public synchronized boolean initializeConnector(MqttsnConnectorDescriptor descriptor, MqttsnConnectorOptions options) throws MqttsnException { int qps = descriptor.getRateLimit(); if(qps > 0){ - rateLimiter = RateLimiter.create(qps); +// rateLimiter = RateLimiter.create(qps); logger.warn("re-initialising connector rate-limiter with {} permits", qps); } else { - rateLimiter = null; +// rateLimiter = null; } return super.initializeConnector(descriptor, options); } @@ -222,7 +224,7 @@ private void initPublisher(){ BrokerPublishOperation op = queue.poll(); if(op != null){ if(connection.canAccept(op.context, op.topicPath, op.payload, op.initialMessage)){ - if(rateLimiter != null) rateLimiter.acquire(); +// if(rateLimiter != null) rateLimiter.acquire(); logger.debug("de-queuing message to broker from queue, {} remaining", queue.size()); PublishResult res = super.publish(op.context, op.topicPath, op.qos, op.retained, op.payload, op.initialMessage); if(res.isError()){ diff --git a/mqtt-sn-load-test/pom.xml b/mqtt-sn-load-test/pom.xml index 255bd711..6842c328 100644 --- a/mqtt-sn-load-test/pom.xml +++ b/mqtt-sn-load-test/pom.xml @@ -31,7 +31,7 @@ org.slj mqtt-sn -0.2.1 +0.2.2 mqtt-sn-load-test diff --git a/mqtt-sn-protection-runtimes/pom.xml b/mqtt-sn-protection-runtimes/pom.xml index 4c0e0d9d..b9fb8e93 100644 --- a/mqtt-sn-protection-runtimes/pom.xml +++ b/mqtt-sn-protection-runtimes/pom.xml @@ -6,7 +6,7 @@org.slj mqtt-sn -0.2.1 +0.2.2 mqtt-sn-protection-runtimes diff --git a/mqtt-sn-protection/pom.xml b/mqtt-sn-protection/pom.xml index f23c748a..e5a61be3 100644 --- a/mqtt-sn-protection/pom.xml +++ b/mqtt-sn-protection/pom.xml @@ -6,7 +6,7 @@org.slj mqtt-sn -0.2.1 +0.2.2 mqtt-sn-protection diff --git a/pom.xml b/pom.xml index 3a162977..7d0b48b4 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@org.slj mqtt-sn -0.2.1 +0.2.2 pom @@ -60,7 +60,6 @@mqtt-sn-core mqtt-sn-gateway mqtt-sn-gateway-connector-aws-iotcore -mqtt-sn-gateway-connector-google-iotcore mqtt-sn-gateway-connector-paho mqtt-sn-load-test mqtt-sn-gateway-console @@ -81,7 +80,7 @@3.4.1 2.10.2 1.11 -0.2.1 +0.2.2