|
|
|
@ -39,6 +39,8 @@ class Box1Communicator:
|
|
|
|
|
# 响应等待机制
|
|
|
|
|
self.pending_responses = {}
|
|
|
|
|
self.response_lock = threading.Lock()
|
|
|
|
|
# 新增就绪状态标志
|
|
|
|
|
self.isReady = False # 服务器是否完全就绪
|
|
|
|
|
self.connect()
|
|
|
|
|
|
|
|
|
|
# 启动连接和接收线程
|
|
|
|
@ -54,17 +56,23 @@ class Box1Communicator:
|
|
|
|
|
while not self.stopEvent.is_set():
|
|
|
|
|
if not self.connected:
|
|
|
|
|
self.connect()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
# 重连后执行就绪检查
|
|
|
|
|
if self.connected:
|
|
|
|
|
self.checkServerReady() # 新增:检查服务器就绪状态
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
|
|
|
|
|
def connect(self):
|
|
|
|
|
try:
|
|
|
|
|
if self.sock:
|
|
|
|
|
self.sock.close()
|
|
|
|
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
|
self.sock.bind((self.host, 6323))
|
|
|
|
|
self.sock.connect((self.host, self.port))
|
|
|
|
|
self.connected = True
|
|
|
|
|
self.packetCounter = 0
|
|
|
|
|
self.isReady = False # 重置就绪状态
|
|
|
|
|
|
|
|
|
|
# 连接后执行就绪检
|
|
|
|
|
|
|
|
|
|
logging.info(f"Connected to {self.host}:{self.port}")
|
|
|
|
|
return True
|
|
|
|
|
except Exception as e:
|
|
|
|
@ -73,10 +81,16 @@ class Box1Communicator:
|
|
|
|
|
time.sleep(self.reconnectInterval)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def sendCommand(self, cmdType, data=None):
|
|
|
|
|
if not self.connected:
|
|
|
|
|
|
|
|
|
|
def sendCommand(self, cmdType, data=None, skipReadyCheck=False):
|
|
|
|
|
# 增加就绪状态检查
|
|
|
|
|
|
|
|
|
|
# 增加连接状态检查,确保完全连接后再发送
|
|
|
|
|
if not self.connected or not self.sock:
|
|
|
|
|
print("Not connected")
|
|
|
|
|
if not self.connect():
|
|
|
|
|
return None # 连接失败
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
with self.lock:
|
|
|
|
@ -84,9 +98,9 @@ class Box1Communicator:
|
|
|
|
|
if cmdType == self.CMD_WRITE_AO and data:
|
|
|
|
|
if len(data) != 36:
|
|
|
|
|
raise ValueError("AO data requires 36 elements")
|
|
|
|
|
body = struct.pack('>' + 'd'*36, *data)
|
|
|
|
|
body = struct.pack('<' + 'd'*36, *data)
|
|
|
|
|
elif cmdType == self.CMD_READ_AI or cmdType == self.CMD_READ_DELTAT:
|
|
|
|
|
body = struct.pack('>d', 0) # 占位数据
|
|
|
|
|
body = struct.pack('<d', 0) # 占位数据
|
|
|
|
|
|
|
|
|
|
dataSize = len(body)
|
|
|
|
|
current_counter = self.packetCounter
|
|
|
|
@ -143,7 +157,7 @@ class Box1Communicator:
|
|
|
|
|
while not self.stopEvent.is_set():
|
|
|
|
|
try:
|
|
|
|
|
if not self.connected:
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
data = self.sock.recv(4096)
|
|
|
|
@ -195,17 +209,34 @@ class Box1Communicator:
|
|
|
|
|
def processData(self, dataType, body, packetNum):
|
|
|
|
|
try:
|
|
|
|
|
result = None
|
|
|
|
|
|
|
|
|
|
# print(body, dataType)
|
|
|
|
|
# AI响应处理
|
|
|
|
|
if dataType == self.RESP_READ_AI:
|
|
|
|
|
if len(body) != 72:
|
|
|
|
|
# print(body)
|
|
|
|
|
if len(body) != 36000:
|
|
|
|
|
logging.error(f"Invalid AI response length: {len(body)}")
|
|
|
|
|
return
|
|
|
|
|
# print(1)
|
|
|
|
|
aiValues = struct.unpack('>8d', body[:64])
|
|
|
|
|
diBools = [(struct.unpack('>Q', body[64:72])[0] >> i) & 1 for i in range(16)]
|
|
|
|
|
for i in range(500):
|
|
|
|
|
start_idx = i * 72
|
|
|
|
|
end_idx_ai = start_idx + 64
|
|
|
|
|
end_idx_di = start_idx + 72
|
|
|
|
|
|
|
|
|
|
# 解析8个AI值 (64字节)
|
|
|
|
|
ai_chunk = body[start_idx:end_idx_ai]
|
|
|
|
|
aiValues = struct.unpack('<8d', ai_chunk)
|
|
|
|
|
|
|
|
|
|
# 解析16个DI状态 (8字节)
|
|
|
|
|
di_chunk = body[end_idx_ai:end_idx_di]
|
|
|
|
|
di_double = struct.unpack('<d', di_chunk)[0]
|
|
|
|
|
# print(di_double)
|
|
|
|
|
diBools = [(int(di_double) >> j) & 1 for j in range(16)]
|
|
|
|
|
|
|
|
|
|
# all_ai_values.append(ai_values)
|
|
|
|
|
# all_di_states.append(di_bools)
|
|
|
|
|
result = (aiValues, diBools)
|
|
|
|
|
# print(result)
|
|
|
|
|
# print(result)
|
|
|
|
|
if self.aiCallback:
|
|
|
|
|
self.aiCallback(aiValues, diBools, packetNum)
|
|
|
|
|
|
|
|
|
@ -214,15 +245,16 @@ class Box1Communicator:
|
|
|
|
|
if len(body) != 128:
|
|
|
|
|
logging.error(f"Invalid DeltaT response length: {len(body)}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
deltatValues = struct.unpack('>16d', body)
|
|
|
|
|
#(body)
|
|
|
|
|
deltatValues = struct.unpack('<16Q', body)
|
|
|
|
|
result = deltatValues
|
|
|
|
|
if self.deltatCallback:
|
|
|
|
|
self.deltatCallback(deltatValues, packetNum)
|
|
|
|
|
|
|
|
|
|
# AO响应处理
|
|
|
|
|
elif dataType == self.RESP_WRITE_AO:
|
|
|
|
|
success = struct.unpack('>d', body)[0] == 0.0 if len(body)==8 else False
|
|
|
|
|
print(len(body))
|
|
|
|
|
success = struct.unpack('<d', body)[0] == 0.0 if len(body)==8 else False
|
|
|
|
|
result = success
|
|
|
|
|
if self.aoCallback:
|
|
|
|
|
self.aoCallback(success, packetNum)
|
|
|
|
@ -369,7 +401,7 @@ def write_worker(communicator, interval):
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
# 创建通信器实例
|
|
|
|
|
communicator = Box1Communicator("localhost", 8000)
|
|
|
|
|
communicator = Box1Communicator("192.168.1.5", 5055)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -379,43 +411,46 @@ def main():
|
|
|
|
|
deltatCallback=deltat_callback,
|
|
|
|
|
aoCallback=ao_callback
|
|
|
|
|
)
|
|
|
|
|
#for i in range(1000):
|
|
|
|
|
|
|
|
|
|
communicator.readAIDI()
|
|
|
|
|
communicator.readDeltaT()
|
|
|
|
|
communicator.writeAo([1.0] * 36)
|
|
|
|
|
|
|
|
|
|
#communicator.readAIDI()
|
|
|
|
|
#time.sleep(0.5)
|
|
|
|
|
# communicator.readDeltaT()
|
|
|
|
|
#communicator.writeAo([x for x in range(36)])
|
|
|
|
|
|
|
|
|
|
# 单步调试
|
|
|
|
|
|
|
|
|
|
# logging.info("Starting Box1 client test with continuous read/write...")
|
|
|
|
|
|
|
|
|
|
# try:
|
|
|
|
|
try:
|
|
|
|
|
# # 等待初始连接
|
|
|
|
|
# time.sleep(1)
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
# # 启动读取线程 (每200ms读取一次)
|
|
|
|
|
# read_thread = threading.Thread(target=read_worker, args=(communicator, 0.2), daemon=True)
|
|
|
|
|
# read_thread.start()
|
|
|
|
|
read_thread = threading.Thread(target=read_worker, args=(communicator, 0.5), daemon=True)
|
|
|
|
|
read_thread.start()
|
|
|
|
|
|
|
|
|
|
# # 启动写入线程 (每500ms写入一次)
|
|
|
|
|
# write_thread = threading.Thread(target=write_worker, args=(communicator, 0.2), daemon=True)
|
|
|
|
|
# write_thread.start()
|
|
|
|
|
write_thread = threading.Thread(target=write_worker, args=(communicator, 0.5), daemon=True)
|
|
|
|
|
write_thread.start()
|
|
|
|
|
|
|
|
|
|
# # # 启动状态监控线程
|
|
|
|
|
# # monitor_thread = threading.Thread(target=status_monitor, daemon=True)
|
|
|
|
|
# monitor_thread = threading.Thread(target=status_monitor, daemon=True)
|
|
|
|
|
# # monitor_thread.start()
|
|
|
|
|
|
|
|
|
|
# # 主线程等待用户输入退出
|
|
|
|
|
# logging.info("Continuous read/write test running. Press Enter to stop...")
|
|
|
|
|
# input()
|
|
|
|
|
logging.info("Continuous read/write test running. Press Enter to stop...")
|
|
|
|
|
input()
|
|
|
|
|
|
|
|
|
|
# except KeyboardInterrupt:
|
|
|
|
|
# logging.info("Test interrupted by user")
|
|
|
|
|
# finally:
|
|
|
|
|
# # 设置停止标志
|
|
|
|
|
# TestState.running = False
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
logging.info("Test interrupted by user")
|
|
|
|
|
finally:
|
|
|
|
|
# 设置停止标志
|
|
|
|
|
TestState.running = False
|
|
|
|
|
|
|
|
|
|
# # 等待工作线程结束
|
|
|
|
|
# time.sleep(1)
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
# # 清理资源
|
|
|
|
|
communicator.shutdown()
|
|
|
|
|