from device_conf import class_comm_device_config
import comm_remap as remap
import menu_page
from comm_device import class_comm_device
from comm_thread import class_comm_master_thread
from menu_base import class_device_menu
import menu_utils as utils
import comm_global
from enum import Enum
import math
from comm_modbus_device import class_modbus_comm_device
from comm_protocol_modbus import class_protocol_modbus

from enum import Enum

class Alarm(Enum) :
    NO_ERR = 0,                                     #无故阿
    ERR_CREEPAGE_LOCK = 1,                                #漏电报警
    ERR_VOLTAGE_LOW = 2,                                #欠压报警
    ERR_OVER_CURRENT = 3,                                #过流保护
    ERR_SHORT_CURRENT = 4,                                #短路保护
    ERR_CREEPAGE_SELECT = 5,                            #选择性报?
    ERR_UNBANLANCE_CURRENT = 6,                         #三相不平衡报?
    ERR_FLASH_FAIL = 7,                                 #FLASH无法写入
    ERR_CREEPAGE_ACTIVE = 8,                            #漏电动作
    ERR_BREAK_PHASE = 9,                                #断相保护动作
    ERR_VOLTAGE_BREAK_PHASE = 10,                        #电压断相        
    ERR_GAS_LOCK = 11,                                    #瓦斯闭锁
    ERR_WIND_MOTOR_LOCK = 12,                            #风电闭锁
    ERR_VOLTAGE_OVER = 13,                                #过压报警
    ERR_SHORT_PHASE = 14,                                #相敏短路
    ERR_WATCH_DOG = 15,                                  #看门狗保房
    ERR_SWITCH_FAIL = 16,                                #开关粘轿
    ERR_SWITCH_THROUGH = 17,                             #开关击?
    ERR_SWITCH_ON_FAIL = 18,                                #开关合闸失?
    ERR_COMM_FAIL = 19,                                     #通讯故障
    ERR_CREEPAGE_SELECT2 = 20,                             #选择性报?
    ERR_TEMP_IO_HIGH = 21,                                #IO口温度过驿
    ERR_SHORT_CURRENT_SIGNAL = 22,                        #信号电流短路
    ERR_REMOTE_OFF = 23,                                 #远方分励
    ERR_REPAIR = 24,                                     #维修状?
    ERR_TEMP_ALARM = 25,                                 #温度报警
    ERR_QUICK_CREEPAGE_ACT = 26,                         #快速漏电动仿
    ERR_GB_LEEK_SHORT = 27,                              #高爆绝缘短路
    ERR_GB_LEEK_BREAK = 28,                              #高爆绝缘断路
    ERR_YB_LOW_VOLTAGE_FAIL = 29,                        #移变低压侧失?
    ERR_YB_LOW_VOLTAGE_UNREADY = 30,                     #移变低压侧未准备?
    ERR_WS_FREQ_FAIL = 31,                               #瓦斯浓度超标
    ERR_HIGH_LOW_LOCK = 32,                              #高低压联钿
    ERR_MOTOR_ROTATE_LOCK = 33,                          #电机堵转
    ERR_FIX_TIME_OVER_CURRENT = 34,                      #定时限过泿
    ERR_FIX_TIME_SHORT_CURRENT = 35,                     #定时限短?
    ERR_PHASE_ERROR = 36,                                #相序故障
    ERR_UNDER_LOAD = 37,                                 #欠载保护
    ERR_PHASE_UNMATCH = 38,                              #互感器反?
    ERR_EXTERNAL_ALARM = 39,                             #外部故障
    ERR_SENSOR_LOSS = 40,                                #水位传感器未?
    ERR_ROTOR_SLOW = 41,                                 
    ERR_ROTOR_LOCK = 42, 
    ERR_POWER_LOSS = 43,                                 #系统断电
    ERR_RSV1 = 44,
    ERR_RSV2 = 45,
    ERR_RSV3 = 46,
    ERR_RSV4 = 47,
    ERR_RSV5 = 48,
    ERR_RSV6 = 49,
    ERR_RSV7 = 50,
    ERR_USER_ALARM1 = 51,                                #=50, 用户自定义故阿
    ERR_USER_ALARM2 = 52,                                #=51,用户自定义故阿
    ERR_USER_ALARM3 = 53,#=52,用户自定义故阿
    ERR_USER_ALARM4 = 54,                                #=53,用户自定义故阿
    ERR_GB_LIGHT_THREAD_SON_LOSS = 55,
    ERR_GB_LIGHT_THREAD_BROTHER_LOSS = 56,
    ERR_GB_LIGHT_MODULE_LOSS = 57,
    ERR_GB_FORCE_LEEK_OFF = 58,
    ERR_GB_FORCE_SHORT_OFF = 58,
    ERR_GB_CREEPAGE_SELECT = 59,                        #选择性报警
    ERR_SWITCH_OUT_POSITION = 60,        
    ERR_DZM_CREEPAGE_ACTIVE = 61,
    ERR_OIL_PRESSURE_SENSOR_FAIL = 62,
    ERR_FREQ_SENSOR_EXCEED = 63,
    ERR_FREQ_SENSOR_FAIL = 64,
    ERR_ANALOG_SENSOR_EXCEED = 65,
    ERR_ANALOG_SENSOR_FAIL = 66,
    ERR_VOLTAGE_LOSS = 67,
    ERR_SPEED_LOSS = 68,
    ERR_GB_ZERO_VOLT_OVER = 69,                         #零序过压
    ERR_PT_BREAK = 70,
    ERR_CT_BREAK = 71,
    ERR_ZERO_OVER_VOLTAGE = 72,
    ERR_ZERO_OVER_CURRENT = 73,
    ERR_GAS_WARNING = 74,     
    ERR_TEMP_WARNING = 75,
    ERR_COMM_LOSS = 76,
    ERR_CAR_FAIL = 77,
    ERR_WATER_LOW = 78,
    ERR_SWITCH_DIDAO_IN_POSITION = 79,
    ERR_SWITCH_DIDAO_MID_POSITION =80,
    ERR_GB_CREEPAGE_SELECT_5 = 81,   #5次谐波选漏
    ERR_FLUX_LOCK = 82,
    ERR_GLOBAL_OIL_TEMP_LOCK = 83,
    ERR_GLOBAL_WATER_PRESSURE_LOCK = 84,
    ERR_GLOBAL_WATER_LEVEL_LOCK = 85,
    ERR_GLOBAL_CURRENT_SENSOR_LOSS = 86,
    ERR_GLOBAL_GAS_PERCENTAGE_LOCK = 87,
    ERR_GLOBAL_GAS_SENSOR_LOSS = 88,
    ERR_MEASURE_OVER_CURRENT = 89,                    #测量回路过流保护
    ERR_CREAPGE_BREAK = 90,
    ERR_REMOTE_CREAPGE_TEST_FAIL = 91,
    ERR_REMOTE_CREAPGE_TEST_SUCCESS = 92,
    ERR_ISOLATE_ALARM = 93,
    ERR_DIDAO_FAIL = 94,
    ERR_EARTH_NOT_READY = 95,
    ERR_ISOLATE_NOT_READY = 96,
    

alias_table = [
    {"alias_bool": {0:"关闭", 1:"打开"}},
    {"alias_voltage": {0:"3300V", 1:"6000V", 2:"10000V"}},
    {"alias_parity": {0: "无校验", 1: "奇校验", 2: "偶校验"}},
    {"alias_baud": {0: "1200", 1: "2400", 2: "4800", 3: "9600", 4:"19200", 5:"38400", 6:"51200", 7:"115200"}},
    {"alias_input": {0: "常开", 1: "常闭"}},
    {"alias_onoff": {0: "分闸", 1: "合闸"}},
    {"alias_alarm": {0: "无故障", 1: "定时限短路", 2 : "定时限过流1段", 3: "定时限过流2段"}},
    {"alias_test":  {0: "测试", 1: "动作"}},
]

mqtt_pack_alarm = [
    {
        "name": "AlarmType",
		"addr": "8138",
        "alias": "alias_test"
	},
]

mqtt_pack_measure = [
    {
        "name": "OnStatus",
		"addr": "8162.0",
        "alias": "alias_onoff",
        "remap_addr": remap.COMM_REMAP_MEASURE_SWITCH_STATUS,
        "scale": 1.0,
        "format": "%1.0f",
        "mqtt" : "OnStatus",
	},
    {
        "name": "AlarmStatus",
		"addr": "8166",
        "alias": "alias_alarm",
        "remap_addr": remap.COMM_REMAP_MEASURE_SWITCH_ALARM,
        "scale": 1.0,
        "format": "%1.0f",
        "mqtt" : "AlarmStatus",
	},
    {
        "name": "Ia",
		"unit": "A",
		"addr": "8156",
		"format": "%1.0f",
        "remap_addr": remap.COMM_REMAP_MEASURE_FLOAT_IA,
        "mqtt" : "Ia",
	},
    {
        "name": "Ib",
		"unit": "A",
		"addr": "8157",
		"format": "%1.0f",
        "remap_addr": remap.COMM_REMAP_MEASURE_FLOAT_IB,
        "mqtt" : "Ib",
	},
    {
        "name": "Ic",
		"unit": "A",
		"addr": "8158",
		"format": "%1.0f",
        "remap_addr": remap.COMM_REMAP_MEASURE_FLOAT_IC,
        "mqtt" : "Ic",
	},
    {
        "name": "Uab",
		"unit": "V",
		"addr": "8153",
		"format": "%1.0f",
        "remap_addr": remap.COMM_REMAP_MEASURE_FLOAT_UAB,
        "mqtt" : "Uab",
	},
    {
        "name": "Ubc",
		"unit": "V",
		"addr": "8154",
		"format": "%1.0f",
        "remap_addr": remap.COMM_REMAP_MEASURE_FLOAT_UBC,
        "mqtt" : "Ubc",
	},
    {
        "name": "Uca",
		"unit": "V",
		"addr": "8155",
		"format": "%1.0f",
        "remap_addr": remap.COMM_REMAP_MEASURE_FLOAT_UCA,
        "mqtt" : "Uca",
	},
    {
        "name": "Uo",
		"unit": "V",
		"addr": "8152",
		"format": "%1.0f",
        "remap_addr": remap.COMM_REMAP_MEASURE_FLOAT_UO,
        "mqtt" : "Uo",
	}, 
    {
        "name": "Io",
		"unit": "mA",
		"addr": "8151",
		"format": "%1.0f",
        "scale" : 1.0,
        "remap_addr" : remap.COMM_REMAP_MEASURE_FLOAT_IO,
        "mqtt" : "Io",
	}, 
    {
        "name": "Ro",
		"unit": "K",
		"addr": "8150",
        "scale": 0.1,
		"format": "%2.1f",
        "remap_addr": remap.COMM_REMAP_MEASURE_FLOAT_RO,
        "mqtt" : "Ro",
	}, 
]

mqtt_pack_alarm = [
    {
        "name": "AlarmType",
		"addr": "8138",
        "alias": "alias_test"
	},
]


modbus_comm_table = [ 
    {"name":"status",     "comm_str" : "8162#4",   "reg_addr":8162,   "reg_count":4,      "cycle": 100},
    {"name":"alarm",      "comm_str" : "8120#10",      "reg_addr":8120,   "reg_count":10,     "cycle": 0,    "mqtt_pack": mqtt_pack_alarm},
    {"name":"measure",    "comm_str" : "8139#35",      "reg_addr":8139,   "reg_count":35,     "cycle": 200,  "mqtt_pack": mqtt_pack_measure},
    {"name":"comm_cmd",   "comm_str" : "100618#32",    "reg_addr":100618, "reg_count":32,     "cycle": 0},
    #{"name":"key_group",     "comm_str" : "8162#4",   "reg_addr":1000,   "reg_count":8,      "cycle": 20},
    {"name":"para_group", "comm_str" : "2000#10",      "reg_addr":2000,   "reg_count":10,     "cycle": 0},
    {"name":"time_group", "comm_str" : "2300#6",      "reg_addr":2300,   "reg_count":6,      "cycle": 500},
    {"name":"protect_group", "comm_str" : "8174#46",   "reg_addr":8174,   "reg_count":46,     "cycle": 0},
    #{"name":"ip_addr_group", "comm_str" : "8410#6",   "reg_addr":8410,   "reg_count":6,      "cycle": 0},
    #{"name":"ip_group",      "comm_str" : "8271#8",   "reg_addr":8271,   "reg_count":8,      "cycle": 0},
    {"name":"inter_group",   "comm_str" : "8240#10",   "reg_addr":8240,   "reg_count":10,     "cycle": 0},
]

def func_comm_table_trigger_check(object_comm_table, comm_table_item) :

    if not hasattr(comm_table_item, "name"):
        return False

    #添加on_status 与 prev_on_status, 用于判断合闸状态是否发送变化
    if not hasattr(object_comm_table, 'prev_on_status'):
        object_comm_table.prev_on_status = False

    if not hasattr(object_comm_table, 'prev_alarm_id'):
        object_comm_table.prev_alarm_id = 0

    onstatus = object_comm_table.read_register_u16(8162) 
    if onstatus == None :
        return False
    onstatus = onstatus & 0x1
    alarm_id = object_comm_table.read_register_u16(8166) 
    if alarm_id == None :
        return False
    
    prev_on_status = object_comm_table.prev_on_status
    prev_alarm_id = object_comm_table.prev_alarm_id
    
    if prev_on_status != onstatus :
        #合分闸状态发生改变, 触发"measure"通讯组
        if comm_table_item.name == "measure" :
            object_comm_table.prev_on_status =onstatus
            return True

    if prev_alarm_id != alarm_id :
        #故障状态发生改变, 触发"alarm"通讯组
        if comm_table_item.name == "alarm" :
            object_comm_table.prev_alarm_id = alarm_id
            return True

    return False

menu_current = [                                             #菜单表[menu_current],存储菜单项属性字典<>
    {
        "name": "额定电流",
		"unit": "A",
		"addr": "2000",
        "scale" : 0.1,
		"format": "%05.1f",
        "min" : 1.0,
        "max" : 400.0,
        "mqtt" : "Ie",
        "remap_addr": remap.COMM_REMAP_PARA_CURRENT_RATE,
	},
	{
        "name": "短路倍数",
        "unit": "倍",
        "scale" : 0.01,
        "format": "%05.2f",
        "addr": "2001",
        "mqtt" : "ShortIe",
        "remap_addr": remap.COMM_REMAP_PARA_CURRENT_SHORT_MUL,
	},
    {
        "name": "退出",
        "action": "exit",
	},
]

CONVERT_FROM_ORIGIN_VALUE_TO_REMAP_VALUE  = 0
CONVERT_FROM_REMAP_VALUE_TO_ORIGIN_VALUE  = 0

def func_rate_voltage_convert(value, type) :
    if type == CONVERT_FROM_ORIGIN_VALUE_TO_REMAP_VALUE :
        if value == 0 :
            result = 380
        elif value == 1 :
            result = 660
        else :
            result = 1140
    else :
        if value == 380 :
            result = 0
        elif value == 660 :
            result = 1
        else :
            result = 2
    return result

menu_voltage = [
    {
        "name": "额定电压",
		"addr": "8211",
		"alias": "alias_voltage",
        "mqtt" : "Ue",
        "remap_addr": remap.COMM_REMAP_PARA_RATE_VOLTAGE,
        "convert": func_rate_voltage_convert,
	},
	{
        "name": "欠压比值",
        "unit": "Ue",
        "addr": "2004", 
        "scale" : 0.001,
        "format": "%05.3f",
        "mqtt" : "UnderVoltageRatio",
        "remap_addr": remap.COMM_REMAP_PARA_LOW_VOLTAGE_RATIO,
	},
	{
        "name": "欠压延时",
        "unit": "s",
        "addr": "2005", 
        "scale" : 0.1,
        "format": "%05.1f",
        "mqtt" : "UnderVoltageDelay",
        "remap_addr": remap.COMM_REMAP_PARA_LOW_VOLTAGE_DELAY,
	},
    {
        "name": "退出",
        "action": "exit",
	},
]

menu_alarm = [
    {
        "name": "故障查询",
        "action": "alarm_query",
	},
    {
        "name": "故障清除",
        "action": "alarm_clear",
	},
    {
        "name": "退出",
        "action": "exit",
	},
]

# 缺省action处理函数
def func_action_process(device : class_modbus_comm_device, menu_item = None) :
    action_str = utils.dict_or_object_get_attr(menu_item, "action", " ")
    mqtt_name  = utils.dict_or_object_get_attr(menu_item, "mqtt", " ")
    if action_str == "write_bit" :
        comm_str = utils.dict_or_object_get_attr(menu_item, "addr", " ")
        reg_addr, bit, reg_count = utils.comm_str_unpack(comm_str)

        if reg_count == 1:
            command_value = [1]
            result = device.write_bit_register(reg_addr, command_value)
            if device.mqtt_thread :
                device.mqtt_thread.publish("response/action/" + device.unique_name, '{"name" : "%s", "result" : %d}'%(mqtt_name, result))  

menu_switch_cmd = [
    {
        "name":   "通讯合闸",
        "action": "write_bit",
        "addr" :  "100618",
        "mqtt" :  "SwitchOn",
	},
    {
        "name":   "通讯分闸",
        "action": "write_bit",
        "addr" :  "100619",
        "mqtt" :  "SwitchOff",
	},
    {
        "name":   "通讯复位",
        "action": "write_bit",
        "addr" :  "100620",
        "mqtt" :  "SwitchRst",
	},
]

menu_test = [
    {
        "name": "短路试验",
        "action": "write_bit",
        "addr" : "100628",
        "mqtt" : "TestShort",
	},
    {
        "name": "漏电试验",
        "action": "write_bit",
        "addr" : "100629",
        "mqtt" : "TestIsolation",
	},
    {
        "name": "退出",
        "action": "exit",
	},
]

menu_protect_set = [
	{
        "name": "短路保护",
        "alias": "alias_bool",
        "addr": "8192.1", 
	},
	{
        "name": "不平衡保护",
        "alias": "alias_bool",
        "addr": "8192.2", 
	},
	{
        "name": "反时限过流",
        "alias": "alias_bool",
        "addr": "8192.3", 
	},
	{
        "name": "过压保护",
        "alias": "alias_bool",
        "addr": "8174.0", 
	},
	{
        "name": "欠压保护",
        "alias": "alias_bool",
        "addr": "8174.1", 
	},
   	{
        "name": "瓦斯闭锁",
        "alias": "alias_bool",
        "addr": "8174.13", 
	},
 	{
        "name": "电压断相",
        "alias": "alias_bool",
        "addr": "8174.2", 
	},
 	{
        "name": "相序保护",
        "alias": "alias_bool",
        "addr": "8174.3", 
	},
 	{
        "name": "漏电动作",
        "alias": "alias_bool",
        "addr": "8174.6", 
	},
 	{
        "name": "选漏保护",
        "alias": "alias_bool",
        "addr": "8174.7", 
	},
   	{
        "name": "风电闭锁",
        "alias": "alias_bool",
        "addr": "8175.0", 
	},

    {
        "name": "退出",
        "action": "exit",
	},
]

menu_comm_set = [
	{
        "name": "485波特率",
        "alias": "alias_baud",
        "addr": "8188", 
	},
	{
        "name": "485校验",
        "alias": "alias_parity",
        "addr": "8194", 
	},
    {
        "name": "IP设置",
        "addr": "8410#2", 
        "action": "ip",
	},
    {
        "name": "IP网关",
        "addr": "8412#2", 
        "action": "ip",
	},
    {
        "name": "IP掩码",
        "addr": "8414#2",
        "action": "ip",
	},
    {
        "name": "退出",
        "action": "exit",
	},
]

menu_system = [
   	{
        "name": "瓦斯触点",
        "alias": "alias_input",
        "addr": "8190", 
	},
   	{
        "name": "风电触点",
        "alias": "alias_input",
        "addr": "8248", 
	},
    {
        "name": "系统日期",
        "addr": "2300#3", 
        "action": "date",
	},
    {
        "name": "当前时间",
        "addr": "2303#3", 
        "action": "time",
	},
    {
        "name": "退出",
        "action": "exit",
	},
]

Menu_Top = [
    {
        "name": "电流设置",
        "sub_menu": "menu_current",
	},
    {
        "name": "电压设置",
        "sub_menu": "menu_voltage"
	},
    {
        "name": "系统设置",
        "sub_menu": "menu_system"
	},
    {
        "name": "保护设置",
        "sub_menu": "menu_protect_set"
    },
    {
        "name": "通讯设置",
        "sub_menu": "menu_comm_set"
    },
    {
        "name": "故障查询",
        "sub_menu": "menu_alarm"
    },
    {
        "name": "保护试验",
        "sub_menu": "menu_test"
    },
    {
        "name": "退出",
        "action": "exit",
	},
]

menu_caption = [
   {"name" : "Menu_Top",            "menu" : Menu_Top,      "next" : Menu_Top,      "prev" : Menu_Top,      "caption": "主菜单",    "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "menu_current",        "menu" : menu_current,  "next" : menu_current,  "prev" : menu_current,  "caption": "电流设置",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "menu_voltage",        "menu" : menu_voltage,  "next" : menu_voltage,  "prev" : menu_voltage,  "caption": "电压设置",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "menu_system",         "menu" : menu_system,  "next" : menu_system,  "prev" : menu_system,  "caption": "系统设置",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "menu_protect_set",    "menu" : menu_protect_set,  "next" : menu_protect_set,  "prev" : menu_protect_set,  "caption": "保护设置",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "menu_comm_set",       "menu" : menu_comm_set,  "next" : menu_comm_set,  "prev" : menu_comm_set,  "caption": "通讯设置",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "menu_alarm",          "menu" : menu_alarm,    "next" : menu_alarm,  "prev" : menu_alarm,  "caption": "故障查询",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "menu_test",           "menu" : menu_test,     "next" : menu_test,  "prev" : menu_test,  "caption": "保护试验",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "mqtt_pack_alarm",     "menu" : mqtt_pack_alarm,     "next" : mqtt_pack_alarm,  "prev" : mqtt_pack_alarm,  "caption": "报警数据",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "mqtt_pack_measure",   "menu" : mqtt_pack_measure,     "next" : mqtt_pack_measure,  "prev" : mqtt_pack_measure,  "caption": "测量数据",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
   {"name" : "menu_switch_cmd",     "menu" : menu_switch_cmd,     "next" : menu_switch_cmd,  "prev" : menu_switch_cmd,  "caption": "通讯命令",  "page" : menu_page.KUNLUN_GRAOUP_PAGE_MENU,  "max_items" : 8},
]

class class_9TE_comm_device_config(class_comm_device_config):
    def __init__(self):
        class_comm_device_config.__init__(self)
        pass
    
    #@override get_alias_table
    def get_alias_table(self) :
        return alias_table

    #@override get_comm_table
    def get_comm_table(self) :
        return modbus_comm_table, func_comm_table_trigger_check

    #@override get_menu_top
    def get_menu_top(self) :
        return Menu_Top

    #@override menu_get_display_page
    def menu_get_display_page(self, active_menu):
        return menu_page.KUNLUN_GRAOUP_PAGE_MENU

    def get_menu_caption_info(self) :
        return menu_caption

    def modify_menu_item(self, menu_item, value) :
        alias_name = utils.dict_or_object_get_attr(menu_item, "alias", None)
        if isinstance(alias_name, Enum) :
            alias_name = alias_name.name

        is_alias = False
        if alias_name != None :
            is_alias = True
            value = math.round(value)   #别名值需要为整数
        
        return False


#comm_device_config的名字不要更改, 创建通讯配置类
comm_device_config = class_9TE_comm_device_config()
