From d48fb9e442ff3340ea1e20dbc6f19e71ba92b145 Mon Sep 17 00:00:00 2001 From: Tony Shou Date: Mon, 22 Apr 2019 11:02:54 +0800 Subject: [PATCH] update code --- .../BatchCoreService.csproj.user | 6 + ...hCoreService.csprojAssemblyReference.cache | Bin 76280 -> 76502 bytes ...ClientDriver.csprojAssemblyReference.cache | Bin 10480 -> 10490 bytes SCADA/Program/CoreTest/SystemLog.cs | 2 +- .../Example.csprojAssemblyReference.cache | Bin 130253 -> 132383 bytes .../DataHelper.csprojAssemblyReference.cache | Bin 35948 -> 37018 bytes SCADA/Program/DataService/Alarm.cs | 150 +-- SCADA/Program/DataService/CacheReader.cs | 688 ++++++-------- SCADA/Program/DataService/Condition.cs | 861 ++++++------------ SCADA/Program/DataService/DeviceAddress.cs | 32 +- SCADA/Program/DataService/Eval.cs | 419 ++++----- SCADA/Program/DataService/ExtensionMethods.cs | 463 ++++------ SCADA/Program/DataService/HistoryData.cs | 49 +- SCADA/Program/DataService/IGroup.cs | 21 +- SCADA/Program/DataService/IReader.cs | 33 +- SCADA/Program/DataService/IServer.cs | 32 +- SCADA/Program/DataService/ITag.cs | 419 ++++----- SCADA/Program/DataService/PLCGroup.cs | 520 +++++------ SCADA/Program/DataService/Storage.cs | 49 +- SCADA/Program/DataService/TagMetaData.cs | 39 +- .../FileDriver.csprojAssemblyReference.cache | Bin 18995 -> 19005 bytes .../HMIControl/bin/Debug/DataHelper.dll | Bin 44032 -> 44032 bytes .../HMIControl/bin/Debug/DataHelper.pdb | Bin 85504 -> 85504 bytes .../HMIControl/bin/Debug/DataService.dll | Bin 81920 -> 81920 bytes .../HMIControl/bin/Debug/DataService.pdb | Bin 222720 -> 222720 bytes .../Debug/HMIControl.VisualStudio.Design.dll | Bin 76800 -> 76800 bytes .../Debug/HMIControl.VisualStudio.Design.pdb | Bin 99840 -> 99840 bytes .../Debug/HMIControl.VisualStudio.Design.dll | Bin 76800 -> 76800 bytes .../Debug/HMIControl.VisualStudio.Design.pdb | Bin 99840 -> 99840 bytes ...ModbusDriver.csprojAssemblyReference.cache | Bin 12255 -> 12265 bytes ...ensPLCDriver.csprojAssemblyReference.cache | Bin 14981 -> 13957 bytes .../TagConfig.csprojAssemblyReference.cache | Bin 59136 -> 60206 bytes 32 files changed, 1474 insertions(+), 2309 deletions(-) create mode 100644 SCADA/Program/BatchCoreService/BatchCoreService.csproj.user diff --git a/SCADA/Program/BatchCoreService/BatchCoreService.csproj.user b/SCADA/Program/BatchCoreService/BatchCoreService.csproj.user new file mode 100644 index 0000000..6cbe588 --- /dev/null +++ b/SCADA/Program/BatchCoreService/BatchCoreService.csproj.user @@ -0,0 +1,6 @@ + + + + ProjectFiles + + \ No newline at end of file diff --git a/SCADA/Program/BatchCoreService/obj/x86/Debug/BatchCoreService.csprojAssemblyReference.cache b/SCADA/Program/BatchCoreService/obj/x86/Debug/BatchCoreService.csprojAssemblyReference.cache index de35cd6b8b272f673af383cf1f8720a9f0131cd2..27504a6417aa8cf730b732717e8b504ddbbf07a3 100644 GIT binary patch literal 76502 zcmeI5349bq+Q!o%-AN5+6feBug}C5w3!bL&ec-w4 zdan1X>wVwrffwGc;)Sl_g|4^gdadjAJ#v_ExNkjr>m>~Q&nAE z-Cbgpl$890z?h*&Da?U&iFhWRO*iMFyLTj#P0?wwY-=`Jlg_wcpnzNfojTDsLujcpt0NVf(iABg>D&+ zDCvEZm0i*xsF=&a^f} zr;MA{xioJ?bV!4ry?Qq@FA;a^aL~!wsSc}`{rgHhcRbX!u zYsWOO;Ij?&b7GnH`kLz6>ITpH2i{N{%f~z{oG`ftMhWbA-5L! z*)Nf5O3%+m$EP!G+58UsV26!s?=-UN&hMuZ`#E^+?Wdq7VJ*VyYu4J^A9u0t+AX?} ziN4rRZ0#M&j5hBFy&iTmdoApyEgMf~k_oSJUmrVJix^DH#8O!_ulYur=V$}$FS!;D zs;~h=D-n0I`5#mtHlT!0uw@k+(e$I)m}V22O=&ix*_@_|W(%4vX||%-nkL^U_vin% zr5Ql89gI!ofniHq&{gvCmG8I=WMiHGA6wLJZRw^m{I!Z>;XFOHG?o&kk z3RVn+aRzajt$uX)kl{mjEU{Q7JcL4r?U5j&FwS5Y*}-P{tV$kXo0*`)8O0Abqk>3-f%z*p$xa{diUdk7u7=i>blx7%= zGaN=L7fXy_>PVQL1zjv>2c~xFkPVA z9Z4lNYqbB8QoHO}tFzQ|LFDbiio}Yc} z6G1gM3CAt=q?ruk)WH;#-4v$o1yfjdg2Y*DIMupkAEb(@Fit&;q*h{Wsdbn}hkfZV zy{iKoWOWbw(P0K1_V4Pz##?nbfDSY1(9qR^4ZZ3xiw+0UVRlysb_!I7gODm>Fis;( z!9lYFp*qCr&_oBfi-XP1#_F*6FK9N<{uXAMeH}H^El3q}V4Or3hjR8gO4$A26<*nD zH{s%7xQSMpBuyI)`b8xoP18;@mnK7lk(d&Zqv@cT2UE%Z4nsLRGx?m9Azp)=%!ive zgk}NFLYPYSjTmfp3s&pk*d4X!#In^>%2MdOmA1EbYj4eUL%+{%PR3fY_I9@k{loHZ%zC$O7P<}SXeraJ5*CJ$k92t6!t*( z@N$>VByw}wc3xF4znA45PogoAOym|=R=x*gIlo4(BAplM5pgII#9=TDrTDWBhbcP> zLzZinPab#qJdWYbo?TK=b_B$ZgxJr^et{WJ>nb*-RjP*rQukP#jeU|Y^o#4pH-xsJ=*+_ z!$G_TKaQi|CXS{#hUQqB<7keDsbp7~p^UxbE|l@t=*+H*9h}Y}N~9R&2b#s~sqVZ4 zFKFmmfxt}}I7ZD-KAKA`VjF*Jkn0oRCKl10NOKa+$uO1d0y9|bdGWVxIj6w(kjJee z;#4Gw(_k2wjXaN5JF-S5%Z@-w8vh|vc@R#=Hmd=Gyth0G9tLu<2g2{5TO%j`92D5k z%pVP_hczhFGvFr9q&W+wl08-iYd094|E_1zszIVx#%JSy-3hcmbQBTiAVr)D!_Zm8 z&2kaDauJ`8?eftdZs0HXHz0rFx=q)Tr3V_{bfG?l^peJ7n~ZHv5Oau=cLJv%O>6QD&9? z=QMb?TH*QWyrDJ0O}UvwJbz=W-pw5}bmq*}837qo)phHC?VY<>vj|qc8Fv1F|3x~7 z&Bdiy7MIan4wL`gGG=pa9U%X9_m_XWS7P;QRF9o4Uzc{WGb8z5Zv?X9DwuL!(ByL? z5U)Yib~W6@H8j`KTt{;~%?&g+(%eLIGfd@V7zS$!jP8e7&MTsylbu`OE^ei{jplZm zJ815txr^pcGd4lFinx|-ojlByh-yG&D$`Q z2f{FvA4JQ&mho@3>T3R`#R{5tXx^pyD@CTi?b3C8$L1#i!KHz45In3L z87o`G>U(T%Ct(a$1}oP5mh%Jby8bnXJWnGce#9E_6HE|1#yIH0K@Fx_KmFJ_sNq*# z97D9*u+lJQ81oqG1|&AqFcz)GWRQ9J>2eWKhK)pi5~$Cchuc3uScu!VDsH?PZ>J1y z`C9^}rDT;RfJ86>cWOr}muPdNsM->-WMZKYTZFK6hY5lQ+m|wIU#PJ4B5Y{`n}H1s zcy(KEAkjA*vy&zOM?@b&R;fVtsSMdCDr9{LS-XMEKo&x_9+0T=Aq#4>T1+&@GYEoeV@JgL1a1Qbxc6n?-cy0=N8sif;0$mfa2o@Ohz}g5AVg-cr%3 zB3c=PmO(2-YYQOJyA!SG?dP3G%Wm9PHfD{J^Ne1&{%3nYT73s0>@ z!~mkTor2a&GFmUHXbmD-IfIr#D@1F1AknkFt~L>CNu{&7L_8Z2QPMS7q3cv=jmRKEPurgSM zSd9Y`(v*tv1Z#o<)}1m~cc@@ZB3KIySO%;RtUZB5aHFX3xfcIj8WAy>u+=HB-7Ld) zlM373gpCgdnVaC|Cb)N_XdfU^**Ot=Qhhv=XwOB&R1#LN5O%Fh*flC))8WzkP!PsY zY8?hU0)LVYSCrUC!59b)gdT+Zfe)!Eoq7p8~l$ldzY*1HNe9@+JI%6QZV3w zH48`-4qhBcwq`4AT`aS8k;+yh**eCsW!MVYiUW!8va*R-<=+B`^$cE>^?Mnsb5*S7 z5UXRcxoHbcTj*6;2_O+vS$u*lA`T{7tuR6G*g8XI>vt+!DYC_9oDExsEsw1v)5fX$`@EhgJuWD10=29@(0&uyumW*6}J^3(3|AhAqQZ z$kwlcgmig$D8V{R0qZCktRq#hjv!cz3|I!N5UeACMA(HtidY@3V0EaB)vr~ojw4nl z8mtUfAy&r&iD0f*ewykDL~D_P);t-l4i&AFiPlL5ErV8w)+sUN63fVdE=zS`7z))(P z2CKb2bOu(KVGA>C;ayvv3u>hP|L@7(c?x??GJA2Ay$j)CpJ~7{6&&jx{8`RLKqBn_ zUreknQLs8t#%h*|)n&x$EQ6K7D#Yq?AW=9L_D8aHg~HYhnXUa)wyuUp?{lEbP->kE zt8FeX#0t|~n2)vf_GQgeAN*}G0*Z>r4RJ}P@R!o$AEfMx16);;*MoST3|aBGqu zX^M!O$<{3jTa#tB_Eg!roornUO;c%^O3P#G4j>VB#qK0lcPUtnm$4eBVs#HZdS42x zh*oLI)_8^B5hW$OmUOriEKjYk9?BO^TKM-$_TH;DpW89$knO7bpFOGi;^S)8KWgsR zv+w_I=ND$Xr(C@GJy#s?=x!}bPhI%k=i?7sxX<}-Zhg|abI;yjz{a;Of8pb0{buz1 zQLOXELy7L2ZvE(6XV3iR(^q;;x@k(Ey*K;hoA~0tUt6`;nGNT!_uw;A7Q6A6hjmX~ zx%9))<&8tDzr3^Gib(Q=)?MD}eHrppfxprva}IxOQR3k`>vAlyfp_r7mvQo?dkpqf zFu%+<#dSl@mCsgI)Wq6jalA_(=b}RSWQ6A1QTZ3}<9nApjTM)`Fo=77LhP%tWU3NV zm3URjeZWHM|18F$xZg*G+<4Pxc9koWUDV3tA$Zu=7_dzL2Ml;%Jq#qmHfjm6dPKo$ zM;WWpDprpZt7{Eb2CEROCxAroqGSIPwh{3p@p?+ZYq*TpFcq(7h!@}cZkj{W9D23Z zvp^!aYV#(PE+t#fDQs;ovo%O%>qWA4yh*@p^b>&cMyRU!L?klkz` zGmwRleF`Kh{WmJr#Zs{rx6MuAasHJg>@$V1-ZEjmRKmU>Vf>7jX(3Gu>9vqw0tsn! z^(%t)wE~uq!KzTf`j%kbYQQp8S6FrZ14t;tVBZn1?-jhd$#|8jc>P4YZZmipyh6M< zh9A7(x!#R;;6vaGB7&dt7WuEuVM7M*=Fks6NS}B49t*)IlKrm<*>JOO$L6M8H0`3- zE^>-Ncyp+nSXFR^A3UtSk+J$(#i~0z>^tCMurgSY9?R*0sAqLN?q;)z#zZn-Y4t>! z=*9JZ@aXznrt346u1a{=cf!TcW#}S3ma`6`B4ZNkVwLF2&HUg&_K^(Phbm+nz{9=^ zE(S6K8R@Z{4G|TLscwV>(T^+r;Gy-djMh6UTARYd<_E(KS_UoBV>z248sramX&;A; zj>ng}W4WB0$wuqbvG$1A94?}Y?tbv#dqalrbrrs?;9>Ja^#(ozAL+52tq}!dt+j4@ zGQGeXYuyIvqCdCsgGbmaGGQ;Pglz{8`yRL$!VF=g$8vs!NE&M$h($4otNh@B^}Gz$ zb1GPa;bGqk7Xy|7i}YB|5Jcf%#ZWAWVO-${538qTte#S_8VL{kKDZdH3|6Gaa&|zZ zjwXoj zYIxZ9!^NOw&>}sSvpb@o>YCEghVQcTGkP^h6}8;L4<284%Y6Mw<8dt_%eKv z9?RJSk<^u+h($4ptNh@Bb(;*V{xOzce;KX}01 zAOm;33S2!r?1$iDfHT069?O}ANdL^ozE~rsb1Of1j9n!&cBRVL{_wCLhKpg$Fh+VT z=Kw^(GauS<{fL-}O+*7X_k#!9r7~=PP+^-54|@q*3~UBA(qlOXAu4hcJcd=Gk(>F! zgX{tsvh!8QTzJ@zz{NmjAR|4N(~Kw_ac#kZn8Ou*@US{t#_B8;t5$f}kHW=ZWw0VW zmXkzOFe2851d-xOKX_>URz~YLDq3^lVLt{JgO)*y^jHpGwiLWKU`DJh84+2eh#c4Y z!DH(rnXMC5w&ugbejF}_EyEV+v7AE?^{lU}O~hJK>1-}P*17;`Vj$nWDCp2nY{K)8m^EFOZgNqD9gbDv2yW&F53<8$$o@x#>}Yt{ zPr}7OW*{RymU9fEjr^&H<5HMl*q%vbU3`mUUILT#BjQ-B7sqj1KX{}qkV!j4C2bKr z?5E&jNHe679?LlqQP2_dUb}k|QpCwz>j#gmtjtzMW$QF}*iXa7uw~dHJ(lwuM8RPG zer{v5v;O)m)`-)&l^;CD+GNI(Dr0BD!~Qc|3}c2d(qlPiA==DuDalxMdwVhwkL42S zR3~m{V zzOI0Wy%a8nFT)q-5I@DdUmPD#0BCbNRxSE^z!2@hx8L(+8VAsLJehw}M zFasFrv7GA>1--I@K{8weB;9x}ok4qf12z&j(!mcNZhOhNO;K^X1s?YEa51TYZ!?&0=+@Mx=%Y1>_;Z81FT7vW-PGqjN&%efy>(2DxC zS^iE_v^t(k%*&5)M8pHwNIXafKX|x}m2uly#cc^Z?3dtTa5K1(9?N+IQE=7S`4YQF zkt!bJ7Jl&f8YT0!gUZ*F@UWM`#qeeLB0ZM#6e8&)W=@W2`>gEd42YbiYJ zm*HZ-GGLJ&%Xtn_FeRhQ%g>+3D)9n0^MeQ3KpC=MsgNy$hy4m%3}gl}(qlOcwHzMyU*KZUGH8(=%XuA<)G)q*Me!zA`N0Ega~Z77RIpaS z!+sSm1}p;>>9L%55QWc$yo&|#SFZ4bht)<**OX} zJ(2B*C2Jz$BczLuxs4w@!q$}uTSp~qB|Plqa501#!bp$he1@o?v-LR=#NW8m4<1@Q zWwd&zXnh3_`*pY&v|t3=T?637%P_-y;e}Qaj)G^aE1GkKDo!9$%KsSBc7()eU^T2^Yhc;fwTGPAQQ1XOD+;!+KE$ z69kX6@4lBlJo67Mboua1IZ1m9K87?ynnzj%kSH>=DhOFbf$S?8vM*K0dJ?j?4P@r) zSzy3}tQU|ddQjT2!79XRG>`~h3S2OUFgh`n&Bc=F*zZW##wf5YkzspSg>5WhTWMf3u!XSg z0wjWt{eFp5Q+j?j|1C*86uB!Q+f9LNu?*RLDr7Z;>@x$Ifh>fq7D)681}HMI`T0k@ z#}Tjb3SM`~c-^VuH4z@Y{|4y_%HOfDVfscR-dtpTfu#}nE5n~0tgo?jm7gLe`Mc}= zccc^we2WyV!1r2#9~FV0iV2ijx*U`tHJ^i_i$_ntZigu&EgLD?98_opB7s0y2HlGZ z^wJ9S2?TE3b@t(vFGj{#mBj@5Y6aF01j0kupqM~Et-vOMKzIn7789t_3T&weY*kF4 zzgA#CAP|fp5D3pgT`_^ZwE|NWfqGvcf?uT^tm#^T8G%4p2K)O0N`=xO z3*3tZhTaD%0<((=G-?H!6alxGz#Of>!HPg@F@cm;pgj;+GUxEe79}38v*!8&4vtXZ zFDOharxlooREAP(zVGNKc*(HVLapPWNG+_55Ay|-(mz5L2&?m>6oI3Q2^^;tI6)Cu zR7~Jxt-z^@z-h$XUNWq8wbt=kq!yn4>wE#_{NJb*xLFanrI^6&T7f$ifxC(c+@lk)S&9QYCnE3O zkw`X0>*vHWZd0^6n|0e7lMANA+T5CSTRRdn*t}%Jcsi9$G`X3nZZ4K-foV*-Ukf1isY@d>06WhwyzdfuFPjBs!0BC{T(NEy^}ls3?~Q0^uQ46cgyK z73diVggNL{OrTOLu&yG|x0t{NT7iuMf$$Le6%*K0E3kPW5FSERF@deL0^2A8{fh}~ zrxh3&2!w|)sF=WDt-w%4U|2DMky?RKfk0RWql*dbq!kz&2!w~QOEH0Jtw4<;z%Qq2 zQJ$a`n5YQw3z=GhI<3H7fk4>h=NAvP0`*#feFK584EQ-at-$_TftiW`KT)O?n5`9v z1p?t|Y%C_=Y6V&Xf$$Lcp&@M!TD1agiU2<+qZOE|704;8VKV9DJY^_$Uwv%YYAIQXm*R2(AUKm0E$%1A(v%_^6#W2VZFgzEK4D z9FG_S6>l7ffE$kI>w4eEDqeVB;CwT^Iz3=pqnpDkxfXhC+&sOo|UrcrX->$CybyanB zb$5wXQd05@0%L~Wr7-(7B;uKLHr<+w?%tJ1wnV4JvhCSuT{`0qte);>vWawRbj`46 zO>}T{@WAT2u4Jw&MmG;0(mJelcxz2f%do+* zAu*d9+f2WW#)a9O+tHYde=6(J9i6d^o9RcTxKQZ1pw=j@W72rm1eLn{iWdx4Jf)bvsb2YyQya;3hwNjc#UsBJMU|r<2hcZgaFHnRHlAb64Ls8)B(go7>^0a`~-QVrvuX zM>VnFvrUb2W0}szy4w2MCeQji-c%pU#rANMoo=S7Igx5Y0W{US&0THMg1nr7T>I+F zd|f)#nrQ3F#E4;jgAr^n`>)#Igj6;cOD6Lh?u8Azt8c^gnb?9vsx7~%-Ya&D>Of#B zSD#7D_m7fygyiJBTp!4dU$H~(1DZeP-N)Nc&5NzEVtFgdPs75-dC4dj=jHlBZZ+~V zBav!JFUUs6r86Db{094BgUze&FtX~-Z>I{|Ibii|r=TWbEyC(+_UhXnH?h|0ExM42 zwXvPp>f4o>9o`AemSE0m*i1(@p3Wo_Ugf?HHnJKqn3jp9vS?oOjWmzZy4YTFHSAPj z1BO;2?q>5RR6jPLgiowTvp&rRG#k=vM6)r?CN!JURMTumvpLNcGy`bzjq+Cf-_|tS z&}<81Q+fNar7h?xdHKqBT()Opo&O(O)Uu9rOF919OJk|>7Pm9&WZA{Z+L;`x%hJ|V zNl9tBW0i=?XisG}if&8PZ{-(GM!P=tz?_?6Z*10V_JAy!lAYhY=91GMt7P{nBDRAS z+ru~m`J1hNbjaW#H6u$bmI-&E&|wE8h$xIR2u60WS$-?Czibo#-~F{)Q|N(}x27hv zIISHxg01Mpu>{I2OH>YAnL^;+uS%({;Zx-I1S#|4h2PA5?12~Zg(wCiLDbOf2;&Ta zk;=sqLzy}ZrcXf^%h`$PUbANtyOk-s6=kKgl&q)+J`!<;W0O)oODs~a9`F%J6(eDs zQ9T@No+1C@Oz+$?4?ICvCJ+C?(Dk~Zu^YNwu-{@d&8{%c7#QhbT4Fb**246FZg(V= z*sRh1OG<4~&0B5Zsal8q7WFh^VVrR=1*JBgse8cmD76Vp_fOSo{QtkC?6!P%&e4wq z)!d%gZ!wW(5{%OTQ&4u3nYtHDVc7{1XR+Z_>y{}<6;olHMi@!0#M)fzFpUnsp~Li^ z4s4LsEzF?9Ogik-(}9h*>aZ^zX3?Rkrvn>$)nPUr_M^j`o(}93s1ExhRm5PNW|)GV zW(Pubh|{5k4sH(zo1Kl7Vey~PY@q!u%ryHtYNp$eD(1pCi5?CW>~oZ``@t)`@|AAF z#Q|^=?KDZ64jS}}N<^BblV%=Gh6W=sB_c=DMKd3!iv1mi3U+4lIVnfH3OQK-H*p}% zLYjkMs@OMTu-PqGshwkY)Ses5)=n-@q4QSS*{zxjm#Ii(8`&R>(6h6v79t|i z(b1J38>`H?9kI?%w*~#fiZW)stjt2U0XgD&cy!}ZuCz6TWLd(kcU@YfgoAz|BQa#T zYWd`TSIp-a-kdolmF0&+>ZjB5?TxYnTjIES==m+ukh2Idk{A*BPKQq5K ztR7aOP)~!KIGyH?FjefaGFZF8@c8#UidG#Gy)r%n|LaAd{h_0XI1?%2EEtCFB5sw7 z*p-X;9IUt3%AITe#-tLKvfvf)pP{9sux44MrVwgOsjM+e0vt(NLm1(^Ui&vsT z=&tK~v<%%D$@3b4Y@~wS_k2zS;#D}2FNd4Bg62w^t7xvKxrXL1G}qEx2U9f(hQXQ) zqrMrn!aYR+y@(FboybXn8nRv5B}1uHtr@J815t zxeKO>7bXl9yz0nrVI9P)P|SD3P259sFU@^4OK6tT+)wiW&4V-#(L7A^2+gB3kI_6% z^90S4G*8hyP4f)Rvoz1aRLz88sNl6vKHIBU4LuKc@dC|@Fjc&YVyKu+%K~3T>RzJj z%QUahyh`&L&FeI8(7Z|W7EINCFboy@({iij{9CEojunhpM)Nk!J2daYRK;KzD&n*h zXIOdhsus8rKj%G|-ss_UBwA9jXe!z1{1qv^n38IZ=M&!VPH4#|d=U7gTHC!r}KMC7;1ng#078i;rnOp;=DzDNNN|7>3@T!AuT&_42KM4kE8mU$c4m@Yt~Uu$^i~ z4jJkW9x>8B0Gcaxq}GJPzsWUIX(_QO|2Mj3y3q;`PxqXN@ovh^B;xtG5shwc|C(8| zR%Q@=V0F*6|GAStX3r*9EJ@4x8*F88Un(L#$4~JEOc1=Lw2$AEGS%uWHKmbA1WDp+ z7`q+DfR$|f=Uj~cr-StkXmGr9BO<;fB;UaV!NaOT#>!E#`Vp(!Nf?8b!OE+z{tg<} z@~d2Vrb9&hgeBr_tJSu$fB!w7~2{Hn`B55w+&k73L(<}t>B*-bQzMQbsgVt#(Y zSwxg!B~c!9Pr;9e+mAncqfms<`T;+B;8sE0QU zwIyQ7#6do6g0Mvt*uIuw`$~na4`E9i*bHo7z^mKV01|75mn_m0+KA{&$oeUeeI`Tp zsS4Rzgsjs*W*`e8TN_AJ`;Y}ST0N#}<0*msyy;XN^O+-}KY?3E0q#Q?xDQm|)+ccD z3~&ax5V#G1M8pRUlXxRyL!z~jg4R1ST5qdpZA!E<1}%eDh*mX_=-Z7}bW$QUFCsQ0 zUz;m@y)N_hn#$LfcVqh5wSJV+D1X^MH#IZRJ67yS~-K3 zsk*|dYao#5)7Vg-h_$8C*<2!?jffpcS5%?vX_>C4RJv+NSC^s7&=u0PBarA7UP)%$ zh!{e)hAM15Dzo*7%GPkQHQ%sh*b3Pi0VMkSZ1G{}@F6SIU?WM{D21~7Wy+SSl#M23 z3k+q3vXHV}fkb$VatyKBO~LAJ8LPWgtm=r>fd(ssRfttRkdUTSj3rp(6tHfU!Ma5S zYXZSqXuvXHg<$OoB!U}7g-?d~Z=;BaiG*#E0^1ETY}c!>?M2x5XpI?{Fyj*5xWwK- zqN;ly+MbQ^OrkRv5mQLmRE4l>WWugi3HuE^`W^zp7)q@}VTa;R(&2&<`$!lAp@GnY za60&qn$j8gDP~H{cylf;li9meWp5Td?4t}=rYQvj9#~C4qHyqHHrd)wVe0~!t@Bm3 zVr1*LhAqQZ$W}9u2rnz+#HvNX>Q6FOXRBDX5v!vORtBpOtGPfTsIvG(T0|ts)&UAz zr^{@ern1#Rw)m8=>1UaKme(AnfQ0l|WkjTjR;Pm2DKc6ot7v73*0BaHQ*DLSRt`uM zK3v{Kw&p8r9WS$WoXXZhvUQwc%di!)br6t{E)NeTScfQJ9VLTxqzcwy1nYPMmH{gS z>u?|ucHxg8R!1sW9V%mWh>F$G#OikjD}z;t)iFRKnCq3Frg|*VI!-}rfsEFC6|ED9 z)(HkJgI0*vi9jN_Hxx{{@9_}PNrdfW1-5xIY@I4>zb9-b8rTeMA#8sD62U`61@BRh zh*JsKX$oZRGGqs+kevaKz9(Y?45ij7u-e;0r(uB^wlKpM-mt})phoKdpGEf0R@if8 z_F7c-{tOTMbOV;D;8^$I&vMQM5@G-UJYsdeg4G-utNm20E+STcG*}s|LaZ(Z5`|-7 zmyoSX6}I+~*_x@cbp<^7o(WxsQj2eD)HavrVu5KcO>^nhYFC09skyw0>|L#}*C?|$ zRb}s5c-VXqrUA=<<$-k_kO*!~@-s&fv50J4udvl1vo%R&>n5^wzG2I>nP9+U>t-Mk zcEuJGt6LPT#>-fZQ?a@o9(^x_B+)7@8Gu&^9$r$yYe|P2!SAV!wKaT+rGW#D z>?;gdrV<7N9$5DQiLer0Ladf5SnVuhHA==J5 z@E%(EQ>zj2JQ;gIVQgEOv29ewUM6Gw#DnS1o9?{V>v{!91o!ldJn#7`VS7!1Z3`K; z%~jamBy4{%u$c-itkB*95(RUUmJzMD6|^>%(b`Bw>ph}%twGD66{7W5AQ4O#DX7OH z;(bE)fdbjOGGyzhkbO+Z_yHu-SenMtYb-wj5>@^ygBoI~Sex77rtrM_auW8bLRghd zSU;7p&q)}+ePswUgn5L00VJf+)h`LwR|;6YWUwMCSl<$?>kU|@eGJ>j?|_6d4E8H@fjId@FikMEpX&^27Upg~5B5#xFlf z-!J(YKYDz>qzsz&jac3AW%%;=Dn}IF9J2946)QokZZcSzRuK$% zSVa)^sg1|oY}WroeMIykUA?*74_>A9rA*fsDqVfyVc!fFQ)!t>i}YAdKSV{wB&x7T ztjX2<;6b)rhU^m+vi|U}7sJIsW*{Ryma`6`f-%)~ks#LNLO*zDy)UEnR~4-d;bGqb z7lW2Ti}YB|Mu-Ob!(H0vJ)`6BdFxm%=Vr3e#&oPRA~uGL*o5wW@Zeh}!}pd7-)8Wz z`E_>#pMj6`SkC5%g0a?mw=-fPV>{XetS5(5bhKGF{Tnu4`Fw$c= z+aQw0TDQedu^kur!2|1g8La12uy%lleLGwXSOzT8V>wYo;b6re{1Ah=zz-f)Ps&(5 zp<*=z9`+q@F<2R_NRQkgH#vGB0(hKu3L@I`toXB;A_D?c7T#U5Pb2M?^pGFUgOU`>RFeGgm=SOzT8 zV>y!$t-x2t8?c&~Ocy_Rz%7!2yG{je3Oww4;bMR@z>yxynTkmN%ts@Zh-qBQ4<2Jz z$&6j8GByJq_I+?Mj2XsAkLAon6g=~x9oLVDeXxqym#h21gY6O-wu@ERX2Zi?0v7|D zfsOQ7&VGoB+ytM4MPh%h<_8b5^JK`*RUwPR!(Iv(1DS!0^jJ;{qHx63#ShWS1%B|b zI!ngtOckpHJnZ}7Vz4q;ksixA08zn+SUVC#k_-Ldp>?W^)*n=~((te!fQv!PphbEt zrxQ`|-hi30j$}m4LyE|7sUJMHPLkO=QDv(O9`=K9F>D#ONRQ>rN7SdWp*|67OQo~9 z{8;M(q=^H$+z%dI$I5gaqtbOSJnV>-xbX?O>U-gH+Ovg@^qJTnuT3G}2=^#~}(jV%~dYk4K959hdsSW2;MME2pw` z5^(zIT=wfm_Ng9j&|2yr(lWrU#{f`kFm7OSW0E=RCw5r!No9U7$ZHF za~h&e{Fai8)pm9!6Y*Fskxq5vb~;uPf24ySJlqm8ZgW-K&Vq;iI9v>F1~<}UIcFp4 z@8jn4wRa}X2Ph-rPgo|-;d*}XD2vOKHLH}J2M_xRxERU|Wu(V)&PNo?7sE#kqmvS; zc@c2|QpJT_!w()`vt_=TRK6~Ohy5g63}1#X(qlQ7BI@VYVhyOfVr_|3TSQ!jWN|rH z@q-803>mQLDqvT^!+r`b1~3B{>9L%v5e2=nfyeE}cPpc@0()f1!gPJlv+p zxb3atwg?{f({M4k8Qe&ZUGTkL5gtD43Gb9L%z5CxMG*ZH(bjP z9%DjgtWss{dwAHd!^JRW7$ZHF^8=z_B(?i}Pd_46{GDs~!Q-n;=BrfY>lb*~Z@|Uy zW%wdJmQzypj~@@Quw0bF1i>Tir@u=dp7}d|^!V_M4G;TG_!!a*X&z|~kSH>=T0zJv z70AAoA^S#!tQR4B%Rpv6Ljwjp$a({b!e@~BkgYWowmz5H`kTsD71>&5*fMN|Y^@0- zq_Net2-eyPSRcz^eWZf5F2Q=+fMvi6!CDVUtQpKXjOAj{#(7E1)sKkviP#1TV(-a_ zy{jU&F%f&mAZ8E?5!(bv6zP0zibbLtCJ0^+|4kXPH&n>BfQS7qd`u7D^zgmT*8m_9 z-Xq$QSZ$?X^|FlBODa~|60464R;KO(10Gh}0ST$!wLQTasDSmX4AwI$Sc3@G#|A6| zRtVN$AQ9GAHNF<2R_LacTI62VJ>3+50;C#15uSP~uk;e>63 z0^5T!Y!9fg?M&E~8`unNA#A$o?IoV%fQkZf^gYS+lw)67AlVNVY^9 z=f*N_OSCqdbvv4q3n#}q+_4Ad+*B3<1FL(kJuQ}P&qn#?s)5zh@gY{MG`eP3v?e+@ zI(T4pT~{*Km2pR>+^$?EmK<2UcULoB4>QqSI4#}orbagp9@09jb$Dw{P0O&su_3Y9 zvspA1zEEXdx}y`B$yCP1b(iFK z_@ygJ>qjhLX)<&R{DfbH0zV@~D_~hVfik4#1#0ddG5wmICJ(d9k)jo-&-IzItRXraWW%Vm2u$ES!e;^RDFT}p z6WCHKuyr61mccf~1h&@-><|cqyAUlVP@@$Xq6iEvCNNwpFftGbkHV;80;9D8V*-J2 z7j`QqP^T3bs|buMCNM!OFfkAakHVy40()r%rYHhaeSrv1TPaw-(F)861i~_y=?nC% zS*=-Gf!T_{e#Hc0T7kGC&{9mGO)HR41P&-B(4iGb2LkucJ?x?56H6PcPG7)50Sf#D zg=uBA0$oUDD7EJMj(&od3~MdaIv$MF!pigzUqC7S!?XfNC;~?o6F6EcaI7M5Trq(Y zv;rq70w)&}_`O!(R7K#lVghGq1LIQ1fJCjJg*46P)y)ut-z~+K)4I96%%+O$?!W?{1OyFa!z;Z?4(_#XjYX!ax1j1eTs+hpHT7mBafp8aoC?@ce zR^S&!fFsJ{3i%j8>pl5!k($z*w!octwC;_0*mV6SV>jfk4`+*pH#l$2`teH+#d*pyTG^GXmjweR^ZVPg^L!$+cPm&Y@KWI9sw% zfKw;60-PbK3UDS|VHt2*oK}Fd-&6t4c`D2SCqQWhIL}EH;M|r%0Zw$$3UEG)D!^F` zg#w(?pcUZE1yz7|rVGn}x2d%Pyc?|w@UCNF4tNVvE5JLAssQgR73P39nY04Dm!t^T qyf?BkcUEwfSh8Lmx0DhsZf2^Ri)Gqinv?FhWUQ^k!ueKW_4+^4_Q&l2 diff --git a/SCADA/Program/ClientDriver/obj/Debug/ClientDriver.csprojAssemblyReference.cache b/SCADA/Program/ClientDriver/obj/Debug/ClientDriver.csprojAssemblyReference.cache index add0c38dab2470335b2ce2be72a879b3de0cd85e..c728f8d9a43732d8377582839dedef873d158886 100644 GIT binary patch delta 56 zcmewm_$zQjCnF=<<}Sub%&bdV8JC>htjMaP#8^4mPu&4X_JhdH7u4k$xfv@N7#J#m Hn2{R*I^Ym` delta 52 zcmewr_#tpZCnF>4<}Sub%&Z#?AEckztjMaPG?_=8b8?uv1(===p*P=97iVPT1_1sH B5Y+$x diff --git a/SCADA/Program/CoreTest/SystemLog.cs b/SCADA/Program/CoreTest/SystemLog.cs index 6ea430b..e3845d4 100644 --- a/SCADA/Program/CoreTest/SystemLog.cs +++ b/SCADA/Program/CoreTest/SystemLog.cs @@ -21,7 +21,7 @@ namespace CoreTest set; } - public bool IsActived + public bool IsActivated { get; set; diff --git a/SCADA/Program/CoreTest/obj/x86/Debug/Example.csprojAssemblyReference.cache b/SCADA/Program/CoreTest/obj/x86/Debug/Example.csprojAssemblyReference.cache index 85528320b62e4553346d0ded29cadf5acb1d3abf..657ad16e898fd587bfe44e0c2cbc7f119e659d7f 100644 GIT binary patch literal 132383 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 DX%1i! literal 130253 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 z zEftt02wdwVaJ^JujxE3v@kS?sTciT>Yyp-A^PL11N(B}P0*jpl?vx7LEeI@e5?Ce` zSS|?M<0P~a$LKdHcOTYyax*<%UN41L~d`=kQj*a9pKzO@AK73Z`cqyj(L0xSkUTLMB1ev=C9 z7X%JC3H%`yNWg*OTL&6^sC6L3pdx(4tFzk{U}=zK3E+5fPV-0ws@MW74XRoK_=Lf5xDlpj=U@^GdNnnapV45w!VldrFV5U^y8bM%| zlfZ1LzzwzlJB2w;0yj$q=Gp@66y`YzERYJ^CI~EY61YPuaF;E>PT_7Rfu&M`|JVZT z6qY*)tdI)aCkWi{B(Pd4@UShwPGOCcz@t)u#|42WoCKbh3Op+ataB3BC>3~K5ZL4- z@RC&E6-kknp!~a@wKt>!Z^4&bqV~2Gu>2|u+B?#K+u$4jROx$`fN)v=Kq|09 z5ZLJ?@QGAlmo31m^Us|GzLW~=5d`)+34ART_|_I+1b*iv@S{}VXF=c>CxPFk0tajX zmIeo%1pbr?XvnSjY)piYZ2U@dVT0I0O%enuISEvj3RJTN*eQ6O1ZqeHYS{uT7iv2R zoGukOQxK@*Bv4-}kRk{)a1v-J6=-Y=urxT=N#H!GKyyK$g_A%_sX!}RfF)vUCxLcS zfsVESJB3b80$rs7-E9FDgA6BuEU7?GTY$x&myt0d@)_odiZp1;*F{>=Z6`67Wd{@&ti=CxJq#z@>t~cqf6NRG`EbU=522P6AP> zK$$JT(qN*Kz+|bwm4d(&CxPiwff<6pOecX^Qi1CPf!R(1bEE<{3j()T0>Ze#e5t?! zTY!<`Wpk#;*%|!Sb0_+s%#l_MXxTOM>Yyox(^mqQJ$r04q$iUawRjS1Le@ zvBqa3t;{MF7$+5=6*uDrX!%X4Ku{_`D-6a9&~k%Pfv8k~){=`CpoQh60tn|UJF?2?ogw+IRdrWx4lspQ0pQK5=Zd8oXsw7NZ!ZBOeHlX`nL9Zi&#&S`H*#A7q{&iSbp zJvp(Vd}Pz8rZG(w6^*0Hqa&kUK5UrtGwM1sS-rI`8_nuWC7R+1-8d^e!MucABocZo zi!5Y97e+Hnv(bix&RmN^KoQ|@CiNphU{)&HI5ir}rqcdgd5Wu3t!>e?o*qP@)u~2( zPCC^QZ`9MpjHrvR(u+`{jBi0S(XMAap29+p*W0hy=~>hBvW7e4dAcJ1&cj2T9wJ@t*CiD z6R|2cG8O6d6{&PfBvdB&qsnn;A0kz!=z2b0G~_(n33x~0){TU~Y4jQCb z^3dnFH4{svK|Q0Ef_P@*M4$I2>% z#XhP}i*2YJJa!OOHwh{R6OJYvLpYZ3J;HH>;|W6uLkTAkP9&T}I2qujfU_)BZflFp zS8cS6XR$Rfeo<)`wx$}3aI_RelSPesTgI26iqCk{*$zEj(3C_QS>)3^qPVQPWGYv^ zF_ddYI&0BzOj()LlWgwUz=nEr!{U10q7gh3-hFWUZU0hiH0Y%`7sCjr0DRvE1lSgZ zMwXAP80Yb_z79p13knXX%xVFKGsgiRn`&Fe`Hp*&aW(+^d|BS6B)h)r)U-Z&g9CF~C1)q`g`WCvORjnO`8UlMdKx0c>4Xsg-x&a@UNmtgW6uH%uo)n} zGDLa2{3v=;Yx_&_gZ8@5Mh5Y^L;NH2lppe8o$;`l@$&8&r}F7d#*bj0Zo5X?_Pab! zD^PB64q+s~R|$|_s3t}+b~K|pwY$|1&MjMNBF^(`E;F|!D1be*H@x7_= z{ik@rfoO3WhU`2gPq09*0ca2=ZB9VCTa#T*BGle%SG zV`Hn7wi=OQGGPk9Hx*zjEgR>GrGS;?`(_4)81&N zE}QnpGj+6b0=%=Wy$V7^ytTF6a48h0_10)xo8IWr{C;{B(Bs!&M4$oI3JSWlip9lR z@hGdJWJ9#8Q*Ien7n<2irQ_M9t>^CVUAgwxEKs~5o``2VHBEa|vjlYcMW*RVJspo3 z{*gL8duheu#l5lJ%1XPZKDZ8``g#(JmW1Z31^Ub)h}rlp<`Cxc8V&|+HK6DrIH?Y- zhAGG2L9fk{C7$Ajy71~A?N*%< zTm&dN1;F5?1>GxYhm{6k(OeDi9bLe(2Dlg%+T}%+b!W~GC>A4yh!E-lHoc(TgHM^d zp=b@R+>Ianwv7++Qlz~>>+>(NM^`2+ER-M$(AZ}xE!WY!&w^ca+Zb-XK7v~h4aqRaMy!#&eAYER$;?gDqk~{OdQXs z?Yf~$(U@-5{TT>=88CKCQ*7+maihn@Dl3g*E`wM5@GFP1AzgM1s&tfRDo? zQiL|bazdJr0hF+t%20GBpj$g$gec#Vn&`4r8h_$R{xOC?#FBY>N1UwZt;GmT%7FJ^ z1TTAvu3CfL3IIQF2E)eDt_P7UU3MK#EM2w=X;$Yy z@IEsxy0T4wuBpE+Lr%Q(Ex1&7sh+dpF9#j+iZnOUB(6Z5xRPMBUHHLZ@_dcV^VKrX z*CNg3ea>@fbj&3A)yRgI4x=NC`$=Pn0dWmt#I*nh!`?CY z(kWA9rA(1^NH;rAk$u}b(!;_S#ta+7m|-c_P;I^&Aa#-y+hyJulN|QPx=FStXo3X% zbTS%6Ilz9?k8r#AG2uo)$w&Z$Mh_)zmhP5^Mh|2u4$XHHFpz6>Fjy+q<6PWK_zAD$ zU@*VJq+G?Vauwf(G%NE}+-I##Zg4l?+knT{bQPlOReYx|?d_22r<>NO2G-#L7@8Y# zo4A9piLe<^G9JL-r62VOQy7wG%k9@5gsDw(zxGbhLGIdZ!MXS;;Vyuo>iE}CcTxFU zyj1=c??#$K+_eiZPxmk{69J|C;rkh|I6sF$Y{Qw@PPms>aWI%!zevvdB01|nN1Bel zQzQA@nhJdf9zHW4b&yoZ{gCPBP>59py;mV6=i_!S4&MWS{^()0#v7B-P%_cxdk``G z7?W&@84(Y4MKl@_zsTQ{Y-%x+JS@c+X}nd4an+D(oac=5M?i=pp-v+uK@E3h@DCCDk8*dgx8q>2ZO1A&X&tqCYSLIr0IJF#0;AX=uJF7 zuYeePkj$sIAl5$vU{r*_-vdxUZ{s$xi}3G+KM>v_>?ZsN;a$RefD+DXUO zTCB`zahMF6U)8`$EUq!?1Qop}_rtpoKaMcPZ~4m#3Rox%>*n2}R1L?g&2g&43U0ezWZ3 z_1Aq}*paw;)}~ud`sIW_ZQk|9J5TT4{QBs@!wPQhmp=D@)@)e4bI*!F>!0_pn0?0H za|Yh>k@w>d_6~b$`=@(9Z;Z_9f9uotZyHhGP_{!aJMpVGCuZwYXaDEtS6=dq;Lh78 zo_4|wM^)>`m9{>0Yh}&FuiqMsAWw!d^zivhR+qdH7_ZeM#>p7cqPReVh(UZ|{`CZ7 z_^}noK8w05^V^@Fyu7_^?>~NP$f5z?ilg3rHs0^V;ViJU-<8K;rtA^Y#QA zkxQef&n;d3;=1_G8cjzGi|WHc_{OExA1}EZMKt7nX(qvk3LRx;_P|k|h z;CS%1;vSb)F0D*jaUny#ubZ3x5)g%m6h(l1FzNO6x8}4o#%f>Tq#M2bq*oFbU3$6n zGU>&op|T@1AOyJ;P`LHqGPk}^xix^?O1a!J7BsmNYv}+O2ue5&Xa+=(92=x?>{FRz zpQs!gOpdj=9CJAa4w(AuXi(yBu1N`qV@S4R6|#LOlWng`w&O{*!7nPHj9gBK3E~rJl2C)nU8drSqMu{D~;PG ztD?Dd)mb#xv)V;-ajT=~$7Ru$H;zk2okjmf5&c9@qMw#U@4*R!_ZfhzQe2f{s+7f0 z2a?Sl!KtVRk`YgxxoRGSW!^IYO5MZtC&KoEi$d{RB6>j zTJ3ac<dS@Nr0;nxi^zt*YzT1jCq zLiSce{_w+mN#9GzrO_d>mh`=h7{?9~H?y$%T2_bXRm3`Xh`6tXy|2YhE*wR_C5zsJ z69(_w0JlTrc8E;7^)h@|QiteroQf*|`CxX4*2S~2nm&>%eOr_Peq!o9ZacSk!%B0nGphSuFpSOe-#53*DM0G%1Pll~i7}g;( ztX*Z;kIAqlW^rs2D4}+{H%r(Hw z=J6juiQ{t~=_$#qo^DIWGkWg-tcQbVE17n;!n8|drq!!V+eW5w4@sA4F4Ih=Z3iWK zm}7J=Np_z?vPCk<7OEuML6W`alFV%`!2y$G_k$AlB?%9ZTMsJSnkRE>uF9>4$*nz* z+nY^Y`IO^gsbnVJsHf-Y*=V{M(2&rl;{Vw782@Rs7UV9Tc8~7|h;j7za_3IVnas>E z1i3?_-5dQ8VjKl>?tGxu!O*+_Yb660zB>xw`gT>ou)F|kfa8>&1aR%LD&TZQ0N1QK=7396 zRRLU;X0JppQF9c)m1vd#YlwwQkL&`t4#`mfmm8@9xX8pVU_wswfI~Qr0yt8m3RtTMptIgl0DbbR0J>l8l}KMK1q2MLc7aBh zt15s_HhU51adXT89c!updQj{F=uUAIK(C1^fL&y}0QQ$11+ZJJ3SiI2UI*+3ISOEJ hM-@P;)-K?_o&?a6RRz#=u@`}MjAIUHt|$Wf{XaiX58(g+ literal 35948 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 KMv9_f!2bjLq`MIS diff --git a/SCADA/Program/DataService/Alarm.cs b/SCADA/Program/DataService/Alarm.cs index 523fadc..6015d78 100644 --- a/SCADA/Program/DataService/Alarm.cs +++ b/SCADA/Program/DataService/Alarm.cs @@ -1,121 +1,66 @@ using System; using System.ComponentModel; -namespace DataService -{ - - public class AlarmItem : IComparable, INotifyPropertyChanged - { +namespace DataService { + public class AlarmItem : IComparable, INotifyPropertyChanged { int _condiId; - + Severity _severity; SubAlarmType _alarmType; DateTime _startTime; - TimeSpan _duration; + TimeSpan _duration; object _alarmValue; string _alarmText; string _source; - public SubAlarmType SubAlarmType - { - get - { - return _alarmType; - } - set - { - _alarmType = value; - } + public SubAlarmType SubAlarmType { + get { return _alarmType; } + set { _alarmType = value; } } - public Severity Severity - { - get - { - return _severity; - } - set - { - _severity = value; - } + public Severity Severity { + get { return _severity; } + set { _severity = value; } } - public DateTime StartTime - { - get - { - return _startTime; - } - set - { - _startTime = value; - } + public DateTime StartTime { + get { return _startTime; } + set { _startTime = value; } } - public int ConditionId - { - get - { - return _condiId; - } - set - { - _condiId = value; - } + public int ConditionId { + get { return _condiId; } + set { _condiId = value; } } - public TimeSpan Duration - { - get - { + public TimeSpan Duration { + get { //return _endTime-_startTime; return _duration; } - set - { + set { _duration = value; OnPropertyChanged("Duration"); } } - public object AlarmValue - { - get - { - return _alarmValue; - } - set - { - _alarmValue = value; - } + public object AlarmValue { + get { return _alarmValue; } + set { _alarmValue = value; } } - public string AlarmText - { - get - { - return _alarmText; - } - set - { - _alarmText = value; - } + public string AlarmText { + get { return _alarmText; } + set { _alarmText = value; } } - public string Source - { - get - { - return _source; - } - set - { - _source = value; - } + public string Source { + get { return _source; } + set { _source = value; } } - public AlarmItem(DateTime time, string alarmText, object alarmValue, SubAlarmType type, Severity severity, int condId, string source) - { + public AlarmItem(DateTime time, string alarmText, object alarmValue, SubAlarmType type, Severity severity, + int condId, string source) { this._startTime = time; this._alarmType = type; this._alarmText = alarmText; @@ -125,8 +70,7 @@ namespace DataService this._source = source; } - public AlarmItem() - { + public AlarmItem() { this._startTime = DateTime.Now; this._alarmType = SubAlarmType.None; this._alarmText = string.Empty; @@ -137,8 +81,7 @@ namespace DataService #region IComparable Members - public int CompareTo(AlarmItem other) - { + public int CompareTo(AlarmItem other) { return this._startTime.CompareTo(other._startTime); } @@ -146,20 +89,15 @@ namespace DataService public event PropertyChangedEventHandler PropertyChanged; - private void OnPropertyChanged(string propertyName) - { - if (this.PropertyChanged != null) - { - + private void OnPropertyChanged(string propertyName) { + if (this.PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } - } [Flags] - public enum AlarmType - { + public enum AlarmType { None = 0, Level = 1, Dev = 2, @@ -171,8 +109,7 @@ namespace DataService } [Flags] - public enum SubAlarmType - { + public enum SubAlarmType { None = 0, LoLo = 1, Low = 2, @@ -187,8 +124,7 @@ namespace DataService MinROC = 512 } - public enum Severity - { + public enum Severity { Error = 7, High = 6, MediumHigh = 5, @@ -200,24 +136,20 @@ namespace DataService } [Flags] - public enum ConditionState : byte - { + public enum ConditionState : byte { Acked = 4, Actived = 2, Enabled = 1 } - public enum EventType : byte - { + public enum EventType : byte { Simple = 1, TraceEvent = 2, ConditionEvent = 4, } - public enum ConditionType : byte - { + public enum ConditionType : byte { Absolute = 0, Percent = 1 } - -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/CacheReader.cs b/SCADA/Program/DataService/CacheReader.cs index 45819d9..c8d4d2f 100644 --- a/SCADA/Program/DataService/CacheReader.cs +++ b/SCADA/Program/DataService/CacheReader.cs @@ -3,908 +3,762 @@ using System.Net; using System.Runtime.InteropServices; using System.Text; -namespace DataService -{ - public sealed class ByteCacheReader : ICache - { +namespace DataService { + public sealed class ByteCacheReader : ICache { byte[] _cache; - public Array Cache { get { return _cache; } } - public int ByteCount - { + public Array Cache { + get { return _cache; } + } + + public int ByteCount { get { return 1; } } int _size; - public int Size - { + + public int Size { get { return _size; } - set { _size = value; this._cache = new byte[_size]; } + set { + _size = value; + _cache = new byte[_size]; + } } public ByteCacheReader() { } - public ByteCacheReader(int size) - { + public ByteCacheReader(int size) { this.Size = size; } - public int GetOffset(DeviceAddress start, DeviceAddress end) - { + public int GetOffset(DeviceAddress start, DeviceAddress end) { return start.Area == end.Area && start.DBNumber == end.DBNumber ? start.Start - end.Start : ushort.MaxValue; } - public ItemData ReadInt32(DeviceAddress address) - { + public ItemData ReadInt32(DeviceAddress address) { return new ItemData(BitConverter.ToInt32(_cache, address.CacheIndex), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadBit(DeviceAddress address) - { - return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadBit(DeviceAddress address) { + return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadInt16(DeviceAddress address) - { + public ItemData ReadInt16(DeviceAddress address) { return new ItemData(BitConverter.ToInt16(_cache, address.CacheIndex), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadByte(DeviceAddress address) - { + public ItemData ReadByte(DeviceAddress address) { return new ItemData(_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadString(DeviceAddress address, ushort size = 0xFF) - { - return new ItemData(Encoding.ASCII.GetString(_cache, address.CacheIndex, size), 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadString(DeviceAddress address, ushort size = 0xFF) { + return new ItemData(Encoding.ASCII.GetString(_cache, address.CacheIndex, size), 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadFloat(DeviceAddress address) - { + public ItemData ReadFloat(DeviceAddress address) { return new ItemData(BitConverter.ToSingle(_cache, address.CacheIndex), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadValue(DeviceAddress address) - { + public ItemData ReadValue(DeviceAddress address) { return this.ReadValueEx(address); } - public int WriteBit(DeviceAddress address, bool bit) - { - _cache[address.CacheIndex] |= (byte)(1 << address.Bit); + public int WriteBit(DeviceAddress address, bool bit) { + _cache[address.CacheIndex] |= (byte) (1 << address.Bit); return 0; } - public int WriteBits(DeviceAddress address, byte bits) - { + public int WriteBits(DeviceAddress address, byte bits) { _cache[address.CacheIndex] = bits; return 0; } - public unsafe int WriteInt16(DeviceAddress address, short value) - { - fixed (byte* p1 = _cache) - { - Marshal.WriteInt16((IntPtr)(p1 + address.CacheIndex), value); + public unsafe int WriteInt16(DeviceAddress address, short value) { + fixed (byte* p1 = _cache) { + Marshal.WriteInt16((IntPtr) (p1 + address.CacheIndex), value); } + return 0; } - public unsafe int WriteInt32(DeviceAddress address, int value) - { - fixed (byte* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), value); + public unsafe int WriteInt32(DeviceAddress address, int value) { + fixed (byte* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), value); } + return 0; } - public unsafe int WriteFloat(DeviceAddress address, float value) - { - fixed (byte* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), *(int*)&value); + public unsafe int WriteFloat(DeviceAddress address, float value) { + fixed (byte* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), *(int*) &value); } + return 0; } - public int WriteString(DeviceAddress address, string str) - { + public int WriteString(DeviceAddress address, string str) { byte[] b = Encoding.ASCII.GetBytes(str); int index = address.CacheIndex; Array.Copy(_cache, index, b, 0, b.Length); return 0; } - public int WriteValue(DeviceAddress address, object value) - { + public int WriteValue(DeviceAddress address, object value) { return this.WriteValueEx(address, value); } - public byte[] ReadBytes(DeviceAddress address, ushort size) - { + public byte[] ReadBytes(DeviceAddress address, ushort size) { byte[] bytes = new byte[size]; Array.Copy(_cache, address.CacheIndex, bytes, 0, size); return bytes; } - public int WriteBytes(DeviceAddress address, byte[] bit) - { - if (bit != null && bit.Length > 0) - { + public int WriteBytes(DeviceAddress address, byte[] bit) { + if (bit != null && bit.Length > 0) { Array.Copy(bit, 0, _cache, address.CacheIndex, bit.Length); return 0; } + return -1; } } - public sealed class NetByteCacheReader : ICache - { + public sealed class NetByteCacheReader : ICache { byte[] _cache; - public Array Cache { get { return _cache; } } - public int ByteCount - { + public Array Cache { + get { return _cache; } + } + + public int ByteCount { get { return 1; } } int _size; - public int Size - { + + public int Size { get { return _size; } - set { _size = value; this._cache = new byte[_size]; } + set { + _size = value; + this._cache = new byte[_size]; + } } public NetByteCacheReader() { } - public NetByteCacheReader(int size) - { + public NetByteCacheReader(int size) { this.Size = size; } - public int GetOffset(DeviceAddress start, DeviceAddress end) - { + public int GetOffset(DeviceAddress start, DeviceAddress end) { return start.Area == end.Area && start.DBNumber == end.DBNumber ? start.Start - end.Start : ushort.MaxValue; } - public ItemData ReadInt32(DeviceAddress address) - { + public ItemData ReadInt32(DeviceAddress address) { return new ItemData(Utility.NetToInt32(_cache, address.CacheIndex), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadBit(DeviceAddress address) - { - return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadBit(DeviceAddress address) { + return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadInt16(DeviceAddress address) - { + public ItemData ReadInt16(DeviceAddress address) { return new ItemData(Utility.NetToInt16(_cache, address.CacheIndex), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadByte(DeviceAddress address) - { + public ItemData ReadByte(DeviceAddress address) { return new ItemData(_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadString(DeviceAddress address, ushort size = 0xFF) - { - return new ItemData(Utility.ConvertToString(_cache, address.CacheIndex, size), 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadString(DeviceAddress address, ushort size = 0xFF) { + return new ItemData(Utility.ConvertToString(_cache, address.CacheIndex, size), 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadFloat(DeviceAddress address) - { + public ItemData ReadFloat(DeviceAddress address) { return new ItemData(Utility.NetToSingle(_cache, address.CacheIndex), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadValue(DeviceAddress address) - { + public ItemData ReadValue(DeviceAddress address) { return this.ReadValueEx(address); } - public int WriteBit(DeviceAddress address, bool bit) - { - _cache[address.CacheIndex] |= (byte)(1 << address.Bit); + public int WriteBit(DeviceAddress address, bool bit) { + _cache[address.CacheIndex] |= (byte) (1 << address.Bit); return 0; } - public int WriteBits(DeviceAddress address, byte bits) - { + public int WriteBits(DeviceAddress address, byte bits) { _cache[address.CacheIndex] = bits; return 0; } - public unsafe int WriteInt16(DeviceAddress address, short value) - { - fixed (byte* p1 = _cache) - { - Marshal.WriteInt16((IntPtr)(p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(value)); + public unsafe int WriteInt16(DeviceAddress address, short value) { + fixed (byte* p1 = _cache) { + Marshal.WriteInt16((IntPtr) (p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(value)); } + return 0; } - public unsafe int WriteInt32(DeviceAddress address, int value) - { - fixed (byte* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(value)); + public unsafe int WriteInt32(DeviceAddress address, int value) { + fixed (byte* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(value)); } + return 0; } - public unsafe int WriteFloat(DeviceAddress address, float value) - { - fixed (byte* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(*(int*)(&value))); + public unsafe int WriteFloat(DeviceAddress address, float value) { + fixed (byte* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(*(int*) (&value))); } + return 0; } - public int WriteString(DeviceAddress address, string str) - { + public int WriteString(DeviceAddress address, string str) { byte[] b = Encoding.ASCII.GetBytes(str); int index = address.CacheIndex; Array.Copy(_cache, index, b, 0, b.Length); return 0; } - public int WriteValue(DeviceAddress address, object value) - { + public int WriteValue(DeviceAddress address, object value) { return this.WriteValueEx(address, value); } - public byte[] ReadBytes(DeviceAddress address, ushort size) - { + public byte[] ReadBytes(DeviceAddress address, ushort size) { byte[] bytes = new byte[size]; Array.Copy(_cache, address.CacheIndex, bytes, 0, size); return bytes; } - public int WriteBytes(DeviceAddress address, byte[] bit) - { - if (bit != null && bit.Length > 0) - { + public int WriteBytes(DeviceAddress address, byte[] bit) { + if (bit != null && bit.Length > 0) { Array.Copy(bit, 0, _cache, address.CacheIndex, bit.Length); return 0; } + return -1; } - } - public sealed class ShortCacheReader : ICache - { + public sealed class ShortCacheReader : ICache { short[] _cache; - public Array Cache - { - get - { - return _cache; - } + + public Array Cache { + get { return _cache; } } - public int ByteCount - { + public int ByteCount { get { return 2; } } int _size; - public int Size - { - get - { - return _size; - } - set - { + + public int Size { + get { return _size; } + set { _size = value; this._cache = new short[_size]; } } - public ShortCacheReader() - { - } + public ShortCacheReader() { } - public ShortCacheReader(int size) - { + public ShortCacheReader(int size) { this.Size = size; } - public int GetOffset(DeviceAddress start, DeviceAddress end) - { + public int GetOffset(DeviceAddress start, DeviceAddress end) { return start.Area == end.Area && start.DBNumber == end.DBNumber ? start.Start - end.Start : ushort.MaxValue; } - public ItemData ReadInt32(DeviceAddress address) - { + public ItemData ReadInt32(DeviceAddress address) { int startIndex = address.CacheIndex; int result; - if (startIndex == _cache.Length - 1) - { + if (startIndex == _cache.Length - 1) { result = _cache[startIndex]; + } else { + result = (_cache[startIndex + 1] << 16) | ((ushort) _cache[startIndex]); } - else - { - result = (_cache[startIndex + 1] << 16) | ((ushort)_cache[startIndex]); - } + return new ItemData(result, 0, QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadBit(DeviceAddress address) - { - return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, QUALITIES.QUALITY_GOOD); + public unsafe ItemData ReadBit(DeviceAddress address) { + return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadInt16(DeviceAddress address) - { + public ItemData ReadInt16(DeviceAddress address) { return new ItemData(_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadByte(DeviceAddress address) - { - return new ItemData((byte)_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadByte(DeviceAddress address) { + return new ItemData((byte) _cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadString(DeviceAddress address, ushort size) - { + public ItemData ReadString(DeviceAddress address, ushort size) { byte[] buffer = new byte[size]; Buffer.BlockCopy(_cache, 2 * address.CacheIndex, buffer, 0, size); return new ItemData(Encoding.ASCII.GetString(buffer).Trim(), 0, QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadFloat(DeviceAddress address) - { + public unsafe ItemData ReadFloat(DeviceAddress address) { int startIndex = address.CacheIndex; int result; - if (startIndex == _cache.Length - 1) - { + if (startIndex == _cache.Length - 1) { result = _cache[startIndex]; + } else { + result = (_cache[startIndex] << 16) | ((ushort) _cache[startIndex + 1]); } - else - { - result = (_cache[startIndex] << 16) | ((ushort)_cache[startIndex + 1]); - } - return new ItemData(*(((float*)&result)), 0, QUALITIES.QUALITY_GOOD); + + return new ItemData(*(((float*) &result)), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadValue(DeviceAddress address) - { + public ItemData ReadValue(DeviceAddress address) { return this.ReadValueEx(address); } - public int WriteBit(DeviceAddress address, bool bit) - { - _cache[address.CacheIndex] |= (short)(1 << address.Bit); + public int WriteBit(DeviceAddress address, bool bit) { + _cache[address.CacheIndex] |= (short) (1 << address.Bit); return 0; } - public int WriteBits(DeviceAddress address, byte bits) - { + public int WriteBits(DeviceAddress address, byte bits) { _cache[address.CacheIndex] = bits; return 0; } - public unsafe int WriteInt16(DeviceAddress address, short value) - { + public unsafe int WriteInt16(DeviceAddress address, short value) { _cache[address.CacheIndex] = value; return 0; } - public unsafe int WriteInt32(DeviceAddress address, int value) - { - fixed (short* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), value); + public unsafe int WriteInt32(DeviceAddress address, int value) { + fixed (short* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), value); } + return 0; } - public unsafe int WriteFloat(DeviceAddress address, float value) - { - fixed (short* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), *(int*)&value); + public unsafe int WriteFloat(DeviceAddress address, float value) { + fixed (short* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), *(int*) &value); } + return 0; } - public int WriteString(DeviceAddress address, string str) - { + public int WriteString(DeviceAddress address, string str) { byte[] b = Encoding.ASCII.GetBytes(str); int index = address.CacheIndex; Buffer.BlockCopy(_cache, index, b, 0, b.Length); return 0; } - public int WriteValue(DeviceAddress address, object value) - { + public int WriteValue(DeviceAddress address, object value) { return this.WriteValueEx(address, value); } - public byte[] ReadBytes(DeviceAddress address, ushort size) - { + public byte[] ReadBytes(DeviceAddress address, ushort size) { byte[] bytes = new byte[2 * size]; Buffer.BlockCopy(_cache, address.CacheIndex, bytes, 0, bytes.Length); return bytes; } - public int WriteBytes(DeviceAddress address, byte[] bit) - { - if (bit != null && bit.Length > 0) - { + public int WriteBytes(DeviceAddress address, byte[] bit) { + if (bit != null && bit.Length > 0) { Buffer.BlockCopy(bit, 0, _cache, address.CacheIndex, bit.Length); return 0; } + return -1; } } - public sealed class NetShortCacheReader : ICache - { + public sealed class NetShortCacheReader : ICache { short[] _cache; - public Array Cache - { - get - { - return _cache; - } + + public Array Cache { + get { return _cache; } } - public int ByteCount - { + public int ByteCount { get { return 2; } } int _size; - public int Size - { - get - { - return _size; - } - set - { + + public int Size { + get { return _size; } + set { _size = value; this._cache = new short[_size]; } } - public NetShortCacheReader() - { - } + public NetShortCacheReader() { } - public NetShortCacheReader(int size) - { + public NetShortCacheReader(int size) { this.Size = size; } - public int GetOffset(DeviceAddress start, DeviceAddress end) - { + public int GetOffset(DeviceAddress start, DeviceAddress end) { return start.Area == end.Area && start.DBNumber == end.DBNumber ? start.Start - end.Start : ushort.MaxValue; } - public ItemData ReadInt32(DeviceAddress address) - { + public ItemData ReadInt32(DeviceAddress address) { int startIndex = address.CacheIndex; int result; - if (startIndex == _cache.Length - 1) - { + if (startIndex == _cache.Length - 1) { result = _cache[startIndex]; + } else { + result = (IPAddress.HostToNetworkOrder(_cache[startIndex]) << 16) | + ((ushort) IPAddress.HostToNetworkOrder(_cache[startIndex + 1])); } - else - { - result = (IPAddress.HostToNetworkOrder(_cache[startIndex]) << 16) | ((ushort)IPAddress.HostToNetworkOrder(_cache[startIndex + 1])); - } + return new ItemData(result, 0, QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadBit(DeviceAddress address) - { - return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, QUALITIES.QUALITY_GOOD); + public unsafe ItemData ReadBit(DeviceAddress address) { + return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadInt16(DeviceAddress address) - { - return new ItemData(IPAddress.HostToNetworkOrder(_cache[address.CacheIndex]), 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadInt16(DeviceAddress address) { + return new ItemData(IPAddress.HostToNetworkOrder(_cache[address.CacheIndex]), 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadByte(DeviceAddress address) - { - return new ItemData((byte)IPAddress.HostToNetworkOrder(_cache[address.CacheIndex]), 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadByte(DeviceAddress address) { + return new ItemData((byte) IPAddress.HostToNetworkOrder(_cache[address.CacheIndex]), 0, + QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadString(DeviceAddress address, ushort size) - { + public unsafe ItemData ReadString(DeviceAddress address, ushort size) { short[] sarray = new short[size / 2]; int index = address.CacheIndex; - for (int i = 0; i < sarray.Length; i++) - { + for (int i = 0; i < sarray.Length; i++) { sarray[i] = IPAddress.HostToNetworkOrder(_cache[index + i]); } + byte[] buffer = new byte[size]; Buffer.BlockCopy(sarray, 0, buffer, 0, size); return new ItemData(Encoding.ASCII.GetString(buffer).Trim(), 0, QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadFloat(DeviceAddress address) - { + public unsafe ItemData ReadFloat(DeviceAddress address) { int startIndex = address.CacheIndex; int result; - if (startIndex == _cache.Length - 1) - { + if (startIndex == _cache.Length - 1) { result = _cache[startIndex]; + } else { + result = (IPAddress.HostToNetworkOrder(_cache[startIndex]) << 16) | + ((ushort) IPAddress.HostToNetworkOrder(_cache[startIndex + 1])); } - else - { - result = (IPAddress.HostToNetworkOrder(_cache[startIndex]) << 16) | ((ushort)IPAddress.HostToNetworkOrder(_cache[startIndex + 1])); - } - return new ItemData(*(((float*)&result)), 0, QUALITIES.QUALITY_GOOD); + + return new ItemData(*(((float*) &result)), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadValue(DeviceAddress address) - { + public ItemData ReadValue(DeviceAddress address) { return this.ReadValueEx(address); } - public int WriteBit(DeviceAddress address, bool bit) - { - _cache[address.CacheIndex] |= (short)(1 << address.Bit.BitSwap()); + public int WriteBit(DeviceAddress address, bool bit) { + _cache[address.CacheIndex] |= (short) (1 << address.Bit.BitSwap()); return 0; } - public int WriteBits(DeviceAddress address, byte bits) - { + public int WriteBits(DeviceAddress address, byte bits) { _cache[address.CacheIndex] = bits; return 0; } - public unsafe int WriteInt16(DeviceAddress address, short value) - { + public unsafe int WriteInt16(DeviceAddress address, short value) { _cache[address.CacheIndex] = value; return 0; } - public unsafe int WriteInt32(DeviceAddress address, int value) - { - fixed (short* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(value)); + public unsafe int WriteInt32(DeviceAddress address, int value) { + fixed (short* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(value)); } + return 0; } - public unsafe int WriteFloat(DeviceAddress address, float value) - { - fixed (short* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(*(int*)&value)); + public unsafe int WriteFloat(DeviceAddress address, float value) { + fixed (short* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), IPAddress.HostToNetworkOrder(*(int*) &value)); } + return 0; } - public int WriteString(DeviceAddress address, string str) - { + public int WriteString(DeviceAddress address, string str) { byte[] b = Encoding.ASCII.GetBytes(str); int index = address.CacheIndex; Buffer.BlockCopy(_cache, index, b, 0, b.Length); return 0; } - public int WriteValue(DeviceAddress address, object value) - { + public int WriteValue(DeviceAddress address, object value) { return this.WriteValueEx(address, value); } - public byte[] ReadBytes(DeviceAddress address, ushort size) - { + public byte[] ReadBytes(DeviceAddress address, ushort size) { byte[] bytes = new byte[2 * size]; Buffer.BlockCopy(_cache, address.CacheIndex, bytes, 0, bytes.Length); return bytes; } - public int WriteBytes(DeviceAddress address, byte[] bit) - { - if (bit != null && bit.Length > 0) - { + public int WriteBytes(DeviceAddress address, byte[] bit) { + if (bit != null && bit.Length > 0) { Buffer.BlockCopy(bit, 0, _cache, address.CacheIndex, bit.Length); return 0; } + return -1; } } - public sealed class IntCacheReader : ICache - { + public sealed class IntCacheReader : ICache { int[] _cache; - public Array Cache - { - get - { - return _cache; - } + public Array Cache { + get { return _cache; } } - public int ByteCount - { + public int ByteCount { get { return 4; } } int _size; - public int Size - { - get - { - return _size; - } - set - { + + public int Size { + get { return _size; } + set { _size = value; this._cache = new int[_size]; } } - public IntCacheReader() - { - } + public IntCacheReader() { } - public IntCacheReader(int size) - { + public IntCacheReader(int size) { this.Size = size; } - public int GetOffset(DeviceAddress start, DeviceAddress end) - { + public int GetOffset(DeviceAddress start, DeviceAddress end) { return start.Area == end.Area && start.DBNumber == end.DBNumber ? start.Start - end.Start : ushort.MaxValue; } - public ItemData ReadInt32(DeviceAddress address) - { - + public ItemData ReadInt32(DeviceAddress address) { return new ItemData(_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadBit(DeviceAddress address) - { - return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, QUALITIES.QUALITY_GOOD); + public unsafe ItemData ReadBit(DeviceAddress address) { + return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadInt16(DeviceAddress address) - { - return new ItemData((short)(_cache[address.CacheIndex]), 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadInt16(DeviceAddress address) { + return new ItemData((short) (_cache[address.CacheIndex]), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadByte(DeviceAddress address) - { - return new ItemData((byte)_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadByte(DeviceAddress address) { + return new ItemData((byte) _cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadString(DeviceAddress address, ushort size) - { + public ItemData ReadString(DeviceAddress address, ushort size) { byte[] buffer = new byte[size]; Buffer.BlockCopy(_cache, 4 * address.CacheIndex, buffer, 0, size); return new ItemData(Encoding.ASCII.GetString(buffer).Trim(), 0, QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadFloat(DeviceAddress address) - { + public unsafe ItemData ReadFloat(DeviceAddress address) { int result = _cache[address.CacheIndex]; - return new ItemData(*(((float*)&result)), 0, QUALITIES.QUALITY_GOOD);//强制将4字节转换为浮点格式 + return new ItemData(*(((float*) &result)), 0, QUALITIES.QUALITY_GOOD); //强制将4字节转换为浮点格式 } - public ItemData ReadValue(DeviceAddress address) - { + public ItemData ReadValue(DeviceAddress address) { return this.ReadValueEx(address); } - public int WriteBit(DeviceAddress address, bool bit) - { + public int WriteBit(DeviceAddress address, bool bit) { _cache[address.CacheIndex] |= (1 << address.Bit); return 0; } - public int WriteBits(DeviceAddress address, byte bits) - { + public int WriteBits(DeviceAddress address, byte bits) { _cache[address.CacheIndex] = bits; return 0; } - public unsafe int WriteInt16(DeviceAddress address, short value) - { + public unsafe int WriteInt16(DeviceAddress address, short value) { _cache[address.CacheIndex] = value; return 0; } - public unsafe int WriteInt32(DeviceAddress address, int value) - { + public unsafe int WriteInt32(DeviceAddress address, int value) { _cache[address.CacheIndex] = value; return 0; } - public unsafe int WriteFloat(DeviceAddress address, float value) - { - fixed (int* p1 = _cache) - { - Marshal.WriteInt32((IntPtr)(p1 + address.CacheIndex), *(int*)&value); + public unsafe int WriteFloat(DeviceAddress address, float value) { + fixed (int* p1 = _cache) { + Marshal.WriteInt32((IntPtr) (p1 + address.CacheIndex), *(int*) &value); } + return 0; } - public int WriteString(DeviceAddress address, string str) - { + public int WriteString(DeviceAddress address, string str) { byte[] b = Encoding.ASCII.GetBytes(str); int index = address.CacheIndex; Buffer.BlockCopy(_cache, index, b, 0, b.Length); return 0; } - public int WriteValue(DeviceAddress address, object value) - { + public int WriteValue(DeviceAddress address, object value) { return this.WriteValueEx(address, value); } - public byte[] ReadBytes(DeviceAddress address, ushort size) - { + public byte[] ReadBytes(DeviceAddress address, ushort size) { byte[] bytes = new byte[4 * size]; Buffer.BlockCopy(_cache, address.CacheIndex, bytes, 0, bytes.Length); return bytes; } - public int WriteBytes(DeviceAddress address, byte[] bit) - { - if (bit != null && bit.Length > 0) - { + public int WriteBytes(DeviceAddress address, byte[] bit) { + if (bit != null && bit.Length > 0) { Buffer.BlockCopy(bit, 0, _cache, address.CacheIndex, bit.Length); return 0; } + return -1; } } - public sealed class FloatCacheReader : ICache - { + public sealed class FloatCacheReader : ICache { float[] _cache; - public Array Cache - { - get - { - return _cache; - } + public Array Cache { + get { return _cache; } } - public int ByteCount - { + public int ByteCount { get { return 4; } } int _size; - public int Size - { - get - { - return _size; - } - set - { + + public int Size { + get { return _size; } + set { _size = value; this._cache = new float[_size]; } } - public FloatCacheReader() - { - } + public FloatCacheReader() { } - public FloatCacheReader(int size) - { + public FloatCacheReader(int size) { this.Size = size; } - public int GetOffset(DeviceAddress start, DeviceAddress end) - { + public int GetOffset(DeviceAddress start, DeviceAddress end) { return start.Area == end.Area && start.DBNumber == end.DBNumber ? start.Start - end.Start : ushort.MaxValue; } - public ItemData ReadInt32(DeviceAddress address) - { - - return new ItemData((int)_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadInt32(DeviceAddress address) { + return new ItemData((int) _cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadBit(DeviceAddress address) - { - return new ItemData(((int)_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, QUALITIES.QUALITY_GOOD); + public unsafe ItemData ReadBit(DeviceAddress address) { + return new ItemData(((int) _cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, + QUALITIES.QUALITY_GOOD); } - public ItemData ReadInt16(DeviceAddress address) - { - return new ItemData((short)(_cache[address.CacheIndex]), 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadInt16(DeviceAddress address) { + return new ItemData((short) (_cache[address.CacheIndex]), 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadByte(DeviceAddress address) - { - return new ItemData((byte)_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); + public ItemData ReadByte(DeviceAddress address) { + return new ItemData((byte) _cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadString(DeviceAddress address, ushort size) - { + public ItemData ReadString(DeviceAddress address, ushort size) { byte[] buffer = new byte[size]; Buffer.BlockCopy(_cache, 4 * address.CacheIndex, buffer, 0, size); return new ItemData(Encoding.ASCII.GetString(buffer).Trim(), 0, QUALITIES.QUALITY_GOOD); } - public unsafe ItemData ReadFloat(DeviceAddress address) - { + public unsafe ItemData ReadFloat(DeviceAddress address) { return new ItemData(_cache[address.CacheIndex], 0, QUALITIES.QUALITY_GOOD); } - public ItemData ReadValue(DeviceAddress address) - { + public ItemData ReadValue(DeviceAddress address) { return this.ReadValueEx(address); } - public int WriteBit(DeviceAddress address, bool bit) - { - _cache[address.CacheIndex] = (int)_cache[address.CacheIndex] | (1 << address.Bit); + public int WriteBit(DeviceAddress address, bool bit) { + _cache[address.CacheIndex] = (int) _cache[address.CacheIndex] | (1 << address.Bit); return 0; } - public int WriteBits(DeviceAddress address, byte bits) - { + public int WriteBits(DeviceAddress address, byte bits) { _cache[address.CacheIndex] = bits; return 0; } - public unsafe int WriteInt16(DeviceAddress address, short value) - { + public unsafe int WriteInt16(DeviceAddress address, short value) { _cache[address.CacheIndex] = value; return 0; } - public unsafe int WriteInt32(DeviceAddress address, int value) - { + public unsafe int WriteInt32(DeviceAddress address, int value) { _cache[address.CacheIndex] = value; return 0; } - public unsafe int WriteFloat(DeviceAddress address, float value) - { + public unsafe int WriteFloat(DeviceAddress address, float value) { _cache[address.CacheIndex] = value; return 0; } - public int WriteString(DeviceAddress address, string str) - { + public int WriteString(DeviceAddress address, string str) { byte[] b = Encoding.ASCII.GetBytes(str); int index = address.CacheIndex; Buffer.BlockCopy(_cache, index, b, 0, b.Length); return 0; } - public int WriteValue(DeviceAddress address, object value) - { + public int WriteValue(DeviceAddress address, object value) { return this.WriteValueEx(address, value); } - public byte[] ReadBytes(DeviceAddress address, ushort size) - { + public byte[] ReadBytes(DeviceAddress address, ushort size) { byte[] bytes = new byte[4 * size]; Buffer.BlockCopy(_cache, address.CacheIndex, bytes, 0, bytes.Length); return bytes; } - public int WriteBytes(DeviceAddress address, byte[] bit) - { - if (bit != null && bit.Length > 0) - { + public int WriteBytes(DeviceAddress address, byte[] bit) { + if (bit != null && bit.Length > 0) { Buffer.BlockCopy(bit, 0, _cache, address.CacheIndex, bit.Length); return 0; } + return -1; } } -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/Condition.cs b/SCADA/Program/DataService/Condition.cs index 1a0c23d..b4415e0 100644 --- a/SCADA/Program/DataService/Condition.cs +++ b/SCADA/Program/DataService/Condition.cs @@ -2,83 +2,55 @@ using System.Collections.Generic; using System.ComponentModel; -namespace DataService -{ +namespace DataService { public delegate void AlarmEventHandler(object sender, AlarmItem e); - public interface IEvent - { + public interface IEvent { bool IsEnabled { get; set; } bool IsAcked { get; set; } - bool IsActived { get; set; } + bool IsActivated { get; set; } Severity Severity { get; } EventType EventType { get; } DateTime LastActive { get; set; } string Comment { get; } } - public abstract class ICondition : IEvent, IDisposable, IComparable, IEquatable - { + public abstract class ICondition : IEvent, IDisposable, IComparable, IEquatable { public const string ALARMSTOP = "Alarm Clear"; - protected bool _enable, _ack, _active; + + protected bool _enable, + _ack, + _active; + protected int _id; protected DateTime _timeStamp; protected SubAlarmType _tempType; protected SubCondition[] _subConditions; - public int ID - { - get - { - return _id; - } - set - { - _id = value; - } + public int ID { + get { return _id; } + set { _id = value; } } - public bool IsEnabled - { - get - { - return _enable; - } - set - { - _enable = value; - } + public bool IsEnabled { + get { return _enable; } + set { _enable = value; } } - public bool IsActived - { - get - { - return _active; - } - set - { - _active = value; - } + public bool IsActivated { + get { return _active; } + set { _active = value; } } - public bool IsAcked - { - get - { - return _ack; - } - set - { + public bool IsAcked { + get { return _ack; } + set { _ack = value; - if (_ack) - { + if (_ack) { _tempType = SubAlarmType.None; _lastAckTime = DateTime.Now; - if (_ack && AlarmAck != null) - { - foreach (EventHandler deleg in AlarmAck.GetInvocationList()) - { + if (_ack && AlarmAck != null) { + foreach (EventHandler deleg in AlarmAck.GetInvocationList()) { deleg.BeginInvoke(this, EventArgs.Empty, null, null); } } @@ -86,192 +58,109 @@ namespace DataService } } - public abstract AlarmType AlarmType - { - get; - } + public abstract AlarmType AlarmType { get; } - public EventType EventType - { - get - { - return EventType.ConditionEvent; - } + public EventType EventType { + get { return EventType.ConditionEvent; } } protected ConditionType _conditionType; - public ConditionType ConditionType - { - get - { - return _conditionType; - } - set - { - _conditionType = value; - } + + public ConditionType ConditionType { + get { return _conditionType; } + set { _conditionType = value; } } - protected DateTime _lastAckTime, _condLastActive, _lastInactive; - public DateTime LastAckTime - { - get - { - return _lastAckTime; - } - set - { - _lastAckTime = value; - } + protected DateTime _lastAckTime, + _condLastActive, + _lastInactive; + + public DateTime LastAckTime { + get { return _lastAckTime; } + set { _lastAckTime = value; } } - public DateTime SubCondLastActive - { - get - { - return _current.StartTime; - } + public DateTime SubCondLastActive { + get { return _current.StartTime; } //set //{ // _subCondLastActive = value; //} } - public DateTime LastActive - { - get - { - return _condLastActive; - } - set - { - _condLastActive = value; - } + public DateTime LastActive { + get { return _condLastActive; } + set { _condLastActive = value; } } - public DateTime LastInactive - { - get - { - return _lastInactive; - } - set - { - _lastInactive = value; - } + public DateTime LastInactive { + get { return _lastInactive; } + set { _lastInactive = value; } } protected AlarmItem _current; protected SubAlarmType _activeSub; - public SubAlarmType ActiveSubCondition - { - get - { - return _activeSub; - } - protected set - { - _activeSub = value; - } - } - public Severity Severity - { - get - { - return _current.Severity; - } + public SubAlarmType ActiveSubCondition { + get { return _activeSub; } + protected set { _activeSub = value; } } - public string Message - { - get - { - return _current.AlarmText; - } + public Severity Severity { + get { return _current.Severity; } } - public abstract string Value - { - get; + public string Message { + get { return _current.AlarmText; } } + public abstract string Value { get; } + protected float _para; - public float Para - { - get - { - return _para; - } - set - { - _para = value; - } + + public float Para { + get { return _para; } + set { _para = value; } } protected float _deadBand; - public float DeadBand - { - get - { - return _deadBand; - } - set - { - _deadBand = value; - } + + public float DeadBand { + get { return _deadBand; } + set { _deadBand = value; } } protected int _delay; - public int Delay - { - get - { - return _delay; - } - set - { - _delay = value; - } + + public int Delay { + get { return _delay; } + set { _delay = value; } } protected string _comment; - public string Comment - { - get - { - return _comment; - } - set - { - _comment = value; - } + + public string Comment { + get { return _comment; } + set { _comment = value; } } protected string _source; - public string Source - { - get - { - return _source; - } + + public string Source { + get { return _source; } } - public IList SubConditions - { - get - { - return _subConditions; - } + public IList SubConditions { + get { return _subConditions; } } public AlarmEventHandler AlarmActive; public EventHandler AlarmAck; - protected ICondition(int id, ConditionType conditionType, string source, string comment, float para, float deadBand, int delay) - { + protected ICondition(int id, ConditionType conditionType, string source, string comment, float para, + float deadBand, int delay) { this._id = id; this._conditionType = conditionType; this._para = para; @@ -290,47 +179,36 @@ namespace DataService protected abstract void OnInActive(Storage value); - public int CompareTo(ICondition other) - { - int comp1 = ((int)this.Severity).CompareTo((int)other.Severity); + public int CompareTo(ICondition other) { + int comp1 = ((int) this.Severity).CompareTo((int) other.Severity); return comp1 == 0 ? this.LastActive.CompareTo(other.LastActive) : -comp1; } - public bool Equals(ICondition other) - { + public bool Equals(ICondition other) { if (other == null) return false; return this._id == other._id; } - public virtual void Dispose() - { + public virtual void Dispose() { _current = null; AlarmAck = null; - AlarmActive = null; ; + AlarmActive = null; + ; } } - public abstract class SimpleCondition : ICondition, INotifyPropertyChanged - { + public abstract class SimpleCondition : ICondition, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; - public override string Value - { - get - { - return _tag == null ? null : _tag.ToString(); - } + public override string Value { + get { return _tag == null ? null : _tag.ToString(); } } protected ITag _tag; - public ITag Tag - { - get - { - return _tag; - } - set - { + + public ITag Tag { + get { return _tag; } + set { if (_tag != null) _tag.ValueChanging -= CheckAlarm; _tag = value; @@ -339,75 +217,63 @@ namespace DataService } } - protected SimpleCondition(int id, ConditionType conditionType, string source, string comment, float para, float deadBand, int delay) : - base(id, conditionType, source, comment, para, deadBand, delay) - { - } + protected SimpleCondition(int id, ConditionType conditionType, string source, string comment, float para, + float deadBand, int delay) : + base(id, conditionType, source, comment, para, deadBand, delay) { } - protected override void OnActive(SubCondition condition, Storage value, DateTime timeStamp) - { - if (condition.SubAlarmType != ActiveSubCondition) - { - if (condition.SubAlarmType != _tempType) - { + protected override void OnActive(SubCondition condition, Storage value, DateTime timeStamp) { + if (condition.SubAlarmType != ActiveSubCondition) { + if (condition.SubAlarmType != _tempType) { _timeStamp = timeStamp; _tempType = condition.SubAlarmType; } - if (_delay == 0 || (timeStamp - _timeStamp).TotalMilliseconds > _delay) - { - if (ActiveSubCondition == SubAlarmType.None) - { + + if (_delay == 0 || (timeStamp - _timeStamp).TotalMilliseconds > _delay) { + if (ActiveSubCondition == SubAlarmType.None) { _active = true; _condLastActive = timeStamp; } + _ack = false; ActiveSubCondition = condition.SubAlarmType; _current.Duration = timeStamp - SubCondLastActive; - _current = new AlarmItem(timeStamp, condition.Message, _tag.GetValue(value), ActiveSubCondition, condition.Severity, _id, _source); - if (AlarmActive != null) - { - foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) - { + _current = new AlarmItem(timeStamp, condition.Message, _tag.GetValue(value), ActiveSubCondition, + condition.Severity, _id, _source); + if (AlarmActive != null) { + foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) { deleg.BeginInvoke(this, _current, null, null); } } + RaiseChanged("Value"); } - } - else - { + } else { RaiseChanged("Value"); } } - protected override void OnInActive(Storage value) - { - if (ActiveSubCondition != SubAlarmType.None) - { + protected override void OnInActive(Storage value) { + if (ActiveSubCondition != SubAlarmType.None) { _active = false; ActiveSubCondition = SubAlarmType.None; _current.Duration = DateTime.Now - SubCondLastActive; - _current = new AlarmItem(DateTime.Now, string.Concat("【", _current.AlarmText, "】", ALARMSTOP), _tag.GetValue(value), SubAlarmType.None, Severity.Normal, _id, _source); - if (AlarmActive != null) - { - foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) - { + _current = new AlarmItem(DateTime.Now, string.Concat("【", _current.AlarmText, "】", ALARMSTOP), + _tag.GetValue(value), SubAlarmType.None, Severity.Normal, _id, _source); + if (AlarmActive != null) { + foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) { deleg.BeginInvoke(this, _current, null, null); } } } } - protected void RaiseChanged(string property) - { - if (PropertyChanged != null) - { + protected void RaiseChanged(string property) { + if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } - public override void Dispose() - { + public override void Dispose() { base.Dispose(); PropertyChanged = null; if (_tag != null) @@ -416,150 +282,112 @@ namespace DataService protected abstract void CheckAlarm(object sender, ValueChangingEventArgs e); - public override AlarmType AlarmType - { - get - { - return AlarmType.None; - } + public override AlarmType AlarmType { + get { return AlarmType.None; } } - public override bool AddSubCondition(SubCondition condition) - { + public override bool AddSubCondition(SubCondition condition) { return true; } - public override bool RemoveSubCondition(SubCondition condition) - { + public override bool RemoveSubCondition(SubCondition condition) { return true; } } - public sealed class ComplexCondition : ICondition, INotifyPropertyChanged - { + public sealed class ComplexCondition : ICondition, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; - public override string Value - { - get - { - return Convert.ToString(_current.AlarmValue); - } + public override string Value { + get { return Convert.ToString(_current.AlarmValue); } } public ComplexCondition(int id, string source, string comment, float deadBand, int delay) : - base(id, ConditionType.Absolute, source, comment, 0f, deadBand, delay) - { - _subConditions = new SubCondition[1] - { - new SubCondition(SubAlarmType.Dsc) - }; + base(id, ConditionType.Absolute, source, comment, 0f, deadBand, delay) { + _subConditions = new SubCondition[1] {new SubCondition(SubAlarmType.Dsc)}; } - protected override void OnActive(SubCondition condition, Storage value, DateTime timeStamp) - { - if (condition.SubAlarmType != ActiveSubCondition) - { - if (condition.SubAlarmType != _tempType) - { + protected override void OnActive(SubCondition condition, Storage value, DateTime timeStamp) { + if (condition.SubAlarmType != ActiveSubCondition) { + if (condition.SubAlarmType != _tempType) { _timeStamp = timeStamp; _tempType = condition.SubAlarmType; } - if (_delay == 0 || (timeStamp - _timeStamp).TotalMilliseconds > _delay) - { - if (ActiveSubCondition == SubAlarmType.None) - { + + if (_delay == 0 || (timeStamp - _timeStamp).TotalMilliseconds > _delay) { + if (ActiveSubCondition == SubAlarmType.None) { _active = true; _condLastActive = timeStamp; } + _ack = false; ActiveSubCondition = condition.SubAlarmType; _current.Duration = timeStamp - SubCondLastActive; - _current = new AlarmItem(timeStamp, condition.Message, true, ActiveSubCondition, condition.Severity, _id, _source); - if (AlarmActive != null) - { - foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) - { + _current = new AlarmItem(timeStamp, condition.Message, true, ActiveSubCondition, condition.Severity, + _id, _source); + if (AlarmActive != null) { + foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) { deleg.BeginInvoke(this, _current, null, null); } } - if (PropertyChanged != null) - { + + if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Value")); } } - } - else - { - if (PropertyChanged != null) - { + } else { + if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Value")); } } } - protected override void OnInActive(Storage value) - { - if (ActiveSubCondition != SubAlarmType.None) - { + protected override void OnInActive(Storage value) { + if (ActiveSubCondition != SubAlarmType.None) { _active = false; ActiveSubCondition = SubAlarmType.None; _current.Duration = DateTime.Now - SubCondLastActive; - _current = new AlarmItem(DateTime.Now, string.Concat("【", _current.AlarmText, "】", ALARMSTOP), false, SubAlarmType.None, Severity.Normal, _id, _source); - if (AlarmActive != null) - { - foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) - { + _current = new AlarmItem(DateTime.Now, string.Concat("【", _current.AlarmText, "】", ALARMSTOP), false, + SubAlarmType.None, Severity.Normal, _id, _source); + if (AlarmActive != null) { + foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) { deleg.BeginInvoke(this, _current, null, null); } } } } - public Action SetFunction(Delegate tagChanged) - { + public Action SetFunction(Delegate tagChanged) { var _func = tagChanged as Func; - if (_func != null) - { - return delegate - { - if (_enable) - { + if (_func != null) { + return delegate { + if (_enable) { SubCondition condition = _subConditions[0]; - if (condition.IsEnabled) - { - if (_func()) - { + if (condition.IsEnabled) { + if (_func()) { OnActive(condition, Storage.Empty, DateTime.Now); return; } } + OnInActive(Storage.Empty); } }; - } - else + } else return null; } - public override void Dispose() - { + public override void Dispose() { base.Dispose(); PropertyChanged = null; } - public override AlarmType AlarmType - { - get - { - return AlarmType.Complex; - } + public override AlarmType AlarmType { + get { return AlarmType.Complex; } } - public override bool AddSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool AddSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.Dsc: _subConditions[0] = condition; return true; @@ -568,10 +396,8 @@ namespace DataService } } - public override bool RemoveSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool RemoveSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.Dsc: _subConditions[0] = SubCondition.Empty; return true; @@ -579,73 +405,56 @@ namespace DataService return false; } } - } - public sealed class LevelAlarm : SimpleCondition - { - public override AlarmType AlarmType - { + public sealed class LevelAlarm : SimpleCondition { + public override AlarmType AlarmType { get { return AlarmType.Level; } } public LevelAlarm(int id, string source, string comment, float deadBand = 0f, int delay = 0) : - base(id, ConditionType.Absolute, source, comment, 0, deadBand, delay) - { - _subConditions = new SubCondition[4] - { - new SubCondition(SubAlarmType.HiHi), - new SubCondition(SubAlarmType.High), - new SubCondition(SubAlarmType.LoLo), - new SubCondition(SubAlarmType.Low) - }; + base(id, ConditionType.Absolute, source, comment, 0, deadBand, delay) { + _subConditions = new SubCondition[4] { + new SubCondition(SubAlarmType.HiHi), new SubCondition(SubAlarmType.High), + new SubCondition(SubAlarmType.LoLo), new SubCondition(SubAlarmType.Low) + }; } - protected override void CheckAlarm(object sender, ValueChangingEventArgs e) - { - if (_enable) - { + protected override void CheckAlarm(object sender, ValueChangingEventArgs e) { + if (_enable) { SubCondition condition; float value = _tag.ScaleToValue(e.NewValue); - for (int i = 0; i < _subConditions.Length; i++) - { - if (_subConditions[i].IsEnabled) - { + for (int i = 0; i < _subConditions.Length; i++) { + if (_subConditions[i].IsEnabled) { condition = _subConditions[i]; - if (i < 2)//Hi Alarm + if (i < 2) //Hi Alarm { - if (value > condition.Threshold) - { + if (value > condition.Threshold) { OnActive(condition, e.NewValue, e.NewTimeStamp); return; - } - else if (_deadBand > 0 && ActiveSubCondition == condition.SubAlarmType && value > condition.Threshold - _deadBand) - { + } else if (_deadBand > 0 && ActiveSubCondition == condition.SubAlarmType && + value > condition.Threshold - _deadBand) { return; } - } - else//Low Alarm + } else //Low Alarm { - if (value < condition.Threshold) - { + if (value < condition.Threshold) { OnActive(condition, e.NewValue, e.NewTimeStamp); return; - } - else if (_deadBand > 0 && ActiveSubCondition == condition.SubAlarmType && value > condition.Threshold + _deadBand) - { + } else if (_deadBand > 0 && ActiveSubCondition == condition.SubAlarmType && + value > condition.Threshold + _deadBand) { return; } } } } + OnInActive(e.NewValue); } } - public override bool AddSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool AddSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.HiHi: _subConditions[0] = condition; return true; @@ -663,10 +472,8 @@ namespace DataService } } - public override bool RemoveSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool RemoveSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.HiHi: _subConditions[0] = SubCondition.Empty; return true; @@ -685,55 +492,47 @@ namespace DataService } } - public sealed class DevAlarm : SimpleCondition - { - public override AlarmType AlarmType - { + public sealed class DevAlarm : SimpleCondition { + public override AlarmType AlarmType { get { return AlarmType.Dev; } } - public DevAlarm(int id, ConditionType conditionType, string source, string comment, float para, float deadBand = 0f, int delay = 0) : - base(id, conditionType, source, comment, para, deadBand, delay) - { - _subConditions = new SubCondition[2] - { - new SubCondition(SubAlarmType.MajDev), - new SubCondition(SubAlarmType.MinDev) - }; + public DevAlarm(int id, ConditionType conditionType, string source, string comment, float para, + float deadBand = 0f, int delay = 0) : + base(id, conditionType, source, comment, para, deadBand, delay) { + _subConditions = new SubCondition[2] { + new SubCondition(SubAlarmType.MajDev), new SubCondition(SubAlarmType.MinDev) + }; } - protected override void CheckAlarm(object sender, ValueChangingEventArgs e) - { - if (_enable) - { + protected override void CheckAlarm(object sender, ValueChangingEventArgs e) { + if (_enable) { float value = _tag.ScaleToValue(e.NewValue) - _para; SubCondition condition; - for (int i = 0; i < _subConditions.Length; i++) - { - if (_subConditions[i].IsEnabled) - { + for (int i = 0; i < _subConditions.Length; i++) { + if (_subConditions[i].IsEnabled) { condition = _subConditions[i]; - if (value > (_conditionType == ConditionType.Absolute ? condition.Threshold : _para * condition.Threshold)) - { + if (value > (_conditionType == ConditionType.Absolute + ? condition.Threshold + : _para * condition.Threshold)) { OnActive(condition, e.NewValue, e.NewTimeStamp); return; - } - else if (_deadBand > 0 && ActiveSubCondition == condition.SubAlarmType && - ((_conditionType == ConditionType.Absolute && value > condition.Threshold - _deadBand) - || (_conditionType == ConditionType.Percent && value > _para * (condition.Threshold - _deadBand)))) - { + } else if (_deadBand > 0 && ActiveSubCondition == condition.SubAlarmType && + ((_conditionType == ConditionType.Absolute && + value > condition.Threshold - _deadBand) + || (_conditionType == ConditionType.Percent && + value > _para * (condition.Threshold - _deadBand)))) { return; } } } + OnInActive(e.NewValue); } } - public override bool AddSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool AddSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.MajDev: _subConditions[0] = condition; return true; @@ -745,10 +544,8 @@ namespace DataService } } - public override bool RemoveSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool RemoveSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.MajDev: _subConditions[0] = SubCondition.Empty; return true; @@ -761,43 +558,32 @@ namespace DataService } } - public sealed class DigitAlarm : SimpleCondition - { - public override AlarmType AlarmType - { + public sealed class DigitAlarm : SimpleCondition { + public override AlarmType AlarmType { get { return AlarmType.Dsc; } } public DigitAlarm(int id, string source = null, string comment = null, int delay = 0) : - base(id, ConditionType.Absolute, source, comment, 0, 0f, delay) - { - _subConditions = new SubCondition[1] - { - new SubCondition(SubAlarmType.Dsc) - }; + base(id, ConditionType.Absolute, source, comment, 0, 0f, delay) { + _subConditions = new SubCondition[1] {new SubCondition(SubAlarmType.Dsc)}; } - protected override void CheckAlarm(object sender, ValueChangingEventArgs e) - { - if (_enable) - { + protected override void CheckAlarm(object sender, ValueChangingEventArgs e) { + if (_enable) { SubCondition condition = _subConditions[0]; - if (condition.IsEnabled) - { - if (e.NewValue.Boolean == condition.Threshold > 0) - { + if (condition.IsEnabled) { + if (e.NewValue.Boolean == condition.Threshold > 0) { OnActive(condition, e.NewValue, e.NewTimeStamp); return; } } + OnInActive(e.NewValue); } } - public override bool AddSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool AddSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.Dsc: _subConditions[0] = condition; return true; @@ -806,10 +592,8 @@ namespace DataService } } - public override bool RemoveSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool RemoveSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.Dsc: _subConditions[0] = SubCondition.Empty; return true; @@ -819,58 +603,49 @@ namespace DataService } } - public sealed class WordDigitAlarm : SimpleCondition - { - public override AlarmType AlarmType - { + public sealed class WordDigitAlarm : SimpleCondition { + public override AlarmType AlarmType { get { return AlarmType.WordDsc; } } public WordDigitAlarm(int id, string source = null, string comment = null, int delay = 0) : - base(id, ConditionType.Absolute, source, comment, 0, 0f, delay) - { + base(id, ConditionType.Absolute, source, comment, 0, 0f, delay) { _subConditions = new SubCondition[16]; - for (int i = 0; i < 16; i++) - { + for (int i = 0; i < 16; i++) { _subConditions[i].SubAlarmType = SubAlarmType.Dsc; _subConditions[i].Threshold = i; - }; + } + + ; } - protected override void CheckAlarm(object sender, ValueChangingEventArgs e) - { - if (_enable) - { + protected override void CheckAlarm(object sender, ValueChangingEventArgs e) { + if (_enable) { short newvalue = e.NewValue.Int16; short oldvlaue = e.OldValue.Int16; - if (newvalue == 0 && oldvlaue != 0) - { + if (newvalue == 0 && oldvlaue != 0) { OnInActive(e.NewValue); return; } - for (short i = 0; i < _subConditions.Length; i++) - { + + for (short i = 0; i < _subConditions.Length; i++) { SubCondition condition = _subConditions[i]; - if (condition.IsEnabled) - { + if (condition.IsEnabled) { int mask = 1 << i; int newval = mask & newvalue; int oldval = mask & oldvlaue; - if (newval != 0 && oldval == 0) - { - OnActive(condition, new Storage { Int16 = i }, e.NewTimeStamp); + if (newval != 0 && oldval == 0) { + OnActive(condition, new Storage {Int16 = i}, e.NewTimeStamp); } } } } } - public override bool AddSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool AddSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.Dsc: - int index = (int)condition.Threshold; + int index = (int) condition.Threshold; if (index >= 0 && index < 16) _subConditions[index] = condition; return true; @@ -879,12 +654,10 @@ namespace DataService } } - public override bool RemoveSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool RemoveSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.Dsc: - int index = (int)condition.Threshold; + int index = (int) condition.Threshold; if (index >= 0 && index < 16) _subConditions[index] = SubCondition.Empty; return true; @@ -893,38 +666,34 @@ namespace DataService } } - protected override void OnActive(SubCondition condition, Storage value, DateTime timeStamp) - { - if (ActiveSubCondition == SubAlarmType.None) - { + protected override void OnActive(SubCondition condition, Storage value, DateTime timeStamp) { + if (ActiveSubCondition == SubAlarmType.None) { _active = true; _condLastActive = timeStamp; } + _ack = false; ActiveSubCondition = condition.SubAlarmType; - _current = new AlarmItem(timeStamp, condition.Message, value.Int16, ActiveSubCondition, condition.Severity, _id, _source); - if (AlarmActive != null) - { - foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) - { + _current = new AlarmItem(timeStamp, condition.Message, value.Int16, ActiveSubCondition, condition.Severity, + _id, _source); + if (AlarmActive != null) { + foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) { deleg.BeginInvoke(this, _current, null, null); } } + RaiseChanged("Value"); } - protected override void OnInActive(Storage value) - { - if (ActiveSubCondition != SubAlarmType.None) - { + protected override void OnInActive(Storage value) { + if (ActiveSubCondition != SubAlarmType.None) { _active = false; ActiveSubCondition = SubAlarmType.None; _current.Duration = DateTime.Now - LastActive; - _current = new AlarmItem(DateTime.Now, string.Concat("【", Comment, "】", ALARMSTOP), 0, SubAlarmType.None, Severity.Normal, _id, _source); - if (AlarmActive != null) - { - foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) - { + _current = new AlarmItem(DateTime.Now, string.Concat("【", Comment, "】", ALARMSTOP), 0, + SubAlarmType.None, Severity.Normal, _id, _source); + if (AlarmActive != null) { + foreach (AlarmEventHandler deleg in AlarmActive.GetInvocationList()) { deleg.BeginInvoke(this, _current, null, null); } } @@ -932,41 +701,31 @@ namespace DataService } } - public sealed class QualitiesAlarm : SimpleCondition - { - public override AlarmType AlarmType - { + public sealed class QualitiesAlarm : SimpleCondition { + public override AlarmType AlarmType { get { return AlarmType.Quality; } } public QualitiesAlarm(int id, string source, string comment, int delay = 0) : - base(id, ConditionType.Absolute, source, comment, 0, 0f, delay) - { - _subConditions = new SubCondition[1] - { - new SubCondition(SubAlarmType.BadPV) - }; + base(id, ConditionType.Absolute, source, comment, 0, 0f, delay) { + _subConditions = new SubCondition[1] {new SubCondition(SubAlarmType.BadPV)}; } - protected override void CheckAlarm(object sender, ValueChangingEventArgs e) - { - if (_enable) - { + protected override void CheckAlarm(object sender, ValueChangingEventArgs e) { + if (_enable) { SubCondition condition = _subConditions[0]; - if (condition.IsEnabled) - { + if (condition.IsEnabled) { if (e.Quality != QUALITIES.QUALITY_GOOD) OnActive(condition, e.NewValue, e.NewTimeStamp); return; } + OnInActive(e.NewValue); } } - public override bool AddSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool AddSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.BadPV: _subConditions[0] = condition; return true; @@ -975,10 +734,8 @@ namespace DataService } } - public override bool RemoveSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool RemoveSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.BadPV: _subConditions[0] = SubCondition.Empty; return true; @@ -988,54 +745,43 @@ namespace DataService } } - public sealed class ROCAlarm : SimpleCondition - { - public override AlarmType AlarmType - { + public sealed class ROCAlarm : SimpleCondition { + public override AlarmType AlarmType { get { return AlarmType.ROC; } } public ROCAlarm(int id, string souce, string comment, float deadBand = 0f, int delay = 0) : - base(id, ConditionType.Percent, souce, comment, 0, deadBand, delay) - { - _subConditions = new SubCondition[2] - { - new SubCondition(SubAlarmType.MajROC), - new SubCondition(SubAlarmType.MinROC) - }; + base(id, ConditionType.Percent, souce, comment, 0, deadBand, delay) { + _subConditions = new SubCondition[2] { + new SubCondition(SubAlarmType.MajROC), new SubCondition(SubAlarmType.MinROC) + }; } - protected override void CheckAlarm(object sender, ValueChangingEventArgs e) - { - if (_enable) - { - float value = (float)((_tag.ScaleToValue(e.NewValue) - e.OldValue.Single) / (e.NewTimeStamp - e.OldTimeStamp).TotalMilliseconds); + protected override void CheckAlarm(object sender, ValueChangingEventArgs e) { + if (_enable) { + float value = (float) ((_tag.ScaleToValue(e.NewValue) - e.OldValue.Single) / + (e.NewTimeStamp - e.OldTimeStamp).TotalMilliseconds); SubCondition condition; - for (int i = 0; i < _subConditions.Length; i++) - { - if (_subConditions[i].IsEnabled) - { + for (int i = 0; i < _subConditions.Length; i++) { + if (_subConditions[i].IsEnabled) { condition = _subConditions[i]; - if (value > condition.Threshold) - { + if (value > condition.Threshold) { OnActive(condition, e.NewValue, e.NewTimeStamp); return; - } - else if (_deadBand > 0 && ActiveSubCondition == condition.SubAlarmType && value > condition.Threshold - _deadBand) - { + } else if (_deadBand > 0 && ActiveSubCondition == condition.SubAlarmType && + value > condition.Threshold - _deadBand) { return; } } } + OnInActive(e.NewValue); } } - public override bool AddSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool AddSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.MajROC: _subConditions[0] = condition; return true; @@ -1047,10 +793,8 @@ namespace DataService } } - public override bool RemoveSubCondition(SubCondition condition) - { - switch (condition.SubAlarmType) - { + public override bool RemoveSubCondition(SubCondition condition) { + switch (condition.SubAlarmType) { case SubAlarmType.MajROC: _subConditions[0] = SubCondition.Empty; return true; @@ -1063,8 +807,7 @@ namespace DataService } } - public struct SubCondition - { + public struct SubCondition { public bool IsEnabled; public SubAlarmType SubAlarmType; @@ -1075,8 +818,8 @@ namespace DataService public string Message; - public SubCondition(SubAlarmType type, float threshold = 0f, Severity severity = Severity.Normal, string message = "", bool enabled = true) - { + public SubCondition(SubAlarmType type, float threshold = 0f, Severity severity = Severity.Normal, + string message = "", bool enabled = true) { this.SubAlarmType = type; this.Threshold = threshold; this.Severity = severity; @@ -1084,21 +827,17 @@ namespace DataService this.IsEnabled = enabled; } - public static readonly SubCondition Empty = new SubCondition(SubAlarmType.None, 0f, Severity.Normal, "正常", false); + public static readonly SubCondition Empty = + new SubCondition(SubAlarmType.None, 0f, Severity.Normal, "正常", false); } - public class CompareCondBySource : IComparer - { - public int Compare(ICondition x, ICondition y) - { - if (x == null || x.Source == null) - { + public class CompareCondBySource : IComparer { + public int Compare(ICondition x, ICondition y) { + if (x == null || x.Source == null) { return y == null || y.Source == null ? 0 : 1; - } - else - { + } else { return y == null || y.Source == null ? 1 : x.Source.CompareTo(y.Source); } } } -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/DeviceAddress.cs b/SCADA/Program/DataService/DeviceAddress.cs index 927ec42..6f325d4 100644 --- a/SCADA/Program/DataService/DeviceAddress.cs +++ b/SCADA/Program/DataService/DeviceAddress.cs @@ -1,11 +1,9 @@ using System; using System.Runtime.InteropServices; -namespace DataService -{ +namespace DataService { [StructLayout(LayoutKind.Sequential)] - public struct DeviceAddress : IComparable - { + public struct DeviceAddress : IComparable { public int Area; public int Start; public ushort DBNumber; @@ -14,8 +12,8 @@ namespace DataService public byte Bit; public DataType VarType; - public DeviceAddress(int area, ushort dbnumber, ushort cIndex, int start, ushort size, byte bit, DataType type) - { + public DeviceAddress(int area, ushort dbnumber, ushort cIndex, int start, ushort size, byte bit, + DataType type) { Area = area; DBNumber = dbnumber; CacheIndex = cIndex; @@ -27,17 +25,15 @@ namespace DataService public static readonly DeviceAddress Empty = new DeviceAddress(0, 0, 0, 0, 0, 0, DataType.NONE); - public int CompareTo(DeviceAddress other) - { - return this.Area > other.Area ? 1 : - this.Area < other.Area ? -1 : - this.DBNumber > other.DBNumber ? 1 : - this.DBNumber < other.DBNumber ? -1 : - this.Start > other.Start ? 1 : - this.Start < other.Start ? -1 : - this.Bit > other.Bit ? 1 : - this.Bit < other.Bit ? -1 : 0; + public int CompareTo(DeviceAddress other) { + return Area > other.Area ? 1 : + Area < other.Area ? -1 : + DBNumber > other.DBNumber ? 1 : + DBNumber < other.DBNumber ? -1 : + Start > other.Start ? 1 : + Start < other.Start ? -1 : + Bit > other.Bit ? 1 : + Bit < other.Bit ? -1 : 0; } } - -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/Eval.cs b/SCADA/Program/DataService/Eval.cs index 14cb0eb..988d176 100644 --- a/SCADA/Program/DataService/Eval.cs +++ b/SCADA/Program/DataService/Eval.cs @@ -4,51 +4,46 @@ using System.Linq.Expressions; using System.Reflection; using System.Runtime.InteropServices; -namespace DataService -{ - public class ExpressionEval : IDisposable - { +namespace DataService { + public class ExpressionEval : IDisposable { Expression _param1; List _tagList = new List(); - public List TagList - { - get - { - return _tagList; - } + + public List TagList { + get { return _tagList; } } IDataServer _server; - public ExpressionEval(IDataServer server) - { + public ExpressionEval(IDataServer server) { _server = server; _param1 = Expression.Constant(this); } - public Delegate Eval(string expression) - { + /// + /// 函数表达式 + /// + /// + /// + public Delegate Eval(string expression) { if (string.IsNullOrEmpty(expression)) return null; var lambda = ComplieRpnExp(RpnExpression(expression)); if (lambda != null) return lambda.Compile(); return null; } - public Delegate WriteEval(string expression) - { + public Delegate WriteEval(string expression) { if (_server == null || string.IsNullOrEmpty(expression)) return null; - if (_server[expression.ToUpper()] != null) - { + if (_server[expression.ToUpper()] != null) { return new Func((object value) => { return WriteTag(expression, value); }); } + return null; } - public Func WriteEval(string expression1, string expression2) - { + public Func WriteEval(string expression1, string expression2) { if (_server == null || string.IsNullOrEmpty(expression2)) return null; - if (_server[expression1.ToUpper()] != null) - { + if (_server[expression1.ToUpper()] != null) { var dele = Eval(expression2); var funcbool = dele as Func; if (funcbool != null) @@ -63,12 +58,12 @@ namespace DataService if (funcstring != null) return () => { return WriteTag(expression1, funcstring()); }; } + return null; } - public static bool ValidationExpression(string expression) - { - return true;//可加入正则表达式验证 + public static bool ValidationExpression(string expression) { + return true; //可加入正则表达式验证 } /// @@ -76,10 +71,8 @@ namespace DataService /// /// 操作符 /// 操作运算符,空格返回0,出错返回-1 - private static byte GetOperatorLevel(char strOperator) - { - switch (strOperator) - { + private static byte GetOperatorLevel(char strOperator) { + switch (strOperator) { case '~': return 10; case '*': @@ -109,7 +102,6 @@ namespace DataService //case ':': default: return 0; - } } @@ -118,12 +110,12 @@ namespace DataService /// /// 标准中缀表达式 /// 标准逆波兰表达式 - public static List RpnExpression(string expression) - { + public static List RpnExpression(string expression) { //加入结束标记 //定义出栈和入栈堆栈 - string[] strNum = expression.Split('~', '%', '>', '<', '=', '!', '&', '|', '?', '#', '^', '+', '-', '*', '/', '(', ')'); - if (strNum.Length < 2) return new List() { expression }; + string[] strNum = expression.Split('~', '%', '>', '<', '=', '!', '&', '|', '?', '#', '^', '+', '-', '*', + '/', '(', ')'); + if (strNum.Length < 2) return new List() {expression}; //操作运算符堆栈 Stack oper = new Stack(); //定义输出堆栈 @@ -140,71 +132,60 @@ namespace DataService int intStackCount = 0; //从左到右读取前缀表达式 - while (i < expression.Length) - { + while (i < expression.Length) { //读取一个字符 char strChar = expression[i]; //取字符的运算级别 - if (strChar == '#') { i++; continue; } + if (strChar == '#') { + i++; + continue; + } + byte intLevel = GetOperatorLevel(strChar); if (intLevel == 0) - //数字直接推入输出堆栈 + //数字直接推入输出堆栈 { - while (n++ < strNum.Length) - { - if (strNum[n] != "") - { + while (n++ < strNum.Length) { + if (strNum[n] != "") { output.Add(strNum[n]); i += strNum[n].Length; //移动数组指针 break; } } - } - else //操作字符根据运算字符级别推入运算符堆栈 + } else //操作字符根据运算字符级别推入运算符堆栈 { - if (oper.Count == 0) - { + if (oper.Count == 0) { //运算符堆栈为空,直接推入堆栈 oper.Push(new Operator(strChar, intLevel)); //移动字符读取指针 i++; - } - else - { + } else { op = oper.Peek(); - if (intLevel > op.Level || intLevel == 2) - { + if (intLevel > op.Level || intLevel == 2) { //运算字符比运算符堆栈最后的级别高或者运算符为'('直接推入运算符堆栈 oper.Push(new Operator(strChar, intLevel)); //移动字符读取指针 i++; - } - else - { + } else { //运算字符不高于运算符堆栈最后的级别,则将运算符堆栈出栈,直到比其高为止 intStackCount = oper.Count; - for (int m = 0; m < intStackCount; m++) - { + for (int m = 0; m < intStackCount; m++) { op = oper.Peek(); - if (op.Level >= intLevel) - { + if (op.Level >= intLevel) { //将操作符出栈并压入输入堆栈 char o = op.OperatorStack; - if (!(o == ')' || o == '(')) - { + if (!(o == ')' || o == '(')) { output.Add(o.ToString()); } + oper.Pop(); - if (op.Level == 2) - { + if (op.Level == 2) { //如果操作符堆栈中最后的操作符为'('则停止出栈 i++; break; } - } - else - { + } else { //直到运算符已经高出运算符栈中最后的级别,则入栈 oper.Push(new Operator(strChar, intLevel)); i++; @@ -217,8 +198,7 @@ namespace DataService } intStackCount = oper.Count; - for (int m = 0; m < intStackCount; m++) - { + for (int m = 0; m < intStackCount; m++) { op = oper.Peek(); output.Add(op.OperatorStack.ToString()); oper.Pop(); @@ -232,287 +212,273 @@ namespace DataService /// /// 标准逆波兰表达式 /// 逆波兰表达式的解 - public LambdaExpression ComplieRpnExp(List strNum) - { + public LambdaExpression ComplieRpnExp(List strNum) { _tagList.Clear(); //拆分逆波兰表达式 int intLenth = strNum.Count; if (intLenth == 0) return null; //定义数字堆栈 - try - { + try { Stack number = new Stack(); - for (int i = 0; i < intLenth; i++) - { + for (int i = 0; i < intLenth; i++) { string expr = strNum[i]; - switch (expr) - { + switch (expr) { case "~": - if (number.Count > 0) - { + if (number.Count > 0) { Expression left = number.Pop(); number.Push(Expression.Not(left)); } + break; case "*": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + number.Push(Expression.Multiply(left, right)); } + break; case "/": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + number.Push(Expression.Divide(left, right)); } + break; case "%": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(int)) left = Expression.Convert(left, typeof(int)); if (right.Type != typeof(int)) right = Expression.Convert(right, typeof(int)); } + number.Push(Expression.Modulo(left, right)); } + break; case "+": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type == typeof(string) || right.Type == typeof(string)) - { + if (left.Type == typeof(string) || right.Type == typeof(string)) { if (left.Type != typeof(string)) left = Expression.Convert(left, typeof(object)); if (right.Type != typeof(string)) right = Expression.Convert(right, typeof(object)); - number.Push(Expression.Call(typeof(string).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }), left, right)); - } - else - { - if (left.Type != right.Type) - { + number.Push(Expression.Call( + typeof(string).GetMethod("Concat", new Type[] {typeof(object), typeof(object)}), + left, right)); + } else { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + number.Push(Expression.Add(left, right)); } } + break; case "-": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + number.Push(Expression.Subtract(left, right)); } + break; case ">": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + number.Push(Expression.GreaterThan(left, right)); } + break; case "<": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + number.Push(Expression.LessThan(left, right)); } + break; case "&": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); number.Push(Expression.And(left, right)); } + break; case "^": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); number.Push(Expression.ExclusiveOr(left, right)); } + break; case "|": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); number.Push(Expression.Or(left, right)); } + break; case "=": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + number.Push(Expression.Equal(left, right)); } + break; case "!": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + number.Push(Expression.NotEqual(left, right)); } + break; case "?": - if (number.Count > 1) - { + if (number.Count > 1) { Expression right = number.Pop(); Expression left = number.Pop(); - if (left.Type != right.Type) - { + if (left.Type != right.Type) { if (left.Type != typeof(float)) left = Expression.Convert(left, typeof(float)); if (right.Type != typeof(float)) right = Expression.Convert(right, typeof(float)); } + Expression test = number.Pop(); number.Push(Expression.Condition(test, left, right)); } + break; default: - if (expr[0] == '@') - { - switch (expr.Substring(1).ToUpper()) - { - case "TIME": - { - Expression> f = () => DateTime.Now.ToShortTimeString(); - number.Push(f.Body); - } + if (expr[0] == '@') { + switch (expr.Substring(1).ToUpper()) { + case "TIME": { + Expression> f = () => DateTime.Now.ToShortTimeString(); + number.Push(f.Body); + } goto lab1; - case "DATE": - { - Expression> f = () => DateTime.Now.ToShortDateString(); - number.Push(f.Body); - } + case "DATE": { + Expression> f = () => DateTime.Now.ToShortDateString(); + number.Push(f.Body); + } goto lab1; - case "DATETIME": - { - Expression> f = () => DateTime.Now.ToString(); - number.Push(f.Body); - } + case "DATETIME": { + Expression> f = () => DateTime.Now.ToString(); + number.Push(f.Body); + } goto lab1; - case "APP": - { - Expression> f = () => AppDomain.CurrentDomain.FriendlyName; - number.Push(f.Body); - } + case "APP": { + Expression> f = () => AppDomain.CurrentDomain.FriendlyName; + number.Push(f.Body); + } goto lab1; - case "NAME": - { - Expression> f = () => Environment.MachineName; - number.Push(f.Body); - } + case "NAME": { + Expression> f = () => Environment.MachineName; + number.Push(f.Body); + } goto lab1; - case "PATH": - { - Expression> f = () => Environment.CurrentDirectory; - number.Push(f.Body); - } + case "PATH": { + Expression> f = () => Environment.CurrentDirectory; + number.Push(f.Body); + } goto lab1; - case "USER": - { - Expression> f = () => Environment.UserName; - number.Push(f.Body); - } + case "USER": { + Expression> f = () => Environment.UserName; + number.Push(f.Body); + } goto lab1; - case "REGION": - { - Expression> f = () => System.Globalization.CultureInfo.CurrentCulture.Name; - number.Push(f.Body); - } + case "REGION": { + Expression> f = () => + System.Globalization.CultureInfo.CurrentCulture.Name; + number.Push(f.Body); + } goto lab1; } } + object result; - if (IsConstant(expr, out result)) - { + if (IsConstant(expr, out result)) { number.Push(Expression.Constant(result)); - } - else - { + } else { number.Push(GetTagExpression(expr)); } - lab1: + + lab1: break; } } Expression d = number.Pop(); return Expression.Lambda(d); + } catch (Exception e) { + return null; } - catch (Exception e) { return null; } } MethodInfo _boolinfo = typeof(ExpressionEval).GetMethod("GetBool"); @@ -520,12 +486,10 @@ namespace DataService MethodInfo _intinfo = typeof(ExpressionEval).GetMethod("GetInt"); MethodInfo _stringinfo = typeof(ExpressionEval).GetMethod("GetString"); - public Expression GetTagExpression(string tagName) - { + public Expression GetTagExpression(string tagName) { if (_server == null) return Expression.Empty(); ITag tag = _server[tagName]; - switch (tag.Address.VarType) - { + switch (tag.Address.VarType) { case DataType.BOOL: return Expression.Call(_param1, _boolinfo, Expression.Constant(tagName)); case DataType.BYTE: @@ -543,12 +507,10 @@ namespace DataService } } - public bool GetBool(string tagName) - { + public bool GetBool(string tagName) { if (_server == null) return false; ITag tag = _server[tagName]; - switch (tag.Address.VarType) - { + switch (tag.Address.VarType) { case DataType.BOOL: return tag.Value.Boolean; case DataType.BYTE: @@ -568,26 +530,23 @@ namespace DataService } } - public float GetFloat(string tagName) - { + public float GetFloat(string tagName) { if (_server == null) return 0f; ITag tag = _server[tagName]; return tag.ScaleToValue(tag.Value); } - public int GetInt(string tagName) - { + public int GetInt(string tagName) { if (_server == null) return 0; ITag tag = _server[tagName]; - switch (tag.Address.VarType) - { + switch (tag.Address.VarType) { case DataType.BOOL: return tag.Value.Boolean ? 1 : 0; case DataType.BYTE: - return (int)tag.Value.Byte; + return (int) tag.Value.Byte; case DataType.WORD: case DataType.SHORT: - return (int)tag.Value.Int16; + return (int) tag.Value.Int16; case DataType.TIME: case DataType.INT: return tag.Value.Int32; @@ -600,82 +559,71 @@ namespace DataService } } - public string GetString(string tagName) - { + public string GetString(string tagName) { return _server == null ? null : _server[tagName].ToString(); } - public int WriteTag(string tagName, object value) - { + public int WriteTag(string tagName, object value) { if (_server == null || value == null) return -1; ITag tag = _server[tagName]; if (tag.Address.VarType == DataType.BOOL || tag.Address.VarType == DataType.STR) return tag.Write(value); - else - { + else { float temp; string str = value as string; if (str == null) temp = Convert.ToSingle(value); - else - { + else { if (!float.TryParse(str, out temp)) return -1; } + return tag.Write(tag.ValueToScale(temp)); } } - private bool IsConstant(string str, out object value) - { - if (str.Length > 1 & str[0] == '\'' && str[str.Length - 1] == '\'') - { + private bool IsConstant(string str, out object value) { + if (str.Length > 1 & str[0] == '\'' && str[str.Length - 1] == '\'') { value = str.Trim('\''); return true; } + string upp = str.ToUpper(); - if (upp == "TRUE") - { + if (upp == "TRUE") { value = true; return true; - } - else if (upp == "FALSE") - { + } else if (upp == "FALSE") { value = false; return true; } - if (_server != null) - { + + if (_server != null) { var tag = _server[upp]; - if (tag != null) - { + if (tag != null) { if (!_tagList.Contains(tag)) _tagList.Add(tag); value = null; return false; } } + int dotcount = 0; - for (int i = 0; i < str.Length; i++) - { + for (int i = 0; i < str.Length; i++) { char opr = str[i]; - if (opr < '0' || opr > '9') - { - if (opr != '.') - { + if (opr < '0' || opr > '9') { + if (opr != '.') { value = str; return true; - } - else - { - if (dotcount > 0) - { + } else { + if (dotcount > 0) { value = str; return true; } + dotcount++; } } } + //value = (dotcount == 0 ? int.Parse(str) : float.Parse(str)); if (dotcount == 0) value = int.Parse(str); @@ -683,15 +631,13 @@ namespace DataService return true; } - public void Clear() - { + public void Clear() { //_param1 = null; _tagList.Clear(); //_tagList = null; } - public void Dispose() - { + public void Dispose() { _param1 = null; _tagList.Clear(); _tagList = null; @@ -703,14 +649,13 @@ namespace DataService /// /// 操作符结构 /// - public struct Operator - { + public struct Operator { public char OperatorStack; public byte Level; - public Operator(char OperatorStack, byte Level) - { + + public Operator(char OperatorStack, byte Level) { this.OperatorStack = OperatorStack; this.Level = Level; } } -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/ExtensionMethods.cs b/SCADA/Program/DataService/ExtensionMethods.cs index f27440d..6064c9f 100644 --- a/SCADA/Program/DataService/ExtensionMethods.cs +++ b/SCADA/Program/DataService/ExtensionMethods.cs @@ -5,111 +5,96 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Data.SqlClient; -namespace DataService -{ - public static class ExtMethods - { - public static string GetExceptionMsg(this Exception e) - { +namespace DataService { + public static class ExtMethods { + public static string GetExceptionMsg(this Exception e) { string err = string.Empty; Exception exp = e; - while (exp != null) - { + while (exp != null) { err += string.Format("\n {0}", exp.Message); exp = exp.InnerException; } + err += string.Format("\n {0}", e.StackTrace); return err; } - public static bool ModifyItemName(this ITag tag, string name) - { + public static bool ModifyItemName(this ITag tag, string name) { IDataServer server = tag.Parent.Server; - lock (server.SyncRoot) - { + lock (server.SyncRoot) { int index = server.GetItemProperties(tag.ID); if (index < 0) return false; var meta = server.MetaDataList[index]; if (meta.Name == name) return true; - server.MetaDataList[index] = new TagMetaData(meta.ID, meta.GroupID, name, meta.Address, meta.DataType, meta.Size, meta.Archive, meta.Maximum, meta.Minimum, meta.Cycle); + server.MetaDataList[index] = new TagMetaData(meta.ID, meta.GroupID, name, meta.Address, meta.DataType, + meta.Size, meta.Archive, meta.Maximum, meta.Minimum, meta.Cycle); server.RemoveItemIndex(meta.Name); server.AddItemIndex(name, tag); return true; } } - public static SubCondition FindSubConditon(this IAlarmServer server, string sourceName, SubAlarmType alarmType) - { + public static SubCondition + FindSubConditon(this IAlarmServer server, string sourceName, SubAlarmType alarmType) { var conds = server.QueryConditions(sourceName); if (conds == null) return SubCondition.Empty; - foreach (ICondition cond in conds) - { + foreach (ICondition cond in conds) { SubCondition sub = cond.FindSubConditon(alarmType); if (sub.SubAlarmType == alarmType) return sub; } + return SubCondition.Empty; } - public static SubCondition FindSubConditon(this ICondition cond, SubAlarmType alarmType) - { + public static SubCondition FindSubConditon(this ICondition cond, SubAlarmType alarmType) { var subs = cond.SubConditions; - if (subs != null && subs.Count > 0) - { - foreach (var sub in subs) - { - if (sub.SubAlarmType == alarmType) - { + if (subs != null && subs.Count > 0) { + foreach (var sub in subs) { + if (sub.SubAlarmType == alarmType) { return sub; } } } + return SubCondition.Empty; } - public static bool HasScaling(this IDataServer server, string tagName) - { + public static bool HasScaling(this IDataServer server, string tagName) { ITag tag = server[tagName]; if (tag == null) return false; int scaleid = server.GetScaleByID(tag.ID); return scaleid >= 0; } - public static bool HasAlarm(this IDataServer dserver, string sourceName) - { + public static bool HasAlarm(this IDataServer dserver, string sourceName) { IAlarmServer server = dserver as IAlarmServer; if (server == null) return false; List conds = server.ConditionList as List; return conds == null || conds.Count == 0 ? false : conds.BinarySearch(new DigitAlarm(0, sourceName)) >= 0; } - public static bool HasSubCondition(this IDataServer dserver, string sourceName, SubAlarmType alarmType) - { + public static bool HasSubCondition(this IDataServer dserver, string sourceName, SubAlarmType alarmType) { IAlarmServer server = dserver as IAlarmServer; if (server == null) return false; var conds = server.QueryConditions(sourceName); if (conds == null) return false; - foreach (ICondition cond in conds) - { + foreach (ICondition cond in conds) { var subs = cond.SubConditions; - if (subs != null && subs.Count > 0) - { - foreach (var sub in subs) - { - if (sub.SubAlarmType == alarmType) - { + if (subs != null && subs.Count > 0) { + foreach (var sub in subs) { + if (sub.SubAlarmType == alarmType) { return true; } } } } + return false; } - public static ItemData ReadValueEx(this IReaderWriter reader, DeviceAddress address) - { - switch (address.VarType) - { + public static ItemData ReadValueEx(this IReaderWriter reader, DeviceAddress address) { + switch (address.VarType) { case DataType.BOOL: var bit = reader.ReadBit(address); return new ItemData(bit.Value, bit.TimeStamp, bit.Quality); @@ -131,13 +116,12 @@ namespace DataService var str = reader.ReadString(address, address.DataSize); return new ItemData(str.Value, str.TimeStamp, str.Quality); } + return new ItemData(null, 0, QUALITIES.QUALITY_BAD); } - public static int WriteValueEx(this IReaderWriter writer, DeviceAddress address, object value) - { - switch (address.VarType) - { + public static int WriteValueEx(this IReaderWriter writer, DeviceAddress address, object value) { + switch (address.VarType) { case DataType.BOOL: return writer.WriteBit(address, Convert.ToBoolean(value)); case DataType.BYTE: @@ -153,115 +137,112 @@ namespace DataService case DataType.STR: return writer.WriteString(address, value.ToString()); } + return -1; } - public static HistoryData[] BatchRead(DataSource source, params ITag[] itemArray) - { + public static HistoryData[] BatchRead(DataSource source, params ITag[] itemArray) { int len = itemArray.Length; HistoryData[] values = new HistoryData[len]; - for (int i = 0; i < len; i++) - { + for (int i = 0; i < len; i++) { itemArray[i].Refresh(source); values[i].ID = itemArray[i].ID; values[i].Value = itemArray[i].Value; values[i].TimeStamp = itemArray[i].TimeStamp; } + return values; } - public static int BatchWrite(IDictionary items) - { + public static int BatchWrite(IDictionary items) { int rev = 0; - foreach (var tag in items) - { + foreach (var tag in items) { if (tag.Key.Write(tag.Value) < 0) rev = -1; } + return rev; } - public static List AssignFromPDU(this ICache cacheReader, int PDU, params DeviceAddress[] addrsArr) - { + public static List AssignFromPDU(this ICache cacheReader, int PDU, params DeviceAddress[] addrsArr) { List rangeList = new List(); int count = addrsArr.Length; - if (count > 0) - { + if (count > 0) { //Array.Sort(addrsArr); DeviceAddress start = addrsArr[0]; start.Bit = 0; int bitCount = cacheReader.ByteCount; - if (count > 1) - { - int cacheLength = 0;//缓冲区的大小 + if (count > 1) { + int cacheLength = 0; //缓冲区的大小 int cacheIndexStart = 0; int startIndex = 0; - DeviceAddress segmentEnd, tagAddress; + DeviceAddress segmentEnd, + tagAddress; DeviceAddress segmentStart = start; - for (int j = 1, i = 1; i < count; i++, j++) - { - tagAddress = addrsArr[i];//当前变量地址 + for (int j = 1, + i = 1; + i < count; + i++, j++) { + tagAddress = addrsArr[i]; //当前变量地址 int offset1 = cacheReader.GetOffset(tagAddress, segmentStart); - if (offset1 > (PDU / cacheReader.ByteCount)) - { + if (offset1 > (PDU / cacheReader.ByteCount)) { segmentEnd = addrsArr[i - 1]; int len = cacheReader.GetOffset(segmentEnd, segmentStart); len += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; - tagAddress.CacheIndex = (ushort)(cacheIndexStart + len); + tagAddress.CacheIndex = (ushort) (cacheIndexStart + len); addrsArr[i] = tagAddress; rangeList.Add(new PDUArea(segmentStart, len, startIndex, j)); - startIndex += j; j = 0; - cacheLength += len;//更新缓存长度 + startIndex += j; + j = 0; + cacheLength += len; //更新缓存长度 cacheIndexStart = cacheLength; - segmentStart = tagAddress;//更新数据片段的起始地址 - } - else - { - tagAddress.CacheIndex = (ushort)(cacheIndexStart + offset1); + segmentStart = tagAddress; //更新数据片段的起始地址 + } else { + tagAddress.CacheIndex = (ushort) (cacheIndexStart + offset1); addrsArr[i] = tagAddress; } - if (i == count - 1) - { + + if (i == count - 1) { segmentEnd = addrsArr[i]; int segmentLength = cacheReader.GetOffset(segmentEnd, segmentStart); - if (segmentLength > PDU / cacheReader.ByteCount) - { + if (segmentLength > PDU / cacheReader.ByteCount) { segmentEnd = addrsArr[i - 1]; segmentLength = segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; } - tagAddress.CacheIndex = (ushort)(cacheIndexStart + segmentLength); + + tagAddress.CacheIndex = (ushort) (cacheIndexStart + segmentLength); addrsArr[i] = tagAddress; segmentLength += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; rangeList.Add(new PDUArea(segmentStart, segmentLength, startIndex, j + 1)); cacheLength += segmentLength; } } + cacheReader.Size = cacheLength; - } - else - cacheReader.Size = start.DataSize <= bitCount ? 1 : start.DataSize / bitCount;//改变Cache的Size属性值将创建Cache的内存区域 + } else + cacheReader.Size = + start.DataSize <= bitCount ? 1 : start.DataSize / bitCount; //改变Cache的Size属性值将创建Cache的内存区域 } + return rangeList; } //调用前应对地址数组排序(是否加锁?) - public static ItemData[] PLCReadMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrsArr) - { + public static ItemData[] PLCReadMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrsArr) { if (addrsArr == null || cache == null || addrsArr.Length == 0) return null; int len = addrsArr.Length; ItemData[] items = new ItemData[len]; - int offset = 0; long now = DateTime.Now.ToFileTime(); + int offset = 0; + long now = DateTime.Now.ToFileTime(); List areas = cache.AssignFromPDU(plc.PDU, addrsArr); - foreach (PDUArea area in areas) - { - byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort)area.Len); + foreach (PDUArea area in areas) { + byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort) area.Len); Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length); offset += rcvBytes.Length / cache.ByteCount; } - for (int i = 0; i < len; i++) - { - switch (addrsArr[i].VarType) - { + + for (int i = 0; i < len; i++) { + switch (addrsArr[i].VarType) { case DataType.BOOL: items[i].Value.Boolean = cache.ReadBit(addrsArr[i]).Value; break; @@ -283,63 +264,66 @@ namespace DataService var item = cache.ReadString(addrsArr[i], addrsArr[i].DataSize); break; } + items[i].Quality = QUALITIES.QUALITY_GOOD; items[i].TimeStamp = now; } + return items; } - public static int PLCWriteMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrArr, object[] buffer, int limit) - { + public static int PLCWriteMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrArr, object[] buffer, + int limit) { if (cache == null || addrArr == null || buffer == null || addrArr.Length != buffer.Length) return -1; if (addrArr.Length == 1) return plc.WriteValue(addrArr[0], buffer[0]); - lock (plc)//不锁定会有并发冲突问题;锁定也不能保障绝对安全,如有人现场操作会导致数据刷新 + lock (plc) //不锁定会有并发冲突问题;锁定也不能保障绝对安全,如有人现场操作会导致数据刷新 { List areas = cache.AssignFromPDU(plc.PDU, addrArr); int offset = 0; - foreach (PDUArea area in areas) - { - byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort)area.Len); + foreach (PDUArea area in areas) { + byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort) area.Len); if (rcvBytes == null) return -1; Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length); offset += rcvBytes.Length / cache.ByteCount; } + DeviceAddress start = addrArr[0]; int startIndex = 0; int endIndex = 0; - while (endIndex < addrArr.Length) - { - if (start.Area != addrArr[endIndex].Area || start.DBNumber != addrArr[endIndex].DBNumber || endIndex - startIndex >= limit) - { - for (int i = startIndex; i < endIndex; i++) - { + while (endIndex < addrArr.Length) { + if (start.Area != addrArr[endIndex].Area || start.DBNumber != addrArr[endIndex].DBNumber || + endIndex - startIndex >= limit) { + for (int i = startIndex; i < endIndex; i++) { cache.WriteValue(addrArr[i], buffer[i]); } - int c1 = start.CacheIndex; int c2 = addrArr[endIndex - 1].CacheIndex; + + int c1 = start.CacheIndex; + int c2 = addrArr[endIndex - 1].CacheIndex; byte[] bytes = new byte[cache.ByteCount * (c2 - c1 + 1)]; Buffer.BlockCopy(cache.Cache, c1, bytes, 0, bytes.Length); if (plc.WriteBytes(start, bytes) < 0) return -1; start = addrArr[endIndex]; startIndex = endIndex; } + endIndex++; } } + return 0; } + /// /// string RightFrom /// /// /// /// - public static string RightFrom(this string text, int index) - { + public static string RightFrom(this string text, int index) { return text.Substring(index + 1, text.Length - index - 1); } - public static string Right(this string text, int length) - { + public static string Right(this string text, int length) { return text.Substring(text.Length - length, length); } @@ -348,16 +332,12 @@ namespace DataService /// /// /// - - public static DateTime ToDateTime(this long filetime) - { + public static DateTime ToDateTime(this long filetime) { return filetime == 0 ? DateTime.Now : DateTime.FromFileTime(filetime); } - public static Type ToType(this DataType dataType) - { - switch (dataType) - { + public static Type ToType(this DataType dataType) { + switch (dataType) { case DataType.BOOL: return typeof(bool); case DataType.BYTE: @@ -378,15 +358,13 @@ namespace DataService } } - public static string ToFormatString(this int num, int len) - { + public static string ToFormatString(this int num, int len) { string str = num.ToString(); int off = len - str.Length; return off > 0 ? string.Concat(new string('0', off), str) : str; } - public static bool IsEquals(this byte[] b1, byte[] b2) - { + public static bool IsEquals(this byte[] b1, byte[] b2) { if (b1 == null || b2 == null) return false; if (b1.Length != b2.Length) return false; for (int i = 0; i < b1.Length; i++) @@ -395,41 +373,38 @@ namespace DataService return true; } - public static string ConvertToString(this byte[] bits) - { + public static string ConvertToString(this byte[] bits) { char[] chars = new char[bits.Length]; - for (int i = 0; i < bits.Length; i++) - { - chars[i] = (char)bits[i]; + for (int i = 0; i < bits.Length; i++) { + chars[i] = (char) bits[i]; } + return new string(chars); } - public static byte[] ConvertToArray(this string bits) - { + public static byte[] ConvertToArray(this string bits) { var chars = bits.ToCharArray(); byte[] arr = new byte[chars.Length]; - for (int i = 0; i < chars.Length; i++) - { - arr[i] = (byte)chars[i]; + for (int i = 0; i < chars.Length; i++) { + arr[i] = (byte) chars[i]; } + return arr; } - public static int BitSwap(this byte bit) - { + public static int BitSwap(this byte bit) { return (bit < 8 ? bit + 8 : bit - 8); } [Obsolete] - public static Storage ToStorage(this ITag tag, object obj) - { + public static Storage ToStorage(this ITag tag, object obj) { Storage value = Storage.Empty; var str = obj as string; - switch (tag.Address.VarType) - { + switch (tag.Address.VarType) { case DataType.BOOL: - value.Boolean = str == null ? Convert.ToBoolean(obj) : str == "0" ? false : str == "1" ? true : bool.Parse(str); + value.Boolean = str == null ? Convert.ToBoolean(obj) : + str == "0" ? false : + str == "1" ? true : bool.Parse(str); break; case DataType.BYTE: value.Byte = Convert.ToByte(obj); @@ -446,17 +421,16 @@ namespace DataService value.Single = Convert.ToSingle(obj); break; } + return value; } - public static byte[] ToByteArray(this ITag tag) - { - switch (tag.Address.VarType) - { + public static byte[] ToByteArray(this ITag tag) { + switch (tag.Address.VarType) { case DataType.BOOL: - return new byte[] { tag.Value.Boolean ? (byte)1 : (byte)0 }; + return new byte[] {tag.Value.Boolean ? (byte) 1 : (byte) 0}; case DataType.BYTE: - return new byte[] { tag.Value.Byte }; + return new byte[] {tag.Value.Byte}; case DataType.WORD: case DataType.SHORT: return BitConverter.GetBytes(tag.Value.Int16); @@ -471,14 +445,12 @@ namespace DataService } } - public static byte[] ToByteArray(this ITag tag, Storage value) - { - switch (tag.Address.VarType) - { + public static byte[] ToByteArray(this ITag tag, Storage value) { + switch (tag.Address.VarType) { case DataType.BOOL: - return new byte[] { value.Boolean ? (byte)1 : (byte)0 }; + return new byte[] {value.Boolean ? (byte) 1 : (byte) 0}; case DataType.BYTE: - return new byte[] { value.Byte }; + return new byte[] {value.Byte}; case DataType.WORD: case DataType.SHORT: return BitConverter.GetBytes(value.Int16); @@ -493,10 +465,8 @@ namespace DataService } } - public static object GetValue(this ITag tag, Storage value) - { - switch (tag.Address.VarType) - { + public static object GetValue(this ITag tag, Storage value) { + switch (tag.Address.VarType) { case DataType.BOOL: return value.Boolean; case DataType.BYTE: @@ -516,42 +486,35 @@ namespace DataService } } - public static float ValueToScale(this ITag tag, float value) - { + public static float ValueToScale(this ITag tag, float value) { IDataServer srv = tag.Parent.Server; int ind = srv.GetScaleByID(tag.ID); Scaling meta = ind < 0 ? Scaling.Empty : srv.ScalingList[ind]; - if (meta.ScaleType == ScaleType.None) - { + if (meta.ScaleType == ScaleType.None) { return value; - } - else - { + } else { double temp = (value - meta.EULo) / (meta.EUHi - meta.EULo); if (meta.ScaleType == ScaleType.SquareRoot) temp = temp * temp; - return (meta.RawHi - meta.RawLo) * (float)temp + meta.RawLo; + return (meta.RawHi - meta.RawLo) * (float) temp + meta.RawLo; } } - public static float ScaleToValue(this ITag tag, Storage value) - { + public static float ScaleToValue(this ITag tag, Storage value) { DataType type = tag.Address.VarType; if (type == DataType.BOOL) return value.Boolean ? 1f : 0f; IDataServer srv = tag.Parent.Server; int ind = srv.GetScaleByID(tag.ID); Scaling meta = ind < 0 ? Scaling.Empty : srv.ScalingList[ind]; - if (meta.ScaleType == ScaleType.None) - { - switch (type) - { + if (meta.ScaleType == ScaleType.None) { + switch (type) { case DataType.BYTE: - return (float)value.Byte; + return (float) value.Byte; case DataType.WORD: case DataType.SHORT: - return (float)value.Int16; + return (float) value.Int16; case DataType.INT: - return (float)value.Int32; + return (float) value.Int32; case DataType.FLOAT: return value.Single; case DataType.STR: @@ -559,12 +522,9 @@ namespace DataService default: return 0f; } - } - else - { + } else { double temp; - switch (type) - { + switch (type) { case DataType.BYTE: temp = (value.Byte - meta.RawLo) / (meta.RawHi - meta.RawLo); break; @@ -581,73 +541,57 @@ namespace DataService default: return 0f; } + if (meta.ScaleType == ScaleType.SquareRoot) temp = Math.Sqrt(temp); - return (meta.EUHi - meta.EULo) * (float)temp + meta.EULo; + return (meta.EUHi - meta.EULo) * (float) temp + meta.EULo; } } - public static float ScaleToValue(this ITag tag) - { + public static float ScaleToValue(this ITag tag) { return ScaleToValue(tag, tag.Value); } - public static string GetTagName(this ITag tag) - { + public static string GetTagName(this ITag tag) { IDataServer srv = tag.Parent.Server; int ind = srv.GetItemProperties(tag.ID); return ind < 0 ? null : srv.MetaDataList[ind].Name; } - public static string GetTagName(this IDataServer srv, short id) - { + public static string GetTagName(this IDataServer srv, short id) { int ind = srv.GetItemProperties(id); return ind < 0 ? null : srv.MetaDataList[ind].Name; } - public static TagMetaData GetMetaData(this ITag tag) - { + public static TagMetaData GetMetaData(this ITag tag) { IDataServer srv = tag.Parent.Server; int index = srv.GetItemProperties(tag.ID); return index < 0 ? new TagMetaData() : srv.MetaDataList[index]; } } - public static class Utility - { + public static class Utility { private static readonly ushort[] crcTable = { - 0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241, - 0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440, - 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40, - 0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841, - 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40, - 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41, - 0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641, - 0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040, - 0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240, - 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441, - 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41, - 0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840, - 0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41, - 0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40, - 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640, - 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041, - 0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240, - 0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441, - 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41, - 0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840, - 0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41, - 0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40, - 0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640, - 0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041, - 0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241, - 0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440, - 0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40, - 0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841, - 0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40, - 0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41, - 0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641, - 0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040 + 0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241, 0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, + 0XC5C1, 0XC481, 0X0440, 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40, 0X0A00, 0XCAC1, + 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841, 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, + 0X1A40, 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41, 0X1400, 0XD4C1, 0XD581, 0X1540, + 0XD701, 0X17C0, 0X1680, 0XD641, 0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040, 0XF001, + 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240, 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, + 0X3480, 0XF441, 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41, 0XFA01, 0X3AC0, 0X3B80, + 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840, 0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41, + 0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40, 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, + 0XE7C1, 0XE681, 0X2640, 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041, 0XA001, 0X60C0, + 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240, 0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, + 0XA441, 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41, 0XAA01, 0X6AC0, 0X6B80, 0XAB41, + 0X6900, 0XA9C1, 0XA881, 0X6840, 0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41, 0XBE01, + 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40, 0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, + 0XB681, 0X7640, 0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041, 0X5000, 0X90C1, 0X9181, + 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241, 0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440, + 0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40, 0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, + 0X59C0, 0X5880, 0X9841, 0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40, 0X4E00, 0X8EC1, + 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41, 0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, + 0X8641, 0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040 }; /// @@ -655,13 +599,12 @@ namespace DataService /// /// The byte array /// An array of ASCII byte values - public static string GetAsciiBytes(byte[] numbers) - { + public static string GetAsciiBytes(byte[] numbers) { string str = string.Empty; - for (int i = 0; i < numbers.Length; i++) - { + for (int i = 0; i < numbers.Length; i++) { str += numbers[i].ToString("X2"); } + return str; } @@ -670,13 +613,12 @@ namespace DataService /// /// The ushort array /// An array of ASCII byte values - public static string GetAsciiBytes(ushort[] numbers) - { + public static string GetAsciiBytes(ushort[] numbers) { string str = string.Empty; - for (int i = 0; i < numbers.Length; i++) - { + for (int i = 0; i < numbers.Length; i++) { str += numbers[i].ToString("X4"); } + return str; } @@ -685,8 +627,7 @@ namespace DataService /// /// The network order byte array /// The host order ushort array - public static ushort[] NetworkBytesToHostUInt16(byte[] networkBytes) - { + public static ushort[] NetworkBytesToHostUInt16(byte[] networkBytes) { if (networkBytes == null) throw new ArgumentNullException("networkBytes"); @@ -696,7 +637,7 @@ namespace DataService ushort[] result = new ushort[networkBytes.Length / 2]; for (int i = 0; i < result.Length; i++) - result[i] = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(networkBytes, i * 2)); + result[i] = (ushort) IPAddress.HostToNetworkOrder(BitConverter.ToInt16(networkBytes, i * 2)); return result; } @@ -706,8 +647,7 @@ namespace DataService /// /// The hex string /// Array of bytes - public static byte[] HexToBytes(string hex) - { + public static byte[] HexToBytes(string hex) { if (string.IsNullOrEmpty(hex)) throw new ArgumentNullException("hex"); @@ -727,16 +667,16 @@ namespace DataService /// /// The data used in LRC /// LRC value - public static byte CalculateLrc(byte[] data, int len = 0) - { + public static byte CalculateLrc(byte[] data, int len = 0) { if (data == null) throw new ArgumentNullException("data"); if (len == 0) len = data.Length; byte lrc = 0; - for (int i = 0; i < len; i++) - { lrc += data[i]; } + for (int i = 0; i < len; i++) { + lrc += data[i]; + } - lrc = (byte)((lrc ^ 0xFF) + 1); + lrc = (byte) ((lrc ^ 0xFF) + 1); return lrc; } @@ -746,15 +686,13 @@ namespace DataService /// /// The data used in CRC /// CRC value - public static byte[] CalculateCrc(byte[] data, int len = 0) - { + public static byte[] CalculateCrc(byte[] data, int len = 0) { if (data == null) throw new ArgumentNullException("data"); if (len == 0) len = data.Length; ushort crc = ushort.MaxValue; - for (int i = 0; i < len; i++) - { - byte tableIndex = (byte)(crc ^ data[i]); + for (int i = 0; i < len; i++) { + byte tableIndex = (byte) (crc ^ data[i]); crc >>= 8; crc ^= crcTable[tableIndex]; } @@ -762,50 +700,43 @@ namespace DataService return BitConverter.GetBytes(crc); } - public static bool CheckSumCRC(byte[] frame) - { + public static bool CheckSumCRC(byte[] frame) { int len = frame.Length; byte[] chk = CalculateCrc(frame, len - 2); return (chk[0] == frame[len - 2] && chk[1] == frame[len - 1]); } - public static unsafe short NetToInt16(byte[] value, int startIndex) - { - if (value == null || startIndex > value.Length - 2) - { + public static unsafe short NetToInt16(byte[] value, int startIndex) { + if (value == null || startIndex > value.Length - 2) { throw new NotImplementedException(); } - fixed (byte* numRef = &(value[startIndex])) - { - return (short)((numRef[0] << 8) | numRef[1]); + + fixed (byte* numRef = &(value[startIndex])) { + return (short) ((numRef[0] << 8) | numRef[1]); } } - public static unsafe int NetToInt32(byte[] value, int startIndex) - { - if (value == null || startIndex > value.Length - 4) - { + public static unsafe int NetToInt32(byte[] value, int startIndex) { + if (value == null || startIndex > value.Length - 4) { throw new NotImplementedException(); } - fixed (byte* numRef = &(value[startIndex])) - { - return (int)((numRef[0] << 24) | (numRef[1] << 16) | (numRef[2] << 8) | numRef[3]); + + fixed (byte* numRef = &(value[startIndex])) { + return (int) ((numRef[0] << 24) | (numRef[1] << 16) | (numRef[2] << 8) | numRef[3]); } } - public static unsafe float NetToSingle(byte[] value, int startIndex) - { + public static unsafe float NetToSingle(byte[] value, int startIndex) { int a = NetToInt32(value, startIndex); - return *(float*)&a; + return *(float*) &a; } - public static string ConvertToString(byte[] bytes, int start = 0, int len = 0) - { + public static string ConvertToString(byte[] bytes, int start = 0, int len = 0) { //西门子300、400 if (bytes == null || bytes.Length == 0) return string.Empty; var klen = bytes[start + 1]; - return Encoding.ASCII.GetString(bytes, start + 2, klen).Trim((char)0); + return Encoding.ASCII.GetString(bytes, start + 2, klen).Trim((char) 0); } } -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/HistoryData.cs b/SCADA/Program/DataService/HistoryData.cs index fd00199..98c5854 100644 --- a/SCADA/Program/DataService/HistoryData.cs +++ b/SCADA/Program/DataService/HistoryData.cs @@ -1,83 +1,68 @@ using System; using System.Collections.Generic; -namespace DataService -{ - public struct HistoryData : IComparable - { +namespace DataService { + public struct HistoryData : IComparable { public short ID; public QUALITIES Quality; public Storage Value; public DateTime TimeStamp; - public HistoryData(short id, QUALITIES qualitie, Storage value, DateTime timeStamp) - { + public HistoryData(short id, QUALITIES qualitie, Storage value, DateTime timeStamp) { ID = id; Quality = qualitie; Value = value; TimeStamp = timeStamp; } - public override bool Equals(object obj) - { + public override bool Equals(object obj) { if (obj == null) return false; - if (obj is HistoryData) - { - return this == (HistoryData)obj; - } - else return false; + if (obj is HistoryData) { + return this == (HistoryData) obj; + } else return false; } - public override int GetHashCode() - { + public override int GetHashCode() { return ID.GetHashCode() ^ TimeStamp.GetHashCode(); } - public static bool operator ==(HistoryData x, HistoryData y) - { + public static bool operator ==(HistoryData x, HistoryData y) { return x.ID == y.ID && x.TimeStamp == y.TimeStamp; } - public static bool operator !=(HistoryData x, HistoryData y) - { + public static bool operator !=(HistoryData x, HistoryData y) { return x.ID != y.ID || x.TimeStamp != y.TimeStamp; } public static readonly HistoryData Empty = new HistoryData(); - public int CompareTo(HistoryData other) - { + public int CompareTo(HistoryData other) { int comp = this.TimeStamp.CompareTo(other.TimeStamp); return comp == 0 ? this.ID.CompareTo(other.ID) : comp; } } - public struct FileData : IComparable - { + public struct FileData : IComparable { public short ID; public Storage Value; public string Text; - public FileData(short id, Storage value, string text) - { + public FileData(short id, Storage value, string text) { ID = id; Value = value; Text = text; } - public int CompareTo(FileData other) - { + public int CompareTo(FileData other) { return this.ID.CompareTo(other.ID); } } - public class CompareHistoryData : IComparer - { - public int Compare(HistoryData x, HistoryData y) - { + public class CompareHistoryData : IComparer { + public int Compare(HistoryData x, HistoryData y) { int c1 = x.TimeStamp.CompareTo(y.TimeStamp); return c1 == 0 ? x.ID.CompareTo(y.ID) : c1; } } -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/IGroup.cs b/SCADA/Program/DataService/IGroup.cs index a3928d4..96a3dfc 100644 --- a/SCADA/Program/DataService/IGroup.cs +++ b/SCADA/Program/DataService/IGroup.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -namespace DataService -{ - public interface IGroup : IDisposable - { +namespace DataService { + public interface IGroup : IDisposable { bool IsActive { get; set; } short ID { get; } int UpdateRate { get; set; } @@ -35,10 +33,8 @@ namespace DataService event DataChangeEventHandler DataChange; } - public class DataChangeEventArgs : EventArgs - { - public DataChangeEventArgs(int transactionID, IList pValues) - { + public class DataChangeEventArgs : EventArgs { + public DataChangeEventArgs(int transactionID, IList pValues) { this.TransactionID = transactionID; this.Values = pValues; } @@ -47,10 +43,8 @@ namespace DataService public IList Values; } - public class WriteCompleteEventArgs : EventArgs - { - public WriteCompleteEventArgs(int transactionID, short[] pIds, int[] errors) - { + public class WriteCompleteEventArgs : EventArgs { + public WriteCompleteEventArgs(int transactionID, short[] pIds, int[] errors) { this.TransactionID = transactionID; this.Values = pIds; this.Errors = errors; @@ -66,5 +60,4 @@ namespace DataService public delegate void ReadCompleteEventHandler(object sender, DataChangeEventArgs e); public delegate void WriteCompleteEventHandler(object sender, WriteCompleteEventArgs e); - -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/IReader.cs b/SCADA/Program/DataService/IReader.cs index 2e28be0..b46c57b 100644 --- a/SCADA/Program/DataService/IReader.cs +++ b/SCADA/Program/DataService/IReader.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -namespace DataService -{ - public interface IReaderWriter - { +namespace DataService { + public interface IReaderWriter { byte[] ReadBytes(DeviceAddress address, ushort size); ItemData ReadInt32(DeviceAddress address); ItemData ReadInt16(DeviceAddress address); @@ -25,26 +23,23 @@ namespace DataService } - public interface ICache : IReaderWriter - { + public interface ICache : IReaderWriter { int Size { get; set; } int ByteCount { get; } Array Cache { get; } int GetOffset(DeviceAddress start, DeviceAddress end); } - public interface IMultiReadWrite - { + public interface IMultiReadWrite { int Limit { get; } ItemData[] ReadMultiple(DeviceAddress[] addrsArr); int WriteMultiple(DeviceAddress[] addrArr, object[] buffer); } - public interface IDriver : IDisposable - { + public interface IDriver : IDisposable { short ID { get; } string Name { get; } - string ServerName { get; set; }//可以考虑增加一个附加参数,Sever只定义本机名 + string ServerName { get; set; } //可以考虑增加一个附加参数,Sever只定义本机名 bool IsClosed { get; } int TimeOut { get; set; } IEnumerable Groups { get; } @@ -55,28 +50,26 @@ namespace DataService event ShutdownRequestEventHandler OnClose; } - public interface IPLCDriver : IDriver, IReaderWriter - { + public interface IPLCDriver : IDriver, IReaderWriter { int PDU { get; } DeviceAddress GetDeviceAddress(string address); string GetAddress(DeviceAddress address); } - public interface IFileDriver : IDriver, IReaderWriter - { + public interface IFileDriver : IDriver, IReaderWriter { string FileName { get; set; } + FileData[] ReadAll(short groupId); //bool RecieveData(string data); } - public class ShutdownRequestEventArgs : EventArgs - { - public ShutdownRequestEventArgs(string reson) - { + public class ShutdownRequestEventArgs : EventArgs { + public ShutdownRequestEventArgs(string reson) { shutdownReason = reson; } + public string shutdownReason; } public delegate void ShutdownRequestEventHandler(object sender, ShutdownRequestEventArgs e); -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/IServer.cs b/SCADA/Program/DataService/IServer.cs index 4ad8815..e15c23c 100644 --- a/SCADA/Program/DataService/IServer.cs +++ b/SCADA/Program/DataService/IServer.cs @@ -1,20 +1,18 @@ using System; using System.Collections.Generic; -namespace DataService -{ +namespace DataService { //历史数据、报警数据的提交和数据均从服务器 - public interface IHDAServer : IDisposable - { + public interface IHDAServer : IDisposable { IEnumerable ReadAtTime(params DateTime[] timeStamps); IEnumerable ReadAtTime(short ID, params DateTime[] timeStamps); IEnumerable ReadRaw(DateTime start, DateTime end); + IEnumerable ReadRaw(DateTime start, DateTime end, short ID); //IEnumerable ReadProcessed(DateTime start, DateTime end, HDAAggregate aggregates, params short[] aggregateIDs); } - public interface IAlarmServer : IDisposable - { + public interface IAlarmServer : IDisposable { int DisableCondition(string sourceName, AlarmType type); int EnableCondition(string sourceName, AlarmType type); int RemoveConditon(string sourceName, AlarmType type); @@ -26,21 +24,22 @@ namespace DataService IList ActivedConditionList { get; } } - public interface IDataServer : IDisposable - { + public interface IDataServer : IDisposable { ITag this[short id] { get; } ITag this[string name] { get; } ExpressionEval Eval { get; } - Object SyncRoot { get; }//对所有涉及集合更改项目使用;包括IGROUP的ADDITEMS + Object SyncRoot { get; } //对所有涉及集合更改项目使用;包括IGROUP的ADDITEMS IList MetaDataList { get; } IList ScalingList { get; } IEnumerable Drivers { get; } IEnumerable BrowseItems(BrowseType browseType, string tagName, DataType dataType); + IDriver AddDriver(short id, string name, string server, int timeOut, string assembly, string className, string spare1, string spare2); + IGroup GetGroupByName(string name); int GetScaleByID(short id); - int GetItemProperties(short id);//返回的是元数据在元数据列表的索引 + int GetItemProperties(short id); //返回的是元数据在元数据列表的索引 bool RemoveDriver(IDriver device); bool AddItemIndex(string key, ITag value); bool RemoveItemIndex(string key); @@ -49,23 +48,21 @@ namespace DataService HistoryData[] BatchRead(DataSource source, bool sync, params ITag[] itemArray); } - public class FCTCOMMAND - { - public const byte fctHead = 0xAB;//报头可加密,如报头不符,则不进行任何操作;客户端Socket发送报警请求,封装于Server + public class FCTCOMMAND { + public const byte fctHead = 0xAB; //报头可加密,如报头不符,则不进行任何操作;客户端Socket发送报警请求,封装于Server public const byte fctHdaIdRequest = 30; public const byte fctHdaRequest = 31; public const byte fctAlarmRequest = 32; public const byte fctOrderChange = 33; public const byte fctReset = 34; - public const byte fctXMLHead = 0xEE;//xml协议 + public const byte fctXMLHead = 0xEE; //xml协议 public const byte fctReadSingle = 1; public const byte fctReadMultiple = 2; public const byte fctWriteSingle = 5; public const byte fctWriteMultiple = 15; } - public enum HDAAggregate - { + public enum HDAAggregate { HDANoAggregate, HDAInterpolative, HDATotal, @@ -93,8 +90,7 @@ namespace DataService HDAAnnotations, } - public enum BrowseType - { + public enum BrowseType { Branch = 1, Leaf = 2, Flat = 3 diff --git a/SCADA/Program/DataService/ITag.cs b/SCADA/Program/DataService/ITag.cs index a08c8df..7d66dde 100644 --- a/SCADA/Program/DataService/ITag.cs +++ b/SCADA/Program/DataService/ITag.cs @@ -1,102 +1,72 @@ using System; -namespace DataService -{ - public abstract class ITag : IComparable - { +namespace DataService { + public abstract class ITag : IComparable { protected short _id; - public short ID - { - get - { - return _id; - } + + public short ID { + get { return _id; } } protected bool _active = true; - public bool Active - { - get - { - return _active; - } - set - { + + public bool Active { + get { return _active; } + set { _group.SetActiveState(value, _id); _active = value; } } protected QUALITIES _quality; - public QUALITIES Quality - { - get - { - return _quality; - } + + public QUALITIES Quality { + get { return _quality; } } protected Storage _value; - public Storage Value - { - get - { - return _value; - } + + public Storage Value { + get { return _value; } } protected DateTime _timeStamp = DateTime.MinValue; - public DateTime TimeStamp - { - get - { - return _timeStamp; - } + + public DateTime TimeStamp { + get { return _timeStamp; } } protected DeviceAddress _plcAddress; - public DeviceAddress Address - { - get - { - return _plcAddress; - } - set - { - _plcAddress = value; - } + + public DeviceAddress Address { + get { return _plcAddress; } + set { _plcAddress = value; } } protected IGroup _group; - public IGroup Parent - { - get - { - return _group; - } + + public IGroup Parent { + get { return _group; } } - protected ITag(short id, DeviceAddress address, IGroup group) - { + protected ITag(short id, DeviceAddress address, IGroup group) { _id = id; _group = group; _plcAddress = address; } - public void Update(Storage newvalue, DateTime timeStamp, QUALITIES quality) - { - if (_timeStamp > timeStamp) return;//如果时间戳更旧或值未改变 - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(quality, _value, newvalue, _timeStamp, timeStamp)); + public void Update(Storage newvalue, DateTime timeStamp, QUALITIES quality) { + if (_timeStamp > timeStamp) return; //如果时间戳更旧或值未改变 + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(quality, _value, newvalue, _timeStamp, timeStamp)); } + _timeStamp = timeStamp; _quality = quality; - if (quality == QUALITIES.QUALITY_GOOD) - { + if (quality == QUALITIES.QUALITY_GOOD) { _value = newvalue; - if (ValueChanged != null) - { + if (ValueChanged != null) { ValueChanged(this, new ValueChangedEventArgs(_value)); } } @@ -110,33 +80,33 @@ namespace DataService public abstract int Write(object value); - public int Write(Storage value, bool bForce) - { + public int Write(Storage value, bool bForce) { DateTime time = DateTime.Now; _timeStamp = time; - if (bForce) - { - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(QUALITIES.QUALITY_GOOD, _value, value, _timeStamp, time)); + if (bForce) { + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(QUALITIES.QUALITY_GOOD, _value, value, _timeStamp, time)); } } + int result = InnerWrite(value); - if (bForce || result != 0) - { + if (bForce || result != 0) { var data = Read(DataSource.Device); - if (data != value) - { + if (data != value) { time = DateTime.Now; - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(QUALITIES.QUALITY_GOOD, _value, data, _timeStamp, time)); + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(QUALITIES.QUALITY_GOOD, _value, data, _timeStamp, + time)); } + _value = data; _timeStamp = time; return result; } } + return 0; } @@ -146,64 +116,56 @@ namespace DataService #region IComparable Members - public override int GetHashCode() - { + public override int GetHashCode() { return _id.GetHashCode(); } - public int CompareTo(ITag other) - { + public int CompareTo(ITag other) { return _plcAddress.CompareTo(other._plcAddress); } #endregion } - public sealed class BoolTag : ITag - { + public sealed class BoolTag : ITag { public BoolTag(short id, DeviceAddress addr, IGroup group) - : base(id, addr, group) - { - } + : base(id, addr, group) { } #region IDevice Members - public override bool Refresh(DataSource source = DataSource.Cache) - { + public override bool Refresh(DataSource source = DataSource.Cache) { var _newvalue = _group.ReadBool(_plcAddress, source); - if (_newvalue.Value != _value.Boolean) - { + if (_newvalue.Value != _value.Boolean) { Storage value = Storage.Empty; value.Boolean = _newvalue.Value; DateTime time = _newvalue.TimeStamp.ToDateTime(); - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); } + _timeStamp = time; _quality = _newvalue.Quality; - if (_quality == QUALITIES.QUALITY_GOOD) - { + if (_quality == QUALITIES.QUALITY_GOOD) { _value = value; - if (ValueChanged != null) - { + if (ValueChanged != null) { ValueChanged(this, new ValueChangedEventArgs(value)); } } + return true; } + return false; } - public override Storage Read(DataSource source = DataSource.Cache) - { + public override Storage Read(DataSource source = DataSource.Cache) { Storage value = Storage.Empty; value.Boolean = _group.ReadBool(_plcAddress, source).Value; return value; } - public override int Write(object value) - { + public override int Write(object value) { if (value == null) return -1; bool temp = _value.Boolean; var str = value as string; @@ -215,65 +177,57 @@ namespace DataService return _group.WriteBit(_plcAddress, temp); } - protected override int InnerWrite(Storage value) - { + protected override int InnerWrite(Storage value) { return _group.WriteBit(_plcAddress, value.Boolean); } #endregion - public override string ToString() - { + public override string ToString() { return _value.Boolean.ToString(); } } - public sealed class ByteTag : ITag - { - + public sealed class ByteTag : ITag { public ByteTag(short id, DeviceAddress addr, IGroup group) - : base(id, addr, group) - { - } + : base(id, addr, group) { } #region IDevice Members - public override bool Refresh(DataSource source = DataSource.Device) - { + + public override bool Refresh(DataSource source = DataSource.Device) { var _newvalue = _group.ReadByte(_plcAddress, source); - if (_newvalue.Value != _value.Byte) - { + if (_newvalue.Value != _value.Byte) { Storage value = Storage.Empty; value.Byte = _newvalue.Value; DateTime time = _newvalue.TimeStamp.ToDateTime(); - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); } + _timeStamp = time; _quality = _newvalue.Quality; - if (_quality == QUALITIES.QUALITY_GOOD) - { + if (_quality == QUALITIES.QUALITY_GOOD) { _value = value; - if (ValueChanged != null) - { + if (ValueChanged != null) { ValueChanged(this, new ValueChangedEventArgs(value)); } } + return true; } + return false; } - public override Storage Read(DataSource source = DataSource.Cache) - { + public override Storage Read(DataSource source = DataSource.Cache) { Storage value = Storage.Empty; value.Byte = _group.ReadByte(_plcAddress, source).Value; return value; } - public override int Write(object value) - { + public override int Write(object value) { byte temp = _value.Byte; var str = value as string; if (str == null) @@ -284,65 +238,57 @@ namespace DataService return _group.WriteBits(_plcAddress, temp); } - protected override int InnerWrite(Storage value) - { + protected override int InnerWrite(Storage value) { return _group.WriteBits(_plcAddress, value.Byte); } #endregion - public override string ToString() - { + public override string ToString() { return _value.Byte.ToString(); } } - public sealed class ShortTag : ITag - { - + public sealed class ShortTag : ITag { public ShortTag(short id, DeviceAddress addr, IGroup group) - : base(id, addr, group) - { - } + : base(id, addr, group) { } #region IDevice Members - public override bool Refresh(DataSource source = DataSource.Device) - { + + public override bool Refresh(DataSource source = DataSource.Device) { var _newvalue = _group.ReadInt16(_plcAddress, source); - if (_newvalue.Value != _value.Int16) - { + if (_newvalue.Value != _value.Int16) { Storage value = Storage.Empty; value.Int16 = _newvalue.Value; DateTime time = _newvalue.TimeStamp.ToDateTime(); - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); } + _timeStamp = time; _quality = _newvalue.Quality; - if (_quality == QUALITIES.QUALITY_GOOD) - { + if (_quality == QUALITIES.QUALITY_GOOD) { _value = value; - if (ValueChanged != null) - { + if (ValueChanged != null) { ValueChanged(this, new ValueChangedEventArgs(value)); } } + return true; } + return false; } - public override Storage Read(DataSource source = DataSource.Cache) - { + public override Storage Read(DataSource source = DataSource.Cache) { Storage value = Storage.Empty; value.Int16 = _group.ReadInt16(_plcAddress, source).Value; return value; } - public override int Write(object value) - { + public override int Write(object value) { var temp = _value.Int16; var str = value as string; if (str == null) @@ -353,64 +299,56 @@ namespace DataService return _group.WriteInt16(_plcAddress, temp); } - protected override int InnerWrite(Storage value) - { + protected override int InnerWrite(Storage value) { return _group.WriteInt16(_plcAddress, value.Int16); } #endregion - public override string ToString() - { + public override string ToString() { return _value.Int16.ToString(); } } - public sealed class IntTag : ITag - { - + public sealed class IntTag : ITag { public IntTag(short id, DeviceAddress addr, IGroup group) - : base(id, addr, group) - { - } + : base(id, addr, group) { } #region IDevice Members - public override bool Refresh(DataSource source = DataSource.Device) - { + + public override bool Refresh(DataSource source = DataSource.Device) { var _newvalue = _group.ReadInt32(_plcAddress, source); - if (_newvalue.Value != _value.Int32) - { + if (_newvalue.Value != _value.Int32) { Storage value = Storage.Empty; value.Int32 = _newvalue.Value; DateTime time = _newvalue.TimeStamp.ToDateTime(); - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); } + _timeStamp = time; _quality = _newvalue.Quality; - if (_quality == QUALITIES.QUALITY_GOOD) - { + if (_quality == QUALITIES.QUALITY_GOOD) { _value = value; - if (ValueChanged != null) - { + if (ValueChanged != null) { ValueChanged(this, new ValueChangedEventArgs(value)); } } + return true; } + return false; } - public override Storage Read(DataSource source = DataSource.Cache) - { + public override Storage Read(DataSource source = DataSource.Cache) { Storage value = Storage.Empty; value.Int32 = _group.ReadInt32(_plcAddress, source).Value; return value; } - public override int Write(object value) - { + public override int Write(object value) { var temp = _value.Int32; var str = value as string; if (str == null) @@ -421,65 +359,57 @@ namespace DataService return _group.WriteInt32(_plcAddress, temp); } - protected override int InnerWrite(Storage value) - { + protected override int InnerWrite(Storage value) { return _group.WriteInt32(_plcAddress, value.Int32); } #endregion - public override string ToString() - { + public override string ToString() { return _value.Int32.ToString(); } } - public sealed class FloatTag : ITag - { - + public sealed class FloatTag : ITag { public FloatTag(short id, DeviceAddress addr, IGroup group) - : base(id, addr, group) - { - } + : base(id, addr, group) { } #region IDevice Members - public override bool Refresh(DataSource source = DataSource.Device) - { + + public override bool Refresh(DataSource source = DataSource.Device) { var _newvalue = _group.ReadFloat(_plcAddress, source); - if (_newvalue.Value != _value.Single) - { + if (_newvalue.Value != _value.Single) { Storage value = Storage.Empty; value.Single = _newvalue.Value; DateTime time = _newvalue.TimeStamp.ToDateTime(); - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(_newvalue.Quality, _value, value, _timeStamp, time)); } + _timeStamp = time; _quality = _newvalue.Quality; - if (_quality == QUALITIES.QUALITY_GOOD) - { + if (_quality == QUALITIES.QUALITY_GOOD) { _value = value; - if (ValueChanged != null) - { + if (ValueChanged != null) { ValueChanged(this, new ValueChangedEventArgs(value)); } } + return true; } + return false; } - public override Storage Read(DataSource source = DataSource.Cache) - { + public override Storage Read(DataSource source = DataSource.Cache) { Storage value = Storage.Empty; value.Single = _group.ReadFloat(_plcAddress, source).Value; return value; } - public override int Write(object value) - { + public override int Write(object value) { var temp = _value.Single; var str = value as string; if (str == null) @@ -490,103 +420,86 @@ namespace DataService return _group.WriteFloat(_plcAddress, temp); } - protected override int InnerWrite(Storage value) - { + protected override int InnerWrite(Storage value) { return _group.WriteFloat(_plcAddress, value.Single); } #endregion - public override string ToString() - { + public override string ToString() { return _value.Single.ToString(); } } - public sealed class StringTag : ITag - { + public sealed class StringTag : ITag { string _str; - public string String - { - get - { - return _str; - } - set - { - _str = value; - } + + public string String { + get { return _str; } + set { _str = value; } } public StringTag(short id, DeviceAddress addr, IGroup group) - : base(id, addr, group) - { - } + : base(id, addr, group) { } #region IDevice Members - public override bool Refresh(DataSource source = DataSource.Device) - { + + public override bool Refresh(DataSource source = DataSource.Device) { var _newvalue = _group.ReadString(_plcAddress, source); - if (_newvalue.Value != _str) - { + if (_newvalue.Value != _str) { DateTime time = _newvalue.TimeStamp.ToDateTime(); - if (ValueChanging != null) - { - ValueChanging(this, new ValueChangingEventArgs(_newvalue.Quality, _value, _value, _timeStamp, time)); + if (ValueChanging != null) { + ValueChanging(this, + new ValueChangingEventArgs(_newvalue.Quality, _value, _value, _timeStamp, time)); } + _timeStamp = time; _quality = _newvalue.Quality; - if (_quality == QUALITIES.QUALITY_GOOD) - { + if (_quality == QUALITIES.QUALITY_GOOD) { _str = _newvalue.Value; - if (ValueChanged != null) - { + if (ValueChanged != null) { ValueChanged(this, new ValueChangedEventArgs(_value)); } } + return true; } + return false; } - public override Storage Read(DataSource source = DataSource.Cache) - { + public override Storage Read(DataSource source = DataSource.Cache) { var value = _group.ReadString(_plcAddress, source); if (value.Quality == QUALITIES.QUALITY_GOOD) _str = value.Value; return Storage.Empty; } - public override int Write(object value) - { + public override int Write(object value) { if (value == null) return -1; - var str = (value is String) ? (String)value : value.ToString(); + var str = (value is String) ? (String) value : value.ToString(); _timeStamp = DateTime.Now; return _group.WriteString(_plcAddress, str); } - protected override int InnerWrite(Storage value) - { + protected override int InnerWrite(Storage value) { return _group.WriteString(_plcAddress, _str); } #endregion - public override string ToString() - { + public override string ToString() { return _str ?? string.Empty; } } - public enum DataSource - { + public enum DataSource { Cache = 1, Device = 2 } - public enum DataType : byte - { + public enum DataType : byte { NONE = 0, BOOL = 1, BYTE = 3, @@ -600,12 +513,11 @@ namespace DataService } public delegate void ValueChangingEventHandler(object sender, ValueChangingEventArgs e); + public delegate void ValueChangedEventHandler(object sender, ValueChangedEventArgs e); - public class ValueChangingEventArgs : EventArgs - { - public ValueChangingEventArgs(QUALITIES quality, T oldValue, T newValue, DateTime oldTime, DateTime newTime) - { + public class ValueChangingEventArgs : EventArgs { + public ValueChangingEventArgs(QUALITIES quality, T oldValue, T newValue, DateTime oldTime, DateTime newTime) { this.Quality = quality; this.OldValue = oldValue; this.NewValue = newValue; @@ -620,14 +532,11 @@ namespace DataService public DateTime NewTimeStamp; } - public class ValueChangedEventArgs : EventArgs - { - public ValueChangedEventArgs(Storage value) - { + public class ValueChangedEventArgs : EventArgs { + public ValueChangedEventArgs(Storage value) { this.Value = value; } public Storage Value; } - -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/PLCGroup.cs b/SCADA/Program/DataService/PLCGroup.cs index cea6922..034c2df 100644 --- a/SCADA/Program/DataService/PLCGroup.cs +++ b/SCADA/Program/DataService/PLCGroup.cs @@ -2,31 +2,22 @@ using System.Collections.Generic; using System.Timers; -namespace DataService -{ - public class PLCGroup : IGroup - { +namespace DataService { + public class PLCGroup : IGroup { protected Timer _timer; protected bool _isActive; - public virtual bool IsActive - { - get - { - return _isActive; - } - set - { + + public virtual bool IsActive { + get { return _isActive; } + set { _isActive = value; - if (value) - { + if (value) { if (_updateRate <= 0) _updateRate = 100; _timer.Interval = _updateRate; _timer.Elapsed += new ElapsedEventHandler(timer_Timer); _timer.Start(); - } - else - { + } else { _timer.Elapsed -= new ElapsedEventHandler(timer_Timer); _timer.Stop(); } @@ -34,98 +25,65 @@ namespace DataService } protected short _id; - public short ID - { - get - { - return _id; - } + + public short ID { + get { return _id; } } protected int _updateRate; - public int UpdateRate - { - get - { - return _updateRate; - } - set - { - _updateRate = value; - } + + public int UpdateRate { + get { return _updateRate; } + set { _updateRate = value; } } protected string _name; - public string Name - { - get - { - return _name; - } - set - { - _name = value; - } + + public string Name { + get { return _name; } + set { _name = value; } } protected float _deadband; - public float DeadBand - { - get - { - return _deadband; - } - set - { - _deadband = value; - } + + public float DeadBand { + get { return _deadband; } + set { _deadband = value; } } protected ICache _cacheReader; protected IPLCDriver _plcReader; - public IDriver Parent - { - get - { - return _plcReader; - } + + public IDriver Parent { + get { return _plcReader; } } protected List _changedList; - public List ChangedList - { - get - { - return _changedList; - } + + public List ChangedList { + get { return _changedList; } } protected List _items; - public IEnumerable Items - { + + public IEnumerable Items { get { return _items; } } protected IDataServer _server; - public IDataServer Server - { - get - { - return _server; - } + + public IDataServer Server { + get { return _server; } } protected List _rangeList = new List(); - protected PLCGroup() - { - } + protected PLCGroup() { } - public PLCGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) - { + public PLCGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) { this._id = id; this._name = name; this._updateRate = updateRate; @@ -137,24 +95,19 @@ namespace DataService this._timer = new Timer(); } - public bool AddItems(IList items) - { + public bool AddItems(IList items) { int count = items.Count; if (_items == null) _items = new List(count); - lock (_server.SyncRoot) - { - for (int i = 0; i < count; i++) - { + lock (_server.SyncRoot) { + for (int i = 0; i < count; i++) { ITag dataItem = null; TagMetaData meta = items[i]; - if (meta.GroupID == this._id) - { + if (meta.GroupID == this._id) { DeviceAddress addr = _plcReader.GetDeviceAddress(meta.Address); if (addr.DataSize == 0) addr.DataSize = meta.Size; if (addr.VarType == DataType.NONE) addr.VarType = meta.DataType; if (addr.VarType != DataType.BOOL) addr.Bit = 0; - switch (meta.DataType) - { + switch (meta.DataType) { case DataType.BOOL: dataItem = new BoolTag(meta.ID, addr, this); break; @@ -176,8 +129,8 @@ namespace DataService dataItem = new StringTag(meta.ID, addr, this); break; } - if (dataItem != null) - { + + if (dataItem != null) { //dataItem.Active = meta.Active; _items.Add(dataItem); _server.AddItemIndex(meta.Name, dataItem); @@ -185,217 +138,190 @@ namespace DataService } } } + _items.TrimExcess(); _items.Sort(); UpdatePDUArea(); return true; } - public bool AddTags(IEnumerable tags) - { - if (_items == null) - { + public bool AddTags(IEnumerable tags) { + if (_items == null) { _items = new List(); } - foreach (ITag tag in tags) - { - if (tag != null) - { + + foreach (ITag tag in tags) { + if (tag != null) { _items.Add(tag); } } + _items.TrimExcess(); _items.Sort(); UpdatePDUArea(); return true; } - public bool RemoveItems(params ITag[] items) - { - foreach (var item in items) - { + public bool RemoveItems(params ITag[] items) { + foreach (var item in items) { _server.RemoveItemIndex(item.GetTagName()); _items.Remove(item); } + UpdatePDUArea(); return true; } - protected void UpdatePDUArea() - { + protected void UpdatePDUArea() { int count = _items.Count; - if (count > 0) - { + if (count > 0) { DeviceAddress _start = _items[0].Address; _start.Bit = 0; int bitCount = _cacheReader.ByteCount; - if (count > 1) - { - int cacheLength = 0;//缓冲区的大小 + if (count > 1) { + int cacheLength = 0; //缓冲区的大小 int cacheIndexStart = 0; int startIndex = 0; DeviceAddress segmentEnd = DeviceAddress.Empty; DeviceAddress tagAddress = DeviceAddress.Empty; DeviceAddress segmentStart = _start; - for (int j = 1, i = 1; i < count; i++, j++) - { - tagAddress = _items[i].Address;//当前变量地址 + for (int j = 1, + i = 1; + i < count; + i++, j++) { + tagAddress = _items[i].Address; //当前变量地址 int offset1 = _cacheReader.GetOffset(tagAddress, segmentStart); - if (offset1 > (_plcReader.PDU - tagAddress.DataSize) / bitCount) - { + if (offset1 > (_plcReader.PDU - tagAddress.DataSize) / bitCount) { segmentEnd = _items[i - 1].Address; int len = _cacheReader.GetOffset(segmentEnd, segmentStart); len += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; - tagAddress.CacheIndex = (ushort)(cacheIndexStart + len); + tagAddress.CacheIndex = (ushort) (cacheIndexStart + len); _items[i].Address = tagAddress; _rangeList.Add(new PDUArea(segmentStart, len, startIndex, j)); - startIndex += j; j = 0; - cacheLength += len;//更新缓存长度 + startIndex += j; + j = 0; + cacheLength += len; //更新缓存长度 cacheIndexStart = cacheLength; - segmentStart = tagAddress;//更新数据片段的起始地址 - } - else - { - tagAddress.CacheIndex = (ushort)(cacheIndexStart + offset1); + segmentStart = tagAddress; //更新数据片段的起始地址 + } else { + tagAddress.CacheIndex = (ushort) (cacheIndexStart + offset1); _items[i].Address = tagAddress; } - if (i == count - 1) - { + + if (i == count - 1) { segmentEnd = _items[i].Address; int segmentLength = _cacheReader.GetOffset(segmentEnd, segmentStart); - if (segmentLength > (_plcReader.PDU - segmentEnd.DataSize) / bitCount) - { + if (segmentLength > (_plcReader.PDU - segmentEnd.DataSize) / bitCount) { segmentEnd = _items[i - 1].Address; segmentLength = segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; } - tagAddress.CacheIndex = (ushort)(cacheIndexStart + segmentLength); + + tagAddress.CacheIndex = (ushort) (cacheIndexStart + segmentLength); _items[i].Address = tagAddress; segmentLength += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; _rangeList.Add(new PDUArea(segmentStart, segmentLength, startIndex, j + 1)); cacheLength += segmentLength; } } + _cacheReader.Size = cacheLength; - } - else - { - var size= _start.DataSize <= bitCount ? 1 : _start.DataSize / bitCount; + } else { + var size = _start.DataSize <= bitCount ? 1 : _start.DataSize / bitCount; _rangeList.Add(new PDUArea(_start, size, 0, 1)); - _cacheReader.Size = size;//改变Cache的Size属性值将创建Cache的内存区域 + _cacheReader.Size = size; //改变Cache的Size属性值将创建Cache的内存区域 } } } - public ITag FindItemByAddress(DeviceAddress addr) - { + public ITag FindItemByAddress(DeviceAddress addr) { int index = _items.BinarySearch(new BoolTag(0, addr, null)); return index < 0 ? null : _items[index]; } - public bool SetActiveState(bool active, params short[] items) - { + public bool SetActiveState(bool active, params short[] items) { return false; } object sync = new object(); - protected void timer_Timer(object sender, EventArgs e) - { - if (_isActive) - { - lock (sync) - { + + protected void timer_Timer(object sender, EventArgs e) { + if (_isActive) { + lock (sync) { Poll(); if (_changedList.Count > 0) Update(); } - } - else + } else return; } - protected virtual int Poll() - { + protected virtual int Poll() { if (_plcReader.IsClosed) return -1; - byte[] cache = (byte[])_cacheReader.Cache; + byte[] cache = (byte[]) _cacheReader.Cache; int offset = 0; - foreach (PDUArea area in _rangeList) - { - byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 - if (rcvBytes == null) - { + foreach (PDUArea area in _rangeList) { + byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort) area.Len); //从PLC读取数据 + if (rcvBytes == null) { //_plcReader.Connect(); return -1; - } - else - { - int index = area.StartIndex;//index指向_items中的Tag元数据 + } else { + int index = area.StartIndex; //index指向_items中的Tag元数据 int count = index + area.Count; - while (index < count) - { + while (index < count) { DeviceAddress addr = _items[index].Address; int iByte = addr.CacheIndex; int iByte1 = iByte - offset; - if (addr.VarType == DataType.BOOL) - { + if (addr.VarType == DataType.BOOL) { int tmp = rcvBytes[iByte1] ^ cache[iByte]; DeviceAddress next = addr; - if (tmp != 0) - { - while (addr.Start == next.Start) - { + if (tmp != 0) { + while (addr.Start == next.Start) { if ((tmp & (1 << next.Bit)) > 0) _changedList.Add(index); if (++index < count) next = _items[index].Address; else break; } - } - else - { - while (addr.Start == next.Start && ++index < count) - { + } else { + while (addr.Start == next.Start && ++index < count) { next = _items[index].Address; } } - } - else - { + } else { ushort size = addr.DataSize; - for (int i = 0; i < size; i++) - { - if (rcvBytes[iByte1 + i] != cache[iByte + i]) - { + for (int i = 0; i < size; i++) { + if (rcvBytes[iByte1 + i] != cache[iByte + i]) { _changedList.Add(index); break; } } + index++; } } + for (int j = 0; j < rcvBytes.Length; j++) - cache[j + offset] = rcvBytes[j];//将PLC读取的数据写入到CacheReader中 + cache[j + offset] = rcvBytes[j]; //将PLC读取的数据写入到CacheReader中 } + offset += rcvBytes.Length; } + return 1; } - protected void Update() - { + protected void Update() { DateTime dt = DateTime.Now; - if (DataChange != null) - { + if (DataChange != null) { HistoryData[] values = new HistoryData[_changedList.Count]; int i = 0; - foreach (int index in _changedList) - { + foreach (int index in _changedList) { ITag item = _items[index]; var itemData = item.Read(); if (item.Active) item.Update(itemData, dt, QUALITIES.QUALITY_GOOD); if (_deadband == 0 || (item.Address.VarType == DataType.FLOAT && - (Math.Abs(itemData.Single / item.Value.Single - 1) > _deadband))) - { + (Math.Abs(itemData.Single / item.Value.Single - 1) > _deadband))) { values[i].ID = item.ID; values[i].Quality = item.Quality; values[i].Value = itemData; @@ -403,54 +329,44 @@ namespace DataService i++; } } - foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList()) - { + + foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList()) { deleg.BeginInvoke(this, new DataChangeEventArgs(1, values), null, null); } - } - else - { - foreach (int index in _changedList) - { + } else { + foreach (int index in _changedList) { ITag item = _items[index]; if (item.Active) item.Update(item.Read(), dt, QUALITIES.QUALITY_GOOD); } } + _changedList.Clear(); } - public void Dispose() - { + public void Dispose() { if (_timer != null) _timer.Dispose(); //if (_items != null) // _items.Clear(); } - public virtual HistoryData[] BatchRead(DataSource source, bool isSync, params ITag[] itemArray) - { + public virtual HistoryData[] BatchRead(DataSource source, bool isSync, params ITag[] itemArray) { int len = itemArray.Length; HistoryData[] values = new HistoryData[len]; - if (source == DataSource.Device) - { + if (source == DataSource.Device) { IMultiReadWrite multi = _plcReader as IMultiReadWrite; - if (multi != null) - { + if (multi != null) { Array.Sort(itemArray); var itemArr = multi.ReadMultiple(Array.ConvertAll(itemArray, x => x.Address)); - for (int i = 0; i < len; i++) - { + for (int i = 0; i < len; i++) { values[i].ID = itemArray[i].ID; values[i].Value = itemArr[i].Value; values[i].TimeStamp = itemArr[i].TimeStamp.ToDateTime(); itemArray[i].Update(itemArr[i].Value, values[i].TimeStamp, itemArr[i].Quality); } - } - else - { - for (int i = 0; i < len; i++) - { + } else { + for (int i = 0; i < len; i++) { itemArray[i].Refresh(source); values[i].ID = itemArray[i].ID; values[i].Value = itemArray[i].Value; @@ -458,52 +374,44 @@ namespace DataService values[i].TimeStamp = itemArray[i].TimeStamp; } } - } - else - { - for (int i = 0; i < len; i++) - { + } else { + for (int i = 0; i < len; i++) { values[i].ID = itemArray[i].ID; values[i].Value = itemArray[i].Value; values[i].Quality = itemArray[i].Quality; values[i].TimeStamp = itemArray[i].TimeStamp; } } + return values; } - public virtual int BatchWrite(SortedDictionary items, bool isSync = true) - { + public virtual int BatchWrite(SortedDictionary items, bool isSync = true) { int len = items.Count; int rev = 0; IMultiReadWrite multi = _plcReader as IMultiReadWrite; - if (multi != null) - { + if (multi != null) { DeviceAddress[] addrs = new DeviceAddress[len]; object[] objs = new object[len]; int i = 0; - foreach (var item in items) - { + foreach (var item in items) { addrs[i] = item.Key.Address; objs[i] = item.Value; i++; } + rev = multi.WriteMultiple(addrs, objs); - } - else - { - foreach (var tag in items) - { + } else { + foreach (var tag in items) { if (tag.Key.Write(tag.Value) < 0) rev = -1; } } - if (DataChange != null && rev >= 0) - { + + if (DataChange != null && rev >= 0) { HistoryData[] data = new HistoryData[len]; int i = 0; - foreach (var item in items) - { + foreach (var item in items) { ITag tag = item.Key; data[i].ID = tag.ID; data[i].TimeStamp = tag.TimeStamp; @@ -511,156 +419,150 @@ namespace DataService data[i].Value = item.Key.ToStorage(item.Value); i++; } - foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList()) - { + + foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList()) { deleg.BeginInvoke(this, new DataChangeEventArgs(1, data), null, null); } } + return rev; } - public ItemData ReadInt32(DeviceAddress address, DataSource source = DataSource.Cache) - { + public ItemData ReadInt32(DeviceAddress address, DataSource source = DataSource.Cache) { return source == DataSource.Cache ? _cacheReader.ReadInt32(address) : _plcReader.ReadInt32(address); } - public ItemData ReadInt16(DeviceAddress address, DataSource source = DataSource.Cache) - { + public ItemData ReadInt16(DeviceAddress address, DataSource source = DataSource.Cache) { return source == DataSource.Cache ? _cacheReader.ReadInt16(address) : _plcReader.ReadInt16(address); } - public ItemData ReadByte(DeviceAddress address, DataSource source = DataSource.Cache) - { + public ItemData ReadByte(DeviceAddress address, DataSource source = DataSource.Cache) { return source == DataSource.Cache ? _cacheReader.ReadByte(address) : _plcReader.ReadByte(address); } - public ItemData ReadFloat(DeviceAddress address, DataSource source = DataSource.Cache) - { + public ItemData ReadFloat(DeviceAddress address, DataSource source = DataSource.Cache) { return source == DataSource.Cache ? _cacheReader.ReadFloat(address) : _plcReader.ReadFloat(address); } - public ItemData ReadBool(DeviceAddress address, DataSource source = DataSource.Cache) - { + public ItemData ReadBool(DeviceAddress address, DataSource source = DataSource.Cache) { return source == DataSource.Cache ? _cacheReader.ReadBit(address) : _plcReader.ReadBit(address); } - public ItemData ReadString(DeviceAddress address, DataSource source = DataSource.Cache) - { + public ItemData ReadString(DeviceAddress address, DataSource source = DataSource.Cache) { ushort siz = address.DataSize; - return source == DataSource.Cache ? _cacheReader.ReadString(address, siz) : - _plcReader.ReadString(address, siz); + return source == DataSource.Cache + ? _cacheReader.ReadString(address, siz) + : _plcReader.ReadString(address, siz); } - public int WriteInt32(DeviceAddress address, int value) - { + public int WriteInt32(DeviceAddress address, int value) { int rs = _plcReader.WriteInt32(address, value); - if (rs >= 0) - { - if (DataChange != null) - { + if (rs >= 0) { + if (DataChange != null) { ITag tag = GetTagByAddress(address); if (tag != null) - DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] - { - new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Int32=value}, DateTime.Now) - })); + DataChange(this, + new DataChangeEventArgs(1, + new HistoryData[1] { + new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Int32 = value}, + DateTime.Now) + })); } } + return rs; } - public int WriteInt16(DeviceAddress address, short value) - { + public int WriteInt16(DeviceAddress address, short value) { int rs = _plcReader.WriteInt16(address, value); - if (rs >= 0) - { - if (DataChange != null) - { + if (rs >= 0) { + if (DataChange != null) { ITag tag = GetTagByAddress(address); if (tag != null) - DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] - { - new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Int16=value}, DateTime.Now) - })); + DataChange(this, + new DataChangeEventArgs(1, + new HistoryData[1] { + new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Int16 = value}, + DateTime.Now) + })); } } + return rs; } - public int WriteFloat(DeviceAddress address, float value) - { + public int WriteFloat(DeviceAddress address, float value) { int rs = _plcReader.WriteFloat(address, value); - if (rs >= 0) - { - if (DataChange != null) - { + if (rs >= 0) { + if (DataChange != null) { ITag tag = GetTagByAddress(address); if (tag != null) - DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] - { - new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Single=value}, DateTime.Now) - })); + DataChange(this, + new DataChangeEventArgs(1, + new HistoryData[1] { + new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Single = value}, + DateTime.Now) + })); } } + return rs; } - public int WriteString(DeviceAddress address, string value) - { + public int WriteString(DeviceAddress address, string value) { int rs = _plcReader.WriteString(address, value); - if (rs >= 0) - { - if (DataChange != null) - { + if (rs >= 0) { + if (DataChange != null) { ITag tag = GetTagByAddress(address); if (tag != null) - DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] - { - new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,Storage.Empty, DateTime.Now) - })); + DataChange(this, + new DataChangeEventArgs(1, + new HistoryData[1] { + new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, Storage.Empty, DateTime.Now) + })); } } + return rs; } - public int WriteBit(DeviceAddress address, bool value) - { + public int WriteBit(DeviceAddress address, bool value) { int rs = _plcReader.WriteBit(address, value); - if (rs >= 0) - { - if (DataChange != null) - { + if (rs >= 0) { + if (DataChange != null) { ITag tag = GetTagByAddress(address); if (tag != null) - DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] - { - new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Boolean=value}, DateTime.Now) - })); + DataChange(this, + new DataChangeEventArgs(1, + new HistoryData[1] { + new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Boolean = value}, + DateTime.Now) + })); } } + return rs; } - public int WriteBits(DeviceAddress address, byte value) - { + public int WriteBits(DeviceAddress address, byte value) { int rs = _plcReader.WriteBits(address, value); - if (rs >= 0) - { - if (DataChange != null) - { + if (rs >= 0) { + if (DataChange != null) { ITag tag = GetTagByAddress(address); if (tag != null) - DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] - { - new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Byte=value}, DateTime.Now) - })); + DataChange(this, + new DataChangeEventArgs(1, + new HistoryData[1] { + new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Byte = value}, + DateTime.Now) + })); } } + return rs; } - private ITag GetTagByAddress(DeviceAddress addr) - { + private ITag GetTagByAddress(DeviceAddress addr) { int index = _items.BinarySearch(new BoolTag(0, addr, null)); return index < 0 ? null : _items[index]; } @@ -669,19 +571,17 @@ namespace DataService } - public struct PDUArea - { + public struct PDUArea { public DeviceAddress Start; public int Len; public int StartIndex; public int Count; - public PDUArea(DeviceAddress start, int len, int startIndex, int count) - { + public PDUArea(DeviceAddress start, int len, int startIndex, int count) { Start = start; Len = len; StartIndex = startIndex; Count = count; } } -} +} \ No newline at end of file diff --git a/SCADA/Program/DataService/Storage.cs b/SCADA/Program/DataService/Storage.cs index 1c2df0b..501d7c1 100644 --- a/SCADA/Program/DataService/Storage.cs +++ b/SCADA/Program/DataService/Storage.cs @@ -1,76 +1,73 @@ using System.Runtime.InteropServices; using System; -namespace DataService -{ +namespace DataService { [StructLayout(LayoutKind.Explicit, Size = 4)] - public struct Storage - { + public struct Storage { // Fields [FieldOffset(0)] public bool Boolean; + [FieldOffset(0)] public byte Byte; + [FieldOffset(0)] public short Int16; + [FieldOffset(0)] public int Int32; + [FieldOffset(0)] public float Single; - public static readonly Storage Empty ; + public static readonly Storage Empty; - static Storage() - { + static Storage() { Empty = new Storage(); } - public override bool Equals(object obj) - { + public override bool Equals(object obj) { if (obj == null) return false; Type type = obj.GetType(); if (type == typeof(Storage)) - return this.Int32 == ((Storage)obj).Int32; - else - { + return this.Int32 == ((Storage) obj).Int32; + else { if (type == typeof(Int32)) - return this.Int32 == (Int32)obj; + return this.Int32 == (Int32) obj; if (type == typeof(Int16)) - return this.Int16 == (Int16)obj; + return this.Int16 == (Int16) obj; if (type == typeof(Byte)) - return this.Byte == (Byte)obj; + return this.Byte == (Byte) obj; if (type == typeof(Boolean)) - return this.Boolean == (Boolean)obj; + return this.Boolean == (Boolean) obj; if (type == typeof(Single)) - return this.Single == (Single)obj; + return this.Single == (Single) obj; if (type == typeof(String)) return this.ToString() == obj.ToString(); } + return false; } - public override int GetHashCode() - { + public override int GetHashCode() { return Int32.GetHashCode(); } - public static bool operator ==(Storage x, Storage y) - { + public static bool operator ==(Storage x, Storage y) { return x.Int32 == y.Int32; } - public static bool operator !=(Storage x, Storage y) - { + public static bool operator !=(Storage x, Storage y) { return x.Int32 != y.Int32; - } + } } - public enum QUALITIES : short - { + public enum QUALITIES : short { // Fields LIMIT_CONST = 3, LIMIT_HIGH = 2, LIMIT_LOW = 1, + //LIMIT_MASK = 3, //LIMIT_OK = 0, QUALITY_BAD = 0, diff --git a/SCADA/Program/DataService/TagMetaData.cs b/SCADA/Program/DataService/TagMetaData.cs index b8f9fec..6b97c09 100644 --- a/SCADA/Program/DataService/TagMetaData.cs +++ b/SCADA/Program/DataService/TagMetaData.cs @@ -1,11 +1,9 @@ using System; using System.Runtime.InteropServices; -namespace DataService -{ +namespace DataService { [StructLayout(LayoutKind.Sequential)] - public struct TagMetaData : IComparable - { + public struct TagMetaData : IComparable { public bool Archive; public DataType DataType; @@ -27,8 +25,7 @@ namespace DataService public string Name; public TagMetaData(short id, short grpId, string name, string address, - DataType type, ushort size, bool archive = false, float max = 0, float min = 0, int cycle = 0) - { + DataType type, ushort size, bool archive = false, float max = 0, float min = 0, int cycle = 0) { ID = id; GroupID = grpId; Name = name; @@ -41,20 +38,17 @@ namespace DataService Cycle = cycle; } - public int CompareTo(TagMetaData other) - { - return this.ID.CompareTo(other.ID); + public int CompareTo(TagMetaData other) { + return ID.CompareTo(other.ID); } - public override string ToString() - { + public override string ToString() { return Name; } } [StructLayout(LayoutKind.Sequential)] - public struct Scaling : IComparable - { + public struct Scaling : IComparable { public short ID; public ScaleType ScaleType; @@ -67,8 +61,7 @@ namespace DataService public float RawLo; - public Scaling(short id, ScaleType type, float euHi, float euLo, float rawHi, float rawLo) - { + public Scaling(short id, ScaleType type, float euHi, float euLo, float rawHi, float rawLo) { ID = id; ScaleType = type; EUHi = euHi; @@ -77,32 +70,28 @@ namespace DataService RawLo = rawLo; } - public int CompareTo(Scaling other) - { + public int CompareTo(Scaling other) { return ID.CompareTo(other.ID); } - public static readonly Scaling Empty = new Scaling { ScaleType = ScaleType.None }; + public static readonly Scaling Empty = new Scaling {ScaleType = ScaleType.None}; } - public struct ItemData - { + public struct ItemData { public T Value; public long TimeStamp; public QUALITIES Quality; - public ItemData(T value, long timeStamp, QUALITIES quality) - { + public ItemData(T value, long timeStamp, QUALITIES quality) { Value = value; TimeStamp = timeStamp; Quality = quality; } } - public enum ScaleType : byte - { + public enum ScaleType : byte { None = 0, Linear = 1, SquareRoot = 2 } -} +} \ No newline at end of file diff --git a/SCADA/Program/FileDriver/obj/Debug/FileDriver.csprojAssemblyReference.cache b/SCADA/Program/FileDriver/obj/Debug/FileDriver.csprojAssemblyReference.cache index 033ea347643c1d08ab55348484e0a6f629bb5644..962dfa45457ccce01829151be956071e02b53b04 100644 GIT binary patch delta 2106 zcmZWpTW?!M5cZzt9A}SXJ8m2&&ZXg{szAX>RfnXZw&VKNgv52~G%6LSGRBb%cAWYW z)PfZ9(1)l{DAR`uBt%6J7x55qLyR4=j3OKfe0nVU@}lPo*nW!4RU3Qx(QLNVicGMAIg@SCv6nxRXWWE|dMr>ir& zR+zwAAR#$nTimnDBwFG3rhgKv=h*748{5qcsdy)Wo1hCp>PCI0E z)?NgwCmxxJ7E}4mGlk;Q(jKyha@ov$xf+*#5?Ujx6~g(K;*namm~c@3#hq1E}&bf*`?Rf)GKNAVLr& zh#@#!2qa=BERSr!x0cJ{BREy~lbPaTHl30AI9m7wxuH-JYL4s19IqO4oPxJojxIgv?*WDZhZAi+baywNsOoEf`KM z%QBkyMFeq7VYIx0x^_rt-s@*U#q7F_X2(=ET`ZIeb7jwLwp2;wLU3xIpB+{_?60GT z@w}hi?`I)piLJs*qi*QwKg7a{0p>i@f*4Ws$Ja2i!?WX0Xe54K4g*odv%tQOrmbZ6w+tqL@Oo^a<*EFH&F2 zd=oAFQv_X9(x8!atdVpJ-R;yLBm$!*p&yH0tYjq-ss8(G*Z$^(5n=K=nha0=IZpW( z2)d{VJZwy0v@wCN&|OR@r#kvI>h-7k1}*%i&WK-?bjV2RZ6v*gp5nAZI`KW~S{=#! z2b}QR2)d|z14ceiBi|i#we3=_NBefys9z;F95S%j!2gN7p-029n7$9xw7W4^2la%qV~vU$MBQH zulJzJS3Ncq531bytf`Duk1fT6N~_+3>P+!?km_d;2MPaM{hI7lH}w%zL}~;TM`Hw4 nMtua8i5fxA-x#so5b=v10k4hg_w{Q{>z!z~Fv>88gIWFqXw(xm delta 2022 zcmZWpO>7%Q6wYkC>&&{2Z5rEgli(n=ib}#JQ9`ApwVkN`Nu1P8^W&xkghDXL)NY95 zrV1QF4+up8DdJTK!2u3%Ln38SOGOhz_)AMwQb^kihl(qp-Z*dx@9lb*wf0H#dFIVG z-@JYAjW;ec^)g#uVNR*0rbd>Xu*RBL0X}1S7^`(KC%h+&vN{M0Mfvz#DW|+xC`cTa zi|S8F_|pQ6mu8nO6Q~l z=gyaz8^)xDa1(lXGeHaOJ&qtR_9|UUPghTOUyYiPeifY3#L_}JSA-6}#mexA z&r2ALEOo+y_mtFyN1Q&m<&A;ls(1Mw!!?=M0Q0S1!&~n6l2el{ob zr_sZY5DksdSSGl+x3{;8!|?_#wsG!5{*ulj#9$S_9ay1`vlo`7%quIXNpOk?(AV zpXAtb3a5OCV3;6HFoNKtbds?!f*#2z&WuPX8~g-1c!uC4LUknT)<{0LMlz1vrI+%B zTz_XL{KH>?M=qI7z`w4nXA-xZtq7VJhaLIIfhk<^EWv4lX@WBZXI0VX6Idg#q5bNU z`&UKyb}*=JHf98uT*=pTu>j3YkwYG;7n#7QXw+UtwB#idkE-*nZoy4;tSc_e&Xo%J z7vN$`lpWJHyl>)$@%2;(co2>VVno|aui|E<%VhpGF8DhLhUv8_RWd?eHgCy@EX(NP zYY3hgyc!P$2XI=4L%8zm_o>Wc=o)cPVRPO4~ zsP=kjlUis~+L_TS*3e}B1unUYV3?kiQEO60>`A$bbTO+brmx}LO!8N_;MWZ?{MGf6 zR=tE>?*=l()0!UJfX=pHWRrxxu?Y=Wg<^K0EfSj6gfidZ+>$w&e@~h}*fjgCntgW7 zZPGlW2X_CGBUf{{W&c00;m8 diff --git a/SCADA/Program/HMIControl/bin/Debug/DataHelper.dll b/SCADA/Program/HMIControl/bin/Debug/DataHelper.dll index 53c6bec1e3bc4e188c6408617f26130f43e7c32a..711b2c78d4f896229682658641c0c24c1524cee5 100644 GIT binary patch delta 87 zcmZp;!PIbrX+j6n1f7jtUeg3TkJRVhzy8E|#sdrH`R8w}+Wcgi4X@4woxL#(K)?jV qGK>ri7Kea%2?Ik=uuJeif61V^%7>j+9(%Jg)PC}>%|1)Eumb=lk|Ngt delta 87 zcmZp;!PIbrX+j56z1GGquW14g^}Ct&PE~T68Y7XZzA@8w^OI>dygKz-dt(@YfC-3Y o7#SEW4gv8J28N(um*7<$QEXdR+j=*gy;b=^IraBupCwz^0aY&_W&i*H diff --git a/SCADA/Program/HMIControl/bin/Debug/DataHelper.pdb b/SCADA/Program/HMIControl/bin/Debug/DataHelper.pdb index c0bd63995d0697bd183800eb43d05306962cc263..7fec1ce4d45e6c25452e130e886d0e5ebbf04c92 100644 GIT binary patch delta 85 zcmZpe!`d*1bps2R!~~taF^mih4FCKkgXSt9c3OGt&B{>w$-g$saJ>;`wJx~WxUHF2 UZac3W<9BtOinq(SF+O1j0B3$7WdHyG delta 85 zcmZpe!`d*1bps2RM7`GD7)AyLhE*L=Y+F~`dN-WCRrx_V_4j5Ot~bK0?{(|lwl?$1 TZReF^{H~5u@pc(E#wY9mRm~vy diff --git a/SCADA/Program/HMIControl/bin/Debug/DataService.dll b/SCADA/Program/HMIControl/bin/Debug/DataService.dll index 8d546c23ab5e2c6b613787ab4d14fc6a0aef4bec..46effd4ef6077f34b33147d021d81fd15fe34d0d 100644 GIT binary patch delta 72 zcmZo@U~On%ozTHFL8q~6YZqgmw19C|=&@hAkDaERu&Alptn_8Oh798a37~@MT&9dt c0y^Jx*@}O#Id|)Qd>Hq)$ delta 72 zcmZo@U~On%ozTHltJT=GwTrP&TEO*5+KdT8oNmjskLCG=fBdjrLx%Bz1W>_rE>lJ+ c0Rt1~39qI3U1#+3YCGKJ+Ogfll<^D~0Mb?&*8l(j diff --git a/SCADA/Program/HMIControl/bin/Debug/DataService.pdb b/SCADA/Program/HMIControl/bin/Debug/DataService.pdb index a44bd75133dbb98c88bd2e5a15d89a625a1f60d4..29a479e170da521cd48ec6236792fc0c7975ee16 100644 GIT binary patch delta 977 zcmZ|OziSg=90u_3*;ubBNo`Y&HqkSU*ETk(Em{$4+FmZnsj*sU%@lvo#ZkdQaIh&3 z1$7YK!GE9#B8Ym`PQk@7gU~@&!BGte{+QI~@!m=nhvUQhzE7Te@4ZXC8L2lT&qCon z53-G#AtKrDxy~CuJKcL@-@*%zf1mP`;p{;F+NQTu8(p6%?~VCO>yN7Wx%}dDXU%vq zWJb5Y-g$TBl^;3k8=>6o&$s+HllQx=UXeQcXjt1TeG(H}hGbY>b8M?mXQ+t`4Khf` zi1Hm<%{!)=^+Pds?EbfYkS*#5I^w#6vV*qYXR2UZ37w(rq3xOFf}Kg~3}p{(+lzd~ z+(}$b)o>E3_Q6aYK!R;FNT!AR+Dg7xMj@e+>t;NqJ86&%_Fr-BxQ#iU(=cS)NRUyh zZqCZ+wL_458ioBZt23MKgf*@+l)tBK`&Q|q{qXH4!;DX0fh9Bu;D{xot}^fxfl1v! zgFx`6o)m5C80NT3$`aasmsZhM*I$~c6PV{NXs|vgJe938Ij(ZWgf)d#wo$gxApQ3Q z)y`CTf7rvmR>{H8SC%%X=pXCDF1*`C|jH`F$oLkdt z7hyNnzO;VTqmW}h%OyAnFT*sv0`oF05gEfs1U+{=Z`Jb*T-!E0ucHzD?;mv|S?&1P F^9QJ1riuUn delta 817 zcmZ|OO=uHA7zW_kHo;_*-LR&*A-fo{L`0KXX$pc?ve|4_sXqs$ROz7=(Tmn7_}j*= zrWz00N=LdydlWqA!J3u^F`^)zax16@Jtzu=YI_q;;ycM4q+lRC%zQKN%$^(xSv}UzD+7@2>Nx!OaXrb# z-KWcZcPAT(zma&F&pX5C4blQmvy&#Xnv&|(;U>Cdw{bY>ziAYy0tJ^`FU!F6!FUKidt27M;CYcZQk>;!(3;g&fXXXAYcMw r8Ab+%7<)#B7)3^gpkSBa$@0^+ciAd>&t`op&&|1Y#`Xe5#tB>i>xCX_ delta 88 zcmZp;!P0PpWkLs2gVx3_rI!LnQyK)nn&!H!w7lwYc1h-e&3j&UnCmoX?Tujo0wy4q rVPs&4v1eq6QDkHY3U&z&O1u}l?O&DO>^*DZwZ8@WY%fq`oWKPD1y>;9 diff --git a/SCADA/Program/HMIControl/bin/Debug/HMIControl.VisualStudio.Design.pdb b/SCADA/Program/HMIControl/bin/Debug/HMIControl.VisualStudio.Design.pdb index 391c321cc7f594789751f9365d9bcfe70c0aef91..5f1773b91165bef0c524f13fadd190cce48d1366 100644 GIT binary patch delta 85 zcmZqZVQc7N+rYvlF;Qo43?l;r!({pC+PiEOy=SvNmFMQ%I%Bg8*Bez=)?6!YZezW(iiP!!X=(Aad>y0XFiZi$S)@ELV T?Ystz-(7Jk-Y!$d_=Fz-KX)K{ diff --git a/SCADA/Program/LinkableControlDesignTime/obj/Debug/HMIControl.VisualStudio.Design.dll b/SCADA/Program/LinkableControlDesignTime/obj/Debug/HMIControl.VisualStudio.Design.dll index 9b9bae60ccc9f8a250b9398f39b5e9a8e5418743..9c71577d694e3562faaa46665682b8b50a327044 100644 GIT binary patch delta 88 zcmZp;!P0PpWkLtjM4gRYN-qW0Etw+}dd|*c>dt27M;CYcZQk>;!(3;g&fXXXAYcMw r8Ab+%7<)#B7)3^gpkSBa$@0^+ciAd>&t`op&&|1Y#`Xe5#tB>i>xCX_ delta 88 zcmZp;!P0PpWkLs2gVx3_rI!LnQyK)nn&!H!w7lwYc1h-e&3j&UnCmoX?Tujo0wy4q rVPs&4v1eq6QDkHY3U&z&O1u}l?O&DO>^*DZwZ8@WY%fq`oWKPD1y>;9 diff --git a/SCADA/Program/LinkableControlDesignTime/obj/Debug/HMIControl.VisualStudio.Design.pdb b/SCADA/Program/LinkableControlDesignTime/obj/Debug/HMIControl.VisualStudio.Design.pdb index 391c321cc7f594789751f9365d9bcfe70c0aef91..5f1773b91165bef0c524f13fadd190cce48d1366 100644 GIT binary patch delta 85 zcmZqZVQc7N+rYvlF;Qo43?l;r!({pC+PiEOy=SvNmFMQ%I%Bg8*Bez=)?6!YZezW(iiP!!X=(Aad>y0XFiZi$S)@ELV T?Ystz-(7Jk-Y!$d_=Fz-KX)K{ diff --git a/SCADA/Program/ModbusDriver/obj/Debug/ModbusDriver.csprojAssemblyReference.cache b/SCADA/Program/ModbusDriver/obj/Debug/ModbusDriver.csprojAssemblyReference.cache index 705c3aeb2649c3f7910735143e7a3336b927b543..2d538ce7a1ae7799aff34a4562acf8e201ae7e25 100644 GIT binary patch delta 678 zcmcZ~|1y3BpgfIEy$3#f^me{v7E{bV;TK6Xw$AfHozav+zuy8)2N z2GPlB2og2|5yn7*5r{#6u^vR6`Tzg_Eg)uT0CG+P88?9#q=d~3NR&)g;Ln;Y$IZ@` zl9R*5W~0B0tUfB}f3ra>JA5@no<wGFa%Ku9z?=Oi(S(1Y4W~v{+Oax delta 713 zcmaDEe?NXhCnF>4$FFqUne!1RfUb)(^f^fQ~=Szj=*vjtZcm!#%S zuI4zzSTb3GKZ_S4pqG-9!^NgK*`7OavH%y~WPLvKJZ%OB22LFip$jAg1%LzyFbV+) zJ`jUV4@h!D4RFpcO6AlC3UC^L2t$wpAO-=(dJu8$|NsBDfS9EL$TRW*6d0?7@ksAOb C-Mowd diff --git a/SCADA/Program/SiemensPLCDriver/obj/Debug/SiemensPLCDriver.csprojAssemblyReference.cache b/SCADA/Program/SiemensPLCDriver/obj/Debug/SiemensPLCDriver.csprojAssemblyReference.cache index a4ec0eae879789fe8b4d644b84006b0504ec159f..421d90fc6c9a7dca9847f9e09a3c2a9366afe473 100644 GIT binary patch delta 2077 zcmZWpTTC2f6yAT?nPp~gY@uBiSPCd&x43s$XpyB*pw-$I7O`5CF3Z$x*-JaX8tR2M z29>liji(O{FO{TCw@%HHDkq2XaHob{IZmEl_KGf(hWQIM4GUDzo6Ln1Y51E38y( znGFYjTmR_#w{XSet`qYSU%(d*goE7%W<^&Eet!?YxbzKt$kp3~e9#y4MZ%$wfwRF~ z)7HsbOYGKn4}Ym-=qJWR zo?ciJc5yy5FF>E`f`yX!rqgMW_rq0w6#8mRd;qOxCwx^E+Z{w!2oZz{A_N_9Q~Z8o z)qIQ%b)sxbr>3&G=|o=gWu-Y$h>}kif=Ws=>}#w~4Vf-sdk>MJhNxfuAlw&5Sr6F6 zWBk*oFz<#*G3Mw+*0~3Ph^vKW=RKITtR9J>XgQpiOT;BPpGr!i(1#k~5CRdUEL41; zulS|D;$ieT0S^Q($ksMC2rJfSnH%i2G4~K!gkgds2u^x3B2xqO+Me6P_99<}ALEZA z@`Zr?LMNcdb&;KfP1guNf)VB>sxmW*tPm#{LvS`D5V6M)3hAFmt}-*5 z%*lAW!Z=F83k0VS=!8UtQ?BVx`LVwEY4pkCBcF4qi3$%r0gtNV{L5%HKMv2-#HL!2 zu9FEG9XXNyDQSUHm)c@vl>ShZev12Fhv^$LBMWoJ!7$!kefS-a=5R@bH&0pLR2s z%9CG4cLyyak&)3x(!b{a#AxN{_HmQ3PEz5ptzNAy+uNwqh7ta4^9*Wr7s~6thu)69 zVj3emgdEjXr?zM?a6_d6%cv|BnDBb+T7g+Au<@?9)o9iK_h7SK=af;L{%mhGn$@>= z`E~YJ$qxPg0Y=kS>4w}22eb5jp5gZLy0M?ZZ*P=BX zJ$eBC>Z-GA%Y8+4w!cqC{D_3x(AC{osB6ED3Y}p=Gpy`1+*b|UDjDFP?qcU0U2_1! U2a0kNU89y!on>|#wIndhe=2Ae7ytkO delta 2101 zcmZWo+fN*26yI;znPq0XyDSTGM=pX~!Ys?emRn13fmTJ7s}!qcS*Fdlduaw(Lye`; zU`p!)M8s z8G=(98=e|b!g2Zaq;i2TCw(Xul@rU%iE9UbmcGAsZr$9=XSft92r3Dx5cp~Y6R{;- z!z(Pk<9LPnn()XOi!LORi{X?kCFEsMXeP%N1YOt~u51qu4i4aPX%MCbukAP5{8D!u zz7Pso8;m(8m;~F-QQn89b`SjP9ANG6Nc5-fNpp{LLV-+7NN)Dk;>`~^RmHUKlQ?@pGnp}IR2#0|$UO8i9`affg;`t+rwHZ{4)^btxqqLUYkC#po=faC zc<34D&!C_EDZ0o0dEyBZEFgFq5J=oKh9p)-vq*2@|HApw+eOt32W`-GC%xM|!QiKo zmSO5BnX>my(M6FSr4U7M)9{g48BHKD>m`tugzGjao#%0%y)u7!Rhp!ryn77q zf{VB}&mP>UG!eX;ORz!&y#|3Jh5Jn3;h$=g?>o7^Z=kKaAMSOOmC$tO<7fTm(&?G9 z&ixHWqh1Q*!J-lxUV5h_LPYypxFI9v=$oiBN*0C7WVe>Fqo4Ltu3!R2E7o$ec?&JM zVT0B2HtzLG{;W4uvYP9Am3&7G-=YoNyE9LCQjV-B(dAW`Ypik^2`mvwdcCp18Wb~z zv+K2c#Oj61^M8kz|&d_I2w2# z><7wS#-u5zQtRYsn0-*&nK5po0nMq~P4jiQQ#5QE0}YW6J~0?*Fmf5L=?uFAXVyFq z#9nq?XMmb6o0#IWQk-3Jf5^x8jD_sv0VUs{+Ag9jvz F{{Zxk8DRhb diff --git a/SCADA/Program/TagConfig/TagConfig/obj/x86/Debug/TagConfig.csprojAssemblyReference.cache b/SCADA/Program/TagConfig/TagConfig/obj/x86/Debug/TagConfig.csprojAssemblyReference.cache index 242d00cd53f87e5cd4fcd7f6f3ff47d574bea933..0f4ac3e8ef22972d562f876bcecb9649207a4fa3 100644 GIT binary patch literal 60206 zcmeI5349dg-N!Q_Gs&|EA$Z?GQBmlIAh)8%AOgxEL1-n2o6Q7PHoIYW69{5a)OzEs z^=QSbVymDOZR?G9-+ELubGzf4`a8*=KlWt01QMd7lUNKbhzF&+|O< zea?C2nG&O`^JZJ(r0k2UJgPZ%QWOhuNJ|({t_AsHTDYwhU<*)>2#B zJY-;O-IQrIh(#jOCo7IXWe#koe+y;(vIg4g=}M)4oLmcv8j@N}$sOe~&DXUe_wRMe+i+hQ3z(~C;$)6MqeOu8e{Y-cKH(U4eZ zmmx)2Yg#PXZf8qMx^*it&F&Rp*BY1C)i)&0;}rdGA2IyEZ5XS_9+0Ap!i4C>zpC)F zEQnbh*!Zbi=9*+xHe8^^%EJwKh9 z+ZdgA$kf7F$KdEd>SG2s)+10V*XYHzIhnMWOG}I{yJUSj)smRqo{90kM#rVHxmYq8 zWkf0vk#VC(Hu8>S8yn`tGHng@b))MVUFqdWU60YM(7R zIO+t{rM~-QwPxe#Ofu2rTr+}ej{lZPXs|OKiMZ|P>kfTw-+dZ98h+U7-iR%5)%jg^ z)d{gwY_{DBDxDZu8 z-9KxG6l$NSYlQ-xvoq)lMTIb?S$1zU)8M3f>n_dpV1vSBvxV)t zWarCVFE-?aU2IFS9mVz(J5cOMu@lA46uVIDN>NSGhhjI1-6{G~I6Z_t`PW_$CYAOt zKrZ*zT>PBAQ-AgsoWIztcWX^Im*F?JG?prBw%f8+mYsmCnaOq7nbMXNdQoMTQ6ee^ ztgo46$Zn2$9gWV3=vo}IAZMr8A!HXUx*-8(%w!OQqGZ1pZ@TWnM=P8zUq76Sy(#vA zu=+zp*jtJ2J8<9H5hW(`@ViKJY3W9#SxvwI#yDdAVEu^mzHdmx*>CvTn`O47(1R^& zNsVi^T3Xqm^KM@^!|0+r*wd@&yq+{~XurG1Ui;WX&$>4>3JXy~F%ZJ4g^+HjAqLTQ zUx*%oE~+({_HNhIU~wVr0aAwGTnwcc24M|{kQA4gEMEUlGW^<8j6#NwV3v%e*blb{+CUbgf&j90^M?jbb{4 z^+SkA#~?HmLk12TG_1tf4HnA%`4RmeMKJ@yYJ`yDQDU&ERRYbV|D!2pL0HE?$bn2Y z%^Px4yPW$NV;r%X){D5o?u3%sI4ngog$-e$K?$ao-H**WwX+%Hh&5-uh#PysLP>1` zmf~27xe!(oLcX_Kw8CPd*TMy7z}P4GW)on;hQ)@&hYYP9vF~7e;P4S9yEq%vx#Ez; zoD<8|O)N{H(^c9ww_DrXTsQRB%$8(qcD6j;)*j2m=g?36xYBr{9DmHIOU@SX;>`Wr=%n>%&xnpW)%-E3L>456>eQ(-H(3vv{7W+zug&sHR zK4<1rr17_CqnJlG{Ai5D5M@g-QM++DOg-ftoVlDetE8gr1SmTj%D!F32XyiZRt_S^ z!Nka#nwt8NH6inrHDU9WHGW>#_%oC>fzDtJM*!4E?KN&6rN+DK7~Mszc3gU#Yf+e^ z-slnvWugP3oZ}GZE|C7R4Jxy|w_-lU0*X$Es(m16OpXyYNZV#r12Ad22KbhbLF5`> zAu_b^Btfn_y}5949DImH6vsmZ>IGv7iZbhlvJ>EPBK~06b_ygcO3pC4yhH|PU!>{$ z2)nc5La zACc!}^vD|Lu}e+iu}h8f*d<@F*A%W*gU2p4cD%kBataBhM@(+l_xi}N&QJha#{Air^ z-e^Tozg#DA;+N}-;HM*ho4)&oHXmE}US5ogAC|W&+{tg%*j@si<($g#vtYyTY}GIX zH}SK63b6%lPivw%6^o{lZPul*=}wzeOWd)ztYFdXSX`bDlWLjkdbvWfar~H^So!|e zSuFpXU!C{#B3>^S&tb*&I2X$)Zh#0@ z7SrVHIa1D^8{v0BK6}3V%Aycox4O6qm!D9u+(Z?|3TQ2_gK)BedAQ*fhFFPU;%16l zC{{sK9SlKZj)wT26?SQm&cd#{=$o*M{%d4tm4|U*b%Iz8YjG>ZZ4kjCIZiH;W91_G zJNRAPoE{+jdKV7%J+J_Wf0;{*onI+?uG~^u})6nL2?q;!0)0i zPolJRBVyf$C>-J4GS6XSYM=F%uQ4O;hbTW3!pRP&tZh(L!4TpBiU%R8#zN2-<00G| z@euyX<5pM|A|8gdc!c8j5W#yfRK6EOH=M5Iv3{}sB+CqXzd5jbu{ zXXyn56Mv(4k>VwabrdgCyh8CR#cL2%lObq~DG-D3V-Jl6Np_5JBu?C_?(g_(7k>sg zbj_G}9e%_c6mLQV^K=_1^oPk?akEIVv+SXe8x1a)*jImw`*&096V@5oLTiQMENubC&Rko zxDmJgp9m)2qj(>pYB~gs@goTL{(XSIdKFUSuCx>Xg01+F;(sA{$7tN4TtvQOLcU`k z!_SYquGg@BtleAm2_n(3zEk0*eDjHpke_DSAOv&Emyi z%ov33T;S2Qel`sHtSZ2&UpcZJ8!u4_W12)lJtHLkyj z7mOg~q7T%TH!}~I5uE1Uh=yY~gcZ9}^rhH?Vo!)Fn~Gt~*$}$=(bbQ)G-WTqk?%qT zp6ZHzWM^-ReIW4PF>d|yj9fU^%7ya>@c3WoLIk2-sDPr3c>)o4E1(*j<|`mRkq`r6 zA!;cG(PtoykI89#R8Hd%caz5=4{Ch8LngWB?AnFq{>jqDQ*M_4g} zVkE_W6#G+*qBwx!K#GGPs<I3_=utZc(+1%9Q!S=cyj`@t`rZp_1( zJm7TvLzo>9-_Mm|9Jwj)saDj-+G24mfWy$bLRpR(@}@@qrBr5OMJoi2s6$56nDZgN zXBEG{9;39>o7BorU3&`!^^(L5c`sX@(>fSf_=^-GqMl`Pw1*0DaqIazygJaaxm~IQ zBkn?NgFR9?!6d8rE1K5!#`Mh;f8$yaL&+GGwb&$R-f7P7Rr}-dhiv3E4y- zA+4K;h)G0ivVzu18Lbs6S`7$Mc^uGMhF@t(UyQjD7?AK@w~B}+Vii}gx_&6Z}%XR8%RNK1?&B1N>)3R>sNXq}^?l_6S7HCh@iAFV8q z2)=)jBU|kXTW82@ovyOA03j;Rh2HR)`t#rtoT)z_Hlc&lOW@!SPV*Dgl|P3qO{sAu zWa!}Z8aU{Fp6=(l4e~+&DGg4KBi4%)tWT1$UZP^X7$MASHCVdJWZi?GVVwXZ@;yCw zaC#!yTB5LZyv)`jm910A)^(aK&6dyBPk@9!I6akEou*(lU&g9K#p+CisJtF3!&~Cz za0#}=H^3&eC0+psr6o33!d5r4x|wxr!?Qt~)XXj=v*#$xw#m$Q=Z>k$R5VKQ1nRkZ#< zw7A!n?r-V-mfI{o3M4AM`Tqtx-i~iYbVkHuyLW)pxI9@UHIAiV~$^V#1${~J#))>mu%Z_$JH;a zefv*4{IJKDqW6pUC%W(4_u+My%=q`a&-EOC%fw!jcX{XE@q0eLv3k-)jaO`a-xCw> zvEzRp)IGKQ$+w1=H`UgC_}d*`i6l>(d%(I%?oQ{7j31n{_>t2S4@@w)RUJph+&Pi& z_H%Pk8iRYs`6J`}{H*x`Y;{S}CCM#G&w+kvWc(MFq34w{)K@M;yQ^jBZwO)jO@pO- zmtepJ>qQ{pkBna;R_he3c9F5#S;gvAV#O^hb$zAlD;KNRfP~WW|DAZfuHdzujMug* zUT+bvmo#3w*79que*lU6`e64>u(!$9I|^I9WwxqRw%#LK>oi-MEuXFTfkfDTkP-0# zT*SX1^2UAnehZng?kZy+A%yud!szBvH;-=f_-`QbAHPNy5g!w_PZZcJ88%ae?Q_ER ziiS;BXkfsF?F%3gm_YuLXnm!iRU)JH)fa_rslC0%xCNZ~szytr<)hUNNaP=Y1$F?9 zh%z_{lLUIkZ7e?pSNxO!Esal9$SMfgYjD(!rEV-qk6{TM@*nCcd|)XeBCr?T>BloJ zVIRtb{YxdRCqh*6YZuG#``U@*m1~#1o~b+HnHQ$~VfSl#ytAm}yhn{E-aM@TW2gN3 z!*^eK;Ljh`9rsnou=ouZKfCJ1HLu@y`4hk0`;yKVPd(+am)FdB{N1rVrX!I-5B z_PL_3F>t^~f8BQ7_Ek%tGPWOf`ePR9dwBG9PxrfY+4B!x z{EJmjT=kl`d)8gz(EAf+!!LL#H6UqMS*MGuR z7babpSWpbB7Y@=yaurTRZ#sF#Ekp0fW$10S3~h}N=6eXD!O~!n9>dxO2P@sul89p~ zv2Af8wxfe*T&!M~vHH7;)s6^ZzKnw- z6bp)B?T&-g0qBcUu?L+zFODmt+g^+PpfQ25yJceK{Q*MEz)CHH8}XI6b9l%)Y8E-E>@4rSUsjy`}3d(u0o^;h?^8G7h$4 zJbie^J25d-=VI6}*U=?5t7NUuco^jFonT*yI zDq1!|n3WnWjTW#WJ%-hS!vOC!@+s}9T%y&EHrSa&ESXps%O%pO=$Le-HI~C;+ibKU z9mAvB*$5)$Ft}%2_%4y*yI6&9E<%{SG<+I9U_*KgD~UsXb>L{bEt&3YwNtr>XobB< z(T`_b!p@TkJ69!a9zs<124UgTxLd*{IE}j%Y(l4Tw}XQ}jhlb1yK;x3s&`aW?^H~6 zA6d1(&~G=`>XEP>36pul%Hbf*5Vzx0bkNB&ZgDtWE)J)u#i0`+%-uCuy21rEq{pxp z;^0rQ9ETIJhz_1{u{ue{YKe-~VuUdJYOFL?z=rhTlRr49Gs7psRxF_p&$xUYFY~oX z) zS6vg^TQTyDXCvZl*ovj};Te~&c`{#ZDqrVOSwHZ#48b=4)yaD!roq+8`@kl2Koo_8 zIv^Sd+wiegZC4eLT2qyf=II29Mu$un;8OvuG^ zj#@k~MF?|*21{4}z=re~)@3;O1ER}uBCeo=XI!k}GFDA0R#zf~IZ|V#u>v-v$FP>+ zP$j+jl*qQnlJyaB73{^;^y3+qu$eMpjVfW+A%wY~CQK6sY)Fq`{Q`%;km!0?h~;$j zjEmNE8Leq5TE9XFbAOGNMhn=G9>cm3hwx3bZi0(gL0_J689PE|Y_iJOEeK(b(u`@w zfDP#}tW`Lu!|q?hR;;EE&$xUYCi693W@J%;rF4#D@cAB2r~h_0S-*%~3UHC$!u_XuHflC^(f zbb4@mBH0{mm=nv`&C$AS)^2S|c2117+V$zyHdtohy=1$1I+aZ{+nFhLE|!@M(Ui2u zBxAEn3`WAJtcS1Q>YCB837t$n6b}Ama(>3Qa$H`)%?Hj}T=h(3q%ppjf(fAtCgm0Q zbIy~CDQE~&U~r)iqhnM~gA68SI&4A{a}*r>#P~~v8WjaIizzrJR6&!XAYM#COQ?c5 zih@Kj1<6nask{RJD;Q}{f$|j$5~Aio4z@IGEO<_*HiQ_W3bbmRH~xr>lx7;PiP{LE;xF zLyIv#JgFw(4n@J8#T48Vs$h+x;J#uC`1v?B1`jI=9x0}P9|=!Mb7!_&Ezz0Y6?4Ov3BM6!3!u zssip%9|Vcp)rW$_UFlT?A1DgA7kQ`xZaJR#K7N= zll$CJfwCVbx3g38fV-9j6>tl)Pz8NL6>!TYM}eP&Jv;?U)7CFk0r%wzD(GKKK{QkW zcVG!Bs4b>oaHsWF z;0tA{f>>UGPa@wZ3RPf-D&T7%!5GXbreJQU02c-)R=5QTJjQY77yi8RD* z##$6X6jS_1uO;vhIwBcqoEV8_lBp6eJ*73t*0xB>P7R>anq;FrGnMR!HQK3CTGYjs z+Qmpw+L{}Qx7+E0f})}V)9hCobgju*U3&+_d9tGa{aK^OZ^u}L_JI_|6eh#~{#A~j zWkJMi#?~WB&8bLh#YE&vx?<3h(Fg5cKih7yQ+6V1S5&9db}Mq;PS@u$w|*l0+l!N_ zh4ta-6XxX4I!1(tQXez8z6OC3nR+j_jq$j}TsqC@vrE<_6HT$^_Ed!B8lId;XCm=< zm=P&OL?+jct!Ig(>+4z~skXYB>e}jhS9&>8UmM9pCfV^eJ5}EhOVlH0>TB(W_GZb! zQ752o$~RP3XQw)1QQOfMg1*IlmQB+liAb~Ein4Mp-VYbg^x4I0Q<257M6+|{t@VT*Uq(wa)oC_XG7O_*Pjx1avjbTpZY z#~Pe#Zi{Pne*4$-@_bGzl1SsG=iEA(<-F-E>a)wU`{1N{dtA1y&n|mZt6R5r=+nez zTbBX6krQpPBgIY>J5%gJu`9)H6uVRGK{1e`f?`jKy(qpzu{VX&L)e#p?FV5}>EL{I zmV0Y%p*wx2!R#+MfAO|n)S7H8#&2O^BvIUGx23H#I{|4kmFcikg-r?cqKYk}K$H&Y zu9>Zc-5B;d8lBV8wV1FZV<*@lWEU*FF#(R5&maax!NG6bcHJevE_J$mgK#ePr#Jw@ z8VnI)ZzVi@=o3)jfpt>7GGIdW>W$^*y5(d zf?X%^@!Ki<&t>tC*Q3p5N1QAsfr!m5Ih3e*t8XgeHY zYhM@D8bN!vYihE({6ERNyQj+pC7`#TsGa#&)5TTA?Xud}d9W`uJfl&bqrF>?=Qp~2PgRtg6Nbx8zc`MwQ z^67Jgk7SHP*4%CpH}-;slG=H&6h~2f55hVcLQbv0+r1L#82YcLm=9qc3n2$G**(~- zvuFWh9I}q<7IA}J8YQ(6Sc(RUD1_ArA*a@07f1?kYJuUKFW+YvgNtMLXb?nE57_zOs8cIa0wYA+DRx3@}t&z4iyRpD1DJeo6 zFzRKXn}jZgQCQgRzF%5ul#a}0l>B&?ADGH@9VfZbOQvF(mexbQZYZyZ;U*~75R1n$ zorYoDW8@U%#|FP^C+t)#>WmTA*_q?2jyYyydZ$Awy8G_kLD2d02^RZGhJ_w?f#oJa zB=NUsqgX^Y{Ai4mA&OUEpmx)8n0iV&IC8mQK|yKpDNuGklzp>|_vz#ntPDhk4-;c6 zD=TZpRtAh$RtAk%R_5}$GB-k5>FW$uvR^=b)L!X!Y%0A{$D?e>YR9D~yB7H|>P@bp zP$oJcO86Y&lmh85-l#guvK5OdmQZv;lpg>=WAYhcqqJ>SEdY~NxH+`|ZarFxXywP_ zEtCB4B8 zTR3h)qjna8iL)urp*WY~Jc{!n%K4B_Q_Sc3ZpB*+D{H~D$nnV(4zUCe&Y+c8Fx&2k zaU6+3OJV4h26^iklaIn%F78BU^TT}wV%3jOd2?DJaRF?^g%C7s{hY3ckwh8f8pi}q za*gA~@H4xYc$a3@+%~R+Lm%Jd{(A|6i zR`oJuYPr{2%gb*e;2LG%eh9xOXMyXpPG&yZPIK(sfensD@mbEW zegv6q>%56laSiN57sa&@{^T7iCvU!-yr07F34NYCX>vDYU56;l@`}rI$lq?hexJJA zvJYm&^$;cFA)M?Wt($QBxdFk%jS%IBLC_e7L%0QT6aLDgmY+8kH^W-oLUAjEzbxwH zvY0KG#U1e5_o(Hg?cVwCL@efHiz7D`-b*EN7nGOOKscGQi5-Gf2rllXxQF6r6!%ix z2T@)NL1RvY&}}P5WqN1WgVo2d?uQKJmo$h6a4sIC_&MFPKd0APE0bO$lm0OL^+vBX zACY`BS@K;dcVZ%N+=L4M2!e@6DITMEoZ<WjKtt3O0c=6OZvbKaDi z-EA(3x$+T23Fi}?yxGK??8nsfH;TVgd_wULiVYP1r1%%brx4}egP<`uE9n;BXZWi$ zyShz$jx+HE#g`ENA}f@O%#e$W9y|K34bH~aEhPgNpPIGmrIO)XSxG%|AeRLj-{zLj zM{pBAs|eb*!kAfWtT7P@C*o~ZF>LzLCeajiEV#DbvuJcIu#n3QlW1D#dMS}?96#m) zDA(E)G|Lcl?UDEdL*zhm5Cwom?78fN=DPIAL+{o(P{zHheWm`km8 z1aWq&eHr4_FL!%N*{k9AaQ*3$Z7
;_TJt~QNfL%7AUJM2SVI_N{1DJmfF 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