Modules/devices/devices links actions inc php

Материал из MajorDoMo инфо
Версия от 23:48, 30 марта 2024; Elmax (обсуждение | вклад) (+ файл devices_links_actions.inc.php)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)


ᐂ В корневой раздел ᐃ В директорию расположения файла

<?php

// Начинаем измерение времени выполнения функции homebridge_update
startMeasure('homebridge_update');
// Переменная для отладки синхронизации, инициализируется значением 0
$debug_sync = 0;
// Проверяем, не является ли устройство системным, не архивировано ли оно и доступен ли HomeBridge
if (!$device1['SYSTEM_DEVICE'] && !$device1['ARCHIVED'] && $this->isHomeBridgeAvailable()) {
    // Отправляем обновленный статус в HomeKit
    require DIR_MODULES . 'devices/homebridgeSendUpdate.inc.php';
}
endMeasure('homebridge_update');

// Начинаем измерение времени выполнения функции checkingLinks
startMeasure('checkingLinks');
// Получаем значение связанного объекта и преобразуем его в число с плавающей точкой
$value = (float)gg($device1['LINKED_OBJECT'] . '.value');
// Получаем статус связанного объекта и преобразуем его в число с плавающей точкой
$status = (float)gg($device1['LINKED_OBJECT'] . '.status');

// Выполняем SQL-запрос для получения связанных устройств
$links = SQLSelect("SELECT devices_linked.*, devices.LINKED_OBJECT FROM devices_linked LEFT JOIN devices ON devices_linked.DEVICE2_ID=devices.ID WHERE devices_linked.IS_ACTIVE=1 AND DEVICE1_ID=" . (int)$device1['ID']);
// Подсчитываем общее количество связанных устройств
$total = count($links);
// Начинаем цикл по всем связанным устройствам
for ($i = 0; $i < $total; $i++) {
    // Проверяем доступ к устройству
    if (!checkAccess('sdevice', $links[$i]['ID'])) continue;
    // Получаем тип связи
    $link_type = $links[$i]['LINK_TYPE'];
    // Десериализуем настройки связи
    $settings = unserialize($links[$i]['LINK_SETTINGS']);
    if ($device1['TYPE'] == 'button' && !$status) continue;
    if ($device1['TYPE'] == 'motion' && $settings['action_type'] != 'sync' && $settings['action_type'] != 'sync_inverted' && !$status) continue;
    $object = $links[$i]['LINKED_OBJECT'];
    // Формируем имя таймера
    $timer_name = 'linkTimer' . $links[$i]['ID'];
    // Инициализируем строку для действия
    $action_string = '';
    // -----------------------------------------------------------------
    // Проверяем тип связи 
    if ($link_type == 'switch_it') {

        // Формируем строку действия в зависимости от типа действия
        if ($settings['action_type'] == 'turnoff') {
            // Выключаем объект
            $action_string = 'callMethodSafe("' . $object . '.turnOff' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        } elseif ($settings['action_type'] == 'turnon') {
            // Включаем объект
            $action_string = 'callMethodSafe("' . $object . '.turnOn' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        } elseif ($settings['action_type'] == 'switch') {
            // Переключаем объект
            $action_string = 'callMethodSafe("' . $object . '.switch' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        } elseif ($settings['action_type'] == 'close') {
            // Закрываем объект
            $action_string = 'callMethodSafe("' . $object . '.close' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        } elseif ($settings['action_type'] == 'open') {
            // Открываем объект
            $action_string = 'callMethodSafe("' . $object . '.open' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        } elseif ($settings['action_type'] == 'sync') {
            // Синхронизируем статус объекта
            if ($status) {
                $action_string = 'callMethodSafe("' . $object . '.turnOn' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
            } else {
                $action_string = 'callMethodSafe("' . $object . '.turnOff' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
            }
        } elseif ($settings['action_type'] == 'sync_inverted') {
            // Синхронизируем инвертированный статус объекта  
            if (!$status) {
                $action_string = 'callMethodSafe("' . $object . '.turnOn' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
            } else {
                $action_string = 'callMethodSafe("' . $object . '.turnOff' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
            }
        }
        // Добавляем задержку, если нужно
        if ($settings['action_delay'] != '') {
            $settings['action_delay'] = (int)processTitle($settings['action_delay']);
            if ($settings['action_delay'] > 0) {
                $action_string = 'setTimeout(\'' . $timer_name . '\',\'' . $action_string . '\',' . (int)$settings['action_delay'] . ');';
            }
        }
    } elseif ($link_type == 'switch_timer') {
        // Формируем таймерное действие
        $timer_name = $object . '_switch_timer';
        $action_string = '';
        if ($settings['darktime']) {
            // проверка активен ли режим DarknessMode
            $action_string .= 'if (gg("DarknessMode.active")) {';
        }
        // включение
        $action_string .= 'callMethodSafe("' . $object . '.turnOn' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        if ($settings['action_delay'] != '') {
            $settings['action_delay'] = (int)processTitle($settings['action_delay']);
            if ($settings['action_delay'] > 0) {
                $action_string .= 'setTimeout(\'' . $timer_name . '\',\'' . 'callMethod("' . $object . '.turnOff' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));' . '\',' . (int)$settings['action_delay'] . ');';
            }
        }
        if ($settings['darktime']) {
            $action_string .= '}';
        }
    } elseif ($link_type == 'set_color') {
        $action_string = 'callMethodSafe("' . $object . '.setColor' . '",array("color"=>"' . $settings['action_color'] . '","link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        // Добавляем задержку выключения, если нужно
        if ($settings['action_delay'] != '') {
            $settings['action_delay'] = (int)processTitle($settings['action_delay']);
            if ($settings['action_delay'] > 0) {
                $action_string = 'setTimeout(\'' . $timer_name . '\',\'' . $action_string . '\',' . (int)$settings['action_delay'] . ');';
            }
        }
        // -----------------------------------------------------------------
        // -----------------------------------------------------------------
        // Код для обработки действий по типу 'sensor_switch'
    } elseif ($link_type == 'sensor_switch') {
        // Если тип действия равен 'turnoff' и статус объекта активен, то выключаем объект
        if ($settings['action_type'] == 'turnoff' && gg($object . '.status')) {
            $action_string = 'callMethodSafe("' . $object . '.turnOff' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
            // Если тип действия равен 'turnon' и статус объекта не активен, то включаем объект
        } elseif ($settings['action_type'] == 'turnon' && !gg($object . '.status')) {
            $action_string = 'callMethodSafe("' . $object . '.turnOn' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
            // Если тип действия равен 'open' и статус объекта активен, то открываем объект
        } elseif ($settings['action_type'] == 'open' && gg($object . '.status')) {
            $action_string = 'callMethodSafe("' . $object . '.open' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
            // Если тип действия равен 'close' и статус объекта не активен, то закрываем объект
        } elseif ($settings['action_type'] == 'close' && !gg($object . '.status')) {
            $action_string = 'callMethodSafe("' . $object . '.close' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        }

        // Если указан тип источника значения, то получаем среднее, минимальное или максимальное значение за указанный период
        if ($settings['source_value_type'] != '') {
            // Преобразуем время периода в целое число
            $period = (int)$settings['source_value_time'];
            // Если период меньше 1, устанавливаем его равным 1
            if ($period < 1) $period = 1;
            // Если тип источника значения равен 'avg', получаем среднее значение за указанный период
            if ($settings['source_value_type'] == 'avg') {
                $value = getHistoryAvg($device1['LINKED_OBJECT'] . '.value', (-1) * $period);
                // Если тип источника значения равен 'min', получаем минимальное значение за указанный период
            } elseif ($settings['source_value_type'] == 'min') {
                $value = getHistoryMin($device1['LINKED_OBJECT'] . '.value', (-1) * $period);
                // Если тип источника значения равен 'max', получаем максимальное значение за указанный период
            } elseif ($settings['source_value_type'] == 'max') {
                $value = getHistoryMax($device1['LINKED_OBJECT'] . '.value', (-1) * $period);
            }
        }

        // Если указан тип условия и значение соответствует условию, то выполняем действие
        if ($settings['condition_type'] == 'above' && $value >= (float)$settings['condition_value']) {
            // Выполняем действие
        } elseif ($settings['condition_type'] == 'below' && $value < (float)$settings['condition_value']) {
            // Выполняем действие
        } else {
            // Если условие не выполняется, то не выполняем действие
            $action_string = '';
        }
    } elseif ($link_type == 'sensor_pass') {
        // Код для обработки действий по типу 'sensor_pass'
        // Передаем значение объекта
        $action_string = 'sg("' . $object . '.value' . '","' . $value . '");';
        // Код для обработки действий по типу 'open_sensor_pass'
    } elseif ($link_type == 'open_sensor_pass') {
        // Передаем статус объекта
        $action_string = 'sg("' . $object . '.status' . '","' . $status . '");';
        // Код для обработки действий по типу 'thermostat_switch'
    } elseif ($link_type == 'thermostat_switch') {
        // Определяем значение для установки
        $set_value = 0;
        // Получаем текущий статус реле
        $current_relay_status = gg($device1['LINKED_OBJECT'] . '.relay_status');
        // Получаем текущий статус цели
        $current_target_status = gg($object . '.status');
        // Если нужно инвертировать статус, то инвертируем значение
        if ($settings['invert_status']) {
            $set_value = $current_relay_status ? 0 : 1;
        } else {
            $set_value = $current_relay_status;
        }
        // Если значение установлено и текущий статус цели не активен, то включаем объект
        if ($set_value && !$current_target_status) {
            $action_string = 'callMethodSafe("' . $object . '.turnOn' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        // Если значение не установлено и текущий статус цели активен, то выключаем объект
        } elseif (!$set_value && $current_target_status) {
            $action_string = 'callMethodSafe("' . $object . '.turnOff' . '",array("link_source"=>"' . $device1['LINKED_OBJECT'] . '"));';
        }
    }

    // Определяем директорию для дополнений
    $addons_dir = dirname(__FILE__) . '/addons';
    if (is_dir($addons_dir)) {
        // Получаем список файлов в директории дополнений
        $addon_files = scandir($addons_dir);
        foreach ($addon_files as $file) {
            if (preg_match('/\_links_actions\.php$/', $file)) {
                // Подключаем дополнительные скрипты для обработки действий
                require($addons_dir . '/' . $file);
            }
        }
    }

    // -----------------------------------------------------------------
    if ($action_string != '') {
        //DebMes("Action string: ".$action_string,'logic_test');
        try {
            $code = $action_string;
            // Выполняем код действия
            $success = eval($code);
            if ($success === false) {
                // Регистрируем ошибку, если код выполнился неудачно
                registerError('linked_device', sprintf('Error in linked device code "%s". Code: %s', $link_type, $code));
            }
        } catch (Exception $e) {
            // Регистрируем ошибку, если возникло исключение
            registerError('linked_device', sprintf('Error in script "%s": ' . $e->getMessage(), $link_type));
        }
    }

    // Завершаем измерение времени выполнения функции checkingLinks
    endMeasure('checkingLinks');
}