射频识别 — 防碰撞源码实现

一、状态转移

Python 实现

import random
import time


class Reader():
    def __init__(self, ACK, command, pwd, handle):
        self.ACK = ACK
        self.command = command
        self.pwd = pwd
        self.handle = handle


class RFID_Tag():

    def __init__(self, state, Slot, RN16, EPC, pwd, power, handle):
        self.state = state
        self.Slot = Slot
        self.RN16 = RN16
        self.pwd = pwd
        self.handle = handle
        self.power = power
        self.EPC = EPC

    def setRN16(self):
        str = ''
        rn16 = str.join(random.choice("0123456789") for i in range(2))
        self.RN16 = rn16

    def setEPC(self):
        str = ''
        epc = str.join(random.choice("0123456789") for i in range(32))
        self.EPC = epc

    def setHandle(self):
        str = ''
        handle = str.join(random.choice("0123456789") for i in range(3))
        self.handle = handle

    def setpwd(self):
        str = ''
        pwd = str.join(random.choice("0123456789") for i in range(4))
        self.pwd = pwd


reader = Reader(0, '', 0, 0)

Tag = RFID_Tag('', 0, '', '', 0, '', '')

while True:
    if reader.command == '' or reader.command == 'cw':  # 输入命令
        reader.command = input('阅读器发出命令:')

    if reader.command == "Select" and Tag.power != 0:  # 标签激活且命令为Select则进入就绪态
        Tag.state = 'ready state'

    elif reader.command == "cw" and Tag.state == '':  # 激活未激活的标签进入就绪态
        Tag.power = 10
        Tag.state = 'ready state'
        print("标签已激活并进入就绪态")

    elif reader.command == "Query" and Tag.state == 'ready state':  # 就绪->仲裁(query)
        Tag.Slot = random.randint(1, 3)
        Tag.setRN16()
        Tag.setEPC()
        Tag.setpwd()
        Tag.setHandle()
        print("标签的Slot初始化为:", Tag.Slot)
        print("标签的RN16初始化为:", Tag.RN16)
        print("标签的自身信息EPC为:", Tag.EPC)
        print("标签的自身句柄为:", Tag.handle)
        print("标签的自身访问密码为:", Tag.pwd)

        Tag.state = 'arbitrate state'
        print("进入仲裁态")
        reader.command = ''

    elif Tag.Slot != 0 and Tag.state == 'arbitrate state' and reader.command == "QueryRep":  # 仲裁->回复(query,Slot=0)
        Tag.Slot -= 1
        reader.command = ''

    elif Tag.Slot == 0 and Tag.state == 'arbitrate state' and reader.command == "QueryRep":  # 仲裁->回复(query,Slot=0)
        Tag.state = 'reply state'
        print("当前标签Slot减为0,进入回复态")
        Tag.Slot = random.randint(1, 6)
        # reader.command = input("是否继续通信:")

    elif Tag.state == 'reply state':  # 回复态
        print('标签发送RN16', Tag.RN16)
        reader.ack = Tag.RN16
        time.sleep(3)
        print('阅读器发送与标签发送来的相同RN16的ACK', reader.ack, '以此进行确认')
        time.sleep(3)
        print('标签发送携带有自身信息的EPC', Tag.EPC)
        time.sleep(3)
        Tag.state = 'acknowledged state'
        print("进入确认态")
        # reader.command = input("是否继续通信:")

    elif Tag.state == 'acknowledged state':  # 确认态
        print('阅读器发送携带有之前RN16的Req_RN, 要求标签返回一个句柄')
        time.sleep(1)
        print("标签返回句柄", Tag.handle)
        time.sleep(1)

        if Tag.pwd * 1 == 0:
            Tag.state = 'secured state'
            print("密码功能未执行或启用,标签进入安全态,开始执行操作")
            reader.command = 'op'
        else:
            Tag.state = 'open state'
            print("密码功能有效,标签进入开放态")
            reader.command = 'op'

    elif Tag.state == 'open state' and reader.command == 'op':  # 开放态
        reader.handle = input("阅读器输入句柄进行回复:")
        reader.pwd = input('阅读器输入密码进行确认访问: ')
        if reader.handle == Tag.handle and reader.pwd == Tag.pwd:
            Tag.state = 'secured state'
            print("密码和句柄正确,标签进入安全态, 开始执行操作")
            reader.command = 'op'
        else:
            print("密码或句柄错误")
            Tag.power = Tag.power - 1
            reader.command = 'op'
        if Tag.power == 0:
            Tag.state = ''
            reader.command = ''
            print("能量耗尽")

    elif Tag.state == 'secured state' and reader.command == 'op':  # 安全态
        reader.command = input("阅读器发出操作命令:")
        if reader.command == 'kill':
            if Tag.pwd * 1 != 0:
                reader.handle = input('请输入操作句柄:')
                reader.pwd = input("请输入标签密码:")
                if reader.handle == Tag.handle and reader.pwd == Tag.pwd:
                    Tag.state = 'killed state'
                    print(Tag.state, "标签已被杀死, 后续将无法访问")
                    break
                else:
                    print("密码或句柄错误")
                    reader.command = 'op'
            else:
                reader.handle = input('请输入正确的句柄:')
                if reader.handle == Tag.handle:
                    Tag.state = 'killed state'
                    print(Tag.state, "句柄正确,杀死标签")
                    break
                else:
                    print("句柄错误!")
                    reader.command = 'op'

    else:
        print('不属于阅读器内部命令,无法操作')
        reader.command = ''

    if Tag.state == 'ready state' and reader.command != "CW":
        print("标签进入就绪态")
        reader.command = ''


二、纯ALOHA

1.实验数据包长度对识别标签效率的影响

MATLAB

Total_Datalen = 1000;
index = linspace(0, 0.12, Total_Datalen);
rate = zeros(1, Total_Datalen);
tag = 10;
for k = 1 : 1 : Total_Datalen    
    T0 = index(k)
    n = 1000;        % 标签发送标识符的次数             
    D = rand(tag,n);  % m 个 标签, n 次仿真
    D1 = 0.5 * D;     %生成区间在[0, 0.5],作为仿真的每个标签的发送时间         
    Init_Tag_send_Time = cumsum(D1, 2);   %按行求和          
    T = Init_Tag_send_Time(1, n);        % 第一行最后一个数作为总信道占有的时间          
    Tag_send_Time = 1 : 1: (tag * n);    %初始化后将求和后的矩阵 B 转化为向量 C             
    for i = 1 : tag                   
        for j = 1 : n
            Tag_send_Time(1, (i-1) * n + j) = Init_Tag_send_Time(i, j);
        end
    end
    D = sort(Tag_send_Time);                  
    Tag_send_interval = diff(D);    %求前后相邻元素的差分, 作为开始发送和结束发送的位置                  
    send_success = 0;                                              
    for i = 1 : (tag * n-1)              
          if D(1,i) <= T           
             if i == 1 && Tag_send_interval(1, 1) >= T0  
                  send_success = send_success + 1;
             elseif i == (tag*n-1) && Tag_send_interval(1,(tag*n-1)) >= T0
                  send_success = send_success + 1;
             elseif Tag_send_interval(1,i) >= T0 && Tag_send_interval(1,i-1) >= T0
                  send_success = send_success + 1;
             end
          end
    end
    rate(k) = T0/T * send_success; 
end

plot(index, rate, 'r.', 'LineWidth', 3)
hold on;
axis on; grid on;
xlabel('数据包长度');
ylabel('信道利用率');
title('纯ALOHA协议,数据包长度与信道利用率的关系');
                   

2.标签数量对识别效率的影响

Total_Tag = input('请输入标签数量:')
rate = zeros(1, Total_Tag)
for tag = 2 : 1 : Total_Tag                        
    n = 100;        % 标签发送标识符的次数             
    D = rand(tag,n);  % m 个 标签, n 次仿真
    D1 = 0.5 * D;     %生成区间在[0, 0.5],作为仿真的每个标签的发送时间         
    Init_Tag_send_Time = cumsum(D1, 2);   %按行求和          
    T = Init_Tag_send_Time(1, n);        % 第一行最后一个数作为总信道占有的时间          
    Tag_send_Time = 1 : 1: (tag * n);    %初始化后将求和后的矩阵 B 转化为向量 C             
    for i = 1 : tag                   
        for j = 1 : n
            Tag_send_Time(1, (i-1) * n + j) = Init_Tag_send_Time(i, j);
        end
    end
    D = sort(Tag_send_Time);                  
    Tag_send_interval = diff(D);    %求前后相邻元素的差分, 作为开始发送和结束发送的位置             
    T0 = 0.001;     %固定每个标签发送数据所需要的时间           
    send_success = 0;                                              
    for i = 1 : (tag * n-1)              
          if D(1,i) <= T           
             if i == 1 && Tag_send_interval(1, 1) >= T0  
                  send_success = send_success + 1;
             elseif i == (tag*n-1) && Tag_send_interval(1,(tag*n-1)) >= T0
                  send_success = send_success + 1;
             elseif Tag_send_interval(1,i) >= T0 && Tag_send_interval(1,i-1) >= T0
                  send_success = send_success + 1;
             end
          end
    end
    rate(tag) = T0/T * send_success 
end

plot(1:Total_Tag, rate, 'r.', 'LineWidth', 3)
hold on;
axis on; grid on;
xlabel('RFID标签数量');
ylabel('信道利用率');
title('纯ALOHA协议,标签个数对信道利用率的关系');
                   


三、时隙ALHA

MATLAB

1.标签数量对识别效率的影响

Total_Tag = input('请输入标签数量:');
T = 1
S = zeros(1, Total_Tag);
n = 10000;       %信道
for tag = 1 : 1 : Total_Tag  
    % 生成平均值为m服从泊松分布的随机数
    B = poissrnd(tag, 1, n); %以tag的值作为lamda
    % free空闲,send有效,collision冲突
    send = 0 ;
    free = 0;
    collision = 0;
    for j = 1 : n
        if B(1, j) < T
            free = free + 1;
        elseif B(1, j) == T
            send = send + 1;
        elseif B(1, j) > T
            collision = collision + 1;
        end
    end
    S(tag) = send / n;
   
end

plot(1:Total_Tag, S, 'b-.', 'LineWidth', 1)
hold on;
axis on; grid on;
xlabel('RFID标签数量');
ylabel('信道利用率');
title('S-ALOHA协议,标签个数对信道利用率的关系');

    

2.实验数据包长度对识别标签效率的影响

Tag = 10
S = zeros(1, 26);
n = 10000;       %信道
for T = 1 : 1 : 25  
    % 生成平均值为m服从泊松分布的随机数
    B = poissrnd(Tag, 1, n); %以tag的值作为lamda
    % free空闲,send有效,collision冲突
    send = 0 ;
    free = 0;
    collision = 0;
    for j = 1 : n
        if B(1, j) < T
            free = free + 1;
        elseif B(1, j) == T
            send = send + 1;
        elseif B(1, j) > T
            collision = collision + 1;
        end
    end
    S(T) = send / n * 3;
   
end

plot(1:26, S, 'b-.', 'LineWidth', 1)
hold on;
axis on; grid on;
xlabel('数据包的长度');
ylabel('信道利用率');
title('S-ALOHA协议,标签个数对信道利用率的关系');

    

四、 FSA

Python

import random
import time
import matplotlib.pyplot as plt
import sys
import numpy as np
import pandas as pd


class Reader():
    def __init__(self, ACK, command, pwd, handle):
        self.ACK = ACK
        self.command = command
        self.pwd = pwd
        self.handle = handle


class RFID_Tag():

    # S为一帧中的某个时隙
    def __init__(self, state, Slot, RN16, EPC, SN, S, handle):
        self.state = 'unselect'
        self.Slot = Slot
        self.RN16 = RN16
        self.SN = SN
        self.handle = handle
        self.S = S
        self.EPC = EPC

    def setRN16(self):
        str = ''
        rn16 = str.join(random.choice("0123456789") for i in range(2))
        self.RN16 = rn16

    def setEPC(self):
        str = ''
        epc = str.join(random.choice("0123456789") for i in range(32))
        self.EPC = epc

    def setHandle(self):
        str = ''
        handle = str.join(random.choice("0123456789") for i in range(3))
        self.handle = handle

    def setpwd(self):
        str = ''
        pwd = str.join(random.choice("0123456789") for i in range(4))
        self.pwd = pwd


reader = Reader(0, '', 0, 0)

respond = 0

#每帧的时隙数
SN = [32, 64, 128]

taglist = [ [] for i in range(4)]
Channel_utilization = [ [] for i in range(4)]
L = 0
sum1 = 0

#第一层循环是为了取得三个曲线
for L in range(3) :
    for n in range(1, 750, 2):
        taglist[L].append(n)
        #定义RFID个数
        RFID = [RFID_Tag('', 0, '', '', 0, False, '') for _ in range(n)]
        for i in range(n):
            RFID[i].SN = random.randint(0, SN[L] - 1)
        # for i in range(n):
        #     print(i, "号标签的 SN 为: % i" % RFID[i].SN)
        respond = 0
        Q = 0 #记录当前处理的帧数
        while True:
            Q += 1 # 记录总帧数
            total = 0 #识别的标签数
            Finish = False #判断是否完成
            for i in range(n):
                if RFID[i].state == 'select':
                    total += 1
                    if (total == n):
                        Q -= 1
                        t = total / (SN[L] * Q)
                        Channel_utilization[L].append(t)
                        sum1 = sum1 + t
                        # print("所有标签均响应成功,信道利用率为 %.2lf" % (total / (SN * Q)))
                        Finish = True
                        break

            if Finish : break

            for i in range(n):
                RFID[i].S = False

            # 遍历每帧内部的所有时隙
            for ver in range(SN[L]):
                success = True
                count = 0
                for i in range(n):
                    if RFID[i].state == 'unselect':
                        if RFID[i].SN == ver and RFID[i].S == False:
                            count += 1
                            if (count > 1):
                                success = False


                #注意当标签的数目为0时,也可以满足条件进入
                if success:
                    for i in range(n):
                        if RFID[i].state == 'unselect' and RFID[i].SN == ver and RFID[i].S == False:
                            RFID[i].S = True
                            respond += 1
                            RFID[i].state = 'select'
                            # print(i, "号标签成功被响应")

                else:
                    # print('多个标签同时响应,重新分配给相应标签Slot')
                    for i in range(n):
                        if RFID[i].SN == ver and RFID[i].state == 'unselect':
                            RFID[i].S = True  # 防止在同一帧下再次发出表示符
                            RFID[i].SN = random.randint(0, SN[L] - 1)

    print("第一层完成")

plt.rcParams['font.sans-serif'] = ['SimHei']  # 正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号

data = {'L=32':Channel_utilization[0],
        'L=64':Channel_utilization[1],
        'L=128':Channel_utilization[2]}

# print(len(taglist[0]))
df = pd.DataFrame(data, index=taglist[0])
fig = df.plot(figsize=(8,6))
plt.xlabel('标签数量') # x轴标签
plt.ylabel('信道利用率') # y轴标签
plt.title('FSA') # 图名称
plt.show()

五、随机二进制数

Python

import random
import sys
import time
import matplotlib.pyplot as plt


class RFID_Tag:
    def __init__(self, count, state):
        self.count = count
        self.state = state

n = 3
RFID = [RFID_Tag(0, 'unrespond') for _ in range(n)]
taglist = []
allresponse = []
SpendTime = []

#为标签定义三个状态,成功识别为responded , 中间识别为respond, 为被识别为 unrespond
for n in range(1, 3000):
    taglist.append(n)
    RFID = [RFID_Tag(0, 'unrespond') for _ in range(n)]
    total = 0
    finish = False
    Time = 0
    while True:

        Time += 1
        for i in range(n):
            if RFID[i].count == 0 and RFID[i].state == 'unrespond':
                RFID[i].state = 'respond'
                allresponse.append(i)

        if len(allresponse) <= 1:
            allresponse = []
            for i in range(n):
                if RFID[i].state == 'respond':
                    RFID[i].state = 'responded'
                elif RFID[i].state == 'unrespond':
                    RFID[i].count -= 1

        else :
            allresponse = []
            for i in range(n):
                if RFID[i].state == 'respond':
                    RFID[i].count = RFID[i].count + random.randint(0, 1)
                    RFID[i].state = 'unrespond'
                elif RFID[i].state == 'unrespond':
                    RFID[i].count += 1
                    # print('没有成功被识别的标签计数器加1')

        for i in range(n):
            if RFID[i].state == 'responded':
                total += 1
                if(total == n) :
                    # print('所有标签识别完成')
                    finish = True
        if finish :
            break

    SpendTime.append(Time-1)

plt.figure(figsize=(8,6))
# figsize:创建图表窗口,设置窗口大小
plt.rcParams['font.sans-serif'] = ['SimHei']  # 正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号
# plt.plot(taglist,SpendTime,linestyle = '-',linewidth = 2, c = 'r',label = '标签数量与遍历所有标签所需的时间关系')
plt.scatter(taglist,SpendTime,linestyle = '-',linewidth = 2, c = 'r',label = '标签数量与遍历所有标签所需的时间关系')
plt.xlabel('标签数量') # x轴标签
plt.ylabel('时间') # y轴标签
plt.title('Random_binary_tree') # 图名称

plt.legend(loc = 'best')
plt.show()

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值