diff --git a/src/pom.xml b/src/pom.xml
index 5a8dd12..5bdcb6a 100644
--- a/src/pom.xml
+++ b/src/pom.xml
@@ -27,6 +27,12 @@
spring-boot-starter-test
test
+
+
+ com.fazecast
+ jSerialComm
+ 2.6.2
+
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/MyApplicationRunner.java b/src/src/main/java/com/my/graphiteDigesterBg/MyApplicationRunner.java
index cc2b6e0..3757f3f 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/MyApplicationRunner.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/MyApplicationRunner.java
@@ -4,6 +4,7 @@ import com.my.graphiteDigesterBg.diframe.DiDeviceActuatorManager;
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 jakarta.annotation.Resource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
@@ -70,7 +71,7 @@ public class MyApplicationRunner implements ApplicationRunner {
actuators.register(MyDevice.ACT_LIQUID_PLATE_MOTOR, new DiActMotor(){{
mid = 51;
}});
- actuators.register(MyDevice.ACT_LIQUID_PERISTALTIC_PUMP, new DiActMotor(){{
+ actuators.register(MyDevice.ACT_LIQUID_PERISTALTIC_PUMP, new DiActPeristalticPump(){{
mid = 61;
}});
}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuator.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuator.java
index 5479614..1a1e421 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuator.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuator.java
@@ -1,4 +1,5 @@
package com.my.graphiteDigesterBg.diframe;
public interface DiActuator {
-
+ // set device
+ void setDevice( DiDevice device );
}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuatorBase.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuatorBase.java
index b8c22a9..6d476aa 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuatorBase.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiActuatorBase.java
@@ -1,8 +1,40 @@
package com.my.graphiteDigesterBg.diframe;
-
-import com.my.graphiteDigesterBg.diframe.DiActuator;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
abstract public class DiActuatorBase implements DiActuator {
+ // device
+ private DiDevice device;
// mid
protected Integer mid;
+
+ @Override
+ public void setDevice( DiDevice device ) {
+ this.device = device;
+ }
+
+ // execute device command
+ protected DiCommandResponse call( DiCommand cmd, Object... args ) {
+ ByteBuffer buffer = null;
+ String cmdMode = this.device.getEnv().getProperty("device.command.mode");
+ if ("text".equals(cmdMode)) {
+ buffer = this.buildCommandBufferForTextMode(cmd, args);
+ } else {
+ throw new RuntimeException("Unknown command mode: " + cmdMode);
+ }
+ ByteBuffer response = this.device.getConnection().call(buffer);
+ return new DiCommandResponse(response);
+ }
+
+ // build command buffer for text mode
+ private ByteBuffer buildCommandBufferForTextMode(DiCommand cmd, Object... args) {
+ List parts = new ArrayList<>();
+ parts.add(cmd.getName());
+ for ( Object arg : args ) {
+ parts.add(arg.toString());
+ }
+ String command = String.join(" ", parts);
+ return ByteBuffer.wrap(command.getBytes());
+ }
}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommand.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommand.java
new file mode 100644
index 0000000..2d4c810
--- /dev/null
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommand.java
@@ -0,0 +1,25 @@
+package com.my.graphiteDigesterBg.diframe;
+public enum DiCommand {
+ MOTOR_EASY_MOVE_BY("motor_easy_move_by", 0x0212);
+
+ // command name
+ private final String name;
+ // command id
+ private final int cmdId;
+
+ // constructor
+ DiCommand(String name, int cmdId) {
+ this.name = name;
+ this.cmdId = cmdId;
+ }
+
+ // get command name
+ public String getName() {
+ return this.name;
+ }
+
+ // get command id
+ public int getCmdId() {
+ return this.cmdId;
+ }
+}
\ No newline at end of file
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommandResponse.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommandResponse.java
new file mode 100644
index 0000000..fc238fb
--- /dev/null
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiCommandResponse.java
@@ -0,0 +1,16 @@
+package com.my.graphiteDigesterBg.diframe;
+import java.nio.ByteBuffer;
+public class DiCommandResponse {
+ // response
+ private final ByteBuffer response;
+
+ // constructor
+ public DiCommandResponse(ByteBuffer response) {
+ this.response = response;
+ }
+
+ // read integer
+ public Integer readInteger( Integer index ) {
+ return this.response.getInt(index);
+ }
+}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDevice.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDevice.java
index dbaabdf..c32eba4 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDevice.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDevice.java
@@ -1,8 +1,19 @@
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.stereotype.Component;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
@Component
public class DiDevice {
+ @Resource
+ private Environment env;
+ // connection
+ private DiDeviceConnection connection;
// io manager
private DiDeviceIOManager io;
// actuator manager
@@ -12,11 +23,38 @@ public class DiDevice {
@PostConstruct
public void init() {
+ this.setupConnection();
this.io = new DiDeviceIOManager(this);
this.actuators = new DiDeviceActuatorManager(this);
this.taskManager = new DiTaskManager(this);
}
+ // setup connection
+ private void setupConnection() {
+ String connectionClassName = this.env.getProperty("device.connection.class");
+ Class> connectionClass = null;
+ try {
+ connectionClass = Class.forName(connectionClassName);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ Constructor> connectionConstructor = null;
+ try {
+ connectionConstructor = connectionClass.getDeclaredConstructor();
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+
+ try {
+ this.connection = (DiDeviceConnection) connectionConstructor.newInstance();
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ this.connection.setDevice(this);
+ this.connection.connect();
+ }
+
// get io manager
public DiDeviceIOManager getIO() {
return this.io;
@@ -31,4 +69,14 @@ public class DiDevice {
public DiTaskManager getTaskManager() {
return this.taskManager;
}
+
+ // get connection
+ public DiDeviceConnection getConnection() {
+ return this.connection;
+ }
+
+ // get env
+ public Environment getEnv() {
+ return this.env;
+ }
}
\ No newline at end of file
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceActuatorManager.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceActuatorManager.java
index b6fc1d9..27104c4 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceActuatorManager.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceActuatorManager.java
@@ -15,11 +15,12 @@ public class DiDeviceActuatorManager {
// register actuator
public void register( String id, DiActuator actuator ) {
- this.actuators.put( id, actuator );
+ actuator.setDevice(this.device);
+ this.actuators.put(id, actuator);
}
// get actuator
- public void get( String id ) {
- this.actuators.get( id );
+ public DiActuator get( String id ) {
+ return this.actuators.get( id );
}
}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceConnection.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceConnection.java
new file mode 100644
index 0000000..03d1b14
--- /dev/null
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDeviceConnection.java
@@ -0,0 +1,10 @@
+package com.my.graphiteDigesterBg.diframe;
+import java.nio.ByteBuffer;
+public interface DiDeviceConnection {
+ // set device
+ void setDevice(DiDevice device);
+ // connect to device
+ void connect();
+ // call device with parameter and return result
+ ByteBuffer call(ByteBuffer parameter);
+}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTask.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTask.java
index 383cf7d..8364ea0 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTask.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTask.java
@@ -6,6 +6,8 @@ public interface DiTask {
TaskStatus getStatus();
// get UUID
String getUUID();
+ // set device
+ void setDevice(DiDevice device);
// set parameter
void setParameter(Object parameter);
// run
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java
index f01f2e1..74ced70 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java
@@ -1,8 +1,9 @@
package com.my.graphiteDigesterBg.diframe;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
abstract public class DiTaskBase implements DiTask {
+ // device
+ private DiDevice device;
// uuid
private final String uuid;
// status
@@ -27,6 +28,11 @@ abstract public class DiTaskBase implements DiTask {
this.status = status;
}
+ // get device
+ protected DiDevice getDevice() {
+ return this.device;
+ }
+
@Override
public String getUUID() {
return this.uuid;
@@ -38,6 +44,11 @@ abstract public class DiTaskBase implements DiTask {
}
@Override
+ public void setDevice(DiDevice device) {
+ this.device = device;
+ }
+
+ @Override
public void setParameter(Object parameter) {
this.parameter = parameter;
}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskManager.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskManager.java
index 3d0c0af..8152df5 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskManager.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskManager.java
@@ -11,9 +11,9 @@ public class DiTaskManager {
// logger
public static final Logger LOG = LoggerFactory.getLogger(DiTaskManager.class);
// device
- private DiDevice device;
+ private final DiDevice device;
// task classes
- private Map> taskClasses;
+ private final Map> taskClasses;
// task executor
private DiTaskExecutor executor;
// executor thread
@@ -75,6 +75,7 @@ public class DiTaskManager {
throw new RuntimeException(e);
}
+ task.setDevice(this.device);
task.setParameter(parameter);
return task;
}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActPeristalticPump.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActPeristalticPump.java
index 870fa7c..11c7d33 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActPeristalticPump.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/actuator/DiActPeristalticPump.java
@@ -1,6 +1,8 @@
package com.my.graphiteDigesterBg.diframe.actuator;
-
import com.my.graphiteDigesterBg.diframe.DiActuatorBase;
-
+import com.my.graphiteDigesterBg.diframe.DiCommand;
public class DiActPeristalticPump extends DiActuatorBase {
+ public void rotate() {
+ this.call(DiCommand.MOTOR_EASY_MOVE_BY, 1);
+ }
}
\ No newline at end of file
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiConsumable.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiConsumable.java
similarity index 61%
rename from src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiConsumable.java
rename to src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiConsumable.java
index 6dbf358..aee50c0 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiConsumable.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiConsumable.java
@@ -1,4 +1,4 @@
package com.my.graphiteDigesterBg.diframe.api;
-public class ApiConsumable {
+public class DiApiConsumable {
}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiDevice.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiDevice.java
similarity index 94%
rename from src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiDevice.java
rename to src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiDevice.java
index 19364f9..67dd71f 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiDevice.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiDevice.java
@@ -7,7 +7,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
-public class ApiDevice extends DiApiControllerBase {
+public class DiApiDevice extends DiApiControllerBase {
@Resource
private DiDevice device;
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiTask.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiTask.java
similarity index 95%
rename from src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiTask.java
rename to src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiTask.java
index 9c22de3..b47f267 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiTask.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiTask.java
@@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;
@Controller
-public class ApiTask extends DiApiControllerBase {
+public class DiApiTask extends DiApiControllerBase {
@Resource
private DiDevice device;
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiUser.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiUser.java
similarity index 80%
rename from src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiUser.java
rename to src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiUser.java
index 483a5b6..21992ca 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiUser.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiUser.java
@@ -1,5 +1,5 @@
package com.my.graphiteDigesterBg.diframe.api;
-public class ApiUser {
+public class DiApiUser {
public void login() {}
public void logout() {}
}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConSerialPort.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConSerialPort.java
new file mode 100644
index 0000000..2eef350
--- /dev/null
+++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConSerialPort.java
@@ -0,0 +1,72 @@
+package com.my.graphiteDigesterBg.diframe.connection;
+import com.fazecast.jSerialComm.SerialPort;
+import com.fazecast.jSerialComm.SerialPortDataListener;
+import com.fazecast.jSerialComm.SerialPortEvent;
+import com.my.graphiteDigesterBg.diframe.DiDevice;
+import com.my.graphiteDigesterBg.diframe.DiDeviceConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.env.Environment;
+import java.nio.ByteBuffer;
+public class DiConSerialPort implements DiDeviceConnection {
+ // logger
+ public static final Logger LOG = LoggerFactory.getLogger(DiConSerialPort.class);
+ // device
+ private DiDevice device;
+ // serial port connection
+ private SerialPort connection;
+
+ @Override
+ public void setDevice(DiDevice device) {
+ this.device = device;
+ }
+
+ @Override
+ public void connect() {
+ Environment env = this.device.getEnv();
+ String path = env.getProperty("device.connection.path");
+ if ( null == path ) {
+ throw new RuntimeException("device option 'device.connection.path' is required.");
+ }
+ Integer baudRate = env.getProperty("device.connection.baudRate", Integer.class);
+ if ( null == baudRate ) {
+ throw new RuntimeException("device option 'device.connection.baudRate' is required.");
+ }
+
+ this.connection = SerialPort.getCommPort(path);
+ this.connection.openPort();
+ if ( !this.connection.isOpen() ) {
+ throw new RuntimeException("Failed to open serial port");
+ }
+
+ this.connection.setBaudRate(baudRate);
+ this.connection.addDataListener(new SerialPortDataListener() {
+ @Override
+ public int getListeningEvents() {
+ return SerialPort.LISTENING_EVENT_DATA_RECEIVED;
+ }
+ @Override
+ public void serialEvent(SerialPortEvent serialPortEvent) {
+ DiConSerialPort.this.handleOnData(serialPortEvent);
+ }
+ });
+ LOG.info("Connecting to device: {}@{}", path, baudRate);
+ }
+
+ // handle on data
+ private void handleOnData(SerialPortEvent serialPortEvent) {
+ byte[] data = serialPortEvent.getReceivedData();
+ System.out.println("Received data of size: " + data.length);
+ for (byte b : data) {
+ System.out.print((char)b);
+ }
+ System.out.println("\n");
+ }
+
+ @Override
+ public ByteBuffer call(ByteBuffer parameter) {
+ byte[] data = parameter.array();
+ this.connection.writeBytes(data, data.length);
+ return null;
+ }
+}
diff --git a/src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java b/src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java
index ab60e61..b48cb76 100644
--- a/src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java
+++ b/src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java
@@ -1,10 +1,16 @@
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.DiActPeristalticPump;
+
@Task(name="digestion")
public class TaskDigestion extends DiTaskBase {
@Override
public void run() {
+ DiActPeristalticPump peristalticPump = (DiActPeristalticPump)this.getDevice().getActuators().get(MyDevice.ACT_LIQUID_PERISTALTIC_PUMP);
+ peristalticPump.rotate();
+
System.out.println("TaskDigestion.run()");
this.setStatus(TaskStatus.FINISHED);
}
diff --git a/src/src/main/resources/application.properties b/src/src/main/resources/application.properties
deleted file mode 100644
index 8b13789..0000000
--- a/src/src/main/resources/application.properties
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/src/main/resources/application.yml b/src/src/main/resources/application.yml
new file mode 100644
index 0000000..29afcf1
--- /dev/null
+++ b/src/src/main/resources/application.yml
@@ -0,0 +1,7 @@
+device :
+ connection :
+ class : com.my.graphiteDigesterBg.diframe.connection.DiConSerialPort
+ path : COM1
+ baudRate : 9600
+ command :
+ mode : text # text | hex | binary
\ No newline at end of file