简述
使用IP地址组播技术,实现海康的设备搜索功能,只要设备接入局域网就能够被搜索到。效果图.
功能代码:
1. scan_device_ui.py 布局文件
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'scan_device.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(849, 633)
self.verticalLayout_2 = QtWidgets.QVBoxLayout(Form)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setContentsMargins(-1, 10, -1, 10)
self.horizontalLayout.setObjectName("horizontalLayout")
self.scan_device = QtWidgets.QPushButton(Form)
self.scan_device.setObjectName("scan_device")
self.horizontalLayout.addWidget(self.scan_device)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.verticalLayout_2.addLayout(self.horizontalLayout)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.device_list = QtWidgets.QTableWidget(Form)
self.device_list.setObjectName("device_list")
self.device_list.setColumnCount(0)
self.device_list.setRowCount(0)
self.horizontalLayout_3.addWidget(self.device_list)
self.formLayout = QtWidgets.QFormLayout()
self.formLayout.setObjectName("formLayout")
self.label_mac = QtWidgets.QLabel(Form)
self.label_mac.setObjectName("label_mac")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_mac)
self.et_mac = QtWidgets.QLineEdit(Form)
self.et_mac.setObjectName("et_mac")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.et_mac)
self.label_ip = QtWidgets.QLabel(Form)
self.label_ip.setObjectName("label_ip")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_ip)
self.et_ip = QtWidgets.QLineEdit(Form)
self.et_ip.setObjectName("et_ip")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.et_ip)
self.label_mask = QtWidgets.QLabel(Form)
self.label_mask.setObjectName("label_mask")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_mask)
self.et_mask = QtWidgets.QLineEdit(Form)
self.et_mask.setObjectName("et_mask")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.et_mask)
self.label_gateway = QtWidgets.QLabel(Form)
self.label_gateway.setObjectName("label_gateway")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_gateway)
self.et_gateway = QtWidgets.QLineEdit(Form)
self.et_gateway.setObjectName("et_gateway")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.et_gateway)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.formLayout.setItem(5, QtWidgets.QFormLayout.FieldRole, spacerItem1)
self.reset_ip = QtWidgets.QPushButton(Form)
self.reset_ip.setObjectName("reset_ip")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.reset_ip)
self.reboot_device = QtWidgets.QPushButton(Form)
self.reboot_device.setObjectName("reboot_device")
self.formLayout.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.reboot_device)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.formLayout.setItem(8, QtWidgets.QFormLayout.FieldRole, spacerItem2)
self.label_cmd = QtWidgets.QLabel(Form)
self.label_cmd.setObjectName("label_cmd")
self.formLayout.setWidget(9, QtWidgets.QFormLayout.LabelRole, self.label_cmd)
self.et_remote_cmd = QtWidgets.QLineEdit(Form)
self.et_remote_cmd.setObjectName("et_remote_cmd")
self.formLayout.setWidget(9, QtWidgets.QFormLayout.FieldRole, self.et_remote_cmd)
self.exec_remote_cmd = QtWidgets.QPushButton(Form)
self.exec_remote_cmd.setObjectName("exec_remote_cmd")
self.formLayout.setWidget(10, QtWidgets.QFormLayout.FieldRole, self.exec_remote_cmd)
self.et_cmd_result = QtWidgets.QTextEdit(Form)
self.et_cmd_result.setObjectName("et_cmd_result")
self.formLayout.setWidget(11, QtWidgets.QFormLayout.FieldRole, self.et_cmd_result)
self.horizontalLayout_3.addLayout(self.formLayout)
self.horizontalLayout_3.setStretch(0, 2)
self.horizontalLayout_3.setStretch(1, 1)
self.verticalLayout_2.addLayout(self.horizontalLayout_3)
self.verticalLayout_2.setStretch(1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.scan_device.setText(_translate("Form", "搜索设备"))
self.label_mac.setText(_translate("Form", "MAC地址:"))
self.label_ip.setText(_translate("Form", "IP地址:"))
self.label_mask.setText(_translate("Form", "子网掩码:"))
self.label_gateway.setText(_translate("Form", "网关地址:"))
self.reset_ip.setText(_translate("Form", "重新设置"))
self.reboot_device.setText(_translate("Form", "重启设备"))
self.label_cmd.setText(_translate("Form", "远程命令:"))
self.exec_remote_cmd.setText(_translate("Form", "执行远程命令(慎用)"))
2. main.py 主文件
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QTableWidgetItem, QTableWidget, QAbstractItemView
from PyQt5.QtCore import Qt, pyqtSignal, QObject
from PyQt5.QtGui import QFont, QImage, QPixmap, QIcon
import sys
import socket
import threading
import scan_device_ui
class signal(QObject):
# 自定义一个信号
signal = pyqtSignal(str)
# 定义一个发送信号的函数
def emit(self, text):
self.signal.emit(text)
class QDeviceWidget(QWidget):
def __init__(self):
super().__init__()
self.ui = ui = scan_device_ui.Ui_Form()
self.ui.setupUi(self)
self.setWindowTitle("海帆-设备配置助手 V1.0")
self.ui.scan_device.clicked.connect(self.scan_device)
self.ui.reset_ip.clicked.connect(self.reset_ip_info)
self.ui.reboot_device.clicked.connect(self.reboot_device)
self.ui.exec_remote_cmd.clicked.connect(self.exec_remote_cmd)
self.MULTICAST_ANY = "0.0.0.0"
self.MULTICAST_IP = "239.255.255.250"
self.MULTICAST_PORT = 35880
self.update_ui = signal()
self.update_ui.signal.connect(self.update_list_ui)
self.start_listening()
self.init_tables()
self.count_index = 0
self.list_content = []
def init_tables(self):
self.ui.device_list.setColumnCount(5)
self.ui.device_list.setHorizontalHeaderLabels(['ID', 'MAC地址', 'IP地址', '子网掩码', '网关'])
self.ui.device_list.setSelectionBehavior(QAbstractItemView.SelectRows)
self.ui.device_list.itemClicked.connect(self.table_item_click)
pass
def table_item_click(self, item):
print("item click = ", item.row())
content = self.list_content[item.row()]
self.ui.et_mac.setText(content[1])
self.ui.et_ip.setText(content[2])
self.ui.et_mask.setText(content[3])
self.ui.et_gateway.setText(content[4])
pass
def start_listening(self):
# 创建UDP socket
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
# 允许端口复用
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定监听多播数据包的端口
self.socket.bind((self.MULTICAST_ANY, self.MULTICAST_PORT))
# 声明该socket为多播类型
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
# 加入多播组,组地址由第三个参数制定
self.socket.setsockopt(
socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(self.MULTICAST_IP) + socket.inet_aton(self.MULTICAST_ANY)
)
self.socket.setblocking(False)
self.receive_thread = threading.Thread(target=self.receive_message_worker, args=())
self.receive_thread.start()
pass
def receive_message_worker(self):
print("start recive message thread ...")
while True:
try:
data, address = self.socket.recvfrom(2048)
except Exception as e:
# print(e)
pass
else:
data = data.decode()
print(data)
self.update_ui.emit(data)
pass
def scan_device(self):
print("scan device start ...")
self.list_content = []
self.count_index = 0
self.ui.device_list.clearContents()
self.socket.sendto("list".encode(), (self.MULTICAST_IP, self.MULTICAST_PORT))
pass
def update_list_ui(self, content):
if content.startswith("client"):
print("client = ", content)
self.ui.device_list.setRowCount(self.count_index + 1)
contents = content.split("-")
item1 = QTableWidgetItem(str(self.count_index + 1))
self.ui.device_list.setItem(self.count_index, 0, item1)
item2 = QTableWidgetItem(contents[1])
self.ui.device_list.setItem(self.count_index, 1, item2)
item3 = QTableWidgetItem(contents[2])
self.ui.device_list.setItem(self.count_index, 2, item3)
if len(contents) > 3:
item4 = QTableWidgetItem(contents[3])
self.ui.device_list.setItem(self.count_index, 3, item4)
item5 = QTableWidgetItem(contents[4])
self.ui.device_list.setItem(self.count_index, 4, item5)
self.count_index += 1
self.list_content.append([str(self.count_index + 1), contents[1], contents[2], contents[3], contents[4]])
if content.startswith("cmdstr"):
content = content.split("#")[1]
self.ui.et_cmd_result.setText(content)
pass
def reset_ip_info(self):
mac = self.ui.et_mac.text()
ip = self.ui.et_ip.text()
mask = self.ui.et_mask.text()
gateway = self.ui.et_gateway.text()
cmd = "modifyip-{}-{}-{}-{}".format(mac, ip, mask, gateway)
print("reset ip param = " + cmd)
self.socket.sendto(cmd.encode(), (self.MULTICAST_IP, self.MULTICAST_PORT))
pass
def reboot_device(self):
mac = self.ui.et_mac.text()
cmd = "reboot-{}".format(mac)
print("reset ip param = " + cmd)
self.socket.sendto(cmd.encode(), (self.MULTICAST_IP, self.MULTICAST_PORT))
def exec_remote_cmd(self):
mac = self.ui.et_mac.text()
cmdstr = self.ui.et_remote_cmd.text()
cmd = "exec#{}#{}#".format(mac, cmdstr)
print("reset ip param = " + cmd)
self.socket.sendto(cmd.encode(), (self.MULTICAST_IP, self.MULTICAST_PORT))
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QDeviceWidget()
# w.setWindowState(Qt.WindowMaximized)
w.show()
sys.exit(app.exec_())