#!/usr/bin/env python # -*- coding: utf-8 -*- """ Modbus TCP 客户端测试脚本 测试VWED在线脚本中的Modbus通信功能 """ import sys import os import time import threading # 添加项目根目录到路径 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) from services.online_script.built_in_modules.modbus_module import VWEDModbusModule from tests.test_modbus_server import ModbusTestServer class ModbusClientTester: """Modbus客户端测试器""" def __init__(self): self.server = None self.modbus_module = VWEDModbusModule("test_script") self.host = 'localhost' self.port = 5020 self.slave_id = 1 def start_test_server(self): """启动测试服务器""" print("启动Modbus测试服务器...") self.server = ModbusTestServer(self.host, self.port) self.server.start_server() time.sleep(2) # 等待服务器启动 print(f"测试服务器已启动: {self.host}:{self.port}") def stop_test_server(self): """停止测试服务器""" if self.server: self.server.stop_server() print("测试服务器已停止") def test_basic_read_operations(self): """测试基础读取操作""" print("\n" + "="*50) print("测试基础读取操作") print("="*50) # 测试读取线圈 print("\n1. 测试读取线圈 (功能码01)") result = self.modbus_module.read_coil_status(self.host, self.port, self.slave_id, 0) print(f" read_coil_status(0): {result}") # 测试读取离散输入 print("\n2. 测试读取离散输入 (功能码02)") result = self.modbus_module.read_input_status(self.host, self.port, self.slave_id, 0) print(f" read_input_status(0): {result}") # 测试读取保持寄存器 print("\n3. 测试读取保持寄存器 (功能码03)") result = self.modbus_module.read_holding_register(self.host, self.port, self.slave_id, 0, 2) print(f" read_holding_register(0, 无符号): {result}") # 测试读取输入寄存器 print("\n4. 测试读取输入寄存器 (功能码04)") result = self.modbus_module.read_input_register(self.host, self.port, self.slave_id, 0, 2) print(f" read_input_register(0, 无符号): {result}") def test_batch_read_operations(self): """测试批量读取操作""" print("\n" + "="*50) print("测试批量读取操作") print("="*50) # 批量读取线圈 print("\n1. 批量读取线圈") result = self.modbus_module.batch_read_coil_status(self.host, self.port, self.slave_id, 0, 5) print(f" batch_read_coil_status(0-4): {result}") # 批量读取离散输入 print("\n2. 批量读取离散输入") result = self.modbus_module.batch_read_input_status(self.host, self.port, self.slave_id, 0, 5) print(f" batch_read_input_status(0-4): {result}") # 批量读取保持寄存器 print("\n3. 批量读取保持寄存器") result = self.modbus_module.batch_read_holding_registers(self.host, self.port, self.slave_id, 0, 5) print(f" batch_read_holding_registers(0-4): {result}") # 批量读取输入寄存器 print("\n4. 批量读取输入寄存器") result = self.modbus_module.batch_read_input_registers(self.host, self.port, self.slave_id, 0, 5) print(f" batch_read_input_registers(0-4): {result}") def test_write_operations(self): """测试写入操作""" print("\n" + "="*50) print("测试写入操作") print("="*50) # 测试写入线圈 print("\n1. 测试写入线圈 (功能码05)") result = self.modbus_module.write_coil_status(self.host, self.port, self.slave_id, 0, True) print(f" write_coil_status(0, True): {result}") # 验证写入结果 read_result = self.modbus_module.read_coil_status(self.host, self.port, self.slave_id, 0) print(f" 验证结果 read_coil_status(0): {read_result}") # 测试写入保持寄存器 print("\n2. 测试写入保持寄存器 (功能码06)") result = self.modbus_module.write_holding_register(self.host, self.port, self.slave_id, 0, 2, 12345) print(f" write_holding_register(0, 12345): {result}") # 验证写入结果 read_result = self.modbus_module.read_holding_register(self.host, self.port, self.slave_id, 0, 2) print(f" 验证结果 read_holding_register(0): {read_result}") def test_batch_write_operations(self): """测试批量写入操作""" print("\n" + "="*50) print("测试批量写入操作") print("="*50) # 批量写入线圈 print("\n1. 批量写入线圈 (功能码0F)") values = [True, False, True, False, True] result = self.modbus_module.batch_write_coil_status(self.host, self.port, self.slave_id, 0, values) print(f" batch_write_coil_status(0-4, {values}): {result}") # 验证结果 read_result = self.modbus_module.batch_read_coil_status(self.host, self.port, self.slave_id, 0, 5) print(f" 验证结果: {read_result}") # 批量写入保持寄存器 print("\n2. 批量写入保持寄存器 (功能码10)") values = [1111, 2222, 3333, 4444, 5555] result = self.modbus_module.batch_write_holding_register(self.host, self.port, self.slave_id, 0, values) print(f" batch_write_holding_register(0-4, {values}): {result}") # 验证结果 read_result = self.modbus_module.batch_read_holding_registers(self.host, self.port, self.slave_id, 0, 5) print(f" 验证结果: {read_result}") def test_generic_operations(self): """测试通用读写操作""" print("\n" + "="*50) print("测试通用读写操作") print("="*50) # 测试通用读取 print("\n1. 通用读取测试") for type_str in ['0x', '1x', '3x', '4x']: result = self.modbus_module.read_single_modbus_value(self.host, self.port, self.slave_id, type_str, 0) print(f" read_single_modbus_value(type={type_str}, addr=0): {result}") # 测试通用批量读取 print("\n2. 通用批量读取测试") for type_str in ['0x', '1x', '3x', '4x']: result = self.modbus_module.read_batch_modbus_value(self.host, self.port, self.slave_id, type_str, 0, 3) print(f" read_batch_modbus_value(type={type_str}, addr=0-2): {result}") # 测试通用写入(只测试可写的类型) print("\n3. 通用写入测试") for type_str, value in [('0x', 1), ('4x', 9999)]: result = self.modbus_module.write_single_modbus_value(self.host, self.port, self.slave_id, type_str, 0, value) print(f" write_single_modbus_value(type={type_str}, addr=0, value={value}): {result}") # 测试不可写类型 print("\n4. 测试只读类型写入(应该失败)") for type_str in ['1x', '3x']: result = self.modbus_module.write_single_modbus_value(self.host, self.port, self.slave_id, type_str, 0, 1) print(f" write_single_modbus_value(type={type_str}, 只读): {result}") def test_instance_operations(self): """测试实例化操作""" print("\n" + "="*50) print("测试实例化操作") print("="*50) # 配置实例 print("\n1. 配置Modbus实例") self.modbus_module.configure_modbus_instance("test_plc", self.host, self.port, self.slave_id, "4x") print(" 已配置实例: test_plc") # 通过实例名称读取 print("\n2. 通过实例名称读取") result = self.modbus_module.read_single_modbus_value_by_instance_name("test_plc", 0) print(f" read_single_modbus_value_by_instance_name(test_plc, 0): {result}") result = self.modbus_module.read_batch_modbus_value_by_instance_name("test_plc", 0, 3) print(f" read_batch_modbus_value_by_instance_name(test_plc, 0-2): {result}") # 通过实例名称写入 print("\n3. 通过实例名称写入") result = self.modbus_module.write_single_modbus_value_by_instance_name("test_plc", 0, 8888) print(f" write_single_modbus_value_by_instance_name(test_plc, 0, 8888): {result}") # 验证结果 read_result = self.modbus_module.read_single_modbus_value_by_instance_name("test_plc", 0) print(f" 验证结果: {read_result}") # 批量写入 result = self.modbus_module.write_batch_modbus_value_by_instance_name("test_plc", 1, [7777, 6666, 5555]) print(f" write_batch_modbus_value_by_instance_name(test_plc, 1-3): {result}") # 验证结果 read_result = self.modbus_module.read_batch_modbus_value_by_instance_name("test_plc", 1, 3) print(f" 验证结果: {read_result}") # 测试未配置实例(应该抛出异常) print("\n4. 测试未配置实例(应该抛出异常)") try: self.modbus_module.read_single_modbus_value_by_instance_name("non_exist", 0) except Exception as e: print(f" 预期异常: {e}") def test_data_type_conversion(self): """测试数据类型转换""" print("\n" + "="*50) print("测试数据类型转换") print("="*50) # 测试有符号和无符号整数 print("\n1. 测试有符号/无符号整数转换") # 写入一个大数值(可能被解释为负数) test_value = 65535 # 最大16位无符号数 result = self.modbus_module.write_holding_register(self.host, self.port, self.slave_id, 10, 2, test_value) print(f" 写入无符号整数 {test_value}: {result}") # 以无符号方式读取 result_unsigned = self.modbus_module.read_holding_register(self.host, self.port, self.slave_id, 10, 2) print(f" 无符号读取结果: {result_unsigned}") # 以有符号方式读取 result_signed = self.modbus_module.read_holding_register(self.host, self.port, self.slave_id, 10, 3) print(f" 有符号读取结果: {result_signed}") # 写入负数(有符号) test_value = -1 result = self.modbus_module.write_holding_register(self.host, self.port, self.slave_id, 11, 3, test_value) print(f" 写入有符号整数 {test_value}: {result}") # 以有符号方式读取 result_signed = self.modbus_module.read_holding_register(self.host, self.port, self.slave_id, 11, 3) print(f" 有符号读取结果: {result_signed}") # 以无符号方式读取 result_unsigned = self.modbus_module.read_holding_register(self.host, self.port, self.slave_id, 11, 2) print(f" 无符号读取结果: {result_unsigned}") def run_all_tests(self): """运行所有测试""" print("VWED Modbus TCP 功能测试") print("="*60) try: # 启动测试服务器 self.start_test_server() # 运行各项测试 self.test_basic_read_operations() self.test_batch_read_operations() self.test_write_operations() self.test_batch_write_operations() self.test_generic_operations() self.test_instance_operations() self.test_data_type_conversion() print("\n" + "="*60) print("所有测试完成!") print("="*60) except Exception as e: print(f"\n测试过程中发生错误: {e}") import traceback traceback.print_exc() finally: # 停止测试服务器 self.stop_test_server() def main(): """主函数""" tester = ModbusClientTester() tester.run_all_tests() if __name__ == "__main__": main()