From d60e4e09c3eb951c10f8f2789f93e2b59a5ebb8a Mon Sep 17 00:00:00 2001 From: liuxy Date: Mon, 21 Oct 2024 17:45:49 +0800 Subject: [PATCH] =?UTF-8?q?rev=EF=BC=9A=E4=BB=99=E5=B7=A5avg=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/nl/acs/agv/server/AgvWaitUtil.java | 10 +- .../server/impl/XianGongAgvServiceImpl.java | 10 +- .../java/org/nl/acs/device/wql/task_inst.xls | Bin 159232 -> 159232 bytes .../ItemProtocol.java | 149 ++--- .../StandardConveyorControlDefinition.java | 11 +- .../StandardCoveyorControlDeviceDriver.java | 545 ++++-------------- .../lamp_three_color/ItemProtocol.java | 93 ++- .../LampThreecolorDefinition.java | 16 +- .../LampThreecolorDeviceDriver.java | 288 +++++---- .../java/org/nl/config/mqtt2/MqttService.java | 48 +- .../service/impl/StageServiceImpl.java | 5 - .../run/ElevatorSocketConnectionAutoRun.java | 4 +- .../resources/config/application-dev2.yml | 6 +- .../src/main/resources/config/application.yml | 2 +- 14 files changed, 375 insertions(+), 812 deletions(-) diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/agv/server/AgvWaitUtil.java b/acs2/nladmin-system/src/main/java/org/nl/acs/agv/server/AgvWaitUtil.java index 3f4b801..92ad2b3 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/acs/agv/server/AgvWaitUtil.java +++ b/acs2/nladmin-system/src/main/java/org/nl/acs/agv/server/AgvWaitUtil.java @@ -44,7 +44,7 @@ public class AgvWaitUtil { // 标准版输送线驱动 StandardCoveyorControlDeviceDriver driver = (StandardCoveyorControlDeviceDriver) device.getDeviceDriver(); // 通知输送线申请取货-1 - driver.writing(1); + driver.writing("toCommand",1); // 判断是否满足条件:action = 1(允许取货) && move = 1(有货) if (driver.getMove() == 1 && driver.getAction() == 1) { String message = "允许AGV取货。"; @@ -83,7 +83,7 @@ public class AgvWaitUtil { // 标准版输送线驱动 StandardCoveyorControlDeviceDriver driver = (StandardCoveyorControlDeviceDriver) device.getDeviceDriver(); // 通知输送线取货完成-2 - driver.writing(2); + driver.writing("toCommand",2); if (driver.getMove() == 0) { String message = "允许AGV取货后离开。"; driver.setMessage(message); @@ -123,7 +123,7 @@ public class AgvWaitUtil { // 标准版输送线驱动 StandardCoveyorControlDeviceDriver driver = (StandardCoveyorControlDeviceDriver) device.getDeviceDriver(); // 通知输送线申请放货-3 - driver.writing(3); + driver.writing("toCommand",3); // 判断是否满足条件:action = 2(允许放货) && move = 0(无货) if (driver.getMove() == 0 && driver.getAction() == 2) { String message = "允许AGV放货。"; @@ -131,7 +131,7 @@ public class AgvWaitUtil { this.deviceExecuteLogService.deviceExecuteLog(deviceCode, "", "", message); flag = true; - if (taskDto.getIs_vehicle().equals("1")) { + if (ObjectUtil.isNotEmpty(taskDto.getIs_vehicle()) && taskDto.getIs_vehicle().equals("1")) { // 获取当前母载具号 taskDto.setVehicle_code(driver.getBarcode()); taskService.update(taskDto); @@ -170,7 +170,7 @@ public class AgvWaitUtil { // 标准版输送线驱动 StandardCoveyorControlDeviceDriver driver = (StandardCoveyorControlDeviceDriver) device.getDeviceDriver(); // 通知输送线放货完成-4 - driver.writing(4); + driver.writing("toCommand",4); if (driver.getMove() == 1) { String message = "允许AGV放货后离开。"; driver.setMessage(message); diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/agv/server/impl/XianGongAgvServiceImpl.java b/acs2/nladmin-system/src/main/java/org/nl/acs/agv/server/impl/XianGongAgvServiceImpl.java index f574cf1..3c5c9bb 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/acs/agv/server/impl/XianGongAgvServiceImpl.java +++ b/acs2/nladmin-system/src/main/java/org/nl/acs/agv/server/impl/XianGongAgvServiceImpl.java @@ -147,7 +147,9 @@ public class XianGongAgvServiceImpl implements XianGongAgvService { // 三色灯驱动 LampThreecolorDeviceDriver driver = (LampThreecolorDeviceDriver) device.getDeviceDriver(); // 给三色灯写入进入命令0-离开,1-进入 - driver.writing(1,3); + String[] key = {"toCommand","toColor"}; + Integer[] value = {1,3}; + driver.writing(Arrays.asList(key),Arrays.asList(value)); // 判断是否允许进入 1-允许,0-不允许 if (driver.getAction() == 1) { @@ -184,12 +186,14 @@ public class XianGongAgvServiceImpl implements XianGongAgvService { // 三色灯驱动 LampThreecolorDeviceDriver driver = (LampThreecolorDeviceDriver) device.getDeviceDriver(); // 给三色灯写入进入命令0-离开,1-进入 - driver.writing(0,Integer.parseInt(device.getExtraValue().get("color").toString())); + String[] key = {"toCommand","toColor"}; + Integer[] value = {0,Integer.parseInt(device.getExtraValue().get("color").toString())}; + driver.writing(Arrays.asList(key),Arrays.asList(value)); // 判断是否允许离开 1-允许,0-不允许 if (driver.getAction() == 1) { // 判断是否清楚车号 - if (device.getExtraValue().get("color").toString().equals("1")) { + if (device.getExtraValue().get("is_clean").toString().equals("1")) { driver.setCar_no(""); } result.put("code", 200); diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/device/wql/task_inst.xls b/acs2/nladmin-system/src/main/java/org/nl/acs/device/wql/task_inst.xls index b3861669451b55cd5e0c21dfa3f21ec6a1208f82..3ae121441605775bde199628614baa25d2eca6d2 100644 GIT binary patch delta 49339 zcmeIbcYIY<_BOun%}oOW1VSLR+$5BQk{$>(q4yd(giA>E#-O;?yv-hd@-Y|aO-}@_n{BAxc=kB%lUeDTVuie)< zciUU>+un+w`^w9S?;gIZ>w6;PGg3r}Uz_7ajDsG9?;bPUUI;I~^ZK>9x!EMI!IuL~ z^@F|L?rPZQN%;j)J3+b(mk(DoF0#DfcuI};cb>R zd31PUyEi=zTe?+To$;oJ$fZN@uj$b;Z^x#6i@b%Nl%~U-J>B$%pOT_u5!1El$3@;h zdD`lES9WfH>f?77GvBsH-jnyHZ{~V$X*yKnP4ZFLrh96I+>iPmm8E_kpi4vp^dzP(Sg4Qk&evyp zJL*?>`z5y%ZG@OpQ@d_{edDU-_4TU`AxEPAwl^cLS!>qBqQ9i+@llsW-6K5uOHp}x zjxRaIBbv2`sZDW#@OpMHE}M}jlEgDevDDYOl@;sLHQ#WLM}OFtga4oT{9cdH+eY`* ztQ6o8?HMH+MXjh1b%I>Jg6`XheW*K+i#zGPBG79*9#Jg9r5Vry-RJRiiM{Ik&#Meq6h3`9~lk~fyyXc8AT?;*;BmxpM7Pdf-7y3zGvbRuxR}z%4CnnFE z#6YrlxV-6~#|+Sa7d1%#1Xww~B)z{cN$ctB0_*E2MEXtX83Qsha);r|l7aGTPhSsM zWfw=>;@QEfa%X~`B37i>39@sY`4Q^r%Mfv*r#pp%i$+M9Zm{Sl@`VWa!M>kg;s^Z0 zjG!TqO-LV@E(4_je@|bw$ig48I`j4OJ2Un3yK0b(d~Xf_(8u=yK#T{LhgDX~!p ziTMIuLXLcq<0bV(6nEOA0U|!EdMDPfrhH8;2YBUQS>BylU4JYn2E2cCLLzxq_;Nd z$u`}OukFI@Kmv{iDmeTe%EBx zzXgaa7hTV5+g0l?8Fn{WU7nbzfRq5}s0{%U6PsE$wH7|r4R!!Mk~+dWk&%*rIK7pk zqk0s8)i#H;kl}yY8x=`Ds;Qv~9!gA1Zk>z*bd~fz!1Z8^NyHGZK3=7~zPh*L1pV2h z)&o4H{!)x3s{8FL(?i9@iHV^5g_&H^Q}k^eJL{KriXN*Xjfzm2TD6o(h)o8wm;@=5 zN*}Mk+cC@2S5HsMnUSg3J5t8Wl!^{cZx4$yix--K z#=wt3SAsg~)KEt>l6cshLJFYhFnv?$hHY2{mbkD0vmq+|rRYaHcFvRfa9M}S=BO(J zUghe_T%Hd6ufLqsS__v=F*9U<`Xb7#=okS_owz_ymWXszxm8AG3YwD2S@;keu`(!2 z3{S7BHv=3{Gq4G>qcOO&ZGmp3H_hHiujuKzzk6r>%WfSs6;6YEU?e}P z151;=)U#^7p2Sj7>K9>jc94%S72{m&e>%rjp~;?7g;tbPQj@)t zW>yqv`ta0l^Tt~`;%+5Brb0~}-E`AU7K(}N6gX1B^zzh9{m-c#vL}I|*V2)*5N5XK zZ61rgKB`YI&BQ+^Zn#~cQnFDlW}?E@h$-t+U%q593(ueF%6~}2SQTdGZ+`lvNoQa% z)y*InExcwSYfd zfZ6|rf!ft?xwPo5BbOG14XH|fa*x)-Ln|gM6}MU)91*bUO20MJ&q2{5glFdNQe+DV zPm3YXWC(`wQT5poC-S}Ai7du9vbcw_4{G=GvSzuPFVkrgF^)n{gavECton}M>b zGw1ia@*`js)~89c%r7`IgSjm;FxntzPc3Tz^Y9i5ps98dtadX9F*R;2|K_?)bEQSV zDs8yUWa*`8iE(Ccr7ukDWe0Yq`HP*p4$nQnh2%`Df9>S-_jCu__zXv&D8t{zm9HX{ zu-BRV0cYUD3_lK&&Qvz81Sg8w~VsEo^{j7|(&5utrpWlJ)S@8@J-cL4)KW->v^pe+VluWIrL4?tWs2e&S}2R^xeooDW_WHwc%> zAE3UT&8=|I8J>~?MdLg=R_VN%Y!f51%@>zxVSLjg^34ZyINuJD`4&VFw@*a21)NEQ z^X(X!Z(#(!{UY)$jL0@AoUKOn7J={R5cOt9>BNE2GcrabE6I$A;jj`1+te_&n(SXAnaO~Nd>vNe z;Oh_LE7?Y}l3X`i)Bc@il3#Gyi*JRgBrP&VBr7R&V;F70VI`L6zJ4NoTXgefaoyeB zUvzYHlsI=|%7TXV$~ehfmF#SPHE%BA?i1js>+ao^H(^ z@kP1WnM60k`ksDCs)XOUBcfkCFcY(=EV3_N`ou*_j(#pav{|1pV=Y^@2F67A3dPvj z6^raJ7BLnJrf{&4jR$Qa5iUF~KD5&_^KsaxL!1F_HZ;pKv03Iv-|moyRVBq4=;lK^ zJQE*|fZ=RXM7CZ#q`N0azhFo&E!SpQh|VovR&JiHecEBm+IQHVqqzAt&q0!B%VKIA zLPOMV6}Q06=gitCo5Z} ztr*=ikwh`r7K5ilY^E(6fl3i>1c^9VqG@Zgi80lgwX0G@;xoi8j!V0&NqlVOl8sBb zc2gVb=5uE4l22sq4zsm8EVKsz;B(KMwZIX8d+HpNMsvD3p>Ei+%i{W=7Rgq9JW(mlUcs1ft^357 zZ9a(C)tw{Sha7$PdX|!dj`i-?ZLvt@m#M7sd!l0@1(Pkt)CxnCOdK!9QIf;Eo6f#0 zZmFBEHyL~x!#!)W06bxc!C=Y4@Yq8QopvbB6&Ekkok?|XJ24)tJf~_tTrsz7%&g%x zm&G;ct#ec1@WI6i`S3VI8Z89m)XhZWkw}ajsF_NIOf(gWH?UQRU=s-T!9~yQ@4M{6 z;D8kv??Z}M1SrPq*JQ_~tEs427ES^tvawa~o;*k8?x*+7?xESqAO~u*otQ)znul4Y zp&>9`0At6~I-L6CiT)zHUZc0D3?veO7TQTK2gtHeK>NFigggISGvXbCc*ObOM^H}vF)N6M~TrwQ%1tG zM$<5Uiy6AD&?jbWix1bDHy&F1SNX}^UmV!6(b?V;;8Y4j;GPD?b8c$5XAB-+4^)l0 zc>v&{TzJPTbOrCHgXYYZVy&73A{gnlP#8H1_gY?~Lm-B4b=Ene(#Rqe*& zko|WLEezq6Aj)i3?0G{=m1VKAdR+}I(3B-X%(3&c%MBG}pp~D!tsx3JyD7In6(-7D zn-$rFvdS}9$@!GU3)}eL9~>XTD_+ba*2i_v?GNwMTEVgy!#>UIad<{=8WYdvZ9`Te z(~uczZ(Fj8)YB&2h%P~heQ{lI;fwJhjTb-5JUsW`i5{+z+kAME!?R?0(@t!goxOo! zpXb70Wz9Fc+g6j-c#fhq1lLray><6|(mFz7ru$&JXH(ir(%OpmE+;L@Q!{v1`Z=8f zWWW46l6+!)#ky4tAAM1UYuBt>&n)Y|V>m{X)dYj<^Yn`*cb|6y9%#A2AvY830gHL~ zd(;z$ONgR>dc}W4Q;)NwglIrGRfze)<^Hk3jlsJ52LF`W_5SMmM*paWhPv9yiuJYi zYxI~Yqhmx~HXd#`RyL*4mm?;QDw~L`3!#abQ}A!vG=!$(%Xo&yj>RVA{Bh%^;5KdA z*s*%6na?JQbpbpkQwNKytf^?s%*)cho|%@+K>#t8^>y`)X4K#;ebB6&@i8bGqBaLB zteC}Quh{LmUb5%At zJFN?lJ(I%2X=6pBENy;K7DP2d`I!jn>1C73W8ec8gRK`st_>S%t5A6|M?rp8yoiVO z8l~;pT(fJ(#$nU54@BdM3nk9xh9Cefj4T@v5YTT~kKPogwz9Im%9*mrl@hYdn$ug0 zK_f!yH5*p95pf=qt3NY8H;cu062Uz;i;}l?q%;%8J8LL&!zI&eHh*6x<)sw1h)nO$ ziH~7@RnU~z71#xX+CdZ*XEtG9#||TU#*ha)dRbMTu#9yL4S1Nh#aDUb6r@T!q7aDpwC*= zX*|*g8yi=zgAIk~FXh0OyWg8pzYM+Fn!vg>C>|P1u(7r>vuHprn-qe}gN-tzzq|A6N0Z{VB@)Zvl#40s&F$jzH*o;+z zSpCW+nNy{Pl=P??3%htgUcQx!y2_Ij_J3{JI@}4_#Uwze((>-;p3sM^2{fW_wF~3V z95SE~`cP7kAHz)QQduFJyi)On>!8?5*gxuJ&3e@2`rszsD(mW(!wT!_*Q_9=t+VTG z)BI(b-g9Y(F_P`_K*jp?6_qt?Kj<-QS68eEg28ey@KF$c@j!xDH;b_czndN{Vvg-u zI?&T88Vl%XtaGC=C6C73IU0j>wEj|{G#N>lZw=O#t3^=EUwrQ>EK!d2T2|)K#939V z0_!%fLx+y}&d*!lId}fzO|xotp{zzsLq%i7Y9sEkvW8&IF6c_eRn`QnHq-?hjmW4y zN0!#?f{ie;0waC>3dCH#G;_m;!8ZamyPyijtZ1yQ0=;I}@S3X@7fza9vkR4JMxYM} z)|t_rXJ55=(sVp}WyjVxuC7?GZ(aWQ3OR#8&lm-%ryrjEeHrS2lNwY*RS?8;E6(JJw|C&6Nq7VvYf1{f2c&oUkx% z4l}@7eF8mSL;Z#|RRId1mLzHvW?ziig_)T1wGOOLR|byl6$wZOwtHu#t@?iV=sMX5 z8iQ*$1lO$(RII3|)z+{zftQ)0{qk#PcOoxmDs&+mDl5@X8|-QuuMDzCa$*9_q2X85 zMZt`G^71ggA^7rs#Cycr4HawF*RJ18Gh>yabX{gloOScLsJI5Lv9`Vuk&v<5?4OpB zDLSXh#vqsm3C z22t5&>}nJP%>W6`+WY)M?SY1AGngL^d#HrQ^?`#2)|x(am77@ZvnSeSOQit9IMW*W-D zfgfFTPIaF-qG|g@FP81PveooyGuV2;uoknIV6dth*Yb+WRj9EoTmG_<)lBWKZa{5S z)YS#ob0okrD0bn;b&$C+xVoZ|iODr*PUePqB7;{&<@(x_{{-_m0Q#p+<9}9s{^E1=fobb#T zhAztFFynm82f5~m<@)u3VB#Doy{fh`h$^aI1GS6{_T8&kd|!sjZrI?;jVYkATA-kC&6Qhgz93;nNQF>L#&YS@cv`awo;a>E+J zn1Ja|eWR=z&_&?+g{)W5mA1ID0i8^Y`ZhZd74hQ!KkrUk)xep4V{m<3<7T;RTBpye zE0zX{#cSgRsRT&GffCGOEB`T_;Ib)md26O%3u=Qjm~Jyo-iCk9`KpXsTQn2qX?8yj zt%DhRu=^T4%P>@#2_QL!f|&kxB)d5HM!FNA`qou8);7pB@BY=@G*Mk&S66?Qvs%&H zN7-WnWn~#SQ{e!D5d#ZQbBJNA95EQhZXUg}*|Qs^W*;0@YWC4w7W6g}u{3fla;ip^ z3Chubzh*KuYnFvNGxSPTsIJ-(Z*!ycc8-`{v4ZMlEKs}(U9`~cJ_glw z(Ig>W#yxGa5G&AvAHW^2Oc8yiKu=J^6S%i(jR#aFOci1;ijy!+2u@}0$Ng8_hfNn^ zJ9@0AaBl;XY?vX$eYi)@#MT+w{c7Bg;r`1k0HWg>Q6|Ls=$drg|BCysxQ|7poIgj1 zXL0{4?x{&a0|Bbs?fZdtSLTtwU zB<>&KKCp`r?%m*Uvr zg6={*gL_+V521fDv`6m|Z4N?N&davY z?1RQfQe*FZ{E9<2PrmbCqx<*zwA+O8o8B2bO$-LPWn-6Jm9*O~>TYen>Z1U)A?YRf~ew%$`|BDX4 zxbU$#Kc*c0cxkZc)uLP8_W!H(o(_*6ZF5oJD7#LC3j(Odi~~)PNCR?ur~(F5P`;E-MXA?{@-!w z%PSwxZKIDLa}25u&$?>!!Q}Jx&BOY7+USReZB2`m=Ij5Q`1D?w?9-@>WPSUvq?o+y zO{?oZ(`OGKAGPt&2K{%#FM@kv?-7OC;)QPvKDo90#ImhNmv6ebW={Sc-*>y?_iy$- zCu-Ts#5X?u_Q6NCOnO-~bUE*(c?bKwI9_|??W~%4rQfaHzw!9%w-+thy7Sk6p7+8X z({KJ$-G_HCxIU&TwOi{SzWv*x%2iK3+HK#HgFAn<_oaEqA3FVR!ZYu`k^I#!zrW+& z3w95_?uu8xS?0N;$KSrxK6-7+Gdqs;$l2QC-B0iBK61jS!pqklSvYmmZHI38^!=({ znM?nmkp1*SPIlUgrTl>UYmBn+5)3atxeEI9B(Zm1t_nTk4 z>(lIn=%%gLzjDsSL$BB}E&s-hzE_>zy|Ko7?v+3KeA=-4{`$y;Ll6CU&)a=2%KyHpWi)x^x|_yx2;aU{rxSox8JN~JXZYAy%$}6qUbE& z$BWngG%d5>+~Z%~z3~0?o!7^Xyy|%FM|1x%sO00Pil5#37tgd0`h7QIvq-!6)t>W5 z{*ZlE!Pt}Mr#5W4?V&Gcy?_7DpRH_Y8h^>ee~VWO%HI3>!-U7K{-MVUfAMuJTY257 zVIK}X{K>U{UbFZg@4WuS)`B(9@BGw7NlXZ!Li z*WS5h@lEf{`{dn{z)drr|LFNUU;KAtn*)o^+Iip4gC5!R{(bL%cXZSHqWJKhgxB`$ zU;M{=KIm}Y4Qo?lilWzL_Wm$!;O_TkeN=d~v0?wI>VytU&MBQceAn8TJGTCP{m=Vf zm^7h7aLHo}|Jdg2+Eqsyy3hPh>-D$SRwOMR(`(*CTk9^I|82wCq^xJV+?u}bUjw_` zvC{id@V+fYeOo>FOQ-4$17CaKfj{r9IWm0cTaypmd(n%Z^q9KzwwUv8Dmwh~s8@Py zKk&x86YpI3cw$^Z{_7i$kL>r>^>-{99=LdS)t;w&eZT+pvtOOC;e#8~=Orh-y5%p+ zUis*`g4^f4_xc~ZSG}|C&CQ4A1m7s$S^nN5gTJ1g_~_0Rdzxk($(Ztc{masU+O+eA zzO`q;LphnBy|#Vo#C!J!>&84j^~1DNvtNAnxs!kN9b0=GWnmX>4oQ4fI z-?940Tkjw0TmJ21FTDF%arMGI|8D$!**(uxwH|zU(R0h*?x(%Kea+Ip?rrQm|H&Kw z)BD!h2_H0H*>6k9_SP5u`L6FuzExGl(+8w@~zf64cynQ1wr}X*hCI7sazt5g>*@ru( zj-C6&fh#+mJ+^Ipw|{oM|H${>i6`6t^T<{I(1NGlo&MCdKVP%rmCQd*n_l$Jp~>^U zcw|uQuV1|Mbf1FE4_~kN(<@2e<%}zQy>VFTLvIhr`R?u8(zh&sySnJ&+l%+6?3sVx zu6Z|gPkLfR`jUp<-`i=`s1FWQr*+@7c2;GV0o|@|^M?cbevSG$wNu)$YsYo=nNBMD78Wk+s|@AJc+-nrkr64mjxeg8Rl!@>uD#JnOxU!U;mKJT^n>BGn7dv@sc zWB-7$+(_l|4#eSuYwSc^cMLX|2!wnVk5OA%fjO8wt}EwAFmsBVLFjm7bI8RAWsOeR zb?ZWN%HasfFUEx--|MJJVVG@_5u93-+7!wD`zP={7I+)}5FNdvANNDBS`;fOA zMC&(>!@gqg**w27UjtEASP!xC&hW#?;JA{M2J10?FpeZ!S}F9 zPdl$$KC`LU!nJq37Ou4yb0mClXeM%S?OBaE-daeqUjOBXnVw>O`j0cx@tCm(8w>cu z6ce8U`T0|cd2e@8Kl!8IJG?-j@oJ|&IDN##j~{Pai!abYi1W6Wlz36BSFG(gqL_l? z2ohTih+#nylk4 zICl(7?T?5Npg{sp@#tcx3QVQMdu5%P$eLjK|q(?wQBXv|HRk&*{>c?3BX z53F4fa{nnF)b9~3B=`rBo?M)L>?NMu%6r! zGDInp_>vXT~zW;Eo2C zDl!OnB175^h>Svre`aPfra8EUVMsBiSt!Om$Qa^Lm?ZdhlW#b$o-(}_%1$w(B`Id9 zk{KH}nWeVC%rDbN=0$5$ywW5uwnp+wBd^>DlA+NfL+D?ecms~bKK-l>Jx1h06Y65) z%|QClM$#(+t+%4-uWkr!dh8BEIb=qlWf>gOHimNOA0hRC2(*C)hqW7>O^=4bQYbZL zNHwwBq?$5XP&rE&sw2}DSW?BSx8%jO5_$D@^3r5>)fW4lff<#fnDv#+*fhzkualXB z7ZrD z00D1s{Fykc18^uc7+xu^5!d2RNti7ouXkj-0qJOb-NioiM{gO12Lse=H>G-R&_`X~ z$#cDa?Iyqe<)&i&8&JSNf(qUyRxsZ{RdP>}U3G6yoq! zd-Oxgu}42_3N@Rfo_UYcPhc%Jyuf5K7bT7p=g55;G+ARXWEh?gA|<9B;)RTFg&wEc z5pK=(G}4>#ZIGwBl^sSu>l$2%NRhEUqd&1Ft&=^Butkzf0*1+-w)AxjFpOari5QL! zuE95y#@;KG#!e`d#?B;^#+GBzG-HHk6R?N|jg}lr_CMPu?t0-K59p3KSF~DWq~cIFdDa?$YK8uXFoy>b5iBxz_Ep&n{gh@hD&S@LiV2; z&{!q6@>P#A4QE`pI{sp0lV`m;skg$oPpGHX!y^bBh3gjX_#-<*tr5Bfrp4yT30){N z=JDY=z!L}AqySjiAO zf>QWc$xk!1M5B+y0f&|b2aT|Ck_9IhEPtGf1=~m@7C7T_2oWziaE3t+@h%Rupl}XJ zNCUd&ic*HcmK7-jTUR7HO*0am<`{`ii!$j({VQOajTxcticYJKM5if5qSIO;(P=j! z^zqVkXhIJq~!$w{J_Z!%=9|$J*FoADXXo+~DHzG}5zW zaU9~nc)FjR9t|XHT+yF6Z}_ZtT|)%dCC*Nb9Uc3RP#SxLP#U2@(`TI@+S#&gg{Ed> z38m5e$>DGq2ikdPYT9@xjrL6rUx#ssG-mw2J!DY39Na@o!5%7<#x5t6#!e)Z#^s4c zYikU^T!Vn9=k0WkV(icOxeaR<_C{*N`n@p!Zifvq4K3sj`AQq6p{4%8`n%Ie!x8H| zI^@b6m_s4tw?bZo(o{%;VMigDZbkYK;-s8Vd?MjIy!G7-#UR8<_PJiQW$%H1v_6t^pX(VBU&ZKAk0Fvkq~385Fy4{AtKmuL>Q}Ck%SnJ5Frw9Cqy3! zkpPHV9KvXI6~MVLd-x)LU0mAh<*~GokW;vaN$V21JB=})lzNkP}@832#qRXJ9ITN(ugAj zk{TgGlp#b2j$(uuAR*dIh&e_|E(dMVxC?6+f}^;Kle1W^51mN~G1q|Lph$>p36Thh zi{KHVgh>R%HZk7{MIp4n3i(`d(XLPoxGY4M z5O#j4NARFN^_QW%&j1?S2v#c&DHQ$p-Sm??WohzqO`AuhB+gs|g?V26mX z3n|ZCg1Sh>7eb7X5Zw9SgN{W(aOZ!oJgy{QD)e*-4AYDw#Kl&K5OxRccU@QtUBG7s%nts=Q=R$$@<3|i-9w}w^OPTi~Oey_R=1Z&)Wxmu3`A{A^ zF4`5MTJ|9&5z=rcLWx93(plt^_Zb3 z=%utS8n z#fk%j-s$rGp5AizC0(C?c}sivgU+~z9|ewCmjPe5c3u|hdk++=eU)UbI@;a{;d1qK zioFrSjg`~w?Jzf13S#Z_+*nEJWXE%3rMiP1=Eh2jW1|HRUy9R3c0BeAyNGS=Yywsp z=FW>=b#Pn{drzMA#m`Z!z`6eJ0^iA38#|^PHTF|Ipx%YmxQatT^t^Q)HMQ631$Db? zy}e!B4jOr~h}*GZH$zbf{lN|3_bk!!whpbQxLJuRv;eh=uXPoxV+r8ouBV`m?z!nri0kTz`Elwh&^7-WC@T(FYb;zB! zb1}7xk&!fRG8LsFKP41f5}CA@Ot^QZn8ZjXPauXuaocRGc+%iO z;hj9t(j|{1$%C6?iigIXu`S{$g9&%Wwu+|>CVW`V$t2ET(nT`i_LpM9t*7OG;NJEnKBLcal+HI zGt%^vX*ljYD7I)JVC{`W17srZrLbgfff9{0*)k0`L&Cwhn?Vib$~4@~2v5WP2#tyI zWFl@zgeT&z0@LKnG~88y)FA?OGSU>tG~5;l7npsOuGgzkK;`kw?IR~}PKUJ+<-EL<67t2Ik-aZ_bhznE- zG(@K1`jlzhU|eA`%}|+!E6ngTTp}{fFqwu+L?g`{SvDn6Pb1NAnTU(LaDh^dG$Ujh zuF~9T-oV!8Q2pn_DMh_7?fz|l9C!TS%flF~(n6dz(p3y59{6CD#xBo~uPn|;DTUuI zj-xbbMw$|tCM`@-@*!{XDV1rs^m#;Vi8J-9e{g+YN&f3d(coCd(2Q8d&p24JH${LJHSvHJ3P>a zyVS)FE;J!Kv`|`#qUrxf9EC#~G`kQd9w!g{oDeU_|7?^Vgj)VAY_T=RV@qie zFM>vX9$0vTcu9pg#z!G3wW%U~hMX`UNqC7j1fhJRswo zkcYtmnG?Tnj&H0zdKi1rk^}f#?f7ded9n=!aH;cKE=3oJHxVRnPE?n|tq>XqZ}ujN zca*;4*2KQXcLxr0D4aNB?n!wczBQ{vrDgxKK%R`K`Ku`_AKwqi?R!po`3eNes(7&Z z2lQUIWqAVn^xHZwR-E|e3_Azk{-kn{FMoJywZvyP!LlWlvNW8UF2FCotFlp7OU3&L zF%L@@&`;gg8JbmTP3@^z@>ldYeER^oSRd?i$X^|}a@x8;`~zX8PY)-38)fgjopAdY6h%j69h2mKuM6^YZ5i2cI=gY^I;XF>6ItLO0spD2o<(G-C5GFsK=q?jq8~hSb zG=-CZqAkPmxvJF!QD6e`3G|h+{j+R%u?~`P6-e#kv37ux&T%TB$Nj-

4rVo$)dq z-n|Hc2;bJy6pa&a+y>ojp&Zv>oE8rr&Du5D&f>uhL$gQXajugGhrxjU7mEiEUu_AM?_03tV4oS#OYdawNSPBQ53>pqEgp%kvhclcHV+Q7tO9ii%7w`S@e{)2 z$79x|;%9`Yn+}$Bb&xo<7Ckx>EK~;5yr{GeE+CFJ0locEQ}G>L!gjQTRkx+kkZ z;o-;79d?>(@kn*?NL4)asrSwenP#SeU+83V4q+VBXp5fNx3BhX4hXdGz$T-u@`-ETG|zsrFAmI3=+ z2JCk=0vatE(*0ReR3k`}Jj{_N&Ek>f;E{}zU)4F)V9ehj|CV3`r%*Kbfc~HRvnmxo z9@#FC4x((_=@!3q$&cNu%0+(W)^@s_C#85eZS8xhvLcE-Ci6_s6| zxk~C~bQcW|c1EgQ4`vNhsrb_)3#6YT_0rptx3?v)qEj#A+MBZKpFNlXF6|#OYpajs zLc?O}J{FfguG;Ej)YbwZnt!Uc*mDH*9S?CO^oNH!XDF<`R&H|bD|1tZzEXydAEFFx z9yT?Prxd}}?0PdT88R&{TrFlAGHisijrpf!V6U_m*Vs~GWI@A?qOYOhENHk#%bKW~Ug?mpo!Nw*IbS_qU48A5pPKzWy#A>_h|l6ORz}3k!9CE5`s=4)(ACeZUD5 zb)XA%poKcn#bcn02Ycjze)$Qao;YEaHQSXV+m(a;H5##nn&U#vu~2hdJaSw-*uMw# zs*^;$~BwZMhS*KDdr!JlWbc@(&KaOer>zDJ3g{iumr=*m&(%E5stpw~TW zq87POi!4WUx!J!IotFVHR7m!6H^ekn1;kP;l&A2hY9r^8Y&g=bw6Do@3|<<6UCNb1~q8;W(Yz4JB{rLlM3I7P6> zykRKQ0x{C4jA0yEM2QvRjz%)lQy2Wr7khVZm{lR#Fj*t!z%$IK`S9&I4i^Mg+jGMu z@Lvt)!zJ+F5MqZr+_Hk<7U&7l6?C==^=I+dutTOgS59gOpdPLmApzbr07d}7-v1k6 z0gR9U<|s14DiwcP#vDys!A;-UC3B)g9QBBWHc|rp-2fUXOY$~CEXhaf!_J4_8Jc?O2H*QH;1lr^Xv?&p2Q!Sc?Z^jINnnko}(<9JkM4-)#K${hTHanE2L0x4bL{3>tK?~qg z8?~j0gZM6jdlUiG+ChZQWjy1#2IbijFIhXj0g2kpfMKE7zt$d6k{x)F|Kws z#sx%sCy;t}W~>AnYXFUvK;w)8jkR#bN}OWgO994OKx17%V_iUOLXb$1vJ40G{FVL9)vjR znVN|bXCibZJ;f(Vph<@6CR#ufC6H+g6D^>L77*=uq67kOS&QBSf6Z z7S3b?M>8W#pvf+v$u1yvr36xY%~K>0{>c(ekw6|phf^$|DXs!du?jRr;Q${Kv{rb6 z%V~b>p9!QMy_qV3yao_|RB8c!iAD)N)dHI80-9<8O?4G$stactr*#BU58zCbK%ERA z{v6c;{t&xV-82hmnglZUF!+XiRYlWWK+{}697l*#D7zwz<>1_zIQ*Gn{y5bF(Zv9o zP9Xid7tI;>bjjA-%9t+Mnp+vurLl1j;$FS^;kXaVcEDMO`o+WXpr&&^? ze(;eGv2na6q1OHSVD zAvAQ6a_`PV9@qvR3dXm%DKe^e;CadffgNs788L632c7m20m*r6d08sMr##;);a>M zO$1s(1e(@X5m_K;Mr~cUQ#90(O>2*@Z9|->5+l$$M4)wyKuc0I_Xa-4&QOr#2(-=- zXzT_<^QJ_gb#>8<4SXJqg=X#^fz~4et!D&UY6y+p7C$G%WN4MU9yCMjdT9I?@vkL^ zqs1_#lOMd2pu?o*1_KP@SroXw>{8Q5PA*LvIHJn_O^$|-1acy zoVy+#*RF>Ly0v#b*v6LNl1}XOh4)}cRGbfS?Ecti(kZFj zpvNGU+VvoZSkO)H2R2@U*^Wr%!rbYgBa&7wxYa@S>`9i$*MO*y6O8YwP+(E$K$lpq z7W7QA!PtlhrglB(NnbAbt9Il^Z~AgE9U%%&Z+gj3!&d^C6Iga%3W)AYcB$yTWCO9Q zA&}bkpo@LEm|+0X&AwdBG=S)3ulUi!-o~MmCh4eudOg`CqSuoR#Quvwwy#sUzzg+d ziC6{YVzvQ9Und2`(v@32H}sq`=}sJaF9An`xp7{^PLV*i(^I)9Gl1yyR4(QiKy-Ri z4C(Y#4u>J7QvQmKNp}L#=gBS*`&r_s1vDI1sJgiZ5PkZgA_Iu7P>La4p={OB70RSL zf#?cl1F`d7qG$hweo6BUj&$%>^H6#^*(WBUo=)bBPI)?kk+d1Uy-KZG*q1EPulo!A zk`@@e-9AsY7gZ#mCr;*-&y(qG!y$xfQLAGeo3a~ z(gDhhaC#%r0m}A9;;20#O%qjWX#h)>80c(J*=`NVR0< z^A+X7+ymevZ{@<=1K^7;6bpJ%*^u<4GU+BH?Sr0Fwl#C~XVKI;naH@khkWTpx%f9?sgp$Dp!cQ# z^vSaQ%jlD3(w#u`$+CesPa%-)lT|L389H))L&%J90?{YS z2IAz0Kx&=L2Tsbxas!Ajz$h1$1`uC>q4?2n%kJ6ew`J0uI2{F^WU_%cqau)6C-bS5 za{NfEvU9!*gDjNlk}M!PciBA~ox2neox5y1r*oH$!$}%(uuj&Xd_MY8F3i0Qz7eBb zG#fyCBZgu~4=@{u9$+Tj2}BPt8;IjRfz(==kI$4tepMhkAD0Ww+{@srn-xR4iP=DO z6Eo>fAi9a!K%7nzNUe_f2u?YEl2-xoBh1#qH)T`^^H_v$%1{jHlx73bDb1wE;G4OvMW-|iCk7`$0MZNJk*BTi znEN3u`Jl1gc15SF9H}|!rjY726@1XB9KUF+gyf4b%0;x%GWc?6rCoZgm18Sd88SWA zOuE#%h6wgvbXl|2-rWFFFRS3wO64NP0OI>F%0;XJ#MfachIDJQf#}v|(w)^yw>BH6 z2e+zNBK67&KJtWlr~$;cVwCfT8D;O)!vdo3n+-(YHw8rBH`|Wr`(^`i$w8bErL0gs zHDzdy4U+H1C>N~^pq>^G9pr2vI>;#?I>^~Tbda-wxQ-!^df5aYy|OjO7i5%+)&>q= zkWnu3C=b2pY#@5kDIj{$*+BH71CW0GdvimcwoU`!YsOM@n`gd!Up*I0Ce2)?W+<9o z`2Ja%`w*;Ogw*{b&;~@H4U9m`jzG(C(#&OiE{LIrWqA>3`4MOZ5om=GXhjid+MozT z?DK>PQyhWDy&7j2A+_p{>FM1bCBcE!{COjSI+&+Lk) z_nB>BtZV|6N}x0eR0Y;FB))5;Tm%iEG|Q6dp=K`x>7mw50ntUx1iH>c7c~GKJNo(6 z9*qVBoNWq+&(u|kY6B--;;b-m(k&c%u9ZvAHA+K&wHj-;H66@rz*9*|f3QVDvEZ?!~KDxuBv0$TR z!T2_k6>^)8>fzf+%H_r$+4i>J=;o%BsOTmf-P~+-_I9b0u5L=5C&VF7Z&+tL^Y7RT zpEP+qOZ2KwrCZUb@Tog?{hDV$7Q5z27DXh~o?T{z) z*r`vh^+ab;oBHUl$))b=H2lBh>)v2;&(|iCezGj)nBNboTOip|WAG@C=`i_5@><38pC7@DO11$E^JxqT^^8f5#ro+(x zt|J%}^=}sOw>yF@(I5V|>Ff8u>j=iSH$j?BF3hG}^f%gGt~8qgM%&A^+Fq_p)w%Xu zoBm^F8*e4(KW29(>}qMB6D3fd1R7`nAy11Qe|qK}z9VWf|l>PzTjX5-|!=i2PQ zSt13LFM;sLoiv7g36yI9LW!ddHh>B(ph5{`PR0r?AiBNT zKy-VvfjD}xM3W^@kpwd5Vnq^&zALogA{J<> ztRlMSaTYs8S@#eLG~56hVgU_t0S&Q$hPZ%+C?GxahgqI-`IP%2ecun6@veiZp6+Ma zx%XgyF8JPhe*M3{Rj8f)lJ8Ead*j&Wiy!B?0R2r*&F~IA*6`ClkKXW8_k+v4V?3Uw zW!*hV`oQzrB)7l)-NjdDyy-FTN|vUdmU*{$x;1U6@J^5Ma6>k>DKW*dk*xP-7L;CRtOT16T_Sz2edANA+ zwgdN_xGuouJh*G>wZPlU#}rLdS9)`k_>I@~NOuD+8MAMtw@{^dW~Fy{8`2&(zU^7jH_?Ex~?EiTJoz=9q&YM$2Qa=Pa z5U}fHug$)iohtjg0$l9r3UM)Q5$|_Z^!Hql#mP-SE%r{1=3ae!cUq6$v|)*Ndeh?pZ(j6uh#%DC8RqTSbnakp8>!JL-V40P zPo;ZHJ=g!I%aLB*sGCn^dOZir0nLrLL^r$Ehe11v3m;WcNsGPNST8|*`RS%s z^I8f?o>}A_kZ>dNuU7Rf>YF?P@0e(AUM0EF+T0D=Ge)xGr?R};V~%_JdNt3%r4WyJ zo!l8bk2P%|21^_J1Ty!A@%&un{Uz>Q1o&y%mgy}$UOL_TgeMB;DotO`g|T&?=}ppD zD(<91pKz@aX!-(v0E)(*gYwnkVukF$#a-WhxVRO22p9LnZo%c{9Wrx0OCD95&ywHC z`{id|yT||Nw=&!w;c2y%jrHs5tJnL-`8HJs>zW>#>FpU;bD?aTQF_HseGks``ml6q z8b8ZBRI7t*nYh@3C?>^YB`v_k{T@@i_4rQqTX9h=ikpmU4=##(IWCINtq6+y2{zFv zE@}J$^nn}J;K#VtkGhc)i;T}m^Gn#hC(u|vo_KtCbo(b)tKaWAeelB5hi~}!&U;Q@ zaS4q0m!S8onAecx@~Ebt%Dt16QGNhIEs8p&Y34Amuj!R8p17vBO1*JSUk&xfq0^~q zf$rB%A2@n??;k$8>!A;?*)7ZUkB4sf=(_EvZ#hf?4-`H=e9K4oT>s(22hernH|Z+Y zt&(5(BhFIRvYKFUeV%9o@u>&ufZ0Age$zi5IfTp@2~@#ECgKe>h-Dx`bDBKTV?G|^ zFy%7bS>>!J0`9<_ec~b9shV4Gr<(4;optyE?!^0#5hkxBT!B$l6YDEy2RGIR&l&j~C&ssBMO(j-q+?S$tO(~l(v$4Jk zKVCk1Lv3BvykMg&9Hp9H-?(adef_El_&Iu6Qfg9{^iL>zSMA?eB{mJ_@~s3_;>%5-w=^eer{3zz(LuAv-7fxi}Q;m zKqfMPo|j)(ojF}?@xT^tRb t?cJZBn_J+2;Knz;zw2{ZE2C?xtBYklk7IncG|=qgrkQ=cxo8Xb|1bP_tResa delta 47823 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 aIl)B)XZxJvb2eUxH}ihc?*oha8UG8U*_JW@ diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/ItemProtocol.java b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/ItemProtocol.java index df1ca69..805f5e3 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/ItemProtocol.java +++ b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/ItemProtocol.java @@ -1,137 +1,62 @@ package org.nl.acs.device_driver.basedriver.standard_conveyor_control; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; + import org.nl.acs.device.device_driver.standard_inspect.ItemDTO; +import org.nl.acs.device_driver.DeviceDriverBaseReader; -import java.util.ArrayList; import java.util.List; +import java.util.ArrayList; -@Slf4j -@Getter -@Setter -public class ItemProtocol { - - public static String item_heartbeat = "heartbeat"; - public static String item_mode = "mode"; - public static String item_move = "move"; - public static String item_action = "action"; - public static String item_ioaction = "ioaction"; - public static String item_height = "height"; - public static String item_error = "error"; - public static String item_direction = "direction"; - public static String item_operation_type = "operation_type"; - public static String item_task = "task"; - public static String item_barcode = "barcode"; - - public static String item_to_command = "to_command"; - public static String item_to_target = "to_target"; - public static String item_to_task = "to_task"; - public static String item_weight = "weight"; - - private StandardCoveyorControlDeviceDriver driver; - - public ItemProtocol(StandardCoveyorControlDeviceDriver driver) { - this.driver = driver; - } - - public int getHeartbeat() { - return this.getOpcIntegerValue(item_heartbeat); - } - - public String getBarcode() { - return this.getOpcStringValue(item_barcode); - } - - public int getMode() { - return this.getOpcIntegerValue(item_mode); - } - - public int getMove() { - return this.getOpcIntegerValue(item_move); - } - - public int getAction() { - return this.getOpcIntegerValue(item_action); - } - - public int getError() { - return this.getOpcIntegerValue(item_error); - } +public enum ItemProtocol implements DeviceDriverBaseReader.KeyProvider { + HEARTBEAT("heartbeat", "心跳", "DB600.B0"), + MODE("mode", "工作模式", "DB600.B1"), + MOVE("move", "光电信号", "DB600.B2"), + ACTION("action", "取放信号", "DB600.B3"), + ERROR("error", "报警信号", "DB600.B4"), + BARCODE("barcode", "托盘号", "DB600.D1"), + TO_COMMAND("toCommand", "下发命令", "DB601.W1"); - public int getOperation_type() { - return this.getOpcIntegerValue(item_operation_type); - } + private final String key; + private final String description; + private final String address; - public int getTask() { - return this.getOpcIntegerValue(item_task); + ItemProtocol(String key, String description, String address) { + this.key = key; + this.description = description; + this.address = address; } - public int getToCommand() { - return this.getOpcIntegerValue(item_to_command); + @Override + public String getKey() { + return this.key; } - public int getToTarget() { - return this.getOpcIntegerValue(item_to_target); + public String getDescription() { + return description; } - public int getToTask() { - return this.getOpcIntegerValue(item_to_task); - } - - - //是否有货 - public int hasGoods(int move) { - return move; - } - - Boolean isonline; - - public int getOpcIntegerValue(String protocol) { - Integer value = this.driver.getIntegeregerValue(protocol); - if (value == null) { -// log.error(this.getDriver().getDeviceCode() + ":protocol " + protocol + " 信号同步异常!"); - setIsonline(false); - } else { - setIsonline(true); - return value; - } - return 0; - - } - public String getOpcStringValue(String protocol) { - String value = this.driver.getStringValue(protocol); - if (value == null) { - //throw new BusinessException("{} : {}", new Object[]{protocol, DeviceErrorProtocol.getMessage(10000)}); - } else { - return value; - } - return "0"; + public String getAddress() { + return address; } public static List getReadableItemDtos() { - ArrayList list = new ArrayList(); - list.add(new ItemDTO(item_heartbeat, "心跳", "DB600.B0")); - list.add(new ItemDTO(item_mode, "工作模式", "DB600.B1", Boolean.valueOf(true))); - list.add(new ItemDTO(item_move, "光电开关信号", "DB600.B2")); - list.add(new ItemDTO(item_action, "取放信号", "DB600.B3")); - list.add(new ItemDTO(item_ioaction, "进出类型", "DB600.B4")); - list.add(new ItemDTO(item_height, "高度类型", "DB600.B5")); - list.add(new ItemDTO(item_error, "报警信号", "DB600.B6")); - list.add(new ItemDTO(item_direction, "电机方向", "DB600.B7")); - list.add(new ItemDTO(item_operation_type, "作业类型", "DB600.B8")); - list.add(new ItemDTO(item_task, "任务号", "DB600.D22")); + List list = new ArrayList<>(); + for (ItemProtocol prop : values()) { + if (!prop.getKey().startsWith("to")) { + list.add(new ItemDTO(prop.getKey(), prop.getDescription(), prop.getAddress())); + } + } return list; } public static List getWriteableItemDtos() { - ArrayList list = new ArrayList(); - list.add(new ItemDTO(item_to_command, "作业命令", "DB601.W2", Boolean.valueOf(true))); - list.add(new ItemDTO(item_to_target, "目标站", "DB601.W4")); - list.add(new ItemDTO(item_to_task, "任务号", "DB601.D8")); + List list = new ArrayList<>(); + for (ItemProtocol prop : values()) { + if (prop.getKey().startsWith("to")) { + list.add(new ItemDTO(prop.getKey(), prop.getDescription(), prop.getAddress())); + } + } return list; } } - diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/StandardConveyorControlDefinition.java b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/StandardConveyorControlDefinition.java index a15474e..ab8834b 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/StandardConveyorControlDefinition.java +++ b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/StandardConveyorControlDefinition.java @@ -10,10 +10,6 @@ import org.springframework.stereotype.Service; import java.util.LinkedList; import java.util.List; -/** - * 检测站点驱动定义 - * 说明:该站点为普通带光电检测站点 - */ @Service public class StandardConveyorControlDefinition implements OpcDeviceDriverDefinition { @Override @@ -23,18 +19,17 @@ public class StandardConveyorControlDefinition implements OpcDeviceDriverDefinit @Override public String getDriverName() { - return "标准版-输送机-控制点"; + return "标准版-输送线"; } @Override public String getDriverDescription() { - return "标准版-输送机-控制点"; + return "标准版-输送线"; } @Override public DeviceDriver getDriverInstance(Device device) { return (new StandardCoveyorControlDeviceDriver()).setDevice(device).setDriverDefinition(this); - } @Override @@ -54,10 +49,8 @@ public class StandardConveyorControlDefinition implements OpcDeviceDriverDefinit return ItemProtocol.getReadableItemDtos(); } - @Override public List getWriteableItemDTOs() { return ItemProtocol.getWriteableItemDtos(); } - } diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/StandardCoveyorControlDeviceDriver.java b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/StandardCoveyorControlDeviceDriver.java index 67a9278..76d7e38 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/StandardCoveyorControlDeviceDriver.java +++ b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control/StandardCoveyorControlDeviceDriver.java @@ -1,485 +1,154 @@ package org.nl.acs.device_driver.basedriver.standard_conveyor_control; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import lombok.Getter; -import lombok.Setter; import lombok.RequiredArgsConstructor; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.nl.acs.device.device_driver.standard_inspect.ReadUtil; -import org.nl.acs.device.service.DeviceService; import org.nl.acs.device_driver.DeviceDriver; +import org.nl.acs.device_driver.DeviceDriverBaseReader; import org.nl.acs.device_driver.RouteableDeviceDriver; +import org.nl.acs.device_driver.StandardRequestMethod; import org.nl.acs.device_driver.driver.AbstractOpcDeviceDriver; import org.nl.acs.device_driver.driver.ExecutableDeviceDriver; -import org.nl.acs.ext.wms.service.AcsToWmsService; -import org.nl.acs.ext.wms.service.impl.AcsToWmsServiceImpl; -import org.nl.acs.instruction.service.InstructionService; -import org.nl.acs.instruction.service.dto.Instruction; -import org.nl.acs.log.service.DeviceExecuteLogService; import org.nl.acs.monitor.DeviceStageMonitor; import org.nl.acs.opc.Device; -import org.nl.acs.opc.DeviceAppService; -import org.nl.acs.opc.WcsConfig; -import org.nl.acs.route.service.RouteLineService; -import org.nl.acs.route.service.dto.RouteLineDto; -import org.nl.acs.task.service.TaskService; -import org.nl.acs.task.service.dto.TaskDto; -import org.nl.modules.system.service.ParamService; -import org.nl.modules.system.util.CodeUtil; -import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.modules.lucene.service.LuceneExecuteLogService; +import org.nl.modules.lucene.service.dto.LuceneLogDto; import org.nl.modules.wql.util.SpringContextHolder; -import org.openscada.opc.lib.da.Server; -import org.springframework.beans.factory.annotation.Autowired; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 输送机-控制点驱动 - */ @Slf4j @Getter @Setter @RequiredArgsConstructor -public class StandardCoveyorControlDeviceDriver extends AbstractOpcDeviceDriver implements DeviceDriver, ExecutableDeviceDriver, RouteableDeviceDriver, DeviceStageMonitor { - protected ItemProtocol itemProtocol = new ItemProtocol(this); - - DeviceAppService deviceAppservice = SpringContextHolder.getBean(DeviceAppService.class); - - InstructionService instructionService = SpringContextHolder.getBean("instructionServiceImpl"); - - DeviceService deviceservice = SpringContextHolder.getBean("deviceServiceImpl"); - - RouteLineService routelineserver = SpringContextHolder.getBean("routeLineServiceImpl"); - - TaskService taskserver = SpringContextHolder.getBean("taskServiceImpl"); - - RouteLineService routeLineService = SpringContextHolder.getBean(RouteLineService.class); - - AcsToWmsService acsToWmsService = SpringContextHolder.getBean(AcsToWmsServiceImpl.class); - - ParamService paramService = SpringContextHolder.getBean(ParamService.class); - DeviceExecuteLogService logServer = SpringContextHolder.getBean("deviceExecuteLogServiceImpl"); - - - String container; - String container_type_desc; - String last_container_type_desc; - String last_container; - //放货准备锁 - String putReadyLock = null; - //有货标记 - protected boolean has_goods_tag = false; +public class StandardCoveyorControlDeviceDriver extends AbstractOpcDeviceDriver implements + DeviceDriver, + ExecutableDeviceDriver, + RouteableDeviceDriver, + DeviceStageMonitor, + StandardRequestMethod, + DeviceDriverBaseReader { - int mode = 0; - int error = 0; - int move = 0; - int action = 0; - String barcode = null; - int task = 0; - //出入库模式 - int operation_type = 0; - int last_mode = 0; - int last_error = 0; - int last_move = 0; - int last_task = 0; + private final LuceneExecuteLogService logService = SpringContextHolder.getBean(LuceneExecuteLogService.class); - Boolean isonline = true; - int hasGoods = 0; - String message = null; - Boolean iserror = false; - - - boolean hasVehicle = false; - boolean isReady = false; - protected int instruction_num = 0; - protected int instruction_num_truth = 0; - boolean isFold = false; - private String assemble_check_tag; - - protected String current_stage_instruction_message; - protected String last_stage_instruction_message; - Integer heartbeat_tag; - private Date instruction_require_time = new Date(); - private Date instruction_finished_time = new Date(); - private Date instruction_apply_time = new Date(); - private int instruction_require_time_out = 3000; - //请求成功标记 - Boolean requireSucess = false; - //申请指令成功标记 - Boolean applySucess = false; - String inst_message; - - private int instruction_finished_time_out; + /** + * 心跳 + */ + private int heartbeat = 0; + private int lastHeartbeat = 0; + /** + * 工作模式 + */ + private int mode = 0; + private int lastMode = 0; + /** + * 光电信号 + */ + private int move = 0; + private int lastMove = 0; + /** + * 取放信号 + */ + private int action = 0; + private int lastAction = 0; + /** + * 报警信号 + */ + private int error = 0; + private int lastError = 0; + /** + * 托盘号 + */ + private String barcode; + private String lastBarcode; + /** + * 下发命令 + */ + private int toCommand = 0; + private int lastToCommand = 0; + /** + * 当前设备编号 + */ + private String currentDeviceCode; - int branchProtocol = 0; - //备注 - String remark; - //数量 - String qty; - //物料 - String material; - //当前指令 - Instruction inst = null; - //上次指令 - Instruction last_inst = null; + /** + * 消息 + */ + private String message; - //触摸屏手动触发任务 - private Boolean is_has_task = false; + /** + * 请求标记 + */ + boolean requireSuccess = false; - //申请搬运任务 - private Boolean apply_handling = false; - //申请物料 - private Boolean apply_material = false; + /** + * 请求时间 + */ + private long requireTime = System.currentTimeMillis(); - //暂定 0就绪 1请求取货 2取货完成 3请求放货 4放货完成 5取货完成离开 6放货完成离开 7请求进入区域 8请求离开区域 - int flag = 0; + /** + * 请求间隔时间 + */ + private long requireTimeOut = 3000L; - String device_code; + /** + * 设备异常标记 + */ + private boolean isError = false; @Override public Device getDevice() { return this.device; } - @Override - public void execute() throws Exception { - String message = null; - try { - device_code = this.getDeviceCode(); - mode = this.itemProtocol.getMode(); - error = this.itemProtocol.getError(); - move = this.itemProtocol.getMove(); - task = this.itemProtocol.getTask(); - action = this.itemProtocol.getAction(); - barcode = this.itemProtocol.getBarcode(); - hasGoods = this.itemProtocol.getMove(); - operation_type = this.itemProtocol.getOperation_type(); - if (mode != last_mode) { - } - if (move != last_move) { - if (move == 0) { - thingToNothing(); - } - this.setRequireSucess(false); - - } - if (error != last_error) { - } - - /* if (mode == 2 && move != 0 && task > 0) { - //inst_message - inst = instructionService.findByCodeFromCache(String.valueOf(task)); - if (inst != null) { - inst_message = "指令号:" + inst.getInstruction_code() + " " + inst.getStart_point_code() + " -> " + inst.getNext_point_code() + " 载具号:" + inst.getVehicle_code(); - if (StrUtil.equals(inst.getInstruction_status(), "1") && StrUtil.equals(this.getDeviceCode(), inst.getNext_device_code())) { - finish_instruction(); - } - if (StrUtil.equals(inst.getInstruction_status(), "0") && StrUtil.equals(this.getDeviceCode(), inst.getStart_device_code())) { - inst.setInstruction_status("1"); - instructionService.update(inst); - } - } - }*/ - } catch (Exception var17) { - return; - } - - if (!this.itemProtocol.getIsonline()) { - this.setIsonline(false); - this.setIserror(true); - message = "信号量同步异常"; - //未联机 - } else if (mode == 0) { - this.setIsonline(false); - this.setIserror(true); - message = "未联机"; - //有报警 - } else if (error != 0) { - this.setIsonline(false); - this.setIserror(true); - message = "有报警"; - //无报警 - } else { - this.setIsonline(true); - this.setIserror(false); - message = ""; - Instruction instruction = null; - List toInstructions; - switch (mode) { - case 1: - log.debug("设备运转模式:等待工作"); - break; - case 2: - //申请任务 - break; - case 3: - - break; - case 4: - //叫料 - - break; - case 5: - //申请空盘 - break; - case 6: - //申请入库 - break; - } - - - switch (flag) { - //取货完成 - case 1: - writing(2); - break; - //放货完成 - case 2: - writing(3); - break; - - } - - } - last_mode = mode; - last_error = error; - last_move = move; - last_task = task; - } - - public boolean exe_error() { - if (this.error == 0) { - return true; - } else { - log.debug("设备报警"); - return false; - } - } - - protected void thingToNothing() { - log.debug("从有货到无货 清理数据"); - this.setRequireSucess(false); - this.setApplySucess(false); - this.set_last_container(container, container_type_desc); - } - - public void set_last_container(String barcode, String type_desc) { - this.setInst_message(null); - this.setContainer(null); - this.set_last_container(barcode); - this.set_last_container_type_desc(type_desc); - } - - public void set_last_container(String barcode) { - } - - public void set_last_container_type_desc(String type) { - } - - - public boolean exe_business() { - return true; - } - - protected void executing(Instruction instruction) { - this.executing(1, instruction, ""); - } - - public void executing(int command, Instruction instruction, String appendMessage) { - String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_command; - String to_target = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_target; - String to_task = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_task; - if (appendMessage == null) { - appendMessage = ""; - } - if (instruction != null) { - instruction_num = Integer.parseInt(instruction.getInstruction_code()); - } - String opcservcerid = this.getDevice().getOpc_server_id(); - Server server = ReadUtil.getServer(opcservcerid); - Map itemMap = new HashMap(); - itemMap.put(to_command, 1); - itemMap.put(to_task, instruction_num); - ReadUtil.write(itemMap, server); - server.disconnect(); - + public & KeyProvider, T> T getOpcValue(E item, Class fieldClassType) { + return (T) this.getValue(item.getKey()); } - public void executing(Server server, Map itemMap) { - ReadUtil.write(itemMap, server); - server.disconnect(); - } - - public void writing(int command) { - String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_command; - - String opcservcerid = this.getDevice().getOpc_server_id(); - Server server = ReadUtil.getServer(opcservcerid); - Map itemMap = new HashMap(); - itemMap.put(to_command, command); - ReadUtil.write(itemMap, server); - ReadUtil.write(itemMap, server); - server.disconnect(); - logServer.deviceExecuteLog(this.device_code, "", "", "to_command 写入 " + command); - } - - public void writing(int command, int target, int task) { - - String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_command; - String to_target = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_target; - String to_task = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_task; - String opcservcerid = this.getDevice().getOpc_server_id(); - Server server = ReadUtil.getServer(opcservcerid); - Map itemMap = new HashMap(); - itemMap.put(to_command, command); - itemMap.put(to_target, target); - itemMap.put(to_task, task); - ReadUtil.write(itemMap, server); - server.disconnect(); - } - - public void writing(int type, int command) { - String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_command; - String to_target = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_target; - String to_task = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_task; - String opcservcerid = this.getDevice().getOpc_server_id(); - Server server = ReadUtil.getServer(opcservcerid); - Map itemMap = new HashMap(); - if (type == 1) { - itemMap.put(to_command, command); - } else if (type == 2) { - itemMap.put(to_target, command); - - } else if (type == 3) { - itemMap.put(to_task, command); - } - ReadUtil.write(itemMap, server); - server.disconnect(); - - } - - public boolean instruction_apply() throws Exception { - return false; - } - - public boolean instruction_require(String container_code) { - return instruction_require(container_code, WcsConfig.task_container_type_default_desc); - } - - /** - * 请求指令 - * - * @param container_code - * @param container_type - */ - public synchronized boolean instruction_require(String container_code, String container_type) { - Date date = new Date(); - if (date.getTime() - this.instruction_require_time.getTime() < (long) this.instruction_require_time_out) { - log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_require_time_out); - return false; - } else { - this.instruction_require_time = date; - TaskDto dto = new TaskDto(); - String now = DateUtil.now(); - dto.setTask_id(IdUtil.simpleUUID()); - dto.setCreate_by(this.getDevice().getDevice_code()); - dto.setUpdate_by(this.getDevice().getDevice_code()); - dto.setStart_point_code(this.getDevice().getDevice_code()); - dto.setVehicle_code(container_code); - dto.setVehicle_type(container_type); - - String taskcode = CodeUtil.getNewCode("TASK_NO"); - dto.setTask_code("-" + taskcode); - dto.setTask_status("0"); - dto.setPriority("101"); - RouteLineDto jo = routelineserver.findByCode(this.getDevice().getDevice_code()); - String next_device_codecode = jo.getNext_device_code(); - if (StrUtil.isBlank(next_device_codecode)) { - throw new RuntimeException("该设备未找到对应路由"); - } - dto.setNext_point_code(next_device_codecode); - dto.setUpdate_time(now); - dto.setCreate_time(now); - - WQLObject wo = WQLObject.getWQLObject("acs_task"); - JSONObject json = (JSONObject) JSONObject.toJSON(dto); - - wo.insert(json); - requireSucess = false; - return true; - } - } - - - public synchronized boolean finish_instruction() throws Exception { - instructionService.finish(inst); - return true; + @Override + public void setLog(String key, Object newValue, Object oldValue) { + logService.deviceExecuteLog(new LuceneLogDto(this.currentDeviceCode, "自动线程读取信号:" + key + ",由" + oldValue + "->" + newValue)); } - public void apply_OutEmpty() { - + @Override + public void execute() { + this.currentDeviceCode = this.getDevice().getDevice_code(); + this.loadAssignData(currentDeviceCode, ItemProtocol.class); } - public synchronized boolean apply_InEmpty() throws Exception { - return false; + @Override + public void executeLogic() { + if (!this.online) { + this.message = "设备离线"; + } else if (this.mode == 0) { + this.message = "设备未联机"; + } else if (this.error != 0) { + this.message = "设备报警"; + this.isError = true; + } else { + this.isError = false; + this.message = ""; + //编写业务逻辑方法 + } } @Override - public JSONObject getDeviceStatusName() { - JSONObject jo = new JSONObject(); - String mode = ""; - String action = ""; - String move = ""; - if (this.getMode() == 0) { - mode = "未联机"; - } else if (this.getMode() == 1) { - mode = "单机"; - } else if (this.getMode() == 2) { - mode = "联机"; - } else if (this.getMode() == 3) { - mode = "运行中"; - } - - if (this.getMove() == 0) { - move = "无货"; - jo.put("hasGoods", false); - } else if (this.getMove() == 1) { - move = "有货"; - jo.put("hasGoods", true); - } else if (this.getMove() == 2) { - move = "有托盘有货"; - jo.put("hasGoods", true); - } - jo.put("device_name", this.getDevice().getDevice_name()); - jo.put("mode", mode); - jo.put("move", move); - jo.put("action", action); - jo.put("isOnline", this.getIsonline()); - jo.put("error", this.getError()); - jo.put("isError", this.getIserror()); - jo.put("task", this.getTask()); - return jo; + public JSONObject getDeviceStatusName() throws Exception { + JSONObject jo = new JSONObject(); + jo.put("device_code", this.currentDeviceCode); + jo.put("device_name", this.getDevice().getDevice_name()); + jo.put("driver_type", "standard_conveyor_control"); + jo.put("is_click", false); + jo.put("message", this.message); + jo.put("isOnline", this.online); + jo.put("isError", this.isError); + return jo; } @Override public void setDeviceStatus(JSONObject data) { - + } + } diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/ItemProtocol.java b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/ItemProtocol.java index ed01e38..7aa5518 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/ItemProtocol.java +++ b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/ItemProtocol.java @@ -1,80 +1,63 @@ package org.nl.acs.device_driver.lamp_three_color; -import lombok.extern.slf4j.Slf4j; + import org.nl.acs.device.device_driver.standard_inspect.ItemDTO; +import org.nl.acs.device_driver.DeviceDriverBaseReader; +import org.nl.acs.device_driver.ItemDto; -import java.util.ArrayList; import java.util.List; +import java.util.ArrayList; -@Slf4j -public class ItemProtocol { - public static String item_heartbeat = "heartbeat"; - public static String item_mode = "mode"; - public static String item_action = "action"; - public static String item_error = "error"; - public static String item_to_command = "toCommand"; - public static String item_to_color = "toColor"; - public static String item_color = "color"; - - - private LampThreecolorDeviceDriver driver; - - public ItemProtocol(LampThreecolorDeviceDriver driver) { - this.driver = driver; - } - - public int getHeartbeat() { - return this.getOpcIntegerValue(item_heartbeat); - } - - public int getColor() { - return this.getOpcIntegerValue(item_color); - } +public enum ItemProtocol implements DeviceDriverBaseReader.KeyProvider { + HEARTBEAT("heartbeat", "心跳", "DB51.B0"), + MODE("mode", "工作模式", "DB51.B1"), + ACTION("action", "是否允许进入", "DB51.B2"), + ERROR("error", "报警信号", "DB51.B4"), + COLOR("color", "颜色", "DB51.B5"), + TO_COMMAND("toCommand", "作业命令", "DB52.W2"), + TO_COLOR("toColor", "下发颜色", "DB52.W3"); - public int getMode() { - return this.getOpcIntegerValue(item_mode); - } + private final String key; + private final String description; + private final String address; - public int getAction() { - return this.getOpcIntegerValue(item_action); + ItemProtocol(String key, String description, String address) { + this.key = key; + this.description = description; + this.address = address; } - public int getError() { - return this.getOpcIntegerValue(item_error); + @Override + public String getKey() { + return this.key; } - public int getToCommand() { - return this.getOpcIntegerValue(item_to_command); + public String getDescription() { + return description; } - - public int getOpcIntegerValue(String protocol) { - Integer value = this.driver.getIntegeregerValue(protocol); - if (value == null) { - //log.error("读取错误!"); - } else { - return value; - } - return 0; - + public String getAddress() { + return address; } public static List getReadableItemDtos() { - ArrayList list = new ArrayList(); - list.add(new ItemDTO(item_heartbeat, "心跳", "DB51.B0")); - list.add(new ItemDTO(item_mode, "工作模式", "DB51.B1", Boolean.valueOf(true))); - list.add(new ItemDTO(item_action, "是否允许进入", "DB51.B2")); - list.add(new ItemDTO(item_error, "报警信号", "DB51.B4")); - list.add(new ItemDTO(item_color, "颜色", "DB51.B5")); + List list = new ArrayList<>(); + for (ItemProtocol prop : values()) { + if (!prop.getKey().startsWith("to")) { + list.add(new ItemDTO(prop.getKey(), prop.getDescription(), prop.getAddress())); + } + } return list; } public static List getWriteableItemDtos() { - ArrayList list = new ArrayList(); - list.add(new ItemDTO(item_to_command, "作业命令", "DB52.W2", Boolean.valueOf(true))); - list.add(new ItemDTO(item_to_color, "颜色", "DB52.W3", Boolean.valueOf(true))); + List list = new ArrayList<>(); + for (ItemProtocol prop : values()) { + if (prop.getKey().startsWith("to")) { + list.add(new ItemDTO(prop.getKey(), prop.getDescription(), prop.getAddress())); + } + } return list; } } - diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/LampThreecolorDefinition.java b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/LampThreecolorDefinition.java index 79915f5..ac6ce9b 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/LampThreecolorDefinition.java +++ b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/LampThreecolorDefinition.java @@ -1,19 +1,15 @@ package org.nl.acs.device_driver.lamp_three_color; - import org.nl.acs.device.device_driver.standard_inspect.ItemDTO; import org.nl.acs.device_driver.DeviceDriver; +import org.nl.acs.device_driver.ItemDto; import org.nl.acs.device_driver.definition.OpcDeviceDriverDefinition; import org.nl.acs.opc.Device; import org.nl.acs.opc.DeviceType; import org.springframework.stereotype.Service; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -/** - * 自动门驱动定义 - */ @Service public class LampThreecolorDefinition implements OpcDeviceDriverDefinition { @Override @@ -34,7 +30,6 @@ public class LampThreecolorDefinition implements OpcDeviceDriverDefinition { @Override public DeviceDriver getDriverInstance(Device device) { return (new LampThreecolorDeviceDriver()).setDevice(device).setDriverDefinition(this); - } @Override @@ -45,22 +40,19 @@ public class LampThreecolorDefinition implements OpcDeviceDriverDefinition { @Override public List getFitDeviceTypes() { List types = new LinkedList(); - types.add(DeviceType.conveyor); + types.add(DeviceType.color); return types; } + @Override public List getReadableItemDTOs() { - return getReadableItemDtos2(); - } - - public static List getReadableItemDtos2() { return ItemProtocol.getReadableItemDtos(); } @Override public List getWriteableItemDTOs() { return ItemProtocol.getWriteableItemDtos(); - } + } } diff --git a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/LampThreecolorDeviceDriver.java b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/LampThreecolorDeviceDriver.java index 6efb55c..888aff9 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/LampThreecolorDeviceDriver.java +++ b/acs2/nladmin-system/src/main/java/org/nl/acs/device_driver/lamp_three_color/LampThreecolorDeviceDriver.java @@ -2,120 +2,148 @@ package org.nl.acs.device_driver.lamp_three_color; import com.alibaba.fastjson.JSONObject; import lombok.Getter; -import lombok.Setter; import lombok.RequiredArgsConstructor; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.nl.acs.agv.server.impl.XianGongAgvServiceImpl; -import org.nl.acs.device.device_driver.standard_inspect.ReadUtil; -import org.nl.acs.device.service.DeviceService; import org.nl.acs.device_driver.DeviceDriver; +import org.nl.acs.device_driver.DeviceDriverBaseReader; +import org.nl.acs.device_driver.RouteableDeviceDriver; +import org.nl.acs.device_driver.StandardRequestMethod; import org.nl.acs.device_driver.driver.AbstractOpcDeviceDriver; import org.nl.acs.device_driver.driver.ExecutableDeviceDriver; import org.nl.acs.ext.UnifiedResponse; -import org.nl.acs.instruction.service.InstructionService; +import org.nl.acs.monitor.DeviceStageMonitor; import org.nl.acs.opc.Device; -import org.nl.acs.route.service.RouteLineService; -import org.nl.acs.task.service.TaskService; +import org.nl.modules.lucene.service.LuceneExecuteLogService; +import org.nl.modules.lucene.service.dto.LuceneLogDto; import org.nl.modules.wql.util.SpringContextHolder; -import org.openscada.opc.lib.da.Server; -import org.springframework.beans.factory.annotation.Autowired; -import java.util.*; - -/** - * 检测站点驱动 - */ @Slf4j @Getter @Setter @RequiredArgsConstructor -public class LampThreecolorDeviceDriver extends AbstractOpcDeviceDriver implements DeviceDriver, ExecutableDeviceDriver { - protected ItemProtocol itemProtocol = new ItemProtocol(this); - - InstructionService instructionService = SpringContextHolder.getBean("instructionServiceImpl"); - - DeviceService deviceservice = SpringContextHolder.getBean("deviceServiceImpl"); - - RouteLineService routelineserver = SpringContextHolder.getBean("routeLineServiceImpl"); - - TaskService taskserver = SpringContextHolder.getBean("taskServiceImpl"); - String container; - String container_type_desc; - String last_container_type_desc; - String last_container; - //放货准备锁 - String putReadyLock = null; - //有货标记 - protected boolean has_goods_tag = false; - String devicecode; - int mode = 0; - int action = 0; - int heartbeat = 0; - int color = 0; - int error = 0; - int move = 0; - int task = 0; - int last_action = 0; - int last_mode = 0; - int last_error = 0; - int last_move = 0; - int last_task = 0; - - String car_no = ""; - - boolean hasVehicle = false; - boolean isReady = false; - protected int instruction_num = 0; - protected int instruction_num_truth = 0; - protected boolean hasGoods = false; - boolean isFold = false; - private String assemble_check_tag; - private Boolean sampleMode0; - private Boolean sampleMode3; - private Integer sampleError; - private Boolean sampleOnline; - protected String displayMessage = null; - public int display_message_time_out = 30000; - public Date display_message_time; - protected String current_stage_instruction_message; - protected String last_stage_instruction_message; - Integer heartbeat_tag; - private Date instruction_require_time = new Date(); - private Date instruction_finished_time = new Date(); - - private int instruction_require_time_out; - boolean requireSucess = false; - - private int instruction_finished_time_out; - - int branchProtocol = 0; +public class LampThreecolorDeviceDriver extends AbstractOpcDeviceDriver implements + DeviceDriver, + ExecutableDeviceDriver, + RouteableDeviceDriver, + DeviceStageMonitor, + StandardRequestMethod, + DeviceDriverBaseReader { + + private final LuceneExecuteLogService logService = SpringContextHolder.getBean(LuceneExecuteLogService.class); + + /** + * 心跳 + */ + private int heartbeat = 0; + private int lastHeartbeat = 0; + /** + * 工作模式 + */ + private int mode = 0; + private int lastMode = 0; + /** + * 是否允许进入 + */ + private int action = 0; + private int lastAction = 0; + /** + * 报警信号 + */ + private int error = 0; + private int lastError = 0; + /** + * 颜色 + */ + private int color = 0; + private int lastColor = 0; + /** + * 作业命令 + */ + private int toCommand = 0; + private int lastToCommand = 0; + /** + * 下发颜色 + */ + private int toColor = 0; + private int lastToColor = 0; + /** + * 当前设备编号 + */ + private String currentDeviceCode; + + /** + * 消息 + */ + private String message; + + /** + * 请求标记 + */ + boolean requireSuccess = false; + + /** + * 请求时间 + */ + private long requireTime = System.currentTimeMillis(); + + /** + * 请求间隔时间 + */ + private long requireTimeOut = 3000L; + + /** + * 设备异常标记 + */ + private boolean isError = false; + + /** + * 车号 + */ + private String car_no; @Override public Device getDevice() { return this.device; } + @Override + public & KeyProvider, T> T getOpcValue(E item, Class fieldClassType) { + return (T) this.getValue(item.getKey()); + } + + @Override + public void setLog(String key, Object newValue, Object oldValue) { + logService.deviceExecuteLog(new LuceneLogDto(this.currentDeviceCode, "自动线程读取信号:" + key + ",由" + oldValue + "->" + newValue)); + } @Override public void execute() { - String message = null; - - String device_code = this.getDevice().getDevice_code(); - heartbeat = this.itemProtocol.getHeartbeat(); - mode = this.itemProtocol.getMode(); - action = this.itemProtocol.getAction(); - error = this.itemProtocol.getError(); - color = this.itemProtocol.getColor(); - if (mode != last_mode) { - } - if (action != last_action) { - } - if (error != last_error) { - } - last_action = action; - last_mode = mode; - last_error = error; + this.currentDeviceCode = this.getDevice().getDevice_code(); + this.loadAssignData(currentDeviceCode, ItemProtocol.class); + } + + @Override + public void executeLogic() { + + this.executeLogicBefore(); + if (!this.online) { + this.message = "设备离线"; + } else if (this.mode == 0) { + this.message = "设备未联机"; + } else if (this.error != 0) { + this.message = "设备报警"; + this.isError = true; + } else { + this.isError = false; + this.message = ""; + //编写业务逻辑方法 + } + } + + private void executeLogicBefore() { if (error == 1) { String[] carArr = {car_no}; JSONObject json = new JSONObject(); @@ -123,76 +151,26 @@ public class LampThreecolorDeviceDriver extends AbstractOpcDeviceDriver implemen // 请求下发agv急停 XianGongAgvServiceImpl xianGongAgv = SpringContextHolder.getBean(XianGongAgvServiceImpl.class); //创建订单序列 - UnifiedResponse response = xianGongAgv.sendOrderStopToXZ(json); - - if (!response.isSuccess()) { - } else { - } - } - - //message = StringFormatUtl.format("设备报警:{}", new Object[]{}); -// String manual_create_task = this.getDevice().getExtraValue().get("manual_create_task").toString(); - - - } - - public synchronized String getStatus() { - JSONObject jo = new JSONObject(); - - if (action == 1) { - jo.put("name", this.getDevice().getDevice_code()); - jo.put("status", "OPEN"); - - } else if (action == 2) { - jo.put("name", this.getDevice().getDevice_code()); - jo.put("status", "CLOSE"); - - } else { - jo.put("name", this.getDevice().getDevice_code()); - jo.put("status", "ERROR"); + xianGongAgv.sendOrderStopToXZ(json); } - return jo.toString(); - } - - - public void writing(int command) { - String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_command; - - String opcservcerid = this.getDevice().getOpc_server_id(); - Server server = ReadUtil.getServer(opcservcerid); - Map itemMap = new HashMap(); - itemMap.put(to_command, command); - ReadUtil.write(itemMap, server); - ReadUtil.write(itemMap, server); - server.disconnect(); - log.info("下发PLC信号:{},{}", to_command, command); - System.out.println("设备:" + devicecode + ",下发PLC信号:" + to_command + ",value:" + command); } - public void writing(int command,int color) { - String toCommand = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_command; - - String toColor = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() - + "." + ItemProtocol.item_to_color; - - String opcservcerid = this.getDevice().getOpc_server_id(); - Server server = ReadUtil.getServer(opcservcerid); - Map itemMap = new HashMap(); - itemMap.put(toCommand, command); - itemMap.put(toColor, color); - ReadUtil.write(itemMap, server); - ReadUtil.write(itemMap, server); - server.disconnect(); - log.info("下发PLC信号:{},{}", toCommand, command); - log.info("下发PLC信号:{},{}", toColor, color); - System.out.println("设备:" + devicecode + ",下发PLC信号:" + toCommand + ",value:" + command); - System.out.println("设备:" + devicecode + ",下发PLC信号:" + toColor + ",value:" + color); + @Override + public JSONObject getDeviceStatusName() throws Exception { + JSONObject jo = new JSONObject(); + jo.put("device_code", this.currentDeviceCode); + jo.put("device_name", this.getDevice().getDevice_name()); + jo.put("driver_type", "lamp_three_color"); + jo.put("is_click", false); + jo.put("message", this.message); + jo.put("isOnline", this.online); + jo.put("isError", this.isError); + return jo; } - public synchronized void OpenOrClose(String type) { - writing(Integer.parseInt(type)); + @Override + public void setDeviceStatus(JSONObject data) { + } } diff --git a/acs2/nladmin-system/src/main/java/org/nl/config/mqtt2/MqttService.java b/acs2/nladmin-system/src/main/java/org/nl/config/mqtt2/MqttService.java index ead4dba..94b58dc 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/config/mqtt2/MqttService.java +++ b/acs2/nladmin-system/src/main/java/org/nl/config/mqtt2/MqttService.java @@ -57,7 +57,7 @@ public class MqttService implements ApplicationAutoInitial { @Autowired private DeviceAppService deviceAppService; - + private final CountDownLatch latch = new CountDownLatch(1); private Mqtt3AsyncClient mqttClient; /** @@ -169,7 +169,7 @@ public class MqttService implements ApplicationAutoInitial { .serverHost(mqttConfig.getUrl()) .addDisconnectedListener((context -> { Throwable cause = context.getCause(); - log.error("mqtt client disconnected , {}", cause.getMessage()); + log.error("[MQTT 断开连接, {}]", cause.getMessage()); MqttClientReconnector reconnect = context.getReconnector(); reconnect.reconnect(true); reconnect.delay(RECONNECT_DELAY, TimeUnit.MILLISECONDS); @@ -188,11 +188,11 @@ public class MqttService implements ApplicationAutoInitial { .cleanSession(mqttConfig.getCleanSession()) .send() .thenAccept(connAck -> { - log.info("mqtt client connection success."); + log.info("[MQTT 连接成功]"); subscribeToTopics(Arrays.asList(mqttConfig.getTopics())); }) .exceptionally(throwable -> { - log.error("mqtt client connection failed: " + throwable.getMessage(), throwable); + log.error("[MQTT 连接失败, {}]", throwable.getMessage()); return null; }); @@ -201,6 +201,17 @@ public class MqttService implements ApplicationAutoInitial { String payload = new String(publish.getPayloadAsBytes(), StandardCharsets.UTF_8); messageArrived(topic, payload); }); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + latch.await(); + log.info("[MQTT 关闭程序]"); + System.out.println("[关闭程序]"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + })); + } private void subscribeToTopics(List topics) { @@ -292,7 +303,7 @@ public class MqttService implements ApplicationAutoInitial { */ public void setOnline(String deviceCode, List tags) { Optional heartbeatPresent = tags.stream() - .filter(tag -> tag.getId().contains(HEARTBEAT) || tag.getId().contains("move")) + .filter(tag -> tag.getId().contains(HEARTBEAT)) .map(Tag::isQ) .findFirst(); heartbeatPresent.ifPresent(q -> { @@ -326,13 +337,26 @@ public class MqttService implements ApplicationAutoInitial { @PreDestroy public void cleanup() { - if (mqttClient != null) { - unloadTags(); - mqttClient.disconnect().thenAccept(disconnectAck -> { - threadPool.shutdown(); - log.info("Application Close, So MQTT client disconnected."); - }); - } + CompletableFuture mqttDisconnectFuture = CompletableFuture.runAsync(() -> { + if (mqttClient != null) { + mqttClient.disconnect().thenAccept(disconnectAck -> System.out.println("[关闭MQTT Client]")); + log.info("[关闭MQTT Client]"); + } + }); + mqttDisconnectFuture.thenRun(() -> { + this.unloadTags(); + log.info("[加载Tags到Redis]"); + System.out.println("[加载Tags到Redis]"); + }).thenRun(() -> { + threadPool.shutdown(); + log.info("[关闭线程池]"); + System.out.println("[关闭线程池]"); + }).exceptionally(throwable -> { + log.error("[关闭异常 {}]", throwable.getMessage()); + System.out.println("[关闭异常]" + throwable.getMessage()); + return null; + }).join(); + latch.countDown(); } private void loadTags() { diff --git a/acs2/nladmin-system/src/main/java/org/nl/modules/logicflow/service/impl/StageServiceImpl.java b/acs2/nladmin-system/src/main/java/org/nl/modules/logicflow/service/impl/StageServiceImpl.java index af7a08d..f418784 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/modules/logicflow/service/impl/StageServiceImpl.java +++ b/acs2/nladmin-system/src/main/java/org/nl/modules/logicflow/service/impl/StageServiceImpl.java @@ -224,12 +224,7 @@ public class StageServiceImpl implements StageService { obj.put("device_name", standardCoveyorControlDeviceDriver.getDevice().getDevice_name()); jo.put("mode", mode); jo.put("move", move); - jo.put("hasGoods", standardCoveyorControlDeviceDriver.getHasGoods()); - jo.put("isOnline", standardCoveyorControlDeviceDriver.getIsonline()); jo.put("error", standardCoveyorControlDeviceDriver.getError()); - jo.put("isError", standardCoveyorControlDeviceDriver.getIserror()); - jo.put("requestSucess", standardCoveyorControlDeviceDriver.getRequireSucess()); - jo.put("applySucess", standardCoveyorControlDeviceDriver.getApplySucess()); jo.put("message", standardCoveyorControlDeviceDriver.getMessage()); } else if (device.getDeviceDriver() instanceof StandardAutodoorDeviceDriver) { standardAutodoorDeviceDriver = (StandardAutodoorDeviceDriver) device.getDeviceDriver(); diff --git a/acs2/nladmin-system/src/main/java/org/nl/start/auto/run/ElevatorSocketConnectionAutoRun.java b/acs2/nladmin-system/src/main/java/org/nl/start/auto/run/ElevatorSocketConnectionAutoRun.java index a0c022f..7964fef 100644 --- a/acs2/nladmin-system/src/main/java/org/nl/start/auto/run/ElevatorSocketConnectionAutoRun.java +++ b/acs2/nladmin-system/src/main/java/org/nl/start/auto/run/ElevatorSocketConnectionAutoRun.java @@ -48,7 +48,7 @@ public class ElevatorSocketConnectionAutoRun extends AbstractAutoRunnable { @Override public void autoRun() throws IOException, InterruptedException { - System.out.println("电梯链接开始"); +/* System.out.println("电梯链接开始"); String ip = "192.168.8.236"; int port = 502; InetSocketAddress socketAddress = new InetSocketAddress(ip, port); @@ -65,7 +65,7 @@ public class ElevatorSocketConnectionAutoRun extends AbstractAutoRunnable { throw new IllegalArgumentException("PLC端开连接!"); } Thread.sleep(5000); - } + }*/ } diff --git a/acs2/nladmin-system/src/main/resources/config/application-dev2.yml b/acs2/nladmin-system/src/main/resources/config/application-dev2.yml index ba3627a..2d990f2 100644 --- a/acs2/nladmin-system/src/main/resources/config/application-dev2.yml +++ b/acs2/nladmin-system/src/main/resources/config/application-dev2.yml @@ -6,9 +6,9 @@ spring: druid: db-type: com.alibaba.druid.pool.DruidDataSource driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy - url: jdbc:log4jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:sdk_acs}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true + url: jdbc:log4jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:sh_kn_acs}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true username: ${DB_USER:root} - password: ${DB_PWD:password} + password: ${DB_PWD:root} # 初始连接数 initial-size: 5 # 最小连接数 @@ -65,7 +65,7 @@ spring: url: 192.168.81.251 clientId: sdk_mqtt21 topics: - - SDK/# + - KN/# qoss: - 2 timeout: 30 diff --git a/acs2/nladmin-system/src/main/resources/config/application.yml b/acs2/nladmin-system/src/main/resources/config/application.yml index 9e96fc9..0602e94 100644 --- a/acs2/nladmin-system/src/main/resources/config/application.yml +++ b/acs2/nladmin-system/src/main/resources/config/application.yml @@ -2,7 +2,7 @@ spring: freemarker: check-template-location: false profiles: - active: prod + active: dev2 jackson: time-zone: GMT+8 data: