11 changed files with 347 additions and 12 deletions
-
21src/main/java/a8k/app/hardware/driver/PipetteCtrlDriverV2.java
-
13src/main/java/a8k/app/hardware/type/A8kPacket.java
-
1src/main/java/a8k/app/hardware/type/CmdId.java
-
1src/main/java/a8k/app/hardware/type/pipette_module/cfg/PipetteCommonConfigIndex.java
-
10src/main/java/a8k/app/hardware/type/pipette_module/cfgbean/PipetteCommonConfig.java
-
84src/main/java/a8k/app/service/module/TurntableAndOptScannerCtrlModule.java
-
64src/main/java/a8k/app/service/statemgr/ReactionPlateContainerStateMgr.java
-
100src/main/java/a8k/app/utils/ZWorkThread.java
-
7src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunCommonConfigPage.java
-
36src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunOperationCtrlPage.java
-
22src/main/java/a8k/extui/page/driver/pipette_module/PipetteGunTestCtrlPage.java
@ -0,0 +1,84 @@ |
|||
package a8k.app.service.module; |
|||
|
|||
import a8k.app.service.data.ReactionRecordMgrService; |
|||
import a8k.app.service.lowerctrl.OptScanModuleCtrlService; |
|||
import a8k.app.service.statemgr.IncubationPlateStateMgrService; |
|||
import a8k.app.service.statemgr.OptScanModuleStateMgrService; |
|||
import a8k.app.teststate.VirtualDevice; |
|||
import a8k.app.utils.ZWorkThread; |
|||
import jakarta.annotation.PostConstruct; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Component |
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
public class TurntableAndOptScannerCtrlModule { |
|||
public enum State { |
|||
idle, |
|||
starting, |
|||
working, |
|||
stopping, |
|||
} |
|||
|
|||
// |
|||
//状态 |
|||
// |
|||
private final VirtualDevice virtualDevice; |
|||
private final IncubationPlateStateMgrService incubationPlateStateMgrService; |
|||
private final OptScanModuleStateMgrService optScanModuleStateMgrService; |
|||
// |
|||
// 数据库 |
|||
// |
|||
private final ReactionRecordMgrService reactionRecordMgrService; |
|||
// |
|||
// 控制 |
|||
// |
|||
private final OptScanModuleCtrlService optScanModuleCtrlService; |
|||
|
|||
|
|||
private ZWorkThread workThread; |
|||
private State state = State.idle; |
|||
private final Object stateLock = new Object(); |
|||
private final Object turntableLock = new Object(); |
|||
|
|||
@PostConstruct |
|||
public void init() { |
|||
state = State.idle; |
|||
workThread = new ZWorkThread(); |
|||
workThread.init("TurntableAndOptScannerCtrlModule-WorkThread"); |
|||
} |
|||
|
|||
public void workThreadFn() { |
|||
// while (!workThread.isStopping()) { |
|||
// } |
|||
} |
|||
|
|||
|
|||
// |
|||
// utils |
|||
// |
|||
private void setState(State state) { |
|||
synchronized (stateLock) { |
|||
this.state = state; |
|||
log.info("TurntableAndOptScannerCtrlModule state changed to {}", state); |
|||
} |
|||
} |
|||
|
|||
private State getState() { |
|||
synchronized (stateLock) { |
|||
return state; |
|||
} |
|||
} |
|||
|
|||
private void waitForState(State state) { |
|||
while (!getState().equals(state)) { |
|||
try { |
|||
Thread.sleep(50); |
|||
} catch (InterruptedException ignored) { |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,64 @@ |
|||
package a8k.app.service.statemgr; |
|||
|
|||
import a8k.app.constant.AppConstant; |
|||
import a8k.app.type.a8k.ConsumableGroup; |
|||
import a8k.app.type.a8k.container.ReactionPlateContainer; |
|||
import jakarta.annotation.PostConstruct; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Component |
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
public class ReactionPlateContainerStateMgr { |
|||
|
|||
public ReactionPlateContainer[] reactionPlateGroup = new ReactionPlateContainer[AppConstant.CONSUMABLE_CHANNEL_NUM]; |
|||
|
|||
@PostConstruct |
|||
void init() { |
|||
for (int i = 0; i < reactionPlateGroup.length; i++) { |
|||
reactionPlateGroup[i] = new ReactionPlateContainer(); |
|||
} |
|||
} |
|||
|
|||
synchronized void installReactionPlateContainer(ConsumableGroup group, Integer projId, String projName, String projShortName, String lotId, String color, Integer num) { |
|||
ReactionPlateContainer reactionPlateContainer = reactionPlateGroup[group.off]; |
|||
reactionPlateContainer.projId = projId; |
|||
reactionPlateContainer.projName = projName; |
|||
reactionPlateContainer.projShortName = projShortName; |
|||
reactionPlateContainer.lotId = lotId; |
|||
reactionPlateContainer.color = color; |
|||
reactionPlateContainer.num = num; |
|||
reactionPlateContainer.isInstall = true; |
|||
reactionPlateContainer.reserveNum = 0; |
|||
} |
|||
|
|||
synchronized void setReactionPlateNum(ConsumableGroup group, Integer num) { |
|||
log.debug("setReactionPlateNum: group={}, num={}", group, num); |
|||
ReactionPlateContainer reactionPlateContainer = reactionPlateGroup[group.off]; |
|||
if (reactionPlateContainer.isInstall) { |
|||
reactionPlateContainer.num = num; |
|||
} else { |
|||
log.warn("setReactionPlateNum: Reaction plate container is not installed for group: {}", group); |
|||
} |
|||
} |
|||
|
|||
|
|||
synchronized Boolean popOneReactionPlate(ConsumableGroup group) { |
|||
log.debug("popOneReactionPlate: group={}", group); |
|||
ReactionPlateContainer reactionPlateContainer = reactionPlateGroup[group.off]; |
|||
if (reactionPlateContainer.isInstall && reactionPlateContainer.num > 0) { |
|||
reactionPlateContainer.num--; |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
synchronized void uninstallReactionPlateContainer(ConsumableGroup group) { |
|||
log.debug("uninstallReactionPlateContainer: group={}", group); |
|||
ReactionPlateContainer reactionPlateContainer = reactionPlateGroup[group.off]; |
|||
reactionPlateContainer.reset(); |
|||
} |
|||
} |
@ -0,0 +1,100 @@ |
|||
package a8k.app.utils; |
|||
|
|||
import org.springframework.util.Assert; |
|||
|
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
public class ZWorkThread { |
|||
Thread thread; |
|||
Runnable pendingRunnable; |
|||
AtomicBoolean workingFlag = new AtomicBoolean(false); |
|||
AtomicBoolean stopPendingFlag = new AtomicBoolean(false); |
|||
|
|||
|
|||
public void init(String name) { |
|||
thread = new Thread(this::workThread); |
|||
thread.setName(name); |
|||
thread.start(); |
|||
} |
|||
|
|||
|
|||
synchronized public void start(Runnable runnable) { |
|||
Assert.isTrue(thread != null, "Thread not initialized. Call init() first."); |
|||
|
|||
if (workingFlag.get()) { |
|||
stop(); |
|||
} |
|||
pendingRunnable = runnable; |
|||
} |
|||
|
|||
synchronized public void stop() { |
|||
Assert.isTrue(thread != null, "Thread not initialized. Call init() first."); |
|||
|
|||
stopPendingFlag.set(true); |
|||
while (workingFlag.get()) { |
|||
threadSleep(50); |
|||
} |
|||
stopPendingFlag.set(false); |
|||
} |
|||
|
|||
public Boolean isStopping() { |
|||
return stopPendingFlag.get(); |
|||
} |
|||
|
|||
public Boolean isWorking() { |
|||
return workingFlag.get(); |
|||
} |
|||
|
|||
|
|||
private void workThread() { |
|||
while (true) { |
|||
Runnable runnable = null; |
|||
if (pendingRunnable != null) { |
|||
runnable = pendingRunnable; |
|||
pendingRunnable = null; |
|||
} |
|||
|
|||
if (runnable == null) { |
|||
threadSleep(50); |
|||
continue; |
|||
} |
|||
|
|||
workingFlag.set(true); |
|||
runnable.run(); |
|||
workingFlag.set(false); |
|||
} |
|||
} |
|||
|
|||
|
|||
public void threadSleep(int ms) { |
|||
try { |
|||
Thread.sleep(ms); |
|||
} catch (InterruptedException ignored) { |
|||
} |
|||
} |
|||
|
|||
public static void main(String[] args) throws InterruptedException { |
|||
ZWorkThread workThread = new ZWorkThread(); |
|||
workThread.init("TestWorkThread"); |
|||
|
|||
workThread.start(() -> { |
|||
while (!workThread.isStopping()) { |
|||
System.out.println("Task 1 is running"); |
|||
workThread.threadSleep(100); |
|||
} |
|||
}); |
|||
|
|||
Thread.sleep(3000); |
|||
workThread.stop(); |
|||
|
|||
workThread.start(() -> { |
|||
while (!workThread.isStopping()) { |
|||
System.out.println("Task 2 is running"); |
|||
workThread.threadSleep(100); |
|||
} |
|||
}); |
|||
Thread.sleep(3000); |
|||
workThread.stop(); |
|||
} |
|||
|
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue