0624更新

main
zcwBit 4 months ago
parent 8413662da9
commit 8d6bc61d44

@ -7,7 +7,7 @@ from collections import deque
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
class Box1Communicator: class TCPCommunicator:
START_FLAG = b'\xF3\x12' START_FLAG = b'\xF3\x12'
END_FLAG = b'\xF3\x14' END_FLAG = b'\xF3\x14'
HEADER_SIZE = 10 HEADER_SIZE = 10
@ -262,7 +262,7 @@ class Box1Communicator:
# AO响应处理 # AO响应处理
elif dataType == self.RESP_WRITE_AO: elif dataType == self.RESP_WRITE_AO:
print(len(body)) # print(len(body))
success = struct.unpack('<d', body)[0] == 0.0 if len(body)==8 else False success = struct.unpack('<d', body)[0] == 0.0 if len(body)==8 else False
result = success result = success
if self.aoCallback: if self.aoCallback:
@ -391,12 +391,40 @@ def write_worker(communicator, interval):
while TestState.running: while TestState.running:
try: try:
# 随机修改一些AO值 # 修改生成16个随机的DO状态0或1
#for i in range(5): do_states = [random.randint(0, 1) for _ in range(16)]
ao_data = [0.004,0.005,0.006,0.007,0.008,0.009,0.010,0.011,0.012,0.013,0.014,0.015,0.016,0.017,0.018,0.019,0,1,100,255,1,2,3,4,5,6,7,8,100,200,300,400,500,600,700,800] # 将16个DO状态转换为16位整数
do_value = 0
for i, state in enumerate(do_states):
do_value |= (state << i)
# 构建AO数据数组包含16个DO状态
ao_data = [
# 0-15: 16通道AO电流数据A
0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.010, 0.011,
0.012, 0.013, 0.014, 0.015, 0.016, 0.017, 0.018, 0.019,
# 16: 输出模式0无输出/1正常输出/2触发输出
1, # 正常输出
# 17: 触发类型0:无输出 1fpga触发/2TC触发/3RTD触发
2, # TC触发
100, # 实验时间ms
# 18: 实验时间ms和 DO状态U16转双精度
float(do_value), # 将16位整数转换为双精度浮点数
# 19: DO状态已包含在上面的do_value中
# 20-27: 8通道TC数据mV
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
# 28-35: 8通道RTD数据Ω
100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0
]
# 写入AO数据 # 写入AO数据
print(ao_data) print(len(ao_data), ao_data)
communicator.writeAo(ao_data) communicator.writeAo(ao_data)
# 等待指定间隔 # 等待指定间隔
@ -409,7 +437,8 @@ def write_worker(communicator, interval):
def main(): def main():
# 创建通信器实例 # 创建通信器实例
communicator = Box1Communicator("192.168.1.50", 5055) # communicator = TCPCommunicator("192.168.1.50", 5055)
communicator = TCPCommunicator("127.0.0.1", 8000)

@ -0,0 +1,174 @@
import logging
import time
import threading
from IOTCPClinet import TCPCommunicator
FPGATrigger = 1
TCTrigger = 2
RTDTrigger = 3
class TCPVarManager:
def __init__(self, host, port):
"""
初始化TCP变量管理器
:param host: 服务器主机地址
:param port: 服务器端口
"""
self.communicator = TCPCommunicator(host, port)
logging.info(f"TCPVarManager initialized for {host}:{port}")
self.AODATA = [0.0] * 16
self.DODATA = [0] * 16
self.TCDATA = [0.0] * 8
self.RTDDATA = [0.0] * 8
self.AIDATA = [0.0] * 8
self.DIDATA = [0] * 16
self.DELTATDATA = [0] * 16
self.startPeriodicRead()
def startTimeTest(self, triggerType, time = 2000):
data = [
# 0-15: 16通道AO电流数据A
*self.AODATA,
# 16: 输出模式0无输出/1正常输出/2触发输出
2, # 触发输出
# 17: 触发类型0:无触发 1fpga触发/2TC触发/3RTD触发
triggerType, # TC触发
time, # 实验时间ms
# 18: 实验时间ms和 DO状态U16转双精度
0, # 将16位整数转换为双精度浮点数
# 19: DO状态已包含在上面的do_value中
# 20-27: 8通道TC数据mV
*self.TCDATA,
# 28-35: 8通道RTD数据Ω
*self.RTDDATA
]
self.writeAoDo(data, self.DODATA)
# print(1)
def readAiDi(self):
"""
读取AI和DI数据
:return: 包含(AI值, DI状态)的元组或发生错误时返回None
"""
try:
result = self.communicator.readAIDI()
# print(result)
if result is None:
logging.warning("Failed to read AI/DI data")
return result
except Exception as e:
logging.error(f"Error reading AI/DI: {e}")
return None
# 新增周期性读取方法
def startPeriodicRead(self, interval=0.5, callback=None):
"""
启动周期性读取AI/DI数据
:param interval: 读取间隔()默认500ms
:param callback: 数据回调函数
"""
self.stop_event = threading.Event()
self.readThread = threading.Thread(
target=self._read_worker,
args=(interval, callback),
daemon=True
)
self.readThread.start()
logging.info(f"Started periodic read every {interval*1000}ms")
def _read_worker(self, interval, callback):
"""工作线程实现周期性读取"""
while not self.stop_event.is_set():
try:
result = self.readAiDi()
self.AIDATA = result[0]
self.DIDATA = result[1]
# print(self.AIDATA, self.DIDATA)
if callback and result:
callback(result[0], result[1])
time.sleep(interval)
except Exception as e:
logging.error(f"Periodic read error: {e}")
time.sleep(1)
def stopPeriodicRead(self):
"""停止周期性读取"""
if hasattr(self, 'stop_event'):
self.stop_event.set()
logging.info("Stopped periodic read")
def writeAoDo(self, aoData, do_states):
"""
写入AO和DO数据
:param aoData: 36个AO值的列表
:param do_states: 16个DO状态的列表 (0或1)
:return: 写入成功返回True否则返回False
"""
if len(aoData) != 36:
logging.error("AO data must contain exactly 36 values")
return False
if len(do_states) != 16:
logging.error("DO states must contain exactly 16 values")
return False
try:
# 将DO状态转换为单个浮点数协议要求
do_value = 0
for i, state in enumerate(do_states):
do_value |= (state << i)
# 替换aoData中第20个元素为DO状态值
aoData[19] = float(do_value)
success = self.communicator.writeAo(aoData)
if not success:
logging.warning("AO/DO write operation failed")
return success
except Exception as e:
logging.error(f"Error writing AO/DO: {e}")
return False
def readDeltaT(self):
"""
读取DeltaT数据
:return: 16个DeltaT值的元组或发生错误时返回None
"""
try:
result = self.communicator.readDeltaT()
if result is None:
logging.warning("Failed to read DeltaT data")
return result
except Exception as e:
logging.error(f"Error reading DeltaT: {e}")
return None
def shutdown(self):
"""关闭连接并清理资源"""
try:
self.stopPeriodicRead()
self.communicator.shutdown()
logging.info("TCPVarManager shutdown complete")
except Exception as e:
logging.error(f"Error during shutdown: {e}")
if __name__ == "__main__":
TCPVarManager = TCPVarManager("127.0.0.1", 8000)
TCPVarManager.startTimeTest(TCTrigger)
try:
# 运行模拟器直到手动停止
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\nStopping simulator...")
TCPVarManager.shutdown()
# TCPVarManager.shutdown()

@ -140,7 +140,8 @@ class Box1Simulator:
logging.error(f"Invalid AO data length: {len(body)}") logging.error(f"Invalid AO data length: {len(body)}")
return None return None
ao_data = struct.unpack('>' + 'd'*36, body) # 修改:使用小端字节序解包数据
ao_data = struct.unpack('<' + 'd'*36, body)
self.ao_values = list(ao_data) self.ao_values = list(ao_data)
logging.info(f"接收到的AO: {ao_data}... (total {len(ao_data)} values)") logging.info(f"接收到的AO: {ao_data}... (total {len(ao_data)} values)")
return self.create_ao_response(True, packet_num) return self.create_ao_response(True, packet_num)
@ -172,32 +173,45 @@ class Box1Simulator:
for i in range(4): for i in range(4):
if random.random() < 0.2: # 20%几率翻转 if random.random() < 0.2: # 20%几率翻转
self.di_states[i] = 1 - self.di_states[i] self.di_states[i] = 1 - self.di_states[i]
# print(self.di_states, 1111)
# 打包AI数据 (8 doubles) # 修改生成500组AI/DI数据
ai_bytes = struct.pack('>' + 'd'*8, *self.ai_values) full_body = b''
for _ in range(500):
# 修改使用小端字节序打包8个AI值
ai_bytes = struct.pack('<' + 'd'*8, *self.ai_values)
# 打包DI状态为一个64位整数 # 打包DI状态为一个64位整数
di_state_int = 0 di_state_int = 0
for i, state in enumerate(self.di_states): for i, state in enumerate(self.di_states):
di_state_int |= (state << i) di_state_int |= (state << i)
di_bytes = struct.pack('>Q', di_state_int)
body = ai_bytes + di_bytes di_bytes = struct.pack('<Q', di_state_int)
print("发送的AI为", self.ai_values, self.di_states)
return self.create_packet(self.RESP_READ_AI, body, packet_num)
# 添加一组数据到响应体
full_body += ai_bytes + di_bytes
# 使用logging记录发送的AI数据
logging.info(f"发送的AI为: AI={self.ai_values}, DI={self.di_states} (共500组)")
return self.create_packet(self.RESP_READ_AI, full_body, packet_num)
def create_ao_response(self, success, packet_num): def create_ao_response(self, success, packet_num):
"""创建AO写入响应数据包""" """创建AO写入响应数据包"""
# 使用0.0表示成功1.0表示失败 # 使用0.0表示成功1.0表示失败
result = 0.0 if success else 1.0 result = 0.0 if success else 1.0
body = struct.pack('>d', result) # 修改:使用小端字节序
body = struct.pack('<d', result)
return self.create_packet(self.RESP_WRITE_AO, body, packet_num) return self.create_packet(self.RESP_WRITE_AO, body, packet_num)
def create_deltat_response(self, packet_num): def create_deltat_response(self, packet_num):
"""创建DeltaT响应数据包""" """创建DeltaT响应数据包"""
# 打包16个64位无符号整数 # 修改使用小端字节序打包16个64位无符号整数
body = struct.pack('>' + 'd'*16, *self.deltat_values) body = struct.pack('<' + '16Q', *self.deltat_values)
# 使用logging记录发送的DeltaT数据
logging.info(f"发送的DeltaT为: {self.deltat_values}")
return self.create_packet(self.RESP_READ_DELTAT, body, packet_num) return self.create_packet(self.RESP_READ_DELTAT, body, packet_num)
def create_packet(self, cmd_type, body, packet_num): def create_packet(self, cmd_type, body, packet_num):

Loading…
Cancel
Save