最近在做RFID定位的项目,为了方便自主开发2.4G读写器和数据服务器。服务端采用Netty。
协议描述:
1. 标签ID数据上传:读写器设备按设定时间频率更新读到的所有电子标签的ID号,并向上位机主动发送数据(用UDP模式)
设备ID(2Byte = 0-65535) + 'A' + Sn(1Byte = 0-255) + 标签数(1Byte = n) + 标签1(3Byte = 0x00,0x2A,0x3B)+ 标签2(3Byte = 0x01,0x2b,0x3c)+....+标签n(3Byte = 0x00,0x23,0x6B) + CheckSum(1Byte)
package com.netty;
import java.net.InetSocketAddress;
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.DatagramChannelFactory;
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
public class UdpServer {
private ConnectionlessBootstrap udpBootstrap;
public UdpServer(int port){
DatagramChannelFactory channelFactory = new NioDatagramChannelFactory();
udpBootstrap = new ConnectionlessBootstrap(channelFactory);
udpBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new UdpEventHandler());
}
});
udpBootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) {
new UdpServer(32500);
}
}
package com.netty;
import java.nio.ByteBuffer;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
public class UdpEventHandler extends SimpleChannelUpstreamHandler {
@Override
public void exceptionCaught(ChannelHandlerContext arg0, ExceptionEvent arg1)
throws Exception {
super.exceptionCaught(arg0, arg1);
}
private ChannelBuffer buffer;
private ByteBuffer byteBuffer;
private byte[] arrayByte;
private int deviceID ; //设备ID
private int cmd; //命令类型
private int sn;
private int count ; //标签数
private int tag; //标签号
private int checkSum ; //校验和
private int tagType; //标签类型
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
super.messageReceived(ctx, e);
buffer = (ChannelBuffer)e.getMessage();
byteBuffer = buffer.copy().toByteBuffer();
arrayByte = byteBuffer.array();
if( !(arrayByte!= null && arrayByte.length >=14) ){
return ;
}
deviceID = toInt(arrayByte[6]);
deviceID = (deviceID<<8) + toInt(arrayByte[7]);
cmd = toInt(arrayByte[8]);
sn = toInt(arrayByte[9]);
count = toInt(arrayByte[10]);
if((char)cmd == 'A' ){
if(count == 0 )
return ;
checkSum = toInt(arrayByte[11+(count*3)]);
//上报标签
for(int i=0;i<count;i++){
tagType = toInt(arrayByte[11+(i*3)]);
tag = toInt(arrayByte[11+(i*3)+1]);
tag = (tag<<8) +toInt(arrayByte[11+(i*3)+2]);
//插入数据库
}
}else if ((char)cmd == 'B'){
//无标签上报心跳包
}
}
//取正
private int toInt(byte b){
if(b >= 0) return (int)b;
else return (int)(b + 256);
}
}