import socket
import sys
import time
import threading
import sys
import signal

# 定义回调函数
def myHandler(signum, frame):
    print("接收信号为：", signum)
    exit(0)
# 等待接收 signal.SIGTERM命令
signal.signal(signal.SIGTERM, myHandler)

argv = sys.argv[1:]
tcp_port = int(argv[0])

# PDU 状态锁
map_work_status_lock = threading.Lock()


map_work_status = {
                "total_voltage": 10,
                "total_current": 22.2,
                "total_electricity": 2222.2,
                "contribute_power": 22.1,
                "powerless_power": 11.1,
                "inspecting_power": 22.2,
                "power_factor": 20,
                "temperature": 23.2,
                "humidity": 10.3,
                "St0": 1,
                "St1": 1,
                "St2": 1,
                "St3": 1,
                "St4": 1,
                "St5": 1,
                "St6": 1,
                "St7": 1,
                "Cur0": 10,
                "Cur1": 10,
                "Cur2": 10,
                "Cur3": 10,
                "Cur4": 10,
                "Cur5": 10,
                "Cur6": 10,
                "Cur7": 10,
                "Pow0": 5,
                "Pow1": 5,
                "Pow2": 5,
                "Pow3": 5,
                "Pow4": 5,
                "Pow5": 5,
                "Pow6": 5,
                "Pow7": 5,
                }
"""字段中文名"""
map_name_chg = {
                "total_voltage": "总电压",
                "total_current": "总电流",
                "total_electricity": "总电能",
                "contribute_power": "有功功率",
                "powerless_power": "无功功率",
                "inspecting_power": "视在功率",
                "power_factor": "功率因数",
                "temperature": "温度值",
                "humidity": "湿度值",
                "St0": "电源输出端口1",
                "St1": "电源输出端口2",
                "St2": "电源输出端口3",
                "St3": "电源输出端口4",
                "St4": "电源输出端口5",
                "St5": "电源输出端口6",
                "St6": "电源输出端口7",
                "St7": "电源输出端口8",
                "Cur0": "端口1电流",
                "Cur1": "端口2电流",
                "Cur2": "端口3电流",
                "Cur3": "端口4电流",
                "Cur4": "端口5电流",
                "Cur5": "端口6电流",
                "Cur6": "端口7电流",
                "Cur7": "端口8电流",
                "Pow0": "端口1功率",
                "Pow1": "端口2功率",
                "Pow2": "端口3功率",
                "Pow3": "端口4功率",
                "Pow4": "端口5功率",
                "Pow5": "端口6功率",
                "Pow6": "端口7功率",
                "Pow7": "端口8功率",
                }
packet_head = \
"************************************************************\r\n\
*                                                          *\r\n\
*                                                          *\r\n\
*     Power Outlet Port Parameters and Status              *\r\n\
*                                                          *\r\n\
*                                                          *\r\n\
************************************************************\r\n\
>\r\n\
>\r\n\
>\r\n\
************************************************************\r\n\
*     Power Outlet Port Status                             *\r\n\
************************************************************\r\n\
Port |       Name | status | current | power | \r\n\
-----+------------+--------+---------+--------\r\n\
"

PDU_total_info_head = \
" \
>\r\n\
>\r\n\
**********************************************************************************************\r\n\
*                                  Total Info                                                *\r\n\
**********************************************************************************************\r\n\
Voltage | Current | Electricity | Contribute | Powerless | Inspecting | temperature | humidity\r\n\
--------+---------+-------------+------------+-----------+------------+-------------+----------\r\n\
"

def packet_string(tem_packet_str: str = "") -> str:
    packet_info = ""
    for num in range(0, 8):
        status_key = "St" + str(num)
        current_key = "Cur" + str(num)
        power_key = "Pow" + str(num)
        packet_info += f"  {str(num)}  |  Outlet {str(num)}  |    {map_work_status[status_key]}   |   {map_work_status[current_key]}    |    {map_work_status[power_key]}  \r\n"
    tem_packet_str = packet_head + packet_info

    str1 = f'   {map_work_status["total_voltage"]}   |  {map_work_status["total_current"]}   |    {map_work_status["total_electricity"]}   |    {map_work_status["contribute_power"]}    |\
    {map_work_status["powerless_power"]}   |    {map_work_status["inspecting_power"]}    |    {map_work_status["temperature"]}     |    {map_work_status["humidity"]}  '

    tem_packet_str += PDU_total_info_head + str1
    return tem_packet_str


print("初始化数据：\r\n" + packet_string(""))

# 创建tcp通信服务
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
tcp_server_socket.bind(('0.0.0.0', tcp_port))
tcp_server_socket.listen(1)
client_socket, addr = tcp_server_socket.accept()

# tcp 连接标志
TCP_LINK_STATUS = 1


def change_info_to_hex() -> bytes:
    packet_head = bytes([0xAA, 0x43, 0x01, 0xFF, 0x00])
    packet_tail = bytes([0x00, 0x00, 0x2E, 0xEC])
    packet_info = bytearray()

    # total voltage
    value = int(float(map_work_status["total_voltage"]) * 10)
    value_bytes = value.to_bytes(2, "big")
    packet_info = packet_head + value_bytes

    # total current
    value = int(float(map_work_status["total_current"]) * 10)
    value_bytes = value.to_bytes(2, "big")
    packet_info += value_bytes

    # total electricity
    value = int(float(map_work_status["total_electricity"]) * 10)
    value_bytes = value.to_bytes(4, "big")
    packet_info += value_bytes

    # contribute power
    value = int(float(map_work_status["contribute_power"]) * 10)
    value_bytes = value.to_bytes(2, "big")
    packet_info += value_bytes
    
    # powerless power
    value = int(float(map_work_status["powerless_power"]) * 10)
    value_bytes = value.to_bytes(2, "big")
    packet_info += value_bytes

    # inspecting power
    value = int(float(map_work_status["inspecting_power"]) * 10)
    value_bytes = value.to_bytes(2, "big")
    packet_info += value_bytes

    # power factor
    value = int(float(map_work_status["power_factor"]) * 10)
    value_bytes = value.to_bytes(2, "big")
    packet_info += value_bytes

    # temperature
    value = int(float(map_work_status["temperature"]) * 10)
    value_bytes = value.to_bytes(2, "big")
    packet_info += value_bytes

    # humidity
    value = int(float(map_work_status["humidity"]) * 10)
    value_bytes = value.to_bytes(2, "big")
    packet_info += value_bytes

    # power number
    packet_info += bytes([0x08])

    for num in range(0, 8):
        status_key = "St" + str(num)
        current_key = "Cur" + str(num)
        power_key = "Pow" + str(num)

        current_value = int(float(map_work_status[current_key]) * 10)
        current_value_bytes = current_value.to_bytes(1, "big")
        packet_info += current_value_bytes + bytes([0x00])

        power_value = int(float(map_work_status[power_key]) * 10)
        power_value_bytes = power_value.to_bytes(1, "big")
        packet_info += power_value_bytes + bytes([0x00])

        status_value = int(map_work_status[status_key])
        status_value_bytes = status_value.to_bytes(1, "big")
        packet_info += status_value_bytes

    packet_info += packet_tail
    
    return packet_info


def HY_TOWEPDU_Pshow_callback (recv_cmd: bytes) -> None:
    if (len(recv_cmd) != 7):
        print(f"This cmd len cant show info of the power, the len is {len(recv_cmd)}")
        return

    map_work_status_lock.acquire()

    # tem_packet_str = packet_string(tem_packet_str)
    print(packet_string(""))

    tem_packet_str = change_info_to_hex()

    if (TCP_LINK_STATUS != 0):
        client_socket.send(tem_packet_str)
    
    map_work_status_lock.release()


def HY_TOWEPDU_SetOutPort_callback (recv_cmd: bytes) -> None:
    if (len(recv_cmd) != 9):
        print(f"This cmd len cant show info of the power, the len is {len(recv_cmd)}")
        return

    # 00 - 07
    key = f'St{int(recv_cmd[5])}'
    value = int(recv_cmd[6])
    map_work_status_lock.acquire()
    map_work_status[key] = value
    map_work_status_lock.release()

    client_socket.send(bytes([0xAA, 0x07, 0x02, 0x01, 0x00, 0x07, 0x00, 0x00, 0xED, 0xEF]))


map_call_back_fun = {
    "5504": HY_TOWEPDU_Pshow_callback,
    "5506": HY_TOWEPDU_SetOutPort_callback
}

def send_status_handle() -> None:
    print("线程1")
    cont = 0
    cont_print = 0
    max_cont = 10000
    while max_cont:
        map_work_status_lock.acquire()

        tem_status_str = ""
        for num in range(0, 8):
            key = "St" + str(num)
            tem_status_str += f"  {str(num)}  |  Outlet {str(num)}  |    {map_work_status[key]}   |\r\n"

        map_work_status_lock.release()

        cont += 1
        if (cont > 2 and TCP_LINK_STATUS):
            cont_print += 1
            
            print("=============== 打印当前模拟设备状态 ================= ", cont_print)
            print(tem_status_str)
            cont = 0
        time.sleep(1)


def recv_set_CMD_handle() -> None:
    print("线程2")
    global TCP_LINK_STATUS
    global client_socket
    while True:
        data = client_socket.recv(1024)
        if (len(data) > 0):
            rec_str = data[0: 2]
            cmd = rec_str.hex()
            print(f"cmd =======> {cmd}")
                
            if (cmd in map_call_back_fun):
                map_call_back_fun[cmd](data)
            else:
                print(f'收到位置报文 ====> {data.hex()}')
        else:
            TCP_LINK_STATUS = 0
            print("连接断开，等待接入")
            client_socket.close()
            client_socket, addr = tcp_server_socket.accept()
            TCP_LINK_STATUS = 1
            print(addr)
            time.sleep(1)


if __name__ == '__main__':
    tr1 = threading.Thread(target=send_status_handle)
    tr2 = threading.Thread(target=recv_set_CMD_handle)
    tr1.start()
    tr2.start()

