Modules/devices/devices edit inc php
Материал из MajorDoMo инфо
Версия от 12:31, 2 апреля 2024; Elmax (обсуждение | вклад) (Elmax переименовал страницу Devices edit inc php в Modules/devices/devices edit inc php: Пропустил при создании путь Modules/devices/)
ᐂ В корневой раздел ᐃ В директорию расположения файла
<?php
/**
* @version 0.1 (wizard)
*/
// Проверяет, является ли текущий владелец панелью, и устанавливает флаг панели управления.
if ($this->owner->name == 'panel') {
$out['CONTROLPANEL'] = 1;
}
// Определяет имя таблицы для устройств и получает запись устройства по ID или по связанному объекту.
$table_name = 'devices';
$rec = SQLSelectOne("SELECT * FROM $table_name WHERE ID='$id'");
if (!$id && gr('linked_object')) {
$rec = SQLSelectOne("SELECT * FROM $table_name WHERE LINKED_OBJECT='" . DBSafe(gr('linked_object')) . "'");
}
// Устанавливает флаг отсутствия навигации, если владелец имеет флаг печати.
if ($this->owner->print == 1) {
$out['NO_NAV'] = 1;
}
// Выполняет дополнительные действия, если связанный объект устройства не пуст.
if (isset($rec['LINKED_OBJECT']) && $rec['LINKED_OBJECT'] != '') {
// Получаем запись объекта по названию связанного объекта
$object_rec = SQLSelectOne("SELECT ID FROM objects WHERE TITLE='" . $rec['LINKED_OBJECT'] . "'");
// Если ID объекта существует, выполняем дополнительные действия
if ($object_rec['ID']) {
// Получаем свойства объекта, связанные с модулями
$properties = SQLSelect("SELECT pvalues.*, properties.TITLE as PROPERTY FROM pvalues LEFT JOIN properties ON properties.ID=pvalues.PROPERTY_ID WHERE pvalues.OBJECT_ID=" . $object_rec['ID'] . " AND pvalues.LINKED_MODULES!='' ORDER BY UPDATED DESC");
// Если свойства найдены, выполняем дополнительные действия
$total = count($properties);
if ($total > 0) {
for ($i = 0; $i < $total; $i++) {
// Разделяем связанные модули по запятым
$linked_modules = explode(',', $properties[$i]['LINKED_MODULES']);
// Экранируем специальные символы в значении свойства
$properties[$i]['VALUE'] = htmlspecialchars($properties[$i]['VALUE']);
// Создаем массив связанных модулей
$properties[$i]['LINKED_MODULES'] = array();
foreach ($linked_modules as $module) {
// Добавляем каждый модуль в массив связанных модулей
$properties[$i]['LINKED_MODULES'][] = array('MODULE' => $module, 'PROPERTY' => $properties[$i]['PROPERTY'], 'OBJECT' => $rec['LINKED_OBJECT']);
}
// Добавляем свойства в выходной массив
$out['LINKED_PROPERTIES'] = $properties;
}
}
}
}
// Инициализирует массив для отображения методов и получает все методы для указанного типа устройства.
$show_methods = array();
if ($rec['TYPE'] != '') {
$methods = $this->getAllMethods($rec['TYPE']);
// Если методы представлены в виде массива, выполняем дополнительные действия
if (is_array($methods)) {
foreach ($methods as $k => $v) {
// Если метод должен быть показан в конфигурации, добавляем его в массив для отображения
if (isset($v['_CONFIG_SHOW']) && $v['_CONFIG_SHOW']) {
$v['NAME'] = $k;
$show_methods[] = $v;
}
}
}
}
// Если есть методы для отображения, сортирует их и добавляет в выходной массив.
if (isset($show_methods[0])) {
usort($show_methods, function ($a, $b) {
if ($a['_CONFIG_SHOW'] == $b['_CONFIG_SHOW']) {
return 0;
}
return ($a['_CONFIG_SHOW'] > $b['_CONFIG_SHOW']) ? -1 : 1;
});
$out['SHOW_METHODS'] = $show_methods;
}
// Добавляет сообщения об успехе или ошибке в выходной массив.
if (gr('ok_msg')) {
$out['OK_MSG'] = gr('ok_msg');
}
if (gr('err_msg')) {
$out['ERR_MSG'] = gr('err_msg');
}
// Выполняет дополнительные действия, если текущая вкладка - 'logic'.
if ($this->tab == 'logic') {
// Получаем имя метода из запроса или устанавливаем его как 'logicAction', если не указано
$method_name = gr('method');
// Получаем объект по связанному объекту устройства
$object = getObject($rec['LINKED_OBJECT']);
// Получаем все методы родительского класса объекта
$methods = $object->getParentMethods($object->class_id, '', 1);
// Если есть методы, выполняем дополнительные действия
$total = count($methods);
for ($i = 0; $i < $total; $i++) {
// Если есть описание метода, добавляем его к названию метода
if ($methods[$i]['DESCRIPTION'] != '') {
$methods[$i]['DESCRIPTION'] = $methods[$i]['TITLE'] . ' - ' . $methods[$i]['DESCRIPTION'];
} else {
$methods[$i]['DESCRIPTION'] = $methods[$i]['TITLE'];
}
// Если связанный объект устройства существует, выполняем дополнительные действия
if (isset($object_rec['ID'])) {
// Получаем метод объекта по названию метода и ID объекта
$object_method = SQLSelectOne("SELECT * FROM methods WHERE TITLE='" . $methods[$i]['TITLE'] . "' AND OBJECT_ID=" . $object_rec['ID'] . " ORDER BY TITLE");
// Если метод объекта существует, выполняем дополнительные действия
if (isset($object_method['ID'])) {
// Добавляем символ '(*)' к описанию метода
$methods[$i]['DESCRIPTION'] .= ' (*)';
// Если имя метода не установлено, устанавливаем его как название метода объекта
if (!$method_name) {
$method_name = $object_method['TITLE'];
}
}
}
}
// Если имя метода не установлено, устанавливаем его как 'logicAction'
if (!$method_name) {
$method_name = 'logicAction';
}
$out['METHOD'] = $method_name;
// Добавляем методы в выходной массив
$out['METHODS'] = $methods;
// Получаем ID метода по имени метода, ID класса объекта и ID объекта
$method_id = $object->getMethodByName($method_name, $object->class_id, $object->id);
// Получаем запись метода по ID
$method_rec = SQLSelectOne("SELECT * FROM methods WHERE ID=" . (int)$method_id);
// Если ID объекта метода не совпадает с ID объекта устройства, создаем новую запись метода
if ($method_rec['OBJECT_ID'] != $object->id) {
$method_rec['CODE'] = '';
}
// Если определены настройки редактора кода, добавляем их в выходной массив
if (defined('SETTINGS_CODEEDITOR_TURNONSETTINGS')) {
$out['SETTINGS_CODEEDITOR_TURNONSETTINGS'] = SETTINGS_CODEEDITOR_TURNONSETTINGS;
$out['SETTINGS_CODEEDITOR_UPTOLINE'] = SETTINGS_CODEEDITOR_UPTOLINE;
$out['SETTINGS_CODEEDITOR_SHOWERROR'] = SETTINGS_CODEEDITOR_SHOWERROR;
}
// Если режим работы - 'update', выполняем дополнительные действия
if ($this->mode == 'update') {
if ($method_rec['OBJECT_ID'] != $object->id) {
$method_rec = array();
$method_rec['OBJECT_ID'] = $object->id;
$method_rec['TITLE'] = $method_name;
$method_rec['CALL_PARENT'] = 1;
$method_rec['ID'] = SQLInsert('methods', $method_rec);
}
$code = gr('code');
// Сохраняем старый код метода
$old_code = $method_rec['CODE'];
// Обновляем код метода новым значением
$method_rec['CODE'] = $code;
$ok = 1;
// Если код метода не пуст, проверяем его на наличие ошибок
if ($method_rec['CODE'] != '') {
$errors = php_syntax_error($method_rec['CODE']);
// Если есть ошибки, обрабатываем их и устанавливаем флаг ошибки
if ($errors) {
$out['ERR_LINE'] = preg_replace('/[^0-9]/', '', substr(stristr($errors, 'php on line '), 0, 18)) - 2;
$out['ERR_CODE'] = 1;
$errorStr = explode('Parse error: ', htmlspecialchars(strip_tags(nl2br($errors))));
$errorStr = explode('Errors parsing', $errorStr[1]);
$errorStr = explode(' in ', $errorStr[0]);
//var_dump($errorStr);
$out['ERRORS'] = $errorStr[0];
$out['ERR_FULL'] = $errorStr[0] . ' ' . $errorStr[1];
$out['ERR_OLD_CODE'] = $old_code;
$ok = 0;
}
} else {
if ($method_rec['ID']) {
SQLExec("DELETE FROM methods WHERE ID=" . $method_rec['ID']);
}
$this->redirect("?id=" . $rec['ID'] . "&view_mode=" . $this->view_mode . "&tab=" . $this->tab . "&method=" . urlencode($method_rec['TITLE']));
}
// Если нет ошибок, обновляем запись метода в базе данных
if ($ok) {
SQLUpdate('methods', $method_rec);
$out['OK'] = 1;
} else {
$out['ERR'] = 1;
}
}
// Добавляем код метода в выходной массив
if (isset($method_rec['CODE'])) {
$out['CODE'] = htmlspecialchars($method_rec['CODE']);
}
// Добавляем ID объекта в выходной массив
$out['OBJECT_ID'] = $method_rec['OBJECT_ID'];
// Получаем ID родительского метода по имени метода, ID класса объекта и ID объекта
$parent_method_id = $object->getMethodByName($method_name, $object->class_id, 0);
// Если есть ID родительского метода, добавляем его в выходной массив
if ($parent_method_id) {
$out['METHOD_ID'] = $parent_method_id;
} else {
// Иначе добавляем ID текущего метода в выходной массив
$out['METHOD_ID'] = $method_rec['ID'];
}
}
// Если текущая вкладка - 'settings', выполняем дополнительные действия
if ($this->tab == 'settings') {
// Получаем все свойства для типа устройства
$properties = $this->getAllProperties($rec['TYPE']);
//print_r($properties);exit; //debug
// Если связанный объект устройства существует и свойства представлены в виде массива, выполняем дополнительные действия
if ($rec['LINKED_OBJECT'] && is_array($properties)) {
$res_properties = array();
$onchanges = array();
$apply_others = gr('apply_others');
foreach ($properties as $k => $v) {
// Если тип конфигурации свойства не пуст, выполняем дополнительные действия
if (isset($v['_CONFIG_TYPE'])) {
// Если режим работы - 'update', выполняем дополнительные действия
if ($this->mode == 'update') {
global ${$k . '_value'};
// Если значение свойства установлено, выполняем дополнительные действия
if (isset(${$k . '_value'})) {
// Если значение свойства - массив, преобразуем его в строку
if (is_array(${$k . '_value'})) {
$value = implode(',', ${$k . '_value'});
} else {
// Иначе очищаем пробелы в начале и конце строки
$value = trim(${$k . '_value'});
}
// Устанавливаем глобальное значение свойства
setGlobal($rec['LINKED_OBJECT'] . '.' . $k, $value);
// Если есть другие устройства для применения, выполняем дополнительные действия
if (is_array($apply_others)) {
foreach ($apply_others as $other_dev) {
// Устанавливаем глобальное значение свойства для других устройств
setGlobal($other_dev . '.' . $k, $value);
// Если есть ограничения доступа для свойства, выполняем дополнительные действия
if ($v['_CONFIG_RESTRICTIONS'] && checkAccessDefined('prop_' . $k, $rec['ID'])) {
$other_obj = getObject($other_dev);
// Если объект существует и имеет ID устройства, копируем права доступа
if (is_object($other_obj) && $other_obj->device_id) {
checkAccessCopy('prop_' . $k, $rec['ID'], $other_obj->device_id);
}
}
}
}
}
// Устанавливаем флаг успешного обновления
$out['OK'] = 1;
// Если есть метод, который должен быть вызван при изменении свойства, добавляем его в массив
if (isset($v['ONCHANGE']) && $v['ONCHANGE'] != '') {
$onchanges[$v['ONCHANGE']] = 1;
}
}
// Добавляем имя свойства в массив свойств
$v['NAME'] = $k;
// Если есть справочная информация для свойства, добавляем ее в массив свойств
if (isset($v['_CONFIG_HELP'])) $v['CONFIG_HELP'] = $v['_CONFIG_HELP'];
// Добавляем тип конфигурации в массив свойств
$v['CONFIG_TYPE'] = $v['_CONFIG_TYPE'];
// Получаем глобальное значение свойства
$v['VALUE'] = getGlobal($rec['LINKED_OBJECT'] . '.' . $k);
// Если тип конфигурации - 'select' или 'multi_select', выполняем дополнительные действия
if ($v['CONFIG_TYPE'] == 'select' || $v['CONFIG_TYPE'] == 'multi_select') {
// Получаем выбранные опции из глобального значения свойства
$selected_options = explode(',', gg($rec['LINKED_OBJECT'] . '.' . $k));
// Разделяем опции по запятым
$tmp = explode(',', $v['_CONFIG_OPTIONS']);
$total = count($tmp);
for ($i = 0; $i < $total; $i++) {
// Разделяем каждую опцию на значение и название
$data_s = explode('=', trim($tmp[$i]));
$value = $data_s[0];
if (isset($data_s[1])) {
$title = $data_s[1];
} else {
$title = $value;
}
// Создаем массив опции
$option = array('VALUE' => $value, 'TITLE' => $title);
// Если значение опции выбрано, устанавливаем флаг выбранной опции
if (in_array($value, $selected_options)) $option['SELECTED'] = 1;
// Добавляем опцию в массив свойств
$v['OPTIONS'][] = $option;
}
} elseif ($v['CONFIG_TYPE'] == 'style_image') {
// Если тип конфигурации - 'style_image', выполняем дополнительные действия
include_once(DIR_MODULES . 'scenes/scenes.class.php');
$scene_class = new scenes();
// Получаем все типы сцен
$styles = $scene_class->getAllTypes();
// Добавляем типы сцен в массив свойств
$v['FOLDERS'] = $styles;
}
// Если есть ограничения доступа для свойства и они определены, устанавливаем флаг установленных ограничений
if (isset($v['_CONFIG_RESTRICTIONS']) && $v['_CONFIG_RESTRICTIONS'] && checkAccessDefined('prop_' . $v['NAME'], $rec['ID'])) {
$v['_CONFIG_RESTRICTIONS_SET'] = 1;
}
// Добавляем свойство в массив результатов
$res_properties[] = $v;
}
}
// Если режим работы - 'update', выполняем дополнительные действия
if ($this->mode == 'update') {
// Вызываем методы, которые должны быть вызваны при изменении свойства
foreach ($onchanges as $k => $v) {
callMethod($rec['LINKED_OBJECT'] . '.' . $k);
}
// Синхронизируем устройство с Homebridge
$this->homebridgeSync($rec['ID'], 1);
}
//print_r($res_properties);exit; // debug
// Добавляем свойства в выходной массив
$out['PROPERTIES'] = $res_properties;
}
//print_r($res_properties);exit; // debug
// Получаем все группы для типа устройства
$groups = $this->getAllGroups($rec['TYPE']);
// Инициализируем глобальную переменную для применения групп
global $apply_groups;
// Если режим работы - 'update', устанавливаем массив применения групп
if ($this->mode == 'update') {
if (!is_array($apply_groups)) {
$apply_groups = array();
}
} else {
$apply_groups = array();
}
// Получаем ID объекта
$total = count($groups);
$object_id = gg($rec['LINKED_OBJECT'] . '.object_id');
// Если есть группы, выполняем дополнительные действия
if ($total > 0) {
for ($i = 0; $i < $total; $i++) {
// Формируем название свойства группы
$property_title = 'group' . $groups[$i]['SYS_NAME'];
// Если режим работы - 'update', выполняем дополнительные действия
if ($this->mode == 'update') {
// Если группа выбрана, устанавливаем значение свойства группы
if (in_array($groups[$i]['SYS_NAME'], $apply_groups)) {
sg($rec['LINKED_OBJECT'] . '.' . $property_title, 1);
} elseif (gg($rec['LINKED_OBJECT'] . '.' . $property_title)) {
// Если группа не выбрана, сбрасываем значение свойства группы
sg($rec['LINKED_OBJECT'] . '.' . $property_title, 0);
// Получаем ID свойства группы
$property_id = current(SQLSelectOne("SELECT ID FROM properties WHERE OBJECT_ID=" . (int)$object_id . " AND TITLE='" . DBSafe($property_title) . "'"));
// Если ID свойства группы существует, удаляем свойство группы
if ($property_id) {
SQLExec("DELETE FROM pvalues WHERE PROPERTY_ID=" . $property_id . " AND OBJECT_ID=" . $object_id);
SQLExec("DELETE FROM properties WHERE ID=" . $property_id);
}
//echo $property_id;exit;
}
}
// Если значение свойства группы установлено, устанавливаем флаг выбранной группы
if (gg($rec['LINKED_OBJECT'] . '.' . $property_title)) {
$groups[$i]['SELECTED'] = 1;
}
}
// Добавляем группы в выходной массив
$out['GROUPS'] = $groups;
}
}
// Если текущая вкладка - 'interface', выполняем дополнительные действия
if ($this->tab == 'interface') {
// Если режим работы - 'update', выполняем дополнительные действия
if ($this->mode == 'update') {
global $add_menu;
global $add_menu_id;
global $add_scene;
global $add_scene_id;
// Если не указана сцена, устанавливаем ID сцены в 0
if (!$add_scene) {
$add_scene_id = 0;
}
// Если не указан ID сцены, устанавливаем сцену в 0
if (!$add_scene_id) {
$add_scene = 0;
}
// Добавляем значения в выходной массив
$out['ADD_MENU'] = $add_menu;
$out['ADD_MENU_ID'] = $add_menu_id;
$out['ADD_SCENE'] = $add_scene;
$out['ADD_SCENE_ID'] = $add_scene_id;
// Если указано добавление в меню, добавляем устройство в меню
if ($out['ADD_MENU']) {
$this->addDeviceToMenu($rec['ID'], $add_menu_id);
}
// Если указано добавление в сцену и ID сцены указан, добавляем устройство в сцену
if ($out['ADD_SCENE'] && $out['ADD_SCENE_ID']) {
$this->addDeviceToScene($rec['ID'], $add_scene_id);
}
// Устанавливаем флаг успешного обновления
$out['OK'] = 1;
}
// Получаем все сцены
$out['SCENES'] = SQLSelect("SELECT ID,TITLE FROM scenes ORDER BY TITLE");
// Получаем все элементы меню
$menu_items = SQLSelect("SELECT ID, TITLE FROM commands ORDER BY PARENT_ID,TITLE");
// Инициализируем массив для элементов меню
$res_items = array();
// Получаем количество элементов меню
$total = count($menu_items);
for ($i = 0; $i < $total; $i++) {
// Если у элемента меню есть подэлементы, добавляем его в массив
$sub = SQLSelectOne("SELECT ID FROM commands WHERE PARENT_ID=" . $menu_items[$i]['ID']);
if (isset($sub['ID'])) {
$res_items[] = $menu_items[$i];
}
}
// Добавляем элементы меню в выходной массив
$out['MENU'] = $res_items;
}
// Если текущая вкладка пуста, выполняем дополнительные действия
if ($this->tab == '') {
// Инициализируем массив для приоритетов
for ($i = 1; $i < 100; $i++) {
$out['PRIORITIES'][] = array('VALUE' => $i);
}
// Получаем переменные
$prefix = gr('prefix');
$out['PREFIX'] = $prefix;
$source_table = gr('source_table');
$out['SOURCE_TABLE'] = $source_table;
$source_table_id = gr('source_table_id');
$out['SOURCE_TABLE_ID'] = $source_table_id;
$type = gr('type');
$out['TYPE'] = $type;
$linked_object = gr('linked_object');
// Если связанный объект не пуст, выполняем дополнительные действия
if ($linked_object != '') {
// Если объект не существует, очищаем связанный объект
if (!getObject($linked_object)) {
$linked_object = '';
}
}
// Добавляем связанный объект в выходной массив
$out['LINKED_OBJECT'] = trim($linked_object);
// Если связанный объект существует и ID устройства не установлен, выполняем дополнительные действия
if ($out['LINKED_OBJECT'] && !$rec['ID']) {
// Получаем запись устройства по связанному объекту
$old_rec = SQLSelectOne("SELECT * FROM devices WHERE LINKED_OBJECT LIKE '" . DBSafe($out['LINKED_OBJECT']) . "'");
// Если запись устройства существует, обновляем текущую запись устройства
if ($old_rec['ID']) {
$rec = $old_rec;
}
}
// Получаем глобальную переменную для добавления заголовка
global $add_title;
// Если заголовок указан, добавляем его в выходной массив
if ($add_title) {
$out['TITLE'] = $add_title;
}
// Если указана таблица источника и ID устройства не установлен, выполняем дополнительные действия
if ($out['SOURCE_TABLE'] && !$rec['ID']) {
// Формируем запрос для выбора устройства
$qry_devices = 1;
// Если тип устройства установлен, добавляем условие выборки по типу устройства
if ($out['TYPE']) {
$qry_devices .= " AND devices.TYPE='" . DBSafe($out['TYPE']) . "'";
}
// Выполняем запрос к базе данных для получения списка существующих устройств
$existing_devices = SQLSelect("SELECT ID, TITLE FROM devices WHERE $qry_devices ORDER BY TITLE");
// Если в результате запроса найдено хотя бы одно устройство, выполняем дополнительные действия
if ($existing_devices[0]['ID']) {
// Устанавливаем флаг наличия существующих устройств
$out['SELECT_EXISTING'] = 1;
// Добавляем список существующих устройств в выходной массив
$out['EXISTING_DEVICES'] = $existing_devices;
}
}
}
// Если текущая вкладка - 'links', выполняем дополнительные действия
if ($this->tab == 'links') {
// Включаем файл с логикой работы с ссылками устройств
include_once(dirname(__FILE__) . '/devices_links.inc.php');
}
// Если текущая вкладка - 'schedule', выполняем дополнительные действия
if ($this->tab == 'schedule') {
// Включаем файл с логикой работы с расписанием устройств
include_once(dirname(__FILE__) . '/devices_schedule.inc.php');
}
// Если режим работы - 'update' и текущая вкладка пуста, выполняем дополнительные действия
if ($this->mode == 'update' && $this->tab == '') {
$added = 0;
$ok = 1;
// Получаем название устройства из запроса и удаляем пробелы в начале и конце строки
$rec['TITLE'] = gr('title', 'trim');
// Если название устройства пустое, устанавливаем флаг ошибки
if ($rec['TITLE'] == '') {
$out['ERR_TITLE'] = 1;
$ok = 0;
}
// Получаем альтернативные названия устройства из запроса и удаляем пробелы в начале и конце строки
$rec['ALT_TITLES'] = gr('alt_titles', 'trim');
// Получаем тип устройства из глобальной переменной
$rec['TYPE'] = $type;
// Если тип устройства пустой, устанавливаем флаг ошибки
if ($rec['TYPE'] == '') {
$out['ERR_TYPE'] = 1;
$ok = 0;
}
// Получаем ID локации из глобальной переменной
global $location_id;
$rec['LOCATION_ID'] = (int)$location_id;
// Если устройство отмечено как избранное, устанавливаем приоритет избранного
if (gr('favorite', 'int')) {
$rec['FAVORITE'] = gr('favorite_priority', 'int');
} else {
$rec['FAVORITE'] = 0;
}
// Устанавливаем флаг системного устройства
$rec['SYSTEM_DEVICE'] = gr('system_device', 'int');
// Устанавливаем флаг архивированного устройства
$rec['ARCHIVED'] = gr('archived', 'int');
// Получаем связанный объект устройства из глобальной переменной
$rec['LINKED_OBJECT'] = $linked_object;
// Если связанный объект устройства не пуст и ID устройства не установлен, выполняем дополнительные действия
if ($rec['LINKED_OBJECT'] && !$rec['ID']) {
// Проверяем, существует ли уже устройство с таким связанным объектом
$other_device = SQLSelectOne("SELECT ID FROM devices WHERE LINKED_OBJECT LIKE '" . DBSafe($rec['LINKED_OBJECT']) . "'");
// Если устройство с таким связанным объектом уже существует, устанавливаем флаг ошибки
if ($other_device['ID']) {
$out['ERR_LINKED_OBJECT'] = 1;
$ok = 0;
}
}
// Получаем флаг добавления нового объекта из глобальной переменной
global $add_object;
$out['ADD_OBJECT'] = $add_object;
// Если флаг добавления нового объекта установлен, очищаем связанный объект устройства
if ($add_object) {
$rec['LINKED_OBJECT'] = '';
}
// Обновляем структуру устройств
if ($ok) {
$this->renderStructure();
// Если устройство уже существует, обновляем его запись
if ($rec['ID']) {
SQLUpdate($table_name, $rec); // update
} else {
$new_rec = 1;
// Если устройство добавляется, создаем новую запись устройства
$rec['ID'] = SQLInsert($table_name, $rec); // adding new record
$added = 1;
}
// Если устройство связано с локацией, выполняем дополнительные действия
if ($rec['LOCATION_ID']) {
// Получаем название объекта локации
$location_title = getRoomObjectByLocation($rec['LOCATION_ID'], 1);
}
// Устанавливаем флаг успешного обновления
$out['OK'] = 1;
// Если тип устройства не пуст, выполняем дополнительные действия
// Получаем детали типа устройства
$type_details = $this->getTypeDetails($rec['TYPE']);
// Если связанный объект устройства не пуст и флаг добавления нового объекта установлен, выполняем дополнительные действия
if (!$rec['LINKED_OBJECT'] && $out['ADD_OBJECT']) {
// Формируем новое название связанного объекта
$prefix = $out['PREFIX'] . ucfirst($rec['TYPE']);
$new_object_title = $prefix . $this->getNewObjectIndex($type_details['CLASS'], $prefix);
// Добавляем новый объект с новым названием
$object_id = addClassObject($type_details['CLASS'], $new_object_title, 'sdevice' . $rec['ID']);
// Устанавливаем новое название связанного объекта устройства
$rec['LINKED_OBJECT'] = $new_object_title;
// Обновляем запись устройства с новым названием связанного объекта
SQLUpdate('devices', $rec);
}
// Добавляем объект устройства с текущим названием
$object_id = addClassObject($type_details['CLASS'], $rec['LINKED_OBJECT'], 'sdevice' . $rec['ID']);
// Получаем ID класса объекта
$class_id = current(SQLSelectOne("SELECT ID FROM classes WHERE TITLE LIKE '" . DBSafe($type_details['CLASS']) . "'"));
// Если класс объекта изменился, выполняем дополнительные действия
$object_rec = SQLSelectOne("SELECT * FROM objects WHERE ID=" . $object_id);
// Устанавливаем описание объекта
$object_rec['DESCRIPTION'] = $rec['TITLE'];
// Устанавливаем ID локации объекта
$object_rec['LOCATION_ID'] = $rec['LOCATION_ID'];
$class_changed = 0;
$class_2b_changed = 1;
$tmp_class_id = $object_rec['CLASS_ID'];
// Проверяем, изменился ли класс объекта
while (isset($tmp_class_id)) {
if ($tmp_class_id == $class_id) {
$class_2b_changed = 0;
break;
}
$tmp = SQLSelectOne("SELECT PARENT_ID FROM classes WHERE ID=" . (int)$tmp_class_id);
$tmp_class_id = (int)$tmp['PARENT_ID'];
}
if ($class_2b_changed) {
// Если класс объекта изменился, обновляем ID класса объекта
$object_rec['CLASS_ID'] = $class_id;
$class_changed = 1;
}
// Обновляем запись объекта в базе данных
SQLUpdate('objects', $object_rec);
// Если класс объекта изменился, вызываем функцию для обработки изменения класса
if ($class_changed) {
objectClassChanged($object_rec['ID']);
}
// Если устройство связано с локацией, выполняем дополнительные действия
if ($location_title) {
// Устанавливаем глобальное значение для связи устройства с локацией
setGlobal($object_rec['TITLE'] . '.linkedRoom', $location_title);
}
// Если устройство добавлено и имеет свойства, устанавливаем значения свойств по умолчанию
if ($added && is_array($type_details['PROPERTIES'])) {
foreach ($type_details['PROPERTIES'] as $property => $details) {
// Если для свойства определено значение по умолчанию, устанавливаем его
if (isset($details['_CONFIG_DEFAULT'])) {
setGlobal($object_rec['TITLE'] . '.' . $property, $details['_CONFIG_DEFAULT']);
}
}
}
// Если устройство добавлено и имеет тип 'sensor_temp', устанавливаем значения свойств по умолчанию
if ($added && $rec['TYPE'] == 'sensor_temp') {
setGlobal($object_rec['TITLE'] . '.minValue', 16);
setGlobal($object_rec['TITLE'] . '.maxValue', 25);
}
// Если устройство добавлено и имеет тип 'sensor_humidity', устанавливаем значения свойств по умолчанию
if ($added && $rec['TYPE'] == 'sensor_humidity') {
setGlobal($object_rec['TITLE'] . '.minValue', 30);
setGlobal($object_rec['TITLE'] . '.maxValue', 60);
}
// Очищаем кэш данных
clearCacheData();
// Добавляем задачу в очередь для синхронизации устройств
addToOperationsQueue('connect_sync_devices', 'required');
// Если устройство связано с таблицей источника, выполняем дополнительные действия
if ($out['SOURCE_TABLE'] && $out['SOURCE_TABLE_ID']) {
// Добавляем устройство в таблицу источника
$this->addDeviceToSourceTable($out['SOURCE_TABLE'], $out['SOURCE_TABLE_ID'], $rec['ID']);
}
// Синхронизируем устройство с Homebridge
$this->homebridgeSync($rec['ID'], 1);
// Если устройство добавлено, перенаправляем на вкладку настроек устройства
if ($added) {
$this->redirect("?view_mode=edit_devices&id=" . $rec['ID'] . "&tab=settings");
}
} else {
$out['ERR'] = 1;
}
}
if (is_array($rec)) {
foreach ($rec as $k => $v) {
// Проверяем, что значение не является массивом и не пустое
if ($v && !is_array($v)) {
// Экранируем специальные символы в значении свойства для предотвращения XSS атак
$rec[$k] = htmlspecialchars($v);
}
}
}
if (!isset($rec['LOCATION_ID'])) {
// Получаем ID локации из глобальной переменной
$rec['LOCATION_ID'] = gr('location_id', 'int');
}
// Выполняем функцию для обработки хэша
outHash($rec, $out);
// Инициализируем массив для типов устройств
$types = array();
// Проходим по всем типам устройств
foreach ($this->device_types as $k => $v) {
// Если у типа устройства есть название, добавляем его в массив типов
if (isset($v['TITLE'])) {
$types[] = array('NAME' => $k, 'TITLE' => $v['TITLE']);
}
// Если текущий тип устройства совпадает с типом устройства в записи и тип устройства не пуст, устанавливаем название типа устройства в выходной массив
if (isset($rec['TYPE']) && $k == $rec['TYPE'] && $rec['TYPE'] != '') {
$out['TYPE_TITLE'] = $v['TITLE'];
}
}
if ($rec['LINKED_OBJECT']) {
$processed = $this->processDevice($rec['ID']);
$out['HTML'] = $processed['HTML'];
}
// Сортируем типы устройств по алфавиту
usort($types, function ($a, $b) {
return strcmp($a['TITLE'], $b['TITLE']);
});
// Добавляем отсортированные типы устройств в выходной массив
$out['TYPES'] = $types;
// Получаем все локации
$out['LOCATIONS'] = SQLSelect("SELECT ID, TITLE FROM locations ORDER BY TITLE+0");
// Если устройство связано с локацией, выполняем дополнительные действия
if ($rec['LOCATION_ID']) {
// Получаем запись локации по ID
$location_rec = SQLSelectOne("SELECT ID,TITLE FROM locations WHERE ID=" . $rec['LOCATION_ID']);
// Обрабатываем название локации и добавляем его в выходной массив
$out['LOCATION_TITLE'] = processTitle($location_rec['TITLE']);
// Получаем все устройства, связанные с текущей локацией
$other_devices = SQLSelect("SELECT ID, TITLE, ARCHIVED FROM devices WHERE LOCATION_ID=" . (int)$rec['LOCATION_ID'] . " ORDER BY TITLE");
// Добавляем список устройств в выходной массив
$out['OTHER_DEVICES'] = $other_devices;
}
// Если тип устройства не пуст, выполняем дополнительные действия
if ($rec['TYPE']) {
// Получаем все устройства, связанные с текущим типом устройства
$other_devices_type = SQLSelect("SELECT ID, TITLE, ARCHIVED, LINKED_OBJECT FROM devices WHERE TYPE='" . $rec['TYPE'] . "' ORDER BY TITLE");
// Добавляем список устройств в выходной массив
$out['OTHER_DEVICES_TYPE'] = $other_devices_type;
}