#!/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("👋 再见!")