#!/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()