sige 1 year ago
parent
commit
5191851edd
  1. BIN
      app.db
  2. 119
      src/main/java/com/iflytop/digester/DigestionTaskThread.java
  3. 15
      src/main/java/com/iflytop/digester/controller/CameraController.java
  4. 9
      src/main/java/com/iflytop/digester/controller/DigestionTaskController.java
  5. 4
      src/main/java/com/iflytop/digester/controller/LiquidController.java
  6. 5
      src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java
  7. 15
      src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionLiquid.java
  8. 16
      src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java
  9. 5
      src/main/java/com/iflytop/digester/model/MdbDigestionTask.java
  10. 15
      src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbNotification.java
  11. 10
      src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbRuntimeVariable.java

BIN
app.db

119
src/main/java/com/iflytop/digester/DigestionTaskThread.java

@ -94,25 +94,38 @@ public class DigestionTaskThread extends Thread {
public void run() {
try {
this.prepare();
// 解析消解配方并取出首轮和末轮配置
var rounds = this.solution.getDigestionRounds();
var firstRound = rounds.remove(0);
var lastRound = rounds.remove(rounds.size() - 1);
MdbDigestionSolution.DigestionSolutionRound firstRound = null;
if ( !rounds.isEmpty() && rounds.size() > 1 ) {
firstRound = rounds.remove(0);
}
MdbDigestionSolution.DigestionSolutionRound lastRound = null;
if ( !rounds.isEmpty() ) {
lastRound = rounds.remove(rounds.size() - 1);
}
// 执行第一轮
this.executeRound(firstRound);
if ( null != firstRound ) {
this.executeRound(firstRound);
}
// 执行中间轮
for (var round : rounds) {
this.executeRound(round);
}
// 执行最后一轮
this.executeLastRound(lastRound);
if ( null != lastRound ) {
this.executeLastRound(lastRound);
}
this.errorProcessThread.join();
this.updateTaskStatus("Finish", "消解任务结束");
this.finishCallback.callback(this);
} catch (Exception e) {
this.updateTaskStatus("Error", e.getMessage());
UfMdbNotification.error("消解任务执行失败 : " + e.getMessage());
} finally {
this.finishCallback.callback(this);
}
}
@ -123,17 +136,23 @@ public class DigestionTaskThread extends Thread {
var device = Device.getInstance();
// 分配加热位
this.heatingSlot = device.heatingTurntable.allocSlot(this.taskModel.batchNo);
if ( "manual".equals(this.taskModel.mode) ) {
this.heatingSlot = device.heatingTurntable.getSlotByIndex(this.taskModel.heatingSlotIndex);
} else {
this.heatingSlot = device.heatingTurntable.allocSlot(this.taskModel.batchNo);
}
this.heatingSlot.setTubes(this.taskModel.getTubes());
this.taskModel.heatingSlotIndex = this.heatingSlot.index;
this.taskModel.save();
// 打开门
device.door.open();
// 等待放入试管架
this.waitForTubeRackPutIn(false);
// 关闭门
device.door.close();
if ( "auto".equals(this.taskModel.mode) ) {
// 打开门
device.door.open();
// 等待放入试管架
this.waitForTubeRackPutIn();
// 关闭门
device.door.close();
}
}
// 检查试管
@ -171,7 +190,7 @@ public class DigestionTaskThread extends Thread {
if ( !this.errorTubeIndexes.isEmpty() ) {
var device = Device.getInstance();
// 等待放入空试管架
this.waitForTubeRackPutIn(true);
this.waitForEmptyTubeRackPutIn();
// 取出剩余异常试管
device.transferArm.takeOutTubesFromErrorSlot(this.errorTubeIndexes);
// 等待取出试管架
@ -268,17 +287,19 @@ public class DigestionTaskThread extends Thread {
device.liquidAddition.addLiquidToTubes(this.heatingSlot.getExistTubeIndexes(), "water", digestionRound.waterVolume);
}
// 正常消解结束
// 移动到加液盘
device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index);
// 打开门
device.door.open();
// 等待取出
this.waitForTubeRackTakeOut();
// 关闭门
device.door.close();
// 释放加热位
this.heatingSlot.setTubeRackNo(null);
// 正常消解结束
if ( "auto".equals(this.taskModel.mode) ) {
// 移动到加液盘
device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index);
// 打开门
device.door.open();
// 等待取出
this.waitForTubeRackTakeOut();
// 关闭门
device.door.close();
// 释放加热位
this.heatingSlot.setTubeRackNo(null);
}
}
// 执行消解异常处理配置
@ -311,7 +332,7 @@ public class DigestionTaskThread extends Thread {
// 将试管架放入异常处理区域
device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index);
// 等待放入空试管架
this.waitForTubeRackPutIn(true);
this.waitForEmptyTubeRackPutIn();
// 取出消解完成的试管
device.transferArm.takeOutTubesFromErrorSlot(this.finishedErrorTubeIndexes);
// 等待取出试管架
@ -321,14 +342,37 @@ public class DigestionTaskThread extends Thread {
}
// 等待放入试管架
private void waitForTubeRackPutIn( Boolean requestEmptyTubeRack ) {
if ( requestEmptyTubeRack ) {
this.manager.sendMessageToTransBot("EmptyTubeRackPutIn", Map.of("batchNo", this.taskModel.batchNo));
private void waitForTubeRackPutIn() {
this.updateTaskStatus("TubeRackPutInWait", "等待放入试管架");
// 发送放入试管架消息
Map<String,Object> message = Map.of("batchNo", this.taskModel.batchNo, "taskId", this.taskModel.outTaskId);
this.manager.sendMessageToTransBot("TubeRackPutIn", message);
// 等待试管架放入完成
synchronized ( this.tubeRackPutInWaitLock ) {
try {
this.tubeRackPutInWaitLock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
this.updateTaskStatus("TubeRackPutInWaitDone", "试管架已放入");
}
// 等待放入试管架
private void waitForEmptyTubeRackPutIn() {
this.updateTaskStatus("TubeRackPutInWait", "等待放入空试管架");
// 发送放入试管架消息
Map<String,Object> message = Map.of("batchNo", this.taskModel.batchNo, "taskId", this.taskModel.outTaskId);
if ( "auto".equals(this.taskModel.mode) ) {
this.manager.sendMessageToTransBot("EmptyTubeRackPutIn", message);
} else {
this.manager.sendMessageToTransBot("TubeRackPutIn", Map.of("batchNo", this.taskModel.batchNo));
UfMdbNotification.action("EmptyTubeRackPutIn", message);
}
this.updateTaskStatus("TubeRackPutInWait", "等待放入试管架");
// 等待试管架放入完成
synchronized ( this.tubeRackPutInWaitLock ) {
try {
this.tubeRackPutInWaitLock.wait();
@ -341,8 +385,15 @@ public class DigestionTaskThread extends Thread {
// 等待取出试管架
private void waitForTubeRackTakeOut() {
this.manager.sendMessageToTransBot("TubeRackTakeOut", Map.of("batchNo", this.taskModel.batchNo));
this.updateTaskStatus("TubeRackTakeOutWait", "等待取出试管架");
Map<String,Object> message = Map.of("batchNo", this.taskModel.batchNo, "taskId", this.taskModel.outTaskId);
if ( "auto".equals(this.taskModel.mode) ) {
this.manager.sendMessageToTransBot("TubeRackTakeOut", message);
} else {
UfMdbNotification.action("TubeRackTakeOut", message);
}
synchronized ( this.tubeRackTakeOutWaitLock ) {
try {
this.tubeRackTakeOutWaitLock.wait();
@ -356,6 +407,9 @@ public class DigestionTaskThread extends Thread {
// 拍照检查试管
private void takeShotAndCheckErrorTubes() {
this.updateTaskStatus("TubeCheck", "拍照检查试管,等待确认异常试管");
Map<String,Object> message = Map.of("batchNo", this.taskModel.batchNo, "taskId", this.taskModel.outTaskId);
UfMdbNotification.action("TubeCheck", message);
this.errorTubeIndexes.clear();
synchronized ( this.errorTubeIndexes ) {
try {
@ -370,6 +424,9 @@ public class DigestionTaskThread extends Thread {
// 拍照检查试管
private void takeShotAndCheckFinishedTubes() {
this.updateTaskStatus("ErrorTubeCheck", "拍照检查异常试管,等待确认完成试管");
Map<String,Object> message = Map.of("batchNo", this.taskModel.batchNo, "taskId", this.taskModel.outTaskId);
UfMdbNotification.action("ErrorTubeCheck", message);
this.finishedErrorTubeIndexes.clear();
synchronized ( this.finishedErrorTubeIndexes ) {
try {

15
src/main/java/com/iflytop/digester/controller/CameraController.java

@ -0,0 +1,15 @@
package com.iflytop.digester.controller;
import com.iflytop.digester.underframework.controller.UfApiControllerBase;
import com.iflytop.digester.underframework.controller.UfApiResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;
@Controller
public class CameraController extends UfApiControllerBase {
@ResponseBody
@PostMapping("/api/camera/take-shot")
public UfApiResponse takeShot() {
return this.success(Map.of("data", "https://avatars.githubusercontent.com/u/53512912?v=4"));
}
}

9
src/main/java/com/iflytop/digester/controller/DigestionTaskController.java

@ -7,6 +7,7 @@ import com.iflytop.digester.underframework.util.UfJsonHelper;
import com.iflytop.digester.underframework.controller.UfApiControllerBase;
import com.iflytop.digester.underframework.controller.UfApiResponse;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -20,11 +21,13 @@ public class DigestionTaskController extends UfApiControllerBase {
@ResponseBody
@PostMapping("/api/digestion-task/start")
public UfApiResponse start(@RequestBody Map<String,Object> params) {
public UfApiResponse start(HttpServletRequest request, @RequestBody Map<String,Object> params) {
String taskId = (String)params.get("taskId");
String name = (String)params.get("name");
String batchNo = (String)params.get("batchNo");
List<Map<String,Object>> tubes = (List<Map<String,Object>>)params.get("tubes");
String mode = (String)params.get("mode");
Integer slotIndex = (Integer)params.get("slotIndex");
var digestion = UfActiveRecord.findOne(MdbDigestionSolution.class, Map.of("name", name));
if ( null == digestion ) {
@ -39,7 +42,9 @@ public class DigestionTaskController extends UfApiControllerBase {
task.status = "pending";
task.message = "等待中";
task.startedAt = (int)(System.currentTimeMillis() / 1000);
task.startedBy = 0;
task.startedBy = this.getUserFromRequest(request).id;
task.mode = mode;
task.heatingSlotIndex = slotIndex;
task.save();
this.taskManager.startTask(task);

4
src/main/java/com/iflytop/digester/controller/LiquidController.java

@ -26,8 +26,8 @@ public class LiquidController extends UfApiControllerBase {
Integer bucketIndex = (Integer)params.get("index");
String liquidType = (String)params.get("type");
var bucket = this.device.liquidAddition.getLiquidByIndex(bucketIndex);
bucket.type = liquidType;
bucket.volume = bucket.totalVolume;
bucket.setType(liquidType);
bucket.setVolume(bucket.totalVolume);
return this.success();
}
}

5
src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java

@ -22,6 +22,11 @@ public class HeatingTurntableInstance {
return slots;
}
// 根据索引获取槽位
public HeatingTurntableSlot getSlotByIndex(Integer index) {
return slots.get(index);
}
public HeatingTurntableSlot getSlotByLiquidPlateTubeRack() {
for (HeatingTurntableSlot slot : slots) {
if (null != slot.tubeRackNo && slot.tubeRackLocation.equals("liquid-plate")) {

15
src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionLiquid.java

@ -1,4 +1,7 @@
package com.iflytop.digester.deviceinstance;
import com.iflytop.digester.underframework.dao.model.UfMdbRuntimeVariable;
public class LiquidAdditionLiquid {
// bucket index
public Integer bucketIndex;
@ -8,4 +11,16 @@ public class LiquidAdditionLiquid {
public Integer volume;
// total volume
public Integer totalVolume;
// set type
public void setType( String type ) {
this.type = type;
UfMdbRuntimeVariable.setString(String.format("LiquidBucketType.%d", this.bucketIndex), type);
}
// set volume
public void setVolume( Integer volume ) {
this.volume = volume;
UfMdbRuntimeVariable.setInteger(String.format("LiquidBucketVolume.%d", this.bucketIndex), volume);
}
}

16
src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java

@ -3,6 +3,8 @@ import com.iflytop.digester.underframework.UfCmdSnippetExecutor;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class TransferRobotArmInstance {
// 等待锁队列
@ -16,7 +18,12 @@ public class TransferRobotArmInstance {
// 执行从异常槽位取出试管
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlotStart");
for (Integer tubeIndex : tubeIndexes) {
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlot." + tubeIndex);
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlot", Map.of(
"MotorLiquidPlatePos", 100,
"MotorArmLeftRightSrcPos", 100,
"MotorArmLeftRightDstPos", 100,
"MotorHeatingTurntablePos", 100
));
}
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlotEnd");
@ -31,7 +38,12 @@ public class TransferRobotArmInstance {
// 执行移动试管到异常槽位
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlotStart");
for (Integer tubeIndex : tubeIndexes) {
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlot." + tubeIndex);
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlot", Map.of(
"MotorLiquidPlatePos", 100,
"MotorArmLeftRightSrcPos", 100,
"MotorArmLeftRightDstPos", 100,
"MotorHeatingTurntablePos", 100
));
}
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlotEnd");

5
src/main/java/com/iflytop/digester/model/MdbDigestionTask.java

@ -30,7 +30,7 @@ public class MdbDigestionTask extends UfActiveRecord {
public Integer startedAt;
@UfActiveRecordField
public Integer startedBy;
public String startedBy;
@UfActiveRecordField
public Integer finishedAt = 0;
@ -38,6 +38,9 @@ public class MdbDigestionTask extends UfActiveRecord {
@UfActiveRecordField
public Integer heatingSlotIndex = -1;
@UfActiveRecordField
public String mode;
// get table name
public static String getTableName() {
return "app_digestion_tasks";

15
src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbNotification.java

@ -1,6 +1,10 @@
package com.iflytop.digester.underframework.dao.model;
import com.iflytop.digester.underframework.dao.record.UfActiveRecord;
import com.iflytop.digester.underframework.dao.record.UfActiveRecordField;
import com.iflytop.digester.underframework.util.UfJsonHelper;
import java.util.Map;
public class UfMdbNotification extends UfActiveRecord {
@UfActiveRecordField
public String type;
@ -59,4 +63,15 @@ public class UfMdbNotification extends UfActiveRecord {
notification.status = "new";
notification.save();
}
// notify action
public static void action( String action, Map<String,Object> params) {
var data = Map.of("action", action, "params", params);
var dataJson = UfJsonHelper.objectToJson(data);
var notification = new UfMdbNotification();
notification.type = "action";
notification.data = dataJson;
notification.status = "new";
notification.save();
}
}

10
src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbRuntimeVariable.java

@ -42,19 +42,19 @@ public class UfMdbRuntimeVariable extends UfActiveRecord {
}
// set string
public static void setString(String value, String name, Object ... args ) {
var variable = UfMdbRuntimeVariable.getVariable(name, args);
public static void setString(String name, String value) {
var variable = UfActiveRecord.findOne(UfMdbRuntimeVariable.class, Map.of("key", name));
if ( null == variable ) {
variable = new UfMdbRuntimeVariable();
variable.key = UfMdbRuntimeVariable.buildKey(name, args);
variable.key = name;
}
variable.value = value;
variable.save();
}
// set integer
public static void setInteger(Integer value, String name, Object ... args ) {
UfMdbRuntimeVariable.setString(value.toString(), name, args);
public static void setInteger(String name, Integer value) {
UfMdbRuntimeVariable.setString(name, value.toString());
}
// remove

Loading…
Cancel
Save