import os
import platform
import socket
import threading
import time
from module.tcp_handler import tcp_handler
from module.file_proc import file_proc
from module.smqtt import smqtt
from module.wlmodbus import wlmodbus
from module.wtopcua import wtopcua

path = os.path.dirname(os.path.abspath(__file__))
dev_sys = platform.system()
resourcesPath = path + os.sep + 'file' + os.sep

def checkin_timer():
    global g_bSendCheckIn
    g_bSendCheckIn = True    
    
def opData_timer():
    global g_bSendOpData
    g_bSendOpData = True

def error_timer():
    global g_bErrorCon
    g_bErrorCon = True

def main_run(source_rm):
    global g_bSendCheckIn
    global g_bSendOpData
    global g_bErrorCon
    global witConfigSep
    while True:
        sendData = {}
        try: 
            if mqtt._start_flag is True:
                if g_bSendCheckIn is True:
                    g_bSendCheckIn = False
                    sendPack = [{"addr":0,"version":"1.02","hardware":"607","local_ip":ip}]
                    mqtt.publish(checkInpub, sendPack) 
                    threading.Timer(24 * 3600, checkin_timer).start()
                if source_rm == 0 or source_rm == 2:
                    if wtlinkOp._is_ok is False and g_bErrorCon is True:
                        g_bErrorCon = False
                        mqtt.publish(ErrorPub, "Serial port is not connected") 
                        threading.Timer(300, error_timer).start()
                    # 读取工况
                    if wtlinkOp._is_ok is True:
                        witConfigSep.acquire() 
                        wtLinkJson = wtLinkData.getWtLinkConfigData()
                        operation = wtLinkJson['config']
                        wtlinkOp.set_rule_data(operation)
                        for index in operation:
                            cmd = index['cmd'] % 256
                            wtlinkOp.readWtLinkOpData(index['id'], cmd, index['name'], index['type'], index['rate'], index['addr'], index['cnt'], index['sensor'])
                        time.sleep(0.1)
                        witConfigSep.release() 
                        sendOpdata = wtlinkOp.getWtLinkOpData()  
                        for key, value in sendOpdata.items():
                            sendData[key] = value 
                if source_rm == 1 or source_rm == 2:
                    wt_opcua.get_opcua_data()
                    sendOpdata = wt_opcua.get_opcua_rm_data()
                    for key, value in sendOpdata.items():
                        sendData[key] = value
                # 发送工况
                sendData['ts'] = round(time.time())
                sendData['addr'] = 1
                sendList = []
                sendList.append(sendData)
                if g_bSendOpData is True:
                    g_bSendOpData = False
                    mqtt.publish(opdataPub, sendList) 
                    if source_rm == 0 or source_rm == 2:
                        wtlinkOp.del_data()
                    threading.Timer(opDataPeriod_s, opData_timer).start()  
            else:
                time.sleep(0.1)
        except Exception as exp:
            print(exp)    
            witConfigSep.release()    
            time.sleep(0.1)

def config_task():
    global witConfigSep
    while True:
        try: 
            if mqtt._start_flag is True:   
                mqtt.wait_rcv_event()
                witConfigSep.acquire()
                config = mqtt.get_rcv_data()    
                wtLinkData.setOpDatafile(resourcesPath + 'WtLinkConfig.json', config)
                witConfigSep.release()
                mqtt.clear_rcv_event()
        except Exception as exp:
            print(exp)  
            witConfigSep.release()
            mqtt.clear_rcv_event()  
            time.sleep(0.1)
        
if __name__ == '__main__':
   
    hostname = socket.gethostname()
    ip = socket.gethostbyname(hostname)
    
    configData = file_proc(resourcesPath + 'Config.json')
    Config = configData.getConfigData()
    wtLinkData = file_proc(resourcesPath + 'WtLinkConfig.json')  
    
    gateway_type = Config.get("gateway", "WTG93RF")
    gateway_sn = Config.get("sn", "12345678")
    g_com = Config.get("COM", "/dev/ttyS0")
    g_baud = Config.get("baud", 9600)
    code_status = Config.get("code_status", 0)
    source_rm = Config.get("source_rm", 0)

    opcuacfg = file_proc(resourcesPath + 'opcuaConfig.json') 

    if code_status == 1:
        time.sleep(60)
        tcp_config = file_proc(resourcesPath + 'modbustcp.json')
        mb_tcp = tcp_handler(tcp_config._data)
    
    mqtt_info = wtLinkData.getMqttInfo()
    opDataPeriod_s = wtLinkData.getOpDataPeriod()

    configsub = 'WT/%s/%s/ConfigRM' %(gateway_type, gateway_sn)
    checkInpub = 'WT/%s/%s/CheckIn' %(gateway_type, gateway_sn)
    opdataPub = 'WT/%s/%s/opData' %(gateway_type, gateway_sn)
    ErrorPub = 'WT/%s/%s/Error' %(gateway_type, gateway_sn)
    
    g_bSendCheckIn = True
    g_bSendOpData = True
    g_bErrorCon = True

    witConfigSep = threading.Lock()

    mqtt = smqtt(mqtt_info)
    mqtt.set_add_topic(configsub)
    mqtt.open_mqtt()

    mqtt_thread = threading.Thread(target=mqtt.internet_task, args=(dev_sys,))
    mqtt_thread.start()

    if source_rm == 0 or source_rm == 2:
        if code_status == 1:
            wtlinkOp = wlmodbus(g_com, g_baud, mb_tcp.data_write_handler)
        else:
            wtlinkOp = wlmodbus(g_com, g_baud, None)
        uart_thread = threading.Thread(target=wtlinkOp.com_connect_task)
        uart_thread.start()
    
    if source_rm == 1 or source_rm == 2:
        cfg_opcua = opcuacfg._data[0]
        opcua_url = cfg_opcua.get("url", "opc.tcp://localhost:4840")
        wt_opcua = wtopcua(opcua_url)
        wt_opcua.get_node_and_feature_from_opcuacfg(cfg_opcua["opcua"])

        
    rcv_thread = threading.Thread(target=config_task)
    rcv_thread.start()

    main_thread = threading.Thread(target=main_run, args=(source_rm,))
    main_thread.start()
    
    # 607需要加上死循环，否则程序就会关闭
    while True:
        time.sleep(300)


    