From bf41bcf83ecb8a59d979effc54a6bb9f9872e2ff Mon Sep 17 00:00:00 2001 From: sige Date: Tue, 18 Jun 2024 15:14:52 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=93=E6=9E=9C=E6=89=AB=E6=8F=8F=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.db | Bin 405504 -> 405504 bytes .../com/iflytop/a800/device/DeviceComponent.java | 26 ++++++++----- .../java/com/iflytop/a800/device/Incubator.java | 11 +++++- src/main/java/com/iflytop/a800/device/Scanner.java | 3 +- .../java/com/iflytop/a800/task/TubeTestTask.java | 41 ++++++++++++++++++--- 5 files changed, 62 insertions(+), 19 deletions(-) diff --git a/app.db b/app.db index 3fb31ded0b8836f6bb111a9c7e2a638ef670946c..f828ff89448a34fd66f6aebcd99301e31cc9ce29 100644 GIT binary patch delta 3405 zcmcImUuYaf7~kEyT$0P(ZH`pZ*p@V*&`LVq%+BoYOtsb|gtn$lt@Nl+LNl{FTZ`$% zaJD4YW*fzng3t!3hal1xst=+S8#$x}ANnNvAU;TuB1JGt=^q~i!Gbt&)Vw4 zEjPE{&G(z{`~8039KN#j@Rg;49 zt~Zxy2wL3*K0IFBTkI~57red#7sGO-@XLiaW`FCbNcz^cj$Fs+d zp`MYEVaW^S)8~!dOPW%nS|WK-OTCx8SWbOs981PC)A|q7r&cB3>@w=jmTY#auYBf5 zXP7Y?KwKdguYxR1wRlVyiAG~aw*2{fA85i_rP5oLj*{?NCCi~4W^LOS@`mf|S zX+1TW(iQ9{lcndb8rh97;1W>`Y{3a2!m$A(oC3;mKqzBEKoUyqCTC^w=K(d=xwd($I=LK<}+IW=`jk3t8!5{V8He; zCWzXO?cyjIcJ}PHw{F?ly?MvxfsKU`i$Dk3m_U-)+C7l(-mdzKAcp9jc6E|k6q{BT0Az+RE<_&5K$OJU5rRVJj1L2jE! zE-Dg40k=I>U2Y521|K8!jYL3Ix#2_FZLqKpu z0LH>4lye%u;1K|XkTui-XjlZm5{P5ZSL6r?10*02FzNV!A;?|Vw<*Tn!vhEjbn9yX zD3OmZ;Hl4C;V8N*THC4u0t+Aln*d7+hOK}R57UPRP}+OLNbi}{5|uNz&q?FIP1*Ni zUvIu5juO9NbZxREVc5qm;8ZF~N%i2K;+5+oezW1=PnR z>XvP#n>UTNC7C_u+04(GFHK@jWsaMd%qDYC8D4)TTocRdQIwXf1V&LrVgeh=sbgU{ybEW3N&mD20^19gqc%7T(j+Y5|Zr z00_Yk^%7mwB8aP0v3>Yk*=I>KtQNed`rwg8rajUDQFoZ3os)&qU876*Q} zJ<%GD;jA#3a(9R%^e=%>fysG zc`KYLYcp!3PUZ6xi*%%@@PF!P_3c~W0wERSNrfX}HfhTFFPT&3pn29L=dvsRygdP; g5VLBoQD9fiH44+J-g+Pk7pmqOrF~U%jp7ae08vPC3;+NC delta 4764 zcmcgvUu+yl9p2qL-=96-ZLGAUAqi2eqT_3%mf?LPaPXWd^M^{-WeAGY2NnyqWU zp4#_Ht0K$g_RLgIpKu@S-9GN_t4OcherSL1sacnJYiVzC*8TE?2;O#7?}=HL_m+;k zvXQK%D=UuUsF`5+X3JGqHfG)RjajdLsT4G>_o~10j>1QN&{)6zTkqU`jn=D9#edD2 z{I37n`sAOyAN&5xPkYs1|J2l#``7>YSMO(T@8%6}-{BXkM^zs?E8XSNZ_OJi^hIjqW3-#d(>-=xtJMJO>9mn@iJB_Y?I>=fdwJtVq zH=O2+leZ?<0MBv1_x1O^sd+*$52FOdCdG(hjgd03MO0vd8Iwt?mYCgxHlx_AA3Zzh{`ov3~A(9|*a;DP4-O%~D!bIg&##3IIpKw2dP;WWij zm{1j3+jX*Pv)w*;WG^q>15vgO(%F;eqQ@Wm+QQ<()2F`rmE}&z082y}4l9q(Ew<+# zduEzUFU_^jJn@oy7eQ?R8=HhFkx&H3)xZhBR>Eo&31Os(LW)B*7D13F<-LCbDWH(m z5mKZjDy5pDNO53O$r$NGDHKyeLrJtGF&?{nZu2|GJ3F^VG<`1(i{^wI*3Bch$EbEW)iMba}Q$29(@b~QOi{} zt2MK2;u284NJdC;3v$;^z>nlsg#)rUbPt!mb#e$Z|=n^Oml9Xqn$EqmY6;Pp~4f}lG=pM*1{m`xFkN6wX2 z@GmT)D@?w*^5{37><=3v5GH&$cG#nH^YbS;Z?C1MN&Et-SxWyLkm748*^!A=%H%>TLwy~W#pDNv(Y=>t#rdA@Y zl>y5%31o;cK~~#P#5zn_%!{;io<2IHFC3w-Vmtro0)5$D%U;Qq9rUS zqVJIc+RjEi4dU@jn@&9C)M}rGHDsG-T<+K|t>si2NnkjJXviT?fv3V0P>gH1^cV`) zq!6c+7YPJ8jtLuboT*I!aD}Xbr`Gq%GK_+94t5Hbporv%z`z1ezy?VTp-qEmgjGx$ z1~Y7s>5lIh>hid8@2SsK4rHB;AAJIpr5s9QEZi9dTmmIr1Q^o<3>U-gP|%1aDKVsf zhA~+&%Z0@pO00(L@)2@9+u5LdhaGw&u?h+V;;Z2u5 Iypv7;57S8AUH||9 diff --git a/src/main/java/com/iflytop/a800/device/DeviceComponent.java b/src/main/java/com/iflytop/a800/device/DeviceComponent.java index f88f447..d7bd212 100644 --- a/src/main/java/com/iflytop/a800/device/DeviceComponent.java +++ b/src/main/java/com/iflytop/a800/device/DeviceComponent.java @@ -16,7 +16,8 @@ abstract public class DeviceComponent { // lock public DeviceComponentLock lock( String name ) { - LOG.info("LOCK : {}", name); + var comName = this.getClass().getSimpleName(); + LOG.info("[Device:{}] LOCK => {}", comName, name); var lock = new DeviceComponentLock(); lock.name = name; @@ -27,28 +28,33 @@ abstract public class DeviceComponent { } } - LOG.info("LOCK WAITING : {}", name); - try { - lock.wait(); - } catch (InterruptedException e) { - throw new RuntimeException(e); + LOG.info("[Device:{}] LOCK WAITING => {}", comName, name); + synchronized ( lock ) { + try { + lock.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } - LOG.info("LOCK DONE : {}", name); + LOG.info("[Device:{}] LOCK DONE => {}", comName, name); return lock; } // unlock public void unlock( DeviceComponentLock lock ) { + var comName = this.getClass().getSimpleName(); synchronized ( this.locks ) { - LOG.info("UNLOCK : {}", lock.name); + LOG.info("[Device:{}] UNLOCK => {}", comName, lock.name); this.locks.remove(lock); if ( this.locks.isEmpty() ) { return ; } + } - var next = this.locks.get(0); - LOG.info("NOTIFY NEXT : {}", next.name); + var next = this.locks.get(0); + LOG.info("[Device:{}] NOTIFY NEXT => {}", comName, next.name); + synchronized ( next ) { next.notifyAll(); } } diff --git a/src/main/java/com/iflytop/a800/device/Incubator.java b/src/main/java/com/iflytop/a800/device/Incubator.java index a48babb..74a4c40 100644 --- a/src/main/java/com/iflytop/a800/device/Incubator.java +++ b/src/main/java/com/iflytop/a800/device/Incubator.java @@ -1,6 +1,7 @@ package com.iflytop.a800.device; import com.iflytop.a800.resource.IncubatorSlot; import com.iflytop.a800.resource.TestCard; +import com.iflytop.uf.UfActuatorCmdExecutor; import com.iflytop.uf.UfCmdSnippetExecutor; import com.iflytop.uf.model.UfMdbOption; import java.util.ArrayList; @@ -23,6 +24,14 @@ public class Incubator extends DeviceComponent { } } + // 移动至提交位置 + public void moveToCommitPos( IncubatorSlot slot ) { + Integer commitStartPos = UfMdbOption.getInteger("IncubatorSlotCommitStartPos"); + Integer commitDistance = UfMdbOption.getInteger("IncubatorSlotCommitDistance"); + int commitPos = commitStartPos + commitDistance * slot.index; + UfActuatorCmdExecutor.execute("MotorIncubatorRotate", "motor_easy_move_to", Integer.toString(commitPos)); + } + // 推送新卡片 public IncubatorSlot pushNewCard(TestCard card) { var lock = this.lock("PushNewCard"); @@ -63,13 +72,11 @@ public class Incubator extends DeviceComponent { // 退出到扫描 public void exitCardToScanner( IncubatorSlot slot ) { - var lock = this.lock("ExitCardToScanner"); Integer startPos = UfMdbOption.getInteger("IncubatorSlotExitStartPos"); Integer distance = UfMdbOption.getInteger("IncubatorSlotExitDistance"); Integer slotPos = startPos + distance * slot.index; Map params = Map.of("slot", slotPos); UfCmdSnippetExecutor.execute("IncubatorTestCardExitToScanner", params); slot.card = null; - this.unlock(lock); } } diff --git a/src/main/java/com/iflytop/a800/device/Scanner.java b/src/main/java/com/iflytop/a800/device/Scanner.java index 56e1c94..2c74c88 100644 --- a/src/main/java/com/iflytop/a800/device/Scanner.java +++ b/src/main/java/com/iflytop/a800/device/Scanner.java @@ -2,13 +2,12 @@ package com.iflytop.a800.device; import com.iflytop.uf.UfActuatorCmdExecutor; import com.iflytop.uf.UfCmdSnippetExecutor; import com.iflytop.uf.util.UfCommon; - import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Base64; import java.util.List; -public class Scanner { +public class Scanner extends DeviceComponent { // 扫描类型F public void scanTypeF() { UfCmdSnippetExecutor.execute("SampleResultAnalysisTypeF"); diff --git a/src/main/java/com/iflytop/a800/task/TubeTestTask.java b/src/main/java/com/iflytop/a800/task/TubeTestTask.java index 0d611d7..be72a64 100644 --- a/src/main/java/com/iflytop/a800/task/TubeTestTask.java +++ b/src/main/java/com/iflytop/a800/task/TubeTestTask.java @@ -164,7 +164,6 @@ public class TubeTestTask extends TaskBase { case "mixing" : this.executeStepMixing(stepNode); break; case "drop-tip" : this.executeStepDropTip(stepNode); break; case "incubate" : this.executeStepIncubate(stepNode); break; - case "analysis" : this.executeStepAnalysis(stepNode); break; case "sampling-done" : this.executeStepSamplingDone(stepNode); break; } } catch ( InterruptedException e ) { @@ -172,7 +171,9 @@ public class TubeTestTask extends TaskBase { } } + this.analysis(); this.taskFinish(); + this.log("项目测试结束"); } // 采样完成 @@ -305,6 +306,7 @@ public class TubeTestTask extends TaskBase { // 提交样本至孵育盘测试卡 var incubatorLock = device.incubator.lock("SampleCommit"); + device.incubator.moveToCommitPos(this.incubatorSlot); Integer volume = stepNode.get("volume").asInt(); pipette.aspirateFromBufferTubeAndDispenseToTestCard(this.bufferTube, volume); device.incubator.unlock(incubatorLock); @@ -327,16 +329,40 @@ public class TubeTestTask extends TaskBase { this.log("孵育完成,等待扫描结果"); } - // 扫描 - private void executeStepAnalysis( JsonNode stepNode ) { - this.log("扫描结果"); + // 扫描分析结果 + private void analysis() { + var asyncEnable = UfMdbOption.getBoolean("AnalysisAsyncEnable", false); + if ( !asyncEnable ) { + this.executeAnalysis(); + this.log("结果分析完成"); + return ; + } + + var thread = new Thread(this::executeAnalysis); + thread.start(); + this.taskWait("AnalysisDone"); + this.log("结果分析完成"); + } + + /** + * 执行扫描分析操作 + */ + private void executeAnalysis() { + this.log("结果扫描"); Device device = Device.getInstance(); - device.incubator.exitCardToScanner(this.incubatorSlot); var scanner = device.scanner; + var scannerLock = scanner.lock("ScanResult"); + + var incubator = device.incubator; + var exitCardLock = incubator.lock("ExitCard"); + incubator.exitCardToScanner(this.incubatorSlot); + incubator.unlock(exitCardLock); + scanner.scanTypeF(); var scanResult = scanner.readResult(); scanner.dropCard(); + scanner.unlock(scannerLock); // 计算 var algo = new ScanResultAnalysisAlgo(); @@ -395,6 +421,11 @@ public class TubeTestTask extends TaskBase { this.test.result = UfJsonHelper.objectToJson(results); this.test.save(); + + var asyncEnable = UfMdbOption.getBoolean("AnalysisAsyncEnable", false); + if ( asyncEnable ) { + this.setStatus("READY"); + } } /**