|
|
@ -1,6 +1,7 @@ |
|
|
|
package com.iflytop.digester.underframework.connection; |
|
|
|
import com.iflytop.digester.underframework.dao.model.TsMdbActuator; |
|
|
|
import com.iflytop.digester.underframework.dao.model.UfMdbActuatorCmd; |
|
|
|
import com.iflytop.digester.underframework.dao.record.UfActiveRecord; |
|
|
|
import com.iflytop.digester.underframework.util.TsByteBuffer; |
|
|
|
import com.iflytop.digester.underframework.util.UfClassHelper; |
|
|
|
import org.java_websocket.client.WebSocketClient; |
|
|
@ -19,13 +20,17 @@ public class UfZcancmderWebsocket extends UfConnectionBase { |
|
|
|
// client |
|
|
|
private WebSocketClient client; |
|
|
|
// packet index |
|
|
|
private int packetIndex = 0; |
|
|
|
private int packetIndexCounter = 0; |
|
|
|
// current packet index |
|
|
|
private int currentPacketIndex = 0; |
|
|
|
// call lock |
|
|
|
private final Object callLock = new Object(); |
|
|
|
// response |
|
|
|
private ByteBuffer response; |
|
|
|
// response error |
|
|
|
private String responseError; |
|
|
|
// timeout timer |
|
|
|
private Timer timeoutTimer; |
|
|
|
|
|
|
|
@Override |
|
|
|
public void connect() { |
|
|
@ -70,6 +75,8 @@ public class UfZcancmderWebsocket extends UfConnectionBase { |
|
|
|
returnValue = (String) UfClassHelper.invokeMethod(this, methodName, List.of(command)); |
|
|
|
} catch (NoSuchMethodException e) { |
|
|
|
returnValue = this.executeDeviceCommand(command); |
|
|
|
} catch (Exception e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
} |
|
|
|
|
|
|
|
if ( 1 == command.waitForFinish ) { |
|
|
@ -80,18 +87,32 @@ public class UfZcancmderWebsocket extends UfConnectionBase { |
|
|
|
|
|
|
|
// execute device command |
|
|
|
private String executeDeviceCommand( UfMdbActuatorCmd actuatorCmd ) { |
|
|
|
this.response = null; |
|
|
|
this.responseError = null; |
|
|
|
this.sendCommandRequest(actuatorCmd); |
|
|
|
|
|
|
|
synchronized (this.callLock) { |
|
|
|
try { |
|
|
|
this.callLock.wait(); |
|
|
|
} catch (InterruptedException e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
// 超时重试3次 |
|
|
|
for ( int i=0; i<3; i++ ) { |
|
|
|
this.response = null; |
|
|
|
this.responseError = null; |
|
|
|
// 启动超时定时器 |
|
|
|
this.startTimeoutTimer(); |
|
|
|
// 发送数据 |
|
|
|
this.sendCommandRequest(actuatorCmd); |
|
|
|
// 等待数据响应或超时 |
|
|
|
synchronized (this.callLock) { |
|
|
|
try { |
|
|
|
this.callLock.wait(); |
|
|
|
} catch (InterruptedException e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
} |
|
|
|
} |
|
|
|
if ( null != this.response ) { |
|
|
|
break ; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if ( null == this.response ) { |
|
|
|
var actuator = UfActiveRecord.findOne(TsMdbActuator.class, actuatorCmd.actuatorId); |
|
|
|
throw new RuntimeException(String.format("设备 [%s] 响应超时: %s", actuator.name, actuatorCmd.cmdKey)); |
|
|
|
} |
|
|
|
|
|
|
|
if ( null != this.responseError ) { |
|
|
|
throw new RuntimeException(this.responseError); |
|
|
|
} |
|
|
@ -112,6 +133,22 @@ public class UfZcancmderWebsocket extends UfConnectionBase { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// start timeout timer |
|
|
|
private void startTimeoutTimer() { |
|
|
|
var timerTask = new TimerTask() { |
|
|
|
@Override |
|
|
|
public void run() { |
|
|
|
LOG.info("[Command-Executor] timeout"); |
|
|
|
UfZcancmderWebsocket.this.timeoutTimer = null; |
|
|
|
synchronized (UfZcancmderWebsocket.this.callLock) { |
|
|
|
UfZcancmderWebsocket.this.callLock.notifyAll(); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
this.timeoutTimer = new Timer(); |
|
|
|
this.timeoutTimer.schedule(timerTask, 3000); |
|
|
|
} |
|
|
|
|
|
|
|
// send command request |
|
|
|
private void sendCommandRequest(UfMdbActuatorCmd actuatorCmd) { |
|
|
|
String cmd = this.buildCommand(actuatorCmd); |
|
|
@ -150,7 +187,7 @@ public class UfZcancmderWebsocket extends UfConnectionBase { |
|
|
|
int bufferSize = 2 + 2 + 1 + 1 + 2 + 4 * paramList.size(); // PacketIndex - MainCmdId - SubCmdId - CmdType - ModuleId - Parameters |
|
|
|
ByteBuffer buffer = ByteBuffer.allocate(bufferSize); |
|
|
|
buffer.order(ByteOrder.LITTLE_ENDIAN); |
|
|
|
buffer.putShort((short) this.packetIndex); // PacketIndex |
|
|
|
buffer.putShort((short) this.packetIndexCounter); // PacketIndex |
|
|
|
buffer.putShort((short) mainCmdId); // MainCmdId |
|
|
|
buffer.put((byte) subCmdId); // SubCmdId |
|
|
|
buffer.put((byte) 0); // CmdType |
|
|
@ -160,9 +197,10 @@ public class UfZcancmderWebsocket extends UfConnectionBase { |
|
|
|
buffer.putInt(Integer.parseInt(param)); |
|
|
|
} |
|
|
|
|
|
|
|
this.packetIndex ++; |
|
|
|
if ( this.packetIndex > 30000 ) { |
|
|
|
this.packetIndex = 0; |
|
|
|
this.currentPacketIndex = this.packetIndexCounter; |
|
|
|
this.packetIndexCounter++; |
|
|
|
if ( this.packetIndexCounter > 30000 ) { |
|
|
|
this.packetIndexCounter = 0; |
|
|
|
} |
|
|
|
|
|
|
|
String cmd = TsByteBuffer.toHex(buffer); |
|
|
@ -174,6 +212,16 @@ public class UfZcancmderWebsocket extends UfConnectionBase { |
|
|
|
private void handleOnTextMessage( String text ) { |
|
|
|
ByteBuffer message = TsByteBuffer.fromHex(text); |
|
|
|
message.order(ByteOrder.LITTLE_ENDIAN); |
|
|
|
short packetIndex = message.getShort(0); |
|
|
|
if ( packetIndex != this.currentPacketIndex ) { |
|
|
|
return ; // 可能超时了, 所以忽略掉 ~~~ |
|
|
|
} |
|
|
|
|
|
|
|
if ( null != this.timeoutTimer ) { |
|
|
|
this.timeoutTimer.cancel(); |
|
|
|
this.timeoutTimer = null; |
|
|
|
} |
|
|
|
|
|
|
|
byte messageType = message.get(5); |
|
|
|
if ( 0x01 == messageType ) { // ack message |
|
|
|
this.handleOnTextAckMessage(message); |
|
|
@ -229,4 +277,33 @@ public class UfZcancmderWebsocket extends UfConnectionBase { |
|
|
|
} |
|
|
|
} while ( true ); |
|
|
|
} |
|
|
|
|
|
|
|
// cmd motor easy move to |
|
|
|
public void cmdMotorEasyMoveTo(UfMdbActuatorCmd command) { |
|
|
|
this.executeDeviceCommand(command); |
|
|
|
this.waitForActuatorFinish(command); |
|
|
|
|
|
|
|
var actuator = UfActiveRecord.findOne(TsMdbActuator.class, command.actuatorId); |
|
|
|
var encoderAvailable = actuator.getProperty("encoderAvailable"); |
|
|
|
if ( null == encoderAvailable || !encoderAvailable.asBoolean() ) { |
|
|
|
return ; |
|
|
|
} |
|
|
|
|
|
|
|
var destValue = Integer.parseInt(command.parameters); |
|
|
|
var encoderValue = this.getActuatorEncoderValue(command); |
|
|
|
if ( Math.abs(encoderValue - destValue) > 10 ) { |
|
|
|
throw new RuntimeException(String.format("电机 [%s] 移动失败,目标位置:%d,当前位置:%d", actuator.name, destValue, encoderValue)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// cmd motor read enc val |
|
|
|
private Integer getActuatorEncoderValue(UfMdbActuatorCmd srcCmd) { |
|
|
|
var command = new UfMdbActuatorCmd(); |
|
|
|
command.actuatorId = srcCmd.actuatorId; |
|
|
|
command.cmdId = "0219"; |
|
|
|
command.cmdKey = "motor_read_enc_val"; |
|
|
|
command.cmdFlags = srcCmd.cmdFlags; |
|
|
|
String value = this.executeDeviceCommand(command); |
|
|
|
return Integer.parseInt(value); |
|
|
|
} |
|
|
|
} |