LoRa服务器的设备节点数据可以通过MQTT client查看,这里的工具就比较多了,我选择用Python自己开发一个,可以看一下,数据可视化方面polt还是可以的。
这里的难点(对于我一个python小白)我们要看一下:
1.1 单独开一个python线程,在里面订阅到MQTT数据,然后base64解密,按照节点端的数据格式,吧数据解析出来,然后放到全局的n变量里面。
1.2 在一个窗口里面显示多个polt图形,然后数据要不断跟新,图形里面折线图也要跟着跟新,同时,折线图的纵横坐标也要跟着跟新(这个还有待调试)。
代码地址:
https://gitee.com/caledonian_study/python_mqtt_lora_test.git
代码如下:
import time
import paho.mqtt.client as mqtt
import json
import base64
import matplotlib.pyplot as plt
import numpy as np
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import threading
n = {}
n1 = {}
n2 = {}
wight = 3
hight = 5
devicenum = 3
"""
n["acceleration.x"] = [0]
n["acceleration.y"] = [0]
n["acceleration.z"] = [0]
n["angular_velocity.x"] = [0]
n["angular_velocity.y"] = [0]
n["angular_velocity.z"] = [0]
n["magnetic_field.x"] = [0]
n["magnetic_field.y"] = [0]
n["magnetic_field.z"] = [0]
n["AppLedStateOn"] = [0]
n["pressure"] = [0]
n["temperature"] = [0]
n["humidity"] = [0]
"""
n["acceleration.x"] = []
n["acceleration.y"] = []
n["acceleration.z"] = []
n["angular_velocity.x"] = []
n["angular_velocity.y"] = []
n["angular_velocity.z"] = []
n["magnetic_field.x"] = []
n["magnetic_field.y"] = []
n["magnetic_field.z"] = []
n["AppLedStateOn"] = []
n["pressure"] = []
n["temperature"] = []
n["humidity"] = []
"""
for num in range(hight * wight):
n[str(num)] = []
n1[str(num)] = []
n2[str(num)] = []
"""
# myplot=[]
# mysubplot=[]
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class myThread(threading.Thread):
def __init__(self, threadID, name, counter, devEUI):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
self.devEUI = devEUI
self.temp = {}
if devEUI == '0080e11500004dca':
self.temp = n
elif devEUI == '0080e11500004a9c':
self.temp = n1
elif devEUI == '0080e1150500e525':
self.temp = n2
def run(self):
print("开始线程:" + self.name)
client = mqtt.Client(protocol=3)
client.username_pw_set("126", "9c779be5-7f49-4e58-b46f-b216c462f651")
client.on_connect = self.on_connect
client.on_message = self.on_message
client.connect(host="lorawan.timeddd.com", port=1883,
keepalive=60) # 订阅频道
time.sleep(1)
# client.subscribe("public")
client.subscribe([("application/126/node/"+self.devEUI+"/rx", 0)])
client.loop_forever()
def on_connect(self, client, userdata, flags, rc):
if rc == 0:
print("连接成功")
print("Connected with result code " + str(rc))
def on_message(self, client, userdata, msg):
self.msgget(msg)
def msgget(self, msg):
tempdate = []
#print(msg.topic + " " + str(msg.payload))
text = json.loads(msg.payload)
# print(text)
print('设备的devEUI ----->', text["devEUI"])
#print('收到的原始数据是 -->',text["deviceName"])
# 需要转成2进制格式才可以转换,所以我们这里再手动转换一下
result = base64.b64decode(text["data"])
# 打印转换后的结果
#print('收到的数据是 ------>',result)
print("%s: %s" % (result, time.ctime(time.time())))
# print(result)
devEUI = text["devEUI"]
for ii, i in enumerate(result):
# print(ii)
# print(i)
# if ii < hight * wight:
tempdate.append(i)
# self.temp[str(ii)].append(i)
#n1[str(ii)].append(i / 2)
#n2[str(ii)].append(i / 4)
print(tempdate) # 原始数据
# 获取锁,用于线程同步
#threadLock.acquire()
self.datepress(tempdate)
#threadLock.release()
def datepress(self, tempdate):
global n
print(len(n["humidity"]))
i = 0
n["acceleration.x"].append(
(tempdate[i+0] << 16)+(tempdate[i+1] << 8)+tempdate[i+2])
n["acceleration.y"].append(
(tempdate[i+3] << 16)+(tempdate[i+4] << 8)+tempdate[i+5])
n["acceleration.z"].append(
(tempdate[i+6] << 16)+(tempdate[i+7] << 8)+tempdate[i+8])
i = 9
n["angular_velocity.x"].append(
(tempdate[i+0] << 16)+(tempdate[i+1] << 8)+tempdate[i+2])
n["angular_velocity.y"].append(
(tempdate[i+0] << 16)+(tempdate[i+1] << 8)+tempdate[i+2])
n["angular_velocity.z"].append(
(tempdate[i+0] << 16)+(tempdate[i+1] << 8)+tempdate[i+2])
i = 18
n["magnetic_field.x"].append(
(tempdate[i+0] << 16)+(tempdate[i+1] << 8)+tempdate[i+2])
n["magnetic_field.y"].append(
(tempdate[i+0] << 16)+(tempdate[i+1] << 8)+tempdate[i+2])
n["magnetic_field.z"].append(
(tempdate[i+0] << 16)+(tempdate[i+1] << 8)+tempdate[i+2])
i = 27
n["AppLedStateOn"].append(tempdate[i+0])
n["pressure"].append((tempdate[i+1] << 8)+tempdate[i+2])
n["temperature"].append(tempdate[i+3])
n["humidity"].append((tempdate[i+4] << 8)+tempdate[i+5])
#print(n)
#self.DateLenControl()
def DateLenControl(self):
global n
if len(n["humidity"]) >2:
n["acceleration.x"].pop(0)
n["acceleration.x"].pop(0)
n["acceleration.x"].pop(0)
n["acceleration.y"].pop(0)
n["acceleration.z"].pop(0)
n["angular_velocity.x"].pop(0)
n["angular_velocity.y"].pop(0)
n["angular_velocity.z"].pop(0)
n["magnetic_field.x"].pop(0)
n["magnetic_field.y"].pop(0)
n["magnetic_field.z"].pop(0)
n["AppLedStateOn"].pop(0)
n["pressure"].pop(0)
n["temperature"].pop(0)
n["humidity"].pop(0)
class myThread2(threading.Thread):
def __init__(self, threadID, name, n):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
#plt.ion()
self.fig = plt.figure(num='device=' + self.name) # 创建figure对象
#self.fig.
#plt.ioff()
#plt.show()
self.n = n
self.myplot = []
self.mysubplot = []
self.ani = FuncAnimation(fig=self.fig,
func=self.update,
frames=np.linspace(0, 100, 100),
init_func=self.myinit,
interval=10,
blit=True)
self.x = []
#plt.ioff()
#plt.show()
def run(self):
# self.fig.show()
print("开始线程:" + self.name)
while 1:
time.sleep(0.5)
#plt.cla()
#plt.pause(0.33)
pass
# The callback for when the client receives a CONNACK response from the server.
def myinit(self):
for num in range(hight * wight):
self.mysubplot.append(self.fig.add_subplot(hight, wight, num + 1))
self.myplot.append(self.mysubplot[num].plot([], [])[0])
# mysubplot[num].set_ylim(0,255)
#mysubplot[num].set_xlim(0, len(n[str(0)]))
self.myplot[num].axes.relim() # 用不同的信号长度更新一个图形
self.myplot[num].axes.autoscale_view()
self.fig.subplots_adjust(wspace=0.5, hspace=0.7, bottom=0.1)
return self.myplot
def update(self, frame):
# print(frame)
length = len(n["humidity"])
self.x = range(length)
#self.x = np.linspace(0, length, length)
# 获取锁,用于线程同步
#threadLock.acquire()
if length > 0 :
#print(n["acceleration.x"][-1])
self.myplot[0].set_data(self.x, np.array(n["acceleration.x"] ))
self.mysubplot[0].set_title('acceleration.x=%.2f' % n["acceleration.x"][-1],fontsize=8)
self.myplot[1].set_data(self.x, np.array(n["acceleration.y"]))
self.mysubplot[1].set_title('acceleration.y=%.2f' % n["acceleration.x"][-1],
fontsize=8)
self.myplot[2].set_data(self.x, np.array(n["acceleration.z"]))
self.mysubplot[2].set_title('acceleration.z=%.2f' % n["acceleration.z"][-1],
fontsize=8)
self.myplot[3].set_data(self.x, np.array(n["angular_velocity.x"]))
self.mysubplot[3].set_title('angular_velocity.x=%.2f' % n["angular_velocity.x"][-1],
fontsize=8)
self.myplot[4].set_data(self.x, np.array(n["angular_velocity.y"]))
self.mysubplot[4].set_title('angular_velocity.y=%.2f' % n["angular_velocity.y"][-1],
fontsize=8)
self.myplot[5].set_data(self.x, np.array(n["angular_velocity.z"]))
self.mysubplot[5].set_title('angular_velocity.z=%.2f' % n["angular_velocity.z"][-1],
fontsize=8)
self.myplot[6].set_data(self.x, np.array(n["magnetic_field.x"]))
self.mysubplot[6].set_title('magnetic_field.x=%.2f' % n["magnetic_field.x"][-1],
fontsize=8)
self.myplot[7].set_data(self.x, np.array(n["magnetic_field.y"]))
self.mysubplot[7].set_title('magnetic_field.y=%.2f' % n["magnetic_field.y"][-1],
fontsize=8)
self.myplot[8].set_data(self.x, np.array(n["magnetic_field.z"]))
self.mysubplot[8].set_title('magnetic_field.z=%.2f' % n["magnetic_field.z"][-1],
fontsize=8)
self.myplot[9].set_data(self.x, np.array(n["AppLedStateOn"]))
self.mysubplot[9].set_title('AppLedStateOn=%.2f' % n["AppLedStateOn"][-1],
fontsize=8)
self.myplot[10].set_data(self.x, np.array(n["pressure"]))
self.mysubplot[10].set_title('pressure=%.2f' % n["pressure"][-1],
fontsize=8)
self.myplot[11].set_data(self.x, np.array(n["temperature"]))
self.mysubplot[11].set_title('temperature=%.2f' % n["temperature"][-1],
fontsize=8)
self.myplot[12].set_data(self.x, np.array(n["humidity"]))
self.mysubplot[12].set_title('humidity=%.2f' % n["humidity"][-1],
fontsize=8)
# 调整横坐标长度
for num in range(hight * wight):
if length > 0:
self.mysubplot[num].set_xlim(0, length+1)
#if(frame==5):
#self.myplot[num].axes.relim() # 用不同的信号长度更新一个图形
#self.myplot[num].axes.autoscale_view()
#threadLock.release()
#self.fig = plt.figure(num='device=' + self.name) # 创建figure对象
return self.myplot
if __name__ == "__main__":
threadLock = threading.Lock()
# 创建新线程
#Datethread1 = myThread(1, "Thread-1", 1,'0080e11500004dca')
Datethread2 = myThread(1, "Thread-1", 1, '0080e11500004a9c')
#Datethread3 = myThread(1, "Thread-1", 1,'0080e1150500e525')
#Picturethread1 = myThread2(2, "0080e11500004dca", n)
Picturethread2 = myThread2(3, "0080e11500004a9c", n1)
#Picturethread3 = myThread2(4, "0080e1150500e525", n2)
# 开启新线程
# Datethread1.start()
Datethread2.start()
# Datethread3.start()
# Picturethread1.start()
Picturethread2.start()
# Picturethread3.start()
# thread1.join()
# thread2.join()
plt.show()
while 1:
pass
print("退出主线程")