From 2a15a451d0735a65c4f2df2d16be7a89ba42795f Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Tue, 15 Aug 2023 11:24:22 -0500 Subject: [PATCH] improve router-mstp app usage (#470) * improve router-mstp app usage * add router-mstp app environment shell script --------- Co-authored-by: Steve Karg --- apps/router-mstp/main.c | 78 +++++++++++++++++++++++++---------- apps/router-mstp/readme.txt | 23 +++++++++-- apps/router-mstp/router-mstp | Bin 0 -> 96240 bytes bin/router-mstp.sh | 53 ++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 25 deletions(-) create mode 100755 apps/router-mstp/router-mstp create mode 100755 bin/router-mstp.sh diff --git a/apps/router-mstp/main.c b/apps/router-mstp/main.c index f161a7fd..8c018915 100644 --- a/apps/router-mstp/main.c +++ b/apps/router-mstp/main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "bacnet/bacdef.h" #include "bacnet/config.h" @@ -102,6 +103,29 @@ static uint8_t MSTP_Rx_Buffer[DLMSTP_MPDU_MAX]; static uint8_t Tx_Buffer[MAX(DLMSTP_MPDU_MAX, BIP_MPDU_MAX)]; /* main loop exit control */ static bool Exit_Requested; +/* debugging info */ +static bool Debug_Enabled; + +/** + * @brief print debug info if debug is enabled + * @param format - printf format string + * @param ... variable arguments + * @return number of bytes printed + */ +static int log_printf(const char *format, ...) +{ + int length = 0; + va_list ap; + + if (Debug_Enabled) { + va_start(ap, format); + length = vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); + } + + return length; +} /** * Search the router table to find a matching DNET entry @@ -289,7 +313,7 @@ static void dnet_cleanup(DNET *dnets) { DNET *dnet = dnets; while (dnet != NULL) { - debug_printf("DNET %u removed\n", (unsigned)dnet->net); + log_printf("DNET %u removed\n", (unsigned)dnet->net); dnet = dnet->next; free(dnets); dnets = dnet; @@ -313,7 +337,7 @@ static void datalink_get_broadcast_address(BACNET_ADDRESS *dest) } /** - * function to send a packet out the BACnet/IP and BACnet/IPv6 ports + * function to send a packet out the BACnet/IP and BACnet MSTP ports * * @param snet - network number of the directly connected port to send * @param dest - address to where packet is sent @@ -332,14 +356,14 @@ static int datalink_send_pdu(uint16_t snet, int bytes_sent = 0; if (snet == 0) { - debug_printf("BVLC & MS/TP Send to DNET %u\n", (unsigned)dest->net); + log_printf("BVLC & MS/TP Send to DNET %u\n", (unsigned)dest->net); bytes_sent = bip_send_pdu(dest, npdu_data, pdu, pdu_len); bytes_sent = dlmstp_send_pdu(dest, npdu_data, pdu, pdu_len); } else if (snet == BIP_Net) { - debug_printf("BVLC Send to DNET %u\n", (unsigned)dest->net); + log_printf("BVLC Send to DNET %u\n", (unsigned)dest->net); bytes_sent = bip_send_pdu(dest, npdu_data, pdu, pdu_len); } else if (snet == MSTP_Net) { - debug_printf("MS/TP Send to DNET %u\n", (unsigned)dest->net); + log_printf("MS/TP Send to DNET %u\n", (unsigned)dest->net); bytes_sent = dlmstp_send_pdu(dest, npdu_data, pdu, pdu_len); } @@ -376,7 +400,7 @@ static void send_i_am_router_to_network(uint16_t snet, uint16_t net) len = encode_unsigned16(&Tx_Buffer[pdu_len], net); pdu_len += len; } else { - debug_printf("I-Am-Router-To-Network "); + log_printf("I-Am-Router-To-Network "); /* Each router shall broadcast out each port an I-Am-Router-To-Network message containing the network numbers of each accessible network except the networks @@ -387,12 +411,12 @@ static void send_i_am_router_to_network(uint16_t snet, uint16_t net) port = Router_Table_Head; while (port != NULL) { if (port->net != snet) { - debug_printf("%u,", port->net); + log_printf("%u,", port->net); len = encode_unsigned16(&Tx_Buffer[pdu_len], port->net); pdu_len += len; dnet = port->dnets; while (dnet != NULL) { - debug_printf("%u,", dnet->net); + log_printf("%u,", dnet->net); len = encode_unsigned16(&Tx_Buffer[pdu_len], dnet->net); pdu_len += len; dnet = dnet->next; @@ -400,7 +424,7 @@ static void send_i_am_router_to_network(uint16_t snet, uint16_t net) } port = port->next; } - debug_printf("from %u\n", snet); + log_printf("from %u\n", snet); } datalink_send_pdu(snet, &dest, &npdu_data, &Tx_Buffer[0], pdu_len); } @@ -600,6 +624,8 @@ static void who_is_router_to_network_handler(uint16_t snet, uint16_t network = 0; uint16_t len = 0; + (void)src; + (void)npdu_data; if (npdu) { if (npdu_len >= 2) { len += decode_unsigned16(&npdu[len], &network); @@ -652,6 +678,8 @@ static void network_control_handler(uint16_t snet, uint16_t len = 0; const char *msg_name = NULL; + (void)src; + (void)npdu_data; msg_name = bactext_network_layer_msg_name(npdu_data->network_message_type); fprintf(stderr, "Received %s\n", msg_name); switch (npdu_data->network_message_type) { @@ -852,7 +880,7 @@ static void routed_apdu_handler(uint16_t snet, npdu_encode_pdu(&Tx_Buffer[0], &local_dest, &router_src, npdu); memmove(&Tx_Buffer[npdu_len], apdu, apdu_len); /* send to my other ports */ - debug_printf("Routing a BROADCAST from %u\n", (unsigned)snet); + log_printf("Routing a BROADCAST from %u\n", (unsigned)snet); port = Router_Table_Head; while (port != NULL) { if (port->net != snet) { @@ -866,7 +894,7 @@ static void routed_apdu_handler(uint16_t snet, port = dnet_find(dest->net, &remote_dest); if (port) { if (port->net == dest->net) { - debug_printf("Routing to Port %u\n", (unsigned)dest->net); + log_printf("Routing to Port %u\n", (unsigned)dest->net); /* Case 1: the router is directly connected to the network referred to by DNET. */ /* In the first case, DNET, DADR, and Hop @@ -885,7 +913,7 @@ static void routed_apdu_handler(uint16_t snet, datalink_send_pdu(port->net, &local_dest, npdu, &Tx_Buffer[0], npdu_len + apdu_len); } else { - debug_printf( + log_printf( "Routing to another Router %u\n", (unsigned)remote_dest.net); /* Case 2: the message must be relayed to another router for further transmission */ @@ -903,7 +931,7 @@ static void routed_apdu_handler(uint16_t snet, npdu_len + apdu_len); } } else if (dest->net) { - debug_printf("Routing to Unknown Route %u\n", (unsigned)dest->net); + log_printf("Routing to Unknown Route %u\n", (unsigned)dest->net); /* Case 3: a global broadcast is required. */ dest->mac_len = 0; npdu->hop_count--; @@ -915,7 +943,7 @@ static void routed_apdu_handler(uint16_t snet, port = Router_Table_Head; while (port != NULL) { if (port->net != snet) { - datalink_send_pdu(port->net, dest, npdu, &Tx_Buffer[0], + datalink_send_pdu(port->net, dest, npdu, &Tx_Buffer[0], npdu_len + apdu_len); } port = port->next; @@ -998,15 +1026,22 @@ static void my_routing_npdu_handler( } /** - * Initialize the BACnet/IPv6 and BACnet/IP data links + * Initialize the BACnet MSTP and BACnet/IP data links */ static void datalink_init(void) { char *pEnv = NULL; BACNET_ADDRESS my_address = { 0 }; + pEnv = getenv("BACNET_ROUTER_DEBUG"); + if (pEnv) { + bip_debug_enable(); + Debug_Enabled = true; + log_printf("Debug=enabled\n"); + } else { + fprintf(stderr, "Debug=disabled\n"); + } /* BACnet/IP Initialization */ - bip_debug_enable(); pEnv = getenv("BACNET_IP_PORT"); if (pEnv) { bip_set_port((uint16_t)strtol(pEnv, NULL, 0)); @@ -1138,7 +1173,6 @@ static void control_c_hooks(void) #ifndef FUZZING - /** * Main function of simple router demo. * @@ -1154,6 +1188,8 @@ int main(int argc, char *argv[]) time_t current_seconds = 0; uint32_t elapsed_seconds = 0; + (void)argc; + (void)argv; printf("BACnet Simple MS/TP to IP Router Demo\n"); printf("BACnet Stack Version %s\n", BACnet_Version); datalink_init(); @@ -1175,7 +1211,7 @@ int main(int argc, char *argv[]) bip_receive(&src, &BIP_Rx_Buffer[0], sizeof(BIP_Rx_Buffer), 5); /* process */ if (pdu_len) { - debug_printf("BACnet/IP Received packet\n"); + log_printf("BACnet/IP Received packet\n"); my_routing_npdu_handler(BIP_Net, &src, &BIP_Rx_Buffer[0], pdu_len); } /* returns 0 bytes on timeout */ @@ -1183,7 +1219,7 @@ int main(int argc, char *argv[]) dlmstp_receive(&src, &MSTP_Rx_Buffer[0], sizeof(MSTP_Rx_Buffer), 5); /* process */ if (pdu_len) { - debug_printf("BACnet MS/TP Received packet\n"); + log_printf("BACnet MS/TP Received packet\n"); my_routing_npdu_handler( MSTP_Net, &src, &MSTP_Rx_Buffer[0], pdu_len); } @@ -1202,6 +1238,4 @@ int main(int argc, char *argv[]) return 0; } - - -#endif // FUZZING +#endif diff --git a/apps/router-mstp/readme.txt b/apps/router-mstp/readme.txt index bff0cb8a..6a863101 100644 --- a/apps/router-mstp/readme.txt +++ b/apps/router-mstp/readme.txt @@ -2,8 +2,9 @@ BACnet Simple Router Demo ========================= The Simple Router demo connects one BACnet/IP and one BACnet MS/TP network. -It also includes a BBMD so that Foreign Device Registration can be used -to tunnel local command line demos to BACnet/IP and BACnet MS/TP networks. +The router demo also includes a BBMD so that Foreign Device Registration can +be used to tunnel local command line demos to BACnet/IP and BACnet MS/TP +networks. Configuration ============= @@ -31,4 +32,20 @@ set BACNET_IP_PORT=47808 set BACNET_IP_NET=1 set BACNET_MSTP_NET=2 -Note: NET number must be unique and 1..65534 (never 0 or 65535) \ No newline at end of file +Note: NET number must be unique and 1..65534 (never 0 or 65535) + +Example Usage +============= +Build the demo applications for BACnet/IP: +$ make +Build the simple router demo: +$ make router-mstp +Configure the router demo: +$ ./bin/router-mstp.sh enp0s3 /dev/ttyUSB0 +Run the router demo: +$ ./bin/router-mstp + +In another terminal, configure client apps for Foreign Device Registration: +$ ./bin/bvlc.sh 192.168.0.1 +$ ./bin/bacwi -1 +$ ./bin/bacepics 123 diff --git a/apps/router-mstp/router-mstp b/apps/router-mstp/router-mstp new file mode 100755 index 0000000000000000000000000000000000000000..d0574b9a37a5a715288948ae2a3ecf8ed383170a GIT binary patch literal 96240 zcmeFaePC48wKsewnIV%9asng}k&jUa1vJP|&;%KsAro?f2?P>83MzzThD4K@baEyE z0S%o5=gf3^y{*=d_Nn%^ecIaIO06b{Elvm|fMNrvs91@Ja>kKwg$TktzqQYqVTk75 z=f3az$NNXqGH36#*Is+=wbx#I?N1*qESa06(QvW9WbST`Vxe0Uh(%49)^HWa!sT&8 zISV&|8_x|vx)%RpcmuyRNl3(B?5kIzTr$3t@Aqo@!0%WUFZPXA zOeIeFbQCnu5B?17H~#&;Q;EmEiTPN0kE{3tzBMfhJoZh@N3toqo=V2|)@#3iqeT1( zzf=P%pCk@~Y#FEEZ^^y(o2kkx_KnGtc%*+j)%1a18`9`6_9a~UEBjQerm*2Gi+=0- z1QQy^#lEq83z1LdT*>&~{HoRC7OCY8CYLR00kN-Adyc!ku6FeuGj6Y|&aJC;de-Ky z&ATJ_ju}%MT~nvCdJ}!ZEt2f=@FkowZ__g(ax2cdst z5cqq8(79(2`0oaRzcUE^OM~G5d=R*K5IX-ch#W=@0yho<&mDyRZG+&i0o;H*1ONI4 z;eW|sa1i*e_NpBOf5IU6R{$T*jo}Q_kr98f@%Ar>-pC-={tz1BTL$2B7{97$xVnRD z5Nq7_%IcL>E@$=1#@aQ`$~vymRrQcvWD_2%FHrn0dN=IcaI1=5WtB$LxtOHq4byfobd^lZHPNi7ua)Q4`yGUfY z)wM{cS`DD>aVkuS)h>?+gsLXa(clpqK~SVRyBb8UUMT_`+nr4e$KiI>gMn%k$JM&3 z#JV_DCNr_N-d^2Y`K^kux_KJw?Dht()`6;4+t-RNXJx&et0Fd5q6o?hz7;tG+Gyuo z4R$B1py)yha9E92uB=*HxzbUK)~S8i&N-@_1KD83)!XaqT}^fpm(oZpS5ix_Y!oXY z$$Hj$iR~Q|cC))yv~x`kwWS?yyB+eSA}i69s2ZraMN$|Ox3ajRbR~pgUsKyC+T9hU z1$8c`y`pk;9pzb5?{ccetyECI6A|?475#I&JkDwd6`*P&fv3eq{Gf|8E`evJH)t;= z!>cK1ZPcKsqdO{E#adz1lx8sz+mnm!Hj z#_K3Og*&Fg6#V1_{AA=&=uv(*!ym$(R`H+u_n*P7)Ne(SvnpJ#&J$yL@&^^3GXVao z3ZFCpzEg$g4S>hxIRL&-#jhCvkMX~D0Q_SW-!}mMxe9-J0Q`&!mrd8Udn|r>0KE3N zq7R|l6?~e*r6?fwyE_4XeFD5U0d7cuzn1{dPk{F&z%2>zn14XiWtua_{$hRr!L2bM zzB$trK8Z&qq$C;=;4l^Ozex#jnybeCrX|4DsWVH;OMt6Wcm}s5z}Y-kB_t%kV>(1h zWeIQ?!1&*?1bA8;%5kd_;6oGOH3{(a1b9ONd{_c}Z2~+a0p5}T=M&(*1UT9B*x%y` z@Zm8azE3B>6aB>J6W}8g@PD5Gr?rIG-QLru*(VX8x!D} z3GkZ|;5i9!V*=ce0H2rupOgTnIbG~;S_1r*7!cpQ1h_h6vQ$d~d~yQ5kN}^O053~` z-vrHhWl82ImKye8SZ8AMHHtgWjMs*^C(VJ$?z5ypF?q)LWZAb@mUn7 zsblzY7N1UWnlgr4SbPe_X{s1*VDTF%PE*A2Di$9@ahe*2%UFB_#c4_ywy<~_#c9bS zJdMSZC{9zuuz|%dW*|;e!f+;wpQSiW1;ZSRe@=0l0)|gtrurYHxPjt*EdBw-X(|}* zW$^n!1IjvG@-uPE)q9fyE!DI8D{UnJn(6 zI8D*Q9E(3lahjTiPk+POpW-wn3-_`3a*ESbEZocDizrT0uyBaQ=TV%dUg0e)K8NBo z5z~VPjoTgOaRV+S+;x|>iy&we5bxw|xy~r#CXKqFqpf-F= zA$dF`fGj{C&&V+JA2O8tjOp^JOUMJOF;?DqFUz)`W$V_R9ESCE`B&)Wk&!}R<{?C5 zOrm>Ym8zo_OPE=WD51E%w`6Xo$8{gF)B0)h^6G`TtL_0Tq;8kGVB%C?rWNj>tM zGLCBvdD31d>m&aMv=xP%0Z?|-GInku?0LX`y#*M=DIY6IOC`1U%YL*3a%B;wfiNE( zi1`5+Cd_&T^P75Lp1%l8?q>?kj2KO7U$C`NK|Dr?`v~z{Bp*{rPFFDZ66UXgNtId& zSZj!Hy#=}k#zs#?+EcK%2)|5t>j@7v$tHnOhFKuykaW%CHC!as(W9$F0OFQT$wTJh zybs@@yAKf4c^h#53cHNVo}q$tlH$2&ArP)5!Z!{i{4vAIH z;pGDezYT*A!vBs>NpR+c(Hc%Zu!cZ0Hv;o@{Nvk02tWo`z6StP zRIb5?@0j@{jzodxn{^ylEbWALwt!>4!@Lo2=*~Qh5x}Zfu>KA#pxm#ZEK^W!0Sf5l zfZnS#;*>~`;E`=d5iXW?$>Cy-lXf{E+?!C&lM00o!5ZJOuS7a4NFSjz9;D=7Vfj1bH|mI*S;LB=MXvQ0iN4&^(d zrP3GjukPcx7W0dAoP=+s0j*p29~8l;Jk1nZaliFG>;2XTx*Yt3R#X7hIZ-U_e?X9q z3f^O<%PLBOy5$byXxKSBeazpWuF>p|QZ(F``~({VT?cwXP&a};`Tb%xhW~b?lTxKd z`}hehM7K-*f1!2BTKaw*u8Ygjd3MO<@#EMM#!UQhiXp!)?5co2scNB&y9 zI7V>gtqhI&Hi~Qz6{eIi+^^S#kV0tBSbp|@7F1wlU+h!QBI^+ z2v~9=uXUA~Ak+C&nCyaflna}_=tYGENipmAtgutUtd%0%}v0Uy5tx85!Bt2stNsoyG{;XAHaD~hGJ7fWB6&X+Hge}TaOZ18P|k==>`2oje zTX$07fo0IR!yb16m;Xi_pt8i}uVJINp;J?3cURNL{JVAF^3qpCr!dp%&oaJB?14>$ z(|r|sa7Y>o4jodBp12fxENt;VvN$H0bV$ZwyX#)P=S0MkP;?fG{vVMfNi9?C2l|7q zBnKLGhGc(><1Rt(x!y0N_;}MEn_sK9`E2~v-V;e-9p~*XM_``b(Y8mNy%^nJy3BW+ zDTk;8>7ccY4Ze;*f!-k%>iq?2zQVMvL#ZjUl6@6APKbsCZ~q9->Bt0!)U5X>`HIrE zvZhK;@|C2dDd~F8=`L^xwYExcLdV{LR-bdUMLm=GjwU_ixweYg^m!QYY|_UV!l2tQ zrO)6DrTmMzP^<-xyUZ?(HJ)459MwvWoB=u3AP0#e>_9H$$xqC4os#DmER$MFF#8T< zKw&J89=_-bQ;2$!b*X8O>A-f3Dx7tR;$p$Q5=w%iajXOvs|1eI)Dr1Jx6L?}bD(G6 z0efyU=5g|?n4p*rlt@=f&7PU5-MA6l7RWA*&432Eh;*Yr&;f~OEhMP6+r$SLzZ)a z1wpXH63qqqlVMb6SEi<`wC#j=E8redrF9B+6y{X{Rb3+NR~UAEj;1TpTN-#YC-NlU z@fFbjZ8g)pUS^GF82OINB)g;XLNXi!1h<5Ag2Y9Zk{K9sxl7<}Lmx!rcnEAfJdabP z4>vP?n8e9{fLKbTFtz)6l-Hev3J-%`K~!LSv?8f3fD%6tR5}>dbb_2cOWp+~ zCodt^h}483erbqlrnFC)24E6^kz&&qK1jG_mWCP;!_Nj|-nkd};WpzWzHRXka)$Pk z>gE+vY0{aJV6|~liS!Sc{SxV7snlna&X-8(MtLN09Y{B}g&rk0|1|CqfcYC%VJ;#; zX<9ZIr@)K(6#iVG#ApdFj5@p*FY}wvLJtEQjMJ=>cL`6!k33fzG-^m3@K@z1>;{IM z-!NJ;`&S|+?Z9|ea3&h{B2y~=*d0XBhJiYmU5|DYszz*{a3X?_5s-8i%{xinSUe-|{nqkX9JCg4Y& zMBv91_z?oXrhpfLmk|gzlSdIW|AWF0DdCSOyiy4h^Wkz9p2j`m^HM$S&8x<$8I*=JlW!1PUsbO%JBJaWfsen-kZvYh`c%RWp z0|$EJedHN^2o0wG3ZH2^(lH05cBGET+;p=!3Ro-4In0DGplAc3s<&G^JUJ+6&?a&T z8YDa(IM)1b{zusekdj$~OPRVir=uI(p=lly{sd}^oF$sQ4sSH-Nj;x*ns5CKK-LfV zj>G8A`${ys(X+_;(-Rio_G@rOcEc%sM7?zpO2ml5!~jb&kHb#|ccsL5hkP@t3zMtZ zbVz#B74W{B3JqX%0P%MeGg1q9G1?AhWcx|XSTP+jKYKqjaHqb6ZfT7rf!y2R%FGFl zod&DPx1ItI$iGqT2g8{0BZ)6Wk)?t9oCwwkY$VZc#cjP8bVz3{a4?FcZoZX{!Gpps zhc&-RPt2ng;Q5vWa}QsJyxLwu31DNI!bT0U`)$TKs4LZs4Ai}(t_82sPor*Q3dR5;f?|Kd)et*&G48n|9Ku6C0l3V+c~O z0QWAnEB{V0L-6*XiI(aytMi3CGmfkFu-YKS)flJ=LWW7QLo^BJI-}B-;A^2#L9E6py`j?~yYm&VoxK_Tb zpqfg)jOt;^o})eZW_P&ZvgP^yQ3kiza(R*FMTBDB$1=06JcWd@93HstWJn) zAYu=rUSMt62(D%eRhI?L5&33T%;GeS9IVl(rHB*aB^0JLjfhbn7Nh=IDY(qW&_~rC zX7yJXGlZ&L(OqEC3QLs4i8HO}4(JIg5QD1z(Ix|m1REmO1yS&SVtml-iVUUR-}V4h zF!JXWk{nxnK%5x@|^Ktn#l9JWO`HM6mImPO; zB=PMRa&`?&%qCH=vG4QP|$bizc{ALLuvKtw!(LRS|4wfYamn92T z2mBS;%#F-&U@XnB`j)0StkMEKyy~Sb7gL&2t=_kyVLSEl_PvnHSDH8SKicrQP<7h0 zN6?%k2QbxB2tvUcUW6@V-nf7Co^xksT<9k$(G;G2N`>C+QA{Deo8I|gPQkH23&j;;vYp#ISl-zTYXE2zxl-967a`A zb{`rAtZCk`<{#mIG#@e39zthaX~0#+K(3M^V+mn2Q;n#Y;;{D21$)Ikb1`g^#Nf|! zVh$?1EC0PmGBJUOcKI=7u)@%0M21*lTrxOSh3-Z*PFSUntoi?ZqyU)KXgA+ZxHN8g z`yXwZiWvtb-dtRDr8ri&21+P)pNvP&%T7+TqaD2y-a7g2|U?Rm73O|cD zjbJ%6Dv!o0f*@ga5XPM>hFpf8gW^Z0dfvuZLtg(_8UP>{>R52qWg{GHYEumK0Mh(T zkHKcF70#hhMUzH_7J8vJPRnP*v@Km3Nj|q~b{1ECL*4X!*aw@YPk;?cL7yHgEv9wC zNeN;k#_u6JILkl8m!izMvxfMxQeso?GmgMq%-W0e{<D~C6VS^HIt5uP($)HxwT zj6zTB(D!>B5)Ps zM#31!Ffyef(hg=@`t+&23_FRwThS{Oa$5c^P)DOE(OW6+&3yal&Z9ZfC?#iR>JAo6 zLWwGoWJV;OYcA!2OFf!Kzs^2`pztMth>*HNP;w(7GagGuOfRJNDwtX&v=vRSu(6N` zmY@ni!vZF&C8!zVIg+lSP1LT^)?Pzfr_zRoDzsMdJfT~pW)wJ>t&SZmc&VKpR~&ZBvXAgH8iaY3LY)G$^qm2|aSl$1~|m2|b- zA=i|fqLxdhxyyU}^j6qr&e9UKi1#+%$XXW>gLwB=LO^hu_&rky-%RuYO{i5FEg?){+u!Cd{<=0{ArCt6MZ(qu6oo6*0#`$(_%Iv6T zBDoD@Y+<%A%%W>({vj`db<|)P^RT!WW+pvSI{V61L>h*HNqBE!7OUXp@*RX|q}9#| zkqNVhh}zjHo?%2{L=SZaE|NwO9p4_3lF776GK_0ECXe1PGKnNQAbv^ZIRODS2nyt@ zodX0*J^AnQKa>%S?)B1G_AcQ`Z(v$E_kSZ4n^Th7Ny$tYVG=7sLoh9rP&8K_wLMG(FGq8L&O^-q^nZFq(v`x!fkE~J%WW+IA+pF z1znK#OJ}zeui+guyobC|L-QCW4(V%Q+bw|=9}scjAnboH|756(soVJG5iyj5eShFm z3N4fbcL=loPk?S+S}OHemtfW9ymfJ@w2zjlzJ!8dWlvEsCUr2?*`Mr7YPnH^IGiot z98Jq=4Mq0%`{pFItWHAsQH}gJ2tz8+^6eWnavJL2au+5S$SoD<{e?-sf^=~_{Ect4 z%`|*3^%o{@BfI4*80Ih3`U)~4x^2`>e8&#B$obu#>wOOv7&$ z-$u99;Di}&g+6elv|hLNWaYaSM)4+Jd5Vck;Ygl~-irj{Nr`Ve3!8Y;REAsgR57f!xYgB@yYMWDKL5QFx_ zUqotYRS359Q+SW_0$MmF0RKC{Y%>70Xp58jAwl<2JvzTmVwR%wVzRHqnB}W5j%=wm zW@+#&ER<$#`TBA73_|gKtWjG6YaI^g0{SLfkw&j1A59-9$_y;cn%v7qd|v(x zmMyR}C%?BTSt`ouQb)e1m?6K3l>DM}47wO*ynULhX~X0#NJGQNljJ@!kOy!Ugbx&D znGRfNPUm05QbIC0S=jHCzLvMgFy`8Tf}ZV34_LEa(nLd&H7jBg0uyY31?jfHO1&wX zzfRwD)Fy?nj4xe`_E;~RvGOk-EYTbgG#~hr=J>RuA|FbmaJ4zMDtTzEQ#!zdgcpYg+mSXe;tSIyp zG50}Qn%UI_6Y>iDevEH<4{OB{*i78CBMbJL7H2un=Ubv(=u%Pn9WXK*>%q_$+ogs3qdmf9d1ikK(`$qZ@*sL&^*c8pDeC#&hYkY#D}-t3x@b2IDh>*(d};X_74%8 zz5OZT+DM+aKSOM89_j5*6Pw%*d;5oq>%INy;)ck0vj#0Iu4_*5_VePXNQOCy;x2PC zeVkicCZfm|^WL#39M-lbat}tMIu5r$yS6Sv|LWT6M44S%>A+dnR-8z}?`HP9oBh&t z(XOo=80*@q$B^2!m0s5A+PW&0enU7LhSZPQ?+&8LVX+(g!%J6@{$NS#0H_3h_%c+C z>RY4Kca2hC$2IkRz`dI4TSfJ)R_a@&)OWQT>!?G;HB{f4SbgnEeXC>jtyJo}N~!Pv z*L8znP`9f!?AASeJ*2TIO48t4X}79*-KHo>j&G%_Z_T%Rqtp4;egK+>(c%;t?C>G{ zc%%0!E8^a$lW+Zsz#;r>iju(jRvZN4nul+SQd97)U*b3XE0#rGK=Aini(0GjXE6s5-DThl3)u_;Q;#EC^Z?@%vdf`4J910fCft7 zTX7@{o(W=LK;a+Zk7MCT4q^}k--^`_Di_VIgki^ebVol0UHpZK%^uxBL=oV^RCteW zC!%1S3zH++qk9EW^4`L4v*`aul=^IV7mGfHsE(rTEb2oPU6Bj_jz!lYifVCetG7q@ zAfkGTN-T8+q7VTW+1R67fG{mkMSjquD?peQC?fVA-JJ;2Bq#Fy9^I`7V@;lml=kQ* zAdHnoE@JJ`jYOCZl0|0r=u!}-jux5Rqq}rWfp_b~>(Hwrqk42QK-BLdX+63R5vI-u zOH2!y#nM+eX~TDXPL8B}*FieZv6Ci1sU?BNRajH=tdPSvEnqqzb#Ar%g5xfn!O^<% zcQLY=p8+YhV{=k=BO`{=N5@(NvyHMA$ynLg^bDnUWAoszNRA8*nAaeOJc{8S_N<6J zNV`;Z@CUA?{uPX!HL!gP`lU*K*;Os5mY*W=uzfKzxW(>69}4~Ms#?^l z=9L6r;jSZ&FUW4}ilMgH%fBH13E}@qP1~qRt=laqFtMuE3s(lzl_AFKx)>a{h1OaE zf2aJYrs95#nC~_5LFoP9dZNQV*Ni z0{gCB^pkNv01AqlKMLYLA{UYTgV}xA6vJ>lo`&NCKqP;5EJmi_%$-Q1eZghQx#Zsp z(xF$Wt8XU*bq*SHJt#^?hHXJ@;L{uBWYBCew;~%1-m^do)EPx@iLqwdIeyAMep2T- zemGWT&+!lFR-wZ3xqn2X=lDzpx~&&DJK*&Gto(CK?~t(t8IkSJ z$i|L9SV#f^b1lH~ZKY;*R%+&yLTL{G4WZ8x4 zBBN)2WRzbw1xZ&zIBFU+A6kH{V@6?C`wDjKkI276UYmd7Bw$c957`P^kMV88;X$fL zyJ)SA2}F=SlYh653BG?MNdv1!LSWc23g=&V1Y7m})~(#$XYUdwpBA1ezR({H)%LRZ z(}JcGJ59pmLv&tta=&0E@FQbYbi$2ePG*=I?3`j3VDj$T-EuNjl(M~UnZt9!Gr|S5 zB>ptJc>(7dcjk1Jp=KMYX77Q2gnxi=w{8)BIoXa@gsRL(1czOU6okh~fhjB?OCOXw*gTS;HG0oaA@T#K(+6ZuSS%U^*44#z&s zcpXV(#StL<<9{a+p%T?-jfle$xIe=IS?ZdzQ3FplFnkO{wo$t7HFiQi;KBOVL8Kic zwu-zMbL@^gBnO5ZkooI>ftmzr`;Or|Dj%)a$6V(ElkML|A%nIW0GncY-s5 zC4e5HY6i^>nFzmgis=Yez|7Ah4Saqdc_J$iFQfEcq+^AtK)_MyWi5H=(Cf?ic0prZ zh}|tLiwa5J9az~uU|m=e6twbQEow_g@x)({zkCF?KfPGA?4Q0}yI{#V?4jelImL#lB8c=;~xcaev z+u_M5f&8!%b_017zrZS>8*Rj z9N;Wda0-AUZ`gxl8m+LiIFT?UspY61c;6FoBH1=X7tzrt+2-3|Tv!~uUrW237SkSD zt;;A5E(Mb~JaYtm%m9OB8aYehWDW-(FfjA%`;3#}D22_F7&9e0t+dyB^fZ>WR<~R% z6RpjB%SD4YtL5S}F)Mr#>eq5{m6+dhu|b>>CWq2rk*sO?SP%Rvajf5#tVMCvI15yj zX9J&8BV!4HQjwMvIf`EmFsf!z>J)HMr*N_3-yn|)P6pT!g;H=$Hrve<*pmnzPQcYR0^gb5c3bB_A z{b?^0NPjv!%Y?wjGHBKT`7yLRQ=wj*=!6Q@oq*N)ek6(1W9Qmf*JP(|Ev?wbwD`=f z;uNk6k+mcIy446<@_O6^UlxO3k4P~heqA9;?r%(`HIOiPi*|*_pTW7(6pdeZGZN9i z;R9jOy$I(oXc4I^wjz!}ybjyaupmD}K6cEPBDIJp)^G_V0<-O4+%Ezx`F^Mmi)ksg z0I^qz__i-})c7+qP(x_r@pL5KiE6T=cIKyXHK$v*pDyU&e$q$ug+JKCoa7sok_;#b zhWO8zV8aPoiZsPT+6P`(d0EIMABl4|S>fzWnuZx@3}0~)r3K9OAOMQYMVtj3IUS_r zJFxPJ1<&5QR3`_V8o?s2A^fw57}m90VSjsc?;s}Q%#rRq0*HUb;_~lzvFu^;%7SJ; zWs!7$rB6^7B2P-v{U>2A!Mu}i&;ARg1k6X@rMjS~o*#pcRxGq3?I|U#JC^o0N~=-Q z9#+y`h^1|%v=XF&*pmRtTM)*{2Uw%*_nDs-AepwdNF)_5;tLkOq7F-9zoZl@JCz8zPxSY`XEIf0?>tCUtx-OH~<=LmoXjJV~RNxb761a6}D!?KuLV73Fx4K|Ic2`w{3#Jda##+YOezZw&jmR zd%gWD`NxuptU_iAO{t|LpoGaZV0qDAuyZBEw|)fI2Ek~^S1>%hpS(=Ufl}UJ39OW; zXGBi{=8?2hm(`O@ZbD=jD_$I;>;N+^FB5Gnn!>P(Uuka3W!(83Sw>M_-?dwzJm#|ob8h~?O0o90v7T$0j^?tavWiZB~YHjcNApg?`XtD zp~f_(E4^57gv`^Fv`I+Arck*7T>I}$^`$38Zj9&h+z`+8teT6dSURay2=}ZaH7ag2 zl)uAM634Df#2&_)<0R}KgqY?qZ$0hFBKwex%6N3t9M^ewXGWmCSKBi}OJ#}_;{A~1 z(#N_Y>xU7whhn0T9Y{vA<368xNiWC2X%0I>(I~rO74uffi(Y68xU@Ldb1TkA&4ZC! zgR@~lx8|7(SFG5A)>x%?DM5h%4LZAEUNjW#v`TM3bKz_35@Bb6e{2I*cdgPPn6LvteBxX& zwAP<9boCNTRyfD-9a^Zn50 zGSIg9S0}L`#xRTj!DI|!a#k28?h8iJs4x=836jO3_|6t-C z`-vH|u}Cyq%eQ?6aYx7s$oIj$jS-^z6aJ+m{YAxjI~sZH8d9U6LBn5xf~s3OD#4TQ zUrKtIx5IP0&9?^1zJS^i?Fj9@l{vri*YNOq3T^`hswcUr;Xi{+pupzspVn+w>%_>3 zusKs~d3|CIDGe~Ffap6Pf)2zXt5n6t4 z<2^QCRjhiqD&?xvnj`X9lr~UC;4|LR*cIcVyW$4sp%ZDrCl#{If4~q072NzBP|(Eq z#l{so?Zs>t(_ryI|I$oFzvlakM$As~6v3Fq>TWurm^^=x1?I53XgJK%0(ADJQ{+}m zP8eUeq74*=Vj4(F5lK-?RQh%J6~Gh;LDbE-NDuE#tL!CSqb|cpFI9bvZ1k7ItD+JA zHWK(XEjoqir+gWAZsN+LWhECO3v^MO^j~N}_tk6>8l}mW;;MyWOV#4zy+2Y#<_I%2 zGDpM7hlcGT{eAKn4Ck$J*_&x$plODxD6qBEP1!YDLM~@TvQ|)Jg3=(RA_g&?fYr3+ z%c3E$UMsIhQ^l#GL!ur11-GK-qGrqK)MEV5n3|mpI$HQ7Y#fT*$KrbN5o*z7aUo7z z7Wj)W#E7%YNo<#7?RV6s2MY&S2aGu|N^SD5@;a4Kzkm_23n6CuY5XbDV>nolQ4%OJ zsLEjpuQ`VmX`Fzd9q6YalpZol9GImKGSm1?eiqJe6UUbk=q^fy7e;G(_{HR?8*_eA zxbC76_%{;&vOs`2Yl(w1%YP|Gh`3>pQwa1FF@=OI*fc^NAG-@I&@ZO3;1Ku8F!Gxr z?x2~Tj|xw~nj8aK6kz!d0Mi%{k5v4ig)oOT;j<0@DA!LqfuIM1>57GK@5aCL!P#v{ zid`LWJ)HaKG!flOzm?#|D&rn9EKQfFshO6SKzOnXf`aIW^~6*kZ7!%6Qh z(*@}?=o})5^saQs`x%dksMd5^dbjg4z3Fst#ygA{#gC?RewOaobhIVKblTK!>ct_K zewzOs!uo!voY{FQhi`w=gwrcu<0@hZ)B3F~jP0Qo%=|}frRlgXdJh)Hu@1eBo`YiU z0X@+mU1m2y*=+_oT1Z98Hsp}HXnT@6G_41wTiLm@ZLo!$)Ps9l%yLl%vN!U%m$BF= z?ZTE?I)-p5A|HJPTDBf|YCduTq$A2e*3FQ2#*jaeUm@iAXrc{Z5vvm3Jy^9kboS4f zy-9E3r0KTnkXyL$t}QrMSqPH7Ac5tZZCEe@S-G_x{8H(u*nNq}cF;?lLDL!K%jMF+ z&6jAwJ#aTx3DV`~LBd8?9q5W$z`P$VCrF(To%ARzjX>M67)FEw=2s{Us}%52_X0v! zmtUpb*!V@FO<&{~uvln*?QZe{X?^b8ANjTu5Ed@rlgM5tM&%P=lUB7dRZ&5&icy$6 zli*v&0%Z)RNrq6F{tH;s$dto>g{y@Ng1Fg3ui~5naICDQ>Z7`}oRUM#VF4P1!at)@ zI*_B#bWD&U*6o~u{NA48s-3uaNhCfJChq_h`Rq%y9M6TXgBJ78%_J|WON93_bAdwlMJlQh*pae; zhx1c8kUg0h*xHtjnMvpVD9&gxmlGYn?T>)BnD1Z_cH}is$azD_ z-o9_xq1;_K>&rj-LbwoAS~g}~@!;-%0j|Ao9803s+k#EUtllfhkGzNl(-a&EN^bfs zj{RgXQULeQz@*{D#rcg2w(0YH_bAG(LdgixpQ!l3xeZFfAf^ z?}9{ML!f1SIyR;Mf)Jlskj_umy^EE~@ULi{30?1*E%Xuv9(MQ(;+u9-KR_{m1xmvB z)vfyr0GcjGXAiErm?_eQ7n=Tn@8&)lKg5Xv-BXBlrwoa$2uoNI4(K)ms4NWQ8jy~m zW(Rb2fJ!N#u!d1Uk`~8dhz=6(jU~=YOpIOGn&dVAp%Z%IA2tEWbl^I3-L2S)m;epj zhXg45QpiX?gL*-h+W?Z^LEQqnMg$`(1K3IXN;*h~vNMxl8u5YhWbqwE+Rc5fduU%| zgoy2=y~V)>EgT4Xs)ycmFc47@LNB31_yO}oP{aBk>(*9woJ9U570GT$vDXobC79IR zcp{B#Cq0$GUP;42huw&K&7XwuAzL$sDlv^7KeHLffUPXDHB6&)CBiuX6$6NHRt16@(8hX4qqB!W$O7Ek67d(vieFF1hTmH;qFvEAe z!OlKip%d(SPl|lw7>HIUFUO~(>NK7hd8F1h`CNMu*A?#0qO+jv08LBNvNaqLu|`y<^I@B0(z zs-qhXaWW4nlaSX=!W|B5i&uSx=TUG&pyNNuLR`S!(msUR4zHyfg<0%IA&y^P<)f>7 zTed`+OQSS)NJZQ|slh5ahABN165}oAZTR9`#hnnDq;udS7NV18qn^r6&E>T;K*%qn zAQHR$8khvamwzYO%shuwX6)pj0s-(30hcdO7^S6eyPg$)L_Q1KhEmgU7VnM}4lG0? zqo`y_cM5TY(l7L;>OMiZ#rz(AIdM_I{5Asey-InlN_kJl%ex6>@EzG(frDc0NM^?Q zaUg6yi#2~N+;a*`#l%uIg}v-r4wD588^)+hc+-M;JZR=cRNDQ21e$atf{Q|!E7Nm( zuY&V{t`v!w-cCYM7ym{z&%TKY4$d^AJozbw$3CRUmk^H3a0If)6N2=K1E=Na6}=Hy)~2{;~% zz%aK5Joo5sLY(9pFkcr>d6A{))Rbk+oZo;QAWhTtn2DXi75pUM(r9 z(d9Tvj=Nol$@Jd}+~lT-E%$8l80dzxjxMbwy+-WedKZq`z?TFKxdoYNQ=Ib5L>^t! z?ND-DIWiq!3y#d*%8!6MS_B`(-q^ux?M^C_OfkC%s%-Lu!WhP3)@#%Ss8kg5t~?I7 zw1uh^gOlXA=R%uCrjTL3ILdSY?^unpCda}>`%EsmjE4_ZNbv>&4-nS13CtDc<5$E;duWpWrhYg;r-KFY%-;PrN*ZNyGe z8clJpcjTXLq|5Q>@R6aDPh%7%xF@-rloX}EIVem24GVF<7-bd(zpr)VpKHe6*kNfO z9xs5PrT4dCtr^dJd?SyB!jhQTYYsPt71kw~^ssSJEyki2gN-pNhHM!XvjyuRRLl)@$$YHoJQb7e$p5M-16KgFPCVtp`uaxwX)J zt?cenm6$2UHFwML)E&KB6|6~vT$=C4{O8kRdQ}OBgrswLYYYP2Mt!MJ+J*O7A~P3aY3bV)bPWA?8mMnxe~XQh$Pb zTTVrhA<#8ty+$U283GbUE~sB)2tq)GIWY8!ish3mt;pxQc!gUR0&`?^L_7J8m}|fhKgYW-V{)>?)SNE|$)f!rI+h=pSB)_ZY?% z2iM_>+($A-6uJd8%-W3yc&$BF>h!6lf#S?aZy^j4ZX)3*`PcCDtkQwl*JJDbq+F}eFyLNeIs6Il#lGgDR_~7S6iMywE-bJXW|N0DoxN=0i8&cRho$(r_84H(p@BE#WNW;WyceG`Ntj%Vt9 zVSifskOUq70vF^UINS;fDWX$MZm4yKI7|pG(F@-0q%aAArAHStn|!_;B3@|NA-yBc z_T$DO&TKuZ^A&yLpR4f|UG~q#Q-D|ebCZ2V7`&Ub@(gTHbthwnQh+g^REgi;@$& zG+qgaiX*<&qhXq73vSvi(b7l<{IBo=j0M)WS5=nZYqQ(@niO&&rk=>G~Q7vHt8gM z^DFS6ZIjRAAu?j^P85v?I)p%dX5?+@J?IEyL3wfZ|GI)d|8FYzJ1FPC3aUppsd@|L z2f_41AsETi?qN!$OovfZ&s4~37Wkh05lOr0X1t;Xu4xXSIWFI)h)vsF$Z0T9MHNt4 zoCF>M07qj+7Ziw=d%x9G71UG~~8*6ac#4VUf-_^<+eTfwwkrPbTkW?0L8~pHx-L}f z`gUA1<>OE(npv>AVzCJtiOB&yO7rsHSY>5R7lBY)_Q>Qf73cvCJA6yET}-pN%gnQ5 zE1fiNPNVnM(lBqvD#mZvDM&nu!|sQ&x0}7E$$iC|AFj70<2)I>;wwN1ns2Hn?>+qd z^Ek}bVwMH+|Ffn2cvtBxdq>xt4utR~C3z1eOJ}j4AYCDs-#m;Gt0@sYy?Rtff_<0# z&g~S&?7p8qn8~6jym>?Host*AxmH-C?NAe##Vn2x>C_aC6@Lv(IIlIK%#jD{g0I>U%=FX9&!wclc`wjVV;s-qVsAJ)bb#1tH_-c3z}Ee zvANYyoLNKZL|*ZhAcRkF#)}ibM@PbG>Ly*`JJxFH+$!ImxfDBN0_>c50rDekLBEx& zo&ym`w~MWG(9H7+xp7#kfGwhv(Tq{lLXT<@=i}LW*ow5X`-EGNw{zpwtr9q(YeZ zq%#{-@9@%VR}LZQ!2o((Hlv5ICsB{fl?dXb_q}*khf)?P(b+BLgL6@=$3Rz=agv+T z+Q1IImWpT0AHsZVKdcMhUkc9r6EG=#l#+L!;N67-kGen3fbX5Zi*H+pZUZS(^{@J* z@Q-NiIWDeZJdS{eX#ZbG>rY>hw8j$KP@P>^uO}T)q?HQj0BMy3C#Hf!xr-)yF=<&_ zW*a%tPPK&Uv?yYt;4EmCDkh53GkAzXOn)j&6ceRA06s{;gXZNALQF5fC1zr3116=P zLh~T+zGCPM#MFv?g5vz0p4RUY5#MnEbSiJbB4x@sTCHbY&no>xT}o5dHr|FQRn!X} z7Z&JnW|>u8QL*t%|FF0nRpN?=0zFoF zXO50tAN!m#gGZbkdtgmX=4-IL|B;J$ne2r|v=PV0mgQ z2*t|B2>cIXd1{=Ei#5cuJQSoO_aNI8VqAxuu`EERT=L3zEswD*5xk#b{t`j?MT}c; z{vsL7xSS*cl_*nf$ONYvlM`vTYS&2P-z}Cdu&EyH<-p9Wr8X;}J6HG6Vyp#Mo|uhW z#Eb#XfZqcEn1RtPG0uTlq;A5SLw=jhXj49Oq4$s~E#d0rmtj{iu+cgy9u8eH~`rR7RG|5z$eU|Tfk-ehS?aE#|A_TVeAhUw@z zS}fZS($rqbL=Pv{Ef9wm;&4baZv?gQXJo9I{@0_W!cz5B3y2`o6h&+(8=`pl;J z3hSfR=uR9{w;A2+cO8CPjV<62D?+Wt%@m-my7nI#g9szgYWxubaxyW3)y42yvZG9} ze{ul65S|1v0hPe{mk`}hJWAr-i9WQ8^mfoc)_ayl;I3k%%g4x3?9MDs87%q(R2m!HG%0tlYj-C#7xmp+4O zz=+)&EFhUE{Syu?Auz zN1fDpF69OzFQ8ab=NUkwtaBCI6E{H3USUk~ZS=Gg)3Rw?_#`w=LAja8y}@Lgy&dQ= z4SgveS!*z?kRvjh4qgOj{t_^%wiVS1?};g`g$q9yCl^NZs7l)eqW_iBz75oCmDUUh zl=jfil-5dA+7&2afYL4ibE?vsDK)ONWl&ZgZ$3Q;VJ0XoAPvw`o3W`3dRb!J$Q0FP z+#oxsK<`dNE?gJlk2l@n)F4M;sn7w#pwBkBEX@GDHr>Uv=wu_j+Fu9gtzZczA zp)nmaFw2q~K!#p&VTSc%k|zwAjf8rWX-_=iF<>P`e+SWpYe0+9UB!j(Cb~iMo+?IO zz8>h*5ba;GQFu6#_903B1o1GvM?j3D+e6Lhjc`0)i{YHQleh}pk&gMnJkv2`-GHny zRSf?Xy-2A+CsF(hIHr$`QWsPTLiAGotrte+F znr<2+i)d3MXnuy#YTV68xQ}C*nlYfFzJ1-}T*F#hjV36qrOKdY+qgfvc-Y$)h|4+~7U`wCiFaWPB zu{axe3uOQ5*XZQu!%0ul|4fBpUcUjnxIg%yU09)sIn?`pDFr*Q>!_DW~1 zbB)2%Fm>wGG_Jm~);YC`o3o^(z;LsnwEXspGDErDS#1zq1~qevn`%wu-U6z)l`_HvbN4%eV4&j+gMfUuC`a-kj5>t zSJ`X9lVM_G8s~7i4Jv`gSs+p4;chb|LT3R)c`6%S&RK>9VvXHxD0I7BZqy+Ljd9>{ zy6u%!HI=LD?B9`E+h|zrXx`spor7^I}WvFvG z*CbFVw^w=Gwc@&Ou~h7As;sN6HdIzuyOG^cXLqgPxMSRT+<>@=U@CX8Xfyw zG&<`yxT2?iDeT003w>k%P9d!y|1^N7;om6yyAl7U;@=!=0VHWCudQ#Wv#Tlv?u*L| zDw8%SBWIe5|8X%~v9jtR!xFo@vDW2e3V{UhxN^~g#TA8%R@w^ZEH2_~_SK#>X1kLb z7OJd7t7{w8xSFN7Y-QPkMHNJvC=}1N78J%JrPgIDi|5Z>uyXDqYiVJ5BDfS%FI*Id zlvk9koMT;Vy9Q8dEx0Cr4Q-T*@~%l&Smt&$ zxNGfVrF)%WNoAeK&c&2hWzSGjxemQf?FO9M4qUCXR;;ZQso`R6!8u({JLjmZw&#kj z+$vX{%Y8LgC35b{`UaMQaHD8%$n`YjR>i{A=!$C0)ey@T%MwFZzJ#iTT(Pgi!8KR9 zo$M#qrN(mI_PSc<4?MMvHC%0Vox&O;2~I^$bl2ABR#u6yMjVjrB1-ktiMb7Kdv0Z2 zrMq5@D`DgSy~^r!oQP`J-B`J46jeMWs8C{IMu@9%)m3{MM6TLHMnKJ{W~p55bh+y* z>o|M8-Mz-{tXh}b;A#fhYI_~zUCphobD{OCIeaSX)J(v$yW=rdQlkgFG}Sh`-0Qfd zHLl#^#&6qZ?z>Gkzy&T(U3Kmp`*-A7WPi|JCFZKlPR*w31G8JO{c~VV69#}7*xCf6 zPhB%Ht(YlGUG2k4Nw9jk6@&v_BQ5%NLaw#yA+8VtE^s-Wx%0*5hd5hfRYI(B9WL`!jYG-^Y=-6?WV#X3|5y2?2`P8I-CqkRpf+N*O{!#Aj=*+Eip%XRM zzzm>zEP{L(ZyG!zkf~p=CSrpK2ZpMkpt*J$Sh;%Y1C3&(Xjh7c^qh{`H6Ep&DpHlJ zzTV@ktzvZtUTqz8oU6CjuLd8A_Sd`6wk}jY*R`6dk^)ArYiJ<7CSwrG$a>+mwA|43 z=G^LTsi*b}|pjQh)$PMOEjql>t)0pe1t6bBVz?Gs@wRP}^5}+6xs@%}sT%}G| z>5H{6d>l-*Y6oj-*VGu4n%23R)et&FE(~w2L)A2{)a9(MT*p;-?2YtYYRAaOLKQV0 zHw(;l*HTJ(rRZ_90Qv^vmCkhrd<`y#q1kSKh(oy1;PjBbVstd+-Z=o0mus3a0A!k( zJKZz@Hhp^T^t^$v{M_%Epx=$6;Z6f92Zf3?a6r)|U}%UH;(>Tc0MDy*dN2rcbM33$ zEKpkMuBzdz(9t@s6jhk#!RR{A1N&n2tnoC8T)DjgHV`%77F3BY`p$<1%OVyPy5b%=+WT>_`)mGVa z$yT7il?x3~`tr5KJ1~2|0L^SuwcS|@j%uCgsSQ9T zeQs3U@7y|cx4K4_2*pR2b)pt_)#QVEE!3Edf34z{=T^GimFr+tE zKw>iqiH0T&Xz0L5Y9bjnl4stSTNxYFIkoZNrPvu?)MCg214RlGZ(6hfaps2O!kngD z`&zV1<2Bnhv5eIq4t6T7 z4I7T}_*!L(>(8}nM;0unK0NF%h7O z6rgxFi;a)05t*61)>2<>h`2PX>RgQwcS6elY46?R>#EB9|J|fOK@3GuE218pf<;J3 zFO&+RO`D_%^b(ttJ9B!HoHU0fIWgy?Z3=3&SZ~}^L`E5ZsK_vm_Mjs{DwMt!MQ67mvHSuK~_aX98s&Kqh>zPm{G#1@B9#E6F!Ql3`WNPMzj!c=F*%9I&>RoWwshoqHR z?LY9XM`_3v{3&ZAJ~J~9_a2PSNn(f>C5}YV?#i<>*oAadG1z9WM+#F?inEnsJElAG zTiQ)&Y_1(9nObT`>_~ZrI;;v4+QZ0AdWCe#;uOTnmFhcP5To#snK^5~)^bBhrbB{q zQk|)%#+556(0)!XW~aH7t}7XyOco~SNhYa}@Kkw}Fsq@PVR&TIUs?+(t*BTz#ldkp zVy#C=Vij@N$ECmU!GxN@Q1dXxS|Cr3ODr(>v(hP4#h#H7t4xbTeycu7h!xC7h~|_y zWt0!i^E#F$ZauHr(&5o+Fqqn()ZNRNL`FZ1c~Bd)O?weB#;!nb}&rSY#*Ls2swfq8Nx#9&99)Lx=B5 zuHOpTB{Pha=?t?X4f!h3Z;mk>D5+s`1@uJ53TM(12UJTq)_ap%-)#khXKtAkT79@0 z9XzB-)%7rLFk2MEu`x(lQ0+`;tvVqd4ey#5iQSxbuTMi$=6gQJIL-^I736qvIjUwy zCIBjw)hL5-w>9c2#)+=CY>z8j+pzci~bC9Z5z zhPx&UBhh%Z%B)?&h|e=k=UP<1*FxzgW~X<|kY2lo#ms>uQzx?wC%=2>{_5MlHx_+N zEL)0IG_fA7%uQ7bdqPP_y5a~{!KMWDkwUj^C1(EMD^5%E&kld4vCx1czo%o2t%~Ct_=yaHu;N3{{*R za}vb^n=UdoOxT$)m@b#-*jW_XRji~!sFZ4%*|K@ERE;$!bf@Cjr6T!r!i*;4)8tVa zFKrnb!wNfCiNeH9ml-UkV~&ZVmKfwjq|SIqui5UknGzXX_H-qrVrs=!Cn~t*YClF8 z>)6~v(Q_<;*1NSg5A>ML^)?kdo1xjW_e|?7VJd#z(^J7sV$&y>O%2B@Rt!rYTGWF?WVfMCyc9hb^L! zW(ZQ4xvBz~teMtSDLa(oI#l}jRwNNM;2Q8bl}4Ziw%5oLo)Cg zv^iz%7;~G;ESSa9ErWH-iOh{BT^)UMRVn!GqhT*WpU`B|Q zu}VlcZZ~5yO{r-az0NoWfq{jUn9P_VoAxXrR8xGPDpmm}DgRmg&xW`GPGScn=+p?4 zkfqrQqdCzryr?;PnkLv-VVu>3@gkG@bHxJsrSrnl4;Ob5n`qRusEgHsCttFr#YJ-K zlx%jGDO7D!BYNoy!a6*IPkiegg$c$qjJGQBWt!2-%xbqWPP*!t*vG|8BZsZmRJ|0YVs$ zO?>sL_-c7)FrcP_;Vz}8kr<}DWJeoXXdBX|HCNt<8GJIM9m+qI$NGSs#fe>|DQ)uO zm_LkaS*es>Vx!Gus`y|Bv>m%CZ4&HHW-1|(k0-WQqhV_0N}l1C0OulZ?1~Rdo0+G= zs#7T?turlVx2+7!JeXk&re}V*SjkjA=0}x2CY8Cg6}GfVlT4SoW@nz9hQbIcS!Rkh zEV)X3YI3pyEiYO&RzoCBp60!kWU^f}L-S)-f~8U)YA)`C8ge%;ydl0f7q8KV$n}9N z>tfNhi_yY}>q!%qK;v{rOa`)Y<$aG>MYO_nxWdxE$iZ5RSxR?}=`zSj_+S3^QE)LpgC1S2?1`AI`g|t^nvL55sLXR4cKfo z9CXGqmMZd4b@erw&VSNWG=nO&z6e-0oMFAoO3sZz+~71z4ZTyWW>&{23pvd#6nryBNMMpt{SnJH(^V1-N>xj2c)nP_5g-b)A~tQa07ojXo{_iiKKK$BbxMU zYPW`qBdo{a6nkTbT|8n-nES@)1A{afMhM>gP7~`&@AX$eBd5oU6QU0@I8)5{539$m zzC<+L=YG4Cep=mmjJjz}^fPYW9${2@v^w2v#BECIL)68`HEy&;E#{+5dFyp)UZf;g zgFFLL0?hYLk|&m&%|;kzEnf0!_o+IvHj0O;1C3Otnc|63-AWpsEVE>fRH;^cF>&7G zB2fLqn6s3^ZVgs>En?iDgL#%F@eFK|Fc#xyE3%cRK}20x)^miZafl+ArjO0ku6lB% z^(h4u$u3Qn;APX8uJKc!_+QI!wi4V`oacY-Ef$sY)Wv$9x>X(ptRM&ERglfL->b z8DHdKOV*TZR}ZkROcYu7)(xFf&n4O4F;SRi9?Lh3+9HZh82R=rTPn5Pv60=FAQoS2 zp-!fGN10ymZKaxRyaJYHWaFRLy{@Nd#Ie%Mq}E`(<`s66nG)GjootR_Kr5xd@V7k1 zb(P^KZ7VLDd5D(`lRvXk^(-CADj&1E@jff23S`e23l2KxrmG(m-VWB%rtw;2i;=J} zZwu-RI-;h8m3xLi;;qRg8xtyC(%2M}I5uXr83Sx+5Y3P8 z{gGPWNpzM+CT#c4B#S#?hnlRN=z@zZ`)WPfVv!V-%okERbTN$V6IdG?4x#OmEV13h z_Ra)Ew@+mja=d*e^3^k+zm!`_%In$`k`Zv&{lI)X?Up&Ecw2^Uib`%}6Ok->O2eRP zbrV)9Z9vjrx0@vq4!xDSRdW{r&71_wBrA3(t(Z+wPcUJ&5+V92JEcXvZ8uFElv+s? zOBr^p#o=Klw^>*)i%c2vYKiVYP}9KLd}&%22hy9lbNcFNI+N|Vp7yijO<`AW9?gQWH~qr zD-vuTVqSu-QTlh;N<@;=8;!&a%@Ez^Gjy+^HWF!TZZM?`$lK(!Sc$N;L@(WBH#7qc ziUrfawMAPRL-Vz}v~^>@5^0m&`6wo<^f(N%$PgzcR-oAO%C4IkCP&%xgBqq~Nrkd{ zpaz5WSKe=s?C8~QMtUsevMr`suA=uQ#QR!O#r~R5y1u*~=Oiq*d*Rn*OrM~I6k90G zVhUILDJiwQyB;-e{i?93MK_%Lx{eCKYDo8;+VCwslFUk03&TvAlZ&utg(WMNePm;U z*a+G0Dpf99zO4}C9W%CKYRiqiA>SfSN0ltKhjnLZFKTZpJd)(IXvEgkok;hL?B)HE zRQD6_g7%F`np-pZ?kBNxF|1cosoJ+{BVcuo!Q%u<-7XuHWqTV=o@~IyCsnx7H!u_- zELw+NQF82hV|5#a1{52M@c4H62xSFv%|b7ReSxF{P&f*m!?-7{6C^;<3qE=Xxg z40_zXdLPZ?vFx*#Qi}D*H&BJWis9B%DV-qRH_IQh6H=qnV<`|;LVPojKHqe!K9z>4 zt&yGTo_MQu^qS2tAtmCQShEk-Db^EdHfDXL70Z4v>o4W0(p!3q7nOq5OdpH>BjYn< z*xvMrA0zMb$lkF?%%BQrV*{qidS|)OEB4*Yj>ulG_=N@S0br!*%eFCg ze#sUuwf2=LjVmLqOw|V`&o(5pZ3}P6nlk(JZJR}VB?%YXzzz$Tq-D|36q#JsJ*S9B z@#!Tm5n0cg1W-h=Z%cw=!CY%ElM3bq6uJZ(WN4rP;q8HT(*&(>-SLi%gIljD zR<<3S?8G^oEeJ-W?Pe-2b&Dr>f8{+gT%hgix$e4-8NVXZ#-g> zBId8y?^dCDqoj1iD5~S1f?Py`Fp7+evqDR37wfF6S2Sy}{n9H?V62U*H&mewFr3BY{C{j@wa50E~Au&9P&z*?ku!i@M;s~ zM$Z-WM^~(q;Y2gFkO4<|WMmd4=0!sr?Kj+08qzm4vW3nr;ZBm8V9abXU1Y7cDT)|f zpyd^TI2oc*#ne3xd=nulG!Y_i1L&YRNlXl>TE}-%$Ws3H0!Cx0rM&;3^08AaV}i*7 zEwd4^VF)EEZe&4UIFnYzSjqu?9YuW?_B!yElw3|#+@_?RM<39jEbQ&$MK0Y6ney8; zKt{8Y5R@a;_iK>)GJ2&w7+11T9@?IIOY%Z_q*t_X+?-^fs_LgMo%ghAjAetq8>)CK zsyw-F^X(`v*s+IToTTb|DtH1o?BWgyn+&_?io+gTSJQgwqLB7_GYO`Dr2sTN2^Vh` zgu07C0YZnG)Jhy&nAjopFg_W%17oR4wkEm1E3<>aQ#B>@030J3B5P4=asroFe1GAk z4xbl+xBFzeVJFjUJXYrVcrya0gbCzi>O^M^=n!=t#rr;goi6GB;|(28doq=#hO^JZNx)cY)QU!+ zr4x8C@@}cV28hANJ+$Hs!gLIsye%QtT;4ZT{gufB-U2GmFzqE{igtaO7N5Ie@}V6^ zo>CDPO#Gi=I)hYU=x#3O5L=jZc(Jjde`HIg%a5&aqlTfx6Ox{8%fh6b1rolXKyFFQD)-8_t^zZzxbolqXmRn7WTG^ zsSF66fxIP5$22JpiR?CEeP1KlOdyki7(J$_^^J0!O_k!5S0rQtwGjxTmG~7M?S$N) zRbO95nlc?B4z2;oba!~ZIX&v{Lr!9=cMHV_89d)W2Y9AS3Z+`W+?JRz=qRC5-_Avo7M)KN-j!89}yGk>v z{HbU09-9<^H!9Uhf7Q@70LlAw+TN08Wv-^9npYo5vy3zn-o^6m@-`hCtH7?+I)y-m zausS_Z|H-@N_!Y`$|q)IN{4KqOt8gutaptno#vdcP!=UoQoYBVmczrPY~t3y!?bzS zwTJm&U5g08ahm{8N5$UDjfY7Sm@Ktk*lgL_z%Vw9phk5HO1x%)bxay;TnxB1j_D;3XRRxfjBjO96loni@qFu=H6t;`LM?H4|+MJJuVEZN1N7MGWf`R^(N4IgJFqJ5@Zo)j6A1)YGC%+Whf&`9>k8-eBNY014N zE;W^xl!kcVs3f*l$L~1cGDOh)nT^pm{bI4!dyvRo?W&BpTXp6EcQLF8n0p;hgP9o{ z<<+J#-%XL%*L0pwoC&R#^hAwL{fMt2UVSpJ!;78u08WfXu8fzMiViI&9VN|y&m&W6 z^u-CU1KwMPJBpjHb?Co5P;T58WQuDC%{I=IjNsYw+wR7|vTRWLx^6HL`#>HyxFx|| z(&%Edl8=r^dgTovJgwk&N#C!t=;TLUnUnH~?{S@Z@Q zrK{oeXK}8ys%Ty;6Nc9=M9W2y-0_vPCN>r8$j2O1n<-!XM7(L%EYZZ21c_mjzWR1m zvjxE^c~7}9AfA6Fg^lv!H40t{nvie9@Qnh0&0%*zJbQOYz)j=hU>WVule%Th4Ck|9 z6ym(tVI_Kgh(BH$wzt{&Jmwxzo9U-ByKV1hG$!098B&714m4pBD%0Zfu2{%i{ln`x z$d6{9Fw2}VijfqJkE(;?p%fY^CNc*mf7Df<~eiDjjm#pOY zOkE1mE*hno4|kgDxmC7ftNge_q0o4zn~2&Ersn&1m5O}Y zAemVX*U8jhKxDEdT$}F@&w=V&lU}mHlMGW6G94fz8w{P7Z}{p;9V&YV7#p+r%D~VV z6-q8erJHalY+Nks)2n!`8&u}~&icp4vti;VOCN2Fb=`@N!zI5H6g1iv>wu4ugEqzE zNw58odmUfIzKv9~eD|%Oul9RiMy1&mT_~dw9=2H)OxKm!ELNC`wy~v3zGIZ@NAm`g z%dME@s9V2kB;US~&kkzoM(abl24Gz&4hyd*F|Ozq!?Z;=T;%$@qpjg9dCQZ_70Knw zsE5hfx!gwCo@5{6yO;%Y{jQMRiadKkD!Ct`s+?Oc2lcBi9;~m1+w%u}nqX_#HREx* zQ#|v-;tv@(_tr2Oe-s^pe!Nl~HE7i>dGRl-M(D6?nz9 zax!zucA{uV+|Et*YO{Xmu8(bO_QAVo+tB)UDdP6Q`sKmsVrB!2?Hgq3E$SMPkFv0E zKg>3ZSNIt#Q}SmA$(~^ zl%>7LzqGSe7Y^#N^)h)}Y&R{4y3G&sI~5)@14ZOf;ZDAR7d)$mkWKPAG8|{mcZkt& z+a9x-iXm`vGWnJp;?+EEE&6PWyz+0H(M3b;TNus@T`#Y4$_1)l;Dc20Cmf0-%D$U( zA#Yh~(ye7|6q`P%UoFcc#im)Ky0VQkX*HpCy+4`$j-vZ6t<}EH-+%IV%w>Fgl)v-% z8{%)0zZKEG=&R8q3!;VhAEA?RIo+biw>SCN?AF0mYt9x+!nbUgph|;$>mxV9>IWZR z9WCkC6mzGJo|%)`asHX*W3_yE)Z(v`+pW}`e$VqPT;8*))wykh>pJ!0o40J>oYdFW zYPC0oZ*dB}`ovFecy#a0ukGHri7$+vo71T;%$nG3jHbL_c`EPdRdReVb$MrJ=OoG1 z&wcVSUF-wj%R5Ei6_w(YPuO~xynnh;$Nf3JF4oD{b;AR?d$#7NS7x(|Idk;R&3U~D z>*o4T-XigtBGOn9=Gz2=nBNm;t9)wW|Nc?Doyxn+*yJ29ceCg*A|K6trnC*(tEIV- z@iO0R`a@&M=Wuy1*S47DF0w7Me`sX0ZMiQ0wr?t-_J!7Z4fEocnq`?Jw`t4fEkj#2 z_pi_KGW5t!ugV6k%-PptaxzQJD7Kgz7?P!?QKnj!xU|ZAuk0q|yUp^w;$B^p)m+MU4PFwKh$!u7G1oh|DJLI& zIwt!0Os#fWrB?eAe+zcm-=}uhYTw{*)m*K16Mswg)@mQRx>ox>fA7AA^Pb*7oISPL zAb(%s?~_h%fzI$ZuyxD8*8ZNMuC13w+csagdCSF{qpdvy8!ycdZQ+x^8#m^Aw`|S( zcYcR@2Kl;h&+E29Bfl9O*s^&r{#G!jyLIJzE*a=qKh(c@1H4F*PEI~5tYOsOyl{Ko zz!nyX^n(?wg4BrrO4v?Kf7C2ozbJz8$4obzz2WBq>k;Fk3l z=14;~ygl++g&f<%84lT}y=`UBgow$?^~z_h=S%5MKFD;NCD!s-p;>EnFlHpvFt*U;&BIvVe#*%PjrQxh=i#+7d@ zOL@i5mZEdan|TUZ7rx6AOh77ZTlau|ulw9w=blqLS6!03oYKG2MI~*7xt?5MO1_Ql zQ@Q@(?+TfbZ?d~YzsgBk&)+n(?ebG+uas|z^9}EW&%P_Itdv7F*K6x%Ox9=?3w(WC z*41+HG(Kh^JcGC$;s0~B8Fvrmq%<3(MC&qeJ#u=()LVy5n8!7_*@WJSCCWJdsV&AiZheANG)jVu~fzCJaYVJTy>s5B~O3J6Fy&hNKzs z!n|?gfcpoxs90Tnawjz~--bW0O#*3 z{H^{#t#+8dShR{+CS}SOIAnfz^z^7d*hevo^pM#D=ujuA%0qE7xV~>ua>!3O4iM_Sj z70^}CY3QE5TJ2uwgV4vI--JF5{XTRtr}O@Of31cO6D_=e^g*l8eb7IH-U|IJ^b^o; zLk~h1U0ACfg1!*?7<3c#Y3PTbi=Pukzkx1=?$}tXt$}_QIskpurdn+jIt1MVy%u^M z^p%?_2k3=cYPD}d_d=h7z5}}W*eLo7=u+qd&^6F|25PmpL;HtF5A;&#A?OtJG3Yy? zPeVTjUHn|eKv2%1iB8^DtF48ug$_Yyq2thxL-#>H3%wco4d`9a!_a%7&%dZvdkA_N z^as%W(5Il+LKkzg&7IJt(62++K##f@`Op)gwx^quI{^P=eC zGS7iNwu|&b5A3GCpv(4<9_abdA3(Q4pMqAPi%*E6&qJ3&e*;|uT{(vyK$q>M{-C>{ zcSG;OUws;SH+1odQFJeKDf9v88tBiV8=-A)qgo%<;l=)XX3g&uh=&xM{3{R;Gr(C7tGbO-cg=!4Ks==Y%A(8r;dKu>%t z?E`um^jhc{&|9I~p`U=xLJvaU4?P5Z8oKy}QItPGzM;25N1?xk-T{r?M!iB`3w;Rs zHRzHhQFQ#XppQbIfWGjZ=*5eo=p5+D&>NuL z(62+cLw^UYLYKXZ@`t_^`Wfia*AX8&23>j*{Lm|)=Uq?xg#JDBi_p_=pnjoa(AFZBTZ+6SoT zmyrJt(q5o5&`&|{hCT#cd>iHS(kRM7JE8KUy7jkU@78F+p2Z7ZeC$z+Zd!1Zs8NK- z=&`eEwKI%G|834sTAY8$GIXPro3_QhZA&gV?m4>`?TcP}(s{33x%A~CK;m=UQ*`?o zl(hi=z<7|oXR4`Uq3w|cEq~Rvczv75 zT*lvBLg`n|fkx}v7GKxW)wbk7YhPP#|HARMCB#~%yi|L1h`*KazFK%y-mX~AVW2_6 z{!YSFPPfSE7C9|&{Se+oP~pA4<-)cl*9q@|g*|P{_8-yJ*4grtwq;#y zIT8Z{N$7-i2>!oW!5Eb5sAX;2;sY)HZA~^`7xQqJ0G!Z$-wpUB-=)-WyuiwdJl~xUOy4b&}o# zM|QQX*?&}b+r9-YpKV(M($%&Mj&&ge#1&afIB4(0RkhlyJnuKQQ2jTwUQjP~33j;E0~K&izMrw{35^N|Qr*#>tVi+(G;c ziT`1I0x6pt(T|X?3+nUL-*#|8>#if4r)4eC4g>9yKFi%ui!29f1yp(GAS8SOu^ zuWftlr(4@P*K6g*i6M&UwVb_p#d)>b%ea=GV0~aa!00CQw}yYO02>99y0vE^Y2LG1 zcP(gJwmy|*m3J#~?|wD*L8V!pd;;uVux|2T<$%1b`WUP_SUZRtY#3V3lr^e5OFutOiv6tI_r9Pq4?pjsSak z3VRyt1hDoLwiti)Ofa=i;1YK!*ek$Rr})-@^@F`Gg>3{o048=%eiC;(*jK?O6|rr!dC@50Crd+Zj|=iBYI3it{1y{-4STv0qg;GYD3#V%cq;^ zN!NW3eC5Hf{$nI|`hMh{)?KT;7o8TpyH4!hfmY1O{)Gr=ooiJCO>V7^kjF}TpC;a$ zH{g>9z)$F6#uaY>!wu4(U`xT?2qtACKf%_39RLgY5=_P@*MoUi97$ia9qj#JmvU`o z*>bUTM#6s$VTTBl`jekvGQRl%*x8DhzT5$JL|=jh-h07c4j$@3;y(oT60meye*ktW zSURmwft?9MOvK40bcv$GDdC9gz0CU)r)7y6Ug4RbDw0&m571YS3 z&@Pa^wl(XUbfl90wRDQZjC0faIs|q(nCQCvgl`-y4|a+ohFt?T0ftG|pYYuTb|qM7 zt7n4U0X7Qun^we%s>jGT2X4%s*K#qBX z-y!R@BA=q)-*UMWZf>Y;Nq5`gZf&=sJALpy|I%9RFBcl0y0_v_E9tATN1}7jnAWwezrwX^n${fAzk;lRQTMxNB&}EDZcoVt&+fWU>fr$AspH*O6!9rb%D2cxj{BrOM1mGvwcCdGY zov(=Z|6qR$_A0?B#VVyJWq2L`Tif!HkXgy=H{m<`s#>iaw|VUByzz_Ybze(s7tV4s#gaTMrGvd>B59|u23rHx z5B6rRtuLUi+_&E#;|L1Q#x#TTh7mcU>>>U;iGQNE>HXAouJwooX+P{Xc=k@#YWK@C zwC#xz|Gct@9^Om%OQ(EHO!zE%B={ll^TAJ-c=%VBf{X6|6nt}ve}9X_h@wvZWd5u~ zSQpn4=RixJjR$c27_v(Lk{+_EyjK%v7jaILIGVmul_zB;^Kbh?8n_p1f`8rzmiDdo zf!zWo;qnuDGyl8??B$ABo00ju+riYQ?`>P$$CHHjApd*-JZ(b{fxQbX_)x<482@|% zEdA`K!Tu5~JZBAjiy6Ru4y-88#va`ueZ{;nTg$e3?;wgqCpHrI2gDtbxEmxc?Qniv znsVB+Fi%#}cpdSND!X0aUS!@5b|%<=SLP$c-$MLQKB6B_fUN~nn|^WIVyU%maGBfO z0sdaDf3GbbXxZItcq#ISkn`6~Y=Q;~^v+$wM?whr|%^Ri2>V)Tq@TA9r-C#$( zJ{hZvow@|<1h9)m7B>EX%rj_zC{7i^>5(Ka``}v#Uyt+AAFY)}B+t5yu$_dZ?WD{P zzXj}-!q4wa{_Y3673@j@E|KvMZP(|tX7ph=YNBQYi;h15|NnyjTH$ZdakX7K2huWC zuc!8`PAd4hGk@5#q`YN*`ds)Y{aNlCZje5Wj>YECF4ZT+uA$`VR^pY3H!krsPn4gJ z>3rra&XnZoi}3#${QsRiEyO7NCvmTepQYnRjP3q~*EE!$)a@$xPp`P{sGg{Qig$cf zs9LSRE8u$#e8HEKI-LgV0ZY#vT?;k<7WzJUhRn-f3bsMglsscg+fB!o!b3U%q>hdt`B*DMRe{7;ygec)%}6CC0p8ZSBTE_5w@6l`X3W^mh?;N zk72`ZXl1$Tj{iVAAj)J*6VO|QSEvD%r(eb#CpRb)^UExoPgz<{`>}+vQ5vO z>YPNkj1dmW7-1V@gx%0s;%>m{{bzWxeRZR<%W*7}2=P+`lTEb82a02`> za9p!zf6tb{vnB9s2|QZ@&z8WmCGczsJX-?Kmcak7OW^ipmc8vxLuP;ZKD!FO@^QD= zeTy@k=JzsXE5G%AztC=@EB!vq?^OL>hB5NH$?s))U4DP=_vZC84)lALg!FgF@BQ}o zlAHhCSVH=b_WO|j$nQh?U*z{8{ipeTNdGFo59uH9`;h)=zyG}nbB2A+AJX?OzYpoV z$?rq@KH&EueShxvA$_0q`;fl-{XV2Ga_HQ@|*St$+%R0p`I89>u(Qp zq4Ep(+dbnU-G^OpXdmJEzh!B`Vn)jPJHLO*3$o_-Azg?4e%ix-?e~A=LjJ!-?rskn zQ=hWcIlJ$5dXdvHr@NdUaC(c=JDuL+^Z}<2JN=Q*k<(u~J<=891x`4(~F#rIo;*-fYV!?-s$unrw=%NZ21DsXz9n6UzUg> zbT|2Nw_!c66D{j5a`4AgZcWF^j?VVgr`v@^%J{c6S`gjUGC#02YKiV|inm5TXo@e4 z?M7N!Yji{u>_t6(WEAX5J$_Ua+Fw1sC<^Vi9zQw?_Mjd=CJJ_=9>+@M(uiHRM#o0E zrucKChrAxrv09_H=#i%QaZ#|x_594P-IPY`x-~jJ%01o;e_r&NUp2!|hz8t#r$bv= zRSb5$9)Etcy(#|-qGtA^HF{xmP$!ntQlh9;W+vTkr$bt!7ezro>+zGK+zQj%dOY+> z2`XF*qo3Cj#ID3>w@}U>TW0s0oPlK_wDzQ^uiNB@en95rh5vEqmv$mQnY$JK3p_m` zRp)^V{{mfvWld3-`StQA{QV95L*T-Huk)WH%>4R!kl?>?T-F5TSKv?ZvwR^)_cMdN zp1%dM`fxKB{6fF=F0O_DXU?yCn!$uk_z%CA3x0uL*4Ksq$uks=bT2cP|I_jJO2+wp z+(`6YsN`$A=j$==cmK`tZZFT!ynpWax(56=;PTw_+qvNPZ6nb#3RdtX9R}#WWG*GT z;IBK&@OL`@u;br$T=xzWwijH}`5G?xeb3V=dvq0FV|Yma`?+nVKOX^?=N^8Aii!WZ z!||N!NeK9~}8Q$Mm2aJMRYdj|izmH(t@?FI^# z-(n-Ww_M79jpL!c|4-*X*lUb?>@m^9j^Ex>FXv~D@AL8r@}G8myW>Irb6Tz5FKNJE z4Bo6>P6d~GpA!SZFZjRbX7G1q;Qbl+7MFiVpUHo@k!T0Fwu?T??@ym=p89l#oIT3_ zqUdS&D}tW9)#W@gc9cpEcI-Wl?{nNAAAQ8-9CkUO-2U3}ryAsc-sS9ZIbOZdR~+B& zc<|rf2!rP9B1?}h*pjkC@HZ>}e*u^BU%1r@#)l2j3;rT8viooram1%_z}a$9ey_Y=o+X3E_)+JVefc84)A>WWt#y2# zY$oQ{>HI^EM<1)l#{=HLKj-*b$3yyWaQt8c{?ULpGjC%hs_?zj&BKnO5w8HH^P8#rZ<{UqG zrq$H#j-TUr&heWZmv;u5$={lRUkNVte$q}8pnC|p99H?*=fALgi60}svhxo*|C0ts z*Es*Q^9Q}X(fRu(jB&H`f70<=9M?UBgni!S>~lFmKfj>(i=u_zuThNp`I5(~e);fFFlmG%L>+WZ*9Ym-6i2XV23;5nP_*_yNa*XL$j* zr01qDSviONZgc(*JAc^UG3NL|$HN|vs~!Ir$2UawyUy{YZ?^llIQ}8W?{qw*^OKH$ z-|^sH%R3QTZVl;t*ztEd&aM7_;`r@eo(x&^_X}_-pXcqjd)>>y<CjY7o z`PXOQf0BX!Lx%k8GtzTchMdo2;H?>Qq!^p!>%k2CQ96!h{10dFKbe6q%8+wn27XaS z`cKW^U!H-_W~ArU8T|KT)XRnp{%sjJAAM+AZdYgEa~aS5;|%$~$iPb(cqId$$#|~3 zT;}_l>8-qP)ePUA zfxj^We@6!X{tWy>8TefpxV+cZES-Osfqy9jKa_z#nt}gY2L5;k{_6~UK}I_|Ap?I& z27YP=-kyP5L@Rw%bugt(#W#HWz_?8U(k2CPB`NJvr7evpC zM#Dsrdb##bvwD$t1;r0v>+7*?&c7d=Hx1^^&)=-_=g-6csq;6^^WUxb{PlwSRL=bQ z`CDEf=^-%Z332i*py!d!PEY3o$Nx?7dS1EvFXw;h8!YUV&T=Z_50UeovH_@#{#H1C z%$0Vp`=zCh(k&~ z;ru6FWa!5{@bikNIqmuz8Td~!@c+udUr0qrIpn?Ed>JNMq4@mg_Bj6ovlbTCiC*V; zuj_Lt|5?Y+@d<;~F7j;|@;~VOOMQZN+WG&=@tYlA>G)SOl?NQf#FUiJg`SX4I{tjepSaY3-}nPgQ9MXZ=-JMHrMHVPe}19k zUv@nw8Tz}(@r$pq`->gl<@jfOL14u3_c{J1$6w|6UpxK)%maSiVgElzjA!}^(Lp_^4plWmhwEu^ObYF*YWLM4re=l zvE%=7xdHl4IhQ5Hohe1GcK#oA8F<*kKAgcX-@yuHk`fc$<8oHHJ_nvh9sj)vh#2AqNa!Ca-WL6+Z0H#txZ3fzy~Y5q&Zy7vRsDuP>ikzI?l&p2I|F~G z%Q@r;5AF2-ar}a{CPcr_!sR`VFZX_Amp|j59RH16Ca9K||zRc}pumi`O*t~pRs(4%UYHu$~U5>mTDedc5E;xLP zq}%a+@7VP_3B4%B={lkbNmL^E4pL--R=0#Tya9Ze?6n! z{j2job*{z7?C4M4k(7Mh;T3+T<2lD$W(~OC@zcR`ew`+3oPY9aLvQv#c~=q@o%fUX zC68~JzYpXMF6Vi!&!HSX?)b?K_W28rf5^)r_+$Uu@xC|MqrG~fqhDb8{qCC#cXf&6 zJBU&a|I6*qOFhNsJHFTL&*_eDaC~Tu0s8GOE-zEunNmc)rzr9#T@PR9VQkT3*u1`0Dc%-6|yvO-Z z^YowN{9jVsZ&Kv2^MBCo61Vz0(&fLe!QVJR@st3+Jj?k@-tHDVe!k-eyuKzKp8%Kg zZ1gktIR6J%8zXLm{@(9+*mw8OtOv{QHpd_IdOyqH=#!3r+|v{Kse2W7rWE;Z2L5xG z^WF1|Iq2aLCt3L)@BR2oT-NgxPYL$RSAfg7X>G&$=_;4=4@1Vdbb-|Qo9fN8dKbvQskY^-|gc{eHWYXTODuNZOoy*4my6ex6_c{FFC%`^*ogG_Y_Y( z&@X?TfiEV(&H9lQ8F;tiZP9PNKW%sU7iI8Y<@}d=Kgg~A_Ga+k?EDMd&bZn|cRKzG z_a~q0a{dUQE?_eB;Tda_i+|T#EEYC632@5>?u|AekPF|^<3VO=McuJ z>KJEX4bSe#`?u^()`%Pj$0=TNNL-#XGdeigsM^sP<@20`GBk8)zIWSZ4s6-7IiK%X zzGC&+ofZwwESA-)BRS%^IGV4_jEG21H{du_PP3AOrt=jJ!N_xLXvavILv^P)C#2(? zXlPG<-RzhgN5*j>c@9zH=$s+DQ2yjplDr=uo!3L6^M#R}DM73C_|$wUUzk)r%BNb+ z`>A;rwtKvsFIAd^PR_-m>fGUn#05>p^kG_t~k3nlT{`D~|z&t{5~b zCsJ^^e(>U<^?e<$Iy)NA%hB!vg=4Goy|YtxO!Ky>8BX@#)LG7s$@`%g`93ekZBx|u zSZQXGusB8{q-*_!39RSdB)46hCtOW#w-&GBTc;KUSGU;VU~MJFY6Pr%qWL(Nh3tW~cI1J;|zGSTt@C;uAOQXsLYfL}5q3 z@&hy?tcqfGx>UX!?X6>?(p3HI!G1zUi0P@Zq-s=WqdvS{dx|-iCjYwG;;fuyr$-67 z2=-5J3l?DO9ybL;;X;bZwNozhsF@sxl-FZ$^AZv%?uFF|TT_w4sf~AJW`sf?E=_Z$ zXh}4Es#-2Ys1Ww2WBKy4SDX`ZJ}J6m=PIcMhz~Hb%2jPLtD5Hk_f;LG%1nXNpVW9R zk4j@x+E$Bt;J6A<)2ml0sqvXI`4p%XDrT_DO{ZKZoPtJjATtRc&kqkzj!I@A!PKHN zobHC5oftE%_jKBUsCq&XErixk7b-Td4w&^5LiJf@we6T1d)SyAhLoQdk8*X6QF^L0 zmmH^(-`q81%?aJGv}~9t4;Lol-1c@`pJqaa=Lz977H5#NAFIW@oX=vCf?dhWfkg(< zm^i^G1-Nd}CrFP+(Q(co=i9Z9Oq4LQ+$TrVVyolB7dgBu&)J5Ua4B|9-<*?)iYSaom!>LM5$ULrgmXDroE#}n&lyu;S{i=S2S}k&g~mtf%EMQQNY45O5?KhJ zl-RrVfYFK{FbXhT^+P?m4oAldOl;1Xl_%R#y!n~g2}#k6T2kkj;J_U&$-pR2;A)if zq2^N3387U?7?1Yb%8gn96)JX~EFJO)-F==jsm7~P0GeP<4;3EMXRgNcGt>D37nS_z zh$-?!MXdCAen){m(yr(s<)BKv**z_0n|L!GkAA!)@+)}@BG$~903us>NrM#9cz%lW zG-q~&5RYCO=fG6OG?nA|k&&|SRPsj05$jPD<#FQ$dmh#@UyyT7HNd0ua8LH^w4}I_ z-+@UD>96Ex!zF?fQSbyD7L7QbpA9LPk%Fz{5uSyQ-h-@$qvi=jM$FxxDHIZx>TS+W>QpSQu#wsX>_RoMMZ(~9JVTlSu2oK zQK*py7AvIsJdGp;LT04IM+d?tDI?3FA@YbJh7-_`ltkZtmLDzrH?%*2%HF z`TT~>+wwhqE~u}2Yn0!xam%`{jrlFTy@MQiIMl@{gLxPyO2Z@hk;<%ke38`G)ULH_ zH*D-*w?4n3V@1c=W`XV0wES>5BQHN1PRJ75MAx@dx-?ZgF-_(i=)r@1aaoE2xC zxXHuUz)I4W7DmP5$U$FuvxSLkjn7#uHc5-ejZ;ueB`f7{(@!_#M4U%jSa1X@C2@qs ziKl~^5j%_xQ#U4WJ#dp}dpV5ivAzu{kHoLa>zUGjNTJyf!n|v9#^TWl^+Fq(D(5HU zoKQ-*J|)2;aW`Ci3wxjp)2P6LIC83ooXb5kH8MR{A79hiwF?VtE;-$KJm8SNotn_v zDf`)eN%=}F&FJD$g5r;g}BgFZBzj75!mRCx_7TRr=~515 z*{Drk3BeOuxk6g!bZN9fYF+O06>uOuPfEaZA2)%<*Vc2S+5*Kua+Q;v3u1=1|?1GDu;QU^FXNl;&kno?JVl<6{ih5ghsxufdH*u-pQ zyguqPrBf_6=A%5B7k4sF+CX_)#;Al8ixh^8PV=SF*ep)Ual;f3R;AovQ$lNHA|tfK z1_fTd%GGHD>L)|dyd1ZUsiW27AmZSb8d~1i^lY_KpQqSRR?!tiaNM}+yQp-iY_}?= zKc0w&=BX1Yn{3D^XBp=?%UBJL5AG~((~e0`E5$;I2CFfuPoT7qYPlZMig1k#g@aY8 zq^yY;2v6!H=QCG|J1UwUZEn)qyzi18YmYftIM9U#W8mGnIstUbjm9nR-8gPKFCKFt zRp2W-Rz&N!uFtP8&;iJd9@&Q1~PWi?rL9mLffLwVbL4$t)9hm9lrq ze?Vq*W>aV2jM=Mgo>A0daV-m@X(=h^f5rkcKP4@pY3neypb-P24C-z4OX;|Emku(t z(fU5MNky;f#3)WMVFoMh#Z^rdRrGkepfnNHQP zH$;?QW~B&lC6sv{+)Fu&Hg*`r&6cOt=U&s3p-|fQB%)m*i?phunDbF>PUel+!*qU4 zJsLO9Huq+(p7bU%x`>TV{XoN|kDEbDD@&nTox#vn)xS$pzp`UxqiHb*ChjD)5=&#| zEL6+lQzg-*>Vx{H+#FAax`oeZnP~gNc)>P~o9CHSrYD$e5B`Z*c&nLEVKT)NKi)v3H^4 zLK{p}X+D*eJo?ul=hPGia zRyVL!#=!~Z?DC1TC>>|h#LgdthnADrLv2I!{7p0Nkq&9J$m@#Qc#Qg3rEzyndY-OTYoUT_EPfr*ZGg&~9 z)U%`|xz{4&`C@|+i#jTElQeoL9+lGZaHTpn9d%4GW8cxWuD=}(_q!cavmL{;rHRpY z#yK5w$4u*Z)G<0Yg*>Cx84KA}oT=a**4^X@n<-8dB!XW}PgJ80sg|gN%Z?poE~NL0 zI%HK9rm~K$JBs5zfisRljqfa~EvQCLKSQv(P~G4DD2e#eN;A?1N6n58nk0G^96(2={^h zX+!+5k1^1xuz|VZxk27X8{&uW32_Y z=yynWsE1pLlYV~qPUFFsS^Q-pH1!Md1N{|Y>G<*Y9CH@`F(a{r5HC=PoQ@y9`}ml@ z2(vVfX%}%k$B!hkV4?iN`-8{6+#bB={UPTTA?NV|d5%B7GXPFQ{H*@Rq+8k>sz@a) z^XCtAm_WAYMKAEQ3KG;(+E+-s;NiDtz@Bgi`{mNV@Z5mOKIUfePc9p0*q<5r8{_{U DRnT{) literal 0 HcmV?d00001 diff --git a/bin/router-mstp.sh b/bin/router-mstp.sh new file mode 100755 index 00000000..ac496f38 --- /dev/null +++ b/bin/router-mstp.sh @@ -0,0 +1,53 @@ +#!/bin/bash +echo Setting parameters for BACnet/IP to MSTP Router + +# BACnet/IP configuration +BACNET_IFACE=${1} +export BACNET_IFACE +echo "BACNET_IFACE=$BACNET_IFACE" + +BACNET_IP_PORT=47808 +export BACNET_IP_PORT +echo "BACNET_IP_PORT=$BACNET_IP_PORT" + +# BBMD port for local apps +BACNET_BBMD_PORT=47809 +export BACNET_BBMD_PORT +echo "BACNET_BBMD_PORT=$BACNET_BBMD_PORT" + +# BACnet MSTP settings +BACNET_MSTP_IFACE=${2} +export BACNET_MSTP_IFACE +echo "BACNET_MSTP_IFACE=$BACNET_MSTP_IFACE" + +BACNET_MSTP_BAUD=38400 +export BACNET_MSTP_BAUD +echo "BACNET_MSTP_BAUD=$BACNET_MSTP_BAUD" + +BACNET_MSTP_MAC=1 +export BACNET_MSTP_MAC +echo "BACNET_MSTP_MAC=$BACNET_MSTP_MAC" + +BACNET_MAX_INFO_FRAMES=128 +export BACNET_MAX_INFO_FRAMES +echo "BACNET_MAX_INFO_FRAMES=$BACNET_MAX_INFO_FRAMES" + +BACNET_MAX_MASTER=127 +export BACNET_MAX_MASTER +echo "BACNET_MAX_MASTER=$BACNET_MAX_MASTER" + +# Network Numbers +BACNET_IP_NET=1 +export BACNET_IP_NET +echo "BACNET_IP_NET=$BACNET_IP_NET" + +BACNET_MSTP_NET=2 +export BACNET_MSTP_NET +echo "BACNET_MSTP_NET=$BACNET_MSTP_NET" + +BACNET_ROUTER_DEBUG=1 +export BACNET_ROUTER_DEBUG +echo "BACNET_ROUTER_DEBUG=$BACNET_ROUTER_DEBUG" + +echo Launching new shell using the BACnet Router environment... +/bin/bash \ No newline at end of file