sige 2 years ago
parent
commit
61dcde4398
  1. 5
      src/pom.xml
  2. 16
      src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDevice.java
  3. 144
      src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConWebsocket.java
  4. 49
      src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConWebsocketClient.java
  5. 8
      src/src/main/resources/application.yml
  6. 16
      src/src/main/resources/device.yml

5
src/pom.xml

@ -29,6 +29,11 @@
<artifactId>jSerialComm</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.4</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.yaml</groupId>-->
<!-- <artifactId>snakeyaml</artifactId>-->

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

@ -1,11 +1,11 @@
package com.my.graphiteDigesterBg.diframe;
import com.my.graphiteDigesterBg.diframe.util.DiByteBuffer;
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;
@ -15,7 +15,6 @@ import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class DiDevice {
@Resource
@ -76,7 +75,7 @@ public class DiDevice {
// setup connection
private void setupConnection() {
String connectionClassName = this.env.getProperty("device.connection.class");
String connectionClassName = this.getConfig("connection.class");
Class<?> connectionClass = null;
try {
connectionClass = Class.forName(connectionClassName);
@ -175,6 +174,8 @@ public class DiDevice {
request = this.buildCommandRequestForTextMode(cmd, mid, args);
} else if ("binary".equals(cmdMode) ) {
request = this.buildCommandRequestForBinaryMode(cmd, mid, args);
} else if ("hex".equals(cmdMode)) {
request = this.buildCommandRequestForHexMode(cmd, mid, args);
} else {
throw new RuntimeException("Unknown command mode: " + cmdMode);
}
@ -239,4 +240,13 @@ public class DiDevice {
return request;
}
// build command buffer for hex mode
private DiCommandRequest buildCommandRequestForHexMode(DiCommand cmd, Integer mid, Object... args) {
DiCommandRequest request = this.buildCommandRequestForBinaryMode(cmd, mid, args);
String hex = DiByteBuffer.toHex(request.parameter);
hex = hex.replace(" ","");
request.parameter = ByteBuffer.wrap(hex.getBytes());
return request;
}
}

144
src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConWebsocket.java

@ -0,0 +1,144 @@
package com.my.graphiteDigesterBg.diframe.connection;
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 java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class DiConWebsocket implements DiDeviceConnection {
// logger
public static final Logger LOG = LoggerFactory.getLogger(DiConWebsocket.class);
// device
private DiDevice device;
// client
private DiConWebsocketClient client;
// requests
private final List<DiCommandRequest> requests;
// constructor
public DiConWebsocket() {
this.requests = new ArrayList<>();
}
@Override
public void setDevice(DiDevice device) {
this.device = device;
}
@Override
public void connect() {
String wsUri = this.device.getConfig("connection.uri");
if ( null == wsUri ) {
throw new RuntimeException("device option 'device.connection.uri' is required.");
}
URI uri = null;
try {
uri = new URI(wsUri);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
this.client = new DiConWebsocketClient(uri);
this.client.connect();
this.client.setHolder(this);
}
@Override
public void call(DiCommandRequest request) {
this.requests.add(request);
String cmd = DiByteBuffer.toHex(request.parameter);
LOG.info("Command => {} : [{}]", request.parameterText, cmd);
cmd = cmd.replace(" ","");
this.client.send(cmd);
this.setupRequestTimeoutTimer(request);
synchronized ( request ) {
try {
request.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
LOG.info("Command <= {}", DiByteBuffer.toHex(request.response));
}
// setup request timeout timer
private void setupRequestTimeoutTimer(DiCommandRequest request) {
TimerTask callTimeoutTimerTask = new TimerTask() {
@Override
public void run() {
DiConWebsocket.this.handleCallTimeout(request);
}
};
request.timeoutTimer = new Timer();
Integer callTimeout = this.device.getConfig("connection.callTimeout", Integer.class);
request.timeoutTimer.schedule(callTimeoutTimerTask, callTimeout);
}
// handle call timeout
private void handleCallTimeout(DiCommandRequest request) {
if ( request.isResponseReceived ) {
return ;
}
request.timeoutCount ++;
if ( request.timeoutCount > 3 ) {
synchronized ( request ) {
request.timeoutTimer = null;
request.errorCode = 8000;
request.notify();
}
return ;
}
String cmd = DiByteBuffer.toHex(request.parameter);
LOG.info("Command (Retry:{}) => {} : [{}]", request.timeoutCount, request.parameterText, cmd);
cmd = cmd.replace(" ","");
this.client.send(cmd);
this.setupRequestTimeoutTimer(request);
}
// handle on data
public void handleOnText(String text) {
ByteBuffer message = DiByteBuffer.fromHex(text);
message.order(ByteOrder.LITTLE_ENDIAN);
byte messageType = message.get(5);
if ( 0x01 == messageType ) { // ack message
this.handleOnTextAckMessage(message);
} else if ( 0x02 == messageType ) { // error message
throw new RuntimeException("error message received: " + text);
} else {
throw new RuntimeException("unknown message type : " + messageType + " <= " + text);
}
}
// handle on data timeout for binary mode ack message
private void handleOnTextAckMessage(ByteBuffer message) {
short messageId = message.getShort(0);
DiCommandRequest request = null;
for ( DiCommandRequest requestItem : this.requests ) {
if ( requestItem.id == messageId ) {
request = requestItem;
break;
}
}
if ( null == request ) {
return ; // 可能是超时了 已经被处理掉了 ~~~
}
request.response = message;
request.isResponseReceived = true;
if ( null != request.timeoutTimer ) {
request.timeoutTimer.cancel();
request.timeoutTimer = null;
}
synchronized ( request ) {
request.notify();
}
}
}

49
src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConWebsocketClient.java

@ -0,0 +1,49 @@
package com.my.graphiteDigesterBg.diframe.connection;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
public class DiConWebsocketClient extends WebSocketClient {
// logger
public static final Logger LOG = LoggerFactory.getLogger(DiConWebsocketClient.class);
// holder
private DiConWebsocket holder;
// constructor
public DiConWebsocketClient(URI uri) {
super(uri);
}
// set holder
public void setHolder(DiConWebsocket holder) {
this.holder = holder;
}
/**
* event handler for receiving text message from device
* @param text message from device
*/
@Override
public void onMessage(String text) {
this.holder.handleOnText(text);
}
@Override
public void onOpen(ServerHandshake serverHandshake) {
LOG.info("device connected : {}", this.uri);
}
@Override
public void onClose(int i, String s, boolean b) {
LOG.info("close");
throw new RuntimeException("device connection closed");
}
@Override
public void onError(Exception e) {
LOG.error("error", e);
throw new RuntimeException(e);
}
}

8
src/src/main/resources/application.yml

@ -8,11 +8,3 @@ spring:
#mybatis:
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
device :
connection :
class : com.my.graphiteDigesterBg.diframe.connection.DiConSerialPort
path : COM1
baudRate : 921600
frameTimeout : 1000
mode : binary # text | hex | binary

16
src/src/main/resources/device.yml

@ -1,10 +1,14 @@
connection :
class : com.my.graphiteDigesterBg.diframe.connection.DiConSerialPort
path : COM1
baudRate : 921600
frameTimeout : 100
callTimeout : 5000
mode : binary # text | hex | binary
# class : com.my.graphiteDigesterBg.diframe.connection.DiConSerialPort
# path : COM1
# baudRate : 921600
# frameTimeout : 100
# callTimeout : 5000
# mode : binary # text | hex | binary
class : com.my.graphiteDigesterBg.diframe.connection.DiConWebsocket
uri : ws://127.0.0.1:8899/device
mode : hex
callTimeout : 3000
# device registers
registers :
# 加液电机

Loading…
Cancel
Save