nrwms_java/youchain-system/src/main/java/com/youchain/rfid/LongTermAsyncRead.java

549 lines
18 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.youchain.rfid;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Vector;
import javax.swing.*;
import com.uhf.api.cls.BackReadOption;
import com.uhf.api.cls.GpiInfo_ST;
import com.uhf.api.cls.GpiTriggerBoundaryListener;
import com.uhf.api.cls.GpiTriggerBoundaryReasonType;
import com.uhf.api.cls.GpiTriggerBoundaryType;
import com.uhf.api.cls.GpiTriggerListener;
import com.uhf.api.cls.GpiTrigger_Type;
import com.uhf.api.cls.ReadExceptionListener;
import com.uhf.api.cls.ReadListener;
import com.uhf.api.cls.Reader;
import com.uhf.api.cls.Reader.AntPower;
import com.uhf.api.cls.Reader.AntPowerConf;
import com.uhf.api.cls.Reader.EmbededData_ST;
import com.uhf.api.cls.Reader.Inv_Potl;
import com.uhf.api.cls.Reader.Inv_Potls_ST;
import com.uhf.api.cls.Reader.Lock_Obj;
import com.uhf.api.cls.Reader.Lock_Type;
import com.uhf.api.cls.Reader.Mtr_Param;
import com.uhf.api.cls.Reader.READER_ERR;
import com.uhf.api.cls.Reader.SL_TagProtocol;
import com.uhf.api.cls.Reader.TAGINFO;
import com.uhf.api.cls.Reader.TagFilter_ST;
import com.youchain.utils.BaseStatus;
public class LongTermAsyncRead extends JFrame{
JButton jbt1;
JButton jbt2;
Vector<String> vt=new Vector<String>();
JList jlist;
ReaderExceptionChecker rechecker = new ReaderExceptionChecker(3, 60);
public LongTermAsyncRead(int h,int w)
{ super();
Container coter=this.getContentPane();
this.setLayout(null);
jbt1=new JButton("开始盘存");
jbt1.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (StartReadTags()!= READER_ERR.MT_OK_ERR)
{
MessageBox("开始盘存失败");
return;
}
}
});
jbt2=new JButton("停止盘存");
jbt2.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
// System.out.println("盘存打印:"+vt);
// TODO Auto-generated method stub
if (rdr.StopReading() != READER_ERR.MT_OK_ERR)
{
MessageBox("停止盘存失败");
return;
}
}
});
jlist=new JList();
coter.add(jbt1);
coter.add(jbt2);
coter.add(jlist);
int stx=50,sty=20,ey=20,bx=100,by=25;
jbt1.setBounds(stx, sty, bx, by);
jbt2.setBounds(stx, sty+ey+by, bx, by);
jlist.setBounds(jbt1.location().x+jbt1.size().width+50, jbt1.location().y,
400, 200);
// this.setContentPane(coter);
this.setBounds(0, 0, w, h);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setVisible(true);
if(OpenReader()!=READER_ERR.MT_OK_ERR)
{ MessageBox("初始化读写器失败,请检查设备地址以及类型,重新打开");
return;
}
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if(rdr!=null)
{
rdr.StopReading();
rdr.CloseReader();
}
System.exit(0);
}
});
}
void MessageBox(String mes)
{
JOptionPane.showMessageDialog(null, mes, "消息提示", JOptionPane.INFORMATION_MESSAGE);
}
ReadListener RL=new ReadListener()
{
@Override
public void tagRead(Reader r, final TAGINFO[] tag) {
// TODO Auto-generated method stub
//可以对读到的标签做进一步的读,写,锁和GPIO等操作******************************
/*
//以下示例写入两个块的数据到盘存到的标签的USER区中。
//注:只有在非高速盘存模式下才可以进行其它的标签操作,高速盘存模式下禁
//止再进行其它标签操作,否则盘存操作将被终止,其它的标签操作也不会成功。
//但GPIO的操作是例外不论哪种盘存模式都可以在此处操作GPIO
TagFilter_ST oldfilter=rdr.new TagFilter_ST();
byte[] wdata=new byte[4];
wdata[0] = 0x12;
wdata[1] = 0x34;
wdata[2] = 0x56;
wdata[3] = 0x78;
READER_ERR er = READER_ERR.MT_OK_ERR;
//先将盘存的过滤条件保存,因为对标签进行写操作的时候也需要设置过滤条件,
//此过滤条件可能和盘存的过滤条件不同,在完成写操作后还需要将盘存的过滤
//条件恢复。不用检查返回值,不会失败
er=rdr.ParamGet(Mtr_Param.MTR_PARAM_TAG_FILTER, oldfilter);
TagFilter_ST newfilter=rdr.new TagFilter_ST();
newfilter.bank=1;
newfilter.fdata=tag[0].EpcId;
newfilter.flen=tag[0].Epclen*8;
newfilter.isInvert=0;
newfilter.startaddr=32;
//设置写标签操作时的过滤条件以标签的EPC码为过滤条件
er=rdr.ParamSet(Mtr_Param.MTR_PARAM_TAG_FILTER, newfilter);
//一般使用标签被盘存到时的天线编号作为进一步操作的天线
er = rdr.WriteTagData(tag[0].AntennaID, (char)3, 0, wdata, 4, null, (short)1000);
if (er != READER_ERR.MT_OK_ERR)
{
//操作有可能失败(很多原因可能造成操作失败,常见的比如标签速度过快,
//已经不在天线场内)
}
if (oldfilter.flen == 0) //表示盘存时没有设置过滤条件
rdr.ParamSet(Mtr_Param.MTR_PARAM_TAG_FILTER, null);
else //恢复盘存时的过滤条件
rdr.ParamSet(Mtr_Param.MTR_PARAM_TAG_FILTER, oldfilter);
//设置GPO1为1
//*
if (rdr.SetGPO(1, 1) != READER_ERR.MT_OK_ERR)
{
//操作有可能失败,比如由于断网
}
//*/
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
//System.out.println("update ui ...");
for(int i=0;i<tag.length;i++)
{
String v=Reader.bytes_Hexstr(tag[i].EpcId);
// RFID长度验证
boolean flag = BaseStatus.lengthVerifyList.contains(Long.valueOf(v.length()));
if (flag) {
vt.add(Reader.bytes_Hexstr(tag[i].EpcId)+"天线:"+tag[i].AntennaID);
}
/*if(tag[i].EmbededDatalen==0)
vt.add(Reader.bytes_Hexstr(tag[i].EpcId)+"天线:"+tag[i].ReadCnt);
else
vt.add(Reader.bytes_Hexstr(tag[i].EpcId)+" "+Reader.bytes_Hexstr(tag[i].EmbededData));*/
}
// 去重
HashSet set = new HashSet(vt);
vt= new Vector(set);
jlist.setListData(vt);
}
});
//*/
}
};
ReadExceptionListener REL=new ReadExceptionListener()
{
@Override
public void tagReadException(Reader r, final READER_ERR re) {
//如果需要可在此处记录异常日志
System.out.println(r.GetReaderAddress() + "--异常信息:" + re.toString());
//判断是否异常发生过于频繁
if (rechecker.IsTrigger())
{
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
MessageBox("读写器异常太过频繁,错误信息:"+re.toString());
}
});
return;
}
else
rechecker.AddErr();
//尝试重新连接读写器并启动盘存操作如果5次均失败则弹出提示
//尝试重新连接读写器并启动盘存操作如果5次均失败则弹出提示
READER_ERR resume_err = READER_ERR.MT_OK_ERR;
for (int i = 0; i < 5; ++i)
{
resume_err = OpenReader();
if (resume_err == READER_ERR.MT_OK_ERR)
{
resume_err = StartReadTags();
if (resume_err == READER_ERR.MT_OK_ERR)
break;
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (resume_err != READER_ERR.MT_OK_ERR)
{
//如果需要可在此处记录异常日志
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
MessageBox("重连读写器失败");
}
});
}
}
};
GpiTriggerListener GTL=new GpiTriggerListener()
{
@Override
public void GpiTrigger(Reader r, GpiInfo_ST gist,int id) {
// TODO Auto-generated method stub
System.out.println(r.GetReaderAddress());
for (int i = 0; i < gist.gpiCount; ++i)
{
System.out.println(gist.gpiStats[i].GpiId+" "+gist.gpiStats[i].State+" "+id);
}
}
};
GpiTriggerBoundaryListener GTBL=new GpiTriggerBoundaryListener()
{
@Override
public void GpiTriggerBoundary(Reader r, GpiTriggerBoundaryType btype,
GpiTriggerBoundaryReasonType reason) {
// TODO Auto-generated method stub
System.out.println(r.GetReaderAddress());
System.out.println(btype+" "+reason);
}
};
Reader rdr = null;
READER_ERR OpenReader()
{
READER_ERR err = READER_ERR.MT_OK_ERR;
if (rdr != null)
{
rdr.CloseReader();
rdr=null;
}
//初始化读写器实例************************************************************
//当使用设备的串口进行连接的时候InitReader_Notype函数的第一个参数也可
//能是串口号例如com1当设备仅有一个天线端口时例如一体机或者发卡器
//InitReader_Notype函数的第二个参数也可能为1
//读写器出厂默认IP为192.168.1.100 com4
int portnum = 4; //注意是读写器天线端口数,不是已连接数量
rdr=new Reader();
err = rdr.InitReader_Notype("192.168.0.224",4);
System.out.println("connect:"+err.toString());
if (err != READER_ERR.MT_OK_ERR)
return err;
//****************************************************************************
//以下为必须要设置的参数和事件回调处理函数************************************
//设置读写器发射功率,本例设置为最大发射功率,可根据实际情况调整,
//一般来说,功率越大则识别距离越远
//获取读写器最大发射功率
int[] maxpower=new int[1];
maxpower[0]=2200;
if (err != READER_ERR.MT_OK_ERR)
return err;
AntPowerConf apcf=rdr.new AntPowerConf();
apcf.antcnt=portnum;
for(int i=0;i<apcf.antcnt;i++)
{
AntPower jaap=rdr.new AntPower();
jaap.antid=i+1;
jaap.readPower=(short)maxpower[0];
jaap.writePower=(short)maxpower[0];
apcf.Powers[i]=jaap;
}
err=rdr.ParamSet( Mtr_Param.MTR_PARAM_RF_ANTPOWER, apcf);
//*
if (err != READER_ERR.MT_OK_ERR)
return err;
//设置读写器执行GEN2空中接口协议
Inv_Potls_ST ipst=rdr.new Inv_Potls_ST();
ipst.potlcnt=1;
ipst.potls=new Inv_Potl[1];
for(int i=0;i<ipst.potlcnt;i++)
{
Inv_Potl ipl=rdr.new Inv_Potl();
ipl.weight=30;
ipl.potl=SL_TagProtocol.SL_TAG_PROTOCOL_GEN2;
ipst.potls[0]=ipl;
}
//不用检查返回值,不会失败
err= rdr.ParamSet(Mtr_Param.MTR_PARAM_TAG_INVPOTL, ipst);
//设置盘存到标签时的回调处理函数
rdr.addReadListener(RL);
//*
//设置读写器发生错误时的回调处理函数
rdr.addReadExceptionListener(REL);
//****************************************************************************
//以下为根据应用需求可能要设置的参数******************************************
//*
//标签数量比较大,且移动速度缓慢或静止不动,设置为Session1可取得更
//好效果,反之标签数量较少移动速度较快应设置为Session0,读写器默认
//为Session0
int[] gen2session=new int[]{1};
err =rdr.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_SESSION, gen2session);
if (err != READER_ERR.MT_OK_ERR)
return err;
//*/
/*
//对于某些应用可能需要读写器只盘存符合某些数据特征的标签,可以通
//过设置过滤条件来实现,这样对于不符合特征的标签就不会被采集,以
//下代码实现只盘存EPC码以0011010011二进制开头的标签
byte[] filterbytes=new byte[2];
filterbytes[0] = 0x34;
filterbytes[1] = (byte) 0xC0;
TagFilter_ST filter=rdr.new TagFilter_ST();
filter.bank=1;
filter.fdata=filterbytes;
filter.flen=4;
filter.isInvert=0;
filter.startaddr=32;
//不用检查返回值,不会失败
rdr.ParamSet(Mtr_Param.MTR_PARAM_TAG_FILTER, filter);//*/
/*
//有些应用除了快速盘存标签的EPC码外还想同时抓取某一个bank内的数据
//可以通过设置此参数实现目前只有slr11xx和slr12xx系列读写器才支
//持以下代码实现抓取tid区从0块开始的12个字节的数据,需要注意的
//是抓取的字节数必须是2的倍数,如果成功获得其它bank的数据则TAGINFO
//结构的成员EmbededData则为获得的数据如果失败的话则TAGINFO结构
//的成员EmbededDatalen为0
EmbededData_ST edst = rdr.new EmbededData_ST();
edst.startaddr=0;
edst.bank=2;
//bytecnt=0 取消嵌入数据
edst.bytecnt=12;
edst.accesspwd=null;
//不用检查返回值,不会失败
rdr.ParamSet(Mtr_Param.MTR_PARAM_TAG_EMBEDEDDATA, edst);//*/
return READER_ERR.MT_OK_ERR;
}
READER_ERR StartReadTags()
{
//初始化结BackReadOption
BackReadOption m_BROption=new BackReadOption();
//本例只使用天线1进行盘存如果要使用多个天线则只需要将使用的天线编
//号赋值到数组ants中例如同时使用天线1和2则代码应该改为ants[0] = 1;
//ants[1] = 2;antcnt = 2;
int antcnt=4;
int[] ants=new int[]{1,2,3,4};
/*for(int i=0;i<antcnt;i++)
ants[i]=i+1;*/
/*是否采用高速模式目前只有slr11xx和slr12xx系列读写器才支持,对于
*一般标签数量不大,速度不快的应用没有必要使用高速模式,本例没有设置
*使用高速模式
* */
m_BROption.IsFastRead = false;//采用非高速模式盘存标签
///非高速盘存模式下必须要设置的参数*******************************************
//盘存周期,单位为ms可根据实际使用的天线个数按照每个天线需要200ms
//的方式计算得出,如果启用高速模式则此选项没有任何意义,可以设置为
//任意值,或者干脆不设置
m_BROption.ReadDuration = (short)(200 * antcnt);
//盘存周期间的设备不工作时间,单位为ms,一般可设置为0增加设备不工作
//时间有利于节电和减少设备发热(针对某些使用电池供电或空间结构不利
//于散热的情况会有帮助)
m_BROption.ReadInterval = 0;
//****************************************************************************
//高速盘存模式参数设置********************************************************
//以下为选择使用高速模式才起作用的选项参,照如下设置即可,如果使能高速
//模式即把IsFastRead设置为true则,只需取消以下被注释的代码即可
//*
//高速模式下为取得最佳效果设置为0即可
m_BROption.FastReadDutyRation = 0;
//标签信息是否携带识别天线的编号
m_BROption.TMFlags.IsAntennaID = true;
//标签信息是否携带标签识别次数
m_BROption.TMFlags.IsReadCnt = false;
//标签信息是否携带识别标签时的信号强度
m_BROption.TMFlags.IsRSSI = false;
//标签信息是否携带时间戳
m_BROption.TMFlags.IsTimestamp = false;
//标签信息是否携带识别标签时的工作频点
m_BROption.TMFlags.IsFrequency = false;
//标签信息是否携带识别标签时同时读取的其它bank数据信息,如果要获取在
//盘存时同时读取其它bank的信息还必须设置MTR_PARAM_TAG_EMBEDEDDATA参数,
//目前只有slr11xx和slr12xx系列读写器才支持
m_BROption.TMFlags.IsEmdData = false;
//保留字段可始终设置为0
m_BROption.TMFlags.IsRFU = false;
//*/
//****************************************************************************
//使用GPI输入信号触发读写器工作***********************************************
//*
//共有三种触发模式:
//1 预定义两种GPI状态一种作为触发读写器启动盘存的条件另一种
// 作为停止盘存的条件
//2 预定义一种GPI状态触发读写器启动盘存指定一段时间(必须大于
// 5秒)后自动停止盘存标签
//3 预定义两种GPI状态满足任何一种GPI状态都触发读写器启动盘存
// 指定一段时间(必须大于5秒)后自动停止盘存标签
//详见"读写器GPI触发工作模式.pdf"
//以下示例为模式1Trigger1State为启动工作时的GPI状态且可以指
//定多个GPI的状态此例指定当GPI1为0时读写器开始盘存,当GPI2为0时
//读写器停止盘存
//m_BROption.IsGPITrigger = true;
//设置读写器发生GPI时的回调处理函数
// rdr.addGpiTriggerListener(GTL);
// rdr.addGpiTriggerBoundaryListener(GTBL);
//第一种触发模式
/*
m_BROption.GpiTrigger.TriggerType = GpiTrigger_Type.GPITRIGGER_TRI1START_TRI2STOP;
m_BROption.GpiTrigger.GpiTrigger1States.gpiCount = 1;
m_BROption.GpiTrigger.GpiTrigger1States.gpiStats[0].GpiId = 1;
m_BROption.GpiTrigger.GpiTrigger1States.gpiStats[0].State = 0;
m_BROption.GpiTrigger.GpiTrigger2States.gpiCount = 1;
m_BROption.GpiTrigger.GpiTrigger2States.gpiStats[0].GpiId = 2;
m_BROption.GpiTrigger.GpiTrigger2States.gpiStats[0].State = 0;
*/
//第二种触发模式
/*m_BROption.GpiTrigger.TriggerType = GpiTrigger_Type.GPITRIGGER_TRI1ORTRI2START_TIMEOUTSTOP;
m_BROption.GpiTrigger.GpiTrigger1States.gpiCount = 1;
m_BROption.GpiTrigger.GpiTrigger1States.gpiStats[0].GpiId = 1;
m_BROption.GpiTrigger.GpiTrigger1States.gpiStats[0].State = 0;
m_BROption.GpiTrigger.GpiTrigger2States.gpiCount = 1;
m_BROption.GpiTrigger.GpiTrigger2States.gpiStats[0].GpiId = 2;
m_BROption.GpiTrigger.GpiTrigger2States.gpiStats[0].State = 0;
m_BROption.GpiTrigger.StopTriggerTimeout=5000;
*/
//第三种触发模式
/*
m_BROption.GpiTrigger.TriggerType = GpiTrigger_Type.GPITRIGGER_TRI1START_TIMEOUTSTOP;
m_BROption.GpiTrigger.GpiTrigger1States.gpiCount = 1;
m_BROption.GpiTrigger.GpiTrigger1States.gpiStats[0].GpiId = 3;
m_BROption.GpiTrigger.GpiTrigger1States.gpiStats[0].State = 0;
m_BROption.GpiTrigger.StopTriggerTimeout=5000;
*/
//在GPI触发工作时当触发条件发生时的处理函数可通过此事件获取触
//发时刻的GPI状态如果不关心触发时刻的GPI状态以及时序关系可以
//不设置此事件,详见文档"读写器GPI触发工作模式.pdf"
return rdr.StartReading(ants, antcnt, m_BROption);
}
//*
public static void main(String[] args)
{
System.out.println(System.getProperty("java.library.path"));
try {
if(!System.getProperty("os.arch").contains("64"))
{
//32位系统需要这个支持库
System.loadLibrary("ACE");
}
System.loadLibrary("PCOMM");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("hello into the longtermasyncread of samples for java");
LongTermAsyncRead fm=new LongTermAsyncRead(300,650);
}
}