sige 2 years ago
parent
commit
7302eabd9b
  1. 5
      src/pom.xml
  2. 6
      src/src/main/java/com/my/graphiteDigesterBg/MyApplicationRunner.java
  3. 2
      src/src/main/java/com/my/graphiteDigesterBg/MyDevice.java
  4. 7
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuator.java
  5. 88
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuatorBase.java
  6. 1
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiApplicationRunner.java
  7. 7
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommand.java
  8. 2
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommandRequest.java
  9. 4
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommandResponse.java
  10. 143
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDevice.java
  11. 11
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceRegister.java
  12. 52
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceRegisterManager.java
  13. 70
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceResourceManager.java
  14. 3
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiResourceManager.java
  15. 4
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiResourceManagerBase.java
  16. 19
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java
  17. 4
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskManager.java
  18. 2
      src/src/main/java/com/my/graphiteDigesterBg/diframe/ResourceManager.java
  19. 10
      src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActMotor.java
  20. 5
      src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActServo.java
  21. 12
      src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConSerialPort.java
  22. 26
      src/src/main/java/com/my/graphiteDigesterBg/diframe/util/DiByteBuffer.java
  23. 6
      src/src/main/java/com/my/graphiteDigesterBg/diframe/util/DiClassHelper.java
  24. 24
      src/src/main/java/com/my/graphiteDigesterBg/resource/ResHeatingTubeRackSlot.java
  25. 24
      src/src/main/java/com/my/graphiteDigesterBg/resource/ResHeatingTubeRackSlotManager.java
  26. 3
      src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java
  27. 24
      src/src/main/java/com/my/graphiteDigesterBg/task/TaskSampleAdd.java
  28. 24
      src/src/main/java/com/my/graphiteDigesterBg/task/TaskStartReset.java
  29. 18
      src/src/main/resources/application.yml
  30. 18
      src/src/main/resources/device.yml
  31. 106
      src/web/package-lock.json
  32. 3
      src/web/package.json
  33. 28
      src/web/src/pages/main/contents/Operation.vue

5
src/pom.xml

@ -33,6 +33,11 @@
<artifactId>jSerialComm</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
</dependencies>
<build>

6
src/src/main/java/com/my/graphiteDigesterBg/MyApplicationRunner.java

@ -5,7 +5,9 @@ import com.my.graphiteDigesterBg.diframe.DiDeviceIO;
import com.my.graphiteDigesterBg.diframe.DiDeviceIOManager;
import com.my.graphiteDigesterBg.diframe.actuator.DiActMotor;
import com.my.graphiteDigesterBg.diframe.actuator.DiActPeristalticPump;
import com.my.graphiteDigesterBg.diframe.actuator.DiActServo;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
@ -18,6 +20,8 @@ public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
this.device.getRegisters().setup();
this.setupIO();
this.setupActuators();
}
@ -53,7 +57,7 @@ public class MyApplicationRunner implements ApplicationRunner {
actuators.register(MyDevice.ACT_HEAT_PLATE_MOTOR, new DiActMotor(){{
mid = 11;
}});
actuators.register(MyDevice.ACT_HEAT_SLOT_01_COVER_SERVO, new DiActMotor(){{
actuators.register(MyDevice.ACT_HEAT_SLOT_01_COVER_SERVO, new DiActServo(){{
mid = 12;
}});
actuators.register(MyDevice.ACT_TRANSFER_UD_MOTOR, new DiActMotor(){{

2
src/src/main/java/com/my/graphiteDigesterBg/MyDevice.java

@ -15,4 +15,6 @@ public class MyDevice extends DiDevice {
public static String IO_HEAT_SLOT_01_HEATER_03 = "heatSlot01Heater03";
public static String IO_HEAT_SLOT_01_HEATER_04 = "heatSlot01Heater04";
public static String IO_AIR_COMPRESSOR = "airCompressor";
public static String RES_HEATING_TUBE_RACK_SLOT = "HeatingTubeRackSlot";
}

7
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuator.java

@ -1,5 +1,12 @@
package com.my.graphiteDigesterBg.diframe;
public interface DiActuator {
static Integer MODULE_STATUS_IDLE = 0;
static Integer MODULE_STATUS_BUSY = 1;
static Integer MODULE_STATUS_ERROR = 2;
// set device
void setDevice( DiDevice device );
// get mid
Integer getMid();
}

88
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuatorBase.java

@ -1,8 +1,5 @@
package com.my.graphiteDigesterBg.diframe;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
abstract public class DiActuatorBase implements DiActuator {
// message index
private static short messageIndex = 0;
@ -21,71 +18,36 @@ abstract public class DiActuatorBase implements DiActuator {
this.call(DiCommand.MODULE_ENABLE, enable ? 1 : 0);
}
// execute device command
protected DiCommandResponse call( DiCommand cmd, Object... args ) {
DiCommandRequest request = null;
String cmdMode = this.device.getEnv().getProperty("device.connection.mode");
if ("text".equals(cmdMode)) {
request = this.buildCommandRequestForTextMode(cmd, args);
} else if ("binary".equals(cmdMode) ) {
request = this.buildCommandRequestForBinaryMode(cmd, args);
} else {
throw new RuntimeException("Unknown command mode: " + cmdMode);
}
this.device.getConnection().call(request);
return new DiCommandResponse(request.response);
// active config
public void activeConfig() {
this.call(DiCommand.MODULE_ACTIVE_CFG);
}
// build command buffer for text mode
private DiCommandRequest buildCommandRequestForTextMode(DiCommand cmd, Object... args) {
List<String> parts = new ArrayList<>();
parts.add(cmd.getName());
parts.add(this.mid.toString());
for ( Object arg : args ) {
parts.add(arg.toString());
}
String command = String.join(" ", parts);
DiCommandRequest request = new DiCommandRequest();
request.parameter = ByteBuffer.wrap(command.getBytes());
return request;
// get mid
public Integer getMid() {
return this.mid;
}
// build command buffer for binary mode
private DiCommandRequest buildCommandRequestForBinaryMode(DiCommand cmd, Object... args) {
int length = 2/*PacketIndex*/ + 2/*MainCmdId*/ + 1/*SubCmdId*/ + 1/*CmdType*/ + 2/*ModuleId*/;
for ( Object param : args ) {
if ( param instanceof Integer ) {
length += 4;
} else {
throw new RuntimeException("param type error");
// wait for finish
protected void waitForFinish() {
Integer status = DiActuator.MODULE_STATUS_BUSY;
do {
try {
DiCommandResponse response = this.call(DiCommand.MODULE_GET_STATUS);
status = response.readInteger(0);
} catch ( RuntimeException e ) {
continue;
}
}
int cmdId = cmd.getCmdId();
int subCmdId = cmdId & 0xFF;
int mainCmdId = (cmdId >> 8) & 0xFFFF;
int moduleId = this.mid;
DiCommandRequest request = new DiCommandRequest();
request.id = DiActuatorBase.messageIndex;
request.parameter = ByteBuffer.allocate(length);
request.parameter.order(ByteOrder.LITTLE_ENDIAN);
request.parameter.putShort(DiActuatorBase.messageIndex);
request.parameter.putShort((short)mainCmdId); // main cmd id
request.parameter.put((byte)subCmdId); // sub cmd id
request.parameter.put((byte)0); // directive type
request.parameter.putShort((short)moduleId); // mid
for ( Object param : args ) {
if ( param instanceof Integer ) {
request.parameter.putInt((Integer)param);
try {
Thread.sleep(100);
} catch ( InterruptedException e ) {
continue ;
}
}
DiActuatorBase.messageIndex ++;
if ( DiActuatorBase.messageIndex > 30000 ) {
DiActuatorBase.messageIndex = 0;
}
} while (!Objects.equals(status, DiActuator.MODULE_STATUS_IDLE));
}
return request;
// execute device command
protected DiCommandResponse call( DiCommand cmd, Object... args ) {
return this.device.call(cmd, this.mid, args);
}
}

1
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiApplicationRunner.java

@ -13,5 +13,6 @@ public class DiApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
this.device.getTaskManager().scanTaskClasses("com.my.graphiteDigesterBg.task");
this.device.getResource().scanResourceManagerClasses("com.my.graphiteDigesterBg.resource");
}
}

7
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommand.java

@ -1,7 +1,12 @@
package com.my.graphiteDigesterBg.diframe;
public enum DiCommand {
MODULE_ACTIVE_CFG("module_active_cfg", 0x0110),
MODULE_GET_STATUS("module_get_status", 0x0104),
MODULE_SET_REG("module_set_reg", 0x0105),
MODULE_GET_REG("module_get_reg", 0x0106),
MODULE_ENABLE("module_enable", 0x0114),
MOTOR_EASY_MOVE_BY("motor_easy_move_by", 0x0212);
MOTOR_EASY_MOVE_BY("motor_easy_move_by", 0x0212),
MOTOR_EASY_MOVE_TO_ZERO("motor_easy_move_to_zero", 0x0214);
// command name
private final String name;

2
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommandRequest.java

@ -5,6 +5,8 @@ public class DiCommandRequest {
public short id;
// parameter
public ByteBuffer parameter;
// parameter text
public String parameterText;
// response
public ByteBuffer response;
// error code

4
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommandResponse.java

@ -1,5 +1,6 @@
package com.my.graphiteDigesterBg.diframe;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class DiCommandResponse {
// response
private final ByteBuffer response;
@ -11,6 +12,7 @@ public class DiCommandResponse {
// read integer
public Integer readInteger( Integer index ) {
return this.response.getInt(index);
this.response.order(ByteOrder.LITTLE_ENDIAN);
return this.response.getInt(8 + index);
}
}

143
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDevice.java

@ -1,34 +1,76 @@
package com.my.graphiteDigesterBg.diframe;
import com.my.graphiteDigesterBg.diframe.connection.DiConSerialPort;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class DiDevice {
@Resource
private Environment env;
// config
private Map<String,Object> config;
// connection
private DiDeviceConnection connection;
// io manager
private DiDeviceIOManager io;
// register manager
private DiDeviceRegisterManager registers;
// actuator manager
private DiDeviceActuatorManager actuators;
// resource manager
private DiDeviceResourceManager resource;
// task manager
private DiTaskManager taskManager;
// message index
private short messageIndex = 0;
@PostConstruct
public void init() {
this.messageIndex = 0;
this.loadDeviceYml();
this.setupConnection();
this.io = new DiDeviceIOManager(this);
this.registers = new DiDeviceRegisterManager(this);
this.actuators = new DiDeviceActuatorManager(this);
this.resource = new DiDeviceResourceManager(this);
this.taskManager = new DiTaskManager(this);
}
// load device.yml
private void loadDeviceYml() {
InputStream input = null;
try {
ClassPathResource resource = new ClassPathResource("device.yml");
input = resource.getInputStream();
Yaml yaml = new Yaml();
this.config = yaml.loadAs(input, Map.class);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
// setup connection
private void setupConnection() {
String connectionClassName = this.env.getProperty("device.connection.class");
@ -79,4 +121,103 @@ public class DiDevice {
public Environment getEnv() {
return this.env;
}
// get resource manager
public DiDeviceResourceManager getResource() {
return this.resource;
}
// get register manager
public DiDeviceRegisterManager getRegisters() {
return this.registers;
}
// get config
public Map<String,Object> getConfig() {
return this.config;
}
// get config
public String getConfig( String path ) {
String[] parts = path.split("\\.");
Object config = this.config;
for ( int i=0; i<parts.length-1; i++ ) {
config = ((Map<String,Object>)config).get(parts[i]);
}
String lastKey = parts[parts.length-1];
return (String)((Map<String,Object>)config).get(lastKey);
}
// execute device command
protected DiCommandResponse call( DiCommand cmd, Integer mid, Object... args ) {
DiCommandRequest request = null;
String cmdMode = this.getConfig("connection.mode");
if ("text".equals(cmdMode)) {
request = this.buildCommandRequestForTextMode(cmd, mid, args);
} else if ("binary".equals(cmdMode) ) {
request = this.buildCommandRequestForBinaryMode(cmd, mid, args);
} else {
throw new RuntimeException("Unknown command mode: " + cmdMode);
}
request.parameterText = this.buildCommandRequestParameterText(cmd, mid, args);
this.getConnection().call(request);
return new DiCommandResponse(request.response);
}
// build command request parameter text
private String buildCommandRequestParameterText(DiCommand cmd, Integer mid, Object... args) {
List<String> parts = new ArrayList<>();
parts.add(cmd.getName());
parts.add(mid.toString());
for ( Object arg : args ) {
parts.add(arg.toString());
}
return String.join(" ", parts);
}
// build command buffer for text mode
private DiCommandRequest buildCommandRequestForTextMode(DiCommand cmd, Integer mid, Object... args) {
String command = this.buildCommandRequestParameterText(cmd, mid, args);
DiCommandRequest request = new DiCommandRequest();
request.parameter = ByteBuffer.wrap(command.getBytes());
return request;
}
// build command buffer for binary mode
private DiCommandRequest buildCommandRequestForBinaryMode(DiCommand cmd, Integer mid, Object... args) {
int length = 2/*PacketIndex*/ + 2/*MainCmdId*/ + 1/*SubCmdId*/ + 1/*CmdType*/ + 2/*ModuleId*/;
for ( Object param : args ) {
if ( param instanceof Integer ) {
length += 4;
} else {
throw new RuntimeException("param type error");
}
}
int cmdId = cmd.getCmdId();
int subCmdId = cmdId & 0xFF;
int mainCmdId = (cmdId >> 8) & 0xFFFF;
int moduleId = mid;
DiCommandRequest request = new DiCommandRequest();
request.id = this.messageIndex;
request.parameter = ByteBuffer.allocate(length);
request.parameter.order(ByteOrder.LITTLE_ENDIAN);
request.parameter.putShort(this.messageIndex);
request.parameter.putShort((short)mainCmdId); // main cmd id
request.parameter.put((byte)subCmdId); // sub cmd id
request.parameter.put((byte)0); // directive type
request.parameter.putShort((short)moduleId); // mid
for ( Object param : args ) {
if ( param instanceof Integer ) {
request.parameter.putInt((Integer)param);
}
}
this.messageIndex ++;
if ( this.messageIndex > 30000 ) {
this.messageIndex = 0;
}
return request;
}
}

11
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceRegister.java

@ -1,2 +1,11 @@
package com.my.graphiteDigesterBg.diframe;public class DiDeviceRegister {
package com.my.graphiteDigesterBg.diframe;
public class DiDeviceRegister {
// key
public String key;
// module id
public Integer mid;
// index
public Integer index;
// default value
public Integer defaultValue;
}

52
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceRegisterManager.java

@ -1,2 +1,52 @@
package com.my.graphiteDigesterBg.diframe;public class DiDeviceRegisterManager {
package com.my.graphiteDigesterBg.diframe;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DiDeviceRegisterManager {
// device instance
private final DiDevice device;
// id => actuator
private final Map<String, DiDeviceRegister> registers;
// constructor
public DiDeviceRegisterManager(DiDevice device ) {
this.device = device;
this.registers = new HashMap<String, DiDeviceRegister>();
}
// setup
public void setup() {
Object config = this.device.getConfig().get("registers");
if ( config == null ) {
return;
}
if ( !(config instanceof List) ) {
throw new RuntimeException("Invalid registers config");
}
List<Map<String,Object>> registers = (List<Map<String, Object>>) config;
for ( Map<String,Object> register : registers ) {
DiDeviceRegister reg = new DiDeviceRegister();
reg.key = (String)register.get("key");
reg.mid = (Integer)register.get("mid");
reg.index = (Integer)register.get("index");
reg.defaultValue = (Integer)register.get("defaultValue");
this.registers.put(reg.key, reg);
}
}
// reset register to default value
public void resetAllByModuleId( Integer mid ) {
for ( DiDeviceRegister register : this.registers.values() ) {
if ( register.mid.equals(mid) ) {
this.device.call(DiCommand.MODULE_SET_REG, register.mid, register.index, register.defaultValue);
}
}
}
// get actuator
public void get( String id ) {
this.registers.get(id);
}
}

70
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceResourceManager.java

@ -1,4 +1,72 @@
package com.my.graphiteDigesterBg.diframe;
public class DiResourceManager {
import com.my.graphiteDigesterBg.diframe.util.DiClassHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DiDeviceResourceManager {
// logger
public static final Logger LOG = LoggerFactory.getLogger(DiTaskManager.class);
// device
private DiDevice device;
// resource managers
private final Map<String, DiResourceManager> managersNameMap;
// resource managers
private final Map<Class<?>, DiResourceManager> managersClassMap;
// constructor
public DiDeviceResourceManager(DiDevice device) {
this.device = device;
this.managersNameMap = new HashMap<>();
this.managersClassMap = new HashMap<>();
}
// get scan task classes
public void scanResourceManagerClasses( String packageName ) {
List<Class<?>> resManClasses = DiClassHelper.getAllClassesInPackage(packageName);
for ( Class<?> resManClass : resManClasses ) {
if ( DiResourceManagerBase.class.isAssignableFrom(resManClass) ) {
ResourceManager manAnnotation = resManClass.getAnnotation(ResourceManager.class);
if ( manAnnotation == null ) {
continue;
}
LOG.info("(Resource) {} => {}", manAnnotation.name(), resManClass.getName());
DiResourceManager man = this.getDiResourceManagerInstance(resManClass);
this.managersNameMap.put(manAnnotation.name(), man);
this.managersClassMap.put(resManClass, man);
}
}
}
// get instance of resource manager
private DiResourceManager getDiResourceManagerInstance(Class<?> resManClass) {
Constructor<?> manConstructor = null;
try {
manConstructor = resManClass.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
DiResourceManager man = null;
try {
man = (DiResourceManager) manConstructor.newInstance();
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
return man;
}
// get manager
public DiResourceManager getManager( String resourceType ) {
return this.managersNameMap.get(resourceType);
}
// get manager
public <T extends DiResourceManagerBase> T getManager( Class<T> clazz ) {
return (T)this.managersClassMap.get(clazz);
}
}

3
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiResourceManager.java

@ -1,2 +1,3 @@
package com.my.graphiteDigesterBg.diframe;public interface DiResourceManager {
package com.my.graphiteDigesterBg.diframe;
public interface DiResourceManager {
}

4
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiResourceManagerBase.java

@ -1,2 +1,4 @@
package com.my.graphiteDigesterBg.diframe;public class DiResourceManagerBase {
package com.my.graphiteDigesterBg.diframe;
abstract public class DiResourceManagerBase implements DiResourceManager {
}

19
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java

@ -1,4 +1,7 @@
package com.my.graphiteDigesterBg.diframe;
import com.my.graphiteDigesterBg.MyDevice;
import com.my.graphiteDigesterBg.diframe.actuator.DiActMotor;
import java.util.ArrayList;
import java.util.List;
abstract public class DiTaskBase implements DiTask {
@ -58,4 +61,20 @@ abstract public class DiTaskBase implements DiTask {
public void run() {
this.status = TaskStatus.FINISHED;
}
// get manager
public <T extends DiResourceManagerBase> T getResourceManager( Class<T> clazz ) {
return this.getDevice().getResource().getManager(clazz);
}
// get actuator
public DiActuator getActuator( String actuatorKey ) {
return this.getDevice().getActuators().get(actuatorKey);
}
// get actuator
public <T extends DiActuator> T getActuator( String actuatorKey, Class<T> clazz ) {
DiActuator actuator = this.getDevice().getActuators().get(actuatorKey);
return clazz.cast(actuator);
}
}

4
src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskManager.java

@ -1,5 +1,5 @@
package com.my.graphiteDigesterBg.diframe;
import com.my.graphiteDigesterBg.diframe.util.ClassHelper;
import com.my.graphiteDigesterBg.diframe.util.DiClassHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
@ -42,7 +42,7 @@ public class DiTaskManager {
// get scan task classes
public void scanTaskClasses( String packageName ) {
List<Class<?>> taskClasses = ClassHelper.getAllClassesInPackage(packageName);
List<Class<?>> taskClasses = DiClassHelper.getAllClassesInPackage(packageName);
for ( Class<?> taskClass : taskClasses ) {
if ( DiTaskBase.class.isAssignableFrom(taskClass) ) {
Task task = taskClass.getAnnotation(Task.class);

2
src/src/main/java/com/my/graphiteDigesterBg/diframe/ResourceManager.java

@ -1,4 +1,4 @@
package com.my.graphiteDigesterBg.diframe.util;
package com.my.graphiteDigesterBg.diframe;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

10
src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActMotor.java

@ -1,11 +1,15 @@
package com.my.graphiteDigesterBg.diframe.actuator;
import com.my.graphiteDigesterBg.diframe.DiActuatorBase;
import com.my.graphiteDigesterBg.diframe.DiCommand;
public class DiActMotor extends DiActuatorBase {
// reset motor to zero position
public void reset() {
this.call(DiCommand.MOTOR_EASY_MOVE_TO_ZERO, -1);
this.waitForFinish();
}
public void moveTo( Integer pos ) {}
public void moveBy( Integer delta ) {}
public void rotate( Integer direction ) {}
public void stop() {}
public void reset() {}
}

5
src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActServo.java

@ -3,4 +3,9 @@ package com.my.graphiteDigesterBg.diframe.actuator;
import com.my.graphiteDigesterBg.diframe.DiActuatorBase;
public class DiActServo extends DiActuatorBase {
public void moveTo( Integer pos ) {}
public void moveBy( Integer delta ) {}
public void rotate( Integer direction ) {}
public void stop() {}
public void reset() {}
}

12
src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConSerialPort.java

@ -5,10 +5,12 @@ import com.fazecast.jSerialComm.SerialPortEvent;
import com.my.graphiteDigesterBg.diframe.DiCommandRequest;
import com.my.graphiteDigesterBg.diframe.DiDevice;
import com.my.graphiteDigesterBg.diframe.DiDeviceConnection;
import com.my.graphiteDigesterBg.diframe.util.DiByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
@ -110,15 +112,18 @@ public class DiConSerialPort implements DiDeviceConnection {
// handle on data timeout for binary mode
private void handleOnDataTimeoutForBinaryMode() {
byte messageType = this.receivedData.get(5);
if ( 0x01 == messageType ) {
if ( 0x01 == messageType ) { // ack message
this.handleOnDataTimeoutForBinaryModeAckMessage();
} else if ( 0x02 == messageType ) { // error message
throw new RuntimeException("error message received: " + DiByteBuffer.toHex(this.receivedData));
} else {
throw new RuntimeException("unknown message type");
throw new RuntimeException("unknown message type : " + messageType + " <= " + DiByteBuffer.toHex(this.receivedData));
}
}
// handle on data timeout for binary mode ack message
private void handleOnDataTimeoutForBinaryModeAckMessage() {
this.receivedData.order(ByteOrder.LITTLE_ENDIAN);
short messageId = this.receivedData.getShort(0);
DiCommandRequest request = null;
for ( DiCommandRequest requestItem : this.requests ) {
@ -143,6 +148,7 @@ public class DiConSerialPort implements DiDeviceConnection {
this.requests.add(request);
byte[] data = request.parameter.array();
this.connection.writeBytes(data, data.length);
LOG.info("Command => {} : [{}]", request.parameterText, DiByteBuffer.toHex(request.parameter));
synchronized ( request ) {
try {
request.wait();
@ -150,6 +156,6 @@ public class DiConSerialPort implements DiDeviceConnection {
throw new RuntimeException(e);
}
}
LOG.info("Command response received: {}", request.response);
LOG.info("Command <= {}", DiByteBuffer.toHex(request.response));
}
}

26
src/src/main/java/com/my/graphiteDigesterBg/diframe/util/DiByteBuffer.java

@ -1,4 +1,26 @@
package com.my.graphiteDigesterBg.diframe.util;
public class MyByteBuffer {
import java.nio.ByteBuffer;
public class DiByteBuffer {
// convert byte buffer to hex string
public static String toHex ( ByteBuffer buffer ) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < buffer.limit(); i++) {
sb.append(String.format("%02X ", buffer.get(i)));
}
return sb.toString();
}
// convert hex string to byte buffer
public static ByteBuffer fromHex ( String hex ) {
// remove space
hex = hex.replaceAll(" ", "");
// convert hex string to byte array
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < hex.length(); i += 2) {
String sub = hex.substring(i, i + 2);
bytes[i / 2] = (byte) Integer.parseInt(sub, 16);
}
// convert byte array to byte buffer
return ByteBuffer.wrap(bytes);
}
}

6
src/src/main/java/com/my/graphiteDigesterBg/diframe/util/DiClassHelper.java

@ -5,7 +5,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ClassHelper {
public class DiClassHelper {
// get all classes in package
public static List<Class<?>> getAllClassesInPackage(String packageName) {
List<Class<?>> classes = new ArrayList<>();
@ -14,7 +14,7 @@ public class ClassHelper {
List<URL> resources = Collections.list(Thread.currentThread().getContextClassLoader().getResources(packagePath));
for (URL resource : resources) {
if ( "file".equals(resource.getProtocol()) ) {
ClassHelper.getClassListByGivenFilePath(packageName,resource.getFile(), classes);
DiClassHelper.getClassListByGivenFilePath(packageName,resource.getFile(), classes);
} else {
throw new RuntimeException("Unsupported protocol: " + resource.getProtocol());
}
@ -30,7 +30,7 @@ public class ClassHelper {
File file = new File(filePath);
if ( file.isDirectory() ) {
for ( File subFile : file.listFiles() ) {
ClassHelper.getClassListByGivenFilePath(packageName + "." + subFile.getName(), subFile.getAbsolutePath(), classes);
DiClassHelper.getClassListByGivenFilePath(packageName + "." + subFile.getName(), subFile.getAbsolutePath(), classes);
}
} else {
if ( file.getName().endsWith(".class") ) {

24
src/src/main/java/com/my/graphiteDigesterBg/resource/ResHeatingTubeRackSlot.java

@ -1,4 +1,26 @@
package com.my.graphiteDigesterBg.resource;
public class HeatingTubeRackSlot {
public class ResHeatingTubeRackSlot {
// index of slot
public Integer index;
// is slot locked
private Boolean isLocked;
public Integer getOperationWindowLocation() {
return 0;
}
// get is slot locked
public Boolean getIsLocked() {
return this.isLocked;
}
// lock slot
public void lock() {
this.isLocked = true;
}
// unlock slot
public void unlock() {
this.isLocked = false;
}
}

24
src/src/main/java/com/my/graphiteDigesterBg/resource/ResHeatingTubeRackSlotManager.java

@ -1,10 +1,26 @@
package com.my.graphiteDigesterBg.resource;
import com.my.graphiteDigesterBg.diframe.DiResourceManagerBase;
import com.my.graphiteDigesterBg.diframe.util.ResourceManager;
import com.my.graphiteDigesterBg.diframe.ResourceManager;
import java.util.ArrayList;
import java.util.List;
@ResourceManager(name="HeatingTubeRackSlot")
public class HeatingTubeRackSlotManager extends DiResourceManagerBase {
public class ResHeatingTubeRackSlotManager extends DiResourceManagerBase {
// slots
private List<ResHeatingTubeRackSlot> slots;
public ResHeatingTubeRackSlotManager() {
this.slots = new ArrayList<>();
}
// get free slot
public HeatingTubeRackSlot getFreeSlot() {
return null;
public ResHeatingTubeRackSlot allocFreeSlot() {
for (ResHeatingTubeRackSlot slot : this.slots) {
if (!slot.getIsLocked()) {
slot.lock();
return slot;
}
}
throw new RuntimeException("No free slot");
}
}

3
src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java

@ -3,8 +3,7 @@ import com.my.graphiteDigesterBg.MyDevice;
import com.my.graphiteDigesterBg.diframe.DiTaskBase;
import com.my.graphiteDigesterBg.diframe.Task;
import com.my.graphiteDigesterBg.diframe.actuator.DiActPeristalticPump;
@Task(name="digestion")
@Task(name="Digestion")
public class TaskDigestion extends DiTaskBase {
@Override
public void run() {

24
src/src/main/java/com/my/graphiteDigesterBg/task/TaskSampleAdd.java

@ -1,2 +1,24 @@
package com.my.graphiteDigesterBg.task;public class TaskSampleAdd {
package com.my.graphiteDigesterBg.task;
import com.my.graphiteDigesterBg.MyDevice;
import com.my.graphiteDigesterBg.diframe.DiTaskBase;
import com.my.graphiteDigesterBg.diframe.Task;
import com.my.graphiteDigesterBg.diframe.actuator.DiActMotor;
import com.my.graphiteDigesterBg.diframe.actuator.DiActServo;
import com.my.graphiteDigesterBg.resource.ResHeatingTubeRackSlot;
import com.my.graphiteDigesterBg.resource.ResHeatingTubeRackSlotManager;
@Task(name="SampleAdd")
public class TaskSampleAdd extends DiTaskBase {
@Override
public void run() {
ResHeatingTubeRackSlotManager slotMan = this.getResourceManager(ResHeatingTubeRackSlotManager.class);
ResHeatingTubeRackSlot slot = slotMan.allocFreeSlot();
DiActMotor heatPlateMotor = (DiActMotor)this.getActuator(MyDevice.ACT_HEAT_PLATE_MOTOR);
heatPlateMotor.moveTo(slot.getOperationWindowLocation());
DiActServo coverServo = (DiActServo)this.getActuator(MyDevice.ACT_HEAT_SLOT_01_COVER_SERVO);
coverServo.moveTo(1000);
this.setStatus(TaskStatus.FINISHED);
}
}

24
src/src/main/java/com/my/graphiteDigesterBg/task/TaskStartReset.java

@ -1,2 +1,24 @@
package com.my.graphiteDigesterBg.task;public class TaskStartReset {
package com.my.graphiteDigesterBg.task;
import com.my.graphiteDigesterBg.MyDevice;
import com.my.graphiteDigesterBg.diframe.DiDeviceRegisterManager;
import com.my.graphiteDigesterBg.diframe.DiTaskBase;
import com.my.graphiteDigesterBg.diframe.Task;
import com.my.graphiteDigesterBg.diframe.actuator.DiActMotor;
@Task(name="StartReset")
public class TaskStartReset extends DiTaskBase {
@Override
public void run() {
DiDeviceRegisterManager registers = this.getDevice().getRegisters();
// 加液机械臂启用并复位
DiActMotor liquidMotor = this.getActuator(MyDevice.ACT_LIQUID_MOTOR, DiActMotor.class);
liquidMotor.setEnable(true);
registers.resetAllByModuleId(liquidMotor.getMid());
liquidMotor.activeConfig();
liquidMotor.reset();
this.setStatus(TaskStatus.FINISHED);
}
}

18
src/src/main/resources/application.yml

@ -1,7 +1,19 @@
device :
connection :
class : com.my.graphiteDigesterBg.diframe.connection.DiConSerialPort
path : COM1
baudRate : 9600
path : COM7
baudRate : 921600
frameTimeout : 1000
mode : binary # text | hex | binary
mode : binary # text | hex | binary
# device registers
registers : ["1", "2"]
# - {name: "LiquidMotorShaft" , mid : 41, index : 1051, defaultValue : 1}
# - {name: "LiquidMotorOneCirclePulse" , mid : 41, index : 1052, defaultValue : 10000}
# - {name: "LiquidMotorOneCirclePulseDenominator" , mid : 41, index : 1053, defaultValue : 18}
# - {name: "LiquidMotorDefaultVelocity" , mid : 41, index : 1054, defaultValue : 40}
# - {name: "LiquidMotorDefaultAcc" , mid : 41, index : 1055, defaultValue : 2}
# - {name: "LiquidMotorDefaultDec" , mid : 41, index : 1056, defaultValue : 2}
# - {name: "LiquidMotorRunToZeroSpeed" , mid : 41, index : 1073, defaultValue : 50}
# - {name: "LiquidMotorRunToZeroDec" , mid : 41, index : 1074, defaultValue : 30}
# - {name: "LiquidMotorLookZeroEdgeSpeed" , mid : 41, index : 1075, defaultValue : 25}
# - {name: "LiquidMotorLookZeroEdgeDec" , mid : 41, index : 1076, defaultValue : 30}

18
src/src/main/resources/device.yml

@ -0,0 +1,18 @@
connection :
class : com.my.graphiteDigesterBg.diframe.connection.DiConSerialPort
path : COM7
baudRate : 921600
frameTimeout : 1000
mode : binary # text | hex | binary
# device registers
registers :
- {key: "LiquidMotorShaft" , mid : 41, index : 1051, defaultValue : 1}
- {key: "LiquidMotorOneCirclePulse" , mid : 41, index : 1052, defaultValue : 10000}
- {key: "LiquidMotorOneCirclePulseDenominator" , mid : 41, index : 1053, defaultValue : 18}
- {key: "LiquidMotorDefaultVelocity" , mid : 41, index : 1054, defaultValue : 40}
- {key: "LiquidMotorDefaultAcc" , mid : 41, index : 1055, defaultValue : 2}
- {key: "LiquidMotorDefaultDec" , mid : 41, index : 1056, defaultValue : 2}
- {key: "LiquidMotorRunToZeroSpeed" , mid : 41, index : 1073, defaultValue : 50}
- {key: "LiquidMotorRunToZeroDec" , mid : 41, index : 1074, defaultValue : 30}
- {key: "LiquidMotorLookZeroEdgeSpeed" , mid : 41, index : 1075, defaultValue : 25}
- {key: "LiquidMotorLookZeroEdgeDec" , mid : 41, index : 1076, defaultValue : 30}

106
src/web/package-lock.json

@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"ant-design-vue": "^4.1.1",
"axios": "^1.6.5",
"core-js": "^3.8.3",
"vue": "^3.2.13"
},
@ -3707,6 +3708,11 @@
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
@ -3739,6 +3745,16 @@
"postcss": "^8.1.0"
}
},
"node_modules/axios": {
"version": "1.6.5",
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.6.5.tgz",
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
"dependencies": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/babel-loader": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.3.0.tgz",
@ -4360,6 +4376,17 @@
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"dev": true
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
@ -5089,6 +5116,14 @@
"node": ">= 0.4"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
@ -6290,7 +6325,6 @@
"version": "1.15.5",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true,
"engines": {
"node": ">=4.0"
},
@ -6381,6 +6415,19 @@
"node": ">= 8"
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
@ -7827,7 +7874,6 @@
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@ -7836,7 +7882,6 @@
"version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
@ -9390,6 +9435,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz",
@ -14737,6 +14787,11 @@
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
@ -14757,6 +14812,16 @@
"postcss-value-parser": "^4.2.0"
}
},
"axios": {
"version": "1.6.5",
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.6.5.tgz",
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
"requires": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"babel-loader": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.3.0.tgz",
@ -15274,6 +15339,14 @@
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"dev": true
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
@ -15840,6 +15913,11 @@
"object-keys": "^1.1.1"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
@ -16814,8 +16892,7 @@
"follow-redirects": {
"version": "1.15.5",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw=="
},
"foreground-child": {
"version": "3.1.1",
@ -16876,6 +16953,16 @@
}
}
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
@ -18022,14 +18109,12 @@
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"requires": {
"mime-db": "1.52.0"
}
@ -19162,6 +19247,11 @@
}
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz",

3
src/web/package.json

@ -9,6 +9,7 @@
},
"dependencies": {
"ant-design-vue": "^4.1.1",
"axios": "^1.6.5",
"core-js": "^3.8.3",
"vue": "^3.2.13"
},
@ -37,7 +38,7 @@
"parser": "@babel/eslint-parser"
},
"rules": {
"vue/multi-word-component-names" : "off"
"vue/multi-word-component-names": "off"
}
},
"browserslist": [

28
src/web/src/pages/main/contents/Operation.vue

@ -44,12 +44,20 @@
</div>
</div>
</div>
<div class="mt-3 flex flex-row justify-around">
<a-button>暂停加热</a-button>
<a-button>清洗石墨盘</a-button>
<a-button>加载预设</a-button>
<a-button>加酸</a-button>
<a-button>加热</a-button>
<div class="mt-3">
<a-row>
<a-col :span="12" class="text-left">
<!-- <a-button>暂停加热</a-button>
<a-button>清洗石墨盘</a-button>
<a-button>加载预设</a-button>
<a-button>加酸</a-button>
<a-button>加热</a-button> -->
</a-col>
<a-col :span="12" class="text-right">
<a-button @click="actionSampleAdd">添加样品</a-button>
<a-button class="ml-1" @click="actionSampleAddOrTakeOut">取出样品</a-button>
</a-col>
</a-row>
</div>
</div>
</a-col>
@ -96,6 +104,14 @@
</div>
</div>
</template>
<script setup>
import ApiClient from '@/utils/ApiClient.js';
//
async function actionSampleAdd() {
let client = ApiClient.getClient();
await client.taskAppend('sampleAdd');
}
</script>
<style scoped>
.heating-plate {background: #EEEFF8;border: solid 12px #E5E7F2;}
.tube-rack-slot .title {font-size: 16px;font-weight: bold;letter-spacing: 0.06em;top:-45px;color: #D6D9F1;}

Loading…
Cancel
Save