import struct 
import uart_group_config as uart
import time
import serial
import menu_utils as utils
from modbus_tk import modbus_rtu, modbus_tcp
import json
from mqtt_device import class_comm_mqtt_interface, class_comm_mqtt_thread
from comm_protocol_modbus import class_protocol_modbus_rtu, class_protocol_modbus_tcp
from comm_device import class_comm_device
from device_conf import class_comm_device_config
from menu_group import class_menu_group
from modbus_server import class_modbus_tcp_server
from comm_modbus_device import class_modbus_comm_device
import comm_global
from print_color import *
from mqtt_object import class_mqtt_info_object_group, class_mqtt_info_object
import keyboard
from comm_thread import class_comm_master_thread

# 常量
DEFAULT_COMM_WRITE_TIMEOUT_MS = 500
DEFAULT_MODBUS_SERVER_IP = "127.0.0.1"

# 初始化 MQTT 信息组
mqtt_info_group = class_mqtt_info_object_group()

#初始化 Modbus TCP 服务器
def initialize_modbus_server(slave_addr, ip, port):
    
    return class_modbus_tcp_server(slave_addr=slave_addr, slave_ip=ip, slave_port=port)
#获取 MQTT 服务器配置
def get_mqtt_server_config():
    
    user_name = utils.dict_or_object_get_attr(uart.mqtt_server, "user_name", "admin")
    password = utils.dict_or_object_get_attr(uart.mqtt_server, "password", "admin")
    server = utils.dict_or_object_get_attr(uart.mqtt_server, "remote", "127.0.0.1")
    port = utils.dict_or_object_get_attr(uart.mqtt_server, "port", 1883)
    return user_name, password, server, port
#创建并返回通讯主线程列表
def create_comm_master_thread_list():
    comm_master_thread_list = []

    for object_config_list in uart.comm_thread_config:
        try:
            protocol_name = utils.dict_or_object_get_attr(object_config_list, "protocol", None)
            mode = utils.dict_or_object_get_attr(object_config_list, "mode", None)

            _protocol = None
            if protocol_name == "modbus_rtu":
                _protocol = class_protocol_modbus_rtu("modbus_rtu")
            elif protocol_name == "modbus_tcp":
                _protocol = class_protocol_modbus_tcp("modbus_tcp")

            if _protocol is None or mode is None:
                continue

            _protocol.open(mode)

            _device_list = utils.dict_or_object_get_attr(object_config_list, "device_list", None)
            _device_comm_object_list = []

            if _device_list:
                for device_list_item_dict in _device_list:
                    try:
                        _unique_name = utils.dict_or_object_get_attr(device_list_item_dict, "unique_name", None)
                        _device_name = utils.dict_or_object_get_attr(device_list_item_dict, "device_name", None)
                        _comm_addr = utils.dict_or_object_get_attr(device_list_item_dict, "comm_addr", None)
                        _device_remap = utils.dict_or_object_get_attr(device_list_item_dict, "device_remap", None)

                        if _unique_name is None or _device_name is None or _comm_addr is None or _device_remap is None:
                            continue

                        device_object = __import__(_device_name)

                        config = getattr(device_object, "comm_device_config", None)
                        _func_action_process = getattr(device_object, "func_action_process", None)
                        _func_alarm_query = getattr(device_object, "func_alarm_query", None)

                        if config:
                            _comm_table, _function = config.get_comm_table()
                            _alias_table = config.get_alias_table()

                            _mqtt_info_object = mqtt_info_group.create_mqtt_info_object(device_name=_device_name)
                            _unique_object = class_modbus_comm_device(
                                comm_addr=_comm_addr,
                                comm_table=_comm_table,
                                device_remap=_device_remap,
                                mqtt_thread=global_mqtt_thread,
                                protocol=_protocol,
                                mqtt_info_object=_mqtt_info_object,
                                unique_name=_unique_name,
                                action_process_func=_func_action_process,
                                request_alarm_func=_func_alarm_query,
                                alias_table=_alias_table
                            )

                            global_mqtt_thread.add_unique_object(unique_name=_unique_name, unique_object=_unique_object)
                            _device_comm_object_list.append(_unique_object)
                    except Exception as e:
                        print_error_msg(f"Failed to configure device: {_device_name}. Error: {str(e)}")

                if _device_comm_object_list:
                    _comm_thread = class_comm_master_thread(
                        device_comm_object_list=_device_comm_object_list,
                        thread_name=_unique_name
                    )
                    comm_master_thread_list.append(_comm_thread)
        except Exception as e:
            print_error_msg(f"Failed to configure communication thread. Error: {str(e)}")

    return comm_master_thread_list

#主函数，初始化并运行应用程序
def main():
    
    _slave_addr = 2
    comm_global.g_key_thread.start()

    _modbus_tcp_server = initialize_modbus_server(_slave_addr, DEFAULT_MODBUS_SERVER_IP, 502)

    _user_name, _password, _server, _port = get_mqtt_server_config()

    # 创建并配置 MQTT 线程
    global global_mqtt_thread
    global_mqtt_thread = class_comm_mqtt_thread()
    global_mqtt_thread.set_mqtt_server(
        server=_server, 
        port=_port, 
        keep_alive=60, 
        user_name=_user_name, 
        password=_password
    )

    # 创建通讯主线程
    comm_master_thread_list = create_comm_master_thread_list()

    # 启动 MQTT 和通讯主线程
    global_mqtt_thread.start()
    for comm_thread in comm_master_thread_list:
        comm_thread.start()

    while True:
        # 定期检查 Modbus TCP 连接状态并重连
        if not _modbus_tcp_server.is_connected():
            print("Modbus TCP 服务器断线重连中...")
            _modbus_tcp_server.reconnect()
            time.sleep(1)  # 延迟一段时间后再次检查
        time.sleep(10)  # 每隔 10 秒检查一次连接状态

    # 清理并关闭线程
    global_mqtt_thread.close()
    for comm_thread in comm_master_thread_list:
        comm_thread.close()
    for comm_thread in comm_master_thread_list:
        comm_thread.join()
    global_mqtt_thread.join()

if __name__ == "__main__":
    main()
