diff --git a/protocol/TCP/Analog.py b/protocol/TCP/Analog.py deleted file mode 100644 index 73e4091..0000000 --- a/protocol/TCP/Analog.py +++ /dev/null @@ -1,69 +0,0 @@ -import struct -import socket -import time -# commond -# 1、Start -# 2、Stop -# 3、Quit -# 4、Data -def getRealAO(x,highValue, lowValue): - if highValue: - lowValue = float(lowValue) - highValue = float(highValue) - return (16 * (x - lowValue) + 4 * (highValue-lowValue))/(1000 * (highValue - lowValue)) - else: - return x/1000 - -class AnalogDataPacket(object): - def __init__(self, commond: int, PacketSerialNo: int, lis: list): - self.PacketSerialNo = PacketSerialNo - # print(struct.pack('d', struct.pack('B' * 8, *lis[16:]))) - DO = '' - for x in reversed(lis[16:]): - DO += str(int(x)) - # print(DO)s - DO = int(DO, 2) - # print(lis) - valueList = lis[:16] + [DO] - self.value = struct.pack('d' * 17, *valueList) - self.commond = commond - self.buf = [ - 0xF312, self.commond, self.PacketSerialNo, self.value, 0xF314 - ] - # print(self.buf) - def packBytes(self): - packstyle = '>HHL{}sH'.format(str(len(self.value))) - req = struct.pack(packstyle, *self.buf) - return req - - - -class AnalogClient(object): - def __init__(self, url): - # print(url) - host, port = url.split(':') - self._host = host - self._port = int(port) - self.socket = socket.socket() - self.packNo = 0X000001 - - def connect(self): - self.socket.connect((self._host, self._port)) - - def close(self): - self.socket.close() - - def writeData(self, lis: list): - l = [x for x in lis] - for i in range(8): - l[i] = l[i] - pack = AnalogDataPacket(4, self.packNo, l) - self.socket.send(pack.packBytes()) - self.packNo += 1 - res = self.socket.recv(8) - data = struct.unpack('>HLH', res) - # print(data) - return data - - - diff --git a/protocol/TCP/IOTCPClinet.py b/protocol/TCP/IOTCPClinet.py new file mode 100644 index 0000000..2d6c808 --- /dev/null +++ b/protocol/TCP/IOTCPClinet.py @@ -0,0 +1,427 @@ +import socket +import struct +import threading +import time +import logging +from collections import deque + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +class Box1Communicator: + START_FLAG = b'\xF3\x12' + END_FLAG = b'\xF3\x14' + HEADER_SIZE = 10 + + # 命令类型 + CMD_READ_AI = 1 + CMD_WRITE_AO = 2 + CMD_READ_DELTAT = 3 + RESP_READ_AI = 11 + RESP_WRITE_AO = 12 + RESP_READ_DELTAT = 13 + + def __init__(self, host, port, reconnectInterval=3): + self.host = host + self.port = port + self.reconnectInterval = reconnectInterval + + self.sock = None + self.connected = False + self.packetCounter = 0 + self.lock = threading.Lock() + self.stopEvent = threading.Event() + + # 回调函数 + self.aiCallback = None + self.deltatCallback = None + self.aoCallback = None + + # 响应等待机制 + self.pending_responses = {} + self.response_lock = threading.Lock() + self.connect() + + # 启动连接和接收线程 + threading.Thread(target=self.connectThread, daemon=True).start() + threading.Thread(target=self.receiveThread, daemon=True).start() + + def registerCallbacks(self, aiCallback=None, deltatCallback=None, aoCallback=None): + self.aiCallback = aiCallback + self.deltatCallback = deltatCallback + self.aoCallback = aoCallback + + def connectThread(self): + while not self.stopEvent.is_set(): + if not self.connected: + self.connect() + time.sleep(1) + + 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 + logging.info(f"Connected to {self.host}:{self.port}") + return True + except Exception as e: + logging.error(f"Connection failed: {e}") + self.connected = False + time.sleep(self.reconnectInterval) + return False + + def sendCommand(self, cmdType, data=None): + if not self.connected: + if not self.connect(): + return None # 连接失败 + + try: + with self.lock: + body = b'' + 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) + elif cmdType == self.CMD_READ_AI or cmdType == self.CMD_READ_DELTAT: + body = struct.pack('>d', 0) # 占位数据 + + dataSize = len(body) + current_counter = self.packetCounter + header = struct.pack('>H I I', cmdType, dataSize, current_counter) + packet = self.START_FLAG + header + body + self.END_FLAG + + # 创建等待事件 + response_event = threading.Event() + with self.response_lock: + self.pending_responses[current_counter] = (cmdType, response_event, deque()) + + self.sock.sendall(packet) + self.packetCounter += 1 + return current_counter + except Exception as e: + logging.error(f"Send error: {e}") + self.connected = False + return None + + def waitForResponse(self, packetNum, expectedType, timeout=5): + """等待指定packetNum的响应""" + try: + with self.response_lock: + if packetNum not in self.pending_responses: + logging.error(f"Invalid packetNum: {packetNum}") + return None + + _, event, result_queue = self.pending_responses[packetNum] + + # 等待响应或超时 + if not event.wait(timeout): + logging.warning(f"Response timeout for packet {packetNum}") + return None + + with self.response_lock: + # 检查结果是否有效 + if not result_queue: + return None + + result = result_queue.popleft() + # 验证响应类型 + if result[0] != expectedType + 10: # 响应类型 = 命令类型 + 10 + logging.error(f"Response type mismatch. Expected:{expectedType+10}, Got:{result[0]}") + return None + + return result[1] + finally: + with self.response_lock: + if packetNum in self.pending_responses: + del self.pending_responses[packetNum] + + def receiveThread(self): + buffer = b'' + while not self.stopEvent.is_set(): + try: + if not self.connected: + time.sleep(1) + continue + + data = self.sock.recv(4096) + if not data: + self.connected = False + continue + + buffer += data + + while True: + startPos = buffer.find(self.START_FLAG) + if startPos == -1: + break + + # 移除起始标志前的无效数据 + if startPos > 0: + buffer = buffer[startPos:] + + # 检查是否收到完整头部 + if len(buffer) < len(self.START_FLAG) + self.HEADER_SIZE: + break + + # 解析头部 + header = buffer[len(self.START_FLAG):len(self.START_FLAG) + self.HEADER_SIZE] + dataType, dataSize, packetNum = struct.unpack('>H I I', header) + + # 检查是否收到完整数据包 + frameLen = len(self.START_FLAG) + self.HEADER_SIZE + dataSize + len(self.END_FLAG) + if len(buffer) < frameLen: + break + + # 提取完整数据帧 + fullFrame = buffer[:frameLen] + buffer = buffer[frameLen:] + + # 验证结束标志 + if fullFrame[-len(self.END_FLAG):] != self.END_FLAG: + logging.warning("Invalid end flag. Discarding packet.") + continue + + # 处理数据包 + body = fullFrame[len(self.START_FLAG) + self.HEADER_SIZE:-len(self.END_FLAG)] + self.processData(dataType, body, packetNum) + + except Exception as e: + logging.error(f"Receive error: {e}") + self.connected = False + + def processData(self, dataType, body, packetNum): + try: + result = None + + # AI响应处理 + if dataType == self.RESP_READ_AI: + if len(body) != 72: + 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)] + result = (aiValues, diBools) + # print(result) + if self.aiCallback: + self.aiCallback(aiValues, diBools, packetNum) + + # DeltaT响应处理 + elif dataType == self.RESP_READ_DELTAT: + if len(body) != 128: + logging.error(f"Invalid DeltaT response length: {len(body)}") + return + + deltatValues = struct.unpack('>16d', 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 + result = success + if self.aoCallback: + self.aoCallback(success, packetNum) + else: + logging.warning(f"Unknown response type: {dataType}") + return + + # 唤醒等待线程 + with self.response_lock: + if packetNum in self.pending_responses: + _, event, result_queue = self.pending_responses[packetNum] + result_queue.append((dataType, result)) + event.set() + + except Exception as e: + logging.error(f"Data processing error: {e}") + + def readAIDI(self): + """同步读取AI数据""" + packetNum = self.sendCommand(self.CMD_READ_AI) + if packetNum is None: + return None + return self.waitForResponse(packetNum, self.CMD_READ_AI) # 返回16通道AI和8通道DI + + def readDeltaT(self): + """同步读取DeltaT数据""" + packetNum = self.sendCommand(self.CMD_READ_DELTAT) + if packetNum is None: + return None + return self.waitForResponse(packetNum, self.CMD_READ_DELTAT) + + def writeAo(self, aoData): + """同步写入AO数据并返回结果""" + packetNum = self.sendCommand(self.CMD_WRITE_AO, aoData) + if packetNum is None: + return False + return self.waitForResponse(packetNum, self.CMD_WRITE_AO) or False + + def shutdown(self): + self.stopEvent.set() + if self.sock: + self.sock.close() + + # 唤醒所有等待线程 + with self.response_lock: + for packetNum, (_, event, _) in list(self.pending_responses.items()): + event.set() + del self.pending_responses[packetNum] + + logging.info("Communicator stopped") + + + + + + + +import time +import logging +import threading +import random +# from procli import Box1Communicator # 导入前面修改的客户端类 + +# 配置日志 +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler("box1_client_test.log"), + logging.StreamHandler() + ] +) + +# 全局状态 +class TestState: + running = True + read_count = 0 + read_count_1 = 0 + write_count = 0 + last_ai = None + last_deltat = None + +# 回调函数定义 +def ai_callback(ai_values, di_states, packet_num): + TestState.last_ai = (ai_values, di_states) + TestState.read_count += 1 + # if TestState.read_count % 10 == 0: + # logging.info(f"AI Callback - Packet {packet_num}: Received {TestState.read_count}th AI update") + logging.info(f" 读取到的AI: {ai_values}...") + logging.info(f" 读取到的DI: {di_states}...") + +def deltat_callback(deltat_values, packet_num): + TestState.last_deltat = deltat_values + TestState.read_count_1 += 1 + # if TestState.read_count_1 % 10 == 0: + # logging.info(f"DeltaT Callback - Packet {packet_num}: Received {TestState.read_count}th DeltaT update") + logging.info(f"读取到的delat: {deltat_values}...") + +def ao_callback(success, packet_num): + TestState.write_count += 1 + status = "SUCCESS" if success else "FAILED" + # if TestState.write_count % 10 == 0: + logging.info(f"写入AO成功 {packet_num}: Write {status} ({TestState.write_count}th write)") + +def read_worker(communicator, interval): + """循环读取数据的线程""" + while TestState.running: + try: + # 读取AI数据 + communicator.readAIDI() + + # 读取DeltaT数据 + communicator.readDeltaT() + + # 等待指定间隔 + time.sleep(interval) + + except Exception as e: + logging.error(f"Read worker error: {e}") + time.sleep(1) + +def write_worker(communicator, interval): + """循环写入数据的线程""" + ao_data = [0.0] * 36 # 初始AO数据 + + while TestState.running: + try: + # 随机修改一些AO值 + for i in range(5): + idx = random.randint(0, 35) + ao_data[idx] = random.uniform(0.0, 5.0) + + # 写入AO数据 + # print(ao_data) + communicator.writeAo(ao_data) + + # 等待指定间隔 + time.sleep(interval) + + except Exception as e: + logging.error(f"Write worker error: {e}") + time.sleep(1) + + +def main(): + # 创建通信器实例 + communicator = Box1Communicator("localhost", 8000) + + + + # 注册回调函数 + communicator.registerCallbacks( + aiCallback=ai_callback, + deltatCallback=deltat_callback, + aoCallback=ao_callback + ) + + communicator.readAIDI() + communicator.readDeltaT() + communicator.writeAo([1.0] * 36) + + # 单步调试 + + # logging.info("Starting Box1 client test with continuous read/write...") + + # try: + # # 等待初始连接 + # time.sleep(1) + + # # 启动读取线程 (每200ms读取一次) + # read_thread = threading.Thread(target=read_worker, args=(communicator, 0.2), daemon=True) + # read_thread.start() + + # # 启动写入线程 (每500ms写入一次) + # write_thread = threading.Thread(target=write_worker, args=(communicator, 0.2), daemon=True) + # write_thread.start() + + # # # 启动状态监控线程 + # # monitor_thread = threading.Thread(target=status_monitor, daemon=True) + # # monitor_thread.start() + + # # 主线程等待用户输入退出 + # logging.info("Continuous read/write test running. Press Enter to stop...") + # input() + + # except KeyboardInterrupt: + # logging.info("Test interrupted by user") + # finally: + # # 设置停止标志 + # TestState.running = False + + # # 等待工作线程结束 + # time.sleep(1) + + # # 清理资源 + communicator.shutdown() + # logging.info("Test completed. Final stats:") + # logging.info(f"Total reads: {TestState.read_count}") + # logging.info(f"Total writes: {TestState.write_count}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/protocol/TCP/RTDTC.py b/protocol/TCP/RTDTC.py deleted file mode 100644 index b01b794..0000000 --- a/protocol/TCP/RTDTC.py +++ /dev/null @@ -1,86 +0,0 @@ -import struct -import socket -import time -# commond -# 1、Start -# 2、Stop -# 3、Quit -# 4、Data - -class RTDTCdataPacket(object): - def __init__(self, commond: int, PacketSerialNo: int, lis: list): - self.PacketSerialNo = PacketSerialNo - self.value = struct.pack('d' * len(lis), *lis) - self.commond = commond - # print(lis) - self.buf = [ - 0xF312, self.commond, self.PacketSerialNo, self.value, 0xF314 - ] - # print(self.buf) - def packBytes(self): - packstyle = '>HHL{}sH'.format(str(len(self.value))) - # print(packstyle) - req = struct.pack(packstyle, *self.buf) - return req - - -class RTDTCClient(object): - def __init__(self, url): - # print(url) - host, port = url.split(':') - self._host = host - self._port = int(port) - self.socket = socket.socket() - self.packNo = 0X000001 - - def connect(self): - try: - self.socket.connect((self._host, self._port)) - except: - pass - - def start(self): - self.connect() - self.packNo = 0X000001 - pack = RTDTCdataPacket(1, self.packNo, [0] * 16) - self.socket.send(pack.packBytes()) - self.packNo += 1 - res = self.socket.recv(8) - data = struct.unpack('>HLH', res) - return data - - def stop(self): - pack = RTDTCdataPacket(2, self.packNo, [0] * 16) - self.socket.send(pack.packBytes()) - self.packNo += 1 - res = self.socket.recv(8) - data = struct.unpack('>HLH', res) - return data - - def quit(self): - pack = RTDTCdataPacket(3, self.packNo, [0] * 16) - self.socket.send(pack.packBytes()) - self.packNo += 1 - res = self.socket.recv(8) - data = struct.unpack('>HLH', res) - self.socket.close() - return data - - def writeData(self, lis: list): - pack = RTDTCdataPacket(4, self.packNo, lis) - self.socket.send(pack.packBytes()) - self.packNo += 1 - res = self.socket.recv(8) - data = struct.unpack('>HLH', res) - return data - -if __name__ == '__main__': - a = RTDTCClient('127.0.0.1:6350') - # a.connect() - a.start() - # print(1) - for x in range(50): - time.sleep(1) - a.writeData([x + 0.001] * 16) - # print(2) - a.stop() \ No newline at end of file diff --git a/protocol/TCP/TemToMv.py b/protocol/TCP/TemToMv.py deleted file mode 100644 index c5ad029..0000000 --- a/protocol/TCP/TemToMv.py +++ /dev/null @@ -1,598 +0,0 @@ -import math - -def pt100(t): - """ - PT100, 温度到电阻转换公式 - - 从0℃~850℃: - Rt=R0(1+A*t+B*t^2) - - 从-200℃~0℃: - Rt=R0[1+A*t+Bt^2+C(t-100)*t^3] - 式中: - Rt----温度为t时的铂电阻的阻值 - R0----温度为0时的铂电阻的阻值,即100Ω - - A=3.9083*10^(-3)℃^(-1) - B=-5.775*10^(-7) ℃^(-2) - C=-4.183*10^(-12) ℃^(-4) - - """ - A = 3.9083 * (10 ** -3) - B = -5.775 * (10 ** -7) - C = -4.183 * (10 ** -12) - R0 = 100 - if 0 <= t <= 850: - Rt = R0 * (1 + A * t + B * t * t) - return Rt - elif -200 <= t < 0: - Rt = R0 * (1 + A * t + B * t * t + C * (t - 100) * t ** 3) - return Rt - else: - raise ValueError("温度超范围 -200 ~ 800 度") - - -def TC_T(t): - ''' - https://max.book118.com/html/2018/0907/8061021016001123.shtm - RTD_T 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if -270 <= t <= 0: - a0 = 0.000_000_000_0 * 10 ** 0 - a1 = 3.874_810_636_4 * 10 ** 1 - a2 = 4.419_443_434_7 * 10 ** -2 - a3 = 1.184_432_310_5 * 10 ** -4 - a4 = 2.003_297_355_4 * 10 ** -5 - a5 = 9.013_801_955_9 * 10 ** -7 - a6 = 2.265_115_420_5 * 10 ** -8 - a7 = 3.607_115_659_3 * 10 ** -10 - a8 = 3.849_393_988_3 * 10 ** -12 - a9 = 2.821_352_192_5 * 10 ** -14 - a10 = 1.425_159_477_9 * 10 ** -16 - a11 = 4.876_866_228_6 * 10 ** -19 - a12 = 1.079_553_927_0 * 10 ** -21 - a13 = 1.394_502_706_2 * 10 ** -24 - a14 = 7.979_515_392_7 * 10 ** -28 - result = sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - a9 * t ** 9, - a10 * t ** 10, - a11 * t ** 11, - a12 * t ** 12, - a13 * t ** 13, - a14 * t ** 14, - ]) / 1000 - elif 0 < t <= 400: - a0 = 0.000_000_000_0 * 10 ** 0 - a1 = 3.874_810_636_4 * 10 ** 1 - a2 = 3.329_222_788_0 * 10 ** -2 - a3 = 2.061_824_340_4 * 10 ** -4 - a4 = -2.188_225_684_6 * 10 ** -6 - a5 = 1.099_688_092_8 * 10 ** -8 - a6 = -3.081_575_877_2 * 10 ** -11 - a7 = 4.547_913_529_0 * 10 ** -14 - a8 = -2.751_290_167_3 * 10 ** -17 - result = sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - ]) / 1000 - return result - - -def TC_E(t): - '''TC/E 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if -270 <= t <= 0: - a0 = 0.000_000_000_0 * 10 ** 0 - a1 = 5.866_550_870_8 * 10 ** 1 - a2 = 4.541_097_712_4 * 10 ** -2 - a3 = -7.799_804_868_6 * 10 ** -4 - a4 = -2.580_016_084_3 * 10 ** -5 - a5 = -5.945_258_305_7 * 10 ** -7 - a6 = -9.321_405_866_7 * 10 ** -9 - a7 = -1.028_760_553_4 * 10 ** -10 - a8 = -8.037_012_362_1 * 10 ** -13 - a9 = -4.397_949_739_1 * 10 ** -15 - a10 = -1.641_477_635_5 * 10 ** -17 - a11 = -3.967_361_951_6 * 10 ** -20 - a12 = -5.582_732_872_1 * 10 ** -23 - a13 = -3.465_784_201_3 * 10 ** -26 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - a9 * t ** 9, - a10 * t ** 10, - a11 * t ** 11, - a12 * t ** 12, - a13 * t ** 13, - ]) / 1000 - elif 0 < t <= 100: - a0 = 0.000_000_000_0 * 10 ** 0 - a1 = 5.866_550_871_0 * 10 ** 1 - a2 = 4.503_227_558_2 * 10 ** -2 - a3 = 2.890_840_721_2 * 10 ** -5 - a4 = -3.305_689_665_2 * 10 ** -7 - a5 = 6.502_440_327_0 * 10 ** -10 - a6 = -1.919_749_550_4 * 10 ** -13 - a7 = -1.253_660_049_7 * 10 ** -15 - a8 = 2.148_921_756_9 * 10 ** -18 - a9 = -1.438_804_178_2 * 10 ** -21 - a10 = 3.596_089_948_1 * 10 ** -25 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - a9 * t ** 9, - a10 * t ** 10, - ]) / 1000 - - -def TC_S(t): - '''TC/S 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if -50 <= t <= 1064.18: - a0 = 0.00000000000 * 10 ** 0 - a1 = 5.40313308631 * 10 ** 0 - a2 = 1.25934289740 * 10 ** -2 - a3 = -2.32477968689 * 10 ** -5 - a4 = 3.22028823036 * 10 ** -8 - a5 = -3.31465196389 * 10 ** -11 - a6 = 2.55744251786 * 10 ** -14 - a7 = -1.25068871393 * 10 ** -17 - a8 = 2.71443176145 * 10 ** -21 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - ]) / 1000 - elif 1064.18 < t <= 1664.5: - a0 = 1.32900444085 * 10 ** 3 - a1 = 3.34509311344 * 10 ** 0 - a2 = 6.54805192818 * 10 ** -3 - a3 = -1.64856259209 * 10 ** -6 - a4 = 1.29989605174 * 10 ** -11 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - ]) / 1000 - elif 1664.5 < t <= 1768.1: - a0 = 1.46628232636 * 10 ** 5 - a1 = -2.58430516752 * 10 ** 2 - a2 = 1.63693574641 * 10 ** -1 - a3 = -3.30439046987 * 10 ** -5 - a4 = -9.43223690612 * 10 ** -12 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - ]) / 1000 - - -def TC_R(t): - '''TC/R 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if -50 <= t <= 1064.18: - a0 = 0.00000000000 * 10 ** 0 - a1 = 5.28961729765 * 10 ** 0 - a2 = 1.39166589782 * 10 ** -2 - a3 = -2.38855693017 * 10 ** -5 - a4 = 3.56916001063 * 10 ** -8 - a5 = -4.62347666298 * 10 ** -11 - a6 = 5.00777441034 * 10 ** -14 - a7 = -3.73105886191 * 10 ** -17 - a8 = 1.57716482367 * 10 ** -20 - a9 = -2.81038625251 * 10 ** -24 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - a9 * t ** 9, - ]) / 1000 - elif 1064.18 < t <= 1664.5: - a0 = 2.95157925316 * 10 ** 3 - a1 = -2.52061251332 * 10 ** 0 - a2 = 1.59564501865 * 10 ** -2 - a3 = -7.64085947576 * 10 ** -6 - a4 = 2.05305291024 * 10 ** -9 - a5 = -2.93359668173 * 10 ** -13 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - ]) / 1000 - elif 1664.5 < t <= 1768.1: - a0 = 1.52232118209 * 10 ** 5 - a1 = -2.68819888545 * 10 ** 2 - a2 = 1.71280280471 * 10 ** -1 - a3 = -3.45895706453 * 10 ** -5 - a4 = -9.34633971046 * 10 ** -12 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - ]) / 1000 - - -def TC_B(t): - '''TC/B 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if 0 <= t <= 630.615: - a0 = 0.00000000000 * 10 ** 0 - a1 = -2.4650818346 * 10 ** -1 - a2 = 5.9040421171 * 10 ** -3 - a3 = -1.3257931636 * 10 ** -6 - a4 = 1.5668291901 * 10 ** -9 - a5 = -1.6944529240 * 10 ** -12 - a6 = 6.2990347094 * 10 ** -16 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - ]) / 1000 - elif 630.615 < t <= 1820: - a0 = -3.8938168621 * 10 ** 3 - a1 = 2.8571747470 * 10 ** 1 - a2 = -8.4885104785 * 10 ** -2 - a3 = 1.5785280164 * 10 ** -4 - a4 = -1.6835344864 * 10 ** -7 - a5 = 1.1109794013 * 10 ** -10 - a6 = -4.4515431033 * 10 ** -14 - a7 = 9.8975640821 * 10 ** -18 - a8 = -9.3791330289 * 10 ** -22 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - ]) / 1000 - - -def TC_J(t): - '''TC/J 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if -210 <= t <= 760: - a0 = 0.00000000000 * 10 ** 0 - a1 = 5.0381187815 * 10 ** 1 - a2 = 3.0475836930 * 10 ** -2 - a3 = -8.5681065720 * 10 ** -5 - a4 = 1.3228195295 * 10 ** -7 - a5 = -1.7052958337 * 10 ** -10 - a6 = 2.0948090697 * 10 ** -13 - a7 = -1.2538395336 * 10 ** -16 - a8 = 1.5631725697 * 10 ** -20 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - ]) / 1000 - elif 760 < t <= 1200: - a0 = 2.9645625681 * 10 ** 5 - a1 = -1.4976127786 * 10 ** 3 - a2 = 3.1787103924 * 10 ** 0 - a3 = -3.1847686701 * 10 ** -3 - a4 = 1.5720819004 * 10 ** -6 - a5 = -3.0691369056 * 10 ** -10 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - ]) / 1000 - -def TC_N(t): - '''TC/N 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if -270 <= t <= 0: - a0 = 0.00000000000 * 10 ** 0 - a1 = 2.6159105962 * 10 ** 1 - a2 = 1.0957484228 * 10 ** -2 - a3 = -9.3841111554 * 10 ** -5 - a4 = -4.6412039759 * 10 ** -8 - a5 = -2.6303357716 * 10 ** -9 - a6 = -2.2653438003 * 10 ** -11 - a7 = -7.6089300791 * 10 ** -14 - a8 = -9.3419667835 * 10 ** -17 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - ]) / 1000 - elif 0 < t <= 1300: - a0 = 0.00000000000 * 10 ** 0 - a1 = 2.5929394601 * 10 ** 1 - a2 = 1.5710141880 * 10 ** -2 - a3 = 4.3825627237 * 10 ** -5 - a4 = -2.5261169794 * 10 ** -7 - a5 = 6.4311819339 * 10 ** -10 - a6 = -1.0063471519 * 10 ** -12 - a7 = 9.9745338992 * 10 ** -16 - a8 = -6.0863245607 * 10 ** -19 - a9 = 2.0849229339 * 10 ** -22 - a10 = -3.0682196151 * 10 ** -26 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - a9 * t ** 9, - a10 * t ** 10, - ]) / 1000 - -def TC_C(t): - '''TC/c 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if 0 <= t <= 630: - a0 = 0.00000000000 * 10 ** 0 - a1 = 1.3406032 * 10 ** 1 - a2 = 1.1924992 * 10 ** -2 - a3 = -7.9806354 * 10 ** -6 - a4 = -5.0787515 * 10 ** -9 - a5 = 1.3164197 * 10 ** -11 - a6 = -7.9197332 * 10 ** -15 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - ]) / 1000 - elif 630 < t <= 2315: - a0 = 4.0528823 * 10 ** 2 - a1 = 1.1509355 * 10 ** 1 - a2 = 1.5696453 * 10 ** -2 - a3 = -1.3704412 * 10 ** -5 - a4 = 5.2290873 * 10 ** -9 - a5 = -9.2082758 * 10 ** -13 - a6 = 4.5245112 * 10 ** -17 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - ]) / 1000 - -def TC_A(t): - '''TC/A 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if 0 <= t <= 2500: - a0 = 0.00000000000 * 10 ** 0 - a1 = 1.1951905 * 10 ** 1 - a2 = 1.6672625 * 10 ** -2 - a3 = -2.8287807 * 10 ** -5 - a4 = 2.8397839 * 10 ** -8 - a5 = -1.8505007 * 10 ** -11 - a6 = 7.3632123 * 10 ** -15 - a7 = -1.6148878 * 10 ** -18 - a8 = 1.4901679 * 10 ** -22 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - ]) / 1000 - -def TC_K(t): - '''TC/T 热电偶 温度转电动势 计算函数 - 输入 : t (摄氏度) - 输出 : e (毫伏) - ''' - if -270 <= t <= 0: - a0 = 0.000_000_000_0 * 10 ** 0 - a1 = 3.945_012_802_5 * 10 ** 1 - a2 = 2.362_237_359_8 * 10 ** -2 - a3 = -3.285_890_678_4 * 10 ** -4 - a4 = -4.990_482_877_7 * 10 ** -6 - a5 = -6.750_905_917_3 * 10 ** -8 - a6 = -5.741_032_742_8 * 10 ** -10 - a7 = -3.108_887_289_4 * 10 ** -12 - a8 = -1.045_160_936_5 * 10 ** -14 - a9 = -1.988_926_687_8 * 10 ** -17 - a10 = -1.632_269_748_6 * 10 ** -20 - return sum([ - a0 * t ** 0, - a1 * t ** 1, - a2 * t ** 2, - a3 * t ** 3, - a4 * t ** 4, - a5 * t ** 5, - a6 * t ** 6, - a7 * t ** 7, - a8 * t ** 8, - a9 * t ** 9, - a10 * t ** 10, - ]) / 1000 - elif 0 < t <= 1300: - a0 = -1.760_041_368_6 * 10 ** 1 - a1 = 3.892_120_497_5 * 10 ** 1 - a2 = 1.855_877_003_2 * 10 ** -2 - a3 = -9.945_759_287_4 * 10 ** -5 - a4 = 3.184_094_571_9 * 10 ** -7 - a5 = -5.607_284_488_9 * 10 ** -10 - a6 = 5.607_505_905_9 * 10 ** -13 - a7 = -3.202_072_000_3 * 10 ** -16 - a8 = 9.715_114_715_2 * 10 ** -20 - a9 = -1.210_472_127_5 * 10 ** -23 - c0 = 1.185_976 * 10 ** 2 - c1 = -1.183_432 * 10 ** -4 - # return (sum([ - # a0 * t ** 0 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a1 * t ** 1 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a2 * t ** 2 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a3 * t ** 3 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a4 * t ** 4 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a5 * t ** 5 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a6 * t ** 6 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a7 * t ** 7 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a8 * t ** 8 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # a9 * t ** 9 + c0 * math.exp(c1 * (t - 126.968_6) ** 2), - # ]) + a0) / 1000 - result = (((((((((a9 * t + a8) * t + a7) * t + a6) * t + a5) * t + a4) * t + a3) * t + a2) * t + a1) * t + a0) / 1000 - if 0 < t <= 19: - result += 0.02 - elif 21 <= t <= 39 : - result += 0.04 - elif 40 <= t <= 49 : - result += 0.05 - elif 50 <= t <= 69 : - result += 0.06 - elif 70 <= t <= 79 : - result += 0.07 - elif 80 <= t <= 89 : - result += 0.08 - elif 90 <= t <= 99 : - result += 0.09 - elif 100 <= t <= 119 : - result += 0.1 - elif 120 <= t <= 149 : - result += 0.11 - elif 150 <= t <= 169 : - result += 0.12 - elif 170 <= t <= 179 : - result += 0.11 - elif 180 <= t <= 189 : - result += 0.1 - elif 190 <= t <= 199 : - result += 0.08 - elif 200 <= t <= 209 : - result += 0.07 - elif 210 <= t <= 219 : - result += 0.06 - elif 220 <= t <= 229 : - result += 0.05 - elif 230 <= t <= 239 : - result += 0.03 - elif 240 <= t <= 269 : - result += 0.02 - elif 270 <= t <= 299 : - result += 0.01 - return result - -def temToMv(varType, temValue): - if varType == 'T': - return TC_T(temValue) - elif varType == 'E': - return TC_E(temValue) - elif varType == 'S': - return TC_S(temValue) - elif varType == 'R': - return TC_R(temValue) - elif varType == 'K': - return TC_K(temValue) - elif varType == 'J': - return TC_J(temValue) - elif varType == 'N': - return TC_N(temValue) - elif varType == 'C': - return TC_C(temValue) - elif varType == 'A': - return TC_A(temValue) - elif varType == 'B': - return TC_B(temValue) - elif varType == 'PT100': - return pt100(temValue) diff --git a/protocol/TCP/TestServer.py b/protocol/TCP/TestServer.py new file mode 100644 index 0000000..36104b8 --- /dev/null +++ b/protocol/TCP/TestServer.py @@ -0,0 +1,226 @@ +import socket +import struct +import threading +import time +import logging +import random + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +class Box1Simulator: + START_FLAG = b'\xF3\x12' + END_FLAG = b'\xF3\x14' + HEADER_SIZE = 10 + + # 命令类型 + CMD_READ_AI = 1 + CMD_WRITE_AO = 2 + CMD_READ_DELTAT = 3 + RESP_READ_AI = 11 + RESP_WRITE_AO = 12 + RESP_READ_DELTAT = 13 + + def __init__(self, host, port): + self.host = host + self.port = port + self.server_socket = None + self.stop_event = threading.Event() + + # 模拟设备状态 + self.ai_values = [0.0] * 8 + self.di_states = [0] * 16 + self.ao_values = [0.0] * 36 + self.deltat_values = [0] * 16 + + # 初始化模拟值 + self.reset_simulated_values() + + # 启动服务 + threading.Thread(target=self.run_server, daemon=True).start() + logging.info(f"Box1 simulator started on {host}:{port}") + + def reset_simulated_values(self): + """重置模拟值到初始状态""" + # 模拟AI值 (0-10V范围) + self.ai_values = [random.uniform(0, 10) for _ in range(8)] + + # 模拟DI状态 (随机0或1) + self.di_states = [random.randint(0, 1) for _ in range(16)] + + # 模拟AO值 (初始全0) + self.ao_values = [0.0] * 36 + + # 模拟DeltaT值 (时间戳差) + self.deltat_values = [random.randint(1000, 5000) for _ in range(16)] + + logging.info("Simulated values reset") + + def run_server(self): + """运行TCP服务器""" + self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.server_socket.bind((self.host, self.port)) + self.server_socket.listen(5) + + while not self.stop_event.is_set(): + try: + client_sock, addr = self.server_socket.accept() + logging.info(f"New connection from {addr}") + threading.Thread(target=self.handle_client, args=(client_sock,), daemon=True).start() + except socket.timeout: + pass + except Exception as e: + logging.error(f"Server error: {e}") + break + + def handle_client(self, client_sock): + """处理客户端连接""" + buffer = b'' + try: + while not self.stop_event.is_set(): + data = client_sock.recv(4096) + if not data: + break + + buffer += data + + while True: + start_pos = buffer.find(self.START_FLAG) + if start_pos == -1: + break + + if start_pos > 0: + buffer = buffer[start_pos:] + + if len(buffer) < len(self.START_FLAG) + self.HEADER_SIZE: + break + + header = buffer[len(self.START_FLAG):len(self.START_FLAG) + self.HEADER_SIZE] + try: + cmd_type, data_size, packet_num = struct.unpack('>H I I', header) + except struct.error: + logging.warning("Invalid header format") + buffer = buffer[len(self.START_FLAG):] + continue + + frame_len = len(self.START_FLAG) + self.HEADER_SIZE + data_size + len(self.END_FLAG) + if len(buffer) < frame_len: + break + + full_frame = buffer[:frame_len] + buffer = buffer[frame_len:] + + if full_frame[-len(self.END_FLAG):] != self.END_FLAG: + logging.warning("Invalid end flag") + continue + + body = full_frame[len(self.START_FLAG) + self.HEADER_SIZE:-len(self.END_FLAG)] + + # 处理客户端命令 + response = self.process_command(cmd_type, body, packet_num) + if response: + client_sock.sendall(response) + + except Exception as e: + logging.error(f"Client handling error: {e}") + finally: + client_sock.close() + logging.info("Client disconnected") + + def process_command(self, cmd_type, body, packet_num): + """处理客户端命令并生成响应""" + try: + # 读取AI命令 + if cmd_type == self.CMD_READ_AI: + return self.create_ai_response(packet_num) + + # 写入AO命令 + elif cmd_type == self.CMD_WRITE_AO: + if len(body) != 288: # 36 doubles * 8 bytes + logging.error(f"Invalid AO data length: {len(body)}") + return None + + ao_data = struct.unpack('>' + 'd'*36, body) + self.ao_values = list(ao_data) + logging.info(f"接收到的AO: {ao_data}... (total {len(ao_data)} values)") + return self.create_ao_response(True, packet_num) + + # 读取DeltaT命令 + elif cmd_type == self.CMD_READ_DELTAT: + # 更新一些DeltaT值以模拟变化 + for i in range(4): + self.deltat_values[i] += random.randint(1, 10) + print("deltatT为", self.deltat_values) + return self.create_deltat_response(packet_num) + + else: + logging.warning(f"Unknown command type: {cmd_type}") + return None + + except Exception as e: + logging.error(f"Command processing error: {e}") + return None + + def create_ai_response(self, packet_num): + """创建AI响应数据包""" + # 模拟值轻微变化 + for i in range(8): + self.ai_values[i] += random.uniform(-0.1, 0.1) + self.ai_values[i] = max(0.0, min(10.0, self.ai_values[i])) + + # 随机翻转一些DI状态 + for i in range(4): + if random.random() < 0.2: # 20%几率翻转 + self.di_states[i] = 1 - self.di_states[i] + + # 打包AI数据 (8 doubles) + ai_bytes = struct.pack('>' + 'd'*8, *self.ai_values) + + # 打包DI状态为一个64位整数 + di_state_int = 0 + for i, state in enumerate(self.di_states): + di_state_int |= (state << i) + di_bytes = struct.pack('>Q', di_state_int) + + body = ai_bytes + di_bytes + print("发送的AI为", self.ai_values, self.di_states) + return self.create_packet(self.RESP_READ_AI, body, packet_num) + + + def create_ao_response(self, success, packet_num): + """创建AO写入响应数据包""" + # 使用0.0表示成功,1.0表示失败 + result = 0.0 if success else 1.0 + body = struct.pack('>d', result) + return self.create_packet(self.RESP_WRITE_AO, body, packet_num) + + def create_deltat_response(self, packet_num): + """创建DeltaT响应数据包""" + # 打包16个64位无符号整数 + body = struct.pack('>' + 'd'*16, *self.deltat_values) + return self.create_packet(self.RESP_READ_DELTAT, body, packet_num) + + def create_packet(self, cmd_type, body, packet_num): + """创建完整的数据包""" + data_size = len(body) + header = struct.pack('>H I I', cmd_type, data_size, packet_num) + return self.START_FLAG + header + body + self.END_FLAG + + def shutdown(self): + """停止服务器""" + self.stop_event.set() + if self.server_socket: + self.server_socket.close() + logging.info("Box1 simulator stopped") + +if __name__ == "__main__": + # 创建模拟器实例 + simulator = Box1Simulator("localhost", 8000) + + try: + # 运行模拟器直到手动停止 + while True: + time.sleep(1) + except KeyboardInterrupt: + print("\nStopping simulator...") + simulator.shutdown() \ No newline at end of file