#!/usr/bin/env python # -*- coding: utf-8 -*- """ Melsec 模拟设备服务器 提供模拟的 Melsec 设备用于测试在线脚本中的 Melsec 内置函数 """ import threading import socket import struct import time print("Melsec 模拟设备服务器") class MockMelsecServer: """模拟 Melsec PLC 服务器用于测试""" def __init__(self, host='127.0.0.1', port=5007): self.host = host self.port = port self.server_socket = None self.running = False self.thread = None # 模拟数据存储 (按照Melsec地址格式) self.memory_areas = { 'M': { # M 位地址 100: True, 101: False, 102: True, 103: False, 200: False, 201: True }, 'D': { # D 字地址 100: 1234, 101: 5678, 200: 9999, 300: 42 }, 'D_STRING': { # D 字地址存储的字符串 500: "HELLO", 502: "WORLD", 600: "TEST", 602: "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"🟢 模拟 Melsec 服务器已启动:{self.host}:{self.port}") print(f"📊 模拟数据:") print(f" - M100=True, M101=False, M102=True, M200=False") print(f" - D100=1234, D101=5678, D200=9999, D300=42") print(f" - D500-501='HELLO', D600-601='TEST'") time.sleep(0.1) # 等待服务器完全启动 except Exception as e: print(f"❌ 启动模拟 Melsec 服务器失败: {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("🔴 模拟 Melsec 服务器已停止") 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_melsec_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_melsec_request(self, request_data): """处理 Melsec 请求并生成响应""" try: # 简化的 MC 协议解析 if len(request_data) < 11: return None # MC协议格式 (Binary模式) # 子头部: 2字节 (50 00) # 网络号: 1字节 (00) # PLC号: 1字节 (FF) # IO号: 2字节 (FF 03) # 站号: 1字节 (00) # 请求数据长度: 2字节 # 请求数据: N字节 # 跳过头部,获取命令码 cmd_code = struct.unpack('