Pyqt5 5.10.1制作MQTT 实时监控噪音大小程序

      刚下飞机,人在洛杉矶,复迟见谅,谢邀. 还是一样的逼格,还是熟悉的味道, 远在北京大四的学妹适逢毕业设计, 要做一个噪音监测软件,于是我略施绵薄之力,仅供参考.

技术方案:

     1. 硬件方面,购买一个音量传感器连接ESP32开发板, 将音量分贝数传至开发板, 开发板连接Mqtt服务器, 每两秒推送一次音量数据

      2.软件方面, 使用pyqt5构建一个桌面程序, 接收来自mqtt的数据, 然后将数据通过echarts展现出来,同时可以设置报警阈值, 超过即调用语音服务报警.

具体实现: 

     1. pyqt5 使用lable显示报警图片

 lbl = self.label_10
 pixmap = QtGui.QPixmap('./alarm.png')  # 按指定路径找到图片
 lbl.setPixmap(pixmap)  # 在label上显示图片
 lbl.setScaledContents(True)  # 让图片自适应label大小
 lbl.showNormal()

     2. pyqt5使用frame显示pychart生成的静态音量html图, 我们通过pyqt5带的QWebEngineView打开本地html文件(注意打开本地文件需使用绝对路径, 传统的相对路径./...并不适用), 然后调用文件里的重汇函数传入最新的音量,让Pychart 刷新图表, 即可实现动态展示,注意这里pyqt5的版本需在5.11以下才有QWebEngineView:

url1 = self.lineEdit2_2.text()

frame1 = self.frame
# 创建一个QWebEngineView实例
w = frame1.width()
h = frame1.height()

self.webView1 = QWebEngineView(frame1)
# 加载网页
self.webView1.load(QUrl(url1))
self.webView1.setGeometry(1, 3, w, h)
self.webView1.setZoomFactor(0.6)
# 显示QFrame
self.webView1.show()

   刷新本地html方法: 

# update pyechart
self.webView1.page().runJavaScript(f'reRender({str(nr_voice)})')

降低pyqt5版本:

D:\mqtt_project> pip install PyQt5==5.10.1

3. 超过预设的最大音量时, 系统播放语音警报:

# say sth. to warn
engine = pyttsx3.init()
engine.setProperty('rate', 180)
engine.setProperty('volume', 100)
# engine.setProperty('voice', 100)
engine.say('Be quiet, or Boss will kill you!')
engine.runAndWait()
engine.stop()

4. mqtt python版

    def mqtt_connect(self):
        def on_connect(client, userdata, flags, rc):
            # print("Connected with result code: " + str(rc))

            if rc == 0:  # rc连接标志,成功会返回0
                self.isMQTTConnect = True
                self.label_status.setText('connect success')
            else:
                self.isMQTTConnect = False
                self.label_status.setText('connect error:' + str(rc))

        connect_as = self.lineEdit1_1.text()
        cli_id = self.lineEdit1_2.text()
        protocol = self.lineEdit1_3_3.text()

        host = self.lineEdit1_3.text()
        port = self.lineEdit1_3_1.text()
        path = self.lineEdit1_3_2.text()
        username = self.lineEdit1_4.text()
        pwd = self.lineEdit1_5.text()
        topic = self.lineEdit2.text()

        url1 = self.lineEdit2_2.text()
        url2 = self.lineEdit2_3.text()

        print(connect_as, cli_id, protocol, host, port, username, pwd, topic, url1, url2)
        # save user's last set
        try:
            config = configparser.ConfigParser()
            config.read(self.config_file)

            config.set(connect_as, 'client_id', str(cli_id))
            config.set(connect_as, 'protocol', protocol)
            config.set(connect_as, 'address', host)
            config.set(connect_as, 'port', port)
            config.set(connect_as, 'path', path)
            config.set(connect_as, 'username', username)
            config.set(connect_as, 'pwd', pwd)
            config.set(connect_as, 'topic', topic)
            config.set(connect_as, 'url', url1)
            config.set(connect_as, 'url2', url2)

            config.write(open(self.config_file, "w"))
            # with open(self.config_file, 'w') as file:
            #     config.write(file)
        except Exception as e:
            print(e)

        self.client = mqtt.Client(client_id=cli_id, transport=protocol)

        try:
            self.client.username_pw_set(username, pwd)
            self.client.connect(host, int(port), 60)
            self.client.on_connect = on_connect
            self.client.loop_start()
        except Exception as e:
            print(e)

    def book_info(self):
        if not self.isMQTTConnect:
            print('subscribing')
            self.label_status_2.setText('Please connect host first.')
            return

        if self.isSubscribe:
            self.un_book()
            return

        def on_message(client, userdata, message):
            mstr = message.payload.decode("ascii")
            self.textEdit2_2.append(mstr)
            nr_voice = None

            if mstr.isnumeric() or mstr.replace('.', '').isnumeric():
                nr_voice = mstr
                self.lcdNumber.display(nr_voice)

            else:

                strs = json.loads(mstr)
                nr_voice = strs['voice']
                self.lcdNumber.display(nr_voice)

            # alarm if exceed maximum
            maximum = self.lineEdit2_4.text()
            if maximum and int(nr_voice) >= int(maximum):
                # self.play_video()
                self.show_img()
            else:
                self.label_10.clear()

            # update pyechart
            self.webView1.page().runJavaScript(f'reRender({str(nr_voice)})')

        self.topic = self.lineEdit2.text()
        self.client.subscribe(self.topic)
        # self.client.on_connect = self.on_connect
        self.client.on_message = on_message
        self.label_status_2.setText('subscribe success.')
        self.isSubscribe = True

    def publish(self):
        wd = self.textEdit2_1.toPlainText()
        result = self.client.publish(self.topic, wd)
        status = result[0]

        if status == 0:

            print('第{}条消息发送成功')

        else:

            print('第{}条消息发送失败')

    def un_connect(self):
        if self.client:
            self.client.disconnect()
            self.label_status.setText('Connect canceled')

    def un_book(self):
        if self.client:
            self.client.unsubscribe(self.topic)
            self.label_status_2.setText('subscribe canceled.')
            self.isSubscribe = False
View Code

 

      以上其实还有另一解决方案, 构建一个web版的mqtt连接, 使用js的模块, 同样可以实现功能. 而且可以直接重新渲染echart图表, 免去了python和js的通信难题. 

posted on 2023-12-11 11:43  nozuodie  阅读(186)  评论(0)    收藏  举报

导航