修复DB100ReaderThread线程和write_genetic操作PLC线程打架。原因是write_genetic没有加线程锁

This commit is contained in:
您çšpengqi
2025-09-26 20:23:03 +08:00
parent 485bbcc3f0
commit 144def0e7d

View File

@ -251,90 +251,6 @@ class Snap7Client:
self.connected = False
return False
# def read_generic(self, db_number, offset, data_type, count=1):
# """
# 通用读取接口,支持多种数据类型
# Args:
# db_number: DB块编号
# offset: 起始偏移量字节或位对于bool类型
# data_type: 数据类型 ('bool', 'byte', 'int', 'word', 'real', 'dint', 'dword')
# count: 要读取的数据个数
# Returns:
# 解析后的数据单个值或值列表失败返回None
# """
# if not self.connected and not self.connect():
# self.logger.warning(f"Read failed: not connected to {self.ip}")
# return None
#
# try:
# if data_type == 'bool':
# # 对于booloffset是位偏移
# byte_offset = offset // 8
# bit_offset = offset % 8
# # 计算需要读取的字节数
# last_bit = bit_offset + count - 1
# last_byte = last_bit // 8
# total_bytes = last_byte - byte_offset + 1
#
# # 读取原始字节数据
# data = self.read_db(db_number, byte_offset, total_bytes)
# if data is None:
# return None
#
# # 解析bool值
# result = []
# for i in range(count):
# current_bit = bit_offset + i
# byte_idx = current_bit // 8
# bit_idx = current_bit % 8
# result.append(bool(data[byte_idx] & (1 << bit_idx)))
#
# return result[0] if count == 1 else result
#
# elif data_type == 'byte':
# data = self.read_db(db_number, offset, count)
# if data is None:
# return None
# return [data[i] for i in range(count)] if count > 1 else data[0]
#
# elif data_type in ['int', 'word']:
# total_bytes = 2 * count
# data = self.read_db(db_number, offset, total_bytes)
# if data is None:
# return None
#
# result = []
# for i in range(count):
# if data_type == 'int':
# result.append(get_int(data, i * 2))
# else: # word
# result.append(get_word(data, i * 2))
# return result[0] if count == 1 else result
#
# elif data_type in ['dint', 'dword', 'real']:
# total_bytes = 4 * count
# data = self.read_db(db_number, offset, total_bytes)
# if data is None:
# return None
#
# result = []
# for i in range(count):
# if data_type == 'dint':
# result.append(get_dint(data, i * 4))
# elif data_type == 'dword':
# result.append(get_dword(data, i * 4))
# else: # real
# result.append(get_real(data, i * 4))
# return result[0] if count == 1 else result
#
# else:
# self.logger.error(f"Unsupported data type: {data_type}")
# return None
#
# except Exception as e:
# self.logger.error(f"Error reading {data_type} from DB{db_number} offset {offset}: {e}")
# return None
def write_generic(self, db_number, offset, data_type, value):
"""
通用写入接口,支持多种数据类型
@ -351,104 +267,105 @@ class Snap7Client:
return False
try:
if data_type == 'bool':
# 对于booloffset是位偏移
byte_offset = offset // 8
bit_offset = offset % 8
with self.lock:
if data_type == 'bool':
# 对于booloffset是位偏移
byte_offset = offset // 8
bit_offset = offset % 8
# 读取当前字节
current_byte = self.read_db(db_number, byte_offset, 1)
if current_byte is None:
return False
# 读取当前字节
current_byte = self.read_db(db_number, byte_offset, 1)
if current_byte is None:
return False
# 修改特定位
if isinstance(value, list):
# 多个bool值
for i, val in enumerate(value):
current_bit = bit_offset + i
byte_idx = current_bit // 8
bit_idx = current_bit % 8
# 修改特定位
if isinstance(value, list):
# 多个bool值
for i, val in enumerate(value):
current_bit = bit_offset + i
byte_idx = current_bit // 8
bit_idx = current_bit % 8
if val:
current_byte[0] |= (1 << bit_idx)
else:
current_byte[0] &= ~(1 << bit_idx)
else:
# 单个bool值
if value:
current_byte[0] |= (1 << bit_offset)
if val:
current_byte[0] |= (1 << bit_idx)
else:
current_byte[0] &= ~(1 << bit_idx)
else:
current_byte[0] &= ~(1 << bit_offset)
# 单个bool值
if value:
current_byte[0] |= (1 << bit_offset)
else:
current_byte[0] &= ~(1 << bit_offset)
# 写回修改后的字节
return self.write_db_bool(db_number, byte_offset, current_byte)
# 写回修改后的字节
return self.write_db_bool(db_number, byte_offset, current_byte)
elif data_type == 'byte':
if isinstance(value, list):
# 批量写入
for i, val in enumerate(value):
if val < 0 or val > 255:
self.logger.error(f"Byte value out of range: {val}")
elif data_type == 'byte':
if isinstance(value, list):
# 批量写入
for i, val in enumerate(value):
if val < 0 or val > 255:
self.logger.error(f"Byte value out of range: {val}")
return False
if not self.write_db(db_number, offset + i, bytes([val])):
return False
return True
else:
# 单个字节
if value < 0 or value > 255:
self.logger.error(f"Byte value out of range: {value}")
return False
if not self.write_db(db_number, offset + i, bytes([val])):
return self.write_db(db_number, offset, bytes([value]))
elif data_type in ['int', 'word']:
if not isinstance(value, list):
value = [value]
for i, val in enumerate(value):
# 确保int值在范围内
if data_type == 'int' and (val < -32768 or val > 32767):
self.logger.error(f"Int value out of range: {val}")
return False
elif data_type == 'word' and (val < 0 or val > 65535):
self.logger.error(f"Word value out of range: {val}")
return False
data = bytearray(2)
if data_type == 'int':
set_int(data, 0, val)
else:
set_word(data, 0, val)
if not self.write_db(db_number, offset + i * 2, data):
return False
return True
elif data_type in ['dint', 'dword', 'real']:
if not isinstance(value, list):
value = [value]
for i, val in enumerate(value):
data = bytearray(4)
if data_type == 'dint':
if val < -2147483648 or val > 2147483647:
self.logger.error(f"DInt value out of range: {val}")
return False
set_dint(data, 0, val)
elif data_type == 'dword':
if val < 0 or val > 4294967295:
self.logger.error(f"DWord value out of range: {val}")
return False
set_dword(data, 0, val)
else: # real
set_real(data, 0, float(val))
if not self.write_db(db_number, offset + i * 4, data):
return False
return True
else:
# 单个字节
if value < 0 or value > 255:
self.logger.error(f"Byte value out of range: {value}")
return False
return self.write_db(db_number, offset, bytes([value]))
elif data_type in ['int', 'word']:
if not isinstance(value, list):
value = [value]
for i, val in enumerate(value):
# 确保int值在范围内
if data_type == 'int' and (val < -32768 or val > 32767):
self.logger.error(f"Int value out of range: {val}")
return False
elif data_type == 'word' and (val < 0 or val > 65535):
self.logger.error(f"Word value out of range: {val}")
return False
data = bytearray(2)
if data_type == 'int':
set_int(data, 0, val)
else:
set_word(data, 0, val)
if not self.write_db(db_number, offset + i * 2, data):
return False
return True
elif data_type in ['dint', 'dword', 'real']:
if not isinstance(value, list):
value = [value]
for i, val in enumerate(value):
data = bytearray(4)
if data_type == 'dint':
if val < -2147483648 or val > 2147483647:
self.logger.error(f"DInt value out of range: {val}")
return False
set_dint(data, 0, val)
elif data_type == 'dword':
if val < 0 or val > 4294967295:
self.logger.error(f"DWord value out of range: {val}")
return False
set_dword(data, 0, val)
else: # real
set_real(data, 0, float(val))
if not self.write_db(db_number, offset + i * 4, data):
return False
return True
else:
self.logger.error(f"Unsupported data type: {data_type}")
return False
self.logger.error(f"Unsupported data type: {data_type}")
return False
except Exception as e:
self.logger.error(f"Error writing {data_type} to DB{db_number} offset {offset}: {e}")
@ -544,7 +461,6 @@ class Snap7Client:
if db_number == 100:
print(f"从缓存文件中读取{db_number}的数据")
db100_raw = self.read_db100_from_file()
if db100_raw is not None:
try:
if data_type == 'bool':
@ -658,6 +574,7 @@ class Snap7Client:
return [data[i] for i in range(count)] if count > 1 else data[0]
elif data_type in ['int', 'word']:
total_bytes = 2 * count
data = self.read_db(db_number, offset, total_bytes)
if data is None:
@ -687,7 +604,6 @@ class Snap7Client:
result.append(get_real(data, i * 4))
return result[0] if count == 1 else result
else:
self.logger.error(f"Unsupported data type: {data_type}")
return None