sige 1 year ago
parent
commit
5a7e098caf
  1. BIN
      app.db
  2. 19
      src/main/java/com/iflytop/digester/DigestionTaskThread.java
  3. 13
      src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java
  4. 20
      src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableSlot.java
  5. 38
      src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java
  6. 31
      src/main/java/com/iflytop/digester/model/MdbDigestionTaskLog.java
  7. 31
      src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java
  8. 4
      src/main/java/com/iflytop/digester/underframework/command/UfCmdDelay.java
  9. 6
      src/main/java/com/iflytop/digester/underframework/command/UfCommand.java
  10. 6
      src/main/java/com/iflytop/digester/underframework/connection/UfModbusRTUOverTCP.java
  11. 6
      src/main/java/com/iflytop/digester/underframework/resourcecontrol/systemcommand/TsCommand.java
  12. 10
      src/main/resources/application-dev.yml
  13. 2
      web

BIN
app.db

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

@ -162,8 +162,25 @@ public class DigestionTaskThread extends Thread {
device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index);
// 拍照检查异常试管
this.takeShotAndCheckErrorTubes();
// 申请异常处理位
var errorSlot = device.heatingTurntable.getErrorSlot();
var emptyTubeIndexes = errorSlot.getEmptyTubeIndexes(this.errorTubeIndexes.size());
var errorTubeIndexes = this.errorTubeIndexes;
if ( emptyTubeIndexes.size() < this.errorTubeIndexes.size() ) {
errorTubeIndexes = this.errorTubeIndexes.subList(0, emptyTubeIndexes.size());
}
// 将异常试管放入异常处理区域
device.transferArm.moveTubesToErrorSlot(this.errorTubeIndexes);
device.transferArm.moveTubesToErrorSlot(errorTubeIndexes, emptyTubeIndexes);
// 更新试管状态
for ( var tubeIndex : errorTubeIndexes ) {
var tube = this.heatingSlot.tubes.get(tubeIndex);
errorSlot.tubes.set(emptyTubeIndexes.get(0), tube);
this.heatingSlot.tubes.set(tubeIndex, null);
}
// 将正常试管放入加热转盘
device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index);
}

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

@ -1,12 +1,15 @@
package com.iflytop.digester.deviceinstance;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;
@Component
public class HeatingTurntableInstance {
@Value("${app.errorSlotIndex}")
private Integer errorSlotIndex;
// 槽位列表
private final List<HeatingTurntableSlot> slots = new ArrayList<>();
@ -15,6 +18,9 @@ public class HeatingTurntableInstance {
for (int i = 0; i < 5; i++) {
HeatingTurntableSlot slot = new HeatingTurntableSlot();
slot.index = i;
if (i == errorSlotIndex) {
slot.isErrorSlot = true;
}
slots.add(slot);
}
}
@ -24,6 +30,11 @@ public class HeatingTurntableInstance {
return slots;
}
// 获取异常槽位
public HeatingTurntableSlot getErrorSlot() {
return slots.get(errorSlotIndex);
}
// 根据索引获取槽位
public HeatingTurntableSlot getSlotByIndex(Integer index) {
return slots.get(index);

20
src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableSlot.java

@ -23,6 +23,8 @@ public class HeatingTurntableSlot {
public List<HeatingTurntableSlotTube> tubes = new ArrayList<>();
// 试管架位置
public String tubeRackLocation = null; // heating-turntable:加热转盘 liquid-plate :加液盘
// 是否异常槽位
public Boolean isErrorSlot = false;
// Constructor
public HeatingTurntableSlot() {
@ -43,6 +45,17 @@ public class HeatingTurntableSlot {
}
}
// 获取空试管索引列表
public List<Integer> getEmptyTubeIndexes( Integer limit ) {
List<Integer> indexes = new ArrayList<>();
for (int i = 0; i < tubes.size(); i++) {
if ( null == tubes.get(i) && indexes.size() < limit ) {
indexes.add(i);
}
}
return indexes;
}
// 获取非空试管索引列表
public List<Integer> getExistTubeIndexes() {
List<Integer> indexes = new ArrayList<>();
@ -60,8 +73,11 @@ public class HeatingTurntableSlot {
this.heatingDuration = duration;
this.heatingStatus = "on";
var snippetName = "HeatingTurntableSlotHeating.Start." + this.index;
Map<String,Object> snippetParams = Map.of("temperature", temperature, "duration", duration);
var snippetName = "HeatingTurntableSlotHeating." + this.index;
Map<String,Object> snippetParams = Map.of(
"temperature", temperature,
"duration", duration * 60 * 1000
);
UfCmdSnippetExecutor.execute(snippetName, snippetParams);
// 加热完成

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

@ -1,7 +1,9 @@
package com.iflytop.digester.deviceinstance;
import com.iflytop.digester.underframework.UfCmdSnippetExecutor;
import com.iflytop.digester.underframework.dao.model.UfMdbOption;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -16,37 +18,33 @@ public class TransferRobotArmInstance {
this.lockArm(lock);
// 执行从异常槽位取出试管
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlotStart");
for (Integer tubeIndex : tubeIndexes) {
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlot", Map.of(
"MotorLiquidPlatePos", 100,
"MotorArmLeftRightSrcPos", 100,
"MotorArmLeftRightDstPos", 100,
"MotorHeatingTurntablePos", 100
));
var snippetKey = "TubeTakeOutFromErrorSlot";
var snippetParams = new HashMap<String, Object>();
snippetParams.put("LiquidPlatePos", UfMdbOption.getInteger("LiquidPlateTube." + tubeIndex, 0));
snippetParams.put("TransLrSrcPos", UfMdbOption.getInteger("HeatPlateErrorSlotTube." + tubeIndex, 0));
snippetParams.put("HeatingPlatePos", UfMdbOption.getInteger("TransLrMotorLiquidPlateTube." + tubeIndex, 0));
snippetParams.put("TransLrDestPos", UfMdbOption.getInteger("TransLrMotorHeatingPlateTube." + tubeIndex, 0));
UfCmdSnippetExecutor.execute(snippetKey, snippetParams);
}
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlotEnd");
this.unlockArm(lock);
}
// 移动试管到异常槽位
public void moveTubesToErrorSlot(List<Integer> tubeIndexes) {
public void moveTubesToErrorSlot(List<Integer> srcIndexes, List<Integer> destIndexes) {
var lock = new Object();
this.lockArm(lock);
// 执行移动试管到异常槽位
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlotStart");
for (Integer tubeIndex : tubeIndexes) {
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlot", Map.of(
"MotorLiquidPlatePos", 100,
"MotorArmLeftRightSrcPos", 100,
"MotorArmLeftRightDstPos", 100,
"MotorHeatingTurntablePos", 100
));
for (Integer tubeIndex : srcIndexes) {
String snippetKey = "TubeMoveToErrorSlot";
Map<String,Object> snippetParams = new HashMap<>();
snippetParams.put("LiquidPlatePos", UfMdbOption.getInteger("LiquidPlateTube." + tubeIndex, 0));
snippetParams.put("TransLrSrcPos", UfMdbOption.getInteger("TransLrMotorLiquidPlateTube." + tubeIndex, 0));
snippetParams.put("HeatingPlatePos", UfMdbOption.getInteger("HeatPlateErrorSlotTube." + tubeIndex, 0));
snippetParams.put("TransLrDestPos", UfMdbOption.getInteger("TransLrMotorHeatingPlateTube." + tubeIndex, 0));
UfCmdSnippetExecutor.execute(snippetKey, snippetParams);
}
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlotEnd");
this.unlockArm(lock);
}

31
src/main/java/com/iflytop/digester/model/MdbDigestionTaskLog.java

@ -0,0 +1,31 @@
package com.iflytop.digester.model;
import com.iflytop.digester.underframework.dao.record.UfActiveRecord;
import com.iflytop.digester.underframework.dao.record.UfActiveRecordField;
public class MdbDigestionTaskLog extends UfActiveRecord {
@UfActiveRecordField
public String taskId;
@UfActiveRecordField
public String action;
@UfActiveRecordField
public String content;
@UfActiveRecordField
public Long timestamp;
// get table name
public static String getTableName() {
return "app_digestion_task_logs";
}
// log
public static void log(String taskId, String action, String content) {
var log = new MdbDigestionTaskLog();
log.taskId = taskId;
log.action = action;
log.content = content;
log.timestamp = System.currentTimeMillis();
log.save();
}
}

31
src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java

@ -2,6 +2,8 @@ package com.iflytop.digester.underframework;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iflytop.digester.underframework.command.UfCommand;
import com.iflytop.digester.underframework.util.UfClassHelper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
@ -14,6 +16,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.StringWriter;
public class UfCmdSnippetExecutor {
@ -79,15 +82,36 @@ public class UfCmdSnippetExecutor {
public void executeStep(String cmdId, String cmdParams) {
var cmd = UfActiveRecord.findOne(UfMdbActuatorCmd.class, cmdId);
if (null == cmd) {
this.executeBuildInCmd(cmdId, cmdParams);
return;
}
cmd.parameters = this.compileParameterString(cmdParams);
UfActuatorCmdExecutor.execute(cmd);
}
// execute build-in command
private void executeBuildInCmd( String cmdId, String cmdParams ) {
var buildInCmdClassName = this.getClass().getPackageName() + ".command.UfCmd" + cmdId;
UfCommand buildInCmd = null;
try {
buildInCmd = (UfCommand)UfClassHelper.newInstance(buildInCmdClassName);
} catch ( Exception e ) {
throw new RuntimeException("无效的指令ID : " + cmdId);
}
// 编译参数为模板
cmdParams = this.compileParameterString(cmdParams);
List<String> args = List.of(cmdParams.split(","));
buildInCmd.execute(args);
}
// 编译参数字符串
private String compileParameterString( String paramText ) {
freemarker.template.Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
cfg.setNumberFormat("0");
Template template = null;
try {
template = new Template("", cmdParams, cfg);
template = new Template("", paramText, cfg);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -97,7 +121,6 @@ public class UfCmdSnippetExecutor {
} catch (TemplateException | IOException e) {
throw new RuntimeException(e);
}
cmd.parameters = paramStrWriter.toString();
UfActuatorCmdExecutor.execute(cmd);
return paramStrWriter.toString();
}
}

4
src/main/java/com/iflytop/digester/underframework/resourcecontrol/systemcommand/TsCmdDelay.java → src/main/java/com/iflytop/digester/underframework/command/UfCmdDelay.java

@ -1,6 +1,6 @@
package com.iflytop.digester.underframework.resourcecontrol.systemcommand;
package com.iflytop.digester.underframework.command;
import java.util.List;
public class TsCmdDelay implements TsCommand {
public class UfCmdDelay implements UfCommand {
@Override
public void execute( List<String> args ) {
// get delay time

6
src/main/java/com/iflytop/digester/underframework/command/UfCommand.java

@ -0,0 +1,6 @@
package com.iflytop.digester.underframework.command;
import java.util.List;
public interface UfCommand {
// execute
void execute( List<String> args );
}

6
src/main/java/com/iflytop/digester/underframework/connection/UfModbusRTUOverTCP.java

@ -38,14 +38,14 @@ public class UfModbusRTUOverTCP extends UfConnectionBase {
synchronized public String execute(UfMdbActuatorCmd command) {
if ( "03".equals(command.cmdId) ) {
Integer slaveId = Integer.parseInt(command.cmdFlags);
Integer address = Integer.parseInt(command.parameters);
Integer address = Integer.parseInt(command.parameters.trim());
Integer value = this.readHoldingRegister(slaveId, address);
return value.toString();
} else if ( "06".equals(command.cmdId) ) {
Integer slaveId = Integer.parseInt(command.cmdFlags);
String[] params = command.parameters.split(",");
Integer address = Integer.parseInt(params[0]);
Integer value = Integer.parseInt(params[1]);
Integer address = Integer.parseInt(params[0].trim());
Integer value = Integer.parseInt(params[1].trim());
this.writeHoldingRegister(slaveId, address, value);
return "";
} else {

6
src/main/java/com/iflytop/digester/underframework/resourcecontrol/systemcommand/TsCommand.java

@ -1,6 +0,0 @@
package com.iflytop.digester.underframework.resourcecontrol.systemcommand;
import java.util.List;
public interface TsCommand {
// execute
void execute( List<String> args );
}

10
src/main/resources/application-dev.yml

@ -13,16 +13,16 @@ device:
connections:
- name : zcancmder
key : zcancmder
enable : false
enable : true
type : ZcancmderWebsocket
# uri: ws://192.168.8.10:19005
uri : ws://127.0.0.1:19005
uri: ws://192.168.8.10:19005
# uri : ws://127.0.0.1:19005
- name : modbus
key : modbus
enable : true
type : ModbusRTUOverTCP
host: 127.0.0.1
port: 502
host: 192.168.8.10
port: 20000
mqtt-broker:
uri: tcp://broker.emqx.io:1883

2
web

@ -1 +1 @@
Subproject commit 1513f7b9d26f452c6ded8c1d7fe43c047fab162a
Subproject commit 464111807ce66ce1d0f0652455cc17689d12ab7e
Loading…
Cancel
Save