extends Panel

signal signal_on_start_timer_03()
signal signal_on_modul_um()

var timer: Timer = Timer.new()
var timer_03: Timer = Timer.new()
var node_cell_ind: Array
var um_cell_ind: Array
var count_cell: int
var past_pribor: int
var logger: Node
var array_pow_1: Array = []
var array_pow_2: Array = []
var count_packet:int = 0
var flag_control_add: bool = false
var flag_fs_1_ready: bool = false
var flag_fs_2_ready: bool = false
var flag_fs_3_ready: bool = false
var flag_dkm: bool = false
var flag_ug: bool = false
var flag_yau: bool = false
var flag_modul_on_1: bool = false
var flag_modul_on_2: bool = false
var flag_modul_litera_1: bool = false
var flag_start: bool = false
var flag_continue_control: bool = false
var prep_set_ug: int = 0


class Logger extends Node:
    var log_level: String = "INFO"
    var log_array: Node

    func _init(log_node: RichTextLabel = null):
        log_array = log_node
        log_array.text = ""

    func get_current_datetime_string() -> String:
        var time = Time.get_datetime_dict_from_system()
        return ' [%02d-%02d-%04d %02d:%02d] ' % [time['day'], time['month'], time['year'], time['hour'], time['minute']]

    func _add_message(level: String, message: String) -> void:
        if (level == "INFO" and log_level in ["INFO", "DEBUG"]) or \
        (level == "WARNING" and log_level in ["WARNING", "INFO", "DEBUG"]) or \
        (level == "ERROR"):
            var datetime_string = get_current_datetime_string()
            log_array.text += "[" + level + "]" + datetime_string + " " + message + "\n"

    func info(message: String) -> void:
        _add_message("INFO", message)

    func warning(message: String) -> void:
        _add_message("WARNING", message)

    func error(message: String) -> void:
        _add_message("ERROR", message)


func _ready() -> void:
    Network.unit_fs_1.connect("data_fs", Callable(self, "_on_data_fs").bind('ФС-1'))
    Network.unit_fs_2.connect("data_fs", Callable(self, "_on_data_fs").bind('ФС-2'))
    Network.unit_fs_3.connect("data_fs", Callable(self, "_on_data_fs").bind('ФС-3'))

    self.add_child(timer)
    self.add_child(timer_03)
    timer.connect('timeout', Callable(self, '_on_timer'))
    self.get_parent().get_child(2).connect('signal_FS_is_ready', Callable(self, '_on_fs_status'))
    timer_03.connect('timeout', Callable(self, '_on_timer_03'))
    self.connect('signal_on_start_timer_03', Callable(self, '_on_start_timer_03'))
    Network.connect('yau_receive', Callable(self, '_on_yau_received'))
    Network.connect('yau_feedback_receive', Callable(self, '_on_yau_feedback_receive'))
    self.connect('signal_on_modul_um', Callable(self, '_on_modul_um'))

    node_cell_ind = [
        $soc_y5/yau_07b,
        $soc_y5/ems_g,
        $soc_y5/ug,
        $soc_y5/ukp_1,
        $soc_y5/ukp_2,

        $soc_P1/MAA_1,
        $soc_P1/MAA_2,
        $soc_P1/IP9_50_2,
        $soc_P1/IP9_50_1,
        $soc_P1/IP12_50,

        $soc_P2/IP9_50,
        $soc_P2/IP12_50,

        $soc_y5/IP5_25,

        $Kasseta_FS/ref_A3,
        $Kasseta_FS/ref_A1,
        $Kasseta_FS/ref_A2,
        $Kasseta_FS/ref_A4,
        $Kasseta_FS/Block_FS_PRD_K,
        $Kasseta_FS/FS_PRD_K,

        $soc_DKM/DKM_1,
        $soc_DKM/DKM_2,
        $soc_DKM/DKM_3,
        ]
    count_cell = len(node_cell_ind)
    um_cell_ind = [
        $socket_ym_lb/blok_ym_1,
        $socket_ym_lb/blok_ym_2,
        $socket_ym_lb/blok_ym_3,
        $socket_ym_lb/blok_ym_4,
        $socket_ym_lb/blok_ym_5,
        $socket_ym_lb/blok_ym_6,

        $socket_ym_pb/blok_ym_1,
        $socket_ym_pb/blok_ym_2,
        $socket_ym_pb/blok_ym_3,
        $socket_ym_pb/blok_ym_4,
        $socket_ym_pb/blok_ym_5,
        $socket_ym_pb/blok_ym_6,

        $socket_ym_lb/blok_ym_litera_1,
    ]
    _draw_control_panel_prd(Constants.CURRENT_MODE)


func _process(_delta: float) -> void:
    if not flag_continue_control:
        return
    if flag_dkm and flag_ug:
        emit_signal('signal_on_modul_um')
    if flag_modul_on_1 and flag_modul_on_2 and flag_start:
        emit_signal('signal_on_start_timer_03')


func _draw_control_panel_prd(pribor):
    if pribor == Constants.MODE.PRD_H:
        # Кассета У5
        $soc_y5/IP5_25.rname = 'А24'
        $soc_y5/yau_07b.rname = 'А30'
        $soc_y5/ems_g.rname = 'А26'
        $soc_y5/ug.rname = 'А27'
        $soc_y5/ukp_1.rname = 'А28'
        $soc_y5/ukp_2.rname = 'А29'
        # Кассета ФС
        $Kasseta_FS/Kasseta.text = 'Кассета ФС-НД'
        $Kasseta_FS/Block_FS_PRD_K.visible = false
        $Kasseta_FS/FS_PRD_K.visible = false
        $Kasseta_FS/ref_A1.rname = 'А1'
        $Kasseta_FS/ref_A1.fname = 'Модуль ФС'
        $Kasseta_FS/ref_A3.rname = 'А3'
        $Kasseta_FS/ref_A3.fname = 'БЛОК ФС-2'
        $Kasseta_FS/ref_A2.rname = 'А2'
        $Kasseta_FS/ref_A2.fname = 'Модуль ФС'
        $Kasseta_FS/ref_A4.rname = 'А4'
        $Kasseta_FS/ref_A4.fname = 'БЛОК ФС-3'
        # Кассета П-1
        $soc_P1/IP12_50.rname = 'А21'
        $soc_P1/IP9_50_1.rname = 'А20'
        $soc_P1/IP9_50_2.rname = 'А19'
        $soc_P1/MAA_1.rname = 'А22'
        $soc_P1/MAA_2.rname = 'А23'
        # Кассета П-2
        $soc_P2.visible = false
        # ДКМ
        $soc_DKM/DKM_1.visible = false
        $soc_DKM/DKM_2.fname = 'ДКМ-2'
        $soc_DKM/DKM_3.fname = 'ДКМ-3'
        # УМ УМ
        $socket_ym_lb/blok_ym_litera_1.visible = false

        $socket_ym_lb/blok_ym_1.rname = 'A7'
        $socket_ym_lb/blok_ym_2.rname = 'A8'
        $socket_ym_lb/blok_ym_3.rname = 'A9'
        $socket_ym_lb/blok_ym_4.rname = 'A10'
        $socket_ym_lb/blok_ym_5.rname = 'A11'
        $socket_ym_lb/blok_ym_6.rname = 'A12'

        $socket_ym_pb/blok_ym_1.rname = 'A13'
        $socket_ym_pb/blok_ym_2.rname = 'A14'
        $socket_ym_pb/blok_ym_3.rname = 'A15'
        $socket_ym_pb/blok_ym_4.rname = 'A16'
        $socket_ym_pb/blok_ym_5.rname = 'A17'
        $socket_ym_pb/blok_ym_6.rname = 'A18'

    elif pribor == Constants.MODE.PRD_B:
        # Кассета У5
        $soc_y5/IP5_25.rname = 'А24'
        $soc_y5/yau_07b.rname = 'А30'
        $soc_y5/ems_g.rname = 'А26'
        $soc_y5/ug.rname = 'А27'
        $soc_y5/ukp_1.rname = 'А28'
        $soc_y5/ukp_2.rname = 'А29'
        # Кассета ФС
        $Kasseta_FS/Kasseta.text = 'Кассета ФС-ВД'
        $Kasseta_FS/Block_FS_PRD_K.visible = false
        $Kasseta_FS/FS_PRD_K.visible = false
        $Kasseta_FS/ref_A1.rname = 'А1'
        $Kasseta_FS/ref_A1.fname = 'Модуль ФС'
        $Kasseta_FS/ref_A3.rname = 'А3'
        $Kasseta_FS/ref_A3.fname = 'БЛОК ФС-4'
        $Kasseta_FS/ref_A2.rname = 'А2'
        $Kasseta_FS/ref_A2.fname = 'Модуль ФС'
        $Kasseta_FS/ref_A4.rname = 'А4'
        $Kasseta_FS/ref_A4.fname = 'БЛОК ФС-5'
        # Кассета П-1
        $soc_P1/IP12_50.rname = 'А21'
        $soc_P1/IP9_50_1.rname = 'А20'
        $soc_P1/IP9_50_2.rname = 'А19'
        $soc_P1/MAA_1.rname = 'А22'
        $soc_P1/MAA_2.rname = 'А23'
        # Кассета П-2
        $soc_P2.visible = false
        # ДКМ
        $soc_DKM/DKM_1.visible = false
        $soc_DKM/DKM_2.fname = 'ДКМ-4'
        $soc_DKM/DKM_3.fname = 'ДКМ-5'
        # УМ УМ
        $socket_ym_lb/blok_ym_litera_1.visible = false

        $socket_ym_lb/blok_ym_1.rname = 'A7'
        $socket_ym_lb/blok_ym_2.rname = 'A8'
        $socket_ym_lb/blok_ym_3.rname = 'A9'
        $socket_ym_lb/blok_ym_4.rname = 'A10'
        $socket_ym_lb/blok_ym_5.rname = 'A11'
        $socket_ym_lb/blok_ym_6.rname = 'A12'

        $socket_ym_pb/blok_ym_1.rname = 'A13'
        $socket_ym_pb/blok_ym_2.rname = 'A14'
        $socket_ym_pb/blok_ym_3.rname = 'A15'
        $socket_ym_pb/blok_ym_4.rname = 'A16'
        $socket_ym_pb/blok_ym_5.rname = 'A17'
        $socket_ym_pb/blok_ym_6.rname = 'A18'

    elif pribor == Constants.MODE.PRD_K:
        # Кассета У5
        $soc_y5/IP5_25.rname = 'А31'
        $soc_y5/yau_07b.rname = 'А37'
        $soc_y5/ems_g.rname = 'А33'
        $soc_y5/ug.rname = 'А34'
        $soc_y5/ukp_1.rname = 'А35'
        $soc_y5/ukp_2.rname = 'А36'
        # Кассета ФС
        $Kasseta_FS/Kasseta.text = 'Кассета ФС-КД'
        $Kasseta_FS/Block_FS_PRD_K.visible = true
        $Kasseta_FS/FS_PRD_K.visible = true
        $Kasseta_FS/ref_A1.rname = 'А3'
        $Kasseta_FS/ref_A1.fname = 'Модуль ФС'
        $Kasseta_FS/ref_A3.rname = 'А6'
        $Kasseta_FS/ref_A3.fname = 'БЛОК ФС-6'
        $Kasseta_FS/ref_A2.rname = 'А2'
        $Kasseta_FS/ref_A2.fname = 'Модуль ФС'
        $Kasseta_FS/ref_A4.rname = 'А5'
        $Kasseta_FS/ref_A4.fname = 'БЛОК ФС-7'
        # Кассета П-1
        $soc_P1/IP12_50.rname = 'А23'
        $soc_P1/IP12_50.fname = 'ИП9-50'
        $soc_P1/IP9_50_1.rname = 'А24'
        $soc_P1/IP9_50_1.fname = 'ИП9-50'
        $soc_P1/IP9_50_2.rname = 'А26'
        $soc_P1/IP9_50_2.fname = 'ИП12-50'

        $soc_P1/MAA_1.rname = 'А27'
        $soc_P1/MAA_2.rname = 'А28'
        # Кассета П-2
        $soc_P2.visible = true
        # ДКМ
        $soc_DKM/DKM_1.visible = true
        $soc_DKM/DKM_2.fname = 'ДКМ-6'
        $soc_DKM/DKM_3.fname = 'ДКМ-7'

        $socket_ym_lb/blok_ym_1.rname = 'A16'
        $socket_ym_lb/blok_ym_2.rname = 'A17'
        $socket_ym_lb/blok_ym_3.rname = 'A18'
        $socket_ym_lb/blok_ym_4.rname = 'A19'
        $socket_ym_lb/blok_ym_5.rname = 'A20'
        $socket_ym_lb/blok_ym_6.rname = 'A21'

        $socket_ym_pb/blok_ym_1.rname = 'A10'
        $socket_ym_pb/blok_ym_2.rname = 'A11'
        $socket_ym_pb/blok_ym_3.rname = 'A12'
        $socket_ym_pb/blok_ym_4.rname = 'A13'
        $socket_ym_pb/blok_ym_5.rname = 'A14'
        $socket_ym_pb/blok_ym_6.rname = 'A15'

        # УМ УМ
        $socket_ym_lb/blok_ym_litera_1.rname = 'A9'
        $socket_ym_lb/blok_ym_litera_1.visible = true


func fs_setup(unit_fs: Node, freq: int, att: float):
    if not flag_continue_control:
        return
    command_fs_off(unit_fs)
    await get_tree().create_timer(0.1).timeout
    unit_fs.status_can_macro_exec(false)
    unit_fs.set_carrier(freq * 1_000_000)
    unit_fs.set_att_batch(att) # Для литеры 2, 4, 6
    unit_fs.set_base_can_macro(freq)
    unit_fs.status_can_macro_exec(true)
    unit_fs.set_gen_state(false) ## отключен на true
    unit_fs.get_gen_state()


func command_fs_off(unit_fs: Node) -> void:
    unit_fs.set_gen_state(true)
    unit_fs.get_gen_state()


func yau_07b_setup(angle_and_att: int):
    if not flag_continue_control:
        return
    Network.write_port_isa(Constants.BASE_PORTS.UG+0x6, angle_and_att)
    Network.write_port_isa(Constants.BASE_PORTS.UG+0x8, angle_and_att)
    if Constants.CURRENT_MODE == Constants.MODE.PRD_K:
        Network.write_port_isa(Constants.BASE_PORTS.UG+0xA, 0)


func _on_data_fs(fs_data:PackedByteArray, fs_name: String):
    if logger:
        var GRP = fs_data.decode_u8(0x0)
        var CMD = fs_data.decode_u8(0x1)
        match CMD:
            Constants.CMD.READ_CARRIER:
                if GRP == Constants.GROUP.BASE:
                    logger.info('✅ В модуль %s установлена частота: %s МГц' % [fs_name, (fs_data.decode_u64(0xC) / 1_000_000.0)])
            Constants.CMD.READ_ATT:
                if GRP == Constants.GROUP.RF:
                    logger.info('✅ В модуль %s установлена аттенюация: %s dB' % [fs_name, (fs_data.decode_float(0x18))])
            Constants.CMD.READ_GEN_STATUS:
                if GRP == Constants.GROUP.GENERATOR:
                    if fs_data.decode_u32(0xC) == 0:
                        if fs_name == 'ФС-1':
                            $Kasseta_FS/ref_A1.state = Constants.STATE_VAL.GOOD
                            flag_fs_1_ready = true
                            logger.info('✅ Состояние генератора ФС-1: Включен')
                        elif fs_name == 'ФС-2':
                            $Kasseta_FS/ref_A2.state = Constants.STATE_VAL.GOOD
                            logger.info('✅ Состояние генератора ФС-2: Включен')
                            flag_fs_2_ready = true
                        elif fs_name == 'ФС-3':
                            $Kasseta_FS/FS_PRD_K.state = Constants.STATE_VAL.GOOD
                            logger.info('✅ Состояние генератора ФС-3: Включен')
                            flag_fs_3_ready = true
                    else:
                        if fs_name == 'ФС-1':
                            flag_fs_1_ready = false
                        if fs_name == 'ФС-2':
                            flag_fs_2_ready = false
                        if fs_name == 'ФС-3':
                            flag_fs_3_ready = false
                        logger.info('🛈 Состояние генератора %s: Отключен' % fs_name)
            Constants.CMD.BASE_CAN_MACRO_READ:
                if GRP == Constants.GROUP.BASE:
                    logger.info('✅ В модуль %s установлена частота CAN: %s МГц' % [fs_name, (fs_data.decode_u16(0x20))])


func _on_yau_received(status_yau):
    if flag_control_add and flag_continue_control:
        # Сбор урожая с УКП-1
        var arr_power_ukp_1: Array = []
        var numbre_scrape = 7 if Constants.CURRENT_MODE == Constants.MODE.PRD_K else 6
        for i in range(numbre_scrape): ## Мощность от УКП_1
            if i == 6:
                i +=1
            var power_ukp_1 = status_yau.decode_u16(Constants.DataIndices.POWER_UKP_1 + 2 * i)
            arr_power_ukp_1.append(power_ukp_1)

        if count_packet == 0:
            array_pow_1 = arr_power_ukp_1
        else:
            for i in range(numbre_scrape):
                if arr_power_ukp_1[i] > array_pow_1[i]:
                    array_pow_1[i] = arr_power_ukp_1[i]
        # Сбор урожая с УКП-2
        var arr_power_ukp_2: Array = []
        numbre_scrape = 6
        for i in range(numbre_scrape): ## Мощность от УКП_2
            var power_ukp_2 = status_yau.decode_u16(Constants.DataIndices.POWER_UKP_2 + 2 * i)
            arr_power_ukp_2.append(power_ukp_2)

        if count_packet == 0:
            array_pow_2 = arr_power_ukp_2
        else:
            for i in range(6):
                if arr_power_ukp_2[i] > array_pow_2[i]:
                    array_pow_2[i] = arr_power_ukp_2[i]
        count_packet += 1


func _on_yau_feedback_receive(status_yau):
    if logger and flag_continue_control:
        ## Флаг для проверки настройки угла и аттенюации на двух литерах
        if Network.unit.isa_ports.has(Constants.BASE_PORTS.UG+6) and Network.unit.isa_ports.has(Constants.BASE_PORTS.UG+8):
            if Network.unit.isa_ports[Constants.BASE_PORTS.UG+6] == prep_set_ug and Network.unit.isa_ports[Constants.BASE_PORTS.UG+8] == prep_set_ug:
                if Constants.CURRENT_MODE == Constants.MODE.PRD_K:
                    if Network.unit.isa_ports[Constants.BASE_PORTS.UG+0xA] == 0:
                        flag_ug = true
                        $soc_y5/ug.state = Constants.STATE_VAL.GOOD
                else:
                    flag_ug = true
                    $soc_y5/ug.state = Constants.STATE_VAL.GOOD
            else:
                flag_ug = false
                $soc_y5/ug.state = Constants.STATE_VAL.NONE
        ## Флаг для проверки модуяции на высоком
        if (status_yau.decode_u16(13) >> 1) & 1 and (not flag_modul_on_1):
            flag_modul_on_1 = true
            logger.info('✅ Модуляция УМ (2, 4, 6) включена!')
        elif (status_yau.decode_u16(13) >> 1) & 1 == 0 and (flag_modul_on_1):
            flag_modul_on_1 = false
            logger.info('🛈 Модуляция УМ (2, 4, 6) отключена!')

        if (status_yau.decode_u16(13) >> 2) & 1 and (not flag_modul_on_2):
            flag_modul_on_2 = true
            logger.info('✅ Модуляция УМ (3, 5, 7) включена!')
        elif (status_yau.decode_u16(13) >> 2) & 1 == 0 and (flag_modul_on_2):
            flag_modul_on_2 = false
            logger.info('🛈 Модуляция УМ (3, 5, 7) отключена!')
        if Constants.CURRENT_MODE == Constants.MODE.PRD_K:
            if Network.unit.isa_ports.has(Constants.BASE_PORTS.EMS_G+8) and Network.unit.isa_ports.has(Constants.BASE_PORTS.EMS_G+2):
                if Network.unit.isa_ports[Constants.BASE_PORTS.EMS_G+2] == Constants.META.MODUL_UM_1:
                    if Network.unit.isa_ports[Constants.BASE_PORTS.EMS_G+8] == 0x2000 and (not flag_modul_litera_1):
                        flag_modul_litera_1 = true
                        logger.info('✅ Модуляция УМ 1 включена!')
                    elif Network.unit.isa_ports[Constants.BASE_PORTS.EMS_G+8] == 0x4000 and flag_modul_litera_1:
                        flag_modul_litera_1 = false
                        logger.info('🛈 Модуляция УМ 1 отключена!')


func _on_start_super_control():
    $lbl_control.text = 'Контроль запущен'
    $lbl_control.modulate = Color.LIGHT_GRAY
    $log_array/await.visible = true
    logger = Logger.new(get_node('log_array'))
    flag_continue_control = true

    if (past_pribor != Constants.CURRENT_MODE):
        past_pribor = Constants.CURRENT_MODE
        _draw_control_panel_prd(Constants.CURRENT_MODE)

    for i in count_cell:
            node_cell_ind[i].state = Constants.STATE_VAL.NONE
    flag_dkm = false
    flag_ug = false
    flag_yau = false
    for node in um_cell_ind:
        node.value0 = 0
        node.value1 = 0
        node.state = Constants.STATE_VAL.NONE

    var predel_temp: int = 200
    ## Temperature for
    for i_temperature in range(6): ## Температура от УКП
        if len(Network.unit.status) > Constants.DataIndices.TEMPERATURE_UKP_2 + 2 * i_temperature:
            var temperature_ukp_1 = Network.unit.status.decode_u16(Constants.DataIndices.TEMPERATURE_UKP_1 + 2 * i_temperature)
            var temperature_ukp_2 = Network.unit.status.decode_u16(Constants.DataIndices.TEMPERATURE_UKP_2 + 2 * i_temperature)
            var TMP_1 = Constants.CONST_MIN_TEMP + (Constants.MAXIMUM_CODE_ADC - temperature_ukp_1) * Constants.TEMP + 3
            var TMP_2 = Constants.CONST_MIN_TEMP + (Constants.MAXIMUM_CODE_ADC - temperature_ukp_2) * Constants.TEMP + 3
            if TMP_1 > predel_temp:
                um_cell_ind[i_temperature].value0 = TMP_1
                um_cell_ind[i_temperature].state = Constants.STATE_VAL.ERROR
                logger.warning('❌ Температура УМ %s = %d' % [um_cell_ind[i_temperature].fname, TMP_1])
            else:
                um_cell_ind[i_temperature].value0 = TMP_1
            if TMP_2 > predel_temp:
                um_cell_ind[i_temperature+6].value0 = TMP_2
                um_cell_ind[i_temperature+6].state = Constants.STATE_VAL.ERROR
                logger.warning('❌ Температура %s: %d' % [um_cell_ind[i_temperature+6].fname, TMP_2])
            else:
                um_cell_ind[i_temperature+6].value0 = TMP_2
        if Constants.CURRENT_MODE == Constants.MODE.PRD_K:
            if len(Network.unit.status) > Constants.DataIndices.TEMPERATURE_UKP_2 + 2 * 7:
                var temperature_litera_1 = Network.unit.status.decode_u16(Constants.DataIndices.TEMPERATURE_UKP_1 + 2 * 7)
                var TEMPERATURE = Constants.CONST_MIN_TEMP + (Constants.MAXIMUM_CODE_ADC - temperature_litera_1) * Constants.TEMP + 3
                if TEMPERATURE > predel_temp:
                    um_cell_ind[12].value0 = TEMPERATURE
                    logger.warning('❌ Температура %s = %d' % [um_cell_ind[12].fname, TEMPERATURE])
                else:
                    um_cell_ind[12].value0 = TEMPERATURE

    if (Network.unit.online):
        $soc_y5/yau_07b.state = Constants.STATE_VAL.GOOD
        logger.info("✅ ЯУ-07Б: Есть связь")
        flag_yau = true
        _status_cell(Network.unit.status)
    else:
        for i in range(1, count_cell):
            node_cell_ind[i].state = Constants.STATE_VAL.NONE
        $soc_y5/yau_07b.state = Constants.STATE_VAL.ERROR
        logger.error("❌ ЯУ-07Б: Нет связи")

    if flag_continue_control:
        flag_fs_1_ready = false
        flag_fs_2_ready = false
        flag_fs_3_ready = false
        var fs_freq: Array
        if Network.unit_fs_1.online:
            var fs_att_1: float
            if Constants.CURRENT_MODE == Constants.MODE.PRD_H:
                fs_freq.append(Constants.FS_FREQ.f2)
                fs_att_1 = Constants.FS_ATT[Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]][0]
            elif Constants.CURRENT_MODE == Constants.MODE.PRD_B:
                fs_freq.append(Constants.FS_FREQ.f4)
                fs_att_1 = Constants.FS_ATT[Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]][0]
            elif Constants.CURRENT_MODE == Constants.MODE.PRD_K:
                fs_freq.append(Constants.FS_FREQ.f6)
                fs_att_1 = Constants.FS_ATT[Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]][0]

                fs_freq.append(Constants.FS_FREQ.f1)

            logger.info('🛈 Настройка модуля ФС %s Гц, [%s] АТТ' % [str(fs_freq[0]), str(fs_att_1)])
            fs_setup(Network.unit_fs_1, fs_freq[0], fs_att_1) # Гц
        else:
            logger.info('❌ Модуль ФС-1: нет связи')
            _on_contol_err()
            return

        if Network.unit_fs_2.online:
            var fs_att_2: float
            if Constants.CURRENT_MODE == Constants.MODE.PRD_H:
                fs_freq.append(Constants.FS_FREQ.f3)
                fs_att_2 = Constants.FS_ATT[Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]][1]
            elif Constants.CURRENT_MODE == Constants.MODE.PRD_B:
                fs_freq.append(Constants.FS_FREQ.f5)
                fs_att_2 = Constants.FS_ATT[Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]][1]
            elif Constants.CURRENT_MODE == Constants.MODE.PRD_K:
                fs_freq.append(Constants.FS_FREQ.f7)
                fs_att_2 = Constants.FS_ATT[Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]][1]
            logger.info('🛈 Настройка модуля ФС %s Гц, [%s] АТТ' % [str(fs_freq[1]), str(fs_att_2)])
            await get_tree().create_timer(1.0).timeout
            fs_setup(Network.unit_fs_2, fs_freq[1], fs_att_2) # Гц
        else:
            logger.info('❌ Модуль ФС-2: нет связи')
            _on_contol_err()
            return

        if Constants.CURRENT_MODE == Constants.MODE.PRD_K:
            if Network.unit_fs_3.online:
                var fs_att_3: float
                fs_att_3 = Constants.FS_ATT[Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]][2]
                logger.info('🛈 Настройка модуля ФС %s Гц, [%s] АТТ' % [str(fs_freq[2]), str(fs_att_3)])
                await get_tree().create_timer(1.0).timeout
                fs_setup(Network.unit_fs_3, fs_freq[2], fs_att_3)
            else:
                logger.info('❌ Модуль ФС-3: нет связи')
                _on_contol_err()
                return

        timer.set_one_shot(true)
        timer.set_wait_time(10)
        timer.start()


func _status_cell(status):
    var status_board: int = status.decode_u8(Constants.DataIndices.STATUS_BOARD)
    var dry_contact: int = status.decode_u8(Constants.DataIndices.DRY_CONTACT)
    var err: bool = false
    # status_board
    for i in range(1, 5):
        if ((status_board >> (i-1)) & 0x1) == 1:
            node_cell_ind[i].state = Constants.STATE_VAL.GOOD
            logger.info("✅ %s : Есть связь" % node_cell_ind[i].get('fname'))
        else:
            node_cell_ind[i].state = Constants.STATE_VAL.ERROR
            logger.error("❌ %s : Нет связи" % node_cell_ind[i].get('fname'))
            err = true

    #dry_contact
    if (node_cell_ind[2].state == Constants.STATE_VAL.GOOD):
        for i_node in range(5, 13):
            var skip = false
            if i_node == 10 or i_node == 11:
                skip = Constants.CURRENT_MODE != Constants.MODE.PRD_K

            if not skip:
                if ((dry_contact >> (i_node-5)) & 0x1) == 0:
                    node_cell_ind[i_node].state = Constants.STATE_VAL.GOOD
                    logger.info("✅ %s : Есть связь" % node_cell_ind[i_node].get('fname'))
                else:
                    node_cell_ind[i_node].state = Constants.STATE_VAL.ERROR
                    logger.error("❌ %s : Нет связи" % node_cell_ind[i_node].get('fname'))
                    err = true

        if err:
            _on_contol_err()
            return

        if node_cell_ind[2].state == Constants.STATE_VAL.GOOD:
            var mask: int = 0x7
            prep_set_ug = 0
            var index_ray: int = Constants.RAY_DICT.find('  25°')
            if Constants.CURRENT_MODE == Constants.MODE.PRD_B or Constants.CURRENT_MODE == Constants.MODE.PRD_K:
                index_ray = Constants.RAY_DICT.find('  35°')
            var index_att: int = Constants.ATT_DICT.find('  10.5 dB')
            ## Регулировка положением луча 1
            prep_set_ug = set_bits(prep_set_ug, index_ray, mask)
            ## Регулировка положением луча 2
            mask = 0x38
            prep_set_ug = set_bits(prep_set_ug, index_att << 3, mask)

            logger.info('🛈 %s: Настройка угла %s' % [node_cell_ind[2].get('fname'), Constants.RAY_DICT[index_ray]])
            logger.info('🛈 %s: Настройка аттенюации %s' % [node_cell_ind[2].get('fname'), Constants.ATT_DICT[index_att]])
            yau_07b_setup(prep_set_ug)
        else:
            logger.error('❌ %s: Нет на связи, не буду продолжать' % node_cell_ind[2].get('fname'))
            _on_contol_err()

    else:
        for i_node_unknow in range(5, 13):
            node_cell_ind[i_node_unknow].state = Constants.STATE_VAL.NONE


## Устанавливает биты в соответствии с маской
## [param v] - Прежние значения бит
## [param a] - Новые значения бит
## [param m] - Маска изменяемых бит
func set_bits(v, a, m):
    return (~m) & v | a & m


func _on_fs_status(META:int):
    await get_tree().create_timer(1.0).timeout
    var control_button: Node = self.get_parent().get_parent().get_child(0).get_child(1).get_child(1)
    var texture_control_button: Node = self.get_parent().get_parent().get_child(0).get_child(1).get_child(8)
    if control_button.button_pressed or texture_control_button.button_pressed:
        if logger and flag_continue_control:
            if META == Constants.META.CI_2_OT_FS or META == Constants.META.CI_4_OT_FS or META == Constants.META.CI_6_OT_FS:
                logger.info('✅ СИ от ФС-1: Включен')
                return
            elif META == Constants.META.CI_3_OT_FS or META == Constants.META.CI_5_OT_FS or META == Constants.META.CI_7_OT_FS:
                logger.info('✅ СИ от ФС-2: Включен')
            elif META == Constants.META.CI_1_OT_FS:
                logger.info('✅ СИ от ФС-3: Включен')

            if not flag_fs_1_ready:
                return

            if not flag_fs_2_ready:
                return

            if Constants.CURRENT_MODE == Constants.MODE.PRD_K:
                if not flag_fs_3_ready:
                    return

            #dkm
            var dkm: int = Network.unit.status.decode_u8(Constants.DataIndices.DKM)

            if Constants.CURRENT_MODE == Constants.MODE.PRD_H:
                if (dkm >> 1) & 0x1 == 1:
                    logger.info('✅ %s: %s' % [$Kasseta_FS/ref_A3.fname, 'Включено'])
                    $soc_DKM/DKM_2.state = Constants.STATE_VAL.GOOD
                    $Kasseta_FS/ref_A3.state = $soc_DKM/DKM_2.state
                else:
                    logger.info('❌ %s: %s' % [$Kasseta_FS/ref_A3.fname, 'Нет связи'])
                    $soc_DKM/DKM_2.state = Constants.STATE_VAL.ERROR
                    $Kasseta_FS/ref_A3.state = $soc_DKM/DKM_2.state
                if (dkm >> 2) & 0x1 == 1:
                    logger.info('✅ %s: %s' % [$Kasseta_FS/ref_A4.fname, 'Включено'])
                    $soc_DKM/DKM_3.state = Constants.STATE_VAL.GOOD
                    $Kasseta_FS/ref_A4.state = $soc_DKM/DKM_3.state
                else:
                    logger.info('❌ %s: %s' % [$Kasseta_FS/ref_A4.fname, 'Нет связи'])
                    $soc_DKM/DKM_3.state = Constants.STATE_VAL.ERROR
                    $Kasseta_FS/ref_A4.state = $soc_DKM/DKM_3.state

                if (dkm >> 1) & 0x1 == 1 and (dkm >> 2) & 0x1 == 1: # Следующий шаг ->
                    flag_dkm = true

            elif Constants.CURRENT_MODE == Constants.MODE.PRD_B:
                if (dkm >> 3) & 0x1 == 1:
                    logger.info('✅ %s: %s' % [$Kasseta_FS/ref_A3.fname, 'Включено'])
                    $soc_DKM/DKM_2.state = Constants.STATE_VAL.GOOD
                    $Kasseta_FS/ref_A3.state = $soc_DKM/DKM_2.state
                else:
                    logger.info('❌ %s: %s' % [$Kasseta_FS/ref_A3.fname, 'Нет связи'])
                    $soc_DKM/DKM_2.state = Constants.STATE_VAL.ERROR
                    $Kasseta_FS/ref_A3.state = $soc_DKM/DKM_2.state
                if (dkm >> 4) & 0x1 == 1:
                    logger.info('✅ %s: %s' % [$Kasseta_FS/ref_A4.fname, 'Включено'])
                    $soc_DKM/DKM_3.state = Constants.STATE_VAL.GOOD
                    $Kasseta_FS/ref_A4.state = $soc_DKM/DKM_3.state
                else:
                    logger.info('❌ %s: %s' % [$Kasseta_FS/ref_A4.fname, 'Нет связи'])
                    $soc_DKM/DKM_3.state = Constants.STATE_VAL.ERROR
                    $Kasseta_FS/ref_A4.state = $soc_DKM/DKM_3.state

                if (dkm >> 3) & 0x1 == 1 and (dkm >> 4) & 0x1 == 1: # Следующий шаг ->
                    flag_dkm = true

            elif Constants.CURRENT_MODE == Constants.MODE.PRD_K:
                if (dkm >> 0) & 0x1 == 1:
                    logger.info('✅ %s: %s ' % [$Kasseta_FS/Block_FS_PRD_K.fname, 'Включено'])
                    $soc_DKM/DKM_1.state = Constants.STATE_VAL.GOOD
                    $Kasseta_FS/Block_FS_PRD_K.state = $soc_DKM/DKM_1.state
                else:
                    logger.info('❌ %s: %s ' % [$Kasseta_FS/Block_FS_PRD_K.fname, 'Нет связи'])
                    $soc_DKM/DKM_1.state = Constants.STATE_VAL.ERROR
                    $Kasseta_FS/Block_FS_PRD_K.state = $soc_DKM/DKM_1.state
                if (dkm >> 5) & 0x1 == 1:
                    logger.info('✅ %s: %s ' % [$Kasseta_FS/ref_A3.fname, 'Включено'])
                    $soc_DKM/DKM_2.state = Constants.STATE_VAL.GOOD
                    $Kasseta_FS/ref_A3.state = $soc_DKM/DKM_2.state
                else:
                    logger.info('❌ %s: %s' % [$Kasseta_FS/ref_A3.fname, 'Нет связи'])
                    $soc_DKM/DKM_2.state = Constants.STATE_VAL.ERROR
                    $Kasseta_FS/ref_A3.state = $soc_DKM/DKM_2.state
                if (dkm >> 6) & 0x1 == 1:
                    logger.info('✅ %s: %s' % [$Kasseta_FS/ref_A4.fname, 'Включено'])
                    $soc_DKM/DKM_3.state = Constants.STATE_VAL.GOOD
                    $Kasseta_FS/ref_A4.state = $soc_DKM/DKM_3.state
                else:
                    logger.info('❌ %s: %s' % [$Kasseta_FS/ref_A4.fname, 'Нет связи'])
                    $soc_DKM/DKM_3.state = Constants.STATE_VAL.ERROR
                    $Kasseta_FS/ref_A4.state = $soc_DKM/DKM_3.state

                if (dkm >> 5) & 0x1 and (dkm >> 6) & 0x1 and (dkm >> 0) & 0x1: # Следующий шаг ->
                    flag_dkm = true
            logger.info('🛈 ДКМ: %s ' % dkm)


func _on_modul_um():
    if not flag_continue_control:
        return
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G, 6666)
    flag_dkm = false
    flag_start = true


func _on_start_timer_03():
    count_packet = 0
    flag_start = false
    flag_control_add = true
    timer_03.wait_time = 0.4
    timer_03.one_shot = true
    timer_03.start()


func _on_timer_03():
    flag_control_add = false
    command_fs_off(Network.unit_fs_1)
    command_fs_off(Network.unit_fs_2)
    if Constants.CURRENT_MODE == Constants.MODE.PRD_K:
        command_fs_off(Network.unit_fs_3)
    await get_tree().create_timer(1.0).timeout
    logger.info('🛈 Количество принятых пакетов от ЯУ-07Б: %s пкт.' % count_packet)
    logger.info('🛈 Максимальные значения мощностей от УКП-1: %s ' % str(array_pow_1))
    logger.info('🛈 Максимальные значения мощности от УКП-2: %s ' % str(array_pow_2))
    _status_prd()
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, Constants.META.CZI_1)


func _on_contol_err():
    logger.warning('❌❌❌')
    flag_continue_control = false
    _status_prd()


func _on_timer():
    var control_button: Node = self.get_parent().get_parent().get_child(0).get_child(1).get_child(1)
    var texture_control_button: Node = self.get_parent().get_parent().get_child(0).get_child(1).get_child(8)
    if control_button.button_pressed or texture_control_button.button_pressed:
        if not flag_fs_1_ready:
            $Kasseta_FS/ref_A1.state = Constants.STATE_VAL.ERROR
            logger.warning('❌ Модуль ФС-1: нет связи')
        if not flag_fs_2_ready:
            $Kasseta_FS/ref_A2.state = Constants.STATE_VAL.ERROR
            logger.warning('❌ Модуль ФС-2: нет связи')
        if not flag_fs_3_ready:
            $Kasseta_FS/FS_PRD_K.state = Constants.STATE_VAL.ERROR
            logger.warning('❌ Модуль ФС-3: нет связи')
        if not flag_fs_1_ready or not flag_fs_2_ready:
            _on_contol_err()
        elif (Constants.CURRENT_MODE == Constants.MODE.PRD_K):
            if not flag_fs_3_ready:
                _on_contol_err()
        else:
            if flag_yau:
                $soc_y5/ems_g.state = Constants.STATE_VAL.ERROR
                logger.warning('❌ Разьем ЭМС-Г: нет связи')
                if not flag_ug:
                    $soc_y5/ug.state = Constants.STATE_VAL.ERROR
                    logger.warning('❌ Разьем УГ: нет связи')
            _on_contol_err()
        _on_timer_03()


func _status_prd():
    var status: int = 0
    for i in range(10):
        status += 1 if (node_cell_ind[i].state == Constants.STATE_VAL.GOOD) else 0
    for i in range(12, count_cell-2):
        status += 1 if (node_cell_ind[i].state == Constants.STATE_VAL.GOOD) else 0

    if (Constants.CURRENT_MODE == Constants.MODE.PRD_K):
        status += 1 if (node_cell_ind[10].state == Constants.STATE_VAL.GOOD) else 0
        status += 1 if (node_cell_ind[11].state == Constants.STATE_VAL.GOOD) else 0
        status += 1 if (node_cell_ind[12].state == Constants.STATE_VAL.GOOD) else 0
        status += 1 if (node_cell_ind[17].state == Constants.STATE_VAL.GOOD) else 0
        status += 1 if (node_cell_ind[18].state == Constants.STATE_VAL.GOOD) else 0

    var pribor_ispraven: bool = false
    var min_dopusk: int = 40
    var status_need = count_cell-7 if Constants.CURRENT_MODE != Constants.MODE.PRD_K else count_cell+1
    if (status == status_need):
        pribor_ispraven = true

    var count_um: int = 0

    for i_pow in array_pow_1:
        if count_um == 6:
            um_cell_ind[count_um+6].value1 = i_pow
            if i_pow < min_dopusk:
                pribor_ispraven = false
                um_cell_ind[count_um+6].state = Constants.STATE_VAL.ERROR
            else:
                um_cell_ind[count_um+6].state = Constants.STATE_VAL.GOOD
            count_um -=1
        else:
            um_cell_ind[count_um].value1 = i_pow
            if i_pow < min_dopusk:
                pribor_ispraven = false
                um_cell_ind[count_um].state = Constants.STATE_VAL.ERROR
            else:
                um_cell_ind[count_um].state = Constants.STATE_VAL.GOOD
        count_um += 1


    for i_pow in array_pow_2:
        um_cell_ind[count_um].value1 = i_pow
        if i_pow < min_dopusk:
            pribor_ispraven = false
            um_cell_ind[count_um].state = Constants.STATE_VAL.ERROR
        else:
            um_cell_ind[count_um].state = Constants.STATE_VAL.GOOD
        count_um += 1

    array_pow_1 = []
    array_pow_2 = []

    if pribor_ispraven:
        $lbl_control.text = 'Прибор %s исправен' % Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]
        $lbl_control.modulate = Color.AQUAMARINE
    else:
        $lbl_control.text = 'Прибор %s неисправен' % Constants.ADDRESSES[self.get_parent().get_child(0).get_child(1).get_node2(1, 0).get_selected_id()][0]
        $lbl_control.modulate = Color.CRIMSON
    $log_array/await.visible = false
    timer.stop()
