板子最好先安装mini-anaconda,我自己安装的python3.9版本
一、rknn官方sdk下载:
https://meta.zbox.filez.com/v/link/view/ef37a9687973439f94f5b06837f12527
提取码:rknn
二、模型转换(安装依赖文件)
ubuntu环境上先执行onnx–>rknn
注意:rknn开发板上,不能使用RKNN,需要使用RKNNLite
报错,缺少库文件
解决办法:wget https://github.com/airockchip/rknn-toolkit2/blob/v2.3.0/rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so
然后移动到/usr/lib 下
运行demo成功!!!
四、海康相机sdk
下载arm版本的sdk,添加所有的库文件
完整代码:移动监测+行为识别+数据推送
from ctypes import *
import sys
import os
import time
from datetime import datetime
# import mysql.connector
from ultralytics import YOLO
import cv2
import requests
# import paho.mqtt.client as mqtt
import json
import numpy as np
# 在文件开头添加一个全局计数器字典
ALARM_COUNTERS = {
"移动侦测报警": 0,
"硬盘满": 0,
"硬盘出错": 0,
"信号丢失": 0,
"移动侦测报警触发": 0,
"非法访问": 0,
"输入/输出视频制式不匹配": 0,
"视频信号异常": 0,
"录像/抓图异常": 0,
"IP地址冲突": 0,
}
# 在全局变量区域添加最后抓图时间记录
LAST_CAPTURE_TIME = 0
CAPTURE_INTERVAL = 2 # 抓图间隔时间(秒)
# 在文件开头的全局变量区域添加
LAST_ALARM_TIME = 0 # 记录上次报警时间
ALARM_INTERVAL = 2 # 报警间隔时间(秒)
# 在文件开头的全局变量区域添加
LAST_DETECT_TIME = 0 # 记录上次人体检测时间
DETECT_INTERVAL = 60 # 人体检测间隔时间(秒)
# 添加设备信息结构体定义
class NET_DVR_DEVICEINFO_V30(Structure):
_fields_ = [
("sSerialNumber", c_byte * 48), # 序列号
("byAlarmInPortNum", c_byte), # 报警输入个数
("byAlarmOutPortNum", c_byte), # 报警输出个数
("byDiskNum", c_byte), # 硬盘个数
("byDVRType", c_byte), # 设备类型
("byChanNum", c_byte), # 设备模拟通道个数
("byStartChan", c_byte), # 起始通道号
("byAudioChanNum", c_byte), # 语音通道数
("byIPChanNum", c_byte), # 最大数字通道个数
("byZeroChanNum", c_byte), # 零通道编码个数
("byMainProto", c_byte), # 主码流传输协议类型
("bySubProto", c_byte), # 子码流传输协议类型
("bySupport", c_byte), # 能力,位与结果为0表示不支持,1表示支持
("bySupport1", c_byte), # 能力集扩充
("bySupport2", c_byte), # 能力集扩充
("wDevType", c_uint16), # 设备型号
("bySupport3", c_byte), # 能力集扩充
("byMultiStreamProto", c_byte), # 是否支持多码流
("byStartDChan", c_byte), # 起始数字通道号
("byStartDTalkChan", c_byte), # 起始数字对讲通道号
("byHighDChanNum", c_byte), # 数字通道个数,高位
("bySupport4", c_byte), # 能力集扩充
("byLanguageType", c_byte), # 支持语种能力
("byVoiceInChanNum", c_byte), # 音频输入通道数
("byStartVoiceInChanNo", c_byte), # 音频输入起始通道号
("bySupport5", c_byte), # 能力集扩充
("bySupport6", c_byte), # 能力集扩充
("byMirrorChanNum", c_byte), # 镜像通道个数
("wStartMirrorChanNo", c_uint16), # 起始镜像通道号
("bySupport7", c_byte), # 能力集扩充
("byRes2", c_byte * 2) # 保留字节
]
# 添加布防参数结构体
class NET_DVR_SETUPALARM_PARAM(Structure):
_fields_ = [
("dwSize", c_uint32),
("byLevel", c_byte),
("byAlarmInfoType", c_byte),
("byRetAlarmTypeV40", c_byte),
("byRetDevInfoVersion", c_byte),
("byRetVQDAlarmType", c_byte),
("byFaceAlarmDetection", c_byte),
("bySupport", c_byte),
("byBrokenNetHttp", c_byte),
("wTaskNo", c_uint16),
("byDeployType", c_byte),
("byRes1", c_byte * 3),
("byAlarmTypeURL", c_byte),
("byCustomCtrl", c_byte)
]
# 添加抓图结构体
class NET_DVR_JPEGPARA(Structure):
_fields_ = [
("wPicSize", c_ushort),
("wPicQuality", c_ushort)
]
# 添加新的抓图结构体
class NET_DVR_JPEGPARA_NEW(Structure):
_fields_ = [
("wPicSize", c_ushort), # 图片尺寸
("wPicQuality", c_ushort), # 图片质量
("dwPicSize", c_uint32), # 图片大小
("byRes", c_byte * 224) # 保留字节
]
# 加载海康威视的SDK动态库
def load_hk_sdk():
if os.name == 'nt': # Windows系统
sdk_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), './lib')
os.environ['PATH'] += ';' + sdk_dir
return CDLL(os.path.join(sdk_dir, 'HCNetSDK.dll'))
else: # Linux系统
sdk_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib/linux')
return CDLL(os.path.join(sdk_dir, 'libhcnetsdk.so'))
# 修改报警回调函数
@CFUNCTYPE(None, c_int, POINTER(c_int), POINTER(c_int), c_int, c_void_p)
def alarm_callback(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser):
global LAST_CAPTURE_TIME, LAST_ALARM_TIME, LAST_DETECT_TIME, ALARM_COUNTERS
try:
current_time = time.time()
# 检查报警时间间隔
time_since_last_alarm = current_time - LAST_ALARM_TIME
if time_since_last_alarm < ALARM_INTERVAL:
# print(f"距离上次报警仅过去 {time_since_last_alarm:.1f} 秒,忽略本次报警")
return
# 更新报警时间
LAST_ALARM_TIME = current_time
if lCommand == 0x1100: # 移动侦测报警
ALARM_COUNTERS["移动侦测报警"] += 1
# print(f"移动侦测报警触发 (总计: {ALARM_COUNTERS['移动侦测报警']}次)")
elif lCommand == 0x4000: # 异常报警
alarm_info = cast(pAlarmInfo, POINTER(NET_DVR_ALARMINFO)).contents
exception_type = alarm_info.dwAlarmType
# print(f"异常类型: {exception_type}")
exception_types = {
0: "信号量报警",
1: "硬盘满",
2: "信号丢失",
3: "移动侦测",
4: "硬盘未格式化",
5: "读写硬盘出错",
6: "遮挡报警",
7: "制式不匹配",
8: "非法访问",
}
exception_msg = exception_types.get(exception_type, "未知异常类型")
if exception_msg not in ALARM_COUNTERS:
ALARM_COUNTERS[exception_msg] = 0
ALARM_COUNTERS[exception_msg] += 1
# print(f"异常类型: {exception_msg} (总计: {ALARM_COUNTERS[exception_msg]}次)")
# 当检测到移动侦测时,先检查上次异常检测的时间间隔
if exception_type == 3:
time_since_last_detect = current_time - LAST_DETECT_TIME
if time_since_last_detect < DETECT_INTERVAL:
# print(f"距离上次异常检测仅过去 {time_since_last_detect:.1f} 秒,跳过本次检测")
return
try:
monitor = cast(pUser, py_object).value
if monitor.capture_picture():
print(f"抓图成功,报警时间: {datetime.fromtimestamp(current_time)}")
except Exception as e:
print(f"抓图过程出错: {str(e)}")
except Exception as e:
print(f"报警回调函数出错: {str(e)}")
# 添加异常信息结构体
class NET_DVR_ALARMINFO(Structure):
_fields_ = [
("dwAlarmType", c_uint32), # 报警类型
("dwAlarmInputNumber", c_uint32), # 报警输入端口
("dwAlarmOutputNumber", c_byte * 4), # 报警输出端口
("dwAlarmRelateChannel", c_byte * 4), # 报警触发的通道
("dwChannel", c_byte * 4), # 现在报警的通道
("dwDiskNumber", c_byte * 4) # 发生报警的硬盘
]
# 添加 MQTT 客户端类
class MQTTPublisher:
def __init__(self):
self.client = mqtt.Client()
try:
# 连接到 MQTT 服务器
self.client.connect("127.0.0.1", 1883, 60)
self.client.loop_start()
print("MQTT 客户端连接成功")
except Exception as e:
print(f"MQTT 客户端连接失败: {str(e)}")
def publish_alarm(self, device_id, alarm_type, detect_image_url, alarm_time):
try:
# 构建消息内容
message = {
"device_id": device_id,
"alarm_type": alarm_type,
"detect_image_url": detect_image_url,
"alarm_time": alarm_time
}
# 发布消息
self.client.publish("camera/alarm", json.dumps(message))
print("MQTT 消息发送成功")
except Exception as e:
print(f"MQTT 消息发送失败: {str(e)}")
def disconnect(self):
self.client.loop_stop()
self.client.disconnect()
# 添加数据库配置和操作类
class DatabaseManager:
def __init__(self):
# self.conn = mysql.connector.connect(
# host="localhost",
# user="root",
# password="",
# database="test"
# )
#self.cursor = self.conn.cursor()
#self.mqtt_publisher = MQTTPublisher()
self.access_token = None
self.token_expire_time = 0
def get_access_token(self):
"""获取访问令牌"""
try:
current_time = time.time()
# 如果token未过期,直接返回
if self.access_token and current_time < self.token_expire_time:
return self.access_token
# 请求新token
data = {
'client_id': 'video',
'client_secret': 'isti123@',
'grant_type': 'client_credentials'
}
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.post(
'http://192.168.30.9:9001/oauth/token',
data=data,
headers=headers
)
if response.status_code == 200:
result = response.json()
self.access_token = result['access_token']
# 设置token过期时间(提前5分钟过期)
self.token_expire_time = current_time + result['expires_in'] - 300
print("获取token成功")
return self.access_token
else:
print(f"获取token失败,状态码: {response.status_code}")
print(f"响应内容: {response.text}")
return None
except Exception as e:
print(f"获取token异常: {str(e)}")
return None
def push_to_api(self, device_id, alarm_type, detect_image_url):
"""推送数据到HTTP接口"""
try:
# 获取token
token = self.get_access_token()
if not token:
print("无法获取token,取消推送")
return
# 从device_id中分离设备编号和通道号
device_serial, channel_no = device_id.split('_')
# 构建请求数据
data = {
"deviceSerial": device_serial,
"channelNo": int(channel_no),
"alarmType": str(alarm_type),
"detectImageUrl": detect_image_url
}
# 构建请求头
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}'
}
# 发送POST请求
response = requests.post(
'http://192.168.30.9:7887/video/detect/upload',
json=data,
headers=headers,
timeout=5
)
print(f"推送数据: {data}")
print(f"响应状态码: {response.status_code}")
print(f"响应内容: {response.text}")
if response.status_code == 200:
print("数据推送成功")
else:
print(f"数据推送失败,状态码: {response.status_code}")
print(f"响应内容: {response.text}")
except Exception as e:
print(f"数据推送异常: {str(e)}")
def insert_alarm_record(self, device_id, alarm_type, detect_image_url=None):
try:
# 保存到数据库
# sql = """INSERT INTO alarm_detect
# (device_id, alarm_type, alarm_time, detect_image_url)
# VALUES (%s, %s, %s, %s)"""
# alarm_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# values = (device_id, alarm_type, alarm_time, detect_image_url)
# self.cursor.execute(sql, values)
# self.conn.commit()
# print("报警记录已插入数据库")
# 发送 MQTT 消息
# self.mqtt_publisher.publish_alarm(
# device_id=device_id,
# alarm_type=alarm_type,
# detect_image_url=detect_image_url,
# alarm_time=alarm_time
# )
# 推送数据到HTTP接口
if detect_image_url: # 只有在有图片URL时才推送
self.push_to_api(device_id, alarm_type, detect_image_url)
except Exception as e:
print(f"推送数据失败: {str(e)}")
def close(self):
# self.cursor.close()
# self.conn.close()
# self.mqtt_publisher.disconnect()
pass
def upload_image(self, image_path):
"""上传图片到指定服务器"""
try:
# 获取token
token = self.get_access_token()
if not token:
print("无法获取token,取消上传")
return None
with open(image_path, 'rb') as f:
files = {'imageFile': f}
headers = {
'Authorization': f'Bearer {token}'
}
print(f"开始上传图片: {image_path}")
response = requests.post(
'http://192.168.30.9:7887/video/detect/image',
files=files,
headers=headers
)
print(f"上传响应状态码: {response.status_code}")
print(f"上传响应内容: {response.text}")
if response.status_code == 200:
result = response.json()
if 'data' in result:
print(f"获取到图片URL: {result['data']}")
return result['data']
else:
print("响应中没有data字段")
else:
print(f"上传失败,状态码: {response.status_code}")
return None
except Exception as e:
print(f"图片上传过程发生异常: {str(e)}")
return None
class AlarmMonitor:
def __init__(self, ip, port, username, password, device_no, channel):
self.ip = ip
self.port = port
self.username = username
self.password = password
self.sdk = load_hk_sdk()
self.device_handle = -1
self.alarm_handle = -1
# 使用设备编号+通道号作为设备ID
self.device_id = f"{device_no}_{channel}"
self.db = DatabaseManager()
# 确保pic目录存在
self.pic_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pic')
if not os.path.exists(self.pic_dir):
os.makedirs(self.pic_dir)
# 修改为使用 pose 检测模型
self.model = YOLO("yolov8n-pose.pt") # 初始化YOLO pose模型
def init_device(self):
# 初始化SDK
init_result = self.sdk.NET_DVR_Init()
if init_result == 0:
print("SDK初始化失败")
return False
# 设置连接超时时间和重连时间
self.sdk.NET_DVR_SetConnectTime(2000, 1)
self.sdk.NET_DVR_SetReconnect(10000, True)
# 注册设备
device_info = NET_DVR_DEVICEINFO_V30()
self.device_handle = self.sdk.NET_DVR_Login_V30(
bytes(self.ip, 'utf-8'),
self.port,
bytes(self.username, 'utf-8'),
bytes(self.password, 'utf-8'),
byref(device_info)
)
if self.device_handle < 0:
print("设备登录失败")
self.get_last_error()
return False
print("设备登录成功")
if self.device_handle >= 0:
# 设置布防参数
alarm_param = NET_DVR_SETUPALARM_PARAM()
alarm_param.dwSize = sizeof(NET_DVR_SETUPALARM_PARAM)
alarm_param.byLevel = 1 # 布防优先级
alarm_param.byAlarmInfoType = 1 # 智能交通报警信息上传类型:0- 老报警信息(NET_DVR_PLATE_RESULT),1- 新报警信息(NET_ITS_PLATE_RESULT)
# 布防
self.alarm_handle = self.sdk.NET_DVR_SetupAlarmChan_V41(self.device_handle, byref(alarm_param))
if self.alarm_handle < 0:
print("布防失败")
return False
print("布防成功")
return True
return False
def start_alarm_listen(self):
if self.device_handle < 0:
print("设备未登录")
return False
# 设置报警回调函数,传入self作为用户数据
self.sdk.NET_DVR_SetDVRMessageCallBack_V31(alarm_callback, py_object(self))
# 启动报警监听
self.alarm_handle = self.sdk.NET_DVR_StartListen_V30(
self.device_handle,
bytes("0.0.0.0", 'utf-8'),
8000,
None,
None
)
if self.alarm_handle < 0:
print("启动报警监听失败")
return False
print("报警监听启动成功")
return True
def stop_alarm_listen(self):
# 在停止监听前打印统计信息
self.print_alarm_statistics()
if self.alarm_handle >= 0:
# 撤防
self.sdk.NET_DVR_CloseAlarmChan_V30(self.alarm_handle)
self.alarm_handle = -1
if self.device_handle >= 0:
self.sdk.NET_DVR_Logout(self.device_handle)
self.device_handle = -1
self.sdk.NET_DVR_Cleanup()
self.db.close() # 关闭数据库连接
def get_last_error(self):
error_code = self.sdk.NET_DVR_GetLastError()
print(f"错误码: {error_code}")
return error_code
def print_alarm_statistics(self):
print("\n报警统计信息:")
print("-" * 40)
for alarm_type, count in ALARM_COUNTERS.items():
if count > 0: # 只打印发生过的报警类型
print(f"{alarm_type}: {count}次")
print("-" * 40)
def detect_person(self, image_path):
"""使用YOLO pose检测图片中是否有人体角度超过80度"""
try:
# 读取图片并旋转180度
image = cv2.imread(image_path)
image = cv2.rotate(image, cv2.ROTATE_180)
# YOLO pose检测
results = self.model.predict(
image,
save=False,
project="results",
name="my_results",
exist_ok=True
)
has_angle_over_80 = False
result_image_path = None
# 检查是否检测到人并计算角度
for result in results:
keypoints = result.keypoints # 获取关键点数据
if len(keypoints) > 0: # 如果检测到关键点
for i in range(len(keypoints)):
np_arr = keypoints[i].xy.cpu().numpy()
# 获取关键点坐标
left_hip = np_arr[0][11] # 左髋
left_knee = np_arr[0][13] # 左膝
right_hip = np_arr[0][12] # 右髋
right_knee = np_arr[0][14] # 右膝
left_shoulder = np_arr[0][5] # 左肩
left_wrist = np_arr[0][9] # 左手腕
right_shoulder = np_arr[0][6]# 右肩
right_wrist = np_arr[0][10] # 右手腕
# 检查所有关键点是否有效
key_points = [left_hip, left_knee, right_hip, right_knee,
left_shoulder, left_wrist, right_shoulder, right_wrist]
if not all(all(point) for point in key_points):
print("存在无效关键点,跳过当前姿态分析")
continue
# 标记所有关键点
for j in range(len(np_arr[0])):
point = tuple(map(int, np_arr[0][j]))
cv2.circle(image, point, 10, (0, 255, 255), -1) # 黄色,半径10,实心圆
cv2.circle(image, point, 10, (0, 0, 0), 2) # 黑色边框
# 转换为整数坐标
left_hip = tuple(map(int, left_hip))
left_knee = tuple(map(int, left_knee))
right_hip = tuple(map(int, right_hip))
right_knee = tuple(map(int, right_knee))
left_shoulder = tuple(map(int, left_shoulder))
left_wrist = tuple(map(int, left_wrist))
right_shoulder = tuple(map(int, right_shoulder))
right_wrist = tuple(map(int, right_wrist))
# 绘制四肢线段,使用不同颜色
cv2.line(image, left_hip, left_knee, (0, 0, 255), 8) # 左腿-红色
cv2.line(image, right_hip, right_knee, (255, 0, 0), 8) # 右腿-蓝色
cv2.line(image, left_shoulder, left_wrist, (0, 255, 0), 8) # 左臂-绿色
cv2.line(image, right_shoulder, right_wrist, (255, 255, 0), 8) # 右臂-青色
# 计算所有腿与手臂的夹角组合
legs = [
(np.array(left_knee) - np.array(left_hip), "左腿"),
(np.array(right_knee) - np.array(right_hip), "右腿")
]
arms = [
(np.array(left_wrist) - np.array(left_shoulder), "左臂"),
(np.array(right_wrist) - np.array(right_shoulder), "右臂")
]
# 检查所有可能的组合
for leg, leg_name in legs:
for arm, arm_name in arms:
angle = np.degrees(np.arctan2(leg[1], leg[0]) -
np.arctan2(arm[1], arm[0]))
angle = angle + 360 if angle < 0 else angle
angle = angle if angle <= 180 else 360 - angle
print(f"{leg_name}与{arm_name}的夹角: {angle}°")
if angle > 80:
has_angle_over_80 = True
# 计算异常组合的中点位置
if leg_name == "左腿":
warning_x = int((left_hip[0] + left_knee[0]) / 2)
warning_y = int((left_hip[1] + left_knee[1]) / 2)
else:
warning_x = int((right_hip[0] + right_knee[0]) / 2)
warning_y = int((right_hip[1] + right_knee[1]) / 2)
# 绘制警告标记
warning_size = 50
warning_color = (0, 0, 255) # 红色
# 绘制三角形警告标志
triangle_pts = np.array([
[warning_x, warning_y - warning_size],
[warning_x - warning_size//2, warning_y + warning_size//2],
[warning_x + warning_size//2, warning_y + warning_size//2]
], np.int32)
cv2.polylines(image, [triangle_pts], True, warning_color, 3)
# 在三角形中心绘制感叹号
cv2.putText(image, "!",
(warning_x - 5, warning_y + 10),
cv2.FONT_HERSHEY_SIMPLEX,
1, warning_color, 3)
# 保存处理后的图片
result_image_path = f"results/my_results/{os.path.basename(image_path)}"
cv2.imwrite(result_image_path, image)
if has_angle_over_80:
print(f"检测到角度超过80°")
return True, result_image_path
else:
print("未检测到异常姿态")
# todo 删除抓拍的图片以及处理后的图片
return False, None
except Exception as e:
print(f"人体姿态检测失败: {str(e)}")
return False, None
def capture_picture(self):
"""抓取图片并保存"""
global LAST_CAPTURE_TIME
# 在开始抓图前检查时间间隔
current_time = time.time()
time_since_last_capture = current_time - LAST_CAPTURE_TIME
if time_since_last_capture < CAPTURE_INTERVAL:
print(f"距离上次抓图仅过去 {time_since_last_capture:.1f} 秒,需要等待 {CAPTURE_INTERVAL-time_since_last_capture:.1f} 秒")
return False
if self.device_handle < 0:
print("设备未登录,无法抓图")
return False
try:
# 在实际抓图前更新时间戳,防止并发
LAST_CAPTURE_TIME = current_time
print(f"开始抓图,更新时间戳: {datetime.fromtimestamp(LAST_CAPTURE_TIME)}")
jpeg_para = NET_DVR_JPEGPARA_NEW()
jpeg_para.wPicSize = 0xff
jpeg_para.wPicQuality = 0
buffer_size = 1024 * 1024
picture_buffer = create_string_buffer(buffer_size)
bytes_returned = c_ulong(0)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
picture_file = os.path.join(self.pic_dir, f'capture_{timestamp}.jpg')
if self.sdk.NET_DVR_CaptureJPEGPicture_NEW(
self.device_handle,
1,
byref(jpeg_para),
picture_buffer,
buffer_size,
byref(bytes_returned)
):
with open(picture_file, 'wb') as f:
f.write(picture_buffer.raw[:bytes_returned.value])
print(f"抓图成功:{picture_file}")
# 进行人体检测
has_person, result_image_path = self.detect_person(picture_file)
if has_person and result_image_path:
print("检测到异常姿态")
# 只有在检测到异常姿态时才更新检测时间
global LAST_DETECT_TIME
LAST_DETECT_TIME = current_time
print(f"更新异常检测时间: {datetime.fromtimestamp(LAST_DETECT_TIME)}")
detect_image_url = self.db.upload_image(result_image_path)
if detect_image_url:
print(f"检测结果图片上传成功: {detect_image_url}")
self.db.insert_alarm_record(
device_id=self.device_id,
alarm_type='1',
detect_image_url=detect_image_url
)
return True
else:
# 如果没有检测到异常姿态,删除图片
try:
os.remove(picture_file)
print(f"已删除抓拍图片: {picture_file}")
if result_image_path and os.path.exists(result_image_path):
os.remove(result_image_path)
print(f"已删除处理后的图片: {result_image_path}")
except Exception as e:
print(f"删除图片失败: {str(e)}")
return False
else:
error_code = self.sdk.NET_DVR_GetLastError()
print(f"抓图失败,错误码:{error_code}")
# 如果抓图失败,重置时间戳
LAST_CAPTURE_TIME = current_time - CAPTURE_INTERVAL
return False
except Exception as e:
print(f"抓图过程发生异常: {str(e)}")
# 发生异常时也重置时间戳
LAST_CAPTURE_TIME = current_time - CAPTURE_INTERVAL
return False
def main():
# 设备列表
devices = [
{
"ip": "192.168.200.166",
"port": 8000,
"username": "admin",
"password": "isti1234",
"device_no": "AA5336153", # 设备编号
"channel": "01" # 通道号
},
{
"ip": "192.168.200.167",
"port": 8000,
"username": "admin",
"password": "password2",
"device_no": "HK002", # 设备编号
"channel": "01" # 通道号
},
]
monitors = []
try:
# 初始化所有设备的监控
for device in devices:
monitor = AlarmMonitor(
device["ip"],
device["port"],
device["username"],
device["password"],
device["device_no"], # 添加设备编号
device["channel"] # 添加通道号
)
if monitor.init_device():
if monitor.start_alarm_listen():
print(f"设备 {device['device_no']}_{device['channel']} 开始监听报警...")
monitors.append(monitor)
else:
print(f"设备 {device['device_no']}_{device['channel']} 启动报警监听失败")
else:
print(f"设备 {device['device_no']}_{device['channel']} 初始化失败")
if monitors:
print(f"成功启动 {len(monitors)} 个设备的监控")
# 保持程序运行
while True:
time.sleep(1)
else:
print("没有成功启动的设备监控")
except KeyboardInterrupt:
print("\n程序退出...")
finally:
# 停止所有设备的监控
for monitor in monitors:
monitor.stop_alarm_listen()
if __name__ == "__main__":
main()