[v0.0.1] 后端联调问题修改

master
shiyi 2 months ago
parent 9678a959ec
commit 6f4711ff8d

@ -90,7 +90,7 @@ public class RemoteService {
UavTypeEnum uavType = UavTypeEnum.getByRemoteCode(mapping.getUavType());
// DONE 2024/6/26: 记录所有型号的飞机映射
UavIdMap.addMap(uavType, Integer.parseInt(mapping.getFlightControlSn()), mapping.getUavId());
HaborUavMap.addMap(mapping.getUavId(), mapping.getHarborSn());
HaborUavMap.addMap(mapping.getUavId(), mapping.getHaborSn());
});
log.info("直控无人机参数映射关系: {}", directControlUavParamList);
}

@ -46,10 +46,13 @@ public class CacConnectionHandler extends ChannelInboundHandlerAdapter {
int port = ipSocket.getPort();
String host = ipSocket.getHostString();
log.info("与中心指控{}:{}建立tcp连接!", host, port);
log.info("地面站发送上线请求");
if (gcsService.gcsSignInRequest()) {
gcsService.gcsAuthRequestToCtrl();
}
ctx.channel().eventLoop().schedule(() -> {
log.info("地面站发送上线请求");
if (gcsService.gcsSignInRequest()) {
gcsService.gcsAuthRequestToCtrl();
}
},
1, TimeUnit.SECONDS);
log.debug("connect-channel: {}", ctx.channel());
ctx.fireChannelActive();
}

@ -35,6 +35,11 @@ public class CacUavCommandIssuedHandler implements IRemoteMessageHandler {
log.error("[cac] 中心指控控制指令下发失败未找到UavId={}对应的哈勃编号", uavId);
return;
}
HaborClient client = (HaborClient) ClientManager.getClient(haborSn);
if (client == null) {
log.error("[cac] 中心指控参数装订指令下发失败,哈勃编号={}对应的客户端未上线", haborSn);
return;
}
byte[] uavCommandCodeId = uavCommand.getUavCommandCodeId();
if (uavCommandCodeId.length!=1) {
log.error("[cac] 中心指控控制指令下发失败,指令码长度错误:{}", ByteUtils.bytes2HexString(uavCommandCodeId));
@ -42,7 +47,7 @@ public class CacUavCommandIssuedHandler implements IRemoteMessageHandler {
}
String uavControlUniId = uavCommand.getUavControlUniId();
log.info("[cac] 中心指控下发控制指令...{}", uavCommand);
HaborClient client = (HaborClient) ClientManager.getClient(haborSn);
client.writeControlCommand(uavCommandCodeId[0], uavControlUniId);
} else {
log.warn("[cac] 当前服务未连接中心指控无法下发控制指令");

@ -38,38 +38,30 @@ public class CacUavParamBindHandler implements IRemoteMessageHandler {
log.error("[cac] 中心指控参数装订指令下发失败未找到UavId={}对应的哈勃编号", uavId);
return;
}
HaborClient client = (HaborClient) ClientManager.getClient(haborSn);
if (client == null) {
log.error("[cac] 中心指控参数装订指令下发失败,哈勃编号={}对应的客户端未上线", haborSn);
return;
}
byte commandCode = uavCommand.getCommandCode();
byte[] commandContent = uavCommand.getCommandContent();
byte[] command14_29 = new byte[16];
command14_29[0] = commandCode;
System.arraycopy(commandContent, 0, command14_29, 1, 15);
if (Arrays.equals(uavCommand.getCrc16(), CRCUtil.getCRCfromGcsTelemetryData(command14_29, 0, 16))) {
if (!Arrays.equals(uavCommand.getCrc16(), CRCUtil.getCRCfromGcsTelemetryData(command14_29, 0, 16))) {
log.error("[cac] 中心指控参数装订指令下发失败CRC校验失败");
return;
}
String uavControlUniId = uavCommand.getUavControlUniId();
log.info("[cac] 中心指控下发参数装订指令...{}", uavCommand);
HaborClient client = (HaborClient) ClientManager.getClient(haborSn);
client.writeParamBindCommand(commandCode, commandContent, uavControlUniId);
} else {
log.warn("[cac] 当前服务未连接中心指控无法下发参数装订指令");
}
}
/**
*
* @param uavCommand
*/
private void queryUavCommandResult(CacUavParamBindMessage uavCommand) {
// String uavId = uavCommand.getUavId();
// int fkUavId = UavIdMap.getFkId(uavId);
// ByteBuf bufToGcs = Unpooled.buffer();
// bufToGcs.writeByte((byte) fkUavId);
// bufToGcs.writeByte(uavCommand.getUavCommandCodeIdLength());
// bufToGcs.writeBytes(uavCommand.getUavCommandCodeId());
// gcsService.sendToGcs(GcsFrameEnum.QUERY_COMMAND.getCode(), bufToGcs);
}
@Override
public RemoteFrameEnum getFrameType() {
return RemoteFrameEnum.UAV_COMMAND_QUERY;
return RemoteFrameEnum.UAV_PARAM_BIND;
}
}

@ -37,6 +37,11 @@ public class CacUavParamQueryHandler implements IRemoteMessageHandler {
log.error("[cac] 中心指控参数查询指令下发失败未找到UavId={}对应的哈勃编号", uavId);
return;
}
HaborClient client = (HaborClient) ClientManager.getClient(haborSn);
if (client == null) {
log.error("[cac] 中心指控参数装订指令下发失败,哈勃编号={}对应的客户端未上线", haborSn);
return;
}
byte commandCode = uavCommand.getCommandCode();
byte[] commandContent = uavCommand.getCommandContent();
byte[] command14_29 = new byte[16];
@ -48,7 +53,7 @@ public class CacUavParamQueryHandler implements IRemoteMessageHandler {
}
String uavControlUniId = uavCommand.getUavControlUniId();
log.info("[cac] 中心指控下发参数查询指令...{}", uavCommand);
HaborClient client = (HaborClient) ClientManager.getClient(haborSn);
client.writeParamQueryCommand(commandCode, commandContent, uavControlUniId);
} else {
log.warn("[cac] 当前服务未连接中心指控无法下发参数查询指令");
@ -57,6 +62,6 @@ public class CacUavParamQueryHandler implements IRemoteMessageHandler {
@Override
public RemoteFrameEnum getFrameType() {
return RemoteFrameEnum.UAV_COMMAND_QUERY;
return RemoteFrameEnum.UAV_PARAM_QUERY;
}
}

@ -40,6 +40,11 @@ public class CacUavRouteBindHandler implements IRemoteMessageHandler {
log.error("[cac] 中心指控航线装订指令下发失败未找到UavId={}对应的哈勃编号", uavId);
return;
}
HaborClient client = (HaborClient) ClientManager.getClient(haborSn);
if (client == null) {
log.error("[cac] 中心指控参数装订指令下发失败,哈勃编号={}对应的客户端未上线", haborSn);
return;
}
byte commandCode = uavCommand.getCommandCode();
byte routePointNum = uavCommand.getRoutePointNum();
byte[] routePointInfo = uavCommand.getRoutePointInfo(); // 16 * routePointNum 个字节
@ -49,7 +54,6 @@ public class CacUavRouteBindHandler implements IRemoteMessageHandler {
}
String uavControlUniId = uavCommand.getUavControlUniId();
log.info("[cac] 中心指控下发航线装订指令...{}", uavCommand);
HaborClient client = (HaborClient) ClientManager.getClient(haborSn);
List<byte[]> routeInfoList = new ArrayList<>();
for (int i = 0; i < routePointNum; i++) {
routeInfoList.add(Arrays.copyOfRange(routePointInfo, i * 16, (i + 1) * 16));
@ -59,21 +63,9 @@ public class CacUavRouteBindHandler implements IRemoteMessageHandler {
log.warn("[cac] 当前服务未连接中心指控无法下发航线装订指令");
}
}
/**
*
* @param uavCommand
*/
private void queryUavCommandResult(CacUavParamBindMessage uavCommand) {
// String uavId = uavCommand.getUavId();
// int fkUavId = UavIdMap.getFkId(uavId);
// ByteBuf bufToGcs = Unpooled.buffer();
// bufToGcs.writeByte((byte) fkUavId);
// bufToGcs.writeByte(uavCommand.getUavCommandCodeIdLength());
// bufToGcs.writeBytes(uavCommand.getUavCommandCodeId());
// gcsService.sendToGcs(GcsFrameEnum.QUERY_COMMAND.getCode(), bufToGcs);
}
@Override
public RemoteFrameEnum getFrameType() {
return RemoteFrameEnum.UAV_COMMAND_QUERY;
return RemoteFrameEnum.UAV_ROUTE_BIND;
}
}

@ -23,8 +23,7 @@ public enum RemoteFrameEnum {
FLIGHT_PLAN_REVOKE_REQUEST((byte) 0x0D, "飞行计划撤销通知"),
FLIGHT_PLAN_REVOKE_RESPONSE((byte) 0x0E, "飞行计划撤销响应"),
UAV_TELEMETRY_DATA_TRANSFER((byte) 0x0F, "无人机遥测数据透传"),
AIRSPACE_REPLY_REQUEST((byte) 0x1A, "空域申请结果通知"),
AIRSPACE_REPLY_RESPONSE((byte) 0x1B, "空域申请结果收到响应"),
// 中心指控
UAV_CONTROL_APPLY((byte) 0x10, "申请无人机控制权"),
UAV_CONTROL_REPLY((byte) 0x11, "回复无人机控制权"),
@ -39,8 +38,13 @@ public enum RemoteFrameEnum {
AIRPORT_STATE_OF_CHARGE_QUERY((byte)0x18, "电格电量查询"),
AIRPORT_CONTAINER_STATUS_QUERY((byte)0x19, "货格状态查询"),
// 推流地址
STREAM_PUSH((byte) 0x21, "推流地址");
AIRSPACE_REPLY_REQUEST((byte) 0x1A, "空域申请结果通知"),
AIRSPACE_REPLY_RESPONSE((byte) 0x1B, "空域申请结果收到响应"),
UAV_PARAM_BIND((byte) 0x2A, "无人机参数装订"),
UAV_PARAM_QUERY((byte) 0x2B, "无人机参数查询"),
UAV_ROUTE_BIND((byte) 0x2C, "无人机航线装订"),
;
private final byte code;

@ -4,7 +4,7 @@ import lombok.Data;
@Data
public class DirectControlUavParam {
String harborSn;
String haborSn;
String flightControlSn;
String uavId;
Integer uavType;

@ -25,9 +25,8 @@ public class CacDataRouterHandler extends SimpleChannelInboundHandler<ByteBuf> {
if (client == null || client.getClientType() != ClientTypeEnum.HABOR) {
return;
}
log.info("数据({}bytes): {}", msg.readableBytes(), ByteBufUtil.hexDump(msg));
// log.debug("[cac] {} 收到数据({}bytes): {}", ((HaborClient) client).shortInfo(), msg.readableBytes(), ByteBufUtil.hexDump(msg));
HaborClient haborClient = (HaborClient) client;
haborClient.process(msg);
haborClient.sendToCac(msg.retain()); // SimpleChannelInboundHandler会自动release msg, 所以这里需要retain一次
}
}

@ -23,6 +23,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Objects;
@ -66,17 +68,34 @@ public class InMessageHandler extends ChannelInboundHandlerAdapter {
IdleStateEvent event = (IdleStateEvent) obj;
IdleState state = event.state();
if (state == IdleState.ALL_IDLE) {
//设备离线,更改设备状态
log.warn("【客户端" + ctx.channel().remoteAddress() + "进入idle状态】");
ChannelFuture future = ctx.channel().close();
if (!future.isSuccess()) {
log.warn("【客户端异常关闭】", future.cause());
BaseClient client = ClientManager.getClient(ctx.channel());
if (client != null) {
//设备离线,更改设备状态
log.warn("【客户端" + ctx.channel().remoteAddress() + "进入idle状态】");
ChannelFuture future = ctx.channel().close();
if (!future.isSuccess()) {
log.warn("【客户端异常关闭】", future.cause());
}
}
}
}
super.userEventTriggered(ctx, obj);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
// 获取对方ip和端口
InetSocketAddress remoteAddress = (InetSocketAddress) channel.remoteAddress();
// String haborSn = String.format("%06d", remoteAddress.getPort()); // 远端端口当作哈勃序列号
// try {
// haborSignIntoCac(haborSn, channel);
// } catch (Exception e) {
// log.error("哈勃上线失败, haborSn={}", haborSn, e);
// }
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg0) throws Exception {
String address = getAddress(ctx);
@ -84,8 +103,12 @@ public class InMessageHandler extends ChannelInboundHandlerAdapter {
// byte[] msg = (byte[])msg0; // TODO 2025/1/16:
ByteBuf msgBuf = (ByteBuf) msg0;
// /*
//上线握手阶段
if (!sessionCache.addToSnMap.containsKey(address)) { // 判断连接是否已经建立,如未建立则先握手
// if (msgBuf.getByte(0) != (byte) 0xAA || msgBuf.getByte(1) != (byte) 0x44) {
// return;
// }
byte[] msg = new byte[msgBuf.readableBytes()];
msgBuf.readBytes(msg);
log.info("【接收握手原数据】 " + ByteUtils.bytes2HexString(msg));
@ -104,7 +127,7 @@ public class InMessageHandler extends ChannelInboundHandlerAdapter {
String deviceCode;
String typeName;
if(type.equals("1")) {
// 首先读取deviceCode 哈勃deviceCode是前面6个byte
// 首先读取deviceCode 哈勃deviceCode是6个byte
typeName = "地面站";
deviceCode = new String(msg, 6, 12, Charset.defaultCharset()).toUpperCase(); // 地面站
protocolAck(ctx, (byte)1);
@ -135,7 +158,7 @@ public class InMessageHandler extends ChannelInboundHandlerAdapter {
return; //握手结束立即返回
}
// */
/*
// NOTE 2025/1/17: 线上版本的逻辑没有在控无人机更新
else {
@ -169,6 +192,7 @@ public class InMessageHandler extends ChannelInboundHandlerAdapter {
*/
// /*
// 已经建立连接且非地面站控制信息,则进行数据转发
else {
if (debug) {
@ -198,30 +222,31 @@ public class InMessageHandler extends ChannelInboundHandlerAdapter {
log.debug("out channel: {} ({})即将发送 --- from channel: {} ({})", sendChannel.remoteAddress(), sessionCache.addToSnMap.get(sendChannel.remoteAddress().toString().replace("/", "")), ctx.channel().remoteAddress(), sn);
// 如果需要发送则增加一次计数引用便于中心指控继续使用buffer
sendChannel.writeAndFlush(msgBuf.retain());
/*
// NOTE 2025/1/17: 线上版本的逻辑没有在控无人机更新, 这里也不再判断飞控的控制关系,直接转发
String sendIp = sessionCache.findSnByChannel(sendChannel); // 通道找到IP
String sendSn = sessionCache.addToSnMap.get(sendIp); // IP找到设备编号
if (sendSn.length() == 6) {
// 发送给哈勃
List<String> devices = ControlDevice.getCurrenCtrDevicesByMac(sn);
if (devices.contains(sendSn) || devices.contains("all")) {
msgBuf.retain();
sendChannel.writeAndFlush(msgBuf.retain());
}
}
if (sendSn.length() == 12) {
// 发送给地面站
sendChannel.writeAndFlush(msgBuf.retain());
return;
}
*/
// String sendIp = sessionCache.findSnByChannel(sendChannel); // 通道找到IP
// String sendSn = sessionCache.addToSnMap.get(sendIp); // IP找到设备编号
// if (sendSn.length() == 6) {
// // 发送给哈勃
// List<String> devices = ControlDevice.getCurrenCtrDevicesByMac(sn);
// if (devices.contains(sendSn) || devices.contains("all")) {
// msgBuf.retain();
// sendChannel.writeAndFlush(msgBuf.retain());
// }
// }
// if (sendSn.length() == 12) {
// // 发送给地面站
// sendChannel.writeAndFlush(msgBuf.retain());
// return;
// }
});
}
// else {
// super.channelRead(ctx, msgBuf);
// }
}
// */
/* String sn = global.addToSnMap.get(address);
if (!global.snList.isEmpty()){
if (global.snList.contains(sn)){
@ -251,10 +276,12 @@ public class InMessageHandler extends ChannelInboundHandlerAdapter {
BaseClient client = ClientManager.getClient(ctx.channel());
if (client == null || client.getClientType() != ClientTypeEnum.HABOR) {
if (msgBuf.refCnt() !=0 ) msgBuf.release(msgBuf.refCnt());
return;
} else {
if (msgBuf.refCnt() == 1) msgBuf.retain();
// 以上是哈勃原来的处理逻辑,完成之后向下游传递,进入中心指控的处理逻辑
ctx.channel().writeAndFlush(msgBuf.retain()); // 模拟转发过程
// ctx.channel().writeAndFlush(msgBuf.retain()); // 模拟转发过程
ctx.fireChannelRead(msg0);
}
@ -262,24 +289,28 @@ public class InMessageHandler extends ChannelInboundHandlerAdapter {
/**接入中心指控系统, 上线*/
private void haborSignIntoCac(String haborSn, Channel channel) {
UavTypeEnum uavType = UavTypeEnum.FP981A;
String uavId = "5";
UavIdMap.addMap(uavType, 1, uavId);
HaborUavMap.addMap(uavId, "23293F");
// if (!HaborUavMap.haborIsControllable(haborSn)) {
// DirectControlUavParam info = remoteService.queryCacDirectControlUavInfo(haborSn);// 缓存没查到就向中心指控查一遍,查不到就直接退出
// if (info == null) {
// log.info("[cac] 未查询到哈勃终端-{}的信息,跳过上线", haborSn);
// return;
// }
// }
// if (ClientManager.getClient(channel) != null) {
// // TODO 2025/1/17: 重复上线的如何处理
// return;
// }
// 新建哈勃客户端并加入管理
// UavIdMap.addMap(UavTypeEnum.FP981A, 1, "5");
// HaborUavMap.addMap("5", "23293F");
// UavIdMap.addMap(UavTypeEnum.FP981A, 2, "6");
// HaborUavMap.addMap("6", "040000");
// UavIdMap.addMap(UavTypeEnum.FP981A, 3, "3");
// HaborUavMap.addMap("7", "000777");
if (!HaborUavMap.haborIsControllable(haborSn)) {
DirectControlUavParam info = remoteService.queryCacDirectControlUavInfo(haborSn);// 缓存没查到就向中心指控查一遍,查不到就直接退出
if (info == null) {
log.info("[cac] 未查询到哈勃终端-{}的信息,跳过上线", haborSn);
return;
}
}
if (ClientManager.getClient(channel) != null) {
// TODO 2025/1/17: 重复上线的如何处理
return;
}
String uavId = HaborUavMap.getUavIdByHaborSn(haborSn);
UavTypeEnum uavType = UavIdMap.getUavType(uavId);
// 新建哈勃客户端并加入管理
HaborClient client = HaborClient.createClient(uavType, haborSn, channel);
if (client != null){
ClientManager.addAndOnline(client);

@ -7,6 +7,7 @@ import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -47,10 +48,10 @@ public class ServerService {
@Override
protected void initChannel(Channel channel) throws Exception {
// channel.pipeline().addLast(new ByteArrayDecoder()); // revise by shiyi: 解码移动到InMessageHandler中
// channel.pipeline().addLast(new ByteArrayEncoder());
channel.pipeline().addLast(new ByteArrayEncoder());
if (!config.isDebug()) {
channel.pipeline().addLast(new IdleStateHandler(0, 0,
60 * 24, TimeUnit.MINUTES));
5, TimeUnit.MINUTES));
}
channel.pipeline()
.addLast("OriginalHandler", inMessageHandler) // 原始哈勃消息解码器

@ -33,11 +33,10 @@ public class CommandRecord {
private AtomicInteger receiveFrameCount = new AtomicInteger(0); // 接收到的指令帧数, 150帧还未判断成功则判定为失败
// private long startTime = 0 ; // 接收到的指令帧数, 150帧还未判断成功则判定为失败
private final int MAX_RECEIVE_COUNT = 150; // 接收到的指令帧数, 150帧还未判断成功则判定为失败
private final long TIMEOUT_THRESHOLD = 5*1000; // 从下发超过5s未回报则判定为失败
private final long TIMEOUT_THRESHOLD = 30*1000; // 从下发超过5s未回报则判定为失败
protected int status;
public static final int FAILED = -1; // 指令失败
public static final int NO_COMMAND = 0; // 空闲
public static final int SUCCESS = 1; // 指令成功
public static final int WAITING_RESULT = 2; // 等待回报
// 定时任务管理
@ -60,18 +59,19 @@ public class CommandRecord {
this.commandUniId = uniId;
this.status = WAITING_RESULT;
this.receiveFrameCount.set(0);
// this.startTime = System.currentTimeMillis();
// 启动一个超时检查的定时任务
// this.timeoutFuture = scheduleTimeoutCheck();
//启动一个超时检查的定时任务
this.timeoutFuture = scheduleTimeoutCheck();
}
// 定时任务每5秒检查一次所有命令是否超时
private ScheduledFuture<?> scheduleTimeoutCheck() {
log.error("[cac] {} {}指令判断定时任务启动", client.shortInfo(), commandType.getInfo());
log.debug("[cac] {} {}指令判断定时任务启动", client.shortInfo(), commandType.getInfo());
// 每5秒检查一次所有命令记录的超时状态
return scheduler.schedule(() -> {
if (status == WAITING_RESULT) {
if (status != NO_COMMAND ) {
status = FAILED; // 标记超时为失败
log.error("[cac] {} {}指令超时", client.shortInfo(), commandType.getInfo());
switch (commandType) {
@ -87,6 +87,7 @@ public class CommandRecord {
case PARAM_QUERY:
this.notifyParamQueryCommandResult(client.uavId, client.uavType, false, null);
}
client.switchToCommonData(); // todo 需要优化尽量不要在里面用client的控制逻辑
}
}, TIMEOUT_THRESHOLD, TimeUnit.MILLISECONDS); // 设置延迟时间
}
@ -94,7 +95,7 @@ public class CommandRecord {
public void cancelScheduleTimeout() {
if (this.timeoutFuture != null && !this.timeoutFuture.isCancelled()) {
if (this.timeoutFuture.cancel(true)) {
log.info("[cac] {} 取消{}指令结果判断定时任务", client.shortInfo(), commandType.getInfo());
log.debug("[cac] {} 取消{}指令结果判断定时任务", client.shortInfo(), commandType.getInfo());
}
}
}
@ -149,7 +150,7 @@ public class CommandRecord {
}
}
public void notifyParamQueryCommandResult(String uavId, UavTypeEnum uavType, boolean isSuccess, HaborClient.UavTakeOffParamQueryResultParam uavTakeOffParamQueryResultParam) {
public void notifyParamQueryCommandResult(String uavId, UavTypeEnum uavType, boolean isSuccess, HaborClient.UavQueryResultParam uavQueryResultParam) {
Map<String, Object> body = new HashMap<>();
try {
body.put("gcsId", GlobalData.GCS_ID);
@ -160,7 +161,7 @@ public class CommandRecord {
body.put("uavParamQueryCode", ByteUtils.byteToInt(this.code));
body.put("bindResult", isSuccess);
if (isSuccess) {
String queryResultContent = uavTakeOffParamQueryResultParam.toJsonStr();
String queryResultContent = uavQueryResultParam.toJsonStr();
body.put("queryResultContent", queryResultContent);
}
CacHpApi.uavParamQueryResultNotify(JSONUtils.obj2json(body));

@ -138,11 +138,18 @@ public class HaborClient extends BaseClient {
/**只通过get读数不改变readerIndex和writerIndex, 也不可更改refCnt*/
public void process(ByteBuf msg) {
processInjectResponse(msg);
if (msg.getByte(0) != HEAD[0] && msg.getByte(1) != HEAD[1]) {
return; // 帧头错误,抛弃
}
if (!processInjectResponse(msg)) {
sendToCac(msg.retain()); // 外面SimpleChannelInboundHandler会自动release msg, 所以这里需要retain一次
}
}
/**注入回报帧处理*/
protected void processInjectResponse(ByteBuf msg) {}
protected boolean processInjectResponse(ByteBuf msg) {
return false;
}
/**发送常发帧*/
protected void writeCommonData() {}
@ -231,12 +238,13 @@ public class HaborClient extends BaseClient {
/**Cac回报参数具体定义见各型号子类*/
public static abstract class UavTakeOffParamQueryResultParam {
public static abstract class UavQueryResultParam {
public abstract String toJsonStr() throws IOException;
}
/**Cac起飞参数查询查询回报具体定义见各型号子类*/
public static abstract class UavTakeOffParamQueryResultParam extends UavQueryResultParam {}
/**Cac重量查询回报具体定义见各型号子类*/
public static abstract class UavWeightQueryResultParam extends UavQueryResultParam {}
protected static class DataByteBuf{
protected ByteBuf buf;
private AtomicInteger sendCount = new AtomicInteger(0);

@ -31,7 +31,7 @@ public class HaborClient981A extends HaborClient {
private static final byte[] UPPER_DATA_3_4 = new byte[]{0x02, 0x01};
/**常发数据内容被填入ByteBuf初始内容所有飞机共用, 禁止修改*/
private static final byte C0 = 0x01; // 空白数据自定义特征字
private static final byte C0 = 0x00; // 空白数据自定义特征字
private static final byte[] COMMON_DATA_14_29 = new byte[]{
0x21, C0, C0, C0, C0, // 14~29
C0, C0, C0, C0, C0,
@ -39,7 +39,7 @@ public class HaborClient981A extends HaborClient {
};
/**控制帧数据内容被填入ByteBuf初始内容*/
private static final byte C1 = 0x02; // 空白数据自定义特征字
private static final byte C1 = 0x00; // 空白数据自定义特征字
private static final byte[] CONTROL_DATA_14_29 = new byte[]{
0x21, C1, C1, C1, C1, // 14~29
C1, C1, C1, C1, C1,
@ -85,7 +85,7 @@ public class HaborClient981A extends HaborClient {
uavId = HaborUavMap.getUavIdByHaborSn(haborSn);
uavType = UavIdMap.getUavType(uavId);
fkId = (byte) UavIdMap.getFkId(uavId);
super.commonDataFreq = 1; // 发送频率, 每秒发送帧数
super.commonDataFreq = 5; // 发送频率, 每秒发送帧数
}
@Override
@ -184,26 +184,27 @@ public class HaborClient981A extends HaborClient {
dataBufToSend.addSendCount();
if (dataBufToSend instanceof CommonDataBuf) {
log.debug("[cac] {} 发送常发帧: {}", shortInfo(), ByteBufUtil.hexDump(dataBufToSend.buf));
// log.debug("[cac] {} 发送常发帧: {}", shortInfo(), ByteUtils.bytes2HexString(ByteBufUtil.getBytes()(dataBufToSend.buf)));
}
if (dataBufToSend instanceof ControlDataBuf) {
log.info("[cac] {} 发送控制指令: {}", shortInfo(), ByteBufUtil.hexDump(dataBufToSend.buf));
log.debug("[cac] {} 发送控制指令: {}", shortInfo(), ByteUtils.bytes2HexString(ByteBufUtil.getBytes(dataBufToSend.buf)));
if (dataBufToSend.getSendCount() >= ((ControlDataBuf) dataBufToSend).needCount) {
log.info("[cac] {} 控制指令发送完毕", shortInfo());
log.info("[cac] {} 控制指令发送完毕, {}", shortInfo(), ByteUtils.bytes2HexString(ByteBufUtil.getBytes(dataBufToSend.buf)));
//
switchToCommonData();
}
}
if (dataBufToSend instanceof QueryDataBuf) {
log.info("[cac] {} 发送查询指令: {}", shortInfo(), ByteBufUtil.hexDump(dataBufToSend.buf));
log.debug("[cac] {} 发送查询指令: {}", shortInfo(), ByteUtils.bytes2HexString(ByteBufUtil.getBytes(dataBufToSend.buf)));
}
if (dataBufToSend instanceof BindDataBuf) {
log.info("[cac] {} 发送参数装订指令: {}", shortInfo(), ByteBufUtil.hexDump(dataBufToSend.buf));
log.debug("[cac] {} 发送参数装订指令: {}", shortInfo(), ByteUtils.bytes2HexString(ByteBufUtil.getBytes(dataBufToSend.buf)));
}
if (dataBufToSend instanceof RouteDataBuf) {
log.info("[cac] {} 发送航线装订指令: {}", shortInfo(), ByteBufUtil.hexDump(dataBufToSend.buf));
log.debug("[cac] {} 发送航线装订指令: {}", shortInfo(), ByteUtils.bytes2HexString(ByteBufUtil.getBytes(dataBufToSend.buf)));
}
}
@ -286,31 +287,31 @@ public class HaborClient981A extends HaborClient {
writeRouteBindCommand0(commandCode, routeInfoList.get(0), controlUniId); //发送第一个节点
}
/**注入回报帧处理*/
/**注入回报帧处理, 如果正常处理返回true否则返回false继续透传*/
@Override
protected void processInjectResponse(ByteBuf msg) {
if (msg.getByte(0) != HEAD[0] && msg.getByte(1) != HEAD[1]) {
return;
}
protected boolean processInjectResponse(ByteBuf msg) {
// 只处理注入回报帧A0
if (msg.getByte(2) != (byte) 0xA0) {
return;
if (msg.getByte(2) == (byte) 0xA0) {
if (checkParamBindResponse(msg)) return true; // 检查参数装订回报
if (checkParamQueryResponse(msg)) return true; // 检查参数查询回报
if (checkRouteBindResponse(msg)) return true; // 检查航线装订回报
}
if (msg.getByte(2) == (byte) 0xA1) {
if (checkControlResponse(msg)) return true; // 检查控制指令回报
}
if (checkControlResponse(msg)) return; // 检查控制指令回报
if (checkParamBindResponse(msg)) return; // 检查参数装订回报
if (checkParamQueryResponse(msg)) return; // 检查参数查询回报
if (checkRouteBindResponse(msg)) return; // 检查航线装订回报
return false;
}
/** 检查控制指令回报*/
private boolean checkControlResponse(ByteBuf msg) {
if (CommandRecord.WAITING_RESULT == previousControl.getState()) {
log.debug("当前指令{}, uniId:{}, A1帧指令回报: {}", ByteUtils.byteToHex(previousControl.code), previousControl.commandUniId, ByteUtils.byteToHex(msg.getByte(29)));
previousControl.addReceiveFrameCount();
if (previousControl.commandMatch(msg.slice(13,16))) {
if (msg.getByte(29) == previousControl.code) {
try {
// previousControl.notifyControlCommandResult();
previousControl.notifyControlCommandResult(uavId, true);
log.info("[cac] {} 控制指令成功结果回报...", shortInfo());
previousControl.clearCommand();
return true;
@ -335,7 +336,7 @@ public class HaborClient981A extends HaborClient {
previousParamBind.addReceiveFrameCount();
if (previousParamBind.commandMatch(msg.slice(13,16))) {
try {
// previousParamBind.notifyParamBindCommandResult(true);
previousParamBind.notifyParamBindCommandResult(uavId, uavType,true);
log.info("[cac] {} 指令装订成功结果回报...", shortInfo());
previousParamBind.clearCommand();
return true;
@ -358,10 +359,20 @@ public class HaborClient981A extends HaborClient {
private boolean checkParamQueryResponse(ByteBuf msg) {
if (CommandRecord.WAITING_RESULT == previousParamQuery.getState()) {
previousParamQuery.addReceiveFrameCount();
if (previousParamQuery.commandMatch(msg.slice(13,16))) {
if (msg.getByte(13) == previousParamQuery.code) { // fixme 匹配的不是同样的内容
try {
UavTakeOffParamQueryResultParam981A uavTakeOffParamQueryResultParam = new UavTakeOffParamQueryResultParam981A(msg.slice(13,16));
// previousParamQuery.notifyParamQueryCommandResult(true, uavTakeOffParamQueryResultParam);
UavQueryResultParam uavQueryResultParam = null;
switch (msg.getByte(13)) {
case (byte) 0x41: // 起飞参数查询
uavQueryResultParam = new UavTakeOffParamQueryResultParam981A(msg.slice(13, 16));
break;
case (byte) 0x33: // 重量查询
uavQueryResultParam = new UavWeightQueryResultParam981A(msg.slice(13, 16));
break;
default:
log.warn("[cac] {} 指令查询结果回报,未知的指令类型:{}", shortInfo(), ByteUtils.byteToHex(msg.getByte(13)));
}
previousParamQuery.notifyParamQueryCommandResult(uavId, uavType, true, uavQueryResultParam);
log.info("[cac] {} 指令查询成功结果回报...", shortInfo());
previousParamQuery.clearCommand();
return true;
@ -388,7 +399,7 @@ public class HaborClient981A extends HaborClient {
if (previousRouteBind.commandMatch(msg.slice(13, 16))) {
if (previousRouteBind.completeOrWaitNext()) { // 如果指令列表均已回报,则判定成功,向中心指控回报, 并恢复常发帧
try {
// previousRouteBind.notifyParamBindCommandResult(true);
previousRouteBind.notifyParamBindCommandResult(uavId,uavType,true);
log.info("[cac] {} 航线装订成功结果成功", shortInfo());
previousRouteBind.clearCommand();
return true;
@ -422,12 +433,12 @@ public class HaborClient981A extends HaborClient {
case (byte) 0xE3: // 开伞
return 45;
default:
return 5;
return 8;
}
}
/** 查询指令回报结果参数类, 各型号分开定义*/
/**Cac起飞参数查询查询回报具体定义见各型号子类*/
@Data
private static class UavTakeOffParamQueryResultParam981A extends UavTakeOffParamQueryResultParam {
/**
@ -522,4 +533,28 @@ public class HaborClient981A extends HaborClient {
return JSONUtils.obj2json(this);
}
}
public static class UavWeightQueryResultParam981A extends UavWeightQueryResultParam{
/**
* kg; 1
*/
private int uavWeight;
/**
* kg; 1
*/
private int cargoWeight;
public UavWeightQueryResultParam981A(ByteBuf dataBufSlice) {
int idx = 1;
uavWeight = dataBufSlice.getUnsignedShortLE(idx);
idx += 2;
cargoWeight = dataBufSlice.getUnsignedShortLE(idx);
idx += 2;
}
public String toJsonStr() throws IOException {
return JSONUtils.obj2json(this);
}
}
}

@ -6,19 +6,19 @@ service:
# 中心指控系统 tcp udp 配置
remote-cac:
ip: 123.57.54.1
ip: 172.10.0.214
remoteTcpPort: 4567
# 中心指控系统 http 配置
http-cac:
host: 123.57.54.1:8048
host: 172.10.0.214:8089
# 中心指控系统-地面站配置
cac_gcs:
id: 18
token: SFRGUEJYR0NTMjAyNTAxMTQ=
id: 1
token: SFRGUC1CWC1HQ1MtMjMwMTAwMQ==
logging:

@ -0,0 +1,34 @@
server:
port: 11112
service:
port: 11111
app:
debug: false
# 中心指控系统 tcp udp 配置
remote-cac:
ip: 123.57.54.1
remoteTcpPort: 4567
# 中心指控系统 http 配置
http-cac:
host: 123.57.54.1:8048
# 中心指控系统-地面站配置
cac_gcs:
id: 18
token: SFRGUEJYR0NTMjAyNTAxMTQ=
logging:
level:
com.platform: debug
management:
endpoints:
web:
exposure:
include: 'loggers'

@ -1,6 +1,6 @@
spring:
profiles:
active: dev
active: pre
app:
debug: true
Loading…
Cancel
Save