0618更新

main
zcwBit 4 months ago
parent 750ae65fb9
commit 68961ec9cc

@ -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

@ -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()

@ -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()

@ -1,598 +0,0 @@
import math
def pt100(t):
"""
PT100, 温度到电阻转换公式
从0~850
Rt=R01+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)

@ -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()
Loading…
Cancel
Save