From 24c48e8af317bb527280d1d24159ce7db4addca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 22 Dec 2016 19:29:48 +0100 Subject: [PATCH] Add gpio plugin with raspberry pi 2 support --- debian/guh-plugins-maker.install | 1 + doc/images/Raspberry-Pi-2-GPIO.png | Bin 0 -> 81563 bytes libguh/hardware/gpio.cpp | 2 +- plugins/deviceplugins/deviceplugins.pro | 1 + .../deviceplugins/gpio/deviceplugingpio.cpp | 287 ++++++++++++++++++ plugins/deviceplugins/gpio/deviceplugingpio.h | 63 ++++ .../deviceplugins/gpio/deviceplugingpio.json | 112 +++++++ plugins/deviceplugins/gpio/gpio.pro | 17 ++ plugins/deviceplugins/gpio/gpiodescriptor.cpp | 44 +++ plugins/deviceplugins/gpio/gpiodescriptor.h | 41 +++ .../deviceplugins/gpio/translations/de_DE.ts | 79 +++++ .../deviceplugins/gpio/translations/en_US.ts | 79 +++++ 12 files changed, 725 insertions(+), 1 deletion(-) create mode 100644 doc/images/Raspberry-Pi-2-GPIO.png create mode 100644 plugins/deviceplugins/gpio/deviceplugingpio.cpp create mode 100644 plugins/deviceplugins/gpio/deviceplugingpio.h create mode 100644 plugins/deviceplugins/gpio/deviceplugingpio.json create mode 100644 plugins/deviceplugins/gpio/gpio.pro create mode 100644 plugins/deviceplugins/gpio/gpiodescriptor.cpp create mode 100644 plugins/deviceplugins/gpio/gpiodescriptor.h create mode 100644 plugins/deviceplugins/gpio/translations/de_DE.ts create mode 100644 plugins/deviceplugins/gpio/translations/en_US.ts diff --git a/debian/guh-plugins-maker.install b/debian/guh-plugins-maker.install index d05c9b97..8d199fee 100644 --- a/debian/guh-plugins-maker.install +++ b/debian/guh-plugins-maker.install @@ -2,3 +2,4 @@ usr/lib/guh/plugins/libguh_devicepluginlircd.so usr/lib/guh/plugins/libguh_deviceplugincommandlauncher.so usr/lib/guh/plugins/libguh_devicepluginudpcommander.so usr/lib/guh/plugins/libguh_devicepluginavahimonitor.so +usr/lib/guh/plugins/libguh_deviceplugingpio.so diff --git a/doc/images/Raspberry-Pi-2-GPIO.png b/doc/images/Raspberry-Pi-2-GPIO.png new file mode 100644 index 0000000000000000000000000000000000000000..cedc3aae688776e8f2d6d00741b26fa887735dc6 GIT binary patch literal 81563 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

Li+HXF zHIkYFeWFh`Z&){>`E)-|=d+oh)Xbsu)N9T%^(u*XoXK`QnIUz)g@#(bSHO%7q=i;3 zH`}4woyZWM<9plI&$7m{bYGtrq>(ap#TE%RP)9lhJ~oY%U>ylZF@ABup{1x7x=-D5 zL(cB~0|lcND&_|%_MFg{WwaX%UmFr8&`DpXbFrp>XVVTTZPSNK;wAD(p2#Efel*sa zbyXNPNpzXwqGK-huu@L^z8(GnK%%DV|BxkO`-^M4X6+=PRjoo9aoS}f9McTuK(OOV^uYp4eEXHy#0Ccv6 z+uZ!1^H!ZL5Emk`di~RWZEj5m`MOCilE%`!}8>_Y>%9SA#$>26KBpqK)eX7VR764ZBu5?dfOJ z+Vvc^u&S`iD(*q{vL#a=>KgQT@97@C{I;z+4q~2)G??LRMYlJ}L#H}dpFoqd*xEfhByhBh8~W$5Sg zu_%^M>bpC!xZFQ9U1G~<+~AXwoGh z75K#2+%BmAq}#;=R)3d3+(m#t1IrFB7u*ra@{Btp4mGMe;*Fw4v&O5jx+rgE#x2{X zW8BE4Yhl!&h$%$Nd z_e)y-y9DGj34k*(hkTuTN)Kdd;L4iyVP}R#&z4_5XJzaa*hNsnz7FAL-HG3r!*>qP zl2v(Gul5#5J+$QMVI>~0{m-$pO0+R64yIN$;n5;4)%3B}^Wr8`(V20otkoJY?Li5X z7n^p#B~__SI{6@5wfJ1o-Hj^KXDD73QTiQ5NwZ!K<7IJAOF&h=DGt64gw!kObqha` ztL6fy6&^ik$DOrIwHL{=D3y7NhqES1(d=y#?A5Yp5XU+P5nUkUP~m~YCQQfB~ch5egS>pOU846XLi_VHco;`7ocDZyIv z%fAoRf*Ou})JT?GHC|i%xE`)# zDOX0zM9|29g(7HTukiyWb2k1^DN59$(0GDUWN*O>%{u$RBX|EW;lmn0 z=Ey_*5-;V0y1#foWzEGqLiDEvRA8SJv(KVS6G+5sY!h31 z&7{f_QdJF8nLsj8O2;4xgFfN({(yYR7gi4qX$n@D4;8TC4ovEKk zCv5ZETbGCo2-%Pjo#c*Git*s~{0Hy_x5U_!Y}8A^gr_Tp4!HQ30&a_gj~_@6c{V0+ zI!fY$+gkcBVAgZX0#9#D>TPYqb`FJ0Duy_4qOKN*{vovC)@I~7EWy^TU z92d)g;636r%(Bzu1zG4<&!tUBj6BDABbwy@o2d+l@9|~{D5+QcnWumPBCy~ik2SX; zAiCp$e;ZpMxNp3stLmv;XOw)&{#mUjYzl{ZeDKjXZUPAS0p$z(@&@xWAtx-ut2=bI zQIvv&@VAWhJZT=Bua$TIEi? z_06(v+3SgiloeCLoj$u9Txg!u<>LYaSU8sgt9ye*gFP@v{EJ1rS4S(M1bi%g)U!!48@*Zr$9 zk7XX-5&r6mEz9(LaQx&T=6v<(MCAaHOOL*;O-bSTN4HL6myZL<7$3BKT_};L>bm?P z6ZkmI%>0X)dAiR2FM52(5(>qMyvfHP;+Cmk*nr{&+2l6#D;=w~M#@BzfJ+AoOpQzW zh^!eU;S~}^HJ~E*iJxpgwggJCSjG+rcDRaSN5Loxq_~1OD1#kB_CxiP6(g)w@5E6%wm+I{H?Ik&zv_t~LGdY!of0zxvoDU!Jh6 z@4??gNurhH^xu`;LaDsEriOkNGQ#`#=y?*!KluOF!n9$(9(%J@d1N7I+OU*5bCkTx z7|DGUKMNi2T#=v{k+wEHXs^g!oR<#~hce$26>Z>7>%@%jT2VrXSDO%^-Q7uw-$vtT$u&vU6&g z-`OKhayaQGByQ#zZ)s_)adH zWxVWHozFQpB5|2qD=Qd~e?+%O*T#3I_8<47O|5hhtJz(+1R>7m9(r|c} z{iorNUgA)~APb0}QWA|fDb3`9NF3IHqrC>~cf8e^eV$06SHXn+5qw;dC>+}UI|E(6 z2n>=s3!w%CUm13MQ_S5uD}1fA-YuZ8k$TWprtK_Eq6>PyA8*iNZ$bF#yj|+Va!kYS zbCAllH4m$rTwUG?_vp}(SW*pLwe9ktI8p<$8M5@P`CfPPhj^oDr{{)Ud3TB=B=Wv4 zPUr>ui*KnyzrIZ;vHezmFgN!^a?UF=5NV-Qofcdh_V7*CHv{;T=h$rBX#qGq^Oye`zb(S40cei`q{mf|g@9 zMv$To(Ba=1EYMi*f!Q)a(bu80C(ok21pJ(6Hj9hy-aa$vd~5iV8FmGn_6SX| zZTTXd^m$BW(4oTe+K4<(=i@9j`UI-OG*Q*W_(`O&rQg|{E&C(e`cdFA$3MB++iPDu zw9dB{PJb^#GBz`nyI3hGcxF_S*1JNoc!fI{K0Hg=^I|o4VD+Q6X-@mrlu|O=i1e0B zvuTwM$8`ik&T00(S(6~ghv=%u&mrSe@Lz+>2ARYFo1tjzh)Jw+bB+{)GuPS#o`MO( z1}b~!*Y!=V{__(s>#m>;acrZi%UgXAoBX~$FXdF0@82?gjfOCwKYSJCLQAd1Rp@k0 zs`m`IG>c|a-n6H!+8a6xotf#{JpMkc{ZisKJJ>TJi1RQB`W8#=6KmLN%j7-;)j?iX z(#>-@ie`snRzBVW{21?h_q8j=735D82s%LgXNGWvi_(u2j65zbtY7VKA+8Ft`dohR z^|r4DAiXv8nIZJrtTwSg4aQTxz6JYW_xP^tNR>rjZ12={GmZjXzsZPP>D}3pmyS|> zYTl|Mgqhy}`tLmcc$pS!ouZ&>pwYE5Ki!3U`ShaR)*?2p+nZHlac|04;xD)WCM`Udzd=ogD3k`WZ*sr2T0g(8vWfgAR!ir8=dc~ zw@}&pY?JPBd-vUPzC~t%m};GrRc%X=d>Js;xyFpzOCgpiQv>~;G)5Cz>2b;_KpjoL z(;53)kyRUuovAhw^e+XQw8vk9%V=5~Yknn@vYJ+4t#JhHB+*0W9()|f%9F&{eRP|FIhuYU<6`L9kK}9MH=U;FyET+)UwR}zKVz2cXLmZ zM(gqGN?li`P>;$wZdacu3kDloG_JcvQ=jhyXR=`|4Hpzrq@T-E(-3l4rPSMFt7rv< zNAu|_7H*e|D%F2S=VwLeb9+SHCF{0ZL?$h#*=7VAZnVYS-yr|gi1~_6F~te+#)z$BeMzp8r{{U6o#S(p4q7%1{Gz??3FkabZv$ybv4q z6Te4&=x-{7?D|jly>m+E9i%~z$XnJ5;ciHQ{fhN>DmcW zH8Vd(^a#3F7J&I(c2O6!3>dy>7|T;D%<(8NG7t9ScOS0*O=E~N&SG9>!;!RChE6EW z^1CigS`>U5H>C_Q&gi(DmN$&lWuDn$m{7lNRa)PM@mY(j(xLhuKn;RYM&}816xg>- zIm4L2!y;$PUj{LKt+Bf;U5o ze|WO^AUbn)jWo)@jk!w|s^nsl-geU*w)C1^ggz)zS^Rm~?5O6{&Do*n(>`Npn-9ca z<*-7HW(4MsBxSS{QX>n+A4M2}DW9B5RaRsI9 z9V{E7W~aAIj|0j*><}(u4N(@O*GA7RA+U-EN;Ddv&EvMe z@CQ6_t2&FJH3QH|NvmD;8=98H!}H)M48M10Hq|@KYh0NB^)s*8a?wLCCqnAZNk+Jb zd+;W+0FPink)q!0AC5w`Fw zlFlC_kYuO8Svx}TFG`$QuS+e0jD4Ts$Um&&LIRr>mbE1s~c4?VTJw0gl^b`8) z_Yi9n2n=WdRpL!?YTB;KS!_!#i@Pl94+>iD49b^6U0aen;X2rdT;BK(jwmD#nNgYx2)sT;nKGm8t!S;*E>zFKKHd{A z?2R^esbon)`TnuflsczL5RLLsDF@aH>M2n+HPo;Ksaz3cb+0#CGC{My;aeMfC@XWK zZQ<7sYc87V5Id{;FlxgS(%nZ5Q9t^UBjD;o%uh1kV$Y>;lG=_zx_x*Q!A;_f{P8g; zXea4n{pa{r&0sXvm}EvEC;$n zdbvBChb~Qrs*1Mg7ZOw#BdR8bLd|Z8$t1%!zWBQFms=EYnAi1sKP8eFu)us=hgzMk zkEPm&NumoxO3Q3v^jMt+nflKPXZhr*h4@7NVQ=*rLL`iNa60JU)J0BmO`m__gY&1N zOV;9w1YeG)9#ABi02BJ-r*QL$3-$ikg$^cbI zJ^e?82j97<6l3qehb(GDQ%`=FwI&V|T2KLmnwlC*hX&uPi?LE+G`))+PPmmnF9&;Z zW6d!N3WkMvrvG1f`NG`1wt{uH+OKr?`{`}a(8X~(u?AGVYs~>3#gU2GrsWd=(;%=_xfe~|~ zP5duU3n-2=3kWD%^B0L(jM2DN2xVXcfvbo*LR)Prt%!Q%Yi znZ9hpk*a{`$Eg0>% zMJuQ1pc$+70uzIw$)<_|(2(QOn-BkOz9`X>gNIm7!plX7mjsI!BI0fEg#5N<(~Owt z6Uxf)s++B_rrgE1Z+I{MkX>BD3*IQwz$H_HjFbHNBW6vx5b6*It5CFicfw2Eh!xWO z)R|RLup9G?WPI0&vE(tsq)x+w`t_oGu;(prrdgHxfMQ1e6tu{i_WwOM>xCBiT4P=5 ztE~$01KKgP;%pv_g|tsevX3e*xLxAVpqD(BwRPQeJ9fvM_pwr{1{@G8)XsE{&C{)5 zepHJA1sWwmp~N_%ssf|JJIu~yo`vxz`A;=*y-JbCG>AZ9&ji{H?tb^pJMi0{gWw{1 z))xY_p7s?YgT4+Ec2J@FHu^D#HL0)uI~yRD8;Smb>)*JKfI&8N>w@erLP0&Fm##ry zo=SB+d@$E}{FXI-xh^Xq@dN$uO5UK}eQj$sp}{F7YPh6(pE%o?pzp}>)1hgNXF@m4 zfIS|HetN3!)g&c4d}4mWBhVw`Ia7b#mr()szhz{bdl^o)x@kTk zAy=Oc+f!vHO)^f74U}JQ z%hc{+a^PKbCpoUWa@?2Dw67$S-5IV-^{QAQ_nO|H5g-4av)^V2OlT29m8InTP^C93 z!;DgxVug}Uhtx2Z?W$SKRf5x3t>(=kM4QnMhVpASLrkUUiZIV{^IzI=cdkev%hG;~ zk?`x72@}>&uf@owqj>J2dq?Y!I_-ylfySDfU+i?S`76IUZs*o)a5vY-OqYG28?_Ie z9$|IMj2MT8kD4szgmbhBr=CayU&2y(M2f?!n(Txd_jByw$e-;v|N}r-6@o zwCb|%>QT;n5e<XqHcNwdK{G|;g2v;9Nwsey``=iH5Aahv}Q2{aPO0=@*LiFR(A;^ zNKs~J#_wrl7@(gn!%^S;y?A%Qvp5{r`1O+XnzUCvE~mra*X?A24kxbk0rUy2h1O>` zDN#doJ;La!&XU_Vb4K0`O^9k%=P^))^&a%w$(&JTjd9eMB378EncreZU_K`B$T!g- zWcdqsv1j?46EtLprE|uw$1=-1oZ`fgS!CSW}77W~h~{XR`fR%QrWXZBROTgcaAgwcUfu8mVd?!m)gE7A<+67K_o$x0_kB(^@P$i{rXSnfmx{k zH+iJgd10nx4h6Qu-;zmU2VgHNo|PwMHz2mlp##t7*t6KCOFKC($mTDDD(-- zU2RhAfzYlBUk1zlxm=a;oH_SQ_T4Tk!{?sL$v)_l@?sqmgh0F0)wWBffa5}BQC?w& zC#{Ve_;P^#pJgE;wEdXP{>oL?ZY9R5+R=T)RZvTc)Bw0v?=r9T z;q!Pw%x~`yyvwdTvD z9A<@TLW!3t0+%5rKTq3D<0GXL_TzH1pCCrBmL}-7^RsRnf$&r2321hyk?$`YhovDNLxD*v0w7i#`navTsOHn;ax%T-Evixw@ zaOtAm<3BL1DopXk*AwHm;o1=fBulbw#<%;<3U(%&1A1Iw--WxTw6$CUm(Pm2U%or_ zj7&3Aw{}-HZ;L6m`#8yfwWI4OugGz`Lm5EOMz0JfjMZtFMjHBqGVU8o zx`^-xPB9?qIl{0H=_JvEMc;ZW4Qx#YfoheLY@>PFg-4TQltz>-d0_YQTCcO5pH!Oi z6DuC%pw2b$Zst<~f0+4U@nk6-cr?Ox$|Sq1iV05FU3pi2!A=_GDk|+_HzkKQpzEo0 zLiZ=t+B8Wj3`jkZWT*b|U%MmOBhLUe%`Vs^SY&lxMlFdp)`zfx5hFd$kGMxIiwhO5 z^o43N&mcv5@DVDuAMe0B=z8$wvezSnUGn~32Cqfg!e$tdL>p=JCpY+69S0;1HKI+6 zTIv(_EHs>x?l(mfXt%uq#)-23n1}#_zZnR8L)35bx7fRfG%xl{T2zaexgz**09hP>Ca0ap-`Y_=b``W z);`<4pUWBFU-pbU*1Zv)Y9gG`bW%DNwuxU7MahHo9z1&hv722N*_6)Vvk6$ko+cz_ z*uth5nCktZ#?fY1J(L^hz?8RN7t7-Q%T?}s{KH|w0DTzh+G1dCGJw%%B%zTa126{IIqVC*H-V8ay(Ka(waa_s3+Lar^_W` z@5QcbDP!}!A0q}0(0InI)WDf2A^WrynBd1Bk3uEo9*X#JIupCq z>x~usa;E-soPk=X2>~$R^~pz%iww#e@VAJ)20t=FG>b3I%kA^TtYA2kzX5!9yy2H6 zbADon7qi{IN9zY_w^sad3TRW!Mq$ZEKEM2(HcV}Wn(hLK={gyRlS_*2Z^%2N$k)TP zC+F#R07-%7N)(Yijpk*x_AIM6dlOJPS3!HatU-C6?mbi*jTVoP9;)5=654ZRV+DE> zYsjxJ0F4~3=cj0&n+9hO!`PQJZg6~%GCJau#&`xU8c z=Uc``hkAS!oO#s<*0U^d6+D#UU0S3_-$P?2*YzwV1nCby{z#n8Kwlbvy`Ld|De{Uq zKJnHqF#H;5%c;p(oSD5wmnRsVY?;lu-tGL2RkGSyodRX#6cb`v`7M6}r&W4`rzy2D z+lj7G;db&|N=qCnu}XK@Ap`*0iYzRHsAh!V zMYb~KN4`#`h$fHp*PciV5OYhD+E$yCQ%p21b7BSj#*YW5x?EZ|RQ2;>ZxV_VzS|L$ zcyV8}KKWNgzgZapfXQVul1{JiPz-p0-&TjiH@um~g-ieTHoA57;0x*I&OctWvjIZ2 z>iY&*Zp`7CA%;XL9L#YI)LCJZ`P~ubtBs)6mn*RG8qNETjlM4ZLZiwZ43CxTJX9E$ z%5}4ADoH9e6i4bO@8m{cqbZPG-?k+h15Lzacb7JM-Jez!>GWfnd2y-=>a+PC_1vSL z+?o;zF|5%f*`K3LVIH3i(1tIK1oQMGTgr3yT_F`c(`C0e{k=wdE35OpJFkRgi6@o8 z4^|aoZ^>BDl4)g)UH4xp{$id;HtA!C zYGTi?{v7kUv}D1?H?F9DmZ3C9yU$utbGhey0&w)JgKGac1;YxtrIBhkGem}DO72@O6i^QPm}UAQMS+?i|H|? z^uq_2A{C#)X=6=H4=7w3k(ZH6(K&Th2{eK7Lpv?&EbHP24o)rqP!{D4mRUxO1_L=0 zi!~Owfw~TyXgRooSy?eOXyhR-;vf5*z;UJvdpN*&$BA>S?vjeS)}-@{5%Unr=Q%gr z6%%yi`L3!R4FC&{%0s;#{G;k{t)6A4Z{zv^HC^~T+^Hx(@jbfA^;7D-)l{jmPfP5D zgj+`wyshvjQSf1ixIDiw(t%&cN z-2Ve#mVE4$;=lVS3^kG6=Ta=x136`Okt-7VkV|1f<$;_46Wikh(aMlmBED*}K9Js} zykdTS1Bj`*YjM{`wR=PZpo)74Ey-67d-V98I!e^^DoEfRQs2QAb`yBCXIcHwrF@1>vzYeH4m`mnq$u@X)&fcWlXKy;eYtE6NiEJyvRDDi;F; z-iN1rEyb@G+ci}e2qN-JRp|J&Eq<$8pp~_p@F)=XY*nowQzpSZ;-2 zV}O04Z;J5iOkk#TT=~m*C$BE&@CJSF**zmPU$TrX9N6{u;Q{_2=K6`>Jh#iaz!i5v z>MTUMKH+v}6JM1x%Gblfa7iId19XvI)$(iZlmKgji*i?9%ub>yF1S&lvogh3U~<`e zy*(u=5?M2=i^e29B^yCT+runW-5cZ|vsI zg9gRtFVKcN^6Zw+t--y*b2{5sQ9Qpxj^BBJ#`y4i8?$3v)YZlM4Txp8)x&pR-py6z z(_C{?EHXXN0qEqiNL}J?)z1b8%}uRbDtcqgSOjVq`=rii99i-BKdcR+S9;DT-PMK~ zkR(X0NRXG}C8s?L_}BZ@WKHN{`n!3ty7xj&z5s#SecS_GZJ|txvDU`TX(xk{$7t=s zP%Mw*&1gxjlaBt%2@SqwI4`|G>I|2INgXB3ciU97aX3ux++q&R-!+-PV}e+06TgN! ztCc5?%RVzPff#dC7SF%VuOU+w2G4PUf|8GS!+`LFlMpO8W&S+=<>9OVny#HGan@@1kl`Mib8H!uz}N;-}CxCuycYZY^17m6u?CuxY8z1c_;mOx3IxiVtP#e9lS5S zQ9DY2X-kB_-@sF$aLHDq%Tw7(oIa0-24MyMJK`CcV`4QJ@c40+0` zEGyOtQ4j}&=$uur0NXd))|MXp7!m-dNLrj!sF>D4L3)B+pQ(|INF%s%LKT)4c>6Pn z+02qRZ{C{UldD*m`ep4R(_gzfan`0_jJgRB($!n;`ZZNEl`O3K7ZLZ6AiXm7n7-wX0OXycy8-xPL4x}W+##P15#cDac4)$;f_nKcg}H2DC({yASDjBqUcn% zHWaI4y^HhnD6;o|ZM3jJfB?-06zsi5hWN$-@=<3X%=KO-q}Z7tVJ9V(-&{*GCDHm0 z08*M=E_6Fk8Xclk^;o$k7SvtbKXB%(fs8V%J>5B_?xO~9MRBf3O<-ImPP1j?M z5~H+o%5BV`xWHF$H#Txa&d8QRo|LG;iDz_`NACJ|py1tNDyW0+txFImYzHSuu{q}D z^K=)HBbh2v&9NNgH|YW;Ki*^ZpkUuJFzV?%FMv5GvK_ieZaD>2zM=p*;5cd{x`B%6 z8?oB4+FbT#DVA6w$Fg&V$ELsPSg@E5_?j!qPle>5^Lg+iV*wUz>o0m-&t!e)fc=qI zfqI-Wl&QK<{y^5@ZGSS)=uESyuguTy^+PC18k{PO?A8rPk!7eG4bJr=dPI{@j|j+@ z-yqVEvBna|{iQ_Ej4 zrB=4A$eX?UE(iH|AoSvmN_@~)J|8fC32K{-S^lC@c*bGV5Cr9{aDLL2ylv%cM*Iwl zTV}z3O8YFBt(4j0S+Vp9%bmX%E1-#NS--WM?L7mObfa#ebyH^I6sgxS8D3xCCxM7v zB4kX;ZWI;1`~2YbQ;v-1>$Jdrt3O{&v%~GTJt0yg2n{*BGR&MBk~_FmN8^`UoN_zA7l>7%)*LFsL7_DH%RXij#B_X_}>4T@ur*KBj<2SB{4uwl)6n%i<^ zE7x)*<{{~+oc&S3&^y{ok-+h`73fKW8g6)&eD9)@)*^uNbcAD_;N zD^RBB^F;zE=WOtU=k~rdZM!~n=Op~pmt6s()YfM?o0p2pUl3a zz3ST0C@ovTdo*YTMR@qsYRCoyLPPAw=wjztzZ_o7_6%q*{TPP=8ic}uO;pOm=LgG) z!(ka@dvAsBMuE6*gRm*!Cv=$_T)3{D24_{oMGnQi`J}~^n*dJU_@4Z!>X1Gt>P%wI#p7F*dra%!0fb%!O_tc+}FQZ&M+m@H2gOrur9 z-gZF(UrvevXmdS{7J)Ltzmh?4Ik!GB*y4SxF>O&sj5AII7r%#YowMNvbT2=gZxP1L{F+4X;e189mr==VVMCl^L&BCqDcT2u)Fh~DpE4D1Yl|4G+ zM16VrjAGA+)D^E#W%T-%MmM)szR-Q4JWybhD1e981Jw5pF{1sXLKT1>niG+VPEUn+ zuX{N-yUcpRSG+TodNWQ@vsDytpm&7Ci|2S%s$OtO-iMQj)a0~c+;nLB83#|+S9y)_ zQId&M%ddhl&!_>&^;Q%q{rwQuu z#Vk!0-`V8D?jQ_^A|jOR?4n84rJhFJ-ESBQ{0gMLFJ-HCT?kLA?TThPsCBsIer4cT zHOL(EedNvZgq2o*d8$g{19Qj$ zgR$H5#qkH=poKO^DFkEzz5wyBTVgOTWg5IK|9JA@i)U3MRw!90F905UPG!jpY@J(=OF|#G~X#N*u1mLxM(Z3>IUV z(Zpa+E6Tr~b?~ry)-SEDn%vghO!?R#da;od=dhKs4xGMF_;le79ZxL%V4!umi2>Ce zaXx)SyxSbB{tJg5~-f9W_hs6%$wXsyL=nq8)*+Y8@+?yWuIP3D7Jb9^*G(w(rq_e{i>_r zS9rP@J7}u@AkyizvR$Hq~J%iwfQZ z4ml{+G|5{a3+-%PDjek7t?FkRND9EbmA(vmlyrqf_g6Vtnp}VcC9}GUM)Pt9(FR__ z%|t%VcKfO~oEvcxvsMZZHdZlORl`Teu3&OC7~? z-!}laWpK!&(7Z%-N1lvDKCQ*%`fN}0lz;iX=r1o?F){c0DQb$m3YGNSNE%)UGz^A) zi-|(g|2h>XRMamI#%4r(91q1)L8dLNta^>BLwD!cL<^hsUVYOO_Wad2&HGhz)Z>tR zawm7)H(tln(NwqNs(+f*D!#=;IMI-=>_V+#*3Ix)-!wv!wsVXAJ^EL5z`D-I9@~A> zt<_2SOzFy940EQ@B({7fG5zZ!a??BL_?+x8m?`QUC^v8FB2Mu+A2{@u^cFM4`f`s7O)VC({8KM* z86gytvgSJIv-svBP3gyLk1lpFqk>Skm?R41DYI+ZV8Shdcgf|%x|Op2oNBD4c+bU< z`c=K$G77nF8N1FxjU}1F?U&5B)%P4`n%)xqz!8A#rB;s~sEe*}(qX{r1|y&3uejgQ z$g=b`xgb~j-aEhR@;i5F*6`tjr}ZzOVxW|JrY@bpZsN0_IA-Iz%eJ2}Wwd7xC1U*B zFJ~kM_dh>;e&Y(&s{L;9dSnq#N0rRN{h%5m7E9sR-=GUxBuqp&TEf{FQ2}3cT*Oq? zXTg-A)tZy%H@auDc#mQE#cMaWE^~oMEMGta$0s!M0A#i$z|@Q6U6cP|!ZE`PN>SZe+>N%j9jx$y z2(W79O2cDqVEf+t14HDiy+SaTDT&7NovD(vRTJOuXA`Q@E0rZOxm<$Z!&|bEzp>a_ zmMF_)bE6o8R>nlr>~_ikEyP8OmiBE6pAyJ9wCLAU!P>Z@HYaN&fAkJ*0JxH7e!eQW zZGgRoCnVRwbg+B#tE=}UB=Kf8;YVL$Atwd& zi$APZMfInIuOB4J&G%;Yo~%4M5tkCeae?N$ErX9%Is1~1C9POrTer4BVQ*pSSKJc9NMKL|x;NThUhz!wvzTAEZ!LJgmkcwg7~mg_EjeVVHBnV*^K zSPASDwMQ@f@^a;#nkWJ?~#_hEcMK3Pg*JT|*V>?*K*19au zw7r%;c;!czz~++iYmSyt(v8ogD)oGp-luq+mj+E4)pzOhU(M{b8fn}=dH;rK^Yhw& zSXnN*u{rSCt>pFA2Xlt7#Tn}tcUsT4jHgz@>G~OEaFg=OluxfNXPkzKE59^znqvx8 zY_ayHXk^c4)9pkNyQJi(w}MxM89i}EBa(xd%x=}ohKmHSw#)b_z$_)Y9R40fc51<2T5##O2;2R8x0n*n5|U@{i{deBH-^G!h(b9Vt+TRy z_okRya#-!ei(s4*I}IfcvtD!`uc2QKRP$7I6WgsFx50yi-re!7$?@=0Qm$H#PCvBo zYqZ=m2!y-6?EhTr<^NSzJ<3}o+-q>Yxy&;DsRigGAsMMi(H0I<+@4*?92N2;N=3Z0!_*urp} ztnwaP0KA$Ak7o)^8{B9`?PhFNk(q|hJ?=cYDqS62YWe%urJJqSmoissgtKM>p>0JI ztR6-&4>Aos`wP~6kLD6y=xh1RTl@8WKpS!Ej6}^XIRzeSE6@lF(qUqhL-SUI*_T{V z)M#%|*a^I6rQABJID2G85N3npd|<&ckb&zkrN-u@4PR`&wMaxuu<-pe*OZ@*a5-gRv9Z&J#C6M#xuvW^#nP}(C^&^g zh=#7XZ_p8dO=06{_{l!QFGrX=LU9HFECax2_GWWv**UKu_2_&)9_ zML<7G9RkqL09Z9*03nTRcB$m`NouQdq!Nj`7KyIQ=a3%9(GX*_@*0`jZdXIX`fvM<(fv;Bf8G4RtM21X+9_Gc}opJBDG$aMhxX(k51O){(* zReh9~_OzSe?SwxX^C{?{Fk)jW94{}#FkxsiDPI4m&^7SlGd$71YOe<*3eGyx4nshvQFo|8xI0pv7_{jOW{^tp_pzgOuPft8rLD}9K5kY>(vik^hs|G+v9UK5?9@(*Gv`0%GbCE2 zNS>aywA{RTQ}bp^%jv0Pk#i2!2|-W}BABIpaason?^49!Cx>6nH@q^&tKqL@Te4J= zgjrt>WW9giomAzSQ5!Ibt*nH<-jcY>h-PE4{2}3Iq;Hs6dhF(M(&=WWFY@GzhjQYHG~}@s6EKYHzcI@ISTgF! z6vT4?{EUs27LIWr*YdJRyT{+-h6*awI^Y z{eyCr$ONiS6;C-67v~1*i2n7Q2c&Y&1y?*R5BwK!njI5h;`Y)8e)kFV{`;K=025q# zMS~nkKwh)#Zq5N3uX~SCu9##Z{Y?*mlc5j103pT-Q-1&C@9(Z46Ucl{BLAy{)RrZ! zv-imLrX|1q-bW?pGEHX*zlr6NI(7s;UbyLHa3-oA@f-c^Plx&nw<#gT27j~T_cH+7 z>&4-YKj=S9B0SBaL~@XI8%TO$f0Ou!5}{sGL4TypU-dlA8UKum(4UPzMw{Jd^RM%k ze?QG_UP4xX`3(>EhgD@+WJt|{|L}wG;I=I;EO#`dhwKAq&om+ z_+L$mmH|{&L@!vl|8GarKY-7M%2fe3{{M`FK<-_T%JvcfCh|Wo2_#=bglzqv;Uo|M zMQy2yOyXw$-@N=y4Pl^Ke=(>s(vv(k-}9yUzwN~XK;>G?MLx3YtkKZj`v`u;6BfCS;m zAoI^$3Y)CQ{q}hO^sN5{%t?o)fdsCde?D6nR~zO*_{t{)Li0mMPP6?=!JH1x5A5%jt4d7aS5@?pQT;Z+#SJKu`%3Di zD~nlA;%lE=bLza(a4+SfWBdD$~l(KHlj2`Bw>f@^GrmH>D?m3)Sgg=KxU{$T8HNRO6 z73b>~T5KgIE4Z5t<}qnw{mH@>bV#Bm`4q>|X8?Rk%q!Dq?oY|XDhI4L>XqataEkYJ zinaJL<4IDFX58wO@FSB?4Gc04J`zEKdjsBrajF@6Z!i^J=C~^_*H+?_i^tZtnwAy< z#;Y99b-c%NTUP@I0uQh^KtI)6A8UX4`O zGCET3AHFl>pvX{qBtiM~e5}+ieOAU?S#35joOnQ&BC(a1?DdVe7Q_d8Vd%=31^kb} z57D^^a0ie|teuO`Q+$F~JG=e)aO+b06ieYVg>30W^c_8FSCFJ~*TzDB&|btB^vI3$ zi+#v<{R$NJO5WiI<ZB3RYx_-F4@{eAW_Iv>rM7ic{8Z=y;Pby?W6Y<)TvHI`7c!+*O(E9%w~n2l@Q8H|o&Zbc_wcLX`g(c2!FaNy{9M z?vuqf!UQd;nLuF`jATtYZ%~0U8KMQePHpTq=VSgQ$geZHd0$(uzE_Akl!ZB*IOpyL zcFo2zbgNJ-QIlpl*MV&ZtsN}yER!S4PYsBWXtu-OM zsG!oz^mEtqf1)XDc-qHxwz%3zn{1X}jn9$3-@f9ExRFLG=cBw~W`Or>Tq+eV5-Gw8 zoKSNc)Zv%a`8^!rDiO>GR~j`os#QMm41`msEWFxljvR^ZAaST;zkX=8_0V&?Gs9tJ z_|UKcR8dqMfm^wN{F+q`BnyfSp2hi=Qz$VI1W0%Z^>SMYoWFkE~$PfZe1W& z-9wIK2`h>am6&{Nwrie|UiV@K$pP6o*^ram-iVM!#3r)B)cav6_dBxI(^c1zEG-fE zkG)$uUtqy!?s2>5U+=y;(*cUmN^5&5yU(=TJ?u$CqXz0bYzw!6j%y!2J3HHmK5SgF zm;Fjw35wy$T8IgXU{iX$`vEh>V|{7T+f;ONs`MppSVjZh9EN#baG-t(QZoYFwc;Q; z7X%$Us}R-=T6WZy-y_##-3n;l`j(d$mPOZ15l!xXXORe5Txb^JsEx!2j%sBw@!`Mb z=2;HN3n2C*!n@aKq{?cN8h#4aTLi8!CDmDR7KHd`x%W zYUdf(B=!rU_;a8xTqY49dwz~Ft-ZXqwkz{i5~ge#yr9Brc7v&Bc(10l;OP$lqqD;B z0H2xd+8F#`6m znvN8L#=SgX(baz3PQzBvstC{EOvpef>kg6g_61A91Ev>qR#NLTRjWu`oI@^MiiTgS zTcvlQ0OwWYm4Uoq9IfxsYbz%+cD-91^axfnZ|Jj7V2!5Q^e6}R;F!KjF^Uz8e~yEq zg{!LChwMrlbG#zxp3spXbWVm0f!vbAUgS|%Q0FWol6o;()eA8u=@x`h4V~%;eTgHX zL^^TXuCy1oCe4$cd#=#PBRJip8MfQm&rxeFlHF|zCWc_e3AE6w;R*OoLt>Iqw~nZJ z2qxM5W@p+<&;rqy0-iAbcI&gpm>f?%m%RYA+=k8Z2nmuV$nI>0*GeKZRF;E81RP@^ zC;pwI?RVjs0iO#paUFeJHG93@r6;b(PqY-*GY45@eiIh7f*j2~gL+OlYIi=7n) zb=xR8^!z9|tj#y7_u!ZuVo7^?KHkl9`d|zu?lu5sHtm`U({unQN>@h>N~KG0))L*c zKi4-Od?jtHq@=XmA#c}^x+>6a-MdP{mW;WV3&AeH*6sw&JMO*8r{q%@*( zqEB@a08NAMH0JD6o}c`c8@r9IbZp^w!igcuNi;9@1vA zUy1`A!lH}()|@I$_6vQKk_*+szMEJ^D?|ry`GWIOpJq0bI#Y!$QtdnHe=fO^#=w_& z{`m*l;rg3V*UwK+k0TOkA;o8Fi*dlU4<|cS+&X2Dd2gQ8o-m5tvTxRE{=7ZkKWZV1 zv>bk_BMh+SN0?w^`&a{PNWh#wbY|ys{2ayj+xH|$YAf(@)TsV~*Phe_!V!@d#kWU= zvj^M8V`@77Lhg*NQpobXhjSZP${r6cZaxk6EZDx!13Jxm>54d+qhm(UgnKXLW!G5Ju8kMf$7`=G2T*9%B-Zrda&p`KRdJC zMS)X#-a@JD^Ale;2d$)NaCvog%QYl%kLZ0_jW;WKR5vG9C_@|BM?KUZKD{4`QAYc& z$nv*bLXOtr{&E?=h`hNy6y2|RgzJ2#2COJjaDg3GpndJz9-@ZZ(=oomehWc^4BQTl zo&a-xDH6W@ImpKddTJNZysb82V({ywqWR}jexw6f-}5Id%(N1O-OxA}pN;v7C)!ro ztE7X!zLANW(g&RmZ>FTF@S!Ax^G;+kSsw(Qd3;-S@PvUF!yiD*4OjMYY1B-y>x{E+ zp{2lG9=!`)cX8eZed3Kdb+E38kzzMDdWXIW@i^*@meWZyt0%PVgFKI1>D4B+izi~c z!mN3*S~P}Z3;s|wxP9Wnmv%6<$t6hf?J1`17VBwuQJ#y)i#S~9>vl17g3Lgz4eh0> zUNv1rD(tCdP|y3OBIYxpYM`)D^T9VwaCGQe{=fy#11=3oNu91(XL~K5AD57qP7TPB z6%Co|jbB7}$;aUkD>>8Xs|rH6PFi-$pdhb7n=4lw;9ZnEIdM}Hh91Y79?m`kuxaaD ze*p+bPe3wouP)qKSk?Zj?Hq8OT4`y&Q|vY-Pny_KPZW^ec`#QFDO%#imWAvKA40FIi}rF%sCRWT=}y} zPWe z)pPV>6RGoEA9;MTObgXnC6V^&nyG~P$aq>R8O}r)WKkpH<8=M1k5Ojku53jOf3Rbum8Tc z))mw(mBcPET~)B?8XYXeh>qDSt0*P&>H8eZCG$coXdS-ij|%Oyu~(tk z<_}k=1EDi#79~WQEHbAsEy-YEV;-XqL%wM{S#gl408K6~E&2F#g8ggx$MJD+2 zKCZb3NI;GThep;zs5u1{!vMdiP$;mJUxb^F(@!6bV@7sSvq2e=$24}m^q<5xgE4gg zg@D5p3e7t!48)Z4Wq}H%biRS+E4bM>KE1?!1f5{M) zmH>N4#o1bv_l;i%W9o}Sm{!MbzJ*%0(^sR~lqjgv(2?fRm45bp7Owm2od#y**6L{@ zH)3cX_31JRc`fTCKr{_J&>(v^e!Jbq2Mr^)S#VQ+)z~+=WJo`qz)MJY_=6-=d-pu; z18pMasF4&QCd&w&cv&MK-H-g+y)=ge9)A}*?_FWODhhG)wc$S2QZtsU-HT&fi5ksw zr8C$I!W@x#yN;V_)u`5_RD`ymdSjvvc0#l_)2v1Z;eC(Fx-SCv0tISQT}1Bt6=#kQ zCDxb%6tDFSX~R`(5{knx$!dtn;?`mfkEs)BKFztDJ@e4_M~pG{vzPO73LabW^cEJ9Fhc~S}d6Rxi(U32Dx8qHH6tuv2QlB4|#k%=vPgX z3BjbqjTnS!{xIXl@^YJS^=23vMV)ai+&i4$K=4XgeO(NM2lFy=jCUrAv{{yvgB%gzBXgJK)611kJ717|$wI0*4}32$J}GD@_-l8IH;zU%#4VzSRxZe!=4cu!0PC8n@>_TO`*9f2dV$mQi_ zdA!53{#hGoVCAAQwgvZ6>I#cOfk-sRCw%&j-r4=8 zUDlCwzti&d{fOtQD#b%WlO~QHdV{h?R;S2fzg}u&=W%n@8C{cA) zezbzdLj_*W_p*2}TOqjnP$h|aFIrAu=TRzYd7wliO2U`VmS1{c?%wNpuCMDa7D9oQeL2Q?`KmC{u{g8 zd1>QPyi>2Nz z*>L(xq)Yd^)u+LeS&t)p=Y0UKC(ob^P8rubI$A4!i4Zm0g=x-Hhi{q* z7QS>EiS7%M;PD!`IRZ>kfyKUm$3*vpyZl!_iEo8cerfyca(h+zHJ&^Qe;2=up(y2-e4vO^Zxk@a3Z^dV|^<%@(WyU z&oR{`8To43dDL-xp4g5!YY=c_h5%0ugKA`lp5xndykWZq)fXGuGNEyxOnSBeJrR9S zCIg$?9`vurbgYO@<^wU&v|L@#%U-K+sC(_#nS+e2N^Y{Uh?wQ120lf-k$py(1)Ja( z57=%Jp>N?6?>JGj=*ps;Gm8(U$+uWRjK#Pqr+jkccD=?}hQ{r*&^7WlcI|WVcI$Lg z5132#?#uRr$=&kV7k5@5p98aT-iy`yd?!rU_5WU7&wMg zjM^?-^W{_2A6fUQQoypPg2J5Im(sO!pwC@}#R!QAR0e*;vnNaYp#w`|0$n7(P}w>? zlAIO&gPi8_1ixt?GsK9A*BtTf60Cd^dYY(OUcu5&{2DR#Xzwkw(}~|5ZqwfJYbcWu zU_xZc+|*hiHL@Z*P0~kPESfW=_r$auGbe(?%)z&__=qBysF{y}Jd{yVmJK*}{F**O zST7J1IG-KO>Hq>NzViIIgW*k_S+sK5iuvctM@D8H<$m_pzLOw(B1Ci}@oh^R_4X=c z3KeQP1Le~4Wr|mwxsZuGRepPNM@R$wi)wAr5ek4vo+2_$5 zJ+d6ms2szg^p*{hG^?vPUCNlF@B#YVNpX1|@RbM*xnULShqjE9BMr+xzgl$MY#n4X zM5%=6OdBo+q+n;3G54|rqIAQ=0I@G@%_UY5BUP2v&b};qyAB0R%_gotJSqeK?9J1u z+bpPqb`x0RQWtZviGA)#V03ocsP7nCN?*fHFf`N{JT5%=tI_HvFhvGczbcQ#%yv7Y zL>!f_a6l@IGK0LzeNHLGfJ_HLK>RTik4qmCiAjUthQqITeNx#VQLM1H(6?t5E!Hw7 zI^`oj>jCGBTXK9a0@_cQ8svNEn3IMU^H#V>@L3sUC6Uio*WP*_`9qUYZk_7bnuGdY zE+pCpu3zgo0i=l_Thfg$vAsv>pNOj1P6@s4F);dc&8AL|j*d<<+54^iyi1GVOxf@w zE%$7)?o~)H!4&viyY(JmSsXEBi2JcXz6O8iE&nIXAfLhm=t%eR!N$~T|M3!#4PU_B zMrxhf1z;v;=ngF0;&mI8eWT8d{kDxgOP8pSzu5+4tX>c#dWO;Q#;H}xs>=Cx`}*)U z`9mGH(xD&q8~6$e;-EV7-M9Lg22*D{9#!}-a!X#{eRt=K!?~?F^-c*$@QQvf2HLf| z!pFJ@E0r)~DB%+$P;xRP!(&`Sjy+`r2xjM^ZBL}$~ z{rHhvfdWUj;Xc{kzEAxghhd@>PRxL~*B-1t@oL#^oFcyAne^~k%|TjbUE0b4x`%y@ zFz1o2?4zO_c@a-xgDFo}h>_bzt8t}NCqGPfPu=i6!?ICoX$_m<&^7#*X^Fzvv^XwZ z)-Z_oJR`CdZYStBv6&*OR4|BRsQD?I3JN1{w}$C($5YA@!rtJr>K(D@c`{`^BRY6M zv-_T(!Vs74d`ogajVk~kC^F(zuyW!~r99)60?jz9__ox3PpZr6NV}WPDB7>&6sZwi zB^oNlrzoLHQtV)Ojcm4=PmzzHG@&5)DJeiIHS^(Ufu^<3z1N|b#rGSJs^nm6mogl} zn$~}ArkJOKdWi#r748$aBpnr*>hOtb355V%=i>H5F-Cas=3^=Mqxu z@72ho?Vlokx8Cv8ExZPFPiUzqr zjNQmtKB|MUy?!|;rsbHqoqF28xv~XUb-rh$t93qRip%npSoM{&Eh_7{NQk42>9j{m z6d9Ll`RtGMH9D8KG=PIPe&^5?O+4BrqCrxk*47`x8!9We&+7{dfad*=a%&Vrev+3C zyoR(pXmGGA*y2kQU)uF^>&3tOMi&^sI!#Cg5QRX`RuD8(hxl>LUV1WfmEiK}84`5u zatA@|BvjyfMIy{s5err8Uo<%2m3dk_J+ZwhX$(xf#E_$60sZo&4e=+v55b(LNo{Sx z>FL33ZPMIly>FmT{^k=@&#K(p0AKI6Ar(l5+)h}{9}{^T9m}qzYW)ao>*~fyh49QH zN9Zt_5}6<><0u>mv8y409nPK3^+#_^1Dr!qKnc7IHw!0a4+uS?3DGGnfvR^qh*5BY3nN zscg@gx0*(&JJqg+>#{DHYM3aPn!c!S;LGa)RWvOv9sudh8Pzm5(oYY;ib8+@^ZZ_H zfTk#~Bs%T7-2ci{OFT+@qhw^v$h>>CBN`2dRCJpO=T|Nlc+P($tlR=Xkc*~sc2nN> znGbGM5c9G>6pW*CkWBu=lm$Bz&Vr`L^ZQ5s+tiyIhi%s8MYdk*tjuwKX0PgSS!x1p zF_%azfiTo+805n{B{wCVCAnX}B>4{^f3189kBS^mYH;xvyb2PMh^lZoKkPpfXsY;e zAmwJ-pVeYANSk!7GM=?#yJwchx)l!CmkO!WzHA3t%8Iqcu@(fzHMZ;%!!R}nG~p=< z`|S!;=<3!+=|z)v-cU+pdfmAm&s>L8UqN=^?;R9ZtUVdGTfffR&IVy*EH;C-6sdL0 zDPqmaKXY$A@ME(NhuU}RDm!9nTTeAJL{d}_Sa&luRjW+}jTwQH?JzN} z4jb&~!giB=bpkoWW+enSMc3mZ7^;DV+t^xISXg!*+)yI*Ja^px ze30V9t-23UWDnBg1!C#JHO+ueGu&)#fKs4c+E`GM2wN722exctLnUe&|L9a;ny;;B z{I;X&+wbk4$bP^KuQQwcOzF_s@R=$up5@!x<%p|aPB4qEb|{Q^dTCANJWKo$SU+C7 znHC8EY4W0BvpbedAeKVFudu6LY4}9PEB-7-txlEk)p*k6T4iz?h{5q_8=v1XW3?|u z$a)NexW{|)=T9DC)V-hAh@AHI^r-Xefl7=gu6PZQ)3Fih#l0f9#BcA?K@gROgD*@*PxUJ|I7kWS(a%Gt4h0;uuA5kC*;YvKfbEB-~$P}TIqw6$0kU|$mOwD`u~ z6xRHOxbeAfjwp8)Pw=uvALe>|@5!>{*A8Es!&`r5nBL9dBfimjkbO%Wm|NJ;< z>*#6!DQDYFqI{?AK%8KoudP6?0rvTY78s|JvG*33jzn7R@~DKmn9plU$r+m-N)-SW zm}zu*5q7+30r%A*;3mYcP!%{SvH>Un-hArGD*gls4gLh~DYuG^q+LvD!W+re>&#jR zjXePK=3EEAbyoNelP?T1dL$uj^@iZyeSrHzU4gG7MG>e-Ya`S0c^q8cik~A&&Cb}z zDWrMTdtRthN1F8qNk-9{VM6D@?|3}S!XT2N zqpQUn+`Po>aBkYihg+Jh4~c;dzjUo~MKrJOte1vHV|&XC!GN3Zo2RTcnzWHRdyyAG zra!h!2!$NItqGw}bvoD^7?5LF*!yo1JULuSLdHv=-ml|Kz-0=@MixGU6}`DdWwS9` zHix=mG@yBO`M}Z9XjP(|QYfOb;ZfDMB{43jCzvaxZ#KAGr#i4HmJqaPREHiL(OaL`qlzSz(K?KI(%dq3*%yxQAO zPtU?;6rabwgQAQ$kR82ut{F~qM8yi}?d=U=?lL*ucRaV*CtF@x_+o7`SJKEnBzpTh z>fJ145C03l?)k|?tW4nhKn)!r3N*S1)g7eZxzM`wNddz`$$r&>;B2|2 z^v$``Za3+h1zQ+px91zusZgqR7yPgeJ(=nl;et>+tT^=D>y4*?AYaQ;%~xNqKtY?9 zYSmzEOJntXdzUKrE4D{=w8tfnD_|NxDPODsuz%i|^NA!XgMvXF)JcdeNUXwG+s8p> z2yw~Dlb}wyGwFAKA-_Gi(a2tlivCUXqB-7e@)4a2f~U%dC9N^m%{4?*tbwk~b4${u zJRv&ny@xo5WT$)kQkM1yK1D+yc&pT|2F&Vd0zVth#1WhE&AQp;`tl_)vKBpHQuW6R zT6Wzf7(Vxnc&3TvUmJn@)*YQRF_O}&dSEG|ZO%Pga-1qK>3N4O|0rI7b%d~51njY8 z-N=V3sGoH-thG9ve_q*8!k=4w!`#WH?KT;&ejo_hvm(VG?1re+3nYh7jHgM~uvEYT z4(5lF&7xh82XcU01<;7f`4f}dLix^>m6dhK%~I_TE8^0|M`JnTa%X??i>cae%#hz< zWZ1-hHX#s?%*jldtS6_1gr-S#&^}j8lh#Z7q0C(S&HCYjOO(4B`wR7vRdcBgP(?u( zG19{0p0<6)x25z39h2V8)z#Hk5e@IB?(&hz>Ju1HT$Ri0_)jbnaZtfQMk=4BGyMAD zx^30!{TWnGgl@ekinDl|m*cPzfZTp^y26YMpSk!aCg~3cgc{g6eG1dsx0ZSes#t2O zXfz$XN#>8C6R={sVP2kVR@gAhv`4Sf%6`>`AV&(hu$MI)#^Ud5w1Xe%PU(; z$++3~&`Nj;b1^K&ul=$V^&t8s7=N^5WjbhXH0E^QmN4$e2-J>s2_L>fj;d0Q2`LMR zRuR8NG6*?#Y|`R3^Dsh$@H0n>Ti@~z5XHiyO}1H=S|V@fE5#J>DMCj&wmkKwcD2+A zxu)Y93%1OLJ83_nZd$W#cJn!UewvgbQiz1F4=lELB+E+c#A6yP04 zrGs3Mu%s=iy4G0-&%IxW{5{6kPhm@dOia;<3KVVEIEn=K|J5?r`27|YLSqo_S?4iS zUlWs%5W_$Os8C)a#CqP!Fl8Mnq<$om?vK{Ia$(uTull?q19pI+ze}I8r1J;bW<< zdcdOLMnUbhQbPCq5}-P_84ZENZr<5m1g00i=kIGe=w+1mhogkV3?1UEwCpwZ6-k*` z!debduN!WB8t`WJ-pR1S%Wi5+%L6wlox>si&~Q-ZiphIWOxf|7pL08V7pf=R&GvC_ zd4_~N%Zn8R9iKR7F$ny?!0#%En2abKQ&J#c>-;^v$-3?KkM$S(gPX7;O=ggN1sVOV z(%f2mA(lo-$gIuS5EFmPP#_8n*!Q%;cQ_O#X9`=0(=48b7rCIq=jykAr z{4IDF0o4%!Bvj-;NC~w)v1D1bQy?Io;C!k6J*&uB#WnE?B%<)%Wu%cI*mh#UKKMSF ztS%t#!;Padd#(vWPvVs``6r>(j?{#XbaOL}K`Moo4|&7z62Y#-q{!{g46A~FJj6fp z@$8vY%mYFii@x&2{nXQ~YMR8TOL}W&`FHwrfL6j6jN>VSezz^|y}|*Tpe*-@AcxRj zrH>bU^&k1L`=M}mkzS-JVNhnu~Z+0$ZHTUzG#am2i zF_8Blgr+=ee^cL8H5KseYQNP=lZ}S!IiAav`e7=J~MOkn1jpd#2lLd(gp45jdX9(T}>pHgm3}rf#^SB1HlmyLZC)t8<@bT9VNTbY|m}nXd(J} zQCwj`Lia^v5-kN9krK`#zVuo`T@4;{2n2Dj1}$^Oxh^AXYilRKo)dvS%N(uGx9Vn5;qn|nipW*@^9|4V6iU><1bn{ zbl06v+l;O((R5Hm*Gx(STk0e95R-<7l1zCaY6u`s{eM$4ld^5Ud@xyme2WI5m|eyk zcCdJ6Rv&4KTh?6hxnu-$8EA4ywh$1`mM7U2B4Pvf>ozKRxDZTyNhNF7k+oBTOCtQn zYy%3b@!6DKRxu+OBm*#}4bf`g(d>Z<~{oj2;8x;#4PoG{2G_ zpaA5y9rzUc(UV}?A9~s+uxQuhtH%GVLFiwP0BtQEQtAIoQy5hL9CJctt9DCUfbZOP zyuDww2*=-QZ6Jqb=>eVYeM&#fGy<-Pn!I$-I^>j1@M*W*k${VSKKv2uth?o2yI$Kc ziX|uG)!oIs4N6+ApK9A!a@W<&lcU<*%d7;MMrRQUT4pzvjm4IC<>iG>Pmao@5&eK~ z4P>MK7UDVR{bv9g*Q~A|s4!W$|G8I&H9yD3i|RGU6zC#+)U3SJfyfFW9HWhHy@Kqo z{S~GsM&JJOZ!@hj4s6`TmDTlL3DiCXww3^M0_+gQbTU{Et-qWH{7`@Z)7^uoQNFi1 zhNGV))xU6a8##1waT)yEAIfC>V?K$0UE~1c=#kuo+!a#1%orB&qr(I&&0fLEC)0AV z$sf4acXWXwAG3n`Z{*0;8_OvFwwyGJ$3CXzgYwCIICkdB-I#qqA4`kIGri)>@w4Z{ z^I_DD1!2x`ty*)NmoI<(f7M-iI91#Gk5h=`-iVFTa5FSq6oTBrYQ9uOIFDF38Y?=(Phs>PrMF8SkUoeHs^VA~-EPhSYM>1Uwr@ zAxz=!2~yr52TT%xGR=^h=$YtP{}3WhBfeDy;2KwG@r|xt-T=B09&Rsn3uSR>enbkC zti*ToWY^=pQusk3v?*C_0z4Dm=ZoVQfge$Nq~S-LJr>N%1}z@(>FdrY8v{>mN7c@3 zgUx>*0)=%4(l1q{E^M2X)km7eMu7(bwD;{79)D_q*oH+9EjbbVaX+FUl<8@E#meQ< z-!zG1pzR`qU$INic~JWoyAP>c8UOp?Zq@D$N}$?j7lzwF(d=Xnz|nc*+X6)&{vJL9 zKvXA5&Kx|o_8K4jsD_#2U@eBz*9)bak{S!v@bbfD(Mdj$RXCKtGmhAS9waE8zD2EN zL>AQb6_|kXsgUfh>x#{ohj^RW8Q=G~5wCu=_~Es=nJunw_r!2O;xXy!a{qb+USW7Q zXzXpcWS~p<__NfGu{L?QJ4yuy{}x1S2M&aT6I2BOCe>wt%gE4B{gf&@df42{GNSjO z)H>8*2RG80^x1Dy)v=vSR$MkYdefB$o}^JeRD19=$>n5N&wT-Jh>nB(XqQMXN5G#E zpDkU&CE=;6qPchpBb-@L-MZihFaQ>yl} z&dur}vxZX)vCUA-bO=$B9Hp(s+>*h{s^JuSLrPpQ><>qsR=V zC4`9XDv|pdcaH<(eRYP|QBc9_BqrcTj21d^EP(bmb8V_n@C`0h`&a<6 zZ;~hmk?&F~Y(F(W3FO;iS|osj(IDcf<(XvFS1~SY-<-Bu51pVVVl(;tfX|gh|8gk} zfwb3ZendBDap#$ZPbaTV@)H1Y6yVL%~hxaNcylMg+YmODNBLUy9w_D zXboze{&pcnDTAxg1vipXJ~xI_6fQyZ0`=bsKo=_B`mKff|6uMpdeCtBYJ|Ir@gZe> z0RpAOdtNS?)VifzBeQ<2n6k9yJW!^gAX0(4HU8c}jWxn;AqVx;=2oiZGnN#fPjn3gCykMT$Px z8G+5eF@)CIswX2=YzJUw5<&fS+1E=&Y=2A%YHBYBQ0%BDLES}cH9RDYI>@S!;=r*` zZt;*D=j@i^@y}xq`n4814wI5yM~h1~wj1KTU!DTRD&?s|f4AvdM`UDt%rHIX2WlcZ zEP=I*v7DUv*z^U@9d}<^91d>uFSk98S28(p!uu`{9La-bP1=O-K1zN1BQZG{ZOB?SF*erZziaZ%A^SAx2OEv$zsL>1);x=dpvCIxg ze8B80M5oi`RX1N5eHveO$cAxl0gj z7fa(=EcKdqZE}ng8znm4&JTl)?n(l;t>6naOqslzK1@C6;8=NUeC99zAwUp5rS$bp z;Z@!PQvs?7nfJQtU?ZUG3tC6-t@D`W4uf;m`DI2*Z-H+ZT6`WsIO)mn-6I$#`fv7 zkBxc6Fx?GEi{v=T`jSu9hGLX}TDfhB23NqM3z=WgBj*7H4gkh6APsCr4uIITt$uHFNBzA7~(@BeqCn*0@VdDP^K>N|rf~ z92?N3gavCa`qGqY8U8$-gZFNjHN4Hxd7et?`D-A>43U<%E2(9Knm-0(A~5zi9cB5L z=-pv%6@sX16Wzk4=bCkeh|sQ%Ho%yerf{z219cJsn=pilC3r#mJP12#il=s@?tWa; zJb@4fpHe)tT1W!}q}dB>?U0K7D>Vh!aUGqcYtYcEe-FwmPHZk;8?Y@?R1suo9DkER zK8TRL+MepX$p3c)U;5rT-m#2u`3@ERiZ|>AU`RJ{%q{o!CNylw;bj1vcOH%XEi!k_ zJBz$bMQZh%`uDE>G=+xKnJIxq?+Bfn9IdCWXg(O?*oY?gJ*j4>4-5blXeu2Q($P(P zmQN|_BP+9J>=#f)uskBbbNJHcYHaHT0tn8C5`{^DvC2b*H4RN5@=e;E0g_OkKaJk+ zI%~p6cBCvO2J*mtqP3z8>^cyY%2sXbdBvx&kfSl;JSZ+48Y+A@H&+*7A-@F*jj@n} zP1qT0s6yus$I|_L@6tlF19OSPCjoKhn7V8n<#?; zP<0RJOV)rFT{NS-Y*On?=)M*%W*&LQIGZhb!MAb#{XPGV;_*-myS{>vB76_^kxJqNeHUqb@!6{hQZbLUj*3mEBuVhxNs3d1+4&084 zw0uu?ll5xgtf}R;-n%VH=7WuA0I;9YAkXX_%FP=3+r31Sk4p?T*)y#Bs{|9h845vb z0Nqdll^A)PovUL5jz3KZL>Q;EH8r(Wy{%`zGB|eU)<|Hj{!Y@h=&_f$tfnrJOP$&_ zx+P#Hlzee8m%?gz6+DaFK9Y$kd3h=cvEH0`={a!!cgZ)2{d0``VOQ;Y*&Emp=@*29 z5tVBK?x&0DAkxpl9~Plfp#t9IN}4TKSZrfyU=bB+|A zEyoX9c^v+XpG#P3;PFxe0mO@aXb4~4N4`9jzO0OIPn(qOqu(MDmA0Kx-@ZEuUp$V+SRZUAn~cP%~I!CkrNLB zn6qktLNaX-hx29rq4Dtrj@=`lT1JSW7jr>Ri4^1gQ|f!?_r%7#q7@_O?iGsRkJ z9tTPuC7a2(K;pDh5N$ri%jI@4rO%zERWat1xdQtkEP406*HwUXGbKv8|FUuk_={-L zP#G=^c8J2Gx5is*84mtkWX-5KY&XwjKMkzq=hm7JI%e{4jOFNZDgeQoP26dDc@)Hv zz*|_DkRm`vwh5@2m*pfg7nh4rbaK*-_IwmVYa3cE=^QGs%*LX|v$G;#?~PZ2Q-0^p zowJvy)s#Y#vGgC{}(=4qnmkW%TIh3+iAG+p5r*++Vu z^|tK2{Ag&>y~83R&j&Cdi@r|IpUSUxV^wrmcJ&(|QHFDyib92U8c`E$ax*A8vT4fk z@llSkyR=OJ8me>(A8T;C+~njZhPLmD{miX~NKbtUoNQ{Qhp5HrK&8}*XN;rWWhVio zK?>(?8VaAgUb#rgQ621Tns_wy*%ajB!OeI7lzm{l2^39LI?3K457aD! z6uPBcZ2V|x8uf9%{Y-K7`GY3+&*{u$JL{b&x@dp-cmj10hc<&OpDVfeyu;|&RQ_86 zJf$#O9q8DndMM$NXK`RKN56GT^FLiRYXZzOM31u|OLw<-$0w_O$wSsdU|`a28|PEc zcl65F4=Eiqm3fWRUW3(KkEkE&3Xac}Io;?gm@HZJg`lpW&5t$dC0O~r_QACmhB*5lV`ck=jxF70hKwV_k4@|8Oy>`h2;G4S-teB{f``WSQ!6{7h_118IzxQ_JPL{-Vkg4 zhJ}AcJgC4@IZU@6-z6_Mt2ys@2VVe^!Y<*5;I}tX#Oc+5xY`mn4H4NV=9qARJJjro zMTEIYEht0sC}*fOPmR^yH=lK+1`sS>+18jf;5P~+EEORZZ5tsuNqv!y-*#U1qv3DA39W~vfdN6o? z;h+T5s4TjN@bUEuCKv_c(7aj+{EHourl3fdeJ3Wcp^A^B4uqkDOTzk;C^brCWXlmW3UaC!}4J za~ilmy>LHYZFHkFw3q8BNFZ?tpjQGF)7Qx$Iq5?q?j4}o#mA3EBIRx63NXiVY)t0` zh=PJn(efJrT7ItLYcI8Xb+4>Hkmf4BK!j4LM`}_%ifI+8{(V;1DO!;6xu3QQ6?1~| zEE{|RC4 zwjEzrZxC?sx03LhWPb$w_M$^}EgzDDr4UMtZ(%go7r?BQrzZY*D^*BgpyGpyDkML0 zAnrp@<*Qa+Dd698!;KvO9FWQ&)L~fP3L!RsSp)m~0k6(X{ITW@kYOo>RL+D;mA0Q! z{|QB*Ch@4sGYY91%KhqB3u?Ff5+#@Q7z}(yj}4~xA@<8Q6T@jB_onj5^At4m+J8M* zgbZ5#0~NF8=^YM|OC(w+NbkS8Cu4iHpdhx)_=K^8m9@2aEk9a6`2DO*>#u>xELH+A zfvcGikRKT-8IUdAd11sOS1p{zzc^BT+)*ihM2q1jbB~z_!3ENA!~cjZxoMFnA33dM zOcO+ImDR7S+hV{+xl|=pMWuwbPi^b~ZYCr-{&@Q`!O4aKS3k%F%xNWMxBZs=W&`6> zuCE9%kD!~3U=R^%2B%SNyL#OlOqJvl>+c%Vz`OU>qMAcgMbkDcwMNo)H~D5Lur*u{ zo+dXl{o<7Ky<+-X5U&`#CfMA;@(7{_kuC+5u2^e{7KfhfvV=etm>J=TrC^v1ME;py z7TI8vR`Dh3l_eR3e(Ifc*8-dJPm~p87Y~dXW~wHfmeEN$vo9)ID#kLx2{SY1OfyqW zpX>$IOG`m0hRJyGaJbfp>AUy7l{#&_Tj3e4Ft?6gb}M_0Cp|}06MCND_=l+4;q5Oc zSCQnXz#jtS!23X1*C0O!M?EOm{Cfc{wc=ktIaoE|+>u)ed8cS_cZ@{}r`myQFBY z^M36&Vva4?eg~BX<6Z||az4>HD<^D&fIP(~ce*wvDn<$e)n5{Imic`_ltR42f1PIh z=R?j_D6v)w;5sH*h5gtG+l=oUJYI)Y=9c3Ek_M^qVyh5#n^b0mf>B!FjlGabr2PKm zhQxZUfdq@&*yA0r5fb08TkZ(-7r}*Ai--L^^cR+lh>#2E;zKYKw={sAmbI#?c8F}J&rBb2?*rpI#q2B}hS4U+J%!xrKOqM1NTV)Y=!pQCP zBi#>&Z+FIL9^8U(r(ul)?oD5*6x1O5PNsfU!QTYL>T(w%;OSn6E?l(J*hYVm;r)D~ zGBuG3lo6cG=*Mk3EvEHcKWW~N2#&umO_d+5+`Ogy*pSZ&Um}4FfJ~|xh%h;yx~Cjm z82@;E@|@6*5=p}o*YI^uDDyz>5MoDCwWQg(P%onXw+;~KHbUVHQhfwAkrf>)o*Dbslu@~GQgng53wz~*{# z2w7iWBIEhR*!_?K$=h7uhe2S27eS=!G#*X!Az|w$C2xNa0+)X3Tf8&Yn_%~R`*e!h zcT0lZ8wRPEZED`Bbj|_D@|`MR3jYZ2;hmqWxXsGx$NeU6;rz%ylBe>(Az)FNhuURZ%p0K{e!k+ zN`DBcQ+^%ZxKV!PN3~@5j~6+o23JZJNIMj$zKSl)4ilHG7R#8BB0jn%+Jx{QORhb( zQsgSe>}>QtoR*vK&uiHqM7ztjqAhlGG@X5gz>)~&uYMk%cSx81>J?YPvuHv31JlT* z4aKVrr~CM<=pPvHa^dAI`pp=8Zy1>N;roru`W8q;{JXbVmwsAeaHH^wOFtv0@%kdx2{mrdh*RcQPQp_J*?8tW31up#3 zN2}1EF8n9o{npHKyVw3Z&3tQjrFh>y`Y(6+pGf|H(B;YrSYELI*7}%^e`TY^(`AbF SL^rPj|4yFJK2AAGy7oT-FaKKr literal 0 HcmV?d00001 diff --git a/libguh/hardware/gpio.cpp b/libguh/hardware/gpio.cpp index a9216550..d3dbe8bd 100644 --- a/libguh/hardware/gpio.cpp +++ b/libguh/hardware/gpio.cpp @@ -161,7 +161,7 @@ int Gpio::gpioNumber() const /*! Returns true if the directories \tt {/sys/class/gpio} and \tt {/sys/class/gpio/export} do exist. */ bool Gpio::isAvailable() { - return QDir("/sys/class/gpio").exists() && QDir("/sys/class/gpio/export").exists(); + return QFile("/sys/class/gpio/export").exists(); } /*! Returns true if this \l{Gpio} could be exported in the system file \tt {/sys/class/gpio/export}. If this Gpio is already exported, this function will return true. */ diff --git a/plugins/deviceplugins/deviceplugins.pro b/plugins/deviceplugins/deviceplugins.pro index afd292fd..4a64ca96 100644 --- a/plugins/deviceplugins/deviceplugins.pro +++ b/plugins/deviceplugins/deviceplugins.pro @@ -28,4 +28,5 @@ SUBDIRS += elro \ denon \ avahimonitor \ senic \ + gpio \ diff --git a/plugins/deviceplugins/gpio/deviceplugingpio.cpp b/plugins/deviceplugins/gpio/deviceplugingpio.cpp new file mode 100644 index 00000000..2e5f36d9 --- /dev/null +++ b/plugins/deviceplugins/gpio/deviceplugingpio.cpp @@ -0,0 +1,287 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016 Simon Stürz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*! + \page gpioplugin.html + \title GPIO Plugin + \brief Plugin to controll gpios on different boards. + + \ingroup plugins + \ingroup guh-plugins-maker + + \chapter Raspberry Pi 2 + + \image Raspberry-Pi-2-GPIO.png "Raspberry Pi 2 GPIOs" + + \chapter Plugin properties + Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses} + and \l{Vendor}{Vendors} of this \l{DevicePlugin}. + + For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}. + + \quotefile plugins/deviceplugins/gpio/deviceplugingpio.json +*/ + + +#include "deviceplugingpio.h" +#include "types/param.h" +#include "plugin/device.h" +#include "devicemanager.h" +#include "plugininfo.h" + +DevicePluginGpio::DevicePluginGpio() +{ + +} + +DeviceManager::DeviceSetupStatus DevicePluginGpio::setupDevice(Device *device) +{ + qCDebug(dcGpioController()) << "Setup" << device->name() << device->params(); + + // Check if GPIOs are available on this platform + if (!Gpio::isAvailable()) { + qCWarning(dcGpioController()) << "There are ou GPIOs on this plattform"; + return DeviceManager::DeviceSetupStatusFailure; + } + + // GPIO Switch + if (device->deviceClassId() == gpioSwitchDeviceClassId) { + // Create and configure gpio + Gpio *gpio = new Gpio(device->paramValue(gpioParamTypeId).toInt(), this); + + if (!gpio->exportGpio()) { + qCWarning(dcGpioController()) << "Could not export gpio for device" << device->name(); + return DeviceManager::DeviceSetupStatusFailure; + } + + if (!gpio->setDirection(Gpio::DirectionOutput)) { + qCWarning(dcGpioController()) << "Could not configure output gpio for device" << device->name(); + return DeviceManager::DeviceSetupStatusFailure; + } + + if (!gpio->setValue(Gpio::ValueLow)) { + qCWarning(dcGpioController()) << "Could not set gpio value for device" << device->name(); + return DeviceManager::DeviceSetupStatusFailure; + } + + m_gpioDevices.insert(gpio, device); + m_raspberryPiGpios.insert(gpio->gpioNumber(), gpio); + return DeviceManager::DeviceSetupStatusSuccess; + } + + if (device->deviceClassId() == gpioSwitchDeviceClassId) { + GpioMonitor *monior = new GpioMonitor(device->paramValue(gpioParamTypeId).toInt(), this); + if (!monior->enable()) { + qCWarning(dcGpioController()) << "Could not enable gpio monitor for device" << device->name(); + return DeviceManager::DeviceSetupStatusFailure; + } + + connect(monior, &GpioMonitor::valueChanged, this, &DevicePluginGpio::onGpioValueChanged); + + m_monitorDevices.insert(monior, device); + m_raspberryPiGpioMoniors.insert(monior->gpio()->gpioNumber(), monior); + return DeviceManager::DeviceSetupStatusSuccess; + } + + return DeviceManager::DeviceSetupStatusSuccess; +} + +DeviceManager::DeviceError DevicePluginGpio::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) +{ + Q_UNUSED(params) + + // Check if GPIOs are available on this platform + if (!Gpio::isAvailable()) { + qCWarning(dcGpioController()) << "There are ou GPIOs on this plattform"; + return DeviceManager::DeviceErrorHardwareNotAvailable; + } + + // Check which board / gpio configuration + const DeviceClass deviceClass = deviceManager()->findDeviceClass(deviceClassId); + if (deviceClass.vendorId() == raspberryPiVendorId) { + + // Create the list of available gpios + QList deviceDescriptors; + + QList gpioDescriptors = raspberryPiGpioDescriptors(); + for (int i = 0; i < gpioDescriptors.count(); i++) { + const GpioDescriptor gpioDescriptor = gpioDescriptors.at(i); + + // Offer only gpios which arn't in use already + if (m_raspberryPiGpios.keys().contains(gpioDescriptor.gpio())) + continue; + + if (m_raspberryPiGpioMoniors.keys().contains(gpioDescriptor.gpio())) + continue; + + QString description; + if (gpioDescriptor.description().isEmpty()) { + description = QString("Pin %1").arg(gpioDescriptor.pin()); + } else { + description = QString("Pin %1 | %2").arg(gpioDescriptor.pin()).arg(gpioDescriptor.description()); + } + + DeviceDescriptor descriptor(deviceClassId, QString("GPIO %1").arg(gpioDescriptor.gpio()), description); + ParamList parameters; + parameters.append(Param(gpioParamTypeId, gpioDescriptor.gpio())); + parameters.append(Param(pinParamTypeId, gpioDescriptor.pin())); + parameters.append(Param(descriptionParamTypeId, gpioDescriptor.description())); + descriptor.setParams(parameters); + + deviceDescriptors.append(descriptor); + } + + emit devicesDiscovered(deviceClassId, deviceDescriptors); + } + + return DeviceManager::DeviceErrorAsync; +} + +DeviceManager::HardwareResources DevicePluginGpio::requiredHardware() const +{ + return DeviceManager::HardwareResourceNone; +} + +void DevicePluginGpio::deviceRemoved(Device *device) +{ + if (m_gpioDevices.values().contains(device)) { + Gpio *gpio = m_gpioDevices.key(device); + if (!gpio) + return; + + m_gpioDevices.remove(gpio); + + if (m_raspberryPiGpios.values().contains(gpio)) + m_raspberryPiGpios.remove(gpio->gpioNumber()); + + delete gpio; + } + + if (m_monitorDevices.values().contains(device)) { + GpioMonitor *monitor = m_monitorDevices.key(device); + if (!monitor) + return; + + m_monitorDevices.remove(monitor); + + if (m_raspberryPiGpioMoniors.values().contains(monitor)) + m_raspberryPiGpios.remove(monitor->gpio()->gpioNumber()); + + delete monitor; + } + +} + +DeviceManager::DeviceError DevicePluginGpio::executeAction(Device *device, const Action &action) +{ + // Get the gpio + const DeviceClass deviceClass = deviceManager()->findDeviceClass(device->deviceClassId()); + Gpio *gpio = Q_NULLPTR; + // Find the gpio in the corresponding hash + if (deviceClass.vendorId() == raspberryPiVendorId) + gpio = m_raspberryPiGpios.value(device->paramValue(gpioParamTypeId).toInt()); + + // Check if gpio was found + if (!gpio) { + qCWarning(dcGpioController()) << "Could not find gpio for executing action on" << device->name(); + return DeviceManager::DeviceErrorHardwareNotAvailable; + } + + // GPIO Switch power action + if (device->deviceClassId() == gpioSwitchDeviceClassId && action.actionTypeId() == powerValueActionTypeId) { + bool success = false; + if (action.param(powerValueStateParamTypeId).value().toBool()) { + success = gpio->setValue(Gpio::ValueHigh); + } else { + success = gpio->setValue(Gpio::ValueLow); + } + + if (!success) { + qCWarning(dcGpioController()) << "Could not set gpio value while execute action on" << device->name(); + return DeviceManager::DeviceErrorHardwareFailure; + } + + return DeviceManager::DeviceErrorNoError; + } + + return DeviceManager::DeviceErrorNoError; +} + +void DevicePluginGpio::postSetupDevice(Device *device) +{ + if (device->deviceClassId() == gpioSwitchDeviceClassId) { + Gpio *gpio = m_gpioDevices.key(device); + device->setStateValue(powerValueStateTypeId, (bool)gpio->value()); + } + + if (device->deviceClassId() == gpioButtonDeviceClassId) { + GpioMonitor *monitor = m_monitorDevices.key(device); + device->setStateValue(pressedStateTypeId, monitor->value()); + } +} + +QList DevicePluginGpio::raspberryPiGpioDescriptors() +{ + // Note: http://www.raspberrypi-spy.co.uk/wp-content/uploads/2012/06/Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900.png + QList gpioDescriptors; + gpioDescriptors << GpioDescriptor(2, 3, "SDA1_I2C"); + gpioDescriptors << GpioDescriptor(3, 5, "SCL1_I2C"); + gpioDescriptors << GpioDescriptor(4, 7); + gpioDescriptors << GpioDescriptor(5, 29); + gpioDescriptors << GpioDescriptor(6, 31); + gpioDescriptors << GpioDescriptor(7, 26, "SPI0_CE1_N"); + gpioDescriptors << GpioDescriptor(8, 24, "SPI0_CE0_N"); + gpioDescriptors << GpioDescriptor(9, 21, "SPI0_MISO"); + gpioDescriptors << GpioDescriptor(10, 19, "SPI0_MOSI"); + gpioDescriptors << GpioDescriptor(11, 23, "SPI0_SCLK"); + gpioDescriptors << GpioDescriptor(12, 32); + gpioDescriptors << GpioDescriptor(13, 33); + gpioDescriptors << GpioDescriptor(14, 8, "UART0_TXD"); + gpioDescriptors << GpioDescriptor(15, 10, "UART0_RXD"); + gpioDescriptors << GpioDescriptor(16, 36); + gpioDescriptors << GpioDescriptor(17, 11); + gpioDescriptors << GpioDescriptor(18, 12, "PCM_CLK"); + gpioDescriptors << GpioDescriptor(19, 35); + gpioDescriptors << GpioDescriptor(20, 38); + gpioDescriptors << GpioDescriptor(21, 40); + gpioDescriptors << GpioDescriptor(22, 15); + gpioDescriptors << GpioDescriptor(23, 16); + gpioDescriptors << GpioDescriptor(24, 18); + gpioDescriptors << GpioDescriptor(25, 22); + gpioDescriptors << GpioDescriptor(26, 37); + gpioDescriptors << GpioDescriptor(27, 13); + return gpioDescriptors; +} + +void DevicePluginGpio::onGpioValueChanged(const bool &value) +{ + GpioMonitor *monitor = static_cast(sender()); + + // Get device and set state value + if (m_raspberryPiGpioMoniors.values().contains(monitor)) { + Device *device = m_monitorDevices.value(monitor); + if (!device) + return; + + device->setStateValue(pressedStateTypeId, value); + } + +} + diff --git a/plugins/deviceplugins/gpio/deviceplugingpio.h b/plugins/deviceplugins/gpio/deviceplugingpio.h new file mode 100644 index 00000000..8ba29d67 --- /dev/null +++ b/plugins/deviceplugins/gpio/deviceplugingpio.h @@ -0,0 +1,63 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016 Simon Stürz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DEVICEPLUGINGPIO_H +#define DEVICEPLUGINGPIO_H + +#include "hardware/gpio.h" +#include "hardware/gpiomonitor.h" +#include "gpiodescriptor.h" +#include "hardware/gpiomonitor.h" +#include "plugin/deviceplugin.h" + +class DevicePluginGpio : public DevicePlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "deviceplugingpio.json") + Q_INTERFACES(DevicePlugin) + +public: + explicit DevicePluginGpio(); + ~DevicePluginGpio(); + + DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; + DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; + DeviceManager::HardwareResources requiredHardware() const override; + void deviceRemoved(Device *device) override; + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; + + void postSetupDevice(Device *device); + +private: + QHash m_gpioDevices; + QHash m_raspberryPiGpios; + + QHash m_monitorDevices; + QHash m_raspberryPiGpioMoniors; + + QList raspberryPiGpioDescriptors(); + +private slots: + void onGpioValueChanged(const bool &value); + +}; + +#endif // DEVICEPLUGINGPIO_H diff --git a/plugins/deviceplugins/gpio/deviceplugingpio.json b/plugins/deviceplugins/gpio/deviceplugingpio.json new file mode 100644 index 00000000..2ad45784 --- /dev/null +++ b/plugins/deviceplugins/gpio/deviceplugingpio.json @@ -0,0 +1,112 @@ +{ + "name": "Gpio Controller", + "idName": "GpioController", + "id": "127ead55-996a-44ac-ba82-fc3c634e018a", + "vendors": [ + { + "name": "Raspberry Pi 2", + "idName": "raspberryPi", + "id": "f0d00b66-bbd8-4a07-8591-ea48a61b229e", + "deviceClasses": [ + { + "id": "3885c520-e202-4435-88f6-3c35c362b2e6", + "name": "GPIO Switch", + "idName": "gpioSwitch", + "deviceIcon": "Switch", + "basicTags": [ + "Device", + "Actuator" + ], + "createMethods": ["discovery"], + "paramTypes": [ + { + "id": "9eda783f-6d9f-4d39-986d-d2cbfff5a7dd", + "idName": "gpio", + "name": "GPIO", + "type": "int", + "index": 0, + "defaultValue": -1 + }, + { + "id": "2204d278-7bc7-407f-ac82-ce3ae1d5779c", + "idName": "pin", + "name": "Pin number", + "type": "int", + "index": 1, + "defaultValue": -1 + }, + { + "id": "504798eb-1faa-4703-a57a-2778e4bf9a67", + "idName": "description", + "name": "Description", + "type": "QString", + "index": 2, + "defaultValue": "-" + } + ], + "stateTypes": [ + { + "id": "06843766-358e-44b0-8d52-2b46ef98459a", + "idName": "powerValue", + "name": "Power", + "index": 0, + "type": "bool", + "defaultValue": false, + "writable": true, + "eventTypeName": "Power changed", + "actionTypeName": "Set power" + } + ] + }, + { + "id": "6aff228b-0410-4ef9-9593-51e8639aacea", + "name": "GPIO Button", + "idName": "gpioButton", + "deviceIcon": "Power", + "basicTags": [ + "Device", + "Sensor" + ], + "createMethods": ["discovery"], + "paramTypes": [ + { + "id": "9eda783f-6d9f-4d39-986d-d2cbfff5a7dd", + "idName": "gpio", + "name": "GPIO", + "type": "int", + "index": 0, + "defaultValue": -1 + }, + { + "id": "2204d278-7bc7-407f-ac82-ce3ae1d5779c", + "idName": "pin", + "name": "Pin number", + "type": "int", + "index": 1, + "defaultValue": -1 + }, + { + "id": "504798eb-1faa-4703-a57a-2778e4bf9a67", + "idName": "description", + "name": "Description", + "type": "QString", + "index": 2, + "defaultValue": "-" + } + ], + "stateTypes": [ + { + "id": "57f1b7cc-26c8-434b-ba04-d3077dc886c8", + "idName": "pressed", + "name": "Pressed", + "index": 0, + "type": "bool", + "defaultValue": false, + "eventTypeName": "Pressed changed" + } + ] + } + ] + } + ] +} diff --git a/plugins/deviceplugins/gpio/gpio.pro b/plugins/deviceplugins/gpio/gpio.pro new file mode 100644 index 00000000..71eb0c5a --- /dev/null +++ b/plugins/deviceplugins/gpio/gpio.pro @@ -0,0 +1,17 @@ +TRANSLATIONS = translations/en_US.ts \ + translations/de_DE.ts + +# Note: include after the TRANSLATIONS definition +include(../../plugins.pri) + +TARGET = $$qtLibraryTarget(guh_deviceplugingpio) + +SOURCES += \ + deviceplugingpio.cpp \ + gpiodescriptor.cpp + +HEADERS += \ + deviceplugingpio.h \ + gpiodescriptor.h + + diff --git a/plugins/deviceplugins/gpio/gpiodescriptor.cpp b/plugins/deviceplugins/gpio/gpiodescriptor.cpp new file mode 100644 index 00000000..b806797f --- /dev/null +++ b/plugins/deviceplugins/gpio/gpiodescriptor.cpp @@ -0,0 +1,44 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016 Simon Stürz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "gpiodescriptor.h" + +GpioDescriptor::GpioDescriptor(const int &gpio, const int &pin, const QString &description): + m_gpio(gpio), + m_pin(pin), + m_description(description) +{ + +} + +int GpioDescriptor::gpio() const +{ + return m_gpio; +} + +int GpioDescriptor::pin() const +{ + return m_pin; +} + +QString GpioDescriptor::description() const +{ + return m_description; +} diff --git a/plugins/deviceplugins/gpio/gpiodescriptor.h b/plugins/deviceplugins/gpio/gpiodescriptor.h new file mode 100644 index 00000000..73b3b36c --- /dev/null +++ b/plugins/deviceplugins/gpio/gpiodescriptor.h @@ -0,0 +1,41 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016 Simon Stürz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef GPIODESCRIPTOR_H +#define GPIODESCRIPTOR_H + +#include + +class GpioDescriptor +{ +public: + GpioDescriptor(const int &gpio, const int &pin, const QString &description = QString()); + + int gpio() const; + int pin() const; + QString description() const; + +private: + int m_gpio; + int m_pin; + QString m_description; +}; + +#endif // GPIODESCRIPTOR_H diff --git a/plugins/deviceplugins/gpio/translations/de_DE.ts b/plugins/deviceplugins/gpio/translations/de_DE.ts new file mode 100644 index 00000000..a1967f1c --- /dev/null +++ b/plugins/deviceplugins/gpio/translations/de_DE.ts @@ -0,0 +1,79 @@ + + + + + GpioController + + + Gpio Controller + The name of the plugin Gpio Controller (127ead55-996a-44ac-ba82-fc3c634e018a) + + + + + Raspberry Pi 2 + The name of the vendor (f0d00b66-bbd8-4a07-8591-ea48a61b229e) + + + + + GPIO Switch + The name of the DeviceClass (3885c520-e202-4435-88f6-3c35c362b2e6) + + + + + GPIO + The name of the paramType (9eda783f-6d9f-4d39-986d-d2cbfff5a7dd) of GPIO Switch + + + + + Pin number + The name of the paramType (2204d278-7bc7-407f-ac82-ce3ae1d5779c) of GPIO Switch + + + + + Description + The name of the paramType (504798eb-1faa-4703-a57a-2778e4bf9a67) of GPIO Switch + + + + + Power changed + The name of the autocreated EventType (06843766-358e-44b0-8d52-2b46ef98459a) + + + + + Power + The name of the ParamType of StateType (06843766-358e-44b0-8d52-2b46ef98459a) of DeviceClass GPIO Switch + + + + + Set power + The name of the autocreated ActionType (06843766-358e-44b0-8d52-2b46ef98459a) + + + + + GPIO Button + The name of the DeviceClass (6aff228b-0410-4ef9-9593-51e8639aacea) + + + + + Pressed changed + The name of the autocreated EventType (57f1b7cc-26c8-434b-ba04-d3077dc886c8) + + + + + Pressed + The name of the ParamType of StateType (57f1b7cc-26c8-434b-ba04-d3077dc886c8) of DeviceClass GPIO Button + + + + diff --git a/plugins/deviceplugins/gpio/translations/en_US.ts b/plugins/deviceplugins/gpio/translations/en_US.ts new file mode 100644 index 00000000..eb9546e0 --- /dev/null +++ b/plugins/deviceplugins/gpio/translations/en_US.ts @@ -0,0 +1,79 @@ + + + + + GpioController + + + Gpio Controller + The name of the plugin Gpio Controller (127ead55-996a-44ac-ba82-fc3c634e018a) + + + + + Raspberry Pi 2 + The name of the vendor (f0d00b66-bbd8-4a07-8591-ea48a61b229e) + + + + + GPIO Switch + The name of the DeviceClass (3885c520-e202-4435-88f6-3c35c362b2e6) + + + + + GPIO + The name of the paramType (9eda783f-6d9f-4d39-986d-d2cbfff5a7dd) of GPIO Switch + + + + + Pin number + The name of the paramType (2204d278-7bc7-407f-ac82-ce3ae1d5779c) of GPIO Switch + + + + + Description + The name of the paramType (504798eb-1faa-4703-a57a-2778e4bf9a67) of GPIO Switch + + + + + Power changed + The name of the autocreated EventType (06843766-358e-44b0-8d52-2b46ef98459a) + + + + + Power + The name of the ParamType of StateType (06843766-358e-44b0-8d52-2b46ef98459a) of DeviceClass GPIO Switch + + + + + Set power + The name of the autocreated ActionType (06843766-358e-44b0-8d52-2b46ef98459a) + + + + + GPIO Button + The name of the DeviceClass (6aff228b-0410-4ef9-9593-51e8639aacea) + + + + + Pressed changed + The name of the autocreated EventType (57f1b7cc-26c8-434b-ba04-d3077dc886c8) + + + + + Pressed + The name of the ParamType of StateType (57f1b7cc-26c8-434b-ba04-d3077dc886c8) of DeviceClass GPIO Button + + + +