package com.mes.tcp; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * MES客户端消息处理器 * 接收服务端响应,解析后分发到对应工位 */ public class MesClientHandler extends ChannelInboundHandlerAdapter { private static final Logger log = LoggerFactory.getLogger(MesClientHandler.class); private final MesTcpClient tcpClient; private final MessageDispatcher dispatcher; public MesClientHandler(MesTcpClient tcpClient, MessageDispatcher dispatcher) { this.tcpClient = tcpClient; this.dispatcher = dispatcher; } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { log.info("TCP连接已建立: {}", ctx.channel().remoteAddress()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { log.info("TCP连接已断开"); if (tcpClient != null) { tcpClient.onDisconnected(); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String rawMessage = msg.toString(); log.info("=============================================================================="); log.info("| TCP返回报文内容: {}", rawMessage); // 格式化消息(移除前缀等) String mesMessage = formatResult(rawMessage); if (mesMessage.isEmpty()) { log.info("| TCP返回报文内容格式错误, 弃用!"); log.info("=============================================================================="); return; } // 解析消息类型 String msgType = getMsgType(mesMessage); log.info("| TCP返回报文类型: {}", msgType); // 解析结果码 String result = getResult(mesMessage); log.info("| TCP返回报文结果: {}", result); // 解析工位号 String stationCode = getStationCode(mesMessage); log.info("| TCP返回工位号: {}", stationCode); log.info("=============================================================================="); // 分发消息 if (dispatcher != null && stationCode != null) { dispatcher.dispatch(stationCode, msgType, result, mesMessage); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { log.error("TCP通信异常: {}", cause.getMessage()); ctx.close(); } /** * 格式化消息(移除状态前缀) */ private String formatResult(String msg) { if (msg == null || msg.length() < 3) { return ""; } String prefix = msg.substring(0, 2).trim(); if ("OK".equals(prefix)) { return msg.substring(3); } return ""; } /** * 获取消息类型 * 消息格式: aaaabbbbbABW[MSGTYPE]GW... * 消息类型位于位置12-16 */ private String getMsgType(String msg) { if (msg.length() < 16) { return ""; } return msg.substring(12, 16); } /** * 获取工位号 * 工位号位于固定位置18-26(v2 协议 oprno 扩到 8 字符) */ private String getStationCode(String msg) { // 固定位置解析 if (msg.length() >= 26) { return msg.substring(18, 26).trim(); } // 备用方案:查找GW字段 int gwIndex = msg.indexOf("GW"); if (gwIndex >= 0 && msg.length() >= gwIndex + 10) { return msg.substring(gwIndex + 2, gwIndex + 10).trim(); } return null; } /** * 获取结果码。 * - v2 协议报文(长度 98):位置 74-76 * - v3 协议报文(AQDW/MQDW,长度 99):lx 从 2 位扩到 3 位,result 后移 1,位置 75-77 */ private String getResult(String msg) { String msgType = getMsgType(msg); // v3 扩展报文 if ("AQDW".equals(msgType) || "MQDW".equals(msgType)) { if (msg.length() >= 77) { return msg.substring(75, 77).trim(); } } else { // v2 或其他报文 if (msg.length() >= 76) { return msg.substring(74, 76).trim(); } } // 备用方案:查找 RS 字段 int rsIndex = msg.indexOf("RS"); if (rsIndex >= 0 && msg.length() >= rsIndex + 4) { return msg.substring(rsIndex + 2, rsIndex + 4).trim(); } return ""; } }