6 changed files with 221 additions and 17 deletions
-
5src/pom.xml
-
16src/src/main/java/com/my/graphiteDigesterBg/diframe/DiDevice.java
-
144src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConWebsocket.java
-
49src/src/main/java/com/my/graphiteDigesterBg/diframe/connection/DiConWebsocketClient.java
-
8src/src/main/resources/application.yml
-
16src/src/main/resources/device.yml
@ -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(); |
|||
} |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue