jiateng_ws/utils/electricity_monitor.py

200 lines
6.5 KiB
Python
Raw Permalink Normal View History

2025-06-26 18:26:22 +08:00
import logging
import time
from threading import Thread, Event
from PySide6.QtCore import QTimer, QObject, Signal
2025-06-26 18:26:22 +08:00
from utils.modbus_utils import ModbusUtils
from utils.modbus_monitor import RegisterHandler
from dao.electricity_dao import ElectricityDAO
from utils.config_loader import ConfigLoader
class ElectricityHandler(RegisterHandler, QObject):
2025-06-26 18:26:22 +08:00
"""电力消耗寄存器处理器"""
# 定义电力数据变化信号
electricity_data_changed = Signal(float)
2025-06-26 18:26:22 +08:00
def __init__(self):
"""初始化处理器"""
QObject.__init__(self)
2025-06-26 18:26:22 +08:00
self.dao = ElectricityDAO()
# 确保表已创建
self.dao.create_table_if_not_exists()
def handle_change(self, value):
"""处理寄存器值变化
Args:
value: 寄存器值
"""
try:
# 保存电力消耗数据
self.dao.save_electricity_data(value)
logging.info(f"已记录电力消耗数据: {value}")
# 发射电力数据变化信号
self.electricity_data_changed.emit(value)
2025-06-26 18:26:22 +08:00
except Exception as e:
logging.error(f"处理电力消耗数据时发生错误: {str(e)}")
class ElectricityMonitor:
"""电力消耗监控器"""
_instance = None
@classmethod
def get_instance(cls):
"""获取单例实例"""
if cls._instance is None:
cls._instance = ElectricityMonitor()
return cls._instance
def __init__(self):
"""初始化电力监控器"""
if ElectricityMonitor._instance:
raise Exception("ElectricityMonitor is a singleton class.")
self.modbus = ModbusUtils()
self.dao = ElectricityDAO()
self.config = ConfigLoader.get_instance()
# 确保表已创建
self.dao.create_table_if_not_exists()
# 创建定时器
self.timer = None
self.client = None
self.stop_event = Event()
self.monitor_thread = None
# 电力寄存器地址
self.electricity_register = 30
# 从配置中读取监听间隔(分钟)
self.interval_minutes = self.config.get_value('electricity.interval_minutes', 1)
# 从配置中读取是否自动启动
self.auto_start = self.config.get_value('electricity.auto_start', True)
# 上次读取时间
self.last_read_time = None
# 如果配置为自动启动,则启动监控
if self.auto_start:
self.start()
def start(self):
"""启动监控"""
if self.timer and self.timer.isActive():
logging.warning("电力监控器已经在运行中")
return
# 创建并启动定时器,每分钟读取一次
self.timer = QTimer()
self.timer.timeout.connect(self._read_electricity_data)
self.timer.start(self.interval_minutes * 60000) # 转换为毫秒
# 立即执行一次读取
self._read_electricity_data()
# 更新配置
self.config.set_value('electricity.auto_start', True)
logging.info(f"电力监控器已启动,每{self.interval_minutes}分钟读取一次寄存器30的数据")
def stop(self):
"""停止监控"""
if self.timer:
self.timer.stop()
if self.client:
self.modbus.close_client(self.client)
self.client = None
# 更新配置
self.config.set_value('electricity.auto_start', False)
logging.info("电力监控器已停止")
def set_interval(self, minutes):
"""设置监听间隔
Args:
minutes: 间隔分钟数
"""
if minutes < 1:
minutes = 1
self.interval_minutes = minutes
# 更新配置
self.config.set_value('electricity.interval_minutes', minutes)
# 如果定时器正在运行,则更新间隔
if self.timer and self.timer.isActive():
self.timer.setInterval(minutes * 60000) # 转换为毫秒
logging.info(f"电力监控间隔已更新为{minutes}分钟")
def is_monitoring(self):
"""检查是否正在监控
Returns:
bool: 是否正在监控
"""
return self.timer is not None and self.timer.isActive()
def get_last_read_time(self):
"""获取上次读取时间
Returns:
datetime: 上次读取时间如果未读取过则返回None
"""
return self.last_read_time
def get_next_read_time(self):
"""获取下次读取时间
Returns:
datetime: 下次读取时间如果未在监控则返回None
"""
if not self.is_monitoring() or not self.last_read_time:
return None
from datetime import datetime, timedelta
return self.last_read_time + timedelta(minutes=self.interval_minutes)
def _read_electricity_data(self):
"""读取电力消耗数据"""
try:
# 如果客户端未连接,则创建连接
if not self.client:
self.client = self.modbus.get_client()
if not self.client:
logging.error("无法连接到Modbus服务器电力数据读取失败")
return
# 读取寄存器30的值
result = self.modbus.read_holding_register(self.client, self.electricity_register)
if result is None or len(result) == 0:
logging.warning(f"读取寄存器D{self.electricity_register}失败")
return
# 获取电力消耗值
electricity_value = result[0]
# 保存到数据库
success = self.dao.save_electricity_data(electricity_value)
if success:
logging.info(f"已记录电力消耗数据: {electricity_value}")
# 更新上次读取时间
from datetime import datetime
self.last_read_time = datetime.now()
else:
logging.error("保存电力消耗数据失败")
except Exception as e:
logging.error(f"读取或保存电力消耗数据时发生错误: {str(e)}")
# 关闭连接,下次重新尝试
if self.client:
self.modbus.close_client(self.client)
self.client = None