Files
Kivy_APP/comm_modbus_device.py
2025-07-25 08:08:11 +08:00

626 lines
30 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from comm_device import class_comm_device
from comm_thread import class_comm_master_thread
from mqtt_device import class_comm_mqtt_thread, class_comm_mqtt_interface
import time
import comm_device
from threading import Thread
import menu_utils as utils
import struct
import math
import json
import random
from enum import Enum
from comm_protocol import class_protocol
from mqtt_object import class_mqtt_info_object
from print_color import *
from comm_protocol_modbus import class_protocol_modbus
BASE_FAIL_DELAY = 1000 # 通信失败基础延迟(毫秒)
MAX_FAIL_DELAY = 30000 # 最大通信失败延迟(毫秒)
BASE_GLOBAL_FAIL_DELAY = 500 # 全局通信失败基础延迟(毫秒)
MAX_GLOBAL_FAIL_DELAY = 60000 # 最大全局通信失败延迟(毫秒)
DEFAULT_TIMEOUT = 20 # 默认超时时间(毫秒)
# MAX_FAIL_COUNT = 15 # 最大失败次数
class class_comm_table_item() :
def __init__(self, name = "", reg_addr = 0, reg_count = 0, cycle = 0, mqtt_pack = None, remap_addr = 0):
self.reg_addr = reg_addr
self.reg_count = reg_count
self.cycle = cycle
self.name = name
self.remain_cycle = 0
self.comm_fail_delay = 0
self.comm_count = 0
self.comm_fail_count = 0
self.comm_success_count = 0
self.comm_success = False
self.comm_trigger = False
self.mqtt_pack = mqtt_pack
self.remap_addr = remap_addr
self.flush_request_delay = 0
self.base_time = time.time()
self.reg_buf = []
self.comm_fail_delay = 0 # 通信失败延迟
def in_range(self, reg_addr, reg_count) :
reg_addr_begin = self.reg_addr
reg_addr_end = self.reg_addr + self.reg_count
if reg_addr >= reg_addr_begin and reg_addr + reg_count <= reg_addr_end :
return True
return False
def update_item_value(self, reg_addr, reg_count, new_value) :
if self.in_range(reg_addr, reg_count) and len(self.reg_buf) :
reg_off = reg_addr - self.reg_addr
new_reg = list(self.reg_buf)
for i in range(reg_count) :
new_reg[reg_off + i] = new_value[i]
self.reg_buf = new_reg
self.comm_trigger = True
def read_register_count(self, reg_addr, reg_count) :
reg_addr_begin = self.reg_addr
reg_addr_end = self.reg_addr + self.reg_count
result = None
if reg_addr >= reg_addr_begin and reg_addr + reg_count <= reg_addr_end :
if len(self.reg_buf) >= self.reg_count:
result = []
reg_off = reg_addr - self.reg_addr
for i in range(reg_count):
result.append(self.reg_buf[reg_off + i])
return result
#为了防止阻塞 mqtt订阅流程, 采用class_mqtt_process_thread线程来处理 接收到的主题与消息
class class_mqtt_process_thread(Thread):
def __init__(self,
parent_device,
topic : str = None,
message : str = None,
):
Thread.__init__(self)
self.topic = topic
self.message = message
self.parent_device : class_modbus_comm_device = parent_device
def run(self):
self.parent_device.on_process_topic_message(self.topic, self.message)
#modbus通讯设备, 管理modbus主机通讯, 实现mqtt客户端
class class_modbus_comm_device(class_comm_device, class_comm_mqtt_interface) :
def __init__(self,
comm_addr = 0,
device_remap = None,
comm_table = None,
func_comm_trigger = None,
mqtt_thread : class_comm_mqtt_thread = None,
protocol : class_protocol_modbus = None,
mqtt_info_object : class_mqtt_info_object = None,
unique_name = None,
action_process_func = None, #action处理函数
request_alarm_func = None, #故障查询函数
alias_table = None):
class_comm_device.__init__(self, comm_addr, device_remap, unique_name)
class_comm_mqtt_interface.__init__(self)
self.comm_loop_count = 0
self.comm_index = 0
self.mqtt_thread = mqtt_thread
self.comm_device_comm_active = True #设置该设备是否需要通讯
self.comm_fail_delay = 0 #通讯延时
self.func_comm_trigger = func_comm_trigger
self.protocol : class_protocol_modbus = protocol
self.mqtt_info_object : class_mqtt_info_object = mqtt_info_object
self.unique_name : str = unique_name
self.action_process_func = action_process_func
self.request_alarm_func = request_alarm_func
self.alias_table = alias_table
self.comm_table = comm_table
self.comm_table_item_list : class_comm_table_item = [] #list of class_comm_table_item
self.create_comm_item_list(comm_table)
def modbus_regs_flush(self, reg_addr, reg_count, values) :
for each in self.comm_table_item_list:
comm_item : class_comm_table_item = each
comm_item.update_item_value(reg_addr, reg_count, values)
def create_comm_item_list(self, comm_table : class_comm_table_item) :
self.comm_table_item_list = []
if comm_table != None :
for comm_item_dict in comm_table :
_name = utils.dict_or_object_get_attr(comm_item_dict, "name", " ")
_reg_addr = utils.dict_or_object_get_attr(comm_item_dict, "reg_addr", 0)
_reg_count = utils.dict_or_object_get_attr(comm_item_dict, "reg_count", 0)
_cycle = utils.dict_or_object_get_attr(comm_item_dict, "cycle", 0)
_mqtt_pack = utils.dict_or_object_get_attr(comm_item_dict, "mqtt_pack", None)
self.comm_table_item_list.append(class_comm_table_item(name = _name,
reg_addr =_reg_addr,
reg_count = _reg_count,
cycle = _cycle,
mqtt_pack = _mqtt_pack))
#@override, mqtt on connect
def on_connect(self, mqtt_thread, userdata, flags, rc) :
if rc == 0 :
#获取线程类 class_comm_mqtt_thread)
mqtt_comm_thread : class_comm_mqtt_thread= mqtt_thread
#订阅相关主题, 获取参数, 修改参数, 获取测量值, 获取报警信息
mqtt_comm_thread.subscribe("request/param/info/#")
mqtt_comm_thread.subscribe("request/param/modify/#")
mqtt_comm_thread.subscribe("request/measure/#")
mqtt_comm_thread.subscribe("request/status/#")
mqtt_comm_thread.subscribe("request/alarm/#")
mqtt_comm_thread.subscribe("request/action/#")
mqtt_comm_thread.subscribe("request/alias/#")
def alias_table_convert(self) :
new_list_dict = []
for each_dict in self.alias_table :
for key_info, value_dict in each_dict.items() :
if isinstance(key_info, Enum) :
name = key_info.name
else :
name = key_info
new_dict = {}
for dict_key, dict_value in value_dict.items() :
if isinstance(dict_key, Enum) :
dict_key_value = dict_key.value[0]
else :
dict_key_value = dict_key
new_dict[dict_key_value] = dict_value
new_list_dict.append({name : new_dict})
return new_list_dict
#该函数在线程里面调用, 不会阻塞mqtt处理订阅的消息
def on_process_topic_message(self, topic, message) :
try :
if isinstance(message, bytes) :
json_dict = json.loads(message.decode('utf-8'))
else :
json_dict = json.loads(message.encode('utf-8'))
print_normal_msg(f"有效的mqtt(topic = {topic}, message = {message})")
except Exception as e:
print_error_msg(f"{str(e)}无效的mqtt(topic = {topic}, message = {message})")
json_dict = None
mqtt_info_name = utils.dict_or_object_get_attr(json_dict, "name", None)
value_str = utils.dict_or_object_get_attr(json_dict, "value", math.nan)
# if mqtt_info_name != None :
# mqtt_menu_item = self.mqtt_info_object.search_menu_item(mqtt_info_name)
# else :
# mqtt_menu_item = None
if mqtt_info_name != None:
mqtt_menu_item = self.mqtt_info_object.search_menu_item(mqtt_info_name)
else :
mqtt_menu_item = None
print_normal_msg(f"执行操作: topic={topic}, mqtt_info_name={mqtt_info_name}")
if "request/alias" in topic : #获取别名
new_alias_table = self.alias_table_convert()
if mqtt_info_name == None :
msg : str = json.dumps(new_alias_table, ensure_ascii=False)
if self.mqtt_thread != None :
self.mqtt_thread.publish("response/alias/" + self.unique_name, msg)
else :
search_dict = None
for each_dict in new_alias_table :
if mqtt_info_name in each_dict.keys() :
search_dict = each_dict
break
if search_dict :
msg : str = json.dumps(search_dict, ensure_ascii=False)
else :
msg : str = '{"%s" : None}'%(mqtt_info_name)
if self.mqtt_thread != None :
self.mqtt_thread.publish("response/alias/" + self.unique_name, msg)
elif "request/alarm" in topic: #故障查询
if self.request_alarm_func != None:
fvalue = utils.dict_or_object_get_attr(json_dict, "index", math.nan)
if isinstance(fvalue, str) :
fvalue = float(fvalue)
if fvalue != math.nan :
alarm_index = round(fvalue)
self.request_alarm_func(self, alarm_index)
elif "request/action" in topic :
if self.action_process_func :
self.action_process_func(self, mqtt_menu_item, value_str)
elif "request/param/info" in topic: #读取参数
_scale = utils.dict_or_object_get_attr(mqtt_menu_item, "scale", 1.0)
_offset = utils.dict_or_object_get_attr(mqtt_menu_item, "offset", 0.0)
_comm_str = utils.dict_or_object_get_attr(mqtt_menu_item, "addr", None)
_alias_name = utils.dict_or_object_get_attr(mqtt_menu_item, "alias", None)
if isinstance(_alias_name, Enum):
_alias_name = _alias_name.name
_format = utils.dict_or_object_get_attr(mqtt_menu_item, "format", "%f")
_fvalue = math.nan
if _comm_str :
_fvalue = self.protocol.read_float(device_addr = self.comm_addr,
comm_str = _comm_str,
scale = _scale,
offset = _offset
)
# if _alias_name != None :
# # if _fvalue == None or _fvalue == math.nan:
# # _format_str = "NAN"
# if _fvalue is None or math.isnan(_fvalue):
# _fvalue = 0
# else :
# _format_str = "%d"%(round(_fvalue))
# if self.mqtt_thread != None :
# self.mqtt_thread.publish("response/param/info/" + self.unique_name, '{"%s" : {"alias" : "%s", "value": "%s"}}'%(mqtt_info_name, _alias_name, _format_str))
# else :
# _format_str = _format%(_fvalue)
# if self.mqtt_thread != None :
# self.mqtt_thread.publish("response/param/info/" + self.unique_name, '{"%s" : "%s"}'%(mqtt_info_name, _format_str))
# else:
# print_warning_msg(f"未处理的请求:{topic, json_dict}")
if _alias_name is not None:
# 处理 _fvalue 的情况
if _fvalue is None or math.isnan(_fvalue):
_fvalue = 0
_format_str = "%d" % (round(_fvalue))
else:
# 当 _alias_name 为 None 时处理
_format_str = _format % (_fvalue) if _fvalue is not None and not math.isnan(_fvalue) else "UNKNOWN"
# 发布消息
if self.mqtt_thread is not None:
if _alias_name is not None:
self.mqtt_thread.publish("response/param/info/" + self.unique_name,
'{"%s" : {"alias" : "%s", "value": "%s"}}' % (mqtt_info_name, _alias_name, _format_str))
else:
self.mqtt_thread.publish("response/param/info/" + self.unique_name,
'{"%s" : "%s"}' % (mqtt_info_name, _format_str))
else:
print_warning_msg(f"未处理的请求:{topic, message}")
elif "request/param/modify" in topic : #写入参数
mqtt_menu_item = self.comm_item_item_adjust(mqtt_menu_item)
scale = utils.dict_or_object_get_attr(mqtt_menu_item, "scale", 1.0)
format_str = utils.dict_or_object_get_attr(mqtt_menu_item, "format", "%1.0f")
offset = utils.dict_or_object_get_attr(mqtt_menu_item, "offset", 0.0)
_comm_str = utils.dict_or_object_get_attr(mqtt_menu_item, "addr", None)
_fvalue = value_str
if isinstance(_fvalue, str) :
modify_fvalue = float(_fvalue)
else :
modify_fvalue = _fvalue
_fvalue_origin = modify_fvalue / scale - offset
if _comm_str :
result = self.protocol.write_float(device_addr = self.comm_addr,
comm_str = _comm_str,
fvalue = _fvalue_origin)
if self.mqtt_thread != None :
self.mqtt_thread.publish("response/param/modify/" + self.unique_name, '{"name" : "%s", "result":%d}'%(mqtt_info_name, result))
else:
print_warning_msg(f"未处理的请求:{topic, json_dict}")
elif mqtt_menu_item == None :
print_warning_msg(f"mqtt无法找到对应信息项(topic = {topic}, message = {json_dict})")
else :
pass
#@override, mqtt subscirbe message process
def on_message(self, mqtt_thread, topic, message) :
if self.mqtt_info_object == None :
return False
if "request/alias" in topic : #获得别名不需要协议通讯, 此处直接处理即可
self.on_process_topic_message(topic, message)
elif "request" in topic :
new_thread : class_mqtt_process_thread = class_mqtt_process_thread(self, topic, message)
new_thread.start()
return True
#通过通讯字符串与scale类型, 获取浮点格式实际值, 通讯失败时返回None
def comm_item_get_value_float(self, comm_addr_str, scale = 1.0, offset = 0) :
reg_value = None
if comm_addr_str != None:
reg_addr, bit, reg_count = utils.comm_str_unpack(comm_addr_str)
is_float = True if "#f" in comm_addr_str else False
is_big_endian = True if "#>" in comm_addr_str else False
is_sign = True if "#s" in comm_addr_str else False
if reg_count == 1 :
if is_sign :
reg_value = self.read_register_s16(reg_addr)
else :
reg_value = self.read_register_u16(reg_addr)
if reg_count == 2 :
if is_float :
reg_value = self.read_register_f32(reg_addr, is_big_endian)
elif is_sign :
reg_value = self.read_register_s32(reg_addr, is_big_endian)
else :
reg_value = self.read_register_u32(reg_addr, is_big_endian)
if bit >= 0 and reg_value != None:
reg_value = (reg_value >> bit)
reg_value = reg_value & (0xFFFFFFFF >> (32 - reg_count))
if reg_value != None :
reg_value = reg_value * scale + offset
return reg_value
#有些菜单项的scale, format或其他属性可以动态调节, 返回调整后的菜单项或 原菜单项
def comm_item_item_adjust(self, menu_item) :
adjust_menu_item = None
func_item_adjust = utils.dict_or_object_get_attr(menu_item, "adjust", None)
if func_item_adjust != None :
adjust_menu_item = func_item_adjust(self, menu_item)
if adjust_menu_item == None :
adjust_menu_item = menu_item
return adjust_menu_item
#通过菜单项中 特定的回调函数, 使每个菜单项可以独立处理一些任务, 比如添加自定义key, value
def comm_call_menu_item_func(self, menu_item_dict, mqtt_dict : dict = None) :
call_func = utils.dict_or_object_get_attr(menu_item_dict, "call", None)
if call_func != None :
call_func(self, menu_item_dict, mqtt_dict)
#通过菜单项中 获取浮点格式实际值, reg_value在通讯失败时返回None, 需要额外检查
def comm_get_value_from_menu_item(self, menu_item_dict) :
menu_item_dict = self.comm_item_item_adjust(menu_item_dict)
scale = utils.dict_or_object_get_attr(menu_item_dict, "scale", 1.0)
offset = utils.dict_or_object_get_attr(menu_item_dict, "offset", 0.0)
comm_addr_str = utils.dict_or_object_get_attr(menu_item_dict, "addr", None)
reg_value = self.comm_item_get_value_float(comm_addr_str, scale, offset)
return reg_value
#通过mqtt名称中 获取浮点格式实际值, reg_value在通讯失败时返回None, 需要额外检查
def comm_get_value_from_mqtt_name(self, mqtt_name : str) :
if mqtt_name in self.mqtt_info_object.mqtt_dict.keys() :
mqtt_menu_item = self.mqtt_info_object.mqtt_dict[mqtt_name]
return self.comm_get_value_from_menu_item(mqtt_menu_item)
return None
#触发一组mqtt菜单组的 key, value字典
def comm_item_trigger_mqtt_pack(self, mqtt_pack) :
if mqtt_pack == None :
return None
mqtt_dict = {}
for pack_item_dict in mqtt_pack :
self.comm_call_menu_item_func(pack_item_dict, mqtt_dict)
reg_value = self.comm_get_value_from_menu_item(pack_item_dict)
format_str = utils.dict_or_object_get_attr(pack_item_dict, "format", "%1.0f")
mqtt_name = utils.dict_or_object_get_attr(pack_item_dict, "mqtt", None)
min_value = utils.dict_or_object_get_attr(pack_item_dict, "min", None)
max_value = utils.dict_or_object_get_attr(pack_item_dict, "max", None)
# 检查是否有最小值和最大值的约束,并验证 reg_value 是否在范围内
if reg_value is not None:
if min_value is not None and reg_value < min_value:
reg_value = min_value # 如果小于最小值,设为最小值
if max_value is not None and reg_value > max_value:
reg_value = max_value # 如果大于最大值,设为最大值
if mqtt_name != None and reg_value != None:
mqtt_dict[mqtt_name] = format_str%(reg_value)
return mqtt_dict
def trigger_comm(self, name):
for item in self.comm_table_item_list:
comm_table_item : class_comm_table_item = item
if comm_table_item.name == name :
comm_table_item.comm_trigger = True
return
def read_register_count(self, reg_addr, reg_count) :
result = None
for item in self.comm_table_item_list :
comm_table_item : class_comm_table_item = item
if comm_table_item.in_range(reg_addr, reg_count) :
if comm_table_item.reg_buf == None :
comm_table_item.comm_trigger = True
elif len(comm_table_item.reg_buf) == 0 :
comm_table_item.comm_trigger = True
else :
result = comm_table_item.read_register_count(reg_addr, reg_count)
if result != None :
break
return result
#@device_comm_flush_request override
def device_comm_flush_request(self, reg_addr, reg_count, cycle = 3000) :
for item in self.comm_table_item_list :
comm_table_item : class_comm_table_item = item
if comm_table_item.in_range(reg_addr, reg_count) :
if comm_table_item.flush_request_delay == 0 :
comm_table_item.flush_request_delay = cycle
#@read_register override
def read_register(self, comm_str) :
reg_addr, bit, reg_count = utils.comm_str_unpack(comm_str)
if reg_count == 0:
return None
return self.read_register_count(reg_addr, reg_count)
#@read_register override
#bool write_register(int reg_addr, reg_count, uint16_t value[])
def write_register(self, reg_addr, reg_count, new_value, timeout_ms = comm_device.DEFAULT_COMM_WRITE_TIMEOUT_MS) :
try:
_protocol : class_protocol_modbus = self.protocol
_old_timeout = _protocol.get_timeout()
_protocol.set_timeout(timeout_ms / BASE_FAIL_DELAY)
write_result = _protocol.modbus_write_regs(self.comm_addr,
reg_addr,
reg_count,
new_value,
)
if write_result == True:
for item in self.comm_table_item_list :
comm_item : class_comm_table_item = item
if comm_item.in_range(reg_addr, reg_count) :
comm_item.update_item_value(reg_addr, reg_count, new_value)
except Exception :
write_result = False
finally :
_protocol.set_timeout(_old_timeout)
return write_result
#bool write_bit_register(int reg_addr, uint16_t value[])
#bool write_bit_register(int reg_addr, uint16_t value)
def write_bit_register(self, reg_addr, value, timeout_ms = comm_device.DEFAULT_COMM_WRITE_TIMEOUT_MS) :
write_result = False
_protocol : class_protocol_modbus = self.protocol
try :
old_timeout = _protocol.get_timeout()
_protocol.set_timeout(timeout_ms / BASE_FAIL_DELAY)
_protocol.modbus_write_regs(self.comm_addr,
reg_addr % 100000 + 100000,
len(value),
value)
write_result = True
except Exception as e:
write_result = False
print_error_msg(f"modbus寄存器无法写入{str(e)}")
finally :
_protocol.set_timeout(old_timeout)
return write_result
#@override cycle function
def update_time_difference(self, table_item):
cur_time = time.time() # 获取当前时间
time_dif = cur_time - table_item.base_time # 计算时间差
table_item.base_time = cur_time # 更新基准时间
return time_dif * BASE_FAIL_DELAY # 返回时间差(毫秒)
def should_trigger_comm(self, table_item, time_dif_ms):
comm_trigger = False # 初始化通信触发标志为False
if self.func_comm_trigger:
comm_trigger = self.func_comm_trigger(self, table_item) # 调用通信触发函数
if table_item.remain_cycle > time_dif_ms:
table_item.remain_cycle -= time_dif_ms # 减少剩余周期
else:
table_item.remain_cycle = table_item.cycle + table_item.comm_fail_delay + self.comm_fail_delay # 重新计算剩余周期
if table_item.cycle > 0 or (table_item.cycle == 0 and not table_item.comm_success):
comm_trigger = True # 如果周期大于0或周期为0但上次通信不成功则触发通信
if table_item.flush_request_delay > 0:
if table_item.flush_request_delay > time_dif_ms:
table_item.flush_request_delay -= time_dif_ms # 减少刷新请求延迟
else:
table_item.flush_request_delay = 0 # 重置刷新请求延迟
comm_trigger = True # 触发通信
if not comm_trigger:
comm_trigger = table_item.comm_trigger # 如果前面没有触发通信,则使用通信触发标志
return comm_trigger # 返回是否触发通信
def execute_communication(self, table_item):
read_result = [] # 初始化读取结果
timeout_ms = getattr(table_item, "通信超时", DEFAULT_TIMEOUT) # 获取超时时间默认500ms
_protocol = self.protocol # 获取协议对象
try:
old_timeout = _protocol.get_timeout() # 保存旧的超时时间
_protocol.set_timeout(timeout_ms / BASE_FAIL_DELAY) # 设置新的超时时间
read_result = _protocol.modbus_read_regs(self.comm_addr, table_item.reg_addr, table_item.reg_count) # 执行Modbus读取
if len(read_result) != table_item.reg_count:
read_result = [] # 如果读取结果数量不匹配,视为读取失败
except Exception as e:
print_error_msg("周期读异常: ", e, f"modbus_read_regs(addr={self.comm_addr}, reg={table_item.reg_addr}, count={table_item.reg_count})") # 打印错误信息
finally:
_protocol.set_timeout(old_timeout) # 恢复旧的超时时间
return read_result # 返回读取结果
def handle_comm_result(self, table_item, read_result):
if not read_result: # 如果读取结果为空,表示通信失败
self.handle_comm_failure(table_item)
else: # 否则通信成功
self.handle_comm_success(table_item, read_result)
table_item.comm_trigger = False # 重置通信触发标志
def handle_comm_failure(self, table_item):
table_item.comm_fail_count += 1 # 增加通信失败计数
table_item.comm_fail_delay = self.limit_delay(table_item.comm_fail_delay + BASE_FAIL_DELAY, MAX_FAIL_DELAY) # 增加并限制通信失败延迟
self.comm_fail_delay = self.limit_delay(self.comm_fail_delay + BASE_GLOBAL_FAIL_DELAY, 60000) # 增加并限制全局通信失败延迟
table_item.comm_success = False # 标记通信失败
def limit_delay(self, delay, max_delay):
"""限制延迟不超过最大值"""
return min(delay, max_delay)
def handle_comm_success(self, table_item, read_result):
table_item.comm_fail_delay = 0 # 重置通信失败延迟
self.comm_fail_delay = 0 # 重置全局通信失败延迟
table_item.reg_buf = read_result # 更新寄存器缓存
table_item.comm_success = True # 标记通信成功
table_item.comm_success_count += 1 # 增加成功计数
if table_item.mqtt_pack:
self.publish_mqtt_message(table_item) # 发布MQTT消息
def publish_mqtt_message(self, table_item):
json_topic = f"{table_item.name}/{self.unique_name}" # 构建MQTT主题
msg_dict = self.comm_item_trigger_mqtt_pack(table_item.mqtt_pack) # 触发MQTT打包
if msg_dict:
json_message = json.dumps(msg_dict, ensure_ascii=False) # 序列化消息字典
if self.mqtt_thread:
self.mqtt_thread.publish(json_topic, json_message) # 发布MQTT消息
def device_comm_cycle(self):
comm_success_count = 0 # 初始化成功计数
total_comm_count = 0 # 初始化总计数
if self.comm_table is None:
return comm_success_count, total_comm_count # 如果通信表为空,提前返回
for item in self.comm_table_item_list:
table_item = item # 获取表项
if table_item.reg_count == 0:
continue # 如果寄存器计数为0跳过此表项
time_dif_ms = self.update_time_difference(table_item) # 更新时间差
comm_trigger = self.should_trigger_comm(table_item, time_dif_ms) # 检查是否应触发通信
if comm_trigger:
total_comm_count += 1 # 增加总通信计数
read_result = self.execute_communication(table_item) # 执行通信
if read_result:
comm_success_count += 1 # 如果读取成功,增加成功计数
self.handle_comm_result(table_item, read_result) # 处理通信结果
return comm_success_count, total_comm_count # 返回成功计数和总计数