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

549 lines
18 KiB
Java
Raw Normal View History

2024-04-30 09:46:49 +08:00
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;
2024-05-14 14:53:10 +08:00
import java.util.Calendar;
2024-04-30 09:46:49 +08:00
import java.util.HashSet;
import java.util.Vector;
2024-05-14 14:53:10 +08:00
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;
2024-04-30 09:46:49 +08:00
public class LongTermAsyncRead extends JFrame{
2024-05-14 14:53:10 +08:00
2024-04-30 09:46:49 +08:00
JButton jbt1;
JButton jbt2;
2024-05-14 14:53:10 +08:00
Vector<String> vt=new Vector<String>();
2024-04-30 09:46:49 +08:00
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) {
2024-12-02 17:03:01 +08:00
// System.out.println("盘存打印:"+vt);
2024-04-30 09:46:49 +08:00
// 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++)
{
2024-05-14 14:53:10 +08:00
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);
2024-04-30 09:46:49 +08:00
else
2024-05-14 14:53:10 +08:00
vt.add(Reader.bytes_Hexstr(tag[i].EpcId)+" "+Reader.bytes_Hexstr(tag[i].EmbededData));*/
2024-04-30 09:46:49 +08:00
}
// 去重
HashSet set = new HashSet(vt);
vt= new Vector(set);
jlist.setListData(vt);
2024-05-14 14:53:10 +08:00
2024-04-30 09:46:49 +08:00
}
});
//*/
}
};
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];
2024-05-14 14:53:10 +08:00
maxpower[0]=2200;
2024-04-30 09:46:49 +08:00
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;
2024-05-14 14:53:10 +08:00
int antcnt=4;
int[] ants=new int[]{1,2,3,4};
/*for(int i=0;i<antcnt;i++)
ants[i]=i+1;*/
2024-04-30 09:46:49 +08:00
/*slr11xxslr12xx,
*使,
*使
* */
2024-05-14 14:53:10 +08:00
m_BROption.IsFastRead = false;//采用非高速模式盘存标签
2024-04-30 09:46:49 +08:00
///非高速盘存模式下必须要设置的参数*******************************************
//盘存周期,单位为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);
}
}