Commit ff1c02a2 authored by wanghao's avatar wanghao

1 上料后 机械臂 回零 后 出现了一次 没有上电的操作,涉及到的 机械臂回零判断流程 优化。

2 实时数据 根据 托盘编号排序
3 如果设备号为空,则不设置各种状态信息,防止出现 没有板子的位置也报错,不能解绑的问题。
parent 9dc83746
......@@ -93,6 +93,8 @@ public class CalibrationResultEventHandler {
for (PalletDeviceBinding palletDeviceBinding : palletDeviceBindings) {
MesDeviceDomain mesDeviceDomain = new MesDeviceDomain();
// 如果设备编号为空 则不处理改设备
if(StringUtils.isBlank(palletDeviceBinding.getDeviceCode())) continue;
// 主板码
mesDeviceDomain.setMotherboardCode(palletDeviceBinding.getDeviceCode());
// 浓度
......
......@@ -25,6 +25,7 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
/**
......@@ -44,10 +45,6 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyyMMdd");
private static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private volatile long lastActivityTime = System.currentTimeMillis();
/**
* 当前正在处理的指令信息
*/
private final Map<String, CommandExecution> currentCommands = new ConcurrentHashMap<>();
// 线程安全锁,确保文件写入安全
private final ReentrantLock fileLock = new ReentrantLock();
......@@ -59,11 +56,26 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
private IRobotArmCommandService robotArmCommandService;
@Resource
private ApplicationEventPublisher eventPublisher; // 新增事件发布器
// 使用原子引用,确保状态变更的原子性
private final AtomicReference<CommandState> commandState = new AtomicReference<>(CommandState.IDLE);
// 当前执行的指令ID
private volatile Long currentCommandId = null;
private enum CommandState {
IDLE, // 空闲
EXECUTING, // 执行中
COMPLETING, // 正在完成(防止重复)
ERROR // 错误
}
/**
* 接收UDP消息
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
try {
// 获取消息内容的字节缓冲区
ByteBuf content = packet.content();
......@@ -93,9 +105,6 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
// 保存消息到文件
//saveMessageToFile(packet.sender().toString(), correctMessage);
// 处理消息逻辑
String response = "服务器已收到UDP消息:" + correctMessage;
// 记录最后活动时间
lastActivityTime = System.currentTimeMillis();
// 判断消息类型并进行相应处理
......@@ -106,26 +115,6 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
// 处理普通状态消息(原有逻辑)
handleNormalMessage(ctx, packet, correctMessage);
}
// // 解析消息
// RobotArmMessageParser.RobotArmStatus status =
// RobotArmMessageParser.parseMessage(correctMessage);
//
// if (status != null) {
// // 处理状态消息
// processStatusMessage(status);
//
// // 检查是否为完全空闲状态
// if (status.isFullyIdle()) {
// handleFullyIdleState();
// }
// }
//
// // 回复客户端
// byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8);
// ctx.writeAndFlush(new DatagramPacket(
// io.netty.buffer.Unpooled.copiedBuffer(responseBytes),
// packet.sender()));
} catch (Exception e) {
log.error("处理UDP消息异常", e);
// 出现异常时发送故障状态
......@@ -144,17 +133,11 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
packet.sender()));
// 解析消息
RobotArmMessageParser.RobotArmStatus status =
RobotArmMessageParser.parseMessage(message);
RobotArmMessageParser.RobotArmStatus status = RobotArmMessageParser.parseMessage(message);
if (status != null) {
// 处理状态消息
processStatusMessage(status);
// 检查是否为完全空闲状态
if (status.isFullyIdle()) {
handleFullyIdleState();
}
}
}
......@@ -176,25 +159,54 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
}
/**
* 仅处理已完成的指令
* 仅处理已完成的指令 - 已修改为使用currentCommandId
*/
public void onlyCompleted() {
// 每次只能有一个指令正在执行
CommandExecution execution = currentCommands.get("127.0.0.1");
// 如果指令追踪为空,则可能是 刚启动,再去 查一下有没有正在执行的任务
if(execution == null) {
Long commandId = null;
// 优先从currentCommandId获取
if (currentCommandId != null) {
commandId = currentCommandId;
} else {
// 如果currentCommandId为空,从数据库查询正在执行的任务
List<RobotArmCommand> robotArmCommands = robotArmCommandService.selectTopRunningRobotArmCommands();
if(robotArmCommands != null && !robotArmCommands.isEmpty()) {
// 注册指令跟踪
execution = new CommandExecution();
execution.commandId = robotArmCommands.get(0).getRobotArmCommandId();
if (robotArmCommands != null && !robotArmCommands.isEmpty()) {
commandId = robotArmCommands.get(0).getRobotArmCommandId();
// 如果找到了指令ID,更新currentCommandId
currentCommandId = commandId;
}
}
if (commandId != null) {
// 使用状态机完成指令
completeCommandWithStateMachine(commandId);
}
}
if (execution != null) {
robotArmCommandService.completeCommand(execution.commandId);
currentCommands.remove("127.0.0.1");
log.info("指令完成: {}", execution.commandId);
/**
* 使用状态机完成指令
*/
private void completeCommandWithStateMachine(Long commandId) {
// 检查当前状态和指令ID是否匹配
if (commandId.equals(currentCommandId) &&
commandState.compareAndSet(CommandState.EXECUTING, CommandState.COMPLETING)) {
try {
robotArmCommandService.completeCommand(commandId);
log.info("指令完成: {}", commandId);
// 清理状态
currentCommandId = null;
commandState.set(CommandState.IDLE);
// 处理待执行指令
handleFullyIdleState();
} catch (Exception e) {
log.error("指令完成失败: {}", commandId, e);
commandState.set(CommandState.ERROR);
}
} else {
log.warn("无法完成指令 {},当前状态: {}, 当前指令ID: {}",
commandId, commandState.get(), currentCommandId);
}
}
......@@ -207,45 +219,55 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
} else {
sendStatusToWebSocket("error");
}
// 处理指令完成
// 处理指令完成逻辑 - 使用状态机防止重复
if (status.isFullyIdle()) {
// 记录详细状态
log.debug("机械臂状态: code={}, text={}, position=({},{},{},{})",
status.getCode(), status.getText(),
status.getX(), status.getY(), status.getZ(), status.getR());
CommandExecution execution = currentCommands.get("127.0.0.1");
// 如果指令追踪为空,则可能是 刚启动,再去 查一下有没有正在执行的任务
if(execution == null) {
List<RobotArmCommand> robotArmCommands = robotArmCommandService.selectTopRunningRobotArmCommands();
if(robotArmCommands != null && !robotArmCommands.isEmpty()) {
// 注册指令跟踪
execution = new CommandExecution();
execution.commandId = robotArmCommands.get(0).getRobotArmCommandId();
handleCompleteState();
} else {
log.info("status.isFullyIdle() = false");
}
}
if (execution != null) {
robotArmCommandService.completeCommand(execution.commandId);
currentCommands.remove("127.0.0.1");
log.info("指令完成: {}", execution.commandId);
private void handleCompleteState() {
// 原子地获取并清空当前指令ID
Long commandIdToComplete = currentCommandId;
if (commandIdToComplete != null) {
// 尝试将状态从 EXECUTING 转为 COMPLETING
if (commandState.compareAndSet(CommandState.EXECUTING, CommandState.COMPLETING)) {
try {
// 完成指令
robotArmCommandService.completeCommand(commandIdToComplete);
log.info("指令完成: {}", commandIdToComplete);
// 清空当前指令
currentCommandId = null;
// 状态转为空闲
commandState.set(CommandState.IDLE);
// 处理待执行指令
handleFullyIdleState();
} catch (Exception e) {
log.error("指令完成失败: {}", commandIdToComplete, e);
commandState.set(CommandState.ERROR);
}
}
} else {
log.info("status.isFullyIdle() = false");
// 没有当前指令,直接处理待执行
handleFullyIdleState();
}
}
/**
* 记录当前执行的指令
*/
public void registerCommandExecution(Long commandId) {
CommandExecution execution = new CommandExecution();
execution.commandId = commandId;
execution.startTime = System.currentTimeMillis();
// 每次只能有一个正在执行中的,所以先暂时用使用了127.0.0.1
currentCommands.put("127.0.0.1", execution);
if (commandState.compareAndSet(CommandState.IDLE, CommandState.EXECUTING)) {
currentCommandId = commandId;
log.info("注册指令跟踪: {}", commandId);
} else {
throw new IllegalStateException("机械臂当前状态不能执行新指令");
}
}
......@@ -288,11 +310,8 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.ALL_IDLE) {
log.info("UDP服务器超过规定时间未收到数据");
long now = System.currentTimeMillis();
long idleDuration = now - lastActivityTime;
// 如果长时间空闲(>2秒)
if (idleDuration > 20000) {
handleLongIdleState();
}
......@@ -301,12 +320,14 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
super.userEventTriggered(ctx, evt);
}
}
private void handleLongIdleState() {
// 检查是否有超时的指令
// 如果当前没有执行中的指令,尝试处理待执行指令
if (currentCommands.isEmpty()) {
private void handleLongIdleState() {
// 检查当前是否有执行中的指令(使用currentCommandId)
if (currentCommandId == null) {
handleFullyIdleState();
} else {
log.info("当前有指令正在执行中,指令ID: {}", currentCommandId);
}
}
/**
......@@ -320,13 +341,6 @@ public class NettyUdpServerHandler extends SimpleChannelInboundHandler<DatagramP
}
}
// 添加指令执行状态
private static class CommandExecution {
Long commandId;
long startTime;
}
/**
* 将消息保存到本地文件
*
......
......@@ -89,6 +89,10 @@ public class RobotArmCommandServiceImpl implements IRobotArmCommandService
}
}
/**
* 机械臂空闲状态下 需要执行的待执行的指令
*/
@Override
@Transactional
public void processPendingCommands() {
......@@ -336,6 +340,10 @@ public class RobotArmCommandServiceImpl implements IRobotArmCommandService
return 0;
}
/**
* 完成指令
* @param commandId c
*/
@Override
@Transactional
public void completeCommand(Long commandId) {
......@@ -346,7 +354,6 @@ public class RobotArmCommandServiceImpl implements IRobotArmCommandService
log.info("command != null && \"2\".equals(command.getStatus()");
// 发送上电指令
try {
String storeyCode = command.getStoreyCode();
String equitmentCode;
int registerOffset;
......@@ -361,6 +368,7 @@ public class RobotArmCommandServiceImpl implements IRobotArmCommandService
log.info("tEquipmentInfo != null");
String powerOutageIp = tEquipmentInfo.getfPowerOutageIp();
Integer powerOutagePort = tEquipmentInfo.getfPowerOutagePort();
log.info("powerOutageIp: {}, powerOutagePort: {},command.getType:{}", powerOutageIp, powerOutagePort, command.getType());
if(StringUtils.isNotBlank(powerOutageIp) && powerOutagePort != null) {
if("0".equals(command.getType())) {
eventPublisher.publishEvent(new CheckPowerOnCommandEvent(
......
......@@ -114,12 +114,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createTime != null "> and palDeviceBinding.f_create_time = #{createTime}</if>
<if test="status != null and status != '' "> and palDeviceBinding.f_status = #{status}</if>
</where>
order by trayInfo.f_tray_code ,palDeviceBinding.f_index asc
order by trayInfo.f_tray_code ,palDeviceBinding.f_number asc
</select>
<select id="getAllExcludeUnbindingTimeByTrayId" parameterType="long" resultMap="PalletDeviceBindingResult">
<include refid="selectPalletDeviceBindingVo"/>
where palDeviceBinding.f_tray_id = #{trayId}
order by palDeviceBinding.f_index asc
order by palDeviceBinding.f_number asc
</select>
<select id="listByTrayCode" parameterType="string" resultMap="PalletDeviceBindingResult">
<include refid="selectPalletDeviceBindingVo"/>
......@@ -327,7 +327,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="simCardStatus != null">f_sim_card_status = #{simCardStatus},</if>
<if test="networkStatus != null">f_network_status = #{networkStatus},</if>
</trim>
where f_pallet_device_binding_id = #{palletDeviceBindingId}
where f_pallet_device_binding_id = #{palletDeviceBindingId} and f_device_code is not null
</update>
<update id="batchUpdateDeviceCode" parameterType="list">
<foreach collection="palletDeviceBindingList" item="item" index="index" separator=";">
......@@ -350,7 +350,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="item.calibrationConcentration != null">f_calibration_concentration = #{item.calibrationConcentration},</if>
<if test="item.calibrationConcentrationStatus != null">f_calibration_concentration_status = #{item.calibrationConcentrationStatus},</if>
</trim>
where f_pallet_device_binding_id = #{item.palletDeviceBindingId}
where f_pallet_device_binding_id = #{item.palletDeviceBindingId} and f_device_code is not null
</foreach>
</update>
<update id="batchUpdateDeviceCodeAndUnbindingTime" parameterType="list">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment