核心
//main
public static void main(String[] args) throws Exception {
//bossGroup
EventLoopGroup bossGroup=new NioEventLoopGroup(1);
//workerGroup
EventLoopGroup workerGroup=new NioEventLoopGroup();
//serverBootstrap
ServerBootstrap serverBootstrap=new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
//channelInboundHandler
ch.pipeline().addLast(new UpStreamHandler());
};
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
//启动
ChannelFuture f=serverBootstrap.bind(8088).sync();
f.channel().closeFuture().sync();
}
//UpStreamHandler
public class UpStreamHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String packageInfo = (String)msg;
System.out.println ("包数据"+ packageInfo);
}
}
项目架构
iot-mns-protocol
core 协议
MonitorProtocol 协议(包中各属性的长度范围和大小范围和进制)
constant 常量
MonitorPacketConstant 包常量(包起始符,厂商标识,设备ID,指令流水号,内容长度,指令内容,包终止符)
MonitorPacketType 包类型(初始化,心跳,心跳间隔,服务器IP和端口设置,寻找设备,设备关机,设备重启,设备恢复出厂,设置定位时间间隔,设置定位时间段,定位实时查询,终端位置数据上报)
entity
NettyResultDTO
iot-mns-packet
core 抽象包,上行包,下行包
upstream 具体的上行包
InitPacket 初始化包
LinkPacket 心跳包
UdPacket 定位数据上报包
FindAckPacket 查找手环Ack包
downstream 具体的下行包
InitAckPacket 初始化Ack包
LinkAckPacket 心跳Ack包
UdAckPacket 定位数据上报Ack包
FindPacket 查找手环包
iot-mns-server
monitor
core
NettyConfig netty配置类
Server
NettyServer
AbstractNettyServer
MonitorNettyTCPServer
MonitorChannelInitializer channel初始化类(MnsIdleStateHandler,ByteArrayEncoder,MonitorPacketDecoder,filterAndStatistics,upStreamHandler)
server
NettyContext netty上下文
ServerManager 启动关闭执行方法
StartServerApplication 启动类
handler(上行handler)
MnsIdleStateHandler 心跳(设置心跳超时时间)
MonitorPacketDecoder 粘包问题(设置包最大长度和包终止符,使用分隔符解码器处理粘包问题)
FilterAndStatistics 过滤和统计无效包
UpStreamHandler channelRead(解析上行包写业务逻辑)
resolver(上行包解析器)
InitPacketResolver 初始化包解析器
LinkPacketResolver 心跳包解析器
UdPacketResolver 定位数据上报包解析器
FindAckPacketResolver 查找手环Ack包解析器
utils(工具类)
ChannelUtils channel操作工具类
PacketUtils Package操作工具类
PropertyUtil 读取properties工具类
service(下行命令服务)
FindMonitorService 查找手环服务接口(可统一放到iot-mns-service-interface里)
FindMonitorServiceImpl 查找手环服务
UpStreamHandler
@Override
public void channelRead(ChannelHandlerContext chc, Object msg) throws Exception {
try {
String packetInfo = (String) msg;
List<String> packetContent = Splitter.on("*").omitEmptyStrings().splitToList(packetInfo.substring(1, packetInfo.length() - 1));
String type = Splitter.on(",").omitEmptyStrings().splitToList(packetContent.get(4)).get(0);
ChannelUtils.save(packetContent.get(1), chc.channel());
switch (MonitorPacketType.val(type)) {
case CLIENT_INIT:
// 终端初始化
LOGGER.info("The Init packet mesg is : {};", packetInfo);
InitPacket initPacket = initPacketResolver.resolver(packetInfo);
// 设备信息更新
IotMonitor iotMonitor = new IotMonitor();
IotMonitor getByDeviceId = iotMonitorService.selectByDeviceId(initPacket.getDeviceSn());
if (getByDeviceId != null) {
iotMonitorService.update(iotMonitor);
} else {
iotMonitorService.save(iotMonitor);
}
// 返回初始化成功的结果
StringBuffer initAckBuffer = new StringBuffer();
// 拼装返回结果
initAckBuffer.append(InitAckPacketConst.INIT_ACK_DATA)
.append(MonitorPacketConstant.PACKET_DATA_SEPARATOR.getData())
.append(InitAckPacketConst.INIT_SUCCESS);
InitAckPacket initAckPacket = InitAckPacket.builder()
.withVenderFlag(initPacket.getVenderFlag())
.withDeviceSn(initPacket.getDeviceSn())
.withDataSeqNum(initPacket.getDataSeqNum())
.withDataInfo(initAckBuffer.toString()).build();
LOGGER.info("The Init ack packet is : {} ;", initAckPacket.getPacket());
PacketUtils.flushResponse(initAckPacket.getPacket(), chc);
break;
case CLIENT_LINK_KEEPED:
// 终端链路保持
LinkPacket linkPacket = linkPacketResolver.resolver(packetInfo);
StringBuffer linkAckBuffer = new StringBuffer()
.append(LinkAckPacketConst.LINK_ACK_DATA)
.append(MonitorPacketConstant.PACKET_DATA_SEPARATOR.getData())
.append(LocalDateTime.now(LinkAckPacketConst.TIME_ZONE).format(DateTimeFormatter.ofPattern(LinkAckPacketConst.TIME_PATTERN)));
LinkAckPacket linkAckPacket = LinkAckPacket.builder()
.withVenderFlag(linkPacket.getVenderFlag())
.withDeviceSn(linkPacket.getDeviceSn())
.withDataSeqNum(linkPacket.getDataSeqNum())
.withDataInfo(linkAckBuffer.toString()).build();
LOGGER.info("The Link ack packet is : {} ;", linkAckPacket.getPacket());
PacketUtils.flushResponse(linkAckPacket.getPacket(), chc);
case CLIENT_GIS_DATA_UPLOAD:
// 终端位置数据上报
UdPacket udPacket = udPacketResolver.resolver(packetInfo);
LOGGER.info("The UD packet mesg is : {};", packetInfo);
//将udPacket存入表monitor_gis_rec中
MonitorGisRec monitorGisRec = new MonitorGisRec();
monitorGisRecService.insert(monitorGisRec);
UdAckPacket udAckPacket = UdAckPacket.builder()
.withVenderFlag(udPacket.getVenderFlag())
.withDeviceSn(udPacket.getDeviceSn())
.withDataSeqNum(udPacket.getDataSeqNum())
.withDataInfo("UD").build();
LOGGER.info("The UD ack packet is : {} ;", udAckPacket.getPacket());
PacketUtils.flushResponse(udAckPacket.getPacket(), chc);
break;
case CLIENT_BE_FOUND:
//查找
LOGGER.info("The find ack packet is : {};", packetInfo);
FindAckPacket findAckPacket = findAckPacketResolver.resolver(packetInfo);
//更新command_rec
CommandRec oldfindCommandRec = iotCommandRecService.selectLastOne(findAckPacket.getDeviceSn(), MonitorPacketType.CLIENT_BE_FOUND.getPacketType());
iotCommandRecService.update(CommandRec.builder()
.withRecId(oldfindCommandRec.getRecId())
.withExecResult(SysMnsConstant.EXEC_RESULT_SUCESS)
.withAckData(packetInfo)
.build());
break;
case CLIENT_UPLOAD_INTERVAL:
//设置定位频率
LOGGER.info("The setFreq ack packet is : {};", packetInfo);
SetFreqAckPacket setFreqAckPacket = setFreqAckPacketResolver.resolver(packetInfo);
//更新command_rec
CommandRec oldSetFreqCommandRec = iotCommandRecService.selectLastOne(setFreqAckPacket.getDeviceSn(), MonitorPacketType.CLIENT_UPLOAD_INTERVAL.getPacketType());
iotCommandRecService.update(CommandRec.builder()
.withRecId(oldSetFreqCommandRec.getRecId())
.withExecResult(SysMnsConstant.EXEC_RESULT_SUCESS)
.withAckData(packetInfo)
.build());
//同步更新iot_monitor
IotMonitor oldSetFreqIotMonitor = iotMonitorService.selectOne(IotMonitor.builder().withDeviceSn(setFreqAckPacket.getDeviceSn()).build());
String freq = StringUtils.split(getCmdDataByPackageInfo(oldSetFreqCommandRec.getCommandData()), MonitorPacketConstant.PACKET_DATA_SEPARATOR.getData())[1];
iotMonitorService.update(IotMonitor.builder()
.withDeviceId(oldSetFreqIotMonitor.getDeviceId())
.withUploadInterval(Integer.valueOf(freq))
.build());
break;
default:
break;
}
} finally {
ReferenceCountUtil.release(msg);
}
}