|
|
@@ -0,0 +1,163 @@
|
|
|
+package com.inspur.netty.handler;
|
|
|
+
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.inspur.device.domain.SmsbDevice;
|
|
|
+import com.inspur.device.domain.vo.SmsbDeviceVo;
|
|
|
+import com.inspur.device.mapper.SmsbDeviceMapper;
|
|
|
+import com.inspur.netty.message.receive.ReceiveMessage;
|
|
|
+import com.inspur.netty.message.receive.ReceiveMessageType;
|
|
|
+import com.inspur.netty.util.NettyConstants;
|
|
|
+import io.netty.buffer.ByteBuf;
|
|
|
+import io.netty.channel.Channel;
|
|
|
+import io.netty.channel.ChannelHandlerContext;
|
|
|
+import io.netty.channel.ChannelInboundHandlerAdapter;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.dromara.common.core.utils.SpringUtils;
|
|
|
+import org.dromara.common.core.utils.StringUtils;
|
|
|
+
|
|
|
+import java.util.Date;
|
|
|
+import java.util.Locale;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+
|
|
|
+/**
|
|
|
+ * netty connect handler
|
|
|
+ *
|
|
|
+ * @author lihao16
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public class ConnectServerHandler extends ChannelInboundHandlerAdapter {
|
|
|
+ /**
|
|
|
+ * mac-channel map
|
|
|
+ */
|
|
|
+ private static Map<String, Channel> macChannelMap = new ConcurrentHashMap();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * channelId-mac map
|
|
|
+ */
|
|
|
+ private static Map<String, String> channelIdMacMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * device mapper
|
|
|
+ */
|
|
|
+ private static final SmsbDeviceMapper smsbDeviceMapper = SpringUtils.getBean(SmsbDeviceMapper.class);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当客户端连接服务器完成就会触发该方法
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
|
|
+ log.info("ConnectServerHandler: channelId = " + ctx.channel().id() + ",login channelGroup");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
|
|
+ ByteBuf buf = (ByteBuf) msg;
|
|
|
+ byte[] buffer = new byte[buf.readableBytes()];
|
|
|
+ buf.readBytes(buffer);
|
|
|
+ String message = new String(buffer, "utf-8");
|
|
|
+ if (StringUtils.isEmpty(message)) {
|
|
|
+ log.info("ConnectServerHandler: 客户端发来的消息是空");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String[] listMsg = message.split(NettyConstants.DATA_PACK_SEPARATOR);
|
|
|
+ for (String obj : listMsg) {
|
|
|
+ if (StringUtils.isEmpty(obj)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ ReceiveMessage receiveMessage = JSONObject.parseObject(obj, ReceiveMessage.class);
|
|
|
+ if (receiveMessage.getMessageType().equals(ReceiveMessageType.MAC_DATA.getValue())) {
|
|
|
+ log.info("ConnectServerHandler: 接收到客户端发来MAC消息:" + message);
|
|
|
+ String channelId = ctx.channel().id().toString();
|
|
|
+ String macAddr = receiveMessage.getMessageData().toString().toLowerCase(Locale.ROOT);
|
|
|
+ log.info("ConnectServerHandler: channelId = " + channelId + ",macAddr =" + macAddr);
|
|
|
+ // bugfix 存在相同mac多个ChannelId
|
|
|
+ Channel oldChannel = macChannelMap.get(macAddr);
|
|
|
+ macChannelMap.put(macAddr, ctx.channel());
|
|
|
+ if (null != oldChannel) {
|
|
|
+ channelIdMacMap.remove(oldChannel.id().toString());
|
|
|
+ }
|
|
|
+ channelIdMacMap.putIfAbsent(channelId, macAddr);
|
|
|
+ // 验证设备的合法性
|
|
|
+ if (validateDevice(macAddr, ctx)) {
|
|
|
+ // update device online status
|
|
|
+ updateDeviceOnlineStatue(macAddr, NettyConstants.DEVICE_ONLINE_STATUS);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ ctx.fireChannelRead(obj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean validateDevice(String macAddr, ChannelHandlerContext ctx) {
|
|
|
+ // 根据Mac地址查询设备是否在平台录入
|
|
|
+ SmsbDeviceVo smsbDeviceVo = smsbDeviceMapper.selectVoOne(new LambdaQueryWrapper<SmsbDevice>()
|
|
|
+ .eq(SmsbDevice::getMac, macAddr));
|
|
|
+ if (null == smsbDeviceVo) {
|
|
|
+ log.info("ConnectServerHandler: device not in smsb plus,macAddr = " + macAddr);
|
|
|
+ // 关闭该长连接
|
|
|
+ ctx.close();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void updateDeviceOnlineStatue(String macAddr, Integer onlineStatus) {
|
|
|
+ log.info("ConnectServerHandler: update device mac : " + macAddr + " online status to : " + onlineStatus);
|
|
|
+ try {
|
|
|
+ // 设备上线
|
|
|
+ if (onlineStatus.equals(NettyConstants.DEVICE_ONLINE_STATUS)) {
|
|
|
+ smsbDeviceMapper.update(null, new LambdaUpdateWrapper<SmsbDevice>()
|
|
|
+ .eq(SmsbDevice::getMac, macAddr)
|
|
|
+ .set(SmsbDevice::getOnlineStatus, onlineStatus)
|
|
|
+ .set(SmsbDevice::getLastOnline, new Date()));
|
|
|
+ }
|
|
|
+ // 设备离线
|
|
|
+ smsbDeviceMapper.update(null, new LambdaUpdateWrapper<SmsbDevice>()
|
|
|
+ .eq(SmsbDevice::getMac, macAddr)
|
|
|
+ .set(SmsbDevice::getOnlineStatus, onlineStatus)
|
|
|
+ .set(SmsbDevice::getOfflineTime, new Date()));
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("ConnectServerHandler: update remote device status error {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
|
|
+ log.info("ConnectServerHandler:Server,exceptionCaught.ctx.close");
|
|
|
+ cause.printStackTrace();
|
|
|
+ removeChannel(ctx);
|
|
|
+ ctx.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
|
|
+ log.info("ConnectServerHandler:Server,channelInactive channel id = " + ctx.channel().id().toString());
|
|
|
+ removeChannel(ctx);
|
|
|
+ ctx.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void removeChannel(ChannelHandlerContext ctx) {
|
|
|
+ log.info("ConnectServerHandler: Server,removeChannel ctx.channel().id() = " + ctx.channel().id().toString());
|
|
|
+ String channelId = ctx.channel().id().toString();
|
|
|
+ if (channelIdMacMap.containsKey(channelId)) {
|
|
|
+ String macAddr = channelIdMacMap.get(channelId);
|
|
|
+ channelIdMacMap.remove(channelId);
|
|
|
+ if (macChannelMap.containsKey(macAddr)) {
|
|
|
+ macChannelMap.remove(macAddr);
|
|
|
+ updateDeviceOnlineStatue(macAddr, NettyConstants.DEVICE_OFFLINE_STATUS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Map<String, Channel> getMacChannelMap() {
|
|
|
+ return macChannelMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Map<String, String> getChannelIdMacMap() {
|
|
|
+ return channelIdMacMap;
|
|
|
+ }
|
|
|
+}
|