VWED_server/tests/test_fins_module.py

254 lines
9.0 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Fins 模拟设备服务器
提供模拟的 Fins 设备用于测试在线脚本中的 Fins 内置函数
"""
import threading
import socket
import struct
import time
print("Fins 模拟设备服务器")
class MockFinsServer:
"""模拟 Fins 服务器用于测试"""
def __init__(self, host='127.0.0.1', port=9600):
self.host = host
self.port = port
self.server_socket = None
self.running = False
self.thread = None
# 模拟数据存储
self.memory_areas = {
0x82: { # DM 区域
100: { # 地址 100
'word': 1234, # word 数据
'bits': [True, False, True, False, True, False, True, False], # 8个位
'string': "HELLO WORLD" # 字符串数据
},
200: { # 地址 200
'word': 5678,
'bits': [False, True, False, True, False, True, False, True],
'string': "TEST DATA"
}
}
}
def start(self):
"""启动模拟服务器"""
try:
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)
self.running = True
self.thread = threading.Thread(target=self._server_loop)
self.thread.daemon = True
self.thread.start()
print(f"🟢 模拟 Fins 服务器已启动:{self.host}:{self.port}")
print(f"📊 模拟数据:")
print(f" - 地址 100: word=1234, bits=[T,F,T,F,T,F,T,F], string='HELLO WORLD'")
print(f" - 地址 200: word=5678, bits=[F,T,F,T,F,T,F,T], string='TEST DATA'")
time.sleep(0.1) # 等待服务器完全启动
except Exception as e:
print(f"❌ 启动模拟 Fins 服务器失败: {str(e)}")
raise
def stop(self):
"""停止模拟服务器"""
self.running = False
if self.server_socket:
self.server_socket.close()
if self.thread:
self.thread.join(timeout=1.0)
print("🔴 模拟 Fins 服务器已停止")
def _server_loop(self):
"""服务器主循环"""
while self.running:
try:
client_socket, addr = self.server_socket.accept()
print(f"📞 客户端连接: {addr}")
# 处理客户端请求
self._handle_client(client_socket)
except Exception as e:
if self.running:
print(f"❌ 服务器循环错误: {str(e)}")
break
def _handle_client(self, client_socket):
"""处理客户端请求"""
try:
# 接收请求
data = client_socket.recv(1024)
if not data:
return
print(f"📨 收到请求数据: {data.hex()}")
# 解析并响应
response = self._process_fins_request(data)
if response:
client_socket.send(response)
print(f"📤 发送响应数据: {response.hex()}")
except Exception as e:
print(f"❌ 处理客户端请求失败: {str(e)}")
finally:
client_socket.close()
def _process_fins_request(self, request_data):
"""处理 Fins 请求并生成响应"""
try:
# 简化的 Fins 协议解析
if len(request_data) < 28:
return None
# 跳过 TCP 头部,解析 Fins 命令
fins_start = 16 # 跳过 FINS TCP 头部
# 提取命令码
cmd = struct.unpack('>H', request_data[fins_start + 10:fins_start + 12])[0]
area = request_data[fins_start + 12]
addr_high = request_data[fins_start + 13]
addr_low = request_data[fins_start + 14]
bit_offset = request_data[fins_start + 15]
address = (addr_high << 8) | addr_low
print(f"🔍 解析命令: CMD=0x{cmd:04X}, Area=0x{area:02X}, Addr={address}, Bit={bit_offset}")
# 生成响应
if cmd == 0x0101: # 读取命令
return self._create_read_response(area, address, bit_offset, request_data)
elif cmd == 0x0102: # 写入命令
return self._create_write_response(area, address, bit_offset, request_data)
except Exception as e:
print(f"❌ 处理 Fins 请求失败: {str(e)}")
return None
def _create_read_response(self, area, address, bit_offset, request_data):
"""创建读取响应"""
try:
# 构造响应头部
response_header = b'FINS' + b'\x00' * 12
# Fins 响应头部(复制请求头部并修改)
fins_header = request_data[16:26] # 复制原始头部
# 添加响应码 (成功)
response_code = struct.pack('>H', 0x0000)
# 获取模拟数据
if area in self.memory_areas and address in self.memory_areas[area]:
area_data = self.memory_areas[area][address]
# 根据请求类型返回不同数据
if bit_offset == 0: # Word 读取
word_data = struct.pack('>H', area_data['word'])
data_part = word_data
else: # Bit 读取
bit_value = 1 if area_data['bits'][bit_offset] else 0
data_part = struct.pack('B', bit_value)
else:
# 返回默认数据
data_part = b'\x00\x00'
# 组装完整响应
fins_response = fins_header + response_code + data_part
# 更新长度
length = len(fins_response)
response_header = response_header[:8] + struct.pack('>I', length) + response_header[12:]
return response_header + fins_response
except Exception as e:
print(f"❌ 创建读取响应失败: {str(e)}")
return None
def _create_write_response(self, area, address, bit_offset, request_data):
"""创建写入响应"""
try:
# 模拟写入操作
print(f"✏️ 模拟写入: Area=0x{area:02X}, Addr={address}, Bit={bit_offset}")
# 构造简单的成功响应
response_header = b'FINS' + b'\x00' * 12
fins_header = request_data[16:26]
response_code = struct.pack('>H', 0x0000) # 成功
fins_response = fins_header + response_code
# 更新长度
length = len(fins_response)
response_header = response_header[:8] + struct.pack('>I', length) + response_header[12:]
return response_header + fins_response
except Exception as e:
print(f"❌ 创建写入响应失败: {str(e)}")
return None
def start_mock_fins_server():
"""启动模拟 Fins 服务器"""
server = MockFinsServer('127.0.0.1', 9600)
server.start()
return server
if __name__ == "__main__":
print("🚀 启动 Fins 模拟设备服务器")
print("=" * 50)
try:
# 启动模拟服务器
server = start_mock_fins_server()
print("\n📋 测试说明:")
print(" 可以在在线脚本中使用以下代码测试:")
print("")
print(" # 测试读取 word")
print(" result = VWED.fins.read_fins_word('127.0.0.1', 9600, 0x82, 100, 0)")
print(" print(f'读取 word 结果: {result}') # 期望: 1234")
print("")
print(" # 测试读取 bit")
print(" result = VWED.fins.read_fins_bit('127.0.0.1', 9600, 0x82, 100, 0)")
print(" print(f'读取 bit 结果: {result}') # 期望: 1 (True)")
print("")
print(" # 测试写入 word")
print(" VWED.fins.write_fins_word('127.0.0.1', 9600, 0x82, 200, 0, 9999)")
print(" print('写入 word 完成')")
print("")
print(" # 测试写入 bit")
print(" VWED.fins.write_fins_bit('127.0.0.1', 9600, 0x82, 200, 3, True)")
print(" print('写入 bit 完成')")
print("")
print("💡 按 Ctrl+C 停止服务器")
# 保持服务器运行
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n⏹️ 收到停止信号")
except Exception as e:
print(f"\n❌ 服务器运行失败: {str(e)}")
finally:
if 'server' in locals():
server.stop()
print("👋 再见!")