不干正事儿系列文章3:MQTT数据传输及pyqtgraph的数据可视化

文章目录

  • 不干正事儿系列文章3:MQTT数据传输及pyqtgraph的数据可视化
    • 0. Intro
    • 1. MQTT简介和部署
      • 1.1 MQTT简介
      • 1.2 MQTT服务器的部署
        • 1.2.1 下载
        • 1.2.2 docker的安装和部署
    • 2. MQTT的简单应用
      • 2.1 调用Python收发数据
      • 2.2 调用数模转换芯片采集数据
      • 2.3 利用MQTT传输数据
    • 3. pyqtgraph的数据可视化

不干正事儿系列文章3:MQTT数据传输及pyqtgraph的数据可视化

系列文章:
不干正事儿系列文章1:Sonic Pi简单应用
不干正事儿系列文章2:AD/DA转换PCF8591模块和树莓派4

0. Intro

根据前序的两篇文章我们已经可以通过Sonic Pi生成音频,也可以让PCF8591采集模量并转化为数字信号了。这样一来我们就可以通过Sonic Pi输出的音频,利用鳄鱼夹将3.5mm音频线上的信号采集出来并且绘制成图(我不知道应该如何让脚本直接读取设备的音频输出,如果有会的大佬还请不吝赐教)。
但是由此也遇到了一个问题,就是利用python的pyplot画图真的是要多慢有多慢,画出来的图像卡成PPT。更何况如果想对之再进行一下FFT再绘图那更是慢的没边了。因此我就考虑是不是先用树莓派利用MQTT将采集到的数据传输到PC上然后再进行运算和绘图的操作。
不过后来我试了一下,PC上的FFT的速度确实是快了许多,但是pyplot的速度还是一如既往的感人,因此我就如标题所说的那样利用了pyqtgraph对数据进行绘图。速度果然快了不是一点点。

1. MQTT简介和部署

1.1 MQTT简介

MQTT[1]消息队列遥测传输(英语:Message Queuing Telemetry Transport)是ISO 标准(ISO/IEC PRF 20922)[2]下基于发布 (Publish)/订阅 (Subscribe)范式的消息协议,可视为“数据传递的桥梁”[3]它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件,以解决当前繁重的数据传输协议,如:HTTP。1
它广泛地用于各种物联网地场景。使用较为简便,因此在这里我选择利用MQTT来从树莓派向PC传输数据。

1.2 MQTT服务器的部署

1.2.1 下载

我这边是拿了我的另外一台树莓派部署了一下(安装有Ubuntu Server的系统,但是我觉得用docker的话应该没啥差别)。选择的是EMQ的MQTT服务器。考虑到树莓派自身的架构,所以我选择了docker。大家可以在这里下载。具体的选择如下:
不干正事儿系列文章3:MQTT数据传输及pyqtgraph的数据可视化_第1张图片
版本我自己试的时候是选择的4.0.5,软件包的话记得选arm64v8。

1.2.2 docker的安装和部署

关于docker的安装网上的文章很多,可以参考一下这篇文章。下面来说一下如何部署。
首先建立一个新的文件夹:

mkdir emqx

然后我们将之前下载好的压缩文件复制过去,unzip一下。
然后我们启动一下docker。

docker load < emqx-docker-v4.0.5-alpine3.10-arm64v8
docker run -d --name emqx31 -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx/emqx:v4.0.5-alpine3.10-arm64v8

其中具体的名字可能需要修改,按照实际情况确定。
然后我们只要在终端中输入

docker start emqx31

就可以完成部署了。


在完成部署之后我们可以使用任意一台设备,打开浏览器访问一下服务器。端口号参考之前部署的时候的端口号,比如我这边就是18083。结合树莓派的IP地址,大约就是192.168.XXX.XXX:18083。
登录的初始账号是admin,密码是passwd。然后我们在网页上添加一下额外的用户,这样我们就不需要在终端中进行这些恼人的操作了。
侧边栏中有admin的栏目,进入之后点击Users。在这里我们可以添加额外的用户并且设定密码。
如果不放心自己有没有弄好的话,可以在ios上下载一款叫做MQTTool的软件,PC上也有类似的软件,互相传输一下测试一下。

2. MQTT的简单应用

2.1 调用Python收发数据

我们先安装一下python上的包:

sudo pip3 install paho-mqtt

然后我们可以尝试一下利用python来订阅和发布消息:

import paho.mqtt.client as mqtt
import json
import time

HOST = "192.168.0.13"
PORT = 1883
client_id = "rddsfsvcxfsd" # 爱是啥就是啥无所谓只要大家别重了就好

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("topicName")

def on_message(client, userdata, msg):
    print("Topic:"+msg.topic+" Message:"+str(msg.payload.decode('utf-8')))

def on_subscribe(client, userdata, mid, granted_qos):
    print("On Subscribed: qos = %d" % granted_qos)

def on_disconnect(client, userdata, rc):
    if rc != 0:
        print("Unexpected disconnection %s" % rc)

client = mqtt.Client(client_id)
client.username_pw_set("publisher", "password")
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
client.connect(HOST, PORT, 60)

while True:
    MQTT_MSG = json.dumps(["Hello", "World!", str(time.time())])
    client.publish("topicName", payload=MQTT_MSG, qos=0)
    client.loop()

可以实现客户端的消息发送。
我们可以利用之前我说的MQTTool软件来接收。我们也可以用python来接受消息,代码如下:

import paho.mqtt.client as mqtt
import json
import time

HOST = "192.168.0.13"
PORT = 1883
client_id = "rdddddd" # 爱是啥就是啥无所谓只要大家别重了就好

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("topicName")

def on_message(client, userdata, msg):
    print("Topic:"+msg.topic+" Message:"+str(msg.payload.decode('utf-8')))

def on_subscribe(client, userdata, mid, granted_qos):
    print("On Subscribed: qos = %d" % granted_qos)

def on_disconnect(client, userdata, rc):
    if rc != 0:
        print("Unexpected disconnection %s" % rc)

def on_subscribe(client, userdata, mid, granted_qos):
    print("On Subscribed: qos = %d" % granted_qos)



client = mqtt.Client(client_id)
client.username_pw_set("publisher", "password")
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
client.connect(HOST, PORT, 60)
client.on_subscribe = on_subscribe

while True:
	client.loop()

2.2 调用数模转换芯片采集数据

这个时候,结合我在不干正事儿系列文章2:AD/DA转换PCF8591模块和树莓派4中对于PCF8591芯片的运用。我们可以写出一个类似的类来简单地,单纯地采集数据。

import smbus
import time
from matplotlib import pyplot as plot


class PCF8591:
    def __init__(self):

        self.address = 0x48
        self.ains = [0x41, 0x42, 0x43, 0x44]#, 0x45, 0x46, 0x47] # 45->light, 47 -> temperature
        self.aout = 0x40
        self.values = [0]*len(self.ains)
        self.Y1 = []
        self.Y2 = []
        self.bus = smbus.SMBus(1)

    def get_data(self):
        
        for i, ain in enumerate(self.ains):
            self.bus.write_byte(self.address, ain)
            self.values[i] = self.bus.read_byte(self.address)
        return self.values

2.3 利用MQTT传输数据

最后我们用这段内容,调用PCF8591采集数据,并通过MQTT传输:

import threading
import paho.mqtt.client as mqtt
import json
import time
from PCF8591 import PCF8591

HOST = "192.168.0.13"
PORT = 1883
client_id = "1083421xxxxx"

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("data/receive")

def on_message(client, userdata, msg):
    print("Topic:"+msg.topic+" Message:"+str(msg.payload.decode('utf-8')))


def on_subscribe(client, userdata, mid, granted_qos):
    print("On Subscribed: qos = %d" % granted_qos)


def on_disconnect(client, userdata, rc):
    if rc != 0:
        print("Unexpected disconnection %s" % rc)

class Mix:
    def __init__(self):
        client = mqtt.Client(client_id)
        client.username_pw_set("publisher", "password")
        client.on_connect = on_connect
        client.on_message = on_message
        client.on_disconnect = on_disconnect
        client.connect(HOST, PORT, 60)
        self.client = client
        self.get = PCF8591()
    
    def thread1(self):
        self.get.get_data()
        time.sleep(0.000001)
    
    def thread2(self):
        MQTT_MSG=json.dumps(self.get.values)
        self.client.publish("data/send", payload=MQTT_MSG, qos=0)
        self.client.loop_start()
        time.sleep(0.000001)

new = Mix()
while True:
    new.thread1()
    new.thread2()

如果对于这一块的MQTT的使用还有其他问题的话可以参考一下emqx提供的文档。也欢迎和我交流。

3. pyqtgraph的数据可视化

这边先简单的提供一个pyqtgraph实时绘图的一个示例,我会最后再更新一篇文章来将这三篇文章的内容汇总在一起,实现数据的实时采集,MQTT的传输,以及可视化。
pyqtgraph的实时绘图来源于这里。

# coding:utf-8
# @文件: 1.py
# @创建者:州的先生
# #日期:2019/5/12
# 博客地址:zmister.com
 
from PyQt5 import QtWidgets,QtCore,QtGui
import tushare as ts
import pyqtgraph as pg
import sys
import datetime
import traceback
import numpy as np
 
class MainUi(QtWidgets.QMainWindow):
  def __init__(self):
    super().__init__()
    self.setWindowTitle("CPU使用率监控 - 州的先生https://zmister.com")
    self.main_widget = QtWidgets.QWidget() # 创建一个主部件
    self.main_layout = QtWidgets.QGridLayout() # 创建一个网格布局
    self.main_widget.setLayout(self.main_layout) # 设置主部件的布局为网格
    self.setCentralWidget(self.main_widget) # 设置窗口默认部件
 
    self.plot_widget = QtWidgets.QWidget() # 实例化一个widget部件作为K线图部件
    self.plot_layout = QtWidgets.QGridLayout() # 实例化一个网格布局层
    self.plot_widget.setLayout(self.plot_layout) # 设置线图部件的布局层
    self.plot_plt = pg.PlotWidget() # 实例化一个绘图部件
    self.plot_plt.showGrid(x=True,y=True) # 显示图形网格
    self.plot_layout.addWidget(self.plot_plt) # 添加绘图部件到线图部件的网格布局层
    # 将上述部件添加到布局层中
    self.main_layout.addWidget(self.plot_widget, 1, 0, 3, 3)
 
    self.setCentralWidget(self.main_widget)
 
def main():
  app = QtWidgets.QApplication(sys.argv)
  gui = MainUi()
  gui.show()
  sys.exit(app.exec_())
 
 
if __name__ == '__main__':
  main()
 

绘图的实时性相比matplotlib要好得多。大家可以试一下。


  1. https://zh.wikipedia.org/wiki/MQTT ↩︎

你可能感兴趣的:(不干正事儿系列)