實作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
演算法思想:
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/246176.html
標籤:python
上一篇:Python爬取小姐姐圖片
