Modules/devices/processCommand inc php: различия между версиями
Материал из MajorDoMo инфо
Elmax (обсуждение | вклад) (Заготовка) |
Elmax (обсуждение | вклад) (+ файл processCommand.inc.php) |
||
Строка 3: | Строка 3: | ||
<pre> | <pre> | ||
<?php | |||
// Проверяет, отключены ли простые устройства в файле конфигурации ROOT . config.php. Если да, прекращает выполнение скрипта. | |||
if (defined('DISABLE_SIMPLE_DEVICES') && DISABLE_SIMPLE_DEVICES == 1) return; | |||
/* | |||
* array('level' => $level, 'message' => $ph, 'member_id' => $member_id, 'source' => $source) | |||
* $details['BREAK'] = 1 / 0 | |||
*/ | |||
// Этот блок кода, вероятно, предназначен для обработки лога или отладки, так как он содержит пример использования переменной $details['BREAK']. | |||
// Однако, поскольку он закомментирован, его выполнение в текущем состоянии скрипта не происходит. | |||
// Включаем файлы локализации для текущего языка сайта и по умолчанию. | |||
@include_once(ROOT . 'languages/' . $this->name . '_' . SETTINGS_SITE_LANGUAGE . '.php'); | |||
@include_once(ROOT . 'languages/' . $this->name . '_default' . '.php'); | |||
// Если в деталях команды указано источник (терминал), то получаем информацию о терминале. | |||
if ($details['source']) { | |||
$terminal = getTerminalByID(str_replace("terminal", "", $details['source'])); | |||
// Если у терминала есть ID местоположения, сохраняем его. | |||
if ($terminal['LOCATION_ID']) { | |||
$location_id = $terminal['LOCATION_ID']; | |||
} | |||
} | |||
/* | |||
* Этот фрагмент кода анализирует входящую команду на предмет наличия указаний на задержку выполнения, | |||
* или продолжительность выполнения действия. | |||
* Если такие указания присутствуют, код вычисляет соответствующие значения в секундах | |||
* и сохраняет их в переменных $period_delay и $period_run_for соответственно. | |||
* Также код сохраняет найденное совпадение в переменную $add_phrase, чтобы потом добавить его к сообщению. | |||
*/ | |||
// Получаем текстовую команду из массива $details, который содержит детали сообщения. | |||
$command = $details['message']; | |||
// Инициализируем переменную $run_code как пустую строку. Эта переменная будет использоваться для хранения кода, который нужно выполнить. | |||
$run_code = ''; | |||
// Инициализируем переменную $opposite_code как пустую строку. Эта переменная будет использоваться для хранения кода, который будет выполнен в качестве противодействия к основному коду. | |||
$opposite_code = ''; | |||
// Инициализируем переменную $add_phrase как пустую строку. Эта переменная будет использоваться для хранения дополнительной фразы, которая будет добавлена к сообщению. | |||
$add_phrase = ''; | |||
// Инициализируем переменную $period_delay как 0. Эта переменная будет использоваться для хранения задержки выполнения команды в секундах. | |||
$period_delay = 0; | |||
// Инициализируем переменную $period_run_for как 0. Эта переменная будет использоваться для хранения продолжительности выполнения команды в секундах. | |||
$period_run_for = 0; | |||
// Проверяем, содержит ли команда фразу, указывающую на необходимость выполнения действия после определенного времени. | |||
if (preg_match('/' . LANG_PATTERN_DO_AFTER . ' (\d+?) (' . LANG_PATTERN_SECOND . '|' . LANG_PATTERN_MINUTE . '|' . LANG_PATTERN_HOUR . ')/uis', textToNumbers($command), $m)) { | |||
// Получаем числовое значение времени задержки из найденного совпадения. | |||
$period_number = $m[1]; | |||
// Добавляем найденное совпадение к переменной $add_phrase, чтобы потом добавить его к сообщению. | |||
$add_phrase = ' ' . $m[0]; | |||
// Определяем единицу измерения времени (секунды, минуты, часы) и вычисляем задержку в секундах. | |||
if (preg_match('/' . LANG_PATTERN_SECOND . '/uis', $m[2])) { | |||
// Если единица измерения - секунды, то задержка равна числовому значению. | |||
$period_delay = $period_number; | |||
} elseif (preg_match('/' . LANG_PATTERN_MINUTE . '/uis', $m[2])) { | |||
// Если единица измерения - минуты, то задержка равна числовому значению, умноженному на 60. | |||
$period_delay = $period_number * 60; | |||
} elseif (preg_match('/' . LANG_PATTERN_HOUR . '/uis', $m[2])) { | |||
// Если единица измерения - часы, то задержка равна числовому значению, умноженному на 3600. | |||
$period_delay = $period_number * 60 * 60; | |||
} | |||
// Удаляем обработанную часть команды, чтобы оставить только саму команду без указания времени задержки. | |||
$command = trim(str_replace($m[0], '', textToNumbers($command))); | |||
} elseif (preg_match('/' . LANG_PATTERN_DO_FOR . ' (\d+?) (' . LANG_PATTERN_SECOND . '|' . LANG_PATTERN_MINUTE . '|' . LANG_PATTERN_HOUR . ')/uis', textToNumbers($command), $m)) { | |||
// Получаем числовое значение времени выполнения из найденного совпадения. | |||
$period_number = $m[1]; | |||
// Добавляем найденное совпадение к переменной $add_phrase, чтобы потом добавить его к сообщению. | |||
$add_phrase = ' ' . $m[0]; | |||
// Определяем единицу измерения времени (секунды, минуты, часы) и вычисляем продолжительность выполнения в секундах. | |||
if (preg_match('/' . LANG_PATTERN_SECOND . '/uis', $m[2])) { | |||
// Если единица измерения - секунды, то продолжительность выполнения равна числовому значению. | |||
$period_run_for = $period_number; | |||
} elseif (preg_match('/' . LANG_PATTERN_MINUTE . '/uis', $m[2])) { | |||
// Если единица измерения - минуты, то продолжительность выполнения равна числовому значению, умноженному на 60. | |||
$period_run_for = $period_number * 60; | |||
} elseif (preg_match('/' . LANG_PATTERN_HOUR . '/uis', $m[2])) { | |||
// Если единица измерения - часы, то продолжительность выполнения равна числовому значению, умноженному на 3600. | |||
$period_run_for = $period_number * 60 * 60; | |||
} | |||
// Удаляем обработанную часть команды, чтобы оставить только саму команду без указания времени выполнения. | |||
$command = trim(str_replace($m[0], '', textToNumbers($command))); | |||
} | |||
// Инициализируем переменную $processed как 0. Эта переменная будет использоваться для отслеживания, была ли команда обработана. | |||
$processed = 0; | |||
// Инициализируем переменную $reply_confirm как 0. Эта переменная будет использоваться для подтверждения выполнения команды. | |||
$reply_confirm = 0; | |||
// Инициализируем переменную $reply_say как пустую строку. Эта переменная будет использоваться для хранения сообщения, которое будет отправлено в ответ на команду. | |||
$reply_say = ''; | |||
// Инициализируем переменную $phpmorphy_loaded как 0. Эта переменная будет использоваться для отслеживания, загружена ли библиотека phpMorphy. | |||
$phpmorphy_loaded = 0; | |||
// Проверяем, существует ли файл библиотеки phpMorphy. | |||
if (file_exists(ROOT . "lib/phpmorphy/common.php")) { | |||
// Подключаем файл библиотеки phpMorphy. | |||
require_once(ROOT . "lib/phpmorphy/common.php"); | |||
$opts = array( | |||
// Указываем тип хранения данных. | |||
'storage' => PHPMORPHY_STORAGE_MEM, | |||
// Включаем предсказание по суффиксу. | |||
'predict_by_suffix' => true, | |||
// Включаем предсказание по базе данных. | |||
'predict_by_db' => true, | |||
// Указываем, что грамматическая информация должна быть представлена в виде текста. | |||
'graminfo_as_text' => true, | |||
); | |||
// Указываем путь к словарям phpMorphy. | |||
$dir = ROOT . 'lib/phpmorphy/dicts'; | |||
// Получаем код текущего языка сайта. | |||
$lang = SETTINGS_SITE_LANGUAGE_CODE; | |||
try { | |||
// Создаем экземпляр класса phpMorphy. | |||
$morphy = new phpMorphy($dir, $lang, $opts); | |||
// Сохраняем ссылку на созданный экземпляр в свойстве объекта. | |||
$this->morphy = &$morphy; | |||
} catch (phpMorphy_Exception $e) { | |||
// Выводим сообщение об ошибке и прерываем выполнение скрипта. | |||
die('Error occured while creating phpMorphy instance: ' . PHP_EOL . $e); | |||
} | |||
// Разбиваем команду на слова. | |||
$words = explode(' ', $command); | |||
// Инициализируем массив для хранения отфильтрованных слов. | |||
$words_filtered = array(); | |||
// Инициализируем счетчик отфильтрованных слов. | |||
$filtered_count = 0; | |||
// Инициализируем массив для хранения базовых форм слов. | |||
$base_forms = array(); | |||
// Инициализируем массив для хранения базовых форм отфильтрованных слов. | |||
$base_forms_filtered = array(); | |||
// Получаем общее количество слов в команде. | |||
$totals = count($words); | |||
for ($is = 0; $is < $totals; $is++) { | |||
// Инициализируем переменную для отслеживания, было ли слово фильтровано. | |||
$filtered = 0; | |||
// Преобразуем слово в верхний регистр. | |||
$upper = mb_strtoupper($words[$is], 'UTF-8'); | |||
// Получаем длину слова. | |||
$len = mb_strlen($words[$is], 'UTF-8'); | |||
// Если длина слова больше или равна 3, считаем его достаточно длинным для анализа. | |||
if ($len >= 3) { | |||
// Добавляем слово в массив отфильтрованных слов. | |||
$words_filtered[] = $words[$is]; | |||
// Помечаем слово как отфильтрованное. | |||
$filtered = 1; | |||
// Увеличиваем счетчик отфильтрованных слов. | |||
$filtered_count++; | |||
} | |||
// Если слово является числом, добавляем его в массив базовых форм. | |||
if (preg_match('/^(\d+)$/', $words[$is])) { | |||
$base_forms[$is] = array($words[$is]); | |||
// Если слово не содержит специальных символов, получаем его базовую форму. | |||
} elseif (!preg_match('/[\(\)\+\.]/', $words[$is])) { | |||
// Преобразуем слово в верхний регистр. | |||
$Word = mb_strtoupper($words[$is], 'UTF-8'); | |||
// Получаем базовую форму слова. | |||
$base_forms[$is] = $morphy->getBaseForm($Word); | |||
// Добавляем исходное слово в массив базовых форм. | |||
$base_forms[$is][] = $words[$is]; | |||
// Если слово содержит специальные символы, добавляем его в массив базовых форм без изменений. | |||
} else { | |||
$base_forms[$is] = array($words[$is]); | |||
} | |||
// Если слово было отфильтровано, добавляем его базовую форму в массив отфильтрованных базовых форм. | |||
if ($filtered) { | |||
$base_forms_filtered[$filtered_count - 1] = $base_forms[$is]; | |||
} | |||
} | |||
// Генерируем все возможные комбинации базовых форм слов. | |||
$combos = $this->generate_combinations($base_forms); | |||
// Если количество отфильтрованных слов меньше общего количества слов, генерируем дополнительные комбинации. | |||
if ($filtered_count < $totals) { | |||
// Генерируем комбинации для отфильтрованных базовых форм. | |||
$add_combos = $this->generate_combinations($base_forms_filtered); | |||
// Добавляем каждую сгенерированную комбинацию в общий массив комбинаций. | |||
foreach ($add_combos as $cmb) { | |||
$combos[] = $cmb; | |||
} | |||
} | |||
// Инициализируем массив для хранения строк, полученных из комбинаций. | |||
$lines = array(); | |||
// Получаем общее количество комбинаций. | |||
$totals = count($combos); | |||
// Преобразуем каждую комбинацию в строку и добавляем ее в массив строк. | |||
for ($is = 0; $is < $totals; $is++) { | |||
$lines[] = implode(' ', $combos[$is]); | |||
} | |||
// Помечаем, что библиотека phpMorphy была успешно загружена. | |||
$phpmorphy_loaded = 1; | |||
} | |||
// Получаем список устройств из базы данных. | |||
$devices = SQLSelect("SELECT ID, TITLE, ALT_TITLES, TYPE, LINKED_OBJECT, LOCATION_ID FROM devices"); | |||
// Проходим по каждому устройству в полученном списке. | |||
foreach ($devices as $device) { | |||
// Если у устройства есть альтернативные названия. | |||
if (trim($device['ALT_TITLES']) != '') { | |||
// Разбиваем альтернативные названия по запятой. | |||
$nicknames = explode(',', trim($device['ALT_TITLES'])); | |||
// Проходим по каждому альтернативному названию. | |||
foreach ($nicknames as $nickname) { | |||
// Копируем текущее устройство. | |||
$add_rec = $device; | |||
// Заменяем название устройства на альтернативное. | |||
$add_rec['TITLE'] = $nickname; | |||
// Добавляем измененное устройство обратно в список устройств. | |||
$devices[] = $add_rec; | |||
} | |||
} | |||
} | |||
// Получаем список групп устройств из базы данных. | |||
$groups = SQLSelect("SELECT * FROM devices_groups"); | |||
// Получаем общее количество групп. | |||
$total = count($groups); | |||
// Проходим по каждой группе в полученном списке. | |||
for ($i = 0; $i < $total; $i++) { | |||
// Копируем текущую группу. | |||
$add_rec = $groups[$i]; | |||
// Устанавливаем тип группы как 'group'. | |||
$add_rec['TYPE'] = 'group'; | |||
// Добавляем группу обратно в список устройств. | |||
$devices[] = $add_rec; | |||
} | |||
// Получаем список комнат с устройствами из базы данных. | |||
$rooms = SQLSelect("SELECT locations.ID, locations.TITLE, COUNT(*) AS TOTAL FROM locations, devices WHERE locations.ID=devices.LOCATION_ID GROUP BY locations.ID"); | |||
// Проходим по каждой комнате в полученном списке. | |||
foreach ($rooms as $room) { | |||
//lights | |||
//if ($room['TITLE']=='Кабинет') { | |||
// Инициализируем массив для хранения типов устройств в комнате. | |||
$device_types = array(); | |||
// Получаем список устройств типа 'relay' в текущей комнате. | |||
$room_devices = SQLSelect("SELECT * FROM devices WHERE LOCATION_ID=" . $room['ID'] . " AND TYPE='relay'"); | |||
// Проходим по каждому устройству в полученном списке. | |||
foreach ($room_devices as $device) { | |||
// Получаем тип нагрузки устройства. | |||
$loadType = gg($device['LINKED_OBJECT'] . '.loadType'); | |||
// Добавляем устройство в массив типов устройств. | |||
$device_types[$loadType][] = $device; | |||
} | |||
// Если в комнате есть устройства типа 'light'. | |||
if (isset($device_types['light'])) { | |||
// Инициализируем массив для новой группы устройств. | |||
$add_rec = array(); | |||
// Устанавливаем тип группы как 'group'. | |||
$add_rec['TYPE'] = 'group'; | |||
// Устанавливаем название группы. | |||
$add_rec['TITLE'] = LANG_DEVICES_LOADTYPE_LIGHT . ' ' . $room['TITLE']; | |||
// Добавляем устройства типа 'light' в группу. | |||
$add_rec['DEVICES'] = $device_types['light']; | |||
// Устанавливаем типы применения группы. | |||
$add_rec['APPLY_TYPES'] = 'relay'; | |||
// Добавляем группу обратно в список устройств. | |||
$devices[] = $add_rec; | |||
// Инициализируем массив для новой группы устройств. | |||
$add_rec = array(); | |||
// Устанавливаем тип группы как 'group'. | |||
$add_rec['TYPE'] = 'group'; | |||
// Устанавливаем альтернативное название группы. | |||
$add_rec['TITLE'] = LANG_DEVICES_LOADTYPE_LIGHT_ALT . ' ' . $room['TITLE']; | |||
// Добавляем устройства типа 'light' в группу. | |||
$add_rec['DEVICES'] = $device_types['light']; | |||
// Устанавливаем типы применения группы. | |||
$add_rec['APPLY_TYPES'] = 'relay'; | |||
// Добавляем группу обратно в список устройств. | |||
$devices[] = $add_rec; | |||
} | |||
//} | |||
} | |||
// Если библиотека phpMorphy была успешно загружена. | |||
if ($phpmorphy_loaded) { | |||
// Получаем общее количество устройств. | |||
$total = count($devices); | |||
// Инициализируем массив для хранения дополнительных устройств. | |||
$add_devices = array(); | |||
// Проходим по каждому устройству в полученном списке. | |||
for ($i = 0; $i < $total; $i++) { | |||
// Получаем название устройства. | |||
$device_title = $devices[$i]['TITLE']; | |||
// Разбиваем название устройства на слова и преобразуем их в верхний регистр. | |||
$words = explode(' ', mb_strtoupper($device_title, 'UTF-8')); | |||
// Инициализируем массив для хранения базовых форм слов. | |||
$base_forms = array(); | |||
// Получаем общее количество слов. | |||
$totals = count($words); | |||
// Проходим по каждому слову в полученном списке. | |||
for ($is = 0; $is < $totals; $is++) { | |||
// Если слово является числом, добавляем его в массив базовых форм. | |||
if (preg_match('/^(\d+)$/', $words[$is])) { | |||
$base_forms[$is] = array($words[$is]); | |||
// Если слово не содержит специальных символов, получаем его базовую форму. | |||
} elseif (!preg_match('/[\(\)\+\.]/', $words[$is])) { | |||
// Преобразуем слово в верхний регистр. | |||
$Word = mb_strtoupper($words[$is], 'UTF-8'); | |||
// Получаем базовую форму слова. | |||
$base_form = $morphy->getBaseForm($Word); | |||
// Если базовая форма представлена в виде массива. | |||
if (is_array($base_form)) { | |||
$base_forms[$is] = $base_form; | |||
// Если базовая форма не представлена в виде массива. | |||
} else { | |||
$base_forms[$is] = array(); | |||
} | |||
// Если исходное слово не содержится в массиве базовых форм. | |||
if (!in_array($words[$is], $base_forms[$is])) { | |||
// Добавляем исходное слово в массив базовых форм. | |||
$base_forms[$is][] = $words[$is]; | |||
} | |||
// Если слово содержит специальные символы, добавляем его в массив базовых форм без изменений. | |||
} else { | |||
$base_forms[$is] = array($words[$is]); | |||
} | |||
} | |||
// Генерируем все возможные комбинации базовых форм слов. | |||
$combos = $this->generate_combinations($base_forms); | |||
// Инициализируем массив для хранения фраз, полученных из комбинаций. | |||
$phrases = array(); | |||
// Проходим по каждой комбинации в полученном списке. | |||
foreach ($combos as $combo) { | |||
// Вычисляем все возможные перестановки для текущей комбинации. | |||
$mutations = $this->computePermutations($combo); | |||
// Проходим по каждой перестановке в полученном списке. | |||
foreach ($mutations as $m) { | |||
// Преобразуем каждую перестановку в строку и добавляем ее в массив фраз. | |||
$phrases[] = implode(' ', $m); | |||
} | |||
} | |||
// Инициализируем массив для хранения новых названий устройств. | |||
$device_titles = array(); | |||
// Получаем общее количество фраз. | |||
$totals = count($phrases); | |||
// Проходим по каждой фразе в полученном списке. | |||
for ($is = 0; $is < $totals; $is++) { | |||
// Получаем новое название устройства. | |||
$new_title = $phrases[$is]; | |||
// Добавляем новое название устройства в массив новых названий. | |||
$device_titles[] = $new_title; | |||
// Копируем текущее устройство. | |||
$new_device = $devices[$i]; | |||
// Заменяем название устройства на новое. | |||
$new_device['TITLE'] = $new_title; | |||
// Сохраняем оригинальное название устройства. | |||
$new_device['ORIGINAL_TITLE'] = $device_title; | |||
// Добавляем измененное устройство в массив дополнительных устройств. | |||
$add_devices[] = $new_device; | |||
} | |||
} | |||
// Проходим по каждому устройству в массиве дополнительных устройств. | |||
foreach ($add_devices as $device) { | |||
// Добавляем устройство обратно в список устройств. | |||
$devices[] = $device; | |||
} | |||
} | |||
// Выводим содержимое переменной $lines для отладки. | |||
//dprint($lines,false); | |||
// Выводим содержимое переменной $devices для отладки. | |||
//dprint($devices); | |||
// Инициализируем переменную $compare_title командой. | |||
$compare_title = $command; | |||
// Проверяем, содержит ли команда фразу, указывающую на необходимость включения устройства. | |||
if (preg_match('/' . LANG_DEVICES_PATTERN_TURNON . '/uis', $compare_title, $m)) { | |||
// Если да, удаляем эту фразу из команды. | |||
$compare_title = trim(str_replace($m[0], ' ', $compare_title)); | |||
} | |||
// Проверяем, содержит ли команда фразу, указывающую на необходимость выключения устройства. | |||
if (preg_match('/' . LANG_DEVICES_PATTERN_TURNOFF . '/uis', $compare_title, $m)) { | |||
// Если да, удаляем эту фразу из команды. | |||
$compare_title = trim(str_replace($m[0], ' ', $compare_title)); | |||
} | |||
// Удаляем начальные слова "ть" и "те" из команды, если они присутствуют. | |||
$compare_title = trim(preg_replace('/^ть /', '', $compare_title)); | |||
$compare_title = trim(preg_replace('/^те /', '', $compare_title)); | |||
// Если после всех преобразований команда стала пустой, прекращаем выполнение скрипта. | |||
if ($compare_title == '') { | |||
return; | |||
} | |||
// Получаем общее количество устройств. | |||
$total = count($devices); | |||
// Проходим по каждому устройству в полученном списке. | |||
for ($i = 0; $i < $total; $i++) { | |||
// Инициализируем переменную для отслеживания, было ли найдено соответствие устройства. | |||
$device_matched = 0; | |||
// Если указано местоположение терминала. | |||
if ($location_id) { | |||
// Ищем строгое соответствие по названию и местоположению. | |||
foreach ($devices as $key => $value) { | |||
// Если ID местоположения устройства совпадает с ID местоположения терминала и название устройства совпадает с командой. | |||
if (in_array($location_id, $value) && strtolower($devices[$key]['TITLE']) == strtolower($compare_title)) { | |||
// Обновляем индекс текущего устройства. | |||
$i = $key; | |||
// Помечаем, что устройство найдено. | |||
$device_matched = 1; | |||
// Прерываем цикл. | |||
break; | |||
} | |||
} | |||
// Если устройство не найдено. | |||
if (!$device_matched) { | |||
// Ищем строгое соответствие по названию. | |||
foreach ($devices as $key => $value) { | |||
// Если название устройства совпадает с командой. | |||
if (in_array(strtolower($compare_title), strtolower($value))) { | |||
// Обновляем индекс текущего устройства. | |||
$i = $key; | |||
// Помечаем, что устройство найдено. | |||
$device_matched = 1; | |||
// Прерываем цикл. | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
// Ищем по старому принципу. | |||
if (preg_match('/' . preg_quote($devices[$i]['TITLE']) . '/uis', $compare_title)) { | |||
// Помечаем, что устройство найдено. | |||
$device_matched = 1; | |||
} elseif (preg_match('/' . preg_quote($compare_title) . '/uis', $devices[$i]['TITLE'])) { | |||
// Помечаем, что устройство найдено. | |||
$device_matched = 1; | |||
// Если библиотека phpMorphy была успешно загружена. | |||
} elseif ($phpmorphy_loaded) { | |||
if (preg_match('/' . preg_quote($devices[$i]['TITLE']) . '/isu', implode('@@@@', $lines), $matches)) { | |||
// Помечаем, что устройство найдено. | |||
$device_matched = 1; | |||
} | |||
} | |||
/* | |||
if (preg_match('/свет над столом/uis',$devices[$i]['TITLE'])) { | |||
dprint($devices[$i]['TITLE'].' - '.$compare_title.': '.$device_matched); | |||
} | |||
*/ | |||
// Если устройство было найдено. | |||
if ($device_matched) { | |||
// Найдено устройство. | |||
// Получаем ID устройства. | |||
$device_id = $devices[$i]['ID']; | |||
// Получаем тип устройства. | |||
$device_type = $devices[$i]['TYPE']; | |||
// Если у устройства есть оригинальное название. | |||
if ($devices[$i]['ORIGINAL_TITLE'] != '') { | |||
// Используем оригинальное название. | |||
$device_title = $devices[$i]['ORIGINAL_TITLE']; | |||
// Если оригинального названия нет. | |||
} else { | |||
// Используем текущее название. | |||
$device_title = $devices[$i]['TITLE']; | |||
} | |||
// Записываем сообщение о том, что устройство было найдено. | |||
DebMes("Device found for $command ($device_title)", 'simple_devices'); | |||
// Получаем связанный объект устройства. | |||
$linked_object = $devices[$i]['LINKED_OBJECT']; | |||
if ($device_type == 'sensor_percentage' || $device_type == 'sensor_humidity') { | |||
// Формируем сообщение для датчиков с процентами и влажностью. | |||
$reply_say = $device_title . ' ' . gg($linked_object . '.value') . '%'; | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
} elseif ($device_type == 'sensor_light') { | |||
// Формируем сообщение для датчиков света. | |||
$reply_say = $device_title . ' ' . gg($linked_object . '.value'); | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
} elseif ($device_type == 'sensor_temp') { | |||
// Формируем сообщение для датчиков температуры. | |||
$reply_say = $device_title . ' ' . gg($linked_object . '.value') . ' ' . LANG_DEVICES_DEGREES; | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
} elseif (preg_match('/sensor/', $device_type)) { | |||
// Формируем сообщение для других датчиков. | |||
$reply_say = $device_title . ' ' . gg($linked_object . '.value') . ''; | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
} elseif ($device_type == 'counter') { | |||
// Формируем сообщение для счетчиков. | |||
$reply_say = $device_title . ' ' . gg($linked_object . '.value') . ' ' . gg($linked_object . '.unit'); | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
} elseif ($device_type == 'openclose') { | |||
// Формируем сообщение для устройств открытия/закрытия. | |||
$reply_say = $device_title . ' ' . (gg($linked_object . '.status') ? LANG_DEVICES_STATUS_CLOSED : LANG_DEVICES_STATUS_OPEN); | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
} elseif ($device_type == 'smoke' || $device_type == 'leak') { | |||
// Формируем сообщение для датчиков дыма и утечек. | |||
$reply_say = $device_title . ' ' . (gg($linked_object . '.status') ? LANG_DEVICES_STATUS_ALARM : LANG_DEVICES_NORMAL_VALUE); | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
} elseif ($device_type == 'button') { | |||
// Добавляем код для имитации нажатия кнопки. | |||
$run_code .= "callMethod('$linked_object.pressed');"; | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
// Помечаем, что необходимо подтверждение выполнения команды. | |||
$reply_confirm = 1; | |||
} elseif ( | |||
$device_type == 'controller' || | |||
$device_type == 'relay' || | |||
$device_type == 'dimmer' || | |||
$device_type == 'rgb' | |||
) { | |||
if (preg_match('/' . LANG_DEVICES_PATTERN_TURNON . '/uis', $command)) { | |||
// Формируем сообщение для включения устройства. | |||
$reply_say = LANG_TURNING_ON . ' ' . $device_title . $add_phrase; | |||
// Добавляем код для включения устройства. | |||
$run_code .= "callMethod('$linked_object.turnOn');"; | |||
// Добавляем код для выключения устройства в качестве противодействия. | |||
$opposite_code .= "callMethod('$linked_object.turnOff');"; | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
// Помечаем, что необходимо подтверждение выполнения команды. | |||
//$reply_confirm = 1; | |||
} elseif (preg_match('/' . LANG_DEVICES_PATTERN_TURNOFF . '/uis', $command)) { | |||
// Формируем сообщение для выключения устройства. | |||
$reply_say = LANG_TURNING_OFF . ' ' . $device_title . $add_phrase; | |||
// Добавляем код для выключения устройства. | |||
$run_code .= "callMethod('$linked_object.turnOff');"; | |||
// Добавляем код для включения устройства в качестве противодействия. | |||
$opposite_code .= "callMethod('$linked_object.turnOn');"; | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
// Помечаем, что необходимо подтверждение выполнения команды. | |||
//$reply_confirm = 1; | |||
} | |||
} elseif ($device_type == 'openable') { | |||
if (preg_match('/' . LANG_DEVICES_PATTERN_OPEN . '/uis', $command)) { | |||
// Формируем сообщение для открытия устройства. | |||
$reply_say = LANG_TURNING_OPEN . ' ' . $device_title . $add_phrase; | |||
// Добавляем код для открытия устройства. | |||
$run_code .= "callMethod('$linked_object.Open');"; | |||
// Добавляем код для закрытия устройства в качестве противодействия. | |||
$opposite_code .= "callMethod('$linked_object.Close');"; | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
// Помечаем, что необходимо подтверждение выполнения команды. | |||
//$reply_confirm = 1; | |||
} elseif (preg_match('/' . LANG_DEVICES_PATTERN_CLOSE . '/uis', $command)) { | |||
// Формируем сообщение для закрытия устройства. | |||
$reply_say = LANG_TURNING_CLOSE . ' ' . $device_title . $add_phrase; | |||
// Добавляем код для закрытия устройства. | |||
$run_code .= "callMethod('$linked_object.Close');"; | |||
// Добавляем код для открытия устройства в качестве противодействия. | |||
$opposite_code .= "callMethod('$linked_object.Open');"; | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
// Помечаем, что необходимо подтверждение выполнения команды. | |||
//$reply_confirm = 1; | |||
} | |||
} elseif ($device_type == 'group') { | |||
// Разбиваем типы применения группы по запятой. | |||
$applies_to = explode(',', $devices[$i]['APPLY_TYPES']); | |||
// Если устройства группы представлены в виде массива. | |||
if (is_array($devices[$i]['DEVICES'])) { | |||
// Инициализируем массив для хранения связанных объектов устройств в группе. | |||
$devices_in_group = array(); | |||
// Проходим по каждому устройству в группе. | |||
foreach ($devices[$i]['DEVICES'] as $group_device) { | |||
// Добавляем связанный объект устройства в массив. | |||
$devices_in_group[] = $group_device['LINKED_OBJECT']; | |||
} | |||
// Если устройства группы не представлены в виде массива. | |||
} else { | |||
// Получаем связанные объекты устройств в группе по свойству. | |||
$devices_in_group = getObjectsByProperty('group' . $devices[$i]['SYS_NAME'], 1); | |||
} | |||
// Выводим содержимое переменной $devices_in_group для отладки. | |||
//dprint($devices_in_group); | |||
// Если устройства группы не представлены в виде массива, пропускаем текущую итерацию цикла. | |||
if (!is_array($devices_in_group)) continue; | |||
if ( | |||
in_array('relay', $applies_to) || | |||
in_array('dimmer', $applies_to) || | |||
in_array('rgb', $applies_to) || | |||
0 | |||
) { | |||
if (preg_match('/' . LANG_DEVICES_PATTERN_TURNON . '/uis', $command)) { | |||
// Формируем сообщение для включения устройства. | |||
$reply_say = LANG_TURNING_ON . ' ' . $device_title . $add_phrase; | |||
foreach ($devices_in_group as $linked_object) { | |||
// Добавляем код для включения каждого устройства в группе. | |||
$run_code .= "callMethod('$linked_object.turnOn');"; | |||
// Добавляем код для выключения каждого устройства в группе в качестве противодействия. | |||
$opposite_code .= "callMethod('$linked_object.turnOff');"; | |||
} | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
// Помечаем, что необходимо подтверждение выполнения команды. | |||
//$reply_confirm = 1; | |||
} elseif (preg_match('/' . LANG_DEVICES_PATTERN_TURNOFF . '/uis', $command)) { | |||
// Формируем сообщение для выключения устройства. | |||
$reply_say = LANG_TURNING_OFF . ' ' . $device_title . $add_phrase; | |||
foreach ($devices_in_group as $linked_object) { | |||
// Добавляем код для выключения каждого устройства в группе. | |||
$run_code .= "callMethod('$linked_object.turnOff');"; | |||
// Добавляем код для включения каждого устройства в группе в качестве противодействия. | |||
$opposite_code .= "callMethod('$linked_object.turnOn');"; | |||
} | |||
// Помечаем, что команда была обработана. | |||
$processed = 1; | |||
// Помечаем, что необходимо подтверждение выполнения команды. | |||
//$reply_confirm = 1; | |||
} | |||
} | |||
// Определяем путь к директории дополнений. | |||
$addons_dir = dirname(__FILE__) . '/addons'; | |||
// Если директория дополнений существует. | |||
if (is_dir($addons_dir)) { | |||
// Получаем список файлов в директории дополнений. | |||
$addon_files = scandir($addons_dir); | |||
// Проходим по каждому файлу в полученном списке. | |||
foreach ($addon_files as $file) { | |||
// Если имя файла соответствует шаблону. | |||
if (preg_match('/\_commands\.php$/', $file)) { | |||
// Подключаем файл дополнения. | |||
require($addons_dir . '/' . $file); | |||
} | |||
} | |||
} | |||
// Если команда была обработана, прерываем цикл. | |||
if ($processed) break; | |||
if ($run_code != '' && $period_delay > 0) { | |||
// Если есть код для выполнения и задержка больше 0, устанавливаем таймер для выполнения кода после задержки. | |||
setTimeout('delay' . md5($run_code), $run_code, $period_delay); | |||
} elseif ($run_code != '' && $period_run_for > 0 && $opposite_code != '') { | |||
// Если есть код для выполнения, продолжительность выполнения больше 0 и есть код для противодействия, выполняем код. | |||
eval($run_code); | |||
// Устанавливаем таймер для выполнения кода противодействия после указанного времени. | |||
setTimeout('opposite' . md5($run_code), $opposite_code, $period_run_for); | |||
} elseif ($run_code != '') { | |||
// Если есть код для выполнения, выполняем его. | |||
eval($run_code); | |||
/* | |||
* TODO использовать eval считается небезопасным, поскольку он выполняет произвольный PHP-код, представленный в виде строки. | |||
* Это может создать уязвимости в безопасности и снизить производительность, поскольку он компилирует и выполняет код каждый раз, | |||
* когда он вызывается. Это может привести к увеличению нагрузки на сервер и снижению производительности. | |||
*/ | |||
} | |||
if ($reply_say != '') { | |||
// Если есть сообщение для ответа, отправляем его. | |||
sayReplySafe($reply_say, 2); | |||
} | |||
if ($reply_confirm) { | |||
// Разбиваем строку подтверждения команды по символу '|'. | |||
$items = explode('|', LANG_DEVICES_COMMAND_CONFIRMATION); | |||
// Удаляем пробелы в начале и конце каждого элемента массива. | |||
$items = array_map('trim', $items); | |||
// Отправляем случайное сообщение из массива подтверждений. | |||
sayReplySafe($items[array_rand($items)], 2); | |||
} | |||
if ($processed) { | |||
// Если команда была обработана, помечаем это. | |||
$details['PROCESSED'] = 1; | |||
// Помечаем, что необходимо прервать выполнение. | |||
$details['BREAK'] = 1; | |||
} | |||
} | |||
} | |||
} | |||
</pre> | </pre> |
Текущая версия от 21:38, 9 апреля 2024
ᐂ В корневой раздел ᐃ В директорию расположения файла
<?php // Проверяет, отключены ли простые устройства в файле конфигурации ROOT . config.php. Если да, прекращает выполнение скрипта. if (defined('DISABLE_SIMPLE_DEVICES') && DISABLE_SIMPLE_DEVICES == 1) return; /* * array('level' => $level, 'message' => $ph, 'member_id' => $member_id, 'source' => $source) * $details['BREAK'] = 1 / 0 */ // Этот блок кода, вероятно, предназначен для обработки лога или отладки, так как он содержит пример использования переменной $details['BREAK']. // Однако, поскольку он закомментирован, его выполнение в текущем состоянии скрипта не происходит. // Включаем файлы локализации для текущего языка сайта и по умолчанию. @include_once(ROOT . 'languages/' . $this->name . '_' . SETTINGS_SITE_LANGUAGE . '.php'); @include_once(ROOT . 'languages/' . $this->name . '_default' . '.php'); // Если в деталях команды указано источник (терминал), то получаем информацию о терминале. if ($details['source']) { $terminal = getTerminalByID(str_replace("terminal", "", $details['source'])); // Если у терминала есть ID местоположения, сохраняем его. if ($terminal['LOCATION_ID']) { $location_id = $terminal['LOCATION_ID']; } } /* * Этот фрагмент кода анализирует входящую команду на предмет наличия указаний на задержку выполнения, * или продолжительность выполнения действия. * Если такие указания присутствуют, код вычисляет соответствующие значения в секундах * и сохраняет их в переменных $period_delay и $period_run_for соответственно. * Также код сохраняет найденное совпадение в переменную $add_phrase, чтобы потом добавить его к сообщению. */ // Получаем текстовую команду из массива $details, который содержит детали сообщения. $command = $details['message']; // Инициализируем переменную $run_code как пустую строку. Эта переменная будет использоваться для хранения кода, который нужно выполнить. $run_code = ''; // Инициализируем переменную $opposite_code как пустую строку. Эта переменная будет использоваться для хранения кода, который будет выполнен в качестве противодействия к основному коду. $opposite_code = ''; // Инициализируем переменную $add_phrase как пустую строку. Эта переменная будет использоваться для хранения дополнительной фразы, которая будет добавлена к сообщению. $add_phrase = ''; // Инициализируем переменную $period_delay как 0. Эта переменная будет использоваться для хранения задержки выполнения команды в секундах. $period_delay = 0; // Инициализируем переменную $period_run_for как 0. Эта переменная будет использоваться для хранения продолжительности выполнения команды в секундах. $period_run_for = 0; // Проверяем, содержит ли команда фразу, указывающую на необходимость выполнения действия после определенного времени. if (preg_match('/' . LANG_PATTERN_DO_AFTER . ' (\d+?) (' . LANG_PATTERN_SECOND . '|' . LANG_PATTERN_MINUTE . '|' . LANG_PATTERN_HOUR . ')/uis', textToNumbers($command), $m)) { // Получаем числовое значение времени задержки из найденного совпадения. $period_number = $m[1]; // Добавляем найденное совпадение к переменной $add_phrase, чтобы потом добавить его к сообщению. $add_phrase = ' ' . $m[0]; // Определяем единицу измерения времени (секунды, минуты, часы) и вычисляем задержку в секундах. if (preg_match('/' . LANG_PATTERN_SECOND . '/uis', $m[2])) { // Если единица измерения - секунды, то задержка равна числовому значению. $period_delay = $period_number; } elseif (preg_match('/' . LANG_PATTERN_MINUTE . '/uis', $m[2])) { // Если единица измерения - минуты, то задержка равна числовому значению, умноженному на 60. $period_delay = $period_number * 60; } elseif (preg_match('/' . LANG_PATTERN_HOUR . '/uis', $m[2])) { // Если единица измерения - часы, то задержка равна числовому значению, умноженному на 3600. $period_delay = $period_number * 60 * 60; } // Удаляем обработанную часть команды, чтобы оставить только саму команду без указания времени задержки. $command = trim(str_replace($m[0], '', textToNumbers($command))); } elseif (preg_match('/' . LANG_PATTERN_DO_FOR . ' (\d+?) (' . LANG_PATTERN_SECOND . '|' . LANG_PATTERN_MINUTE . '|' . LANG_PATTERN_HOUR . ')/uis', textToNumbers($command), $m)) { // Получаем числовое значение времени выполнения из найденного совпадения. $period_number = $m[1]; // Добавляем найденное совпадение к переменной $add_phrase, чтобы потом добавить его к сообщению. $add_phrase = ' ' . $m[0]; // Определяем единицу измерения времени (секунды, минуты, часы) и вычисляем продолжительность выполнения в секундах. if (preg_match('/' . LANG_PATTERN_SECOND . '/uis', $m[2])) { // Если единица измерения - секунды, то продолжительность выполнения равна числовому значению. $period_run_for = $period_number; } elseif (preg_match('/' . LANG_PATTERN_MINUTE . '/uis', $m[2])) { // Если единица измерения - минуты, то продолжительность выполнения равна числовому значению, умноженному на 60. $period_run_for = $period_number * 60; } elseif (preg_match('/' . LANG_PATTERN_HOUR . '/uis', $m[2])) { // Если единица измерения - часы, то продолжительность выполнения равна числовому значению, умноженному на 3600. $period_run_for = $period_number * 60 * 60; } // Удаляем обработанную часть команды, чтобы оставить только саму команду без указания времени выполнения. $command = trim(str_replace($m[0], '', textToNumbers($command))); } // Инициализируем переменную $processed как 0. Эта переменная будет использоваться для отслеживания, была ли команда обработана. $processed = 0; // Инициализируем переменную $reply_confirm как 0. Эта переменная будет использоваться для подтверждения выполнения команды. $reply_confirm = 0; // Инициализируем переменную $reply_say как пустую строку. Эта переменная будет использоваться для хранения сообщения, которое будет отправлено в ответ на команду. $reply_say = ''; // Инициализируем переменную $phpmorphy_loaded как 0. Эта переменная будет использоваться для отслеживания, загружена ли библиотека phpMorphy. $phpmorphy_loaded = 0; // Проверяем, существует ли файл библиотеки phpMorphy. if (file_exists(ROOT . "lib/phpmorphy/common.php")) { // Подключаем файл библиотеки phpMorphy. require_once(ROOT . "lib/phpmorphy/common.php"); $opts = array( // Указываем тип хранения данных. 'storage' => PHPMORPHY_STORAGE_MEM, // Включаем предсказание по суффиксу. 'predict_by_suffix' => true, // Включаем предсказание по базе данных. 'predict_by_db' => true, // Указываем, что грамматическая информация должна быть представлена в виде текста. 'graminfo_as_text' => true, ); // Указываем путь к словарям phpMorphy. $dir = ROOT . 'lib/phpmorphy/dicts'; // Получаем код текущего языка сайта. $lang = SETTINGS_SITE_LANGUAGE_CODE; try { // Создаем экземпляр класса phpMorphy. $morphy = new phpMorphy($dir, $lang, $opts); // Сохраняем ссылку на созданный экземпляр в свойстве объекта. $this->morphy = &$morphy; } catch (phpMorphy_Exception $e) { // Выводим сообщение об ошибке и прерываем выполнение скрипта. die('Error occured while creating phpMorphy instance: ' . PHP_EOL . $e); } // Разбиваем команду на слова. $words = explode(' ', $command); // Инициализируем массив для хранения отфильтрованных слов. $words_filtered = array(); // Инициализируем счетчик отфильтрованных слов. $filtered_count = 0; // Инициализируем массив для хранения базовых форм слов. $base_forms = array(); // Инициализируем массив для хранения базовых форм отфильтрованных слов. $base_forms_filtered = array(); // Получаем общее количество слов в команде. $totals = count($words); for ($is = 0; $is < $totals; $is++) { // Инициализируем переменную для отслеживания, было ли слово фильтровано. $filtered = 0; // Преобразуем слово в верхний регистр. $upper = mb_strtoupper($words[$is], 'UTF-8'); // Получаем длину слова. $len = mb_strlen($words[$is], 'UTF-8'); // Если длина слова больше или равна 3, считаем его достаточно длинным для анализа. if ($len >= 3) { // Добавляем слово в массив отфильтрованных слов. $words_filtered[] = $words[$is]; // Помечаем слово как отфильтрованное. $filtered = 1; // Увеличиваем счетчик отфильтрованных слов. $filtered_count++; } // Если слово является числом, добавляем его в массив базовых форм. if (preg_match('/^(\d+)$/', $words[$is])) { $base_forms[$is] = array($words[$is]); // Если слово не содержит специальных символов, получаем его базовую форму. } elseif (!preg_match('/[\(\)\+\.]/', $words[$is])) { // Преобразуем слово в верхний регистр. $Word = mb_strtoupper($words[$is], 'UTF-8'); // Получаем базовую форму слова. $base_forms[$is] = $morphy->getBaseForm($Word); // Добавляем исходное слово в массив базовых форм. $base_forms[$is][] = $words[$is]; // Если слово содержит специальные символы, добавляем его в массив базовых форм без изменений. } else { $base_forms[$is] = array($words[$is]); } // Если слово было отфильтровано, добавляем его базовую форму в массив отфильтрованных базовых форм. if ($filtered) { $base_forms_filtered[$filtered_count - 1] = $base_forms[$is]; } } // Генерируем все возможные комбинации базовых форм слов. $combos = $this->generate_combinations($base_forms); // Если количество отфильтрованных слов меньше общего количества слов, генерируем дополнительные комбинации. if ($filtered_count < $totals) { // Генерируем комбинации для отфильтрованных базовых форм. $add_combos = $this->generate_combinations($base_forms_filtered); // Добавляем каждую сгенерированную комбинацию в общий массив комбинаций. foreach ($add_combos as $cmb) { $combos[] = $cmb; } } // Инициализируем массив для хранения строк, полученных из комбинаций. $lines = array(); // Получаем общее количество комбинаций. $totals = count($combos); // Преобразуем каждую комбинацию в строку и добавляем ее в массив строк. for ($is = 0; $is < $totals; $is++) { $lines[] = implode(' ', $combos[$is]); } // Помечаем, что библиотека phpMorphy была успешно загружена. $phpmorphy_loaded = 1; } // Получаем список устройств из базы данных. $devices = SQLSelect("SELECT ID, TITLE, ALT_TITLES, TYPE, LINKED_OBJECT, LOCATION_ID FROM devices"); // Проходим по каждому устройству в полученном списке. foreach ($devices as $device) { // Если у устройства есть альтернативные названия. if (trim($device['ALT_TITLES']) != '') { // Разбиваем альтернативные названия по запятой. $nicknames = explode(',', trim($device['ALT_TITLES'])); // Проходим по каждому альтернативному названию. foreach ($nicknames as $nickname) { // Копируем текущее устройство. $add_rec = $device; // Заменяем название устройства на альтернативное. $add_rec['TITLE'] = $nickname; // Добавляем измененное устройство обратно в список устройств. $devices[] = $add_rec; } } } // Получаем список групп устройств из базы данных. $groups = SQLSelect("SELECT * FROM devices_groups"); // Получаем общее количество групп. $total = count($groups); // Проходим по каждой группе в полученном списке. for ($i = 0; $i < $total; $i++) { // Копируем текущую группу. $add_rec = $groups[$i]; // Устанавливаем тип группы как 'group'. $add_rec['TYPE'] = 'group'; // Добавляем группу обратно в список устройств. $devices[] = $add_rec; } // Получаем список комнат с устройствами из базы данных. $rooms = SQLSelect("SELECT locations.ID, locations.TITLE, COUNT(*) AS TOTAL FROM locations, devices WHERE locations.ID=devices.LOCATION_ID GROUP BY locations.ID"); // Проходим по каждой комнате в полученном списке. foreach ($rooms as $room) { //lights //if ($room['TITLE']=='Кабинет') { // Инициализируем массив для хранения типов устройств в комнате. $device_types = array(); // Получаем список устройств типа 'relay' в текущей комнате. $room_devices = SQLSelect("SELECT * FROM devices WHERE LOCATION_ID=" . $room['ID'] . " AND TYPE='relay'"); // Проходим по каждому устройству в полученном списке. foreach ($room_devices as $device) { // Получаем тип нагрузки устройства. $loadType = gg($device['LINKED_OBJECT'] . '.loadType'); // Добавляем устройство в массив типов устройств. $device_types[$loadType][] = $device; } // Если в комнате есть устройства типа 'light'. if (isset($device_types['light'])) { // Инициализируем массив для новой группы устройств. $add_rec = array(); // Устанавливаем тип группы как 'group'. $add_rec['TYPE'] = 'group'; // Устанавливаем название группы. $add_rec['TITLE'] = LANG_DEVICES_LOADTYPE_LIGHT . ' ' . $room['TITLE']; // Добавляем устройства типа 'light' в группу. $add_rec['DEVICES'] = $device_types['light']; // Устанавливаем типы применения группы. $add_rec['APPLY_TYPES'] = 'relay'; // Добавляем группу обратно в список устройств. $devices[] = $add_rec; // Инициализируем массив для новой группы устройств. $add_rec = array(); // Устанавливаем тип группы как 'group'. $add_rec['TYPE'] = 'group'; // Устанавливаем альтернативное название группы. $add_rec['TITLE'] = LANG_DEVICES_LOADTYPE_LIGHT_ALT . ' ' . $room['TITLE']; // Добавляем устройства типа 'light' в группу. $add_rec['DEVICES'] = $device_types['light']; // Устанавливаем типы применения группы. $add_rec['APPLY_TYPES'] = 'relay'; // Добавляем группу обратно в список устройств. $devices[] = $add_rec; } //} } // Если библиотека phpMorphy была успешно загружена. if ($phpmorphy_loaded) { // Получаем общее количество устройств. $total = count($devices); // Инициализируем массив для хранения дополнительных устройств. $add_devices = array(); // Проходим по каждому устройству в полученном списке. for ($i = 0; $i < $total; $i++) { // Получаем название устройства. $device_title = $devices[$i]['TITLE']; // Разбиваем название устройства на слова и преобразуем их в верхний регистр. $words = explode(' ', mb_strtoupper($device_title, 'UTF-8')); // Инициализируем массив для хранения базовых форм слов. $base_forms = array(); // Получаем общее количество слов. $totals = count($words); // Проходим по каждому слову в полученном списке. for ($is = 0; $is < $totals; $is++) { // Если слово является числом, добавляем его в массив базовых форм. if (preg_match('/^(\d+)$/', $words[$is])) { $base_forms[$is] = array($words[$is]); // Если слово не содержит специальных символов, получаем его базовую форму. } elseif (!preg_match('/[\(\)\+\.]/', $words[$is])) { // Преобразуем слово в верхний регистр. $Word = mb_strtoupper($words[$is], 'UTF-8'); // Получаем базовую форму слова. $base_form = $morphy->getBaseForm($Word); // Если базовая форма представлена в виде массива. if (is_array($base_form)) { $base_forms[$is] = $base_form; // Если базовая форма не представлена в виде массива. } else { $base_forms[$is] = array(); } // Если исходное слово не содержится в массиве базовых форм. if (!in_array($words[$is], $base_forms[$is])) { // Добавляем исходное слово в массив базовых форм. $base_forms[$is][] = $words[$is]; } // Если слово содержит специальные символы, добавляем его в массив базовых форм без изменений. } else { $base_forms[$is] = array($words[$is]); } } // Генерируем все возможные комбинации базовых форм слов. $combos = $this->generate_combinations($base_forms); // Инициализируем массив для хранения фраз, полученных из комбинаций. $phrases = array(); // Проходим по каждой комбинации в полученном списке. foreach ($combos as $combo) { // Вычисляем все возможные перестановки для текущей комбинации. $mutations = $this->computePermutations($combo); // Проходим по каждой перестановке в полученном списке. foreach ($mutations as $m) { // Преобразуем каждую перестановку в строку и добавляем ее в массив фраз. $phrases[] = implode(' ', $m); } } // Инициализируем массив для хранения новых названий устройств. $device_titles = array(); // Получаем общее количество фраз. $totals = count($phrases); // Проходим по каждой фразе в полученном списке. for ($is = 0; $is < $totals; $is++) { // Получаем новое название устройства. $new_title = $phrases[$is]; // Добавляем новое название устройства в массив новых названий. $device_titles[] = $new_title; // Копируем текущее устройство. $new_device = $devices[$i]; // Заменяем название устройства на новое. $new_device['TITLE'] = $new_title; // Сохраняем оригинальное название устройства. $new_device['ORIGINAL_TITLE'] = $device_title; // Добавляем измененное устройство в массив дополнительных устройств. $add_devices[] = $new_device; } } // Проходим по каждому устройству в массиве дополнительных устройств. foreach ($add_devices as $device) { // Добавляем устройство обратно в список устройств. $devices[] = $device; } } // Выводим содержимое переменной $lines для отладки. //dprint($lines,false); // Выводим содержимое переменной $devices для отладки. //dprint($devices); // Инициализируем переменную $compare_title командой. $compare_title = $command; // Проверяем, содержит ли команда фразу, указывающую на необходимость включения устройства. if (preg_match('/' . LANG_DEVICES_PATTERN_TURNON . '/uis', $compare_title, $m)) { // Если да, удаляем эту фразу из команды. $compare_title = trim(str_replace($m[0], ' ', $compare_title)); } // Проверяем, содержит ли команда фразу, указывающую на необходимость выключения устройства. if (preg_match('/' . LANG_DEVICES_PATTERN_TURNOFF . '/uis', $compare_title, $m)) { // Если да, удаляем эту фразу из команды. $compare_title = trim(str_replace($m[0], ' ', $compare_title)); } // Удаляем начальные слова "ть" и "те" из команды, если они присутствуют. $compare_title = trim(preg_replace('/^ть /', '', $compare_title)); $compare_title = trim(preg_replace('/^те /', '', $compare_title)); // Если после всех преобразований команда стала пустой, прекращаем выполнение скрипта. if ($compare_title == '') { return; } // Получаем общее количество устройств. $total = count($devices); // Проходим по каждому устройству в полученном списке. for ($i = 0; $i < $total; $i++) { // Инициализируем переменную для отслеживания, было ли найдено соответствие устройства. $device_matched = 0; // Если указано местоположение терминала. if ($location_id) { // Ищем строгое соответствие по названию и местоположению. foreach ($devices as $key => $value) { // Если ID местоположения устройства совпадает с ID местоположения терминала и название устройства совпадает с командой. if (in_array($location_id, $value) && strtolower($devices[$key]['TITLE']) == strtolower($compare_title)) { // Обновляем индекс текущего устройства. $i = $key; // Помечаем, что устройство найдено. $device_matched = 1; // Прерываем цикл. break; } } // Если устройство не найдено. if (!$device_matched) { // Ищем строгое соответствие по названию. foreach ($devices as $key => $value) { // Если название устройства совпадает с командой. if (in_array(strtolower($compare_title), strtolower($value))) { // Обновляем индекс текущего устройства. $i = $key; // Помечаем, что устройство найдено. $device_matched = 1; // Прерываем цикл. break; } } } } // Ищем по старому принципу. if (preg_match('/' . preg_quote($devices[$i]['TITLE']) . '/uis', $compare_title)) { // Помечаем, что устройство найдено. $device_matched = 1; } elseif (preg_match('/' . preg_quote($compare_title) . '/uis', $devices[$i]['TITLE'])) { // Помечаем, что устройство найдено. $device_matched = 1; // Если библиотека phpMorphy была успешно загружена. } elseif ($phpmorphy_loaded) { if (preg_match('/' . preg_quote($devices[$i]['TITLE']) . '/isu', implode('@@@@', $lines), $matches)) { // Помечаем, что устройство найдено. $device_matched = 1; } } /* if (preg_match('/свет над столом/uis',$devices[$i]['TITLE'])) { dprint($devices[$i]['TITLE'].' - '.$compare_title.': '.$device_matched); } */ // Если устройство было найдено. if ($device_matched) { // Найдено устройство. // Получаем ID устройства. $device_id = $devices[$i]['ID']; // Получаем тип устройства. $device_type = $devices[$i]['TYPE']; // Если у устройства есть оригинальное название. if ($devices[$i]['ORIGINAL_TITLE'] != '') { // Используем оригинальное название. $device_title = $devices[$i]['ORIGINAL_TITLE']; // Если оригинального названия нет. } else { // Используем текущее название. $device_title = $devices[$i]['TITLE']; } // Записываем сообщение о том, что устройство было найдено. DebMes("Device found for $command ($device_title)", 'simple_devices'); // Получаем связанный объект устройства. $linked_object = $devices[$i]['LINKED_OBJECT']; if ($device_type == 'sensor_percentage' || $device_type == 'sensor_humidity') { // Формируем сообщение для датчиков с процентами и влажностью. $reply_say = $device_title . ' ' . gg($linked_object . '.value') . '%'; // Помечаем, что команда была обработана. $processed = 1; } elseif ($device_type == 'sensor_light') { // Формируем сообщение для датчиков света. $reply_say = $device_title . ' ' . gg($linked_object . '.value'); // Помечаем, что команда была обработана. $processed = 1; } elseif ($device_type == 'sensor_temp') { // Формируем сообщение для датчиков температуры. $reply_say = $device_title . ' ' . gg($linked_object . '.value') . ' ' . LANG_DEVICES_DEGREES; // Помечаем, что команда была обработана. $processed = 1; } elseif (preg_match('/sensor/', $device_type)) { // Формируем сообщение для других датчиков. $reply_say = $device_title . ' ' . gg($linked_object . '.value') . ''; // Помечаем, что команда была обработана. $processed = 1; } elseif ($device_type == 'counter') { // Формируем сообщение для счетчиков. $reply_say = $device_title . ' ' . gg($linked_object . '.value') . ' ' . gg($linked_object . '.unit'); // Помечаем, что команда была обработана. $processed = 1; } elseif ($device_type == 'openclose') { // Формируем сообщение для устройств открытия/закрытия. $reply_say = $device_title . ' ' . (gg($linked_object . '.status') ? LANG_DEVICES_STATUS_CLOSED : LANG_DEVICES_STATUS_OPEN); // Помечаем, что команда была обработана. $processed = 1; } elseif ($device_type == 'smoke' || $device_type == 'leak') { // Формируем сообщение для датчиков дыма и утечек. $reply_say = $device_title . ' ' . (gg($linked_object . '.status') ? LANG_DEVICES_STATUS_ALARM : LANG_DEVICES_NORMAL_VALUE); // Помечаем, что команда была обработана. $processed = 1; } elseif ($device_type == 'button') { // Добавляем код для имитации нажатия кнопки. $run_code .= "callMethod('$linked_object.pressed');"; // Помечаем, что команда была обработана. $processed = 1; // Помечаем, что необходимо подтверждение выполнения команды. $reply_confirm = 1; } elseif ( $device_type == 'controller' || $device_type == 'relay' || $device_type == 'dimmer' || $device_type == 'rgb' ) { if (preg_match('/' . LANG_DEVICES_PATTERN_TURNON . '/uis', $command)) { // Формируем сообщение для включения устройства. $reply_say = LANG_TURNING_ON . ' ' . $device_title . $add_phrase; // Добавляем код для включения устройства. $run_code .= "callMethod('$linked_object.turnOn');"; // Добавляем код для выключения устройства в качестве противодействия. $opposite_code .= "callMethod('$linked_object.turnOff');"; // Помечаем, что команда была обработана. $processed = 1; // Помечаем, что необходимо подтверждение выполнения команды. //$reply_confirm = 1; } elseif (preg_match('/' . LANG_DEVICES_PATTERN_TURNOFF . '/uis', $command)) { // Формируем сообщение для выключения устройства. $reply_say = LANG_TURNING_OFF . ' ' . $device_title . $add_phrase; // Добавляем код для выключения устройства. $run_code .= "callMethod('$linked_object.turnOff');"; // Добавляем код для включения устройства в качестве противодействия. $opposite_code .= "callMethod('$linked_object.turnOn');"; // Помечаем, что команда была обработана. $processed = 1; // Помечаем, что необходимо подтверждение выполнения команды. //$reply_confirm = 1; } } elseif ($device_type == 'openable') { if (preg_match('/' . LANG_DEVICES_PATTERN_OPEN . '/uis', $command)) { // Формируем сообщение для открытия устройства. $reply_say = LANG_TURNING_OPEN . ' ' . $device_title . $add_phrase; // Добавляем код для открытия устройства. $run_code .= "callMethod('$linked_object.Open');"; // Добавляем код для закрытия устройства в качестве противодействия. $opposite_code .= "callMethod('$linked_object.Close');"; // Помечаем, что команда была обработана. $processed = 1; // Помечаем, что необходимо подтверждение выполнения команды. //$reply_confirm = 1; } elseif (preg_match('/' . LANG_DEVICES_PATTERN_CLOSE . '/uis', $command)) { // Формируем сообщение для закрытия устройства. $reply_say = LANG_TURNING_CLOSE . ' ' . $device_title . $add_phrase; // Добавляем код для закрытия устройства. $run_code .= "callMethod('$linked_object.Close');"; // Добавляем код для открытия устройства в качестве противодействия. $opposite_code .= "callMethod('$linked_object.Open');"; // Помечаем, что команда была обработана. $processed = 1; // Помечаем, что необходимо подтверждение выполнения команды. //$reply_confirm = 1; } } elseif ($device_type == 'group') { // Разбиваем типы применения группы по запятой. $applies_to = explode(',', $devices[$i]['APPLY_TYPES']); // Если устройства группы представлены в виде массива. if (is_array($devices[$i]['DEVICES'])) { // Инициализируем массив для хранения связанных объектов устройств в группе. $devices_in_group = array(); // Проходим по каждому устройству в группе. foreach ($devices[$i]['DEVICES'] as $group_device) { // Добавляем связанный объект устройства в массив. $devices_in_group[] = $group_device['LINKED_OBJECT']; } // Если устройства группы не представлены в виде массива. } else { // Получаем связанные объекты устройств в группе по свойству. $devices_in_group = getObjectsByProperty('group' . $devices[$i]['SYS_NAME'], 1); } // Выводим содержимое переменной $devices_in_group для отладки. //dprint($devices_in_group); // Если устройства группы не представлены в виде массива, пропускаем текущую итерацию цикла. if (!is_array($devices_in_group)) continue; if ( in_array('relay', $applies_to) || in_array('dimmer', $applies_to) || in_array('rgb', $applies_to) || 0 ) { if (preg_match('/' . LANG_DEVICES_PATTERN_TURNON . '/uis', $command)) { // Формируем сообщение для включения устройства. $reply_say = LANG_TURNING_ON . ' ' . $device_title . $add_phrase; foreach ($devices_in_group as $linked_object) { // Добавляем код для включения каждого устройства в группе. $run_code .= "callMethod('$linked_object.turnOn');"; // Добавляем код для выключения каждого устройства в группе в качестве противодействия. $opposite_code .= "callMethod('$linked_object.turnOff');"; } // Помечаем, что команда была обработана. $processed = 1; // Помечаем, что необходимо подтверждение выполнения команды. //$reply_confirm = 1; } elseif (preg_match('/' . LANG_DEVICES_PATTERN_TURNOFF . '/uis', $command)) { // Формируем сообщение для выключения устройства. $reply_say = LANG_TURNING_OFF . ' ' . $device_title . $add_phrase; foreach ($devices_in_group as $linked_object) { // Добавляем код для выключения каждого устройства в группе. $run_code .= "callMethod('$linked_object.turnOff');"; // Добавляем код для включения каждого устройства в группе в качестве противодействия. $opposite_code .= "callMethod('$linked_object.turnOn');"; } // Помечаем, что команда была обработана. $processed = 1; // Помечаем, что необходимо подтверждение выполнения команды. //$reply_confirm = 1; } } // Определяем путь к директории дополнений. $addons_dir = dirname(__FILE__) . '/addons'; // Если директория дополнений существует. if (is_dir($addons_dir)) { // Получаем список файлов в директории дополнений. $addon_files = scandir($addons_dir); // Проходим по каждому файлу в полученном списке. foreach ($addon_files as $file) { // Если имя файла соответствует шаблону. if (preg_match('/\_commands\.php$/', $file)) { // Подключаем файл дополнения. require($addons_dir . '/' . $file); } } } // Если команда была обработана, прерываем цикл. if ($processed) break; if ($run_code != '' && $period_delay > 0) { // Если есть код для выполнения и задержка больше 0, устанавливаем таймер для выполнения кода после задержки. setTimeout('delay' . md5($run_code), $run_code, $period_delay); } elseif ($run_code != '' && $period_run_for > 0 && $opposite_code != '') { // Если есть код для выполнения, продолжительность выполнения больше 0 и есть код для противодействия, выполняем код. eval($run_code); // Устанавливаем таймер для выполнения кода противодействия после указанного времени. setTimeout('opposite' . md5($run_code), $opposite_code, $period_run_for); } elseif ($run_code != '') { // Если есть код для выполнения, выполняем его. eval($run_code); /* * TODO использовать eval считается небезопасным, поскольку он выполняет произвольный PHP-код, представленный в виде строки. * Это может создать уязвимости в безопасности и снизить производительность, поскольку он компилирует и выполняет код каждый раз, * когда он вызывается. Это может привести к увеличению нагрузки на сервер и снижению производительности. */ } if ($reply_say != '') { // Если есть сообщение для ответа, отправляем его. sayReplySafe($reply_say, 2); } if ($reply_confirm) { // Разбиваем строку подтверждения команды по символу '|'. $items = explode('|', LANG_DEVICES_COMMAND_CONFIRMATION); // Удаляем пробелы в начале и конце каждого элемента массива. $items = array_map('trim', $items); // Отправляем случайное сообщение из массива подтверждений. sayReplySafe($items[array_rand($items)], 2); } if ($processed) { // Если команда была обработана, помечаем это. $details['PROCESSED'] = 1; // Помечаем, что необходимо прервать выполнение. $details['BREAK'] = 1; } } } }