基于python实现ZigBee树状拓扑网络建构与动态地址分配及路由仿真

时间:2021-1-8 作者:admin

实现ZigBee树状拓扑网络建构与动态地址分配及路由仿真

输出效果基于python实现ZigBee树状拓扑网络建构与动态地址分配及路由仿真

基于python实现ZigBee树状拓扑网络建构与动态地址分配及路由仿真

基于python实现ZigBee树状拓扑网络建构与动态地址分配及路由仿真
源代码以及分析

import tkinter as tk
import random
import math
import sys
# 设置最大递归次数
sys.setrecursionlimit(2000)
# 设置一个常量代表传感器固定半径
SENOR_RADIUS = 6
class Window:
    def __init__(self, master):
        self.root = master
        self.createpage()
        self.run()
    '''创建界面'''
    def createpage(self):
        self.root.geometry('1210x710')
        # 设置窗口是否可以变化长/宽,False不可变,True可变,默认为True
        self.root.resizable(width=False, height=False)
        #设置模块1 参数输入 的各个部件在窗口的相对位置横坐标
        flame1_text_x = 130
        #设置外围框,让界面更好看
        tk.LabelFrame(self.root, text='|参数|', fg='black', padx=10, pady=10,font='Verdana 10 bold').place(x=10, y=10, height=250, width=290)
        # ZigBee网络的nwkMaxChildren (Cm)
        tk.Label(self.root, text='最大子节点数(Cm):', fg='black').place(x = 15, y = 35)
        self.nwkMaxChildren_text = tk.StringVar(value="5")
        self.nwkMaxChildren = tk.Entry(self.root, textvariable=self.nwkMaxChildren_text)
        self.nwkMaxChildren.place(x = flame1_text_x , y = 35)
        # nwkMaxRouters (Rm)
        tk.Label(self.root, text='ZR节点数(Rm):', fg='black').place(x = 15, y = 65)
        self.nwkMaxRouters_text = tk.StringVar(value="3")
        self.nwkMaxRouters = tk.Entry(self.root, textvariable=self.nwkMaxRouters_text)
        self.nwkMaxRouters.place(x = flame1_text_x , y = 65)
        # newMaxDepth (Lm)
        tk.Label(self.root, text='网络最大深度(Lm):', fg='black').place(x=15, y=95)
        self.newMaxDepth_text = tk.StringVar(value="5")
        self.newMaxDepth = tk.Entry(self.root, textvariable=self.newMaxDepth_text)
        self.newMaxDepth.place(x = flame1_text_x , y = 95)
        # 协调器(coordinator)
        tk.Label(self.root, text='协调器(ZC):', fg='black').place(x=15, y=125)
        self.coordinator_text = tk.StringVar(value="1")#由于ZC的值固定为 1,所以我们也要设置ZC的值为 1
        self.coordinator = tk.Entry(self.root, textvariable=self.coordinator_text, state = 'readonly')
        # state Entry 组件可以设置的状态:"normal","disabled" 或 "readonly"
        #(注意,它跟 "disabled" 相似,但它支持选中和拷贝,只是不能修改,而 "disabled" 是完全禁止)
        self.coordinator.place(x = flame1_text_x , y = 125)
        # 路由器(Router)
        tk.Label(self.root, text='路由器(ZR):', fg='black').place(x=15, y=155)
        self.router_text = tk.StringVar(value="15")
        self.router = tk.Entry(self.root, textvariable=self.router_text)
        self.router.place(x = flame1_text_x , y = 155)
        # 普通节点(Device)
        tk.Label(self.root, text='终端节点(ZED):', fg='black').place(x=15, y=185)
        self.device_text = tk.StringVar(value="15")
        self.device = tk.Entry(self.root, textvariable=self.device_text)
        self.device.place(x = flame1_text_x , y = 185)
        #传感器通讯距离(distance_get)
        tk.Label(self.root, text='传感器通讯距离:', fg='black').place(x=15, y=215)
        self.distance_get_text = tk.StringVar(value="300")
        self.distance_get = tk.Entry(self.root, textvariable=self.distance_get_text)
        self.distance_get.place(x = flame1_text_x , y = 215)
        # 创建按钮
        tk.Button(self.root, text='ZigBee传感器布置', command=self.Pictue_Create).place(x=50, y=280,height=50, width=200)
        #设置模块2 路径查找 的各个部件在窗口的相对位置纵坐标
        flame2_text_y = 400
        #创建外包框
        tk.LabelFrame(self.root, text='|路径查找|', fg='black', padx=10, pady=10,font='Verdana 10 bold').place(x=10, y=flame2_text_y, height=120, width=290)
        #source_node_address 源节点地址
        tk.Label(self.root, text='源节点地址:', fg='black').place(x=15, y=flame2_text_y + 30)
        self.source_node_address_text = tk.StringVar()
        self.source_node_address = tk.Entry(self.root, textvariable=self.source_node_address_text)
        self.source_node_address.place(x = flame1_text_x , y = flame2_text_y + 30)
        #destination_node_address 目的节点地址
        tk.Label(self.root, text='目的节点地址:', fg='black').place(x=15, y=flame2_text_y + 70)
        self.destination_node_address_text = tk.StringVar()
        self.destination_node_address = tk.Entry(self.root, textvariable=self.destination_node_address_text)
        self.destination_node_address.place(x = flame1_text_x , y = flame2_text_y + 70)
        # 创建按钮
        tk.Button(self.root, text='显示路径', command =  self.Path_Lookup_ready ).place(x=50, y=flame2_text_y + 140,height=50, width=200)      
        # 创建画布
        self.cv = tk.Canvas(self.root, bg='white', width=900, height=700)
        self.cv.place(x=300)
        
    '''清空内容'''
    def Wipe_Data(self):
        # 清空文本框和画图框内的内容
        self.cv.delete(tk.ALL)
    '''创建ZC中心传感器'''
    def Gathering_Point_Create(self):
        self.sensor_zc[0][0] = self.gathering_point_center_x
        self.sensor_zc[0][1] = self.gathering_point_center_y
        #设置标志数,表示这个传感器是ZC
        self.sensor_zc[0][9] = 0
        self.cv.create_oval((self.gathering_point_center_x - SENOR_RADIUS, self.gathering_point_center_y - SENOR_RADIUS,
                                self.gathering_point_center_x + SENOR_RADIUS, self.gathering_point_center_y + SENOR_RADIUS),
                                outline='black',
                                fill='red'
                            )
        #设置ZC的初始地址和计算出C(skip)的值
        self.sensor_zc[0][7] = 6
        if(self.Rm == 1):
            Cskip = 1 + self.Cm * (self.Lm - self.sensor_zc[0][5] - 1)
        else:
            Cskip = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - self.sensor_zc[0][5] - 1))) / (1 - self.Rm)
        self.sensor_zc[0][8] = int(Cskip)
        address = str(self.sensor_zc[0][7])
        C_skip = str(self.sensor_zc[0][8])
        text_string = address + " C:" + C_skip
        #创建字体
        self.cv.create_text(self.gathering_point_center_x, self.gathering_point_center_y + self.canvas_text_y, text = 'ZC-' + text_string)
    '''创建ZR中心传感器'''
    def ZR_Sensor_Create(self):    
        for num_sensor_zr_temp in range(0, self.Zr):
            circle_center_x = random.randint(15, 885)
            circle_center_y = random.randint(15, 685)
            # 将每次随机生成的传感器的坐标 放入列表
            self.sensor_zr[num_sensor_zr_temp][0] = circle_center_x
            self.sensor_zr[num_sensor_zr_temp][1] = circle_center_y
            #设置标志数,表示这个传感器是ZR
            self.sensor_zr[num_sensor_zr_temp][9] = 1
            self.cv.create_rectangle((circle_center_x - 5, circle_center_y - 5,
                                 circle_center_x + 10, circle_center_y + 5),
                                 outline='blue',
                                 fill='blue'
                                )

    '''创建ZED中心传感器'''
    def ZED_Sensor_Create(self):   
        for num_sensor_zr_temp in range(0, self.Zed):
            circle_center_x = random.randint(15, 885)
            circle_center_y = random.randint(15, 685)
            # 将每次随机生成的传感器的坐标 放入列表
            self.sensor_zed[num_sensor_zr_temp][0] = circle_center_x
            self.sensor_zed[num_sensor_zr_temp][1] = circle_center_y
            #设置标志数,表示这个传感器是ZED
            self.sensor_zed[num_sensor_zr_temp][7] = 2
            self.cv.create_oval((circle_center_x - SENOR_RADIUS, circle_center_y - SENOR_RADIUS,
                                 circle_center_x + SENOR_RADIUS, circle_center_y + SENOR_RADIUS),
                                 outline='purple',
                                 fill='purple'
                                )

    '''在canvas上画图'''
    def Pictue_Create(self):
        #将打印在画布上的信息格式化
        self.canvas_text_y = 12
        # 清空内容
        self.Wipe_Data()
        # 获取输入框中的内容
        self.Cm = self.nwkMaxChildren.get()
        self.Rm = self.nwkMaxRouters.get()
        self.Lm = self.newMaxDepth.get()
        self.Zc = self.coordinator.get()
        self.Zr = self.router.get()
        self.Zed = self.device.get()
        self.distance = self.distance_get.get()       
        # 打印获取的内容
        #将获取的数值转成int
        self.Cm = int(self.Cm)
        self.Rm = int(self.Rm)
        self.Lm = int(self.Lm)
        self.Zc = int(self.Zc)
        self.Zr = int(self.Zr)
        self.Zed = int(self.Zed)
        self.distance = int(self.distance)
        # 创建存储ZC(协调器)的二维列表
        self.sensor_zc = [[0 for i in range(10)]]
        # 创建存储ZR(路由器)的二维列表
        self.sensor_zr = [[0 for i in range(10)]for j in range(self.Zr)]
        # 创建存储ZED普通节点(Device)的二维列表
        self.sensor_zed = [[0 for i in range(8)]for j in range(self.Zed)]
        # 确定Zc的坐标&
        self.gathering_point_center_x = 450
        self.gathering_point_center_y = 350
        # 生成通讯中心(ZC)
        self.Gathering_Point_Create()
        # 创建临时数组储存已经进行连接的ZR、ZED传感器坐标等等信息
        self.sensor_zr_temp = []
        self.sensor_zed_temp = []
        #创建ZR、ZED传感器
        self.ZR_Sensor_Create()
        self.ZED_Sensor_Create()
        #打印生成的两个数组
        '''
        print('==========================================================')
        print("这是连接的ZR保存数值的列表:",self.sensor_zr)
        print("这是连接的ZED保存数值的列表:",self.sensor_zed)
        print('==========================================================')
        '''
        #判断每个传感器上的点的连接
        self.Tree_Topology_Establishment()
        #打印生成的两个数组
        '''
        print('----------------------------------------------------------')
        print("这是连接的ZC保存所有数值的列表:",self.sensor_zc)
        print("这是连接的ZR保存所有数值的列表:",self.sensor_zr_temp)
        print("这是连接的ZR保存没有连接的列表:",self.sensor_zr)
        print("这是连接的ZED保存的列表:",self.sensor_zed_temp)
        print("这是连接的ZED保存没有连接的列表:",self.sensor_zed)
        print('----------------------------------------------------------')
        '''
    '''计算ZC与旁边传感器ZC和ZED的关系,符合条件的进行连接'''
    def Cal_ZC_Connect(self):
        #把ZR旁边的ZED结点连接起来R
        for num_sensor_zr in range(0, self.Zr):
            temp_x = self.gathering_point_center_x - self.sensor_zr[num_sensor_zr][0]
            temp_y = self.gathering_point_center_y - self.sensor_zr[num_sensor_zr][1]
            temp_x = temp_x * temp_x
            temp_y = temp_y * temp_y
            temp_distance = math.sqrt(temp_x + temp_y)
            #两点的距离小于规定的传感器通讯距离
            if(temp_distance <= self.distance):
                if(self.sensor_zc[0][3] < self.Cm):
                    if(self.sensor_zc[0][4] < self.Rm):
                        self.sensor_zc[0][4] = self.sensor_zc[0][4] + 1
                        self.sensor_zc[0][3] = self.sensor_zc[0][3] + 1
                        self.sensor_zr[num_sensor_zr][2] = 1
                        self.sensor_zr[num_sensor_zr][5] = self.sensor_zc[0][5] + 1
                        #显示子结点在父节点中的编号
                        self.sensor_zr[num_sensor_zr][6] = self.sensor_zc[0][4]
                        #地址的分配
                        if(self.Rm == 1):
                            Cskip = 1 + self.Cm * (self.Lm - self.sensor_zc[0][5] - 1)
                        else:
                            Cskip = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - self.sensor_zc[0][5] - 1))) / (1 - self.Rm)
                        #计算下一个子结点的地址
                        self.sensor_zr[num_sensor_zr][7] = self.sensor_zc[0][7] + 1 + self.sensor_zc[0][8] * (self.sensor_zc[0][4] - 1)
                        #计算下一个子结点的Cskip并存入数组
                        Cskip_child = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - self.sensor_zr[num_sensor_zr][5] - 1))) / (1 - self.Rm)
                        self.sensor_zr[num_sensor_zr][8] = int(Cskip_child)
                        #把地址和其他数据显示在传感器下面
                        address = str(self.sensor_zr[num_sensor_zr][7])
                        C_skip = str(self.sensor_zr[num_sensor_zr][8])
                        Num = str(self.sensor_zr[num_sensor_zr][6])
                        text_string = 'A:' + address# + ' C:' + C_skip + ' N:' + Num
                        self.cv.create_text(self.sensor_zr[num_sensor_zr][0], self.sensor_zr[num_sensor_zr][1] + self.canvas_text_y, text='ZR-' + text_string)
                        #对两个传感器进行连接
                        self.cv.create_line(self.gathering_point_center_x, self.gathering_point_center_y,
                                            self.sensor_zr[num_sensor_zr][0], self.sensor_zr[num_sensor_zr][1],
                                            fill='orange')
                        #创建临时数组存储已经连接的传感器的数据
                        temp_arr = self.sensor_zr[num_sensor_zr][::]
                        self.sensor_zr_temp.append(temp_arr)
        #把ZC旁边的ZED结点连接起来
        for num_sensor_zed in range(0, self.Zed):
            temp_x = self.gathering_point_center_x - self.sensor_zed[num_sensor_zed][0]
            temp_y = self.gathering_point_center_y - self.sensor_zed[num_sensor_zed][1]
            temp_x = temp_x * temp_x
            temp_y = temp_y * temp_y
            temp_distance = math.sqrt(temp_x + temp_y)
            #两点的距离小于规定的传感器通讯距离
            if(temp_distance <= self.distance):
                if((self.Cm - self.sensor_zc[0][3]) > 0):
                    if(self.sensor_zed[num_sensor_zed][2] == 0):
                        self.sensor_zc[0][3] = self.sensor_zc[0][3] + 1
                        self.sensor_zed[num_sensor_zed][2] = 1
                        self.sensor_zed[num_sensor_zed][3] = self.sensor_zc[0][5] + 1
                        #显示子结点在父节点中的编号
                        self.sensor_zed[num_sensor_zed][4] = self.sensor_zc[0][3] - self.sensor_zc[0][4]
                        #地址的分配
                        if(self.Rm == 1):
                            Cskip = 1 + self.Cm * (self.Lm - self.sensor_zc[0][5] - 1)
                        else:
                            Cskip = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - self.sensor_zc[0][5] - 1))) / (1 - self.Rm)
                        #计算ZED的address
                        self.sensor_zed[num_sensor_zed][5] = self.sensor_zc[0][7] + self.sensor_zc[0][8] * self.Rm + self.sensor_zc[0][3] - self.sensor_zc[0][4]                        
                        #把地址显示在传感器下面
                        address = str(self.sensor_zed[num_sensor_zed][5])
                        Num = str(self.sensor_zed[num_sensor_zed][4])
                        text_string = 'A:' + address# + ' N:' + Num
                        self.cv.create_text(self.sensor_zed[num_sensor_zed][0], self.sensor_zed[num_sensor_zed][1] + self.canvas_text_y, text='ZED-' + text_string)
                        #对两个传感器之间连线
                        self.cv.create_line(self.gathering_point_center_x, self.gathering_point_center_y,
                                            self.sensor_zed[num_sensor_zed][0], self.sensor_zed[num_sensor_zed][1],
                                            fill='orange')
                        #创建临时数组存储已经连接的传感器的数据
                        temp_arr = self.sensor_zed[num_sensor_zed][::]
                        self.sensor_zed_temp.append(temp_arr)
    '''计算ZR与旁边传感器ZR的关系,符合条件的进行连接'''                
    def Cal_Con_ZRtoZR_Recursion(self):
        # 设置标志数
        self.i = 0
        # 对列表求差集
        difference_set = list(set([tuple(t) for t in self.sensor_zr]).difference(set([tuple(t) for t in self.sensor_zr_temp])))
        self.sensor_zr.clear()
        # 求差集以后 会变成列表包元组 需要转化成列表包列表
        for num_sensor_zr_temp in range(0, (len(difference_set))):
            temp_arr_a = [  difference_set[num_sensor_zr_temp][0], 
                            difference_set[num_sensor_zr_temp][1], 
                            difference_set[num_sensor_zr_temp][2], 
                            difference_set[num_sensor_zr_temp][3], 
                            difference_set[num_sensor_zr_temp][4], 
                            difference_set[num_sensor_zr_temp][5],
                            difference_set[num_sensor_zr_temp][6],
                            difference_set[num_sensor_zr_temp][7],
                            difference_set[num_sensor_zr_temp][8],
                            difference_set[num_sensor_zr_temp][9]]
            self.sensor_zr.append(temp_arr_a)
        '''
        print('----------------------------------------------------------')
        print("这是sensor_zr列表:",self.sensor_zr,"它的长度为",len(self.sensor_zr))
        print("这是sensor_zr_temp列表:",self.sensor_zr_temp,"它的长度为",len(self.sensor_zr_temp))
        print('----------------------------------------------------------')
        '''
        # 对sensor_zr_temp 和 sensor_zr两个列表遍历
        '''
        外层循环:对符合要求并已经进行连接的传感器坐标列表遍历
        '''
        for num_sensor_zr_temp in range(0, len(self.sensor_zr_temp)):
            #sensor_zr_temp: 储存符合要求并已经进行连接的传感器坐标
            '''
            内层循环:对没有遍历或者不符合要求的传感器坐标遍历
            '''
            for num_sensor_zr in range(0, len(self.sensor_zr)):
                #sensor_zr: 储存没有遍历或者不符合要求的传感器坐标
                temp_x = self.sensor_zr[num_sensor_zr][0] - self.sensor_zr_temp[num_sensor_zr_temp][0]
                temp_y = self.sensor_zr[num_sensor_zr][1] - self.sensor_zr_temp[num_sensor_zr_temp][1]
                temp_x = temp_x * temp_x
                temp_y = temp_y * temp_y
                temp_distance = math.sqrt(temp_x + temp_y)
                #判断每个点与剩余未连接点的连接情况
                if(temp_distance <= self.distance):
                    if(self.sensor_zr_temp[num_sensor_zr_temp][3] < self.Cm):
                        if(self.sensor_zr_temp[num_sensor_zr_temp][4] < self.Rm):
                            if(self.sensor_zr_temp[num_sensor_zr_temp][5] < self.Lm):
                                if(self.sensor_zr[num_sensor_zr][2] == 0):
                                    self.sensor_zr_temp[num_sensor_zr_temp][4] = self.sensor_zr_temp[num_sensor_zr_temp][4] + 1
                                    self.sensor_zr_temp[num_sensor_zr_temp][3] = self.sensor_zr_temp[num_sensor_zr_temp][3] + 1
                                    self.sensor_zr[num_sensor_zr][2] = 1
                                    self.sensor_zr[num_sensor_zr][5] = self.sensor_zr_temp[num_sensor_zr_temp][5] + 1
                                    #显示子结点在父节点中的编号
                                    self.sensor_zr[num_sensor_zr][6] = self.sensor_zr_temp[num_sensor_zr_temp][4]
                                    #地址的分配
                                    if(self.Rm == 1):
                                        Cskip = 1 + self.Cm * (self.Lm - self.sensor_zr_temp[num_sensor_zr_temp][5] - 1)
                                    else:
                                        Cskip = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - self.sensor_zr_temp[num_sensor_zr_temp][5] - 1))) / (1 - self.Rm)
                                    self.sensor_zr[num_sensor_zr][7] = self.sensor_zr_temp[num_sensor_zr_temp][7] + 1 + self.sensor_zr_temp[num_sensor_zr_temp][8] * (self.sensor_zr_temp[num_sensor_zr_temp][4] - 1) 
                                    Cskip_child = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - self.sensor_zr[num_sensor_zr][5] - 1))) / (1 - self.Rm)
                                    self.sensor_zr[num_sensor_zr][8] = int(Cskip_child)
                                    #把地址显示在传感器下面
                                    address = str(self.sensor_zr[num_sensor_zr][7])
                                    C_skip = str(self.sensor_zr[num_sensor_zr][8])
                                    Num = str(self.sensor_zr[num_sensor_zr][6])
                                    text_string = 'A:' + address# + ' C:' + C_skip + ' N:' + Num
                                    self.cv.create_text(self.sensor_zr[num_sensor_zr][0], self.sensor_zr[num_sensor_zr][1] + self.canvas_text_y, text='ZR-' + text_string)
                                    
                                    #对两个传感器连线
                                    self.cv.create_line(self.sensor_zr[num_sensor_zr][0], self.sensor_zr[num_sensor_zr][1],
                                                        self.sensor_zr_temp[num_sensor_zr_temp][0], self.sensor_zr_temp[num_sensor_zr_temp][1],
                                                        fill='orange')
                                    #创建临时数组存储已经连接的传感器的数据
                                    temp_arr = self.sensor_zr[num_sensor_zr][::]
                                    self.sensor_zr_temp.append(temp_arr)
                                    # 当判定有点相连的 令标志数等于1
                                    self.i = 1

        '''这段代码是取还没有进行连接的传感器坐标数据'''
        reList = list(set([tuple(t) for t in self.sensor_zr_temp]))
        self.sensor_zr_temp.clear()
        # 去重以后 会变成列表包元组 需要转化成列表包列表
        for num_sensor_zr_temp in range(0, (len(reList))):
            temp_arr_a = [reList[num_sensor_zr_temp][0], 
                            reList[num_sensor_zr_temp][1], 
                            reList[num_sensor_zr_temp][2], 
                            reList[num_sensor_zr_temp][3], 
                            reList[num_sensor_zr_temp][4], 
                            reList[num_sensor_zr_temp][5],
                            reList[num_sensor_zr_temp][6],
                            reList[num_sensor_zr_temp][7],
                            reList[num_sensor_zr_temp][8],
                            reList[num_sensor_zr_temp][9]]
            self.sensor_zr_temp.append(temp_arr_a)

        if(self.i == 0):
            # 当没有点可以遍历的时候 退出递归
            self.over()
        else:
            self.Cal_Con_ZRtoZR_Recursion()

    def Cal_Con_ZRtoZED_Recursion(self):
        #设置标志数
        self.i = 0
        # 对列表求差集
        difference_set = list(set([tuple(t) for t in self.sensor_zed]).difference(set([tuple(t) for t in self.sensor_zed_temp])))
        self.sensor_zed.clear()
        # 求差集以后 会变成列表包元组 需要转化成列表包列表
        for num_sensor_zed_a in range(0, (len(difference_set))):
            temp_arr_a = [  difference_set[num_sensor_zed_a][0], 
                            difference_set[num_sensor_zed_a][1], 
                            difference_set[num_sensor_zed_a][2], 
                            difference_set[num_sensor_zed_a][3], 
                            difference_set[num_sensor_zed_a][4], 
                            difference_set[num_sensor_zed_a][5], 
                            difference_set[num_sensor_zed_a][6],
                            difference_set[num_sensor_zed_a][7]]
            self.sensor_zed.append(temp_arr_a)
        '''
        外层循环:对符合要求并已经进行连接的传感器坐标列表遍历
        '''
        for num_sensor_zr_temp in range(0, len(self.sensor_zr_temp)):
            '''
            内层循环:对没有遍历或者不符合要求的传感器坐标遍历
            '''
            for num_sensor_zed in range(0, len(self.sensor_zed)):
                #sensor_zr: 储存没有遍历或者不符合要求的传感器坐标
                #sensor_zr_temp: 储存符合要求并已经进行连接的传感器坐标
                temp_x = self.sensor_zed[num_sensor_zed][0] - self.sensor_zr_temp[num_sensor_zr_temp][0]
                temp_y = self.sensor_zed[num_sensor_zed][1] - self.sensor_zr_temp[num_sensor_zr_temp][1]
                temp_x = temp_x * temp_x
                temp_y = temp_y * temp_y
                temp_distance = math.sqrt(temp_x + temp_y)
                 #判断每个点与剩余未连接点的连接情况
                if(temp_distance <= self.distance):
                    if((self.Cm - self.sensor_zr_temp[num_sensor_zr_temp][3]) > 0):
                        if(self.sensor_zed[num_sensor_zed][2] == 0):
                            if(self.sensor_zr_temp[num_sensor_zr_temp][5] < self.Lm):
                                self.sensor_zr_temp[num_sensor_zr_temp][3] = self.sensor_zr_temp[num_sensor_zr_temp][3] + 1
                                self.sensor_zed[num_sensor_zed][2] = 1
                                self.sensor_zed[num_sensor_zed][3] = self.sensor_zr_temp[num_sensor_zr_temp][5] + 1
                                self.sensor_zed[num_sensor_zed][4] = self.sensor_zr_temp[num_sensor_zr_temp][3] - self.sensor_zr_temp[num_sensor_zr_temp][4]
                                #地址的分配
                                if(self.Rm == 1):
                                    Cskip = 1 + self.Cm * (self.Lm - self.sensor_zr_temp[num_sensor_zr_temp][5] - 1)
                                else:
                                    Cskip = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - self.sensor_zr_temp[num_sensor_zr_temp][5] - 1))) / (1 - self.Rm)
                                #计算ZED的address
                                self.sensor_zed[num_sensor_zed][5] = self.sensor_zr_temp[num_sensor_zr_temp][7] + self.sensor_zr_temp[num_sensor_zr_temp][8] * self.Rm + self.sensor_zr_temp[num_sensor_zr_temp][3] - self.sensor_zr_temp[num_sensor_zr_temp][4]                        
                                #把地址显示在传感器下面
                                address = str(self.sensor_zed[num_sensor_zed][5])
                                Num = str(self.sensor_zed[num_sensor_zed][4])
                                text_string = 'A:' + address# + ' N:' + Num
                                self.cv.create_text(self.sensor_zed[num_sensor_zed][0], self.sensor_zed[num_sensor_zed][1] + self.canvas_text_y, text='ZED-' + text_string)                           
                                #对两个传感器进行连线
                                self.cv.create_line(self.sensor_zed[num_sensor_zed][0], self.sensor_zed[num_sensor_zed][1],
                                                    self.sensor_zr_temp[num_sensor_zr_temp][0], self.sensor_zr_temp[num_sensor_zr_temp][1],
                                                    fill='orange')
                                #创建临时数组存储已经连接的传感器的数据
                                temp_arr = self.sensor_zed[num_sensor_zed][::]
                                self.sensor_zed_temp.append(temp_arr)
                                # 当判定有点相连的 令标志数等于1
                                self.i = 1

        '''这段代码是取还没有进行连接的传感器坐标数据'''
        reList = list(set([tuple(t) for t in self.sensor_zed_temp]))
        self.sensor_zed_temp.clear()
        # 去重以后 会变成列表包元组 需要转化成列表包列表
        for num_sensor_zed_temp in range(0, (len(reList))):
            temp_arr_a = [  reList[num_sensor_zed_temp][0], 
                            reList[num_sensor_zed_temp][1], 
                            reList[num_sensor_zed_temp][2], 
                            reList[num_sensor_zed_temp][3],
                            reList[num_sensor_zed_temp][4], 
                            reList[num_sensor_zed_temp][5],
                            reList[num_sensor_zed_temp][6],
                            reList[num_sensor_zed_temp][7]]
            self.sensor_zed_temp.append(temp_arr_a)

        if(self.i == 0):
            # 当没有点可以遍历的时候 退出递归
            self.over()
        else:
            self.Cal_Con_ZRtoZED_Recursion()

    '''构建ZigBee树状图'''
    def Tree_Topology_Establishment(self):
        #判断ZC和ZR、ZED是否可以进行连接,并对其分配地址
        self.Cal_ZC_Connect()
        #计算 ZR 和 ZR 的连接情况,并对其分配地址
        self.Cal_Con_ZRtoZR_Recursion()
        #计算 ZR 和 ZED 的连接情况,并对其分配地址
        self.Cal_Con_ZRtoZED_Recursion()
        
    '''路径查找'''
    def Path_Lookup_ready(self):
        #读取数据
        self.SNA = self.source_node_address.get()
        self.DNA = self.destination_node_address.get()
        self.SNA = int(self.SNA)
        self.DNA = int(self.DNA)
        # 创建存储起始结点信息的二维列表
        self.SNA_list = [0 for i in range(10)]
        # 创建存储目的结点信息的二维列表
        self.DNA_list = [0 for i in range(10)]
        #设置标志数,标志是否查找到结点地址
        Sign_SNA = 0
        Sign_DNA = 0
        #在ZC ZR ZED中找SNA
        while(1):
            if(self.sensor_zc[0][7] == self.SNA):
                #print('起始节点在ZC组中')
                Sign_SNA = 1
                self.SNA_list = self.sensor_zc[0][::]
                break

            for num_sensor_zr_temp in range(0, len(self.sensor_zr_temp)):
                if(self.sensor_zr_temp[num_sensor_zr_temp][7] == self.SNA):
                    #print('起始节点在ZR组中')
                    Sign_SNA =  1
                    self.SNA_list = self.sensor_zr_temp[num_sensor_zr_temp][::]
                    break
            if(Sign_SNA != 1): 
                for  num_sensor_zed_temp in range(0,len(self.sensor_zed_temp)):
                    if(self.sensor_zed_temp[num_sensor_zed_temp][5] == self.SNA):
                        #print('起始节点在ZED组中')
                        Sign_SNA =  1
                        self.SNA_list[0] = self.sensor_zed_temp[num_sensor_zed_temp][0]
                        self.SNA_list[1] = self.sensor_zed_temp[num_sensor_zed_temp][1]
                        self.SNA_list[2] = self.sensor_zed_temp[num_sensor_zed_temp][2]
                        self.SNA_list[5] = self.sensor_zed_temp[num_sensor_zed_temp][3]
                        self.SNA_list[6] = self.sensor_zed_temp[num_sensor_zed_temp][4]
                        self.SNA_list[7] = self.sensor_zed_temp[num_sensor_zed_temp][5]
                        self.SNA_list[8] = self.sensor_zed_temp[num_sensor_zed_temp][6]
                        self.SNA_list[9] = self.sensor_zed_temp[num_sensor_zed_temp][7]
                        break
            break
        # 输出SNA_list)
        # print(self.SNA_list)
        # 在ZC ZR ZED中找DNA
        while(1):
            if(self.sensor_zc[0][7] == self.DNA):
                #print('目的节点在ZC组中')
                Sign_DNA = 1
                self.DNA_list = self.sensor_zc[0][::]
                break

            for num_sensor_zr_temp in range(0, len(self.sensor_zr_temp)):
                if(self.sensor_zr_temp[num_sensor_zr_temp][7] == self.DNA):
                    #print('目的节点在ZR组中')
                    Sign_DNA =  1
                    self.DNA_list = self.sensor_zr_temp[num_sensor_zr_temp][::]
                    break
            if(Sign_DNA != 1):               
                for  num_sensor_zed_temp in range(0,len(self.sensor_zed_temp)):
                    if(self.sensor_zed_temp[num_sensor_zed_temp][5] == self.DNA):
                        #print('目的节点在ZED组中')
                        Sign_DNA =  1
                        self.DNA_list[0] = self.sensor_zed_temp[num_sensor_zed_temp][0]
                        self.DNA_list[1] = self.sensor_zed_temp[num_sensor_zed_temp][1]
                        self.DNA_list[2] = self.sensor_zed_temp[num_sensor_zed_temp][2]
                        self.DNA_list[5] = self.sensor_zed_temp[num_sensor_zed_temp][3]
                        self.DNA_list[6] = self.sensor_zed_temp[num_sensor_zed_temp][4]
                        self.DNA_list[7] = self.sensor_zed_temp[num_sensor_zed_temp][5]
                        self.DNA_list[8] = self.sensor_zed_temp[num_sensor_zed_temp][6]
                        self.DNA_list[9] = self.sensor_zed_temp[num_sensor_zed_temp][7]
                        break
            break   
        # 输出DNA_list
        # print(self.DNA_list)
        if(Sign_DNA == 0) or (Sign_SNA == 0):
            self.over()
        else:
            #查找&进入递归
            self.Path_Lookup()

    def Path_Lookup(self):
        #判断两个点的地址是否相同
        if(self.SNA_list[7] == self.DNA_list[7]):
            return 0
        #对两个传感器进行判断
        else:
            #计算当前SNA的父节点的Cskip
            if (self.SNA_list[9] == 0):
                deep_SNA = 0
            else:
                deep_SNA = self.SNA_list[5] - 1
            if(self.Rm == 1):
                Cskip_SNA = 1 + self.Cm * (self.Lm - self.sensor_zc[0][5] - 1)
            else:
                Cskip_SNA = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - deep_SNA - 1))) / (1 - self.Rm)
            Cskip_SNA = int(Cskip_SNA)
            #计算计算当前DNA的父节点的CskipD
            if (self.DNA_list[9] == 0):
                deep_DNA = 0
            else:
                deep_DNA = self.DNA_list[5] - 1
            if(self.Rm == 1):
                Cskip_DNA = 1 + self.Cm * (self.Lm - self.sensor_zc[0][5] - 1)
            else:
                Cskip_DNA = (1 + self.Cm - self.Rm - self.Cm * math.pow(self.Rm,(self.Lm - deep_DNA - 1))) / (1 - self.Rm)
            Cskip_DNA = int(Cskip_DNA)
            #判断DNA是不是在SNA的子树中
            if (self.SNA_list[9] == 0) or ((self.SNA_list[9] == 1) and (self.SNA_list[7] < self.DNA_list[7]) and ( self.DNA_list[7] < (self.SNA_list[7] + Cskip_SNA))):
                #DNA在SNA的子树中,DNA向父节点回写,并以父节点覆盖DNA中的数据
                #print('DNA在SNA的子树中')
                #通过公式反推子结点对应父节点的地址
                if(self.DNA_list[9] == 1):
                    DNA_Parent_Address = self.DNA_list[7] - 1 - Cskip_DNA * (self.DNA_list[6] - 1)
                else:
                    DNA_Parent_Address = self.DNA_list[7] - Cskip_DNA * self.Rm - self.DNA_list[6]
                #print(DNA_Parent_Address)
                #用父节点的地址向ZC的地址比对,判断当前子结点的父节点是不是ZC
                if(self.sensor_zc[0][7] == DNA_Parent_Address):
                    #对两个传感器进行连接
                    self.cv.create_line(self.gathering_point_center_x, self.gathering_point_center_y,
                                        self.DNA_list[0], self.DNA_list[1],
                                        fill='blue'
                                        )
                    self.DNA_list = self.sensor_zc[0][::]
                #用父节点的地址向ZR的地址比对,判断当前子结点的父节点对应的ZR
                for num_sensor_zr_temp in range(0, len(self.sensor_zr_temp)):
                    if(self.sensor_zr_temp[num_sensor_zr_temp][7] == DNA_Parent_Address):
                        self.cv.create_line(self.sensor_zr_temp[num_sensor_zr_temp][0], self.sensor_zr_temp[num_sensor_zr_temp][1],
                                        self.DNA_list[0], self.DNA_list[1],
                                        fill='blue'                                    
                                        )
                        self.DNA_list = self.sensor_zr_temp[num_sensor_zr_temp][::]
                        break

            else:
                #DNA不在SNA的子树中
                #print('DNA不在SNA的子树中')
                #SNA向父节点回写,并以父节点覆盖SNA中的数据
                #通过公式反推子结点对应父节点的地址
                if(self.SNA_list[9] == 1):
                    SNA_Parent_Address = self.SNA_list[7] - 1 - Cskip_SNA * (self.SNA_list[6] - 1)
                else:
                    SNA_Parent_Address = self.SNA_list[7] - Cskip_SNA * self.Rm - self.SNA_list[6]
                #print(SNA_Parent_Address)
                #用父节点的地址向ZC的地址比对,判断当前子结点的父节点是不是ZC
                if(self.sensor_zc[0][7] == SNA_Parent_Address):
                    #对两个传感器进行连接
                    self.cv.create_line(self.gathering_point_center_x, self.gathering_point_center_y,
                                        self.SNA_list[0], self.SNA_list[1],
                                        fill='blue')
                    self.SNA_list = self.sensor_zc[0][::]
                #用父节点的地址向ZR的地址比对,判断当前子结点的父节点对应的ZR
                for num_sensor_zr_temp in range(0, len(self.sensor_zr_temp)):
                    if(self.sensor_zr_temp[num_sensor_zr_temp][7] == SNA_Parent_Address):
                        self.cv.create_line(self.sensor_zr_temp[num_sensor_zr_temp][0], self.sensor_zr_temp[num_sensor_zr_temp][1],
                                        self.SNA_list[0], self.SNA_list[1],
                                        fill='blue')
                        self.SNA_list = self.sensor_zr_temp[num_sensor_zr_temp][::]
                        break
        '''
        print('递归完成后的SNA:',self.SNA_list)      
        print('递归完成后的DNA:',self.DNA_list)               
        print('-------------------------------------------------')
        '''
        #递归
        self.Path_Lookup()
                
    def over(self):
        return 0
        #print("递归完成")

    def run(self):
        try:
            self.root.mainloop()
        except Exception as e:
            print("*** exception:\n".format(e))

def main():
    window = tk.Tk()
    window.title('SensorProject Design By HJK and ZN')
    Window(window).run()

if __name__ == '__main__':
    main()

打包好的文件,下载后解压点击其中的 sensorprojectfinal.exe 就可以运行了

链接:https://pan.baidu.com/s/1rPiKkslLS8cV7UR8wJs-Tg
提取码:1111

算法思想:

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。