目录

(1)communication.py

(2)Reader.py

(3)Tag.py


实验1—— EPC C1G2标准下的标签状态转换仿真 

实验说明: 利用Python或Matlab模拟C1G2标签的状态转换模型; 程序应能显示标签当前的状态,并能通过键入的不同指令完成状态的转换。

文件结构如下:

(1)communication.py

import sys
from Tag import Tag
from Reader import Readerdef validACK(tagIndex):print('有效的的ACK RN16,tag返回EPC,标签变为Acknowledged状态')tagArray[tagIndex].setState('Acknowledged')return tagArray[tagIndex].returnEPC()def invalidACK():print('无效的ACK RN16,no reply')def returnHandle(tagIndex):tagArray[tagIndex].setState('Open')handle = tagArray[tagIndex].returnHandle()print('tag返回handle:{},进入{}状态,交出钥匙,接受指令'.format(handle, tagArray[tagIndex].state))return handledef access(command):if command == 'read':cmd = reader.read(tagArray[tagIndex])elif command == 'write':cmd = reader.write(tagArray[tagIndex])elif command == 'lock':cmd = reader.lock(tagArray[tagIndex])elif command == 'kill':cmd = reader.kill(tagArray[tagIndex])return cmd# tagNum是标签的数目,tagArray用以存储所有标签
tagNum = int(input('please10 input the number of Tag: '))
Q = int(input('please input the Q to decide the maxNum of slot: '))
tagArray = []
tagIndex = 0for i in range(tagNum):tag = Tag()tag.endPoint = (2 ** (Q - 1))tagArray.append(tag)reader = Reader()
print('*****************开始通信*****************')
print('\n*****************进入选择阶段*****************')
selectChoice = int(input('输入0选择全部标签,输入1选择奇数号标签,输入2选择偶数号标签: '))
reader.select(tagArray, selectChoice)
print('\n*****************进入盘存阶段*****************')
ans, tagIndex = reader.Query(tagArray)
while ans is None:  # ans非空时代表slot值为0 tag返回一个RN16 此时ans=RN16ans, tagIndex = reader.QueryRep(tagArray)
else:ACKRN16 = reader.ACK(ans)print('ACK返回RN16,判断是否有效进入下一步')if ACKRN16 == ans:EPC = validACK(tagIndex)print('\n*****************进入访问阶段*****************')NewRN16 = reader.Req_RN(EPC, ACKRN16)if NewRN16 == ACKRN16:print('收到有效的RN16,tag将返回handle(新的16位随机数)')handle = returnHandle(tagIndex)command, returnhandle = reader.Command(handle)if returnhandle == handle:cmd = access(command)while cmd:command, returnhandle = reader.Command(handle)cmd = access(command)else:sys.exit(0)else:print('收到无效的RN16,no reply')else:invalidACK()

(2)Reader.py

import randomfrom Tag import Tagclass Reader:def __init__(self):self.readerID = self.setReaderID()self.crush = 0self.noRespond = 0self.Q = 2# 给每一个阅读器设置一个唯一的16位IDdef setReaderID(self):str = ''ID = str.join(random.choice('0123456789') for i in range(16))return ID# 定义阅读器的标签选择规则 tag=0 选择所有标签 tag=1 选择奇数标签 =2选择偶数标签def select(self, tagArray, tag=0):if tag == 0:for i in range(len(tagArray)):tagArray[i].selected = Trueprint('select阶段, 所有标签全部被选中')elif tag == 1:for i in range(1, len(tagArray), 2):tagArray[i].selected = Trueprint('select阶段, 奇数号标签全部被选中')else:for i in range(0, len(tagArray), 2):tagArray[i].selected = Trueprint('select阶段, 偶数号标签全部被选中')def QueryTagState(self, tagArray):cnt, index = 0, 0  # cnt为此刻slot值为0的标签数目,index为可得到回应的标签for i in range(len(tagArray)):if tagArray[i].slot == 0:cnt += 1index = iif cnt > 1:print('多个tag回应, 发生碰撞, 无法识别, 为Arbitrate状态')self.crush += 1# 碰撞次数大于随即数右端点的一半if self.crush > Tag.endPoint / 2:self.QueryAdjust()return None, indexelif cnt == 1:tagArray[index].setState('Reply')print('{}号tag,其ID为{},slot值为0, 回应reader的随机数为{}, tag进入{}状态'.format(index, tagArray[index].id,tagArray[index].returnRN16(),tagArray[index].state))return tagArray[index].returnRN16(), indexelse:print('无tag回应, 均为Arbitrate状态')self.noRespond += 1# 无响应次数大于随即数右端点的一半if self.noRespond > Tag.endPoint / 2:self.QueryAdjust()return None, index# 阅读器发出查询Query命令,被选择的标签开始置随机数slotdef Query(self, tagArray):print('********发出第一次Query********')for i in range(len(tagArray)):if tagArray[i].selected == True:tagArray[i].setSlot()tagArray[i].setState('Arbitrate')print('{}号tag,状态为{}'.format(i, tagArray[i].state))tag, index = self.QueryTagState(tagArray)return tag, indexdef QueryRep(self, tagArray):print('********发出QueryRep, 各标签slot值减1, 或恰好有标签响应********')for i in range(len(tagArray)):if tagArray[i].selected == True:tagArray[i].reduceSlot()tag, index = self.QueryTagState(tagArray)return tag, indexdef QueryAdjust(self, tagArray):print('********发出QueryAdjust, 根据碰撞次数和未响应次数调整slot阈值********')tagNum = len(tagArray)if self.noRespond > tagNum * 2:print('等待响应时间过长, {}轮未得到响应, 下调slot阈值'.format(self.noRespond))for i in range(tagNum):tagArray[i].adjustSlot(tag=False)self.noRespond = 0elif self.crush > tagNum * 2:print('碰撞{}轮, 过于频繁, 上调slot阈值'.format(self.crush))for i in range(tagNum):tagArray[i].adjustSlot(tag=True)self.crush = 0else:print('无需调整slot阈值, 已碰撞{}次, 等待响应{}轮'.format(self.crush, self.noRespond))# 收到标签的RN16 1.返回ACK指令夹带原RN16 或 2.返回ACK指令,但夹带的RN16错误def ACK(self, RN16):print('我收到了你的RN16{},ACK'.format(RN16))return RN16# 得到EPC码后 再次请求随机数 RN16为标签第一次返回的随机数def Req_RN(self, EPC, RN16):print('我收到了你的EPC{}, Req_RN, 请求返回一个新的随机数'.format(EPC))return RN16# 得到handle后 随机返回一次命令已经确认的handle值def Command(self, handle):commandSet = ['read', 'write', 'lock', 'kill']command = random.choice(commandSet)print('发出新命令{}'.format(command))return command, handledef read(self, tag):print('read tag data:')print('tagID:{}\n tagEPC:{}\n tagData:{}'.format(tag.id, tag.EPC, tag.data))return 1def write(self, tag):data = input('待写入数据:')tag.data = dataprint('写入完成')return 1def lock(self, tag):print('tagID:{}已lock'.format(tag.id))return 1def kill(self, tag):print('tagID:{} killed,访问结束'.format(tag.id))return 0

(3)Tag.py

import randomclass Tag:# 类属性endPoint = 4def __init__(self):self.id = self.setID()self.slot = Noneself.state = 'Ready'self.EPC = self.setEPC()self.selected = Falseself.len = Noneself.sendTime = Noneself.readerNum = Noneself.data = self.initData()# 给每一个标签一个唯一ID 生成16位随机数def setID(self):str = ''ID = str.join(random.choice('0123456789') for i in range(16))print('初始化标签ID,tagID={}'.format(ID))return ID# 给每个标签赋值一个给定区间[0,10]的随机数def setSlot(self):self.slot = random.randint(0, self.endPoint)print('随机给定slot值,tagID={}的slot值为{}, tag的右端点是{}'.format(self.id, self.slot, self.endPoint))# 收到QueryAdjust就调整区间右端点 根据tag的值来更改 调整槽计数器的范围 True上调 False下调def adjustSlot(self, tag=True):if tag == True:print()Tag.endPoint *= 2else:Tag.endPoint /= 2self.setSlot()def setLength(self, length):"""function: 设置数据包长度len和对应所需要的花费时间:return: NULL"""self.len = lengthself.sendTime = length * 0.5 + 0.1   #数据包发送时间# 自减Slotdef reduceSlot(self):self.slot = (self.slot-1+self.endPoint)%self.endPoint# 给每个标签赋值一个96位的随机数 即它的EPC码 只初始化一次def setEPC(self):str = ''RN96 = str.join(random.choice('0123456789') for i in range(96))return RN96# 返回EPC码def returnEPC(self):return self.EPC# 返回16位的随机数 RN16def returnRN16(self):str = ''RN16 = str.join(random.choice('0123456789') for i in range(16))return RN16# 返回一个新的随机数 即Handledef returnHandle(self):return self.returnRN16()# 改变标签状态def setState(self, newState):self.state = newStatedef initData(self):foodSet = ['奥利奥', '趣多多', '好丽友', '喜之郎', '娃哈哈']priceSet = ['10', '15', '21', '8', '29']food = random.choice(foodSet)price = random.choice(priceSet)return '我的存储区里搁了一个{},{}元一个'.format(food, price)

(4)概要介绍

在EPC C1G2协议标准中,标签的行为可以用有限状态机来描述,七个状态。

就绪态(ready state)
        就绪态是标签在通电前所处的状态。标签处于就绪态,不参与询问过程。
一个询问过程由阅读器发出的查询命令引起,由下一个查询命令终止。阅读器通过查询命令获得标签的EPC码。
当标签接收到一个查询命令,离开就绪态。标签从阅读器发送的查询命令中,选择一个参数生成随机数用于计算发送的时隙。如果随机数为0,则标签进入恢复状态。否则标签进入仲裁态。
仲裁态(arbitrate state)
        当标签处于仲裁态时,它将参加这一轮的查询。但由于此时的标签的时隙数不为0,所以标签等待时隙数变为0.当标签的时隙数变为0时,标签进入回复状态。
回复态(reply state)
        当标签需要回复EPC码时,首先进入的是回复态。这时,标签的时隙数为0,标签返回一个16比特的随机数RN16给阅读器。发送RN16是标签发送EPC码给阅读器的第一步。如果标签正确地接收到RN16,它将会发送一个确认命令ACK给标签。在接收RN16的时候,阅读器可能无法正确接收,主要原因有:a.两个或多个标签同时发生RN16给阅读器b.其它射频信号干扰了RN16的传输c.阅读器错过接收RN16的时间。
        如果标签成功接收到来自阅读器的确认命令ACK,标签将会发送它的EPC码,同时发送PC码(描述标签的物理信息)和CRC码(用于错误检测)。
接收到确认命令ACK引起标签从回复态进入确认态。标签处于回复态的时间有限,只有标签发送RN16后,没有接收到阅读器的任何命令的有效时间才处于该状态。此后,标签会自动进入仲裁态。
确认态(acknowledged state)
        当标签发送它的EPC码给阅读器后 ,标签进入确认态。确认态是标签进入访问命令的必经状态。在确认态中,标签不会被杀死。确认态就像回复态一样,有一个计时器,每当接收到一个命令式,计时器将会置位0。如果标签在指定的时间内没有收到来自阅读器的命令,标签将会自动返回仲裁态。
开放态
安全态
杀死态

        杀死操作不能被解除,它将会永远地毁坏标签。 对于一个标签而言,它是在接收到阅读器的正确的密码和杀死命令之后,才会进入杀死态。此后,标签会一直处于杀死态而不是就绪态。当标签进入杀死态,不会再响应阅读器的任何命令。

参考链接:

(24条消息) 标签的状态机_Caramel_biscuit的博客-CSDN博客_在确认态,标签会回复给阅读器pc

物联网与射频识别技术,课程实验(一)相关推荐

  1. 现代检测技术课程实验编程:最小二乘法应用编程

    现代检测技术课程实验编程:最小二乘法应用编程 一.最小二乘法编程题目描述 二.最小二乘法编程题目要求 三.什么是最小二乘法 四.最小二乘法编程步骤 4.1. 界面的设计 4.2. 程序的编写 4.2. ...

  2. Web前端开发技术课程实验报告实验3:Vue路由实验

    实验代码:实验3第2题实验参考.rar-互联网文档类资源-CSDN下载 Web前端开发技术课程实验报告 实验3:Vue路由实验 姓名:_ __ _ ___ ___   班级:_ _ _ ___ _ _ ...

  3. 现代检测技术课程实验:电桥测量位移

    现代检测技术课程:电桥测量位移 一.内容:电桥测量位移 二.电路连接 三.电路仿真 四.x与Uo的关系式 一.内容:电桥测量位移 电桥测量位移描述如下 使用2个线性电位器(总电阻值为R0=5000Ω, ...

  4. python扫雷游戏实验分析_高级编程技术课程实验报告-扫雷游戏

    班级 通 信 一 班 姓名 陈远春 学号 201100120084 课程实验内容 扫雷游戏,是 Windows 操作系统自带的一款经典游戏.其规则简单,上手 容易, 不论男女老少皆可娱乐. 扫雷的目的 ...

  5. 物联网与射频识别技术,课程实验(四)

    实验4-- 基于帧的时隙ALOHA(FSA)算法的实现与性能分析 实验说明: 利用Python或Matlab模拟基于帧的时隙ALOHA算法: 分析标签数量k.帧中所含时隙个数n对信道利用率的影响,其中 ...

  6. 江南大学物联网工程学院数据库课程实验二作业2实验报告

    一.开发环境 DBMS: Microsoft SQL Server 2019 (64- bit) 可视化管理工具: Microsoft SQL Server Management Studio- 18 ...

  7. 江南大学物联网工程学院数据库课程实验三作业3vb.net实验报告

    一.开发环境 语言环境:Microsoft.NET Framework 4.6 SDK IDE:Microsoft Visual Studio Community 2015 二.代码及配置 1.For ...

  8. 计算机仿真实验结果的评价与分析,基于问卷调查法的计算机仿真技术课程综合性实验效果分析评价...

    摘要:综合性实验对于提高学生综合素质,培养学生实践能力与创新精神具有极其重要的作用,为了科学评价计算机仿真技术课程综合性实验效果,文章基于问卷调查法,阐述如何设计情况调查表,如何采用多种评价方法对学生 ...

  9. 杨月江计算机导论答案,计算机导论课程实验教学大纲-计算机学院-华北科技学院.doc...

    计算机导论课程实验教学大纲-计算机学院-华北科技学院.doc 华 北 科 技 学 院 2010级 实验教学大纲 网络工程系 目 录 TOC \o "1-1" \h \z \u HY ...

最新文章

  1. Wireshark网络分析实例集锦2.1.2隐藏、删除、重新排序及编辑列
  2. CEV模型与质量甜点算法设计
  3. 如何解决JavaScript中0.1+0.2不等于0.3
  4. TypeScript开发手册
  5. centos7修改ip地址自动获取_南京课工场IT培训:如何搭建DHCP服务器及自动获取IP地址及相关操作...
  6. 蓝桥杯 ALGO31 算法训练 开心的金明 java版
  7. OpenCV-图像处理(09、模糊图像二)
  8. java opencv 模板匹配算法_OpenCV模板匹配算法详解
  9. java 解码和加密 汉信码_java中的编码与解码
  10. fluent p1模型_FLUENT模型选择
  11. 奇特的一生 柳比歇夫坚持56年的“时间统计法” - 读后感
  12. 台湾屏东大学校徽设计被指抄袭 校方:征选过程严谨
  13. 切换Apple Store ID后,Apple Mucic资料库无法加载问题的解决方案
  14. open-falcon judge部署
  15. c语言中常用的输入输出函数有哪些,C语言中常用的输入和输出函数
  16. 二进制补码加减运算的溢出检查
  17. 《置身事内》中国政府与经济发展读后梳理
  18. 智能千变模板直播带货骗局
  19. python 移动ui框架_Touch UI:基于vue的移动端UI框架
  20. C语言表白流星雨(二)

热门文章

  1. 用ChatGPT讲一个关于猴子的故事
  2. linux命令 清空文件夹,linux清空文件夹命令问题
  3. BLM业务领导力模型
  4. 市值超万亿港元!那个CEO写下70万行代码的公司上市了
  5. 【UCIe】UCIe 数据完整性
  6. 大数据时代,女性做数据分析师有没有优势?
  7. python版恶俗古风自动生成器.py
  8. vue首次加载生命周期
  9. [计算机、网络相关历史]unix简史
  10. 全网最通俗的条件随机场CRF