HJ212-2017是中国环境保护部发布的环境监测数据传输协议,主要用于环境监测设备与监控中心之间的数据传输。该协议定义了数据传输的格式、内容、通信方式等,广泛应用于空气质量、水质等环境监测领域。本文将详细介绍HJ212-2017协议的结构,并通过Java语言和Netty框架实现一个简单的协议解析。
HJ212-2017协议采用ASCII码进行数据传输,数据包由多个字段组成,每个字段以分号(;)分隔。协议的基本结构如下:
ST=xx;CN=xx;PW=xx;MN=xx;Flag=xx;CP=xx;CRC=xx\r\n
ST:系统类型,表示数据来源的系统类型。
CN:命令编号,表示数据包的类型。
PW:密码,用于身份验证。
MN:设备编号,唯一标识设备。
Flag:标志位,表示数据的传输状态。
CP:数据段,包含具体的监测数据。
CRC:校验码,用于数据完整性校验。
数据段(CP)是HJ212-2017协议中最重要的部分,包含了具体的监测数据。数据段由多个数据项组成,每个数据项以逗号(,)分隔,格式如下:
DataTime=xx;xxx-Rtd=xx,xxx-Flag=xx;...
DataTime:数据时间,表示数据采集的时间。
创建一个简单的Netty服务器,用于接收HJ212-2017协议数据。
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class HJ212Server {
private final int port;
public HJ212Server(int port) {
this.port = port;
}
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
@Override
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new StringDecoder(), new StringEncoder(), new HJ212Handler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port = 8080;
new HJ212Server(port).run();
}
}
实现一个HJ212Handler,用于解析HJ212-2017协议数据
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
public class HJ212Handler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
// 解析HJ212协议数据
HJ212Data data = parseHJ212Data(msg);
if (data != null) {
System.out.println("Received HJ212 Data: " + data);
} else {
System.out.println("Invalid HJ212 Data: " + msg);
}
}
private HJ212Data parseHJ212Data(String data) {
HJ212Data hj212Data = new HJ212Data();
String[] fields = data.split(";");
for (String field : fields) {
String[] keyValue = field.split("=");
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
switch (key) {
case "ST":
hj212Data.setSt(value);
break;
case "CN":
hj212Data.setCn(value);
break;
case "PW":
hj212Data.setPw(value);
break;
case "MN":
hj212Data.setMn(value);
break;
case "Flag":
hj212Data.setFlag(value);
break;
case "CP":
parseCP(hj212Data, value);
break;
case "CRC":
hj212Data.setCrc(value);
break;
default:
break;
}
}
}
return hj212Data;
}
private void parseCP(HJ212Data hj212Data, String cp) {
String[] cpFields = cp.split(",");
for (String cpField : cpFields) {
String[] keyValue = cpField.split("=");
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
if (key.endsWith("-Rtd")) {
String factor = key.substring(0, key.length() - 4);
hj212Data.addRtdData(factor, value);
} else if (key.endsWith("-Flag")) {
String factor = key.substring(0, key.length() - 5);
hj212Data.addFlagData(factor, value);
} else if (key.equals("DataTime")) {
hj212Data.setDataTime(value);
}
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
import java.util.HashMap;
import java.util.Map;
public class HJ212Data {
private String st;
private String cn;
private String pw;
private String mn;
private String flag;
private String dataTime;
private String crc;
private Map rtdData = new HashMap<>();
private Map flagData = new HashMap<>();
// Getters and Setters
public void addRtdData(String factor, String value) {
rtdData.put(factor, value);
}
public void addFlagData(String factor, String value) {
flagData.put(factor, value);
}
@Override
public String toString() {
return "HJ212Data{" +
"st='" + st + '\'' +
", cn='" + cn + '\'' +
", pw='" + pw + '\'' +
", mn='" + mn + '\'' +
", flag='" + flag + '\'' +
", dataTime='" + dataTime + '\'' +
", crc='" + crc + '\'' +
", rtdData=" + rtdData +
", flagData=" + flagData +
'}';
}
}
ST=32;CN=2011;PW=123456;MN=88888880000001;Flag=4;CP=DataTime=20231010120000;w01018-Rtd=12.5,w01018-Flag=N;w01019-Rtd=0.8,w01019-Flag=N;CRC=ABCD\r\n