修改框架内容
This commit is contained in:
parent
425ba5eba4
commit
e44347eec9
|
|
@ -52,7 +52,7 @@ public class MachineCommandManager {
|
||||||
*/
|
*/
|
||||||
public void bindMachine(String sn, String vendorType) {
|
public void bindMachine(String sn, String vendorType) {
|
||||||
vendorRegistry.bindSnToVendor(sn, vendorType);
|
vendorRegistry.bindSnToVendor(sn, vendorType);
|
||||||
log.info("绑定设备到厂家: sn=, vendorType={}", sn, vendorType);
|
log.info("绑定设备到厂家: sn={}, vendorType={}", sn, vendorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ public enum CommandType {
|
||||||
*/
|
*/
|
||||||
TAKE_OFF,
|
TAKE_OFF,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返航
|
* 返航
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public class Transaction {
|
||||||
/**
|
/**
|
||||||
* 事务超时时间(毫秒)
|
* 事务超时时间(毫秒)
|
||||||
*/
|
*/
|
||||||
private long timeoutMs = 120000; // 默认2分钟
|
private long timeoutMs = 10000; // 默认10秒
|
||||||
|
|
||||||
public Transaction(String name, CommandType commandType) {
|
public Transaction(String name, CommandType commandType) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tuoheng.machine.instruction;
|
package com.tuoheng.machine.instruction;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
@ -38,7 +39,7 @@ public class CallbackConfig {
|
||||||
/**
|
/**
|
||||||
* 超时时间(毫秒)
|
* 超时时间(毫秒)
|
||||||
*/
|
*/
|
||||||
private long timeoutMs = 30000;
|
private long timeoutMs = 3000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断消息是否匹配
|
* 判断消息是否匹配
|
||||||
|
|
@ -60,8 +61,19 @@ public class CallbackConfig {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] parts = path.split("\\.");
|
// 如果 messageBody 是字符串,尝试解析为 JSON
|
||||||
Object current = messageBody;
|
Object current = messageBody;
|
||||||
|
if (messageBody instanceof String) {
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
current = objectMapper.readValue((String) messageBody, Object.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 解析失败,返回 null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = path.split("\\.");
|
||||||
|
|
||||||
for (String part : parts) {
|
for (String part : parts) {
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ public enum AirportState {
|
||||||
*/
|
*/
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在线
|
* 在线
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -52,59 +52,13 @@ public class DjiVendorConfig implements VendorConfig {
|
||||||
switch (commandType) {
|
switch (commandType) {
|
||||||
|
|
||||||
case TAKE_OFF:
|
case TAKE_OFF:
|
||||||
return droneState == DroneState.ONLINE ;
|
return droneState == DroneState.ONLINE && airportState == AirportState.ONLINE;
|
||||||
|
|
||||||
case RETURN_HOME:
|
case RETURN_HOME:
|
||||||
return droneState == DroneState.FLYING ;
|
return droneState == DroneState.FLYING || droneState == DroneState.ARRIVED;
|
||||||
|
|
||||||
case EMERGENCY_STOP:
|
|
||||||
// 飞行中、返航中可以急停(未处于急停状态)
|
|
||||||
return (droneState == DroneState.FLYING || droneState == DroneState.RETURNING) &&
|
|
||||||
stopState != StopState.ENTERED;
|
|
||||||
|
|
||||||
case RESUME_FLIGHT:
|
|
||||||
// 急停状态可以继续飞行
|
|
||||||
return stopState == StopState.ENTERED;
|
|
||||||
|
|
||||||
case POINT_FLY:
|
|
||||||
// 飞行中、到达目的地、返航中可以指点飞行(未急停)
|
|
||||||
return (droneState == DroneState.FLYING ||
|
|
||||||
droneState == DroneState.ARRIVED ||
|
|
||||||
droneState == DroneState.RETURNING) &&
|
|
||||||
stopState != StopState.ENTERED;
|
|
||||||
|
|
||||||
case CANCEL_POINT:
|
|
||||||
// 飞行中可以取消指点
|
|
||||||
return droneState == DroneState.FLYING;
|
|
||||||
|
|
||||||
case START_MISSION:
|
|
||||||
// 未知状态或离线状态且未急停时可以开始航线任务
|
|
||||||
return (droneState == DroneState.UNKNOWN || droneState == DroneState.ONLINE) &&
|
|
||||||
stopState != StopState.ENTERED;
|
|
||||||
|
|
||||||
case OPEN_COVER:
|
|
||||||
// 舱门关闭状态可以打开
|
|
||||||
return coverState == CoverState.CLOSED;
|
|
||||||
|
|
||||||
case CLOSE_COVER:
|
|
||||||
// 舱门打开状态可以关闭
|
|
||||||
return coverState == CoverState.OPENED;
|
|
||||||
|
|
||||||
case ENTER_DEBUG_MODE:
|
|
||||||
// 在线状态且未处于调试模式时可以进入调试模式
|
|
||||||
return airportState == AirportState.ONLINE &&
|
|
||||||
debugModeState == DebugModeState.UNKNOWN;
|
|
||||||
|
|
||||||
case EXIT_DEBUG_MODE:
|
|
||||||
// 调试模式可以退出
|
|
||||||
return debugModeState == DebugModeState.ENTERED;
|
|
||||||
|
|
||||||
case REBOOT_AIRPORT:
|
|
||||||
// 在线状态可以重启
|
|
||||||
return airportState == AirportState.ONLINE;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +71,6 @@ public class DjiVendorConfig implements VendorConfig {
|
||||||
availableCommands.add(commandType);
|
availableCommands.add(commandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return availableCommands;
|
return availableCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,56 +81,9 @@ public class DjiVendorConfig implements VendorConfig {
|
||||||
// 起飞命令
|
// 起飞命令
|
||||||
Transaction takeOffTransaction = new Transaction("起飞", CommandType.TAKE_OFF)
|
Transaction takeOffTransaction = new Transaction("起飞", CommandType.TAKE_OFF)
|
||||||
.root(new DjiTakeOffInstruction())
|
.root(new DjiTakeOffInstruction())
|
||||||
.setTimeout(90000);
|
.setTimeout(10000);
|
||||||
transactionMap.put(CommandType.TAKE_OFF, takeOffTransaction);
|
transactionMap.put(CommandType.TAKE_OFF, takeOffTransaction);
|
||||||
|
|
||||||
// 返航命令
|
|
||||||
Transaction returnHomeTransaction = new Transaction("返航", CommandType.RETURN_HOME)
|
|
||||||
.root(new DjiReturnHomeInstruction())
|
|
||||||
.setTimeout(120000);
|
|
||||||
transactionMap.put(CommandType.RETURN_HOME, returnHomeTransaction);
|
|
||||||
|
|
||||||
// 急停命令
|
|
||||||
Transaction emergencyStopTransaction = new Transaction("急停", CommandType.EMERGENCY_STOP)
|
|
||||||
.root(new DjiEmergencyStopInstruction())
|
|
||||||
.setTimeout(30000);
|
|
||||||
transactionMap.put(CommandType.EMERGENCY_STOP, emergencyStopTransaction);
|
|
||||||
|
|
||||||
// 继续飞行命令
|
|
||||||
Transaction resumeFlightTransaction = new Transaction("继续飞行", CommandType.RESUME_FLIGHT)
|
|
||||||
.root(new DjiResumeFlightInstruction())
|
|
||||||
.setTimeout(60000);
|
|
||||||
transactionMap.put(CommandType.RESUME_FLIGHT, resumeFlightTransaction);
|
|
||||||
|
|
||||||
// 指点飞行命令
|
|
||||||
Transaction pointFlyTransaction = new Transaction("指点飞行", CommandType.POINT_FLY)
|
|
||||||
.root(new DjiPointFlyInstruction())
|
|
||||||
.setTimeout(90000);
|
|
||||||
transactionMap.put(CommandType.POINT_FLY, pointFlyTransaction);
|
|
||||||
|
|
||||||
// 取消指点命令
|
|
||||||
Transaction cancelPointTransaction = new Transaction("取消指点", CommandType.CANCEL_POINT)
|
|
||||||
.root(new DjiCancelPointInstruction())
|
|
||||||
.setTimeout(30000);
|
|
||||||
transactionMap.put(CommandType.CANCEL_POINT, cancelPointTransaction);
|
|
||||||
|
|
||||||
// 开始航线任务命令
|
|
||||||
Transaction startMissionTransaction = new Transaction("开始航线任务", CommandType.START_MISSION)
|
|
||||||
.root(new DjiStartMissionInstruction())
|
|
||||||
.setTimeout(120000);
|
|
||||||
transactionMap.put(CommandType.START_MISSION, startMissionTransaction);
|
|
||||||
|
|
||||||
// 打开舱门命令
|
|
||||||
Transaction openCoverTransaction = new Transaction("打开舱门", CommandType.OPEN_COVER)
|
|
||||||
.root(new DjiOpenCoverInstruction())
|
|
||||||
.setTimeout(60000);
|
|
||||||
transactionMap.put(CommandType.OPEN_COVER, openCoverTransaction);
|
|
||||||
|
|
||||||
// 关闭舱门命令
|
|
||||||
Transaction closeCoverTransaction = new Transaction("关闭舱门", CommandType.CLOSE_COVER)
|
|
||||||
.root(new DjiCloseCoverInstruction())
|
|
||||||
.setTimeout(60000);
|
|
||||||
transactionMap.put(CommandType.CLOSE_COVER, closeCoverTransaction);
|
|
||||||
|
|
||||||
log.info("大疆厂家配置初始化完成,共配置{}个命令", transactionMap.size());
|
log.info("大疆厂家配置初始化完成,共配置{}个命令", transactionMap.size());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ public class DjiCancelPointInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("cancelPoint")
|
.expectedValue("cancelPoint")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(10000)
|
.timeoutMs(10000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +46,6 @@ public class DjiCancelPointInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/state")
|
.topic("dji/" + sn + "/state")
|
||||||
.fieldPath("droneState")
|
.fieldPath("droneState")
|
||||||
.expectedValue("POINT_CANCELLED")
|
.expectedValue("POINT_CANCELLED")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(30000)
|
.timeoutMs(30000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ public class DjiCloseCoverInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("closeCover")
|
.expectedValue("closeCover")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(10000)
|
.timeoutMs(10000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +46,6 @@ public class DjiCloseCoverInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/state")
|
.topic("dji/" + sn + "/state")
|
||||||
.fieldPath("coverState")
|
.fieldPath("coverState")
|
||||||
.expectedValue("CLOSED")
|
.expectedValue("CLOSED")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(60000)
|
.timeoutMs(60000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ public class DjiEmergencyStopInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("emergencyStop")
|
.expectedValue("emergencyStop")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(5000)
|
.timeoutMs(5000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +49,6 @@ public class DjiEmergencyStopInstruction extends AbstractInstruction {
|
||||||
// 急停状态可能是 EMERGENCY_STOP 或 RETURN_EMERGENCY_STOP
|
// 急停状态可能是 EMERGENCY_STOP 或 RETURN_EMERGENCY_STOP
|
||||||
return "EMERGENCY_STOP".equals(state) || "RETURN_EMERGENCY_STOP".equals(state);
|
return "EMERGENCY_STOP".equals(state) || "RETURN_EMERGENCY_STOP".equals(state);
|
||||||
})
|
})
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(30000)
|
.timeoutMs(30000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ public class DjiLandInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("land")
|
.expectedValue("land")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(10000)
|
.timeoutMs(10000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +47,6 @@ public class DjiLandInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/state")
|
.topic("dji/" + sn + "/state")
|
||||||
.fieldPath("droneState")
|
.fieldPath("droneState")
|
||||||
.expectedValue("PREPARING")
|
.expectedValue("PREPARING")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(60000)
|
.timeoutMs(60000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ public class DjiOpenCoverInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("openCover")
|
.expectedValue("openCover")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(10000)
|
.timeoutMs(10000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +46,6 @@ public class DjiOpenCoverInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/state")
|
.topic("dji/" + sn + "/state")
|
||||||
.fieldPath("coverState")
|
.fieldPath("coverState")
|
||||||
.expectedValue("OPENED")
|
.expectedValue("OPENED")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(60000)
|
.timeoutMs(60000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ public class DjiPointFlyInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("pointFly")
|
.expectedValue("pointFly")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(10000)
|
.timeoutMs(10000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +51,6 @@ public class DjiPointFlyInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/state")
|
.topic("dji/" + sn + "/state")
|
||||||
.fieldPath("droneState")
|
.fieldPath("droneState")
|
||||||
.expectedValue("POINT_FLYING")
|
.expectedValue("POINT_FLYING")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(30000)
|
.timeoutMs(30000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ public class DjiResumeFlightInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("resumeFlight")
|
.expectedValue("resumeFlight")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(10000)
|
.timeoutMs(10000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +49,6 @@ public class DjiResumeFlightInstruction extends AbstractInstruction {
|
||||||
// 继续飞行后可能变为 FLYING 或 RETURNING
|
// 继续飞行后可能变为 FLYING 或 RETURNING
|
||||||
return "FLYING".equals(state) || "RETURNING".equals(state);
|
return "FLYING".equals(state) || "RETURNING".equals(state);
|
||||||
})
|
})
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(30000)
|
.timeoutMs(30000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ public class DjiReturnHomeInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("returnHome")
|
.expectedValue("returnHome")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(10000)
|
.timeoutMs(10000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +46,6 @@ public class DjiReturnHomeInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/state")
|
.topic("dji/" + sn + "/state")
|
||||||
.fieldPath("droneState")
|
.fieldPath("droneState")
|
||||||
.expectedValue("RETURNING")
|
.expectedValue("RETURNING")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(60000)
|
.timeoutMs(60000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ public class DjiStartMissionInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("cmd")
|
||||||
.expectedValue("startMission")
|
.expectedValue("startMission")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(10000)
|
.timeoutMs(10000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +48,6 @@ public class DjiStartMissionInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/state")
|
.topic("dji/" + sn + "/state")
|
||||||
.fieldPath("droneState")
|
.fieldPath("droneState")
|
||||||
.expectedValue("FLYING")
|
.expectedValue("FLYING")
|
||||||
.canShortCircuit(false)
|
|
||||||
.timeoutMs(60000)
|
.timeoutMs(60000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,20 +32,21 @@ public class DjiTakeOffInstruction extends AbstractInstruction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CallbackConfig getMethodCallbackConfig(InstructionContext context) {
|
public CallbackConfig getMethodCallbackConfig(InstructionContext context) {
|
||||||
|
// return null;
|
||||||
String sn = context.getSn();
|
String sn = context.getSn();
|
||||||
|
|
||||||
// 方法回调:等待起飞指令的ACK响应
|
// 方法回调:等待起飞指令的ACK响应
|
||||||
return CallbackConfig.builder()
|
return CallbackConfig.builder()
|
||||||
.topic("dji/" + sn + "/response")
|
.topic("dji/" + sn + "/response")
|
||||||
.fieldPath("cmd")
|
.fieldPath("data.result")
|
||||||
.expectedValue("takeoff")
|
.expectedValue("takeoff")
|
||||||
.canShortCircuit(false) // 不可短路,必须等待响应
|
|
||||||
.timeoutMs(10000) // 10秒超时
|
.timeoutMs(10000) // 10秒超时
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CallbackConfig getStateCallbackConfig(InstructionContext context) {
|
public CallbackConfig getStateCallbackConfig(InstructionContext context) {
|
||||||
|
// return null;
|
||||||
String sn = context.getSn();
|
String sn = context.getSn();
|
||||||
|
|
||||||
// 状态回调:等待无人机状态变为飞行中
|
// 状态回调:等待无人机状态变为飞行中
|
||||||
|
|
@ -53,13 +54,12 @@ public class DjiTakeOffInstruction extends AbstractInstruction {
|
||||||
.topic("dji/" + sn + "/state")
|
.topic("dji/" + sn + "/state")
|
||||||
.fieldPath("droneState")
|
.fieldPath("droneState")
|
||||||
.expectedValue("FLYING")
|
.expectedValue("FLYING")
|
||||||
.canShortCircuit(false) // 不可短路,必须等待状态变化
|
.timeoutMs(10000) // 10秒超时
|
||||||
.timeoutMs(60000) // 60秒超时
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTimeoutMs() {
|
public long getTimeoutMs() {
|
||||||
return 90000; // 90秒总超时
|
return 10000; // 10秒总超时
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,25 @@
|
||||||
package com.tuoheng.old;
|
package com.tuoheng.old;
|
||||||
|
|
||||||
import com.tuoheng.old.events.DrcEvent;
|
import com.tuoheng.machine.MachineCommandManager;
|
||||||
import com.tuoheng.old.service.DrcMachineService;
|
import com.tuoheng.machine.command.CommandResult;
|
||||||
import com.tuoheng.old.status.DrcState;
|
import com.tuoheng.machine.command.CommandType;
|
||||||
|
import com.tuoheng.machine.mqtt.MqttCallbackRegistry;
|
||||||
|
import com.tuoheng.machine.state.*;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.statemachine.StateMachine;
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DRC状态机测试
|
* DRC状态机测试
|
||||||
|
|
@ -15,71 +27,165 @@ import org.springframework.statemachine.StateMachine;
|
||||||
*/
|
*/
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
public class DrcStateMachineTest {
|
public class DrcStateMachineTest {
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
DrcMachineService drcMachineService;
|
MachineCommandManager machineCommandManager;
|
||||||
|
|
||||||
@Test
|
@Autowired
|
||||||
public void testDrcMachineService(){
|
MqttCallbackRegistry mqttCallbackRegistry;
|
||||||
|
|
||||||
String sn = "airport-001";
|
private static final ScheduledExecutorService scheduler =
|
||||||
/**
|
Executors.newScheduledThreadPool(2);
|
||||||
* 不存在的会报错,需要在 MachinePlatTypeRepository 里面定义有这个机场编号
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
StateMachine<DrcState, DrcEvent> stateMachine =
|
|
||||||
drcMachineService.getOrCreateStateMachine("airport-001--2");
|
|
||||||
}catch (RuntimeException runtimeException){}
|
|
||||||
|
|
||||||
StateMachine<DrcState, DrcEvent> stateMachine = drcMachineService.getStateMachine("airport-001");
|
|
||||||
drcMachineService.getOrCreateStateMachine("airport-001");
|
|
||||||
stateMachine = drcMachineService.getStateMachine("airport-001");
|
|
||||||
|
|
||||||
/**
|
private Boolean initState = false;
|
||||||
* 打印一下当前的状态
|
|
||||||
*/
|
|
||||||
log.debug(drcMachineService.getCurrentStates("airport-001"));
|
|
||||||
|
|
||||||
/**
|
private static final String SN = "SN9527";
|
||||||
* 从UnKnown状态可以走到任意状态
|
|
||||||
*/
|
|
||||||
drcMachineService.sendEvent(sn,DrcEvent.ENTERED);
|
|
||||||
|
|
||||||
/**
|
@BeforeEach
|
||||||
* ENTERED无法进入ENTERING DrcMachineConfig 里面配置的
|
public void init(){
|
||||||
*/
|
if(initState){
|
||||||
log.debug(String.valueOf(drcMachineService.sendEvent(sn,DrcEvent.ENTERING)));
|
return;
|
||||||
|
}
|
||||||
/**
|
initState = true;
|
||||||
* 现在是 ENTERED,但是你还想进入ENTERED ,这个是不可以的
|
machineCommandManager.bindMachine(SN,"DJI");
|
||||||
*/
|
|
||||||
log.debug(String.valueOf(drcMachineService.sendEvent(sn,DrcEvent.ENTERED)));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印一下当前的状态
|
|
||||||
*/
|
|
||||||
log.debug(drcMachineService.getCurrentStates("airport-001"));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 变成退出中;这个时候需要在
|
|
||||||
* DjiCanExitGuard 判断是否可以执行
|
|
||||||
* DjiExitAction 执行远程方法,远程方法本身执行成功则不抛出异常,否则抛出异常
|
|
||||||
*/
|
|
||||||
log.debug(String.valueOf(drcMachineService.sendEvent(sn,DrcEvent.EXITING)));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印一下当前的状态
|
|
||||||
* 修改 stateContext 里面的实现,就可以跳过某些状态
|
|
||||||
*/
|
|
||||||
log.debug(drcMachineService.getCurrentStates("airport-001"));
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
// log.debug(String.valueOf(drcMachineService.sendEvent(sn,DrcEvent.EXITED)));
|
|
||||||
//
|
|
||||||
// log.debug(drcMachineService.getCurrentStates("airport-001"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
public void checkInitState(){
|
||||||
|
MachineStates machineStates = machineCommandManager.getMachineStates(SN);
|
||||||
|
assertNotNull(machineStates);
|
||||||
|
assertEquals(AirportState.UNKNOWN, machineStates.getAirportState());
|
||||||
|
assertEquals(DrcState.UNKNOWN, machineStates.getDrcState());
|
||||||
|
assertEquals(CoverState.UNKNOWN, machineStates.getCoverState());
|
||||||
|
assertEquals(DroneState.UNKNOWN, machineStates.getDroneState());
|
||||||
|
assertEquals(StopState.UNKNOWN, machineStates.getStopState());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 非在线状态下不可起飞
|
||||||
|
* @throws ExecutionException
|
||||||
|
* @throws InterruptedException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
public void checkTakeOffCommand() throws ExecutionException, InterruptedException {
|
||||||
|
CompletableFuture<CommandResult> future =
|
||||||
|
machineCommandManager.executeCommand(SN, CommandType.TAKE_OFF,new HashMap<>());
|
||||||
|
assertFalse(future.get().isSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(3)
|
||||||
|
public void setState() {
|
||||||
|
|
||||||
|
MachineStates machineStates = new MachineStates();
|
||||||
|
machineStates.setAirportState(AirportState.ONLINE);
|
||||||
|
machineStates.setDroneState(DroneState.ONLINE);
|
||||||
|
machineCommandManager.updateMachineStates(SN, machineStates);
|
||||||
|
|
||||||
|
machineStates = machineCommandManager.getMachineStates(SN);
|
||||||
|
assertNotNull(machineStates);
|
||||||
|
assertEquals(AirportState.ONLINE, machineStates.getAirportState());
|
||||||
|
assertEquals(DroneState.ONLINE, machineStates.getDroneState());
|
||||||
|
assertEquals(DrcState.UNKNOWN, machineStates.getDrcState());
|
||||||
|
assertEquals(CoverState.UNKNOWN, machineStates.getCoverState());
|
||||||
|
assertEquals(StopState.UNKNOWN, machineStates.getStopState());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
// @Order(4)
|
||||||
|
// public void checkTakeOffOverTime1() throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
// /**
|
||||||
|
// * 指令执行超时;因为缺乏指令成功的回调
|
||||||
|
// */
|
||||||
|
// CompletableFuture<CommandResult> future =
|
||||||
|
// machineCommandManager.executeCommand(SN, CommandType.TAKE_OFF,new HashMap<>());
|
||||||
|
// assertFalse(future.get().isSuccess());
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令执行成功,因为mqttCallbackRegistry模拟了发送回调
|
||||||
|
* 需要将 DjiTakeOffInstruction 的 getStateCallbackConfig 中直接返回null
|
||||||
|
*/
|
||||||
|
// @Test
|
||||||
|
// @Order(5)
|
||||||
|
// public void checkTakeOffOverTime2() throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
//
|
||||||
|
// CompletableFuture<CommandResult> future =
|
||||||
|
// machineCommandManager.executeCommand(SN, CommandType.TAKE_OFF,new HashMap<>());
|
||||||
|
//
|
||||||
|
// scheduler.schedule(new Runnable() {
|
||||||
|
// @Override
|
||||||
|
// public void run() {
|
||||||
|
// String response = "{\"data\":{\"result\":\"takeoff\"}}";
|
||||||
|
// mqttCallbackRegistry.handleMessage("dji/SN9527/response",response);
|
||||||
|
// }
|
||||||
|
// },100,TimeUnit.MILLISECONDS);
|
||||||
|
//
|
||||||
|
// assertTrue(future.get().isSuccess());
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令执行失败
|
||||||
|
* 需要将 DjiTakeOffInstruction 的 getStateCallbackConfig 中的注释放开
|
||||||
|
*/
|
||||||
|
// @Test
|
||||||
|
// @Order(5)
|
||||||
|
// public void checkTakeOffOverTime2() throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
//
|
||||||
|
// CompletableFuture<CommandResult> future =
|
||||||
|
// machineCommandManager.executeCommand(SN, CommandType.TAKE_OFF,new HashMap<>());
|
||||||
|
//
|
||||||
|
// scheduler.schedule(new Runnable() {
|
||||||
|
// @Override
|
||||||
|
// public void run() {
|
||||||
|
// String response = "{\"data\":{\"result\":\"takeoff\"}}";
|
||||||
|
// mqttCallbackRegistry.handleMessage("dji/SN9527/response",response);
|
||||||
|
// }
|
||||||
|
// },100,TimeUnit.MILLISECONDS);
|
||||||
|
//
|
||||||
|
// assertFalse(future.get().isSuccess());
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要将 DjiTakeOffInstruction 的 getStateCallbackConfig 中的注释放开
|
||||||
|
* @throws ExecutionException
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @throws TimeoutException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Order(5)
|
||||||
|
public void checkTakeOffOverTime2() throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
|
||||||
|
CompletableFuture<CommandResult> future =
|
||||||
|
machineCommandManager.executeCommand(SN, CommandType.TAKE_OFF,new HashMap<>());
|
||||||
|
|
||||||
|
scheduler.schedule(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String response = "{\"data\":{\"result\":\"takeoff\"}}";
|
||||||
|
mqttCallbackRegistry.handleMessage("dji/SN9527/response",response);
|
||||||
|
|
||||||
|
// 添加延迟,等待状态回调监听器注册
|
||||||
|
try {
|
||||||
|
Thread.sleep(50); // 等待50ms
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
response = "{\"droneState\":\"FLYING\"}";
|
||||||
|
mqttCallbackRegistry.handleMessage("dji/SN9527/state",response);
|
||||||
|
}
|
||||||
|
},100,TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
assertTrue(future.get().isSuccess());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue