一个典型物联网系统中传输机制的设计与实现【模拟路灯】2

一个典型物联网系统中传输机制的设计与实现

本文书写原由:由于本人习惯保存开发时的所有相关内容所以在上传至GitHub上时连同同学的视频一起上传,在上一篇文章中被指责抄袭,本人心中过意不去便重新又使用了几种方法完成该题目以证清白,希望某些人戾气不要那么重。

(1)题目背景

一般一个典型的物联网系统包括感控层(传感器),网络层和应用层组成,而网络层主 要用于实现感控对象与应用层的服务对象之间的通信。本次作业就以 TCP/IP 协议栈中传输 层协议的应用开发为目标,以 UDP 方式实现一种感控对象与服务对象之间的通信机制,其 体系结构如图 1 所示。其中感控对象为一个虚拟路灯对象,在实现过程中用随机数模拟其温 度、湿度和环境照度等感知数据,灯作为被控对象,可以通过服务器对其进行打开、关闭控 制,且用不同颜色表示其开关状态。每个虚拟路灯都将有一个标识,以示区别。而服务对象 可以同时与若干个虚拟路灯对象通信,每个虚拟路灯会定期向服务对象发送其当前状态,服 务对象可以对任一个虚拟路灯进行开关控制。

在这里插入图片描述

(2)题目要求

(1)虚拟路灯状态上传数据直接基于 UDP 实现传输,不考了可靠性,而服务对象发送 给各虚拟路灯的开关命令要利用握手机制实现可靠传输。

(2)基于 UDP 自定义上传、下发数据包格式和传输方式。并实现通信协议的定义、封装和解析。

(3)不限定编程语言。

(3)使用工具

Pycharm、Python、socket、PyQt5

(4)设计思路

客户端

使用Python中PyQt完成页面设计,不同于前文,此处我们设计完全自动化,在前一代码中我们客户端需要手动输入环境状态,在此代码下我们可以使用一个自定义的方法完成生成,并定时发送给服务端。
在这里插入图片描述

图1 Client端界面

服务端

服务端依旧使用Qt完成页面设计,此处与前文不同的点是我们也可以根据从服务端收到的信息实时监控展示。

在这里插入图片描述

图2 Sever端界面

(5)源码

ClientThread.py

import random
import time
import socket
import sys

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *

LocalHost = "127.0.0.1"
def randomMes(): # 随机生成环境状态信息
    tep = str(random.randint(-20, 40))
    light = str(random.randint(0, 101))
    wet = str(random.randint(0, 101))
    return tep, light, wet

class Client(QtCore.QThread):
    client_socket = None
    _signal_data = pyqtSignal(tuple)
    _signal_result = pyqtSignal(str)

    def __init__(self):
        super(Client, self).__init__()
        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    def __del__(self):
        self.wait()

    def run(self):
        while True:
            data = randomMes()
            self._signal_data.emit(data)
            data_t = data[0]
            data_l = data[1]
            data_w = data[2]
            self.client_socket.sendto(data_t.encode("utf8"), (LocalHost, 8000))
            self.client_socket.sendto(data_w.encode("utf8"), (LocalHost, 8000))
            self.client_socket.sendto(data_l.encode("utf8"), (LocalHost, 8000))
            self.status, self.address = self.client_socket.recvfrom(1024)
            if self.status == b'open':
                self._signal_result.emit("Open")
            else:
                self._signal_result.emit("Close")
            time.sleep(5)


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.setWindowModality(QtCore.Qt.ApplicationModal)
        MainWindow.resize(457, 304)
        self.labelstatus = QtWidgets.QLabel(MainWindow)
        self.labelstatus.setGeometry(QtCore.QRect(20, 40, 111, 51))
        self.labelstatus.setTextFormat(QtCore.Qt.PlainText)
        self.labelstatus.setScaledContents(False)
        self.labelstatus.setAlignment(QtCore.Qt.AlignCenter)
        self.labelstatus.setWordWrap(False)
        self.labelstatus.setObjectName("labelstatus")
        self.labelStatus = QtWidgets.QLabel(MainWindow)
        self.labelStatus.setGeometry(QtCore.QRect(160, 50, 101, 31))
        self.labelStatus.setText("")
        self.labelStatus.setAlignment(QtCore.Qt.AlignCenter)
        self.labelStatus.setObjectName("labelStatus")
        self.labelStatus2 = QtWidgets.QLabel(MainWindow)
        self.labelStatus2.setGeometry(QtCore.QRect(30, 80, 101, 61))
        self.labelStatus2.setTextFormat(QtCore.Qt.AutoText)
        self.labelStatus2.setAlignment(QtCore.Qt.AlignCenter)
        self.labelStatus2.setObjectName("labelStatus2")
        self.labelTem = QtWidgets.QLabel(MainWindow)
        self.labelTem.setGeometry(QtCore.QRect(90, 150, 72, 15))
        self.labelTem.setObjectName("labelTem")
        self.labelWet = QtWidgets.QLabel(MainWindow)
        self.labelWet.setGeometry(QtCore.QRect(90, 190, 72, 15))
        self.labelWet.setObjectName("labelWet")
        self.labelLight = QtWidgets.QLabel(MainWindow)
        self.labelLight.setGeometry(QtCore.QRect(90, 230, 72, 15))
        self.labelLight.setObjectName("labelLight")
        self.pushButton = QtWidgets.QPushButton(MainWindow)
        self.pushButton.setGeometry(QtCore.QRect(300, 120, 111, 71))
        self.pushButton.setObjectName("pushButton")
        self.label = QtWidgets.QLabel(MainWindow)
        self.label.setGeometry(QtCore.QRect(140, 140, 61, 31))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(MainWindow)
        self.label_2.setGeometry(QtCore.QRect(140, 180, 61, 31))
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(MainWindow)
        self.label_3.setGeometry(QtCore.QRect(140, 220, 61, 31))
        self.label_3.setObjectName("label_3")
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Ludeng"))
        self.labelstatus.setText(_translate("MainWindow", "路灯状态:"))
        self.labelStatus2.setText(_translate("MainWindow", "环境状态:"))
        self.labelTem.setText(_translate("MainWindow", "温度:"))
        self.labelWet.setText(_translate("MainWindow", "湿度:"))
        self.labelLight.setText(_translate("MainWindow", "亮度:"))
        self.pushButton.setText(_translate("MainWindow", "开启"))
        self.label.setText(_translate("MainWindow", "0"))
        self.label_2.setText(_translate("MainWindow", "0%"))
        self.label_3.setText(_translate("MainWindow", "0"))
        self.socketThread = None
        self.pushButton.clicked.connect(self.start_login)

    def start_login(self):
        if not self.socketThread:
            self.socketThread = Client()
            self.socketThread._signal_data.connect(self.call_back)  # 绑定修改室内状态信息
            self.socketThread._signal_result.connect(self.displayresult)  # 绑定修改灯状态信息
            self.socketThread.start()

    def call_back(self, data):
        self.label.setText(str(data[0]))
        self.label_2.setText(str(data[2]) + "%")
        self.label_3.setText(str(data[1]))

    def displayresult(self, result):
        self.labelStatus.setText(str(result))

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

ServerLight.py

import socket

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *

class Thread(QThread):
    _signal = pyqtSignal(int, str, tuple, str)
    ip_address = []
    udp_socket = None

    def __init__(self):
        super(Thread, self).__init__()
        print("正在启动服务端")
        # 创建套接字
        self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # udp IPV4			tcp  IPV4
        # 绑定本地信息
        self.udp_socket.bind(('', 8000))
        print("启动成功")

    def __del__(self):
        self.wait()

    def run(self):
        while True:
            # 接收终端的数据
            recv_data_T, address = self.udp_socket.recvfrom(1024)  # 接收温度
            recv_data_W, address = self.udp_socket.recvfrom(1024)  # 接收湿度
            recv_data_L, address = self.udp_socket.recvfrom(1024)  # 接收环境照度
            recv_data_T = recv_data_T.decode('utf-8')
            recv_data_W = recv_data_W.decode('utf-8')
            recv_data_L = recv_data_L.decode('utf-8')
            print("您接收到来自" + address[0] + "的数据为")
            print("温度为:" + recv_data_T)
            print("湿度为:" + recv_data_W + "%")
            print("亮度为:" + recv_data_L)

            # 退出数据传送判断
            if recv_data_T == '#' or recv_data_W == '#' or recv_data_L == '#':
                break
            # 判断是否满足开灯条件
            if recv_data_T <= '15' and recv_data_W <= '50' or recv_data_L <= '30':
                self.udp_socket.sendto(b"open", address)
                self.bind(address, (recv_data_T, recv_data_W, recv_data_L), 'open')
            elif recv_data_T != '20' or recv_data_L != '5' or recv_data_W != '25':
                self.udp_socket.sendto(b"close", address)
                self.bind(address, (recv_data_T, recv_data_W, recv_data_L), 'close')

    def bind(self, address, data, status):
        if address[0] in self.ip_address:
            self._signal.emit(self.ip_address.index(address[0]), address[0], data, status)
        else:
            if len(self.ip_address) < 3:
                self.ip_address.append(address[0])
                self._signal.emit(self.ip_address.index(address[0]), address[0], data, status)
            else:
                self._signal.emit(-1, (), '')

    @property
    def signal(self):
        return self._signal


class Ui_ServerLight(object):
    ip_address = []
    thread = None
    list1 = []
    list2 = []
    list3 = []
    def setupUi(self, ServerLight):
        ServerLight.setObjectName("ServerLight")
        ServerLight.setEnabled(True)
        ServerLight.resize(640, 480)
        ServerLight.setAutoFillBackground(False)
        self.centralwidget = QtWidgets.QWidget(ServerLight)
        self.centralwidget.setObjectName("centralwidget")
        self.light1 = QtWidgets.QFrame(self.centralwidget)
        self.light1.setGeometry(QtCore.QRect(30, 19, 201, 211))
        self.light1.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.light1.setFrameShadow(QtWidgets.QFrame.Raised)
        self.light1.setObjectName("light1")
        self.liststatus1 = QtWidgets.QListView(self.light1)
        self.liststatus1.setGeometry(QtCore.QRect(10, 60, 171, 131))
        self.liststatus1.setObjectName("liststatus1")
        self.label = QtWidgets.QLabel(self.light1)
        self.label.setGeometry(QtCore.QRect(20, 10, 60, 16))
        self.label.setObjectName("label")
        self.ip1 = QtWidgets.QLabel(self.light1)
        self.ip1.setGeometry(QtCore.QRect(70, 10, 60, 16))
        self.ip1.setObjectName("ip1")
        self.light3 = QtWidgets.QFrame(self.centralwidget)
        self.light3.setGeometry(QtCore.QRect(30, 240, 201, 221))
        self.light3.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.light3.setFrameShadow(QtWidgets.QFrame.Raised)
        self.light3.setObjectName("light3")
        self.ip3 = QtWidgets.QLabel(self.light3)
        self.ip3.setGeometry(QtCore.QRect(70, 10, 60, 16))
        self.ip3.setObjectName("ip3")
        self.label_3 = QtWidgets.QLabel(self.light3)
        self.label_3.setGeometry(QtCore.QRect(20, 10, 60, 16))
        self.label_3.setObjectName("label_3")
        self.liststatus3 = QtWidgets.QListView(self.light3)
        self.liststatus3.setGeometry(QtCore.QRect(10, 60, 171, 131))
        self.liststatus3.setObjectName("liststatus1_2")
        self.light2 = QtWidgets.QFrame(self.centralwidget)
        self.light2.setGeometry(QtCore.QRect(309, 19, 201, 211))
        self.light2.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.light2.setFrameShadow(QtWidgets.QFrame.Raised)
        self.light2.setObjectName("light2")
        self.ip2 = QtWidgets.QLabel(self.light2)
        self.ip2.setGeometry(QtCore.QRect(70, 10, 60, 16))
        self.ip2.setObjectName("ip2")
        self.label_2 = QtWidgets.QLabel(self.light2)
        self.label_2.setGeometry(QtCore.QRect(20, 10, 60, 16))
        self.label_2.setObjectName("label_2")
        self.liststatus2 = QtWidgets.QListView(self.light2)
        self.liststatus2.setGeometry(QtCore.QRect(10, 60, 171, 131))
        self.liststatus2.setObjectName("liststatus2")
        self.openServer = QtWidgets.QPushButton(self.centralwidget)
        self.openServer.setGeometry(QtCore.QRect(530, 250, 81, 26))
        self.openServer.setObjectName("openServer")
        self.CloseServer = QtWidgets.QPushButton(self.centralwidget)
        self.CloseServer.setGeometry(QtCore.QRect(530, 300, 81, 26))
        self.CloseServer.setObjectName("CloseServer")
        self.devicemsg = QtWidgets.QFrame(self.centralwidget)
        self.devicemsg.setGeometry(QtCore.QRect(309, 240, 201, 211))
        self.devicemsg.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.devicemsg.setFrameShadow(QtWidgets.QFrame.Raised)
        self.devicemsg.setObjectName("devicemsg")
        self.devicelist = QtWidgets.QListView(self.devicemsg)
        self.devicelist.setGeometry(QtCore.QRect(0, 50, 201, 161))
        self.devicelist.setObjectName("devicelist")
        self.label_4 = QtWidgets.QLabel(self.devicemsg)
        self.label_4.setGeometry(QtCore.QRect(10, 10, 60, 16))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(519, 25, 101, 41))
        self.label_5.setObjectName("label_5")
        self.serverstatus = QtWidgets.QLabel(self.centralwidget)
        self.serverstatus.setGeometry(QtCore.QRect(550, 70, 31, 21))
        self.serverstatus.setObjectName("serverstatus")
        ServerLight.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(ServerLight)
        self.statusbar.setObjectName("statusbar")
        ServerLight.setStatusBar(self.statusbar)

        self.retranslateUi(ServerLight)
        QtCore.QMetaObject.connectSlotsByName(ServerLight)

    def retranslateUi(self, ServerLight):
        _translate = QtCore.QCoreApplication.translate
        ServerLight.setWindowTitle(_translate("ServerLight", "ServerLight"))
        self.label.setText(_translate("ServerLight", "设备1"))
        self.ip1.setText(_translate("ServerLight", "ip地址1"))
        self.ip3.setText(_translate("ServerLight", "ip地址3"))
        self.label_3.setText(_translate("ServerLight", "设备3"))
        self.ip2.setText(_translate("ServerLight", "ip地址2"))
        self.label_2.setText(_translate("ServerLight", "设备2"))
        self.openServer.setText(_translate("ServerLight", "开机"))
        self.CloseServer.setText(_translate("ServerLight", "关机"))
        self.label_4.setText(_translate("ServerLight", "设备信息"))
        self.label_5.setText(_translate("ServerLight", "当前服务器状态:"))
        self.serverstatus.setText(_translate("ServerLight", "关机"))
        # 开关事件
        self.openServer.clicked.connect(self.server)
        self.CloseServer.clicked.connect(self.server)

    # 开关服务器
    def server(self):
        if self.serverstatus.text() == "关机" and not self.thread:
            self.thread = Thread()
            self.thread.start()
            self.serverstatus.setText("开机")
            self.thread.signal.connect(self.display)
        elif self.serverstatus.text() == "开机" and self.thread:
            self.thread = None
            self.serverstatus.setText("关机")

    def display(self, event, ip, msg, status):
        if ip and ip not in self.ip_address:
            self.ip_address.append(ip)
            slm = QStringListModel()
            slm.setStringList(self.ip_address)
            self.devicelist.setModel(slm)
        if event == 0:
            self.ip1.setText(ip)
            self.list1.append("温度:"+msg[0]+",湿度:"+msg[1]+"%,亮度:"+msg[2])
            slm = QStringListModel()
            slm.setStringList(self.list1)
            self.liststatus1.setModel(slm)
        elif event == 1:
            self.ip2.setText(ip)
        elif event == 2:
            self.ip3.setText(ip)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    ServerLight = QtWidgets.QMainWindow()
    ui = Ui_ServerLight()
    ui.setupUi(ServerLight)
    ServerLight.show()
    sys.exit(app.exec_())

(6)GitHub查看

GitHub:https://github.com/ITApeDeHao/AnalogStreetLight

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ITApe_DeHao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值