<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://mdminfo.ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vik+Tam</id>
	<title>MajorDoMo инфо - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://mdminfo.ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vik+Tam"/>
	<link rel="alternate" type="text/html" href="https://mdminfo.ru/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Vik_Tam"/>
	<updated>2026-06-02T09:44:45Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.38.4</generator>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BF%D0%BB%D0%B5%D0%B5%D1%80%D0%B0_VLC_%D0%B2_MajorDoMo&amp;diff=2141</id>
		<title>Установка плеера VLC в MajorDoMo</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BF%D0%BB%D0%B5%D0%B5%D1%80%D0%B0_VLC_%D0%B2_MajorDoMo&amp;diff=2141"/>
		<updated>2025-11-13T18:14:01Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Для Linux */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
==Для Windows==&lt;br /&gt;
&lt;br /&gt;
Устанавливаем плеер http://www.videolan.org/vlc/&lt;br /&gt;
&lt;br /&gt;
Для Windows есть 2 варианта работы с плеером: через RC(по умолчанию) и через HTTP (VLC over HTTP). Далее настройка для второго варианта.&lt;br /&gt;
&lt;br /&gt;
Настройки/ Интерфейс/WEB - отметить галочкой&lt;br /&gt;
&lt;br /&gt;
[[Файл:1a964-clip-51kb.png|800px|мини|центр|vlc]]&lt;br /&gt;
&lt;br /&gt;
Настройки/ Интерфейс/LUA - задать пароль к HTTP&lt;br /&gt;
&lt;br /&gt;
[[Файл:23774-clip-56kb.png|800px|мини|центр|VLC]]&lt;br /&gt;
&lt;br /&gt;
Перезапустить VLC. Проверим веб-интерфейс:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;http://&amp;quot;IP адрес машины с плеером&amp;quot;:8080&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Добавить в автозагрузку.&lt;br /&gt;
&lt;br /&gt;
Вариант установки в качестве сервиса&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;vlc.exe -I ntservice --ntservice-install --ntservice-name &amp;quot;VLC&amp;quot;  --ntservice-extraintf &amp;quot;http&amp;quot; --http-password 12345&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Для Linux==&lt;br /&gt;
=== Первый вариант с автозапуском через crontab ===&lt;br /&gt;
Устанавливаем VLC:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install vlc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Настроим автозапуск:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;crontab -e -u majordomo_Юзер&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в конец:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;@reboot vlc -I http&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Начиная с версии 2.1.0 для запуска веб-интерфейса vlc требуется пароль, поэтому для запуска используем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;@reboot vlc -I http --http-password 12345&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Перезагружаемся. Проверим веб-интерфейс:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;http://&amp;quot;IP адрес машины с плеером&amp;quot;:8080&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Логин не используется, пароль указанный вами. Если необходимо переназначить порт вэб интерфейса vlc (например для того, чтобы освободить порт 8080 для сервера Blynk) добавляем параметр --http-port 7070&lt;br /&gt;
&lt;br /&gt;
=== Второй вариант с Установкой VLC и запуск в качестве сервиса SystemD ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    sudo apt-get install -y vlc &amp;lt;/pre&amp;gt;&lt;br /&gt;
Создать описание сервиса VLC на порту 7070 с паролем (имя пользователя - пустое поле)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; sudo nano /etc/systemd/system/vlcd.service &amp;lt;/pre&amp;gt;&lt;br /&gt;
Содержимое файла:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 [Unit]&lt;br /&gt;
Description=VLCDaemon&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Requires=majordomo.service&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/var/www/html&lt;br /&gt;
&lt;br /&gt;
ExecStart=/usr/bin/vlc -I http --http-password=12345 --http-port 7070 --no-video --aout=alsa --alsa-audio-device hw:0,0&lt;br /&gt;
&lt;br /&gt;
Restart=always&lt;br /&gt;
User=www-data&lt;br /&gt;
Group=www-data&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Добавить vlc в автозагрузку:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; sudo systemctl daemon-reload &lt;br /&gt;
sudo systemctl enable vlcd&lt;br /&gt;
sudo systemctl start vlcd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
PS: после какого то времени и обновления системы, перестало воспроизводиться радио поэтому изменил строчку в сервисе автозапуска (с указанием конкретного аудио устройства):&lt;br /&gt;
&lt;br /&gt;
Если не работает - проверяем локально, правим /usr/share/vlc/lua/http/.hosts, смотрим права и разрешения.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=MySQL_%22Unknown_storage_engine_%27Aria%27%22.&amp;diff=2122</id>
		<title>MySQL &quot;Unknown storage engine 'Aria'&quot;.</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=MySQL_%22Unknown_storage_engine_%27Aria%27%22.&amp;diff=2122"/>
		<updated>2025-01-17T06:54:07Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Решение проблемы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Возникающие ошибки]]&lt;br /&gt;
==Описание==&lt;br /&gt;
В логах systemD MariaDB.service &lt;br /&gt;
&amp;lt;pre&amp;gt;[ERROR] Could not open mysql.plugin table: &amp;quot;Unknown storage engine 'Aria'&amp;quot;. Some plugins may be not loaded&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ошибка возникала на RPi после перезагрузки, проявление не запускается страницы УД MajorDoMo, в &lt;br /&gt;
 systemctl status mariadb.service&lt;br /&gt;
&amp;lt;pre&amp;gt; × mariadb.service - MariaDB 10.11.3 database server&lt;br /&gt;
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled)&lt;br /&gt;
     Active: failed (Result: exit-code) since Fri 2025-01-17 07:41:12 MSK; 14s ago&lt;br /&gt;
       Docs: man:mariadbd(8)&lt;br /&gt;
             https://mariadb.com/kb/en/library/systemd/&lt;br /&gt;
    Process: 2206 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)&lt;br /&gt;
    Process: 2207 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)&lt;br /&gt;
    Process: 2209 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] &amp;amp;&amp;amp; VAR= ||   VAR=`cd /usr/bin/..; /usr/bin/galera_recovery`;&amp;gt;&lt;br /&gt;
    Process: 2279 ExecStart=/usr/sbin/mariadbd $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION (code=exited, status=1/FAILURE)&lt;br /&gt;
   Main PID: 2279 (code=exited, status=1/FAILURE)&lt;br /&gt;
     Status: &amp;quot;MariaDB server is down&amp;quot;&lt;br /&gt;
        CPU: 878ms &amp;lt;/pre&amp;gt;&lt;br /&gt;
==Решение проблемы==&lt;br /&gt;
Удалим файлы логов, связанные с Aria&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo rm -rf /var/lib/mysql/aria_log.00000001&lt;br /&gt;
sudo rm -rf /var/lib/mysql/aria_log_control&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Перезапустим сервиc SQL&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo systemctl restart mysql.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=MySQL_%22Unknown_storage_engine_%27Aria%27%22.&amp;diff=2121</id>
		<title>MySQL &quot;Unknown storage engine 'Aria'&quot;.</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=MySQL_%22Unknown_storage_engine_%27Aria%27%22.&amp;diff=2121"/>
		<updated>2025-01-17T06:53:37Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: «Category:Возникающие ошибки ==Описание== В логах systemD MariaDB.service  &amp;lt;pre&amp;gt;[ERROR] Could not open mysql.plugin table: &amp;quot;Unknown storage engine 'Aria'&amp;quot;. Some plugins may be not loaded &amp;lt;/pre&amp;gt; Ошибка возникала на RPi после перезагрузки, проявление не запускается страницы УД MajorDoMo, в   systemctl status mariadb.service &amp;lt;pre&amp;gt; × mariadb.service - MariaDB 1...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Возникающие ошибки]]&lt;br /&gt;
==Описание==&lt;br /&gt;
В логах systemD MariaDB.service &lt;br /&gt;
&amp;lt;pre&amp;gt;[ERROR] Could not open mysql.plugin table: &amp;quot;Unknown storage engine 'Aria'&amp;quot;. Some plugins may be not loaded&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ошибка возникала на RPi после перезагрузки, проявление не запускается страницы УД MajorDoMo, в &lt;br /&gt;
 systemctl status mariadb.service&lt;br /&gt;
&amp;lt;pre&amp;gt; × mariadb.service - MariaDB 10.11.3 database server&lt;br /&gt;
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled)&lt;br /&gt;
     Active: failed (Result: exit-code) since Fri 2025-01-17 07:41:12 MSK; 14s ago&lt;br /&gt;
       Docs: man:mariadbd(8)&lt;br /&gt;
             https://mariadb.com/kb/en/library/systemd/&lt;br /&gt;
    Process: 2206 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)&lt;br /&gt;
    Process: 2207 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)&lt;br /&gt;
    Process: 2209 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] &amp;amp;&amp;amp; VAR= ||   VAR=`cd /usr/bin/..; /usr/bin/galera_recovery`;&amp;gt;&lt;br /&gt;
    Process: 2279 ExecStart=/usr/sbin/mariadbd $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION (code=exited, status=1/FAILURE)&lt;br /&gt;
   Main PID: 2279 (code=exited, status=1/FAILURE)&lt;br /&gt;
     Status: &amp;quot;MariaDB server is down&amp;quot;&lt;br /&gt;
        CPU: 878ms &amp;lt;/pre&amp;gt;&lt;br /&gt;
==Решение проблемы==&lt;br /&gt;
Удалим файлы логов, связанные с Area&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo rm -rf /var/lib/mysql/aria_log.00000001&lt;br /&gt;
sudo rm -rf /var/lib/mysql/aria_log_control&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Перезапустим сервиc SQL&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo systemctl restart mysql.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=RHVoice&amp;diff=2114</id>
		<title>RHVoice</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=RHVoice&amp;diff=2114"/>
		<updated>2024-10-23T09:02:45Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; [[Category:Взаимодействие]]&lt;br /&gt;
&lt;br /&gt;
=== Общие сведения о технологии ===&lt;br /&gt;
'''''RHVoice''''' - это свободно распространяемый многоязычный синтезатор речи с открытым исходным кодом.&lt;br /&gt;
'''''RHVoice''''' использует статистический параметрический синтез. Он опирается на уже существующие речевые технологии с открытым исходным кодом (прежде всего HTS и связанные компоненты).&lt;br /&gt;
'''''Поддерживаемые языки:'''''&lt;br /&gt;
Изначально RHVoice говорил только по-русски. Теперь он также поддерживает американский английский, бразильский португальский, эсперанто, грузинский, украинский, киргизский и татарский. &lt;br /&gt;
===Поддерживаемые платформы===&lt;br /&gt;
RHVoice поддерживает Windows, GNU/Linux и Android. Он совместим со стандартными интерфейсами преобразования текста в речь на этих платформах SAPI5 в Windows, Speech Dispatcher в GNU/Linux и API для преобразования текста в речь в Android. &lt;br /&gt;
&lt;br /&gt;
===Установка===&lt;br /&gt;
[https://rhvoice.ru/installation/ Установка на Windows] &lt;br /&gt;
Установка на Debian/Ubuntu (входит в комплект базовых образов MajorDoMo для Raspberry Pi):&lt;br /&gt;
[http://github:%20https://github.com/RHVoice/RHVoice/blob/master/doc/ru/Compiling-on-Linux.md Github Установка на Linux] &lt;br /&gt;
Сначала устанавливаем зависимости:&lt;br /&gt;
&amp;lt;pre&amp;gt;apt-get install gcc g++ git pkg-config scons libao4 libao-common libao-dev&lt;br /&gt;
apt-get install -y mplayer alsa-base alsa-utils alsa-tools libao4 libao-common libao-dev pulseaudio gcc g++ pkg-config scons libpulse-dev portaudio19-dev speech-dispatcher libspeechd-dev python3-lxml&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Затем собираем RHVoice:&lt;br /&gt;
&amp;lt;pre&amp;gt;cd /usr/src/&lt;br /&gt;
git clone https://github.com/Olga-Yakovleva/RHVoice&lt;br /&gt;
cd RHVoice&lt;br /&gt;
scons&lt;br /&gt;
scons install&lt;br /&gt;
ldconfig &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Проверить можно так в консоли выполнить команду:&lt;br /&gt;
&amp;lt;pre&amp;gt;echo &amp;quot;test&amp;quot; | RHVoice-test&amp;lt;/pre&amp;gt;&lt;br /&gt;
или так:&lt;br /&gt;
&amp;lt;pre&amp;gt;echo &amp;quot;Привет&amp;quot; | RHVoice-test -p Anna&amp;lt;/pre&amp;gt; &lt;br /&gt;
В ответ на ПК произноситься заданная в кавычках фраза (тест или Привет)&lt;br /&gt;
Возможно появление ответа (варнинга) в консоли: default Engine is default &lt;br /&gt;
Ещё один способ проверки - создание средствами RHVoice звукового (*.wav) файла:&lt;br /&gt;
&amp;lt;pre&amp;gt; echo &amp;quot;привет&amp;quot; | RHVoice-test -p anna -o /home/test.wav&amp;lt;/pre&amp;gt; &lt;br /&gt;
Воспроизведение файла:&lt;br /&gt;
&amp;lt;pre&amp;gt;aplay /home/test.wav &amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Конфигурационный файл (для Linux)''' &lt;br /&gt;
Конфигурационный файл RHVoice.conf содержит подробное описание настроек синтезатора речи на русском языке и находится по следующему пути:&lt;br /&gt;
/usr/local/etc/RHVoice/RHVoice.conf&lt;br /&gt;
===Взаимодействие с MajorDoMo===&lt;br /&gt;
Для взаимодействия с системой «Умного Дома» MajorDoMo используется модуль [https://connect.smartliving.ru/addons/category4/40.html RHVoiceTTS] , [https://mjdm.ru/forum/viewtopic.php?f=5&amp;amp;t=2843&amp;amp;hilit=RHVoice+TTS ссылка на обсуждение на форуме]. &lt;br /&gt;
Модуль можно установить из '''Маркет дополнений''' категория '''Взаимодействие'''. &lt;br /&gt;
После установки модуль и настройки доступны из меню '''Приложения'''. &lt;br /&gt;
=== Проверка работоспособности MajorDoMo с установленным модулем RHVoice ===&lt;br /&gt;
Проверить работоспособность модуля и разговор MajorDoMo можно следующим образом: переходим  в '''Панель управления''', '''Объекты''', выбираем '''Шаблоны поведения'''.&lt;br /&gt;
Добавляем новую запись, вводим название (к примеру «Тест»), сохраняем.&lt;br /&gt;
Появляются новые поля для заполнение, в поле код устанавливаем PHP и вводим строку со следующим кодом:&lt;br /&gt;
&amp;lt;pre&amp;gt; say(&amp;quot;привет, говорит Умный Дом&amp;quot;,2);&amp;lt;/pre&amp;gt;&lt;br /&gt;
Сохраняем. Переходим на главную страницу MajorDoMo, в окне команд вводим название шаблона поведения (Тест). В ответ Умный Дом говорит прописанную ранее фразу (привет, говорит Умный Дом) и показывает её в окне сообщений.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%9E%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2%D1%85%D0%BE%D0%B4%D0%B0_%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9&amp;diff=2113</id>
		<title>Отключение запроса входа пользователей</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%9E%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2%D1%85%D0%BE%D0%B4%D0%B0_%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9&amp;diff=2113"/>
		<updated>2024-06-15T06:44:53Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: «Category:Первые шаги == Отключение запроса выбора входа пользователей == В альфе версии с 12.0.6.2024 обновилась процедура входа пользователей — теперь вход через отдельную страницу http://ipMjDM/popup/users.html.  В конфиге (/config.php) можно отключить отображение списка польз...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Первые шаги]]&lt;br /&gt;
== Отключение запроса выбора входа пользователей ==&lt;br /&gt;
В альфе версии с 12.0.6.2024 обновилась процедура входа пользователей — теперь вход через отдельную страницу http://ipMjDM/popup/users.html. &lt;br /&gt;
В конфиге (/config.php) можно отключить отображение списка пользователей для выбора и оставить только вход&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo nano /var/www/html/config.php &amp;lt;/pre&amp;gt;&lt;br /&gt;
(Добавить опцию: define('DISABLE_USERS_LIST',1); ) &lt;br /&gt;
&amp;lt;pre&amp;gt;define('DISABLE_USERS_LIST',1);&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Devices_class_php&amp;diff=1954</id>
		<title>Devices class php</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Devices_class_php&amp;diff=1954"/>
		<updated>2024-03-30T06:13:31Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: попробовал убрать точки в заглавии&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:SDevices]]&lt;br /&gt;
Devices_class_php&lt;br /&gt;
Возможно где-то ошибки с закрывающими или открывающими {} в связи с добавлением коментов, мог гдето херакнуть, прошу заранее прощения, сам ищу косяки и поправлю если найду. Но вроде бы не должно быть.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/**&lt;br /&gt;
 * Общий коммент к пониманию стандарта PHPDoc:&lt;br /&gt;
 * Аннотация @method для указания на то, что это комментарий к методу.&lt;br /&gt;
 * Аннотация @param для описания параметров метода.&lt;br /&gt;
 * Аннотация @return для описания возвращаемого значения метода.&lt;br /&gt;
 * Аннотация @see для ссылок на другие классы или методы.&lt;br /&gt;
 * Аннотация @since для указания версии, с которой был добавлен метод.&lt;br /&gt;
 *&lt;br /&gt;
 * Типы параметров и возвращаемых значений:&lt;br /&gt;
 * - string: строковое значение.&lt;br /&gt;
 * - int: целочисленное значение.&lt;br /&gt;
 * - float: число с плавающей точкой.&lt;br /&gt;
 * - bool: булево значение (true или false).&lt;br /&gt;
 * - array: массив.&lt;br /&gt;
 * - object: объект.&lt;br /&gt;
 * - mixed: любой тип данных.&lt;br /&gt;
 * - callable: функция или метод.&lt;br /&gt;
 * - resource: ресурс (например, файл).&lt;br /&gt;
 * - null: специальное значение, обозначающее отсутствие значения.&lt;br /&gt;
 *&lt;br /&gt;
 * Пример использования:&lt;br /&gt;
 * @method void myVoidMethod() Описание метода, который не возвращает значение.&lt;br /&gt;
 * @param string $param1 Параметр типа string.&lt;br /&gt;
 * @param int $param2 Параметр типа int.&lt;br /&gt;
 * @param float $param3 Параметр типа float.&lt;br /&gt;
 * @param bool $param4 Параметр типа bool.&lt;br /&gt;
 * @param array $param5 Параметр типа array.&lt;br /&gt;
 * @param object $param6 Параметр типа object.&lt;br /&gt;
 * @param mixed $param7 Параметр типа mixed (любой тип).&lt;br /&gt;
 * @param callable $param8 Параметр типа callable (функция или метод).&lt;br /&gt;
 * @param resource $param9 Параметр типа resource (ресурс, например, файл).&lt;br /&gt;
 * @param null $param10 Параметр типа null.&lt;br /&gt;
 * @return string Возвращает значение типа string.&lt;br /&gt;
 * @return int Возвращает значение типа int.&lt;br /&gt;
 * @return float Возвращает значение типа float.&lt;br /&gt;
 * @return bool Возвращает значение типа bool.&lt;br /&gt;
 * @return array Возвращает значение типа array.&lt;br /&gt;
 * @return object Возвращает значение типа object.&lt;br /&gt;
 * @return mixed Возвращает значение типа mixed (любой тип).&lt;br /&gt;
 * @return callable Возвращает значение типа callable (функция или метод).&lt;br /&gt;
 * @return resource Возвращает значение типа resource (ресурс, например, файл).&lt;br /&gt;
 * @return null Возвращает значение типа null.&lt;br /&gt;
 */&lt;br /&gt;
/**&lt;br /&gt;
 * Класс Devices&lt;br /&gt;
 * @package project&lt;br /&gt;
 * @author Wizard &amp;lt;sergejey@gmail.com&amp;gt;&lt;br /&gt;
 * @copyright http://majordomo.smartliving.ru/ (c)&lt;br /&gt;
 * @version 0.1 (wizard, 13:07:05 [Jul 19, 2016])&lt;br /&gt;
 * @class Devices&lt;br /&gt;
 * @property string $name Имя модуля&lt;br /&gt;
 * @property string $title Заголовок модуля&lt;br /&gt;
 * @property string $module_category Категория модуля&lt;br /&gt;
 * @method void __construct() Конструктор класса&lt;br /&gt;
 * @method void saveParams($data = 0) Сохранение параметров модуля&lt;br /&gt;
 * @method void getParams() Получение параметров модуля из строки запроса&lt;br /&gt;
 * @method void setDictionary() Установка словаря для модуля&lt;br /&gt;
 * @method void run() Основная логика модуля&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
// Класс devices расширяет модуль, что позволяет использовать функциональность модуля в классе devices.&lt;br /&gt;
class devices extends module&lt;br /&gt;
{&lt;br /&gt;
    var $view;&lt;br /&gt;
    var $id;&lt;br /&gt;
/**&lt;br /&gt;
 * Конструктор класса модуля&lt;br /&gt;
 * @method void __construct()&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
    function __construct()&lt;br /&gt;
    {&lt;br /&gt;
        // Инициализация имени модуля.&lt;br /&gt;
        $this-&amp;gt;name = &amp;quot;devices&amp;quot;;&lt;br /&gt;
        // Установка заголовка модуля, который будет отображаться в интерфейсе.&lt;br /&gt;
        $this-&amp;gt;title = &amp;quot;&amp;lt;#LANG_SECTION_DEVICES#&amp;gt;&amp;quot;;&lt;br /&gt;
        // Установка категории модуля, которая также будет отображаться в интерфейсе.&lt;br /&gt;
        $this-&amp;gt;module_category = &amp;quot;&amp;lt;#LANG_SECTION_DEVICES#&amp;gt;&amp;quot;;&lt;br /&gt;
        // Проверка, установлен ли модуль.&lt;br /&gt;
        $this-&amp;gt;checkInstalled();&lt;br /&gt;
&lt;br /&gt;
        // Установка словаря для модуля.&lt;br /&gt;
        $this-&amp;gt;setDictionary();&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
/**&lt;br /&gt;
 * saveParams&lt;br /&gt;
 *&lt;br /&gt;
 * Сохранение параметров модуля&lt;br /&gt;
 *&lt;br /&gt;
 * @method void saveParams($data = 0)&lt;br /&gt;
 * @param mixed $data Данные для сохранения&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
   function saveParams($data = 0)&lt;br /&gt;
   {&lt;br /&gt;
       $p = array();&lt;br /&gt;
       // Проверка наличия идентификатора модуля и его сохранение в массив параметров.&lt;br /&gt;
       if (isset($this-&amp;gt;id)) {&lt;br /&gt;
           $p[&amp;quot;id&amp;quot;] = $this-&amp;gt;id;&lt;br /&gt;
       }&lt;br /&gt;
       // Проверка наличия режима просмотра и его сохранение в массив параметров.&lt;br /&gt;
       if (isset($this-&amp;gt;view_mode)) {&lt;br /&gt;
           $p[&amp;quot;view_mode&amp;quot;] = $this-&amp;gt;view_mode;&lt;br /&gt;
       }&lt;br /&gt;
       // Проверка наличия режима редактирования и его сохранение в массив параметров.&lt;br /&gt;
       if (isset($this-&amp;gt;edit_mode)) {&lt;br /&gt;
           $p[&amp;quot;edit_mode&amp;quot;] = $this-&amp;gt;edit_mode;&lt;br /&gt;
       }&lt;br /&gt;
       // Проверка наличия вкладки и ее сохранение в массив параметров.&lt;br /&gt;
       if (isset($this-&amp;gt;tab)) {&lt;br /&gt;
           $p[&amp;quot;tab&amp;quot;] = $this-&amp;gt;tab;&lt;br /&gt;
       }&lt;br /&gt;
       // Вызов родительского метода saveParams с передачей массива параметров.&lt;br /&gt;
       return parent::saveParams($p);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * getParams&lt;br /&gt;
 *&lt;br /&gt;
 * Получение параметров модуля из строки запроса&lt;br /&gt;
 * Этот фрагмент кода содержит два метода:&lt;br /&gt;
 * saveParams и getParams. &lt;br /&gt;
 * Метод saveParams сохраняет параметры модуля,&lt;br /&gt;
 * а метод getParams получает их из строки запроса.&lt;br /&gt;
 * Оба методы используют глобальные переменные для работы с параметрами&lt;br /&gt;
 *&lt;br /&gt;
 * @method void getParams()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
   function getParams()&lt;br /&gt;
   {&lt;br /&gt;
       global $id;&lt;br /&gt;
       global $mode;&lt;br /&gt;
       global $view_mode;&lt;br /&gt;
       global $edit_mode;&lt;br /&gt;
       global $tab;&lt;br /&gt;
       // Проверка наличия идентификатора и его присвоение свойству класса.&lt;br /&gt;
       if (isset($id)) {&lt;br /&gt;
           $this-&amp;gt;id = $id;&lt;br /&gt;
       }&lt;br /&gt;
       // Проверка наличия режима и его присвоение свойству класса.&lt;br /&gt;
       if (isset($mode)) {&lt;br /&gt;
           $this-&amp;gt;mode = $mode;&lt;br /&gt;
       }&lt;br /&gt;
       // Проверка наличия режима просмотра и его присвоение свойству класса.&lt;br /&gt;
       if (isset($view_mode)) {&lt;br /&gt;
           $this-&amp;gt;view_mode = $view_mode;&lt;br /&gt;
       }&lt;br /&gt;
       // Проверка наличия режима редактирования и его присвоение свойству класса.&lt;br /&gt;
       if (isset($edit_mode)) {&lt;br /&gt;
           $this-&amp;gt;edit_mode = $edit_mode;&lt;br /&gt;
       }&lt;br /&gt;
       // Проверка наличия вкладки и ее присвоение свойству класса.&lt;br /&gt;
       if (isset($tab)) {&lt;br /&gt;
           $this-&amp;gt;tab = $tab;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
/**&lt;br /&gt;
 * setDictionary&lt;br /&gt;
 * Метод setDictionary включает два файла,&lt;br /&gt;
 * которые содержат структуру устройств и связи между ними.&lt;br /&gt;
 * Это необходимо для корректной работы модуля устройств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void setDictionary()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function setDictionary()&lt;br /&gt;
   {&lt;br /&gt;
       // Включение файлов, содержащих структуру устройств и связи между ними.&lt;br /&gt;
       include(dirname(__FILE__) . '/devices_structure.inc.php');&lt;br /&gt;
       include(dirname(__FILE__) . '/devices_structure_links.inc.php');&lt;br /&gt;
   }&lt;br /&gt;
/**&lt;br /&gt;
 * Run&lt;br /&gt;
 *&lt;br /&gt;
 * Метод run выполняет основную логику модуля.&lt;br /&gt;
 * Он проверяет действие, которое необходимо выполнить, и вызывает соответствующий метод.&lt;br /&gt;
 * Затем он устанавливает различные параметры,&lt;br /&gt;
 * такие как режим просмотра, режим редактирования, режим, действие и вкладку.&lt;br /&gt;
 * После этого он сохраняет данные в свойстве класса и создает новый объект парсера,&lt;br /&gt;
 * используя указанный шаблон и данные.&lt;br /&gt;
 * Результат парсинга сохраняется в свойстве класса.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void run()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function run()&lt;br /&gt;
{&lt;br /&gt;
    // Инициализация массива для хранения данных.&lt;br /&gt;
    $out = array();&lt;br /&gt;
    // Проверка действия и вызов соответствующего метода.&lt;br /&gt;
    if ($this-&amp;gt;action == 'admin') {&lt;br /&gt;
        $this-&amp;gt;admin($out);&lt;br /&gt;
    } elseif ($this-&amp;gt;action == 'link') {&lt;br /&gt;
        $this-&amp;gt;link($out);&lt;br /&gt;
    } else {&lt;br /&gt;
        $this-&amp;gt;usual($out);&lt;br /&gt;
    }&lt;br /&gt;
    // Проверка и установка действия родительского объекта.&lt;br /&gt;
    if (isset($this-&amp;gt;owner-&amp;gt;action)) {&lt;br /&gt;
        $out['PARENT_ACTION'] = $this-&amp;gt;owner-&amp;gt;action;&lt;br /&gt;
    }&lt;br /&gt;
    // Проверка и установка имени родительского объекта.&lt;br /&gt;
    if (isset($this-&amp;gt;owner-&amp;gt;name)) {&lt;br /&gt;
        $out['PARENT_NAME'] = $this-&amp;gt;owner-&amp;gt;name;&lt;br /&gt;
    }&lt;br /&gt;
    // Установка режима просмотра.&lt;br /&gt;
    $out['VIEW_MODE'] = $this-&amp;gt;view_mode;&lt;br /&gt;
    // Установка режима редактирования.&lt;br /&gt;
    $out['EDIT_MODE'] = $this-&amp;gt;edit_mode;&lt;br /&gt;
    // Установка режима.&lt;br /&gt;
    $out['MODE'] = $this-&amp;gt;mode;&lt;br /&gt;
    // Установка действия.&lt;br /&gt;
    $out['ACTION'] = $this-&amp;gt;action;&lt;br /&gt;
    // Установка вкладки.&lt;br /&gt;
    $out['TAB'] = $this-&amp;gt;tab;&lt;br /&gt;
    // Сохранение данных в свойстве класса.&lt;br /&gt;
    $this-&amp;gt;data = $out;&lt;br /&gt;
    // Создание нового объекта парсера с указанным шаблоном и данными.&lt;br /&gt;
    $p = new parser(DIR_TEMPLATES . $this-&amp;gt;name . &amp;quot;/&amp;quot; . $this-&amp;gt;name . &amp;quot;.html&amp;quot;, $this-&amp;gt;data, $this);&lt;br /&gt;
    // Сохранение результата парсинга в свойстве класса.&lt;br /&gt;
    $this-&amp;gt;result = $p-&amp;gt;result;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * link&lt;br /&gt;
 *&lt;br /&gt;
 * Метод link обрабатывает связь устройства.&lt;br /&gt;
 * Он проверяет наличие различных параметров,&lt;br /&gt;
 * таких как тип устройства, исходная таблица, идентификатор исходной таблицы, префикс,&lt;br /&gt;
 * дополнительный заголовок и связанный объект.&lt;br /&gt;
 * Если все параметры корректны, он генерирует уникальный идентификатор для устройства&lt;br /&gt;
 * и устанавливает флаг успешного выполнения.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void link()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function link(&amp;amp;$out)&lt;br /&gt;
{&lt;br /&gt;
    $ok = 1;&lt;br /&gt;
    // Проверка наличия типа устройства и его сохранение в массив вывода.&lt;br /&gt;
    if ($this-&amp;gt;type) {&lt;br /&gt;
        $out['TYPE'] = $this-&amp;gt;type;&lt;br /&gt;
    } else {&lt;br /&gt;
        // Если тип устройства не определен, устанавливаем флаг ошибки.&lt;br /&gt;
        $ok = 0;&lt;br /&gt;
    }&lt;br /&gt;
    // Проверка наличия исходной таблицы и ее сохранение в массив вывода.&lt;br /&gt;
    if ($this-&amp;gt;source_table) {&lt;br /&gt;
        $out['SOURCE_TABLE'] = $this-&amp;gt;source_table;&lt;br /&gt;
    } else {&lt;br /&gt;
        // Если исходная таблица не определена, устанавливаем флаг ошибки.&lt;br /&gt;
        $ok = 0;&lt;br /&gt;
    }&lt;br /&gt;
    // Проверка наличия идентификатора исходной таблицы и его сохранение в массив вывода.&lt;br /&gt;
    if ($this-&amp;gt;source_table_id) {&lt;br /&gt;
        $out['SOURCE_TABLE_ID'] = $this-&amp;gt;source_table_id;&lt;br /&gt;
    } else {&lt;br /&gt;
        // Если идентификатор исходной таблицы не определен, устанавливаем флаг ошибки.&lt;br /&gt;
        $ok = 0;&lt;br /&gt;
    }&lt;br /&gt;
    // Проверка наличия префикса и его сохранение в массив вывода.&lt;br /&gt;
    if ($this-&amp;gt;prefix) {&lt;br /&gt;
        $out['PREFIX'] = $this-&amp;gt;prefix;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Проверка наличия дополнительного заголовка и его сохранение в массив вывода.&lt;br /&gt;
    if (isset($this-&amp;gt;add_title)) {&lt;br /&gt;
        $out['ADD_TITLE'] = urlencode($this-&amp;gt;add_title);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Проверка наличия связанного объекта и его сохранение в массив вывода.&lt;br /&gt;
    if ($this-&amp;gt;linked_object) {&lt;br /&gt;
        $device_rec = SQLSelectOne(&amp;quot;SELECT ID,TITLE FROM devices WHERE LINKED_OBJECT LIKE '&amp;quot; . DBSafe($this-&amp;gt;linked_object) . &amp;quot;'&amp;quot;);&lt;br /&gt;
        if (isset($device_rec['TITLE'])) {&lt;br /&gt;
            $out['TITLE'] = $device_rec['TITLE'];&lt;br /&gt;
            // Если установлен флаг предварительного просмотра, обрабатываем устройство и сохраняем результат в массив вывода.&lt;br /&gt;
            if ($this-&amp;gt;preview) {&lt;br /&gt;
                $data = $this-&amp;gt;processDevice($device_rec['ID']);&lt;br /&gt;
                $out['HTML'] = $data['HTML'];&lt;br /&gt;
            }&lt;br /&gt;
            $out['ID'] = $device_rec['ID'];&lt;br /&gt;
        }&lt;br /&gt;
        $out['LINKED_OBJECT'] = $this-&amp;gt;linked_object;&lt;br /&gt;
    }&lt;br /&gt;
    // Генерация уникального идентификатора для устройства.&lt;br /&gt;
    $out['UNIQ'] = uniqid('dev');&lt;br /&gt;
    // Если все параметры корректны, устанавливаем флаг успешного выполнения.&lt;br /&gt;
    if ($ok) {&lt;br /&gt;
        $out['OK'] = 1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * getTypeDetails&lt;br /&gt;
 *&lt;br /&gt;
 * Метод getTypeDetails возвращает детали типа устройства из словаря типов устройств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array getTypeDetails($type)&lt;br /&gt;
 * @param string $type Тип устройства&lt;br /&gt;
 * @return array Детали типа устройства&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getTypeDetails($type)&lt;br /&gt;
{&lt;br /&gt;
    // Возвращает детали типа устройства из словаря типов устройств.&lt;br /&gt;
    return $this-&amp;gt;device_types[$type];&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * getTypeLinks&lt;br /&gt;
 *&lt;br /&gt;
 * Метод getTypeLinks возвращает все связи, которые связаны с указанным типом устройства.&lt;br /&gt;
 * Он сначала получает детали типа устройства,&lt;br /&gt;
 * а затем проходит по всем связям устройств, проверяя,&lt;br /&gt;
 * присутствует ли класс или родительский класс типа устройства в типах связей.&lt;br /&gt;
 * Если да, то все связи этого типа добавляются в результирующий массив.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array getTypeLinks($type)&lt;br /&gt;
 * @param string $type Тип устройства&lt;br /&gt;
 * @return array Все связи, связанные с указанным типом устройства&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getTypeLinks($type)&lt;br /&gt;
{&lt;br /&gt;
    // Получаем детали типа устройства.&lt;br /&gt;
    $type_details = $this-&amp;gt;getTypeDetails($type);&lt;br /&gt;
    $res_links = array();&lt;br /&gt;
    // Проходимся по всем связям устройств.&lt;br /&gt;
    foreach ($this-&amp;gt;device_links as $k =&amp;gt; $v) {&lt;br /&gt;
        // Разделяем типы связей на отдельные элементы.&lt;br /&gt;
        $link_types = explode(',', $k);&lt;br /&gt;
        $link_types = array_map('trim', $link_types);&lt;br /&gt;
        // Если класс или родительский класс типа устройства присутствует в типах связей,&lt;br /&gt;
        if (in_array($type_details['CLASS'], $link_types) || in_array($type_details['PARENT_CLASS'], $link_types)) {&lt;br /&gt;
            // добавляем все связи этого типа в результирующий массив.&lt;br /&gt;
            foreach ($v as $link) {&lt;br /&gt;
                $res_links[] = $link;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Возвращаем результирующий массив связей.&lt;br /&gt;
    return $res_links;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * getLinkDetails&lt;br /&gt;
 *&lt;br /&gt;
 * Метод getLinkDetails возвращает детали связи устройства по указанному имени связи.&lt;br /&gt;
 * Он проходит по всем связям устройств и возвращает детали той связи,&lt;br /&gt;
 * имя которой совпадает с указанным именем связи.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array getLinkDetails($link_name)&lt;br /&gt;
 * @param string $link_name Имя связи устройства&lt;br /&gt;
 * @return array Детали связи устройства&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getLinkDetails($link_name)&lt;br /&gt;
{&lt;br /&gt;
    // Проходимся по всем связям устройств.&lt;br /&gt;
    foreach ($this-&amp;gt;device_links as $k =&amp;gt; $v) {&lt;br /&gt;
        foreach ($v as $link) {&lt;br /&gt;
            // Если имя связи совпадает с указанным именем связи, возвращаем детали этой связи.&lt;br /&gt;
            if ($link['LINK_NAME'] == $link_name) {&lt;br /&gt;
                return $link;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * getAllGroups&lt;br /&gt;
 *&lt;br /&gt;
 * Метод getAllGroups возвращает все группы устройств, которые применимы к указанному типу устройства.&lt;br /&gt;
 * Он выбирает все группы устройств из базы данных,&lt;br /&gt;
 * проходит по ним и добавляет в результирующий массив те группы,&lt;br /&gt;
 * типы которых присутствуют в типах, применимых к группе.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array getAllGroups($type)&lt;br /&gt;
 * @param string $type Тип устройства&lt;br /&gt;
 * @return array Все группы устройств, применимые к указанному типу устройства&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getAllGroups($type)&lt;br /&gt;
{&lt;br /&gt;
    // Выбираем все группы устройств из базы данных.&lt;br /&gt;
    $groups = SQLSelect(&amp;quot;SELECT * FROM devices_groups&amp;quot;);&lt;br /&gt;
    $res = array();&lt;br /&gt;
    $total = count($groups);&lt;br /&gt;
    // Проходимся по всем группам.&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        $tmp = explode(',', $groups[$i]['APPLY_TYPES']);&lt;br /&gt;
        // Если тип устройства присутствует в типах, применимых к группе, добавляем группу в результирующий массив.&lt;br /&gt;
        if (in_array($type, $tmp)) {&lt;br /&gt;
            $res[] = $groups[$i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Возвращаем результирующий массив групп.&lt;br /&gt;
    return $res;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * getAllProperties&lt;br /&gt;
 *&lt;br /&gt;
 * Метод getAllProperties возвращает все свойства указанного типа устройства,&lt;br /&gt;
 * включая свойства его родительского класса.&lt;br /&gt;
 * Он сначала получает свойства текущего типа устройства,&lt;br /&gt;
 * а затем, если у типа устройства есть родительский класс,&lt;br /&gt;
 * проходит по всем типам устройств, ищет свойства родительского класса и добавляет их в свойства текущего типа,&lt;br /&gt;
 * если они еще не присутствуют.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array getAllProperties($type)&lt;br /&gt;
 * @param string $type Тип устройства&lt;br /&gt;
 * @return array Все свойства указанного типа устройства, включая свойства его родительского класса&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getAllProperties($type)&lt;br /&gt;
{&lt;br /&gt;
    // Получаем свойства текущего типа устройства.&lt;br /&gt;
    $properties = $this-&amp;gt;device_types[$type]['PROPERTIES'];&lt;br /&gt;
    $parent_class = isset($this-&amp;gt;device_types[$type]['PARENT_CLASS']) ? $this-&amp;gt;device_types[$type]['PARENT_CLASS'] : '';&lt;br /&gt;
    // Если у типа устройства есть родительский класс,&lt;br /&gt;
    if ($parent_class != '') {&lt;br /&gt;
        // проходимся по всем типам устройств.&lt;br /&gt;
        foreach ($this-&amp;gt;device_types as $k =&amp;gt; $v) {&lt;br /&gt;
            // Если класс текущего типа совпадает с родительским классом,&lt;br /&gt;
            if ($v['CLASS'] == $parent_class) {&lt;br /&gt;
                // получаем свойства родительского класса.&lt;br /&gt;
                $parent_properties = $this-&amp;gt;getAllProperties($k);&lt;br /&gt;
                // Проходимся по всем свойствам родительского класса.&lt;br /&gt;
                foreach ($parent_properties as $pk =&amp;gt; $pv) {&lt;br /&gt;
                    // Если свойство родительского класса еще не присутствует в свойствах текущего типа, добавляем его.&lt;br /&gt;
                    if (!isset($properties[$pk])) {&lt;br /&gt;
                        $properties[$pk] = $pv;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Возвращаем все свойства текущего типа устройства, включая свойства родительского класса.&lt;br /&gt;
    return $properties;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * getAllMethods&lt;br /&gt;
 *&lt;br /&gt;
 * Метод getAllMethods возвращает все методы указанного типа устройства,&lt;br /&gt;
 * включая методы его родительского класса.&lt;br /&gt;
 * Он сначала получает методы текущего типа устройства,&lt;br /&gt;
 * а затем, если у типа устройства есть родительский класс,&lt;br /&gt;
 * проходит по всем типам устройств,&lt;br /&gt;
 * ищет методы родительского класса и добавляет их в методы текущего типа,&lt;br /&gt;
 * если они еще не присутствуют.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array getAllMethods($type)&lt;br /&gt;
 * @param string $type Тип устройства&lt;br /&gt;
 * @return array Все методы указанного типа устройства, включая методы его родительского класса&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getAllMethods($type)&lt;br /&gt;
{&lt;br /&gt;
    // Получаем методы текущего типа устройства.&lt;br /&gt;
    $methods = $this-&amp;gt;device_types[$type]['METHODS'];&lt;br /&gt;
    $parent_class = isset($this-&amp;gt;device_types[$type]['PARENT_CLASS']) ? $this-&amp;gt;device_types[$type]['PARENT_CLASS'] : '';&lt;br /&gt;
    // Если у типа устройства есть родительский класс,&lt;br /&gt;
    if ($parent_class != '') {&lt;br /&gt;
        // проходимся по всем типам устройств.&lt;br /&gt;
        foreach ($this-&amp;gt;device_types as $k =&amp;gt; $v) {&lt;br /&gt;
            // Если класс текущего типа совпадает с родительским классом,&lt;br /&gt;
            if ($v['CLASS'] == $parent_class) {&lt;br /&gt;
                // получаем методы родительского класса.&lt;br /&gt;
                $parent_methods = $this-&amp;gt;getAllMethods($k);&lt;br /&gt;
                // Проходимся по всем методам родительского класса.&lt;br /&gt;
                foreach ($parent_methods as $pk =&amp;gt; $pv) {&lt;br /&gt;
                    // Если метод родительского класса еще не присутствует в методах текущего типа, добавляем его.&lt;br /&gt;
                    if (!isset($methods[$pk])) {&lt;br /&gt;
                        $methods[$pk] = $pv;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Возвращаем все методы текущего типа устройства, включая методы родительского класса.&lt;br /&gt;
    return $methods;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * getNewObjectIndex&lt;br /&gt;
 *&lt;br /&gt;
 * Метод getNewObjectIndex возвращает новый индекс для объекта указанного класса.&lt;br /&gt;
 * Он сначала получает объекты указанного класса, а затем, если префикс не пустой,&lt;br /&gt;
 * выбирает дополнительные объекты, которые начинаются с этого префикса.&lt;br /&gt;
 * Затем он проходит по всем объектам, ищет числа в их названиях и обновляет индекс,&lt;br /&gt;
 * если найденное число больше текущего индекса.&lt;br /&gt;
 * В конце метод возвращает индекс, увеличенный на 1, и добавляет в начало ноль, если индекс меньше 10.&lt;br /&gt;
 *&lt;br /&gt;
 * @method string getNewObjectIndex($class, $prefix = '')&lt;br /&gt;
 * @param string $class Имя класса&lt;br /&gt;
 * @param string $prefix Префикс для поиска объектов&lt;br /&gt;
 * @return string Новый индекс для объекта указанного класса&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getNewObjectIndex($class, $prefix = '')&lt;br /&gt;
{&lt;br /&gt;
    // Получаем объекты указанного класса.&lt;br /&gt;
    $objects = getObjectsByClass($class);&lt;br /&gt;
    if ($prefix != '') {&lt;br /&gt;
        // Если префикс не пустой, выбираем дополнительные объекты, которые начинаются с этого префикса.&lt;br /&gt;
        $other_objects = SQLSelect(&amp;quot;SELECT TITLE FROM objects WHERE TITLE LIKE '&amp;quot; . $prefix . &amp;quot;%'&amp;quot;);&lt;br /&gt;
        foreach ($other_objects as $obj) {&lt;br /&gt;
            $objects[] = $obj;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    $index = 0;&lt;br /&gt;
    $total = count($objects);&lt;br /&gt;
    // Проходимся по всем объектам.&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        // Если в названии объекта присутствует число,&lt;br /&gt;
        if (preg_match('/(\d+)/', $objects[$i]['TITLE'], $m)) {&lt;br /&gt;
            $current_index = (int)$m[1];&lt;br /&gt;
            // и это число больше текущего индекса, обновляем индекс.&lt;br /&gt;
            if ($current_index &amp;gt; $index) {&lt;br /&gt;
                $index = $current_index;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    $index++;&lt;br /&gt;
    // Если индекс меньше 10, добавляем в начало ноль.&lt;br /&gt;
    if ($index &amp;lt; 10) {&lt;br /&gt;
        $index = '0' . $index;&lt;br /&gt;
    }&lt;br /&gt;
    // Возвращаем индекс.&lt;br /&gt;
    return $index;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * processDevice&lt;br /&gt;
 *&lt;br /&gt;
 * Метод processDevice обрабатывает устройство с указанным идентификатором.&lt;br /&gt;
 * Он выбирает запись устройства из базы данных, получает шаблон для объекта класса устройства,&lt;br /&gt;
 * обрабатывает шаблон и сохраняет результат в массив результатов.&lt;br /&gt;
 * Если тип устройства - 'camera', он устанавливает высоту результата.&lt;br /&gt;
 * В конце метод возвращает результат.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array processDevice($device_id, $view = '')&lt;br /&gt;
 * @param int $device_id Идентификатор устройства&lt;br /&gt;
 * @param string $view Название представления&lt;br /&gt;
 * @return array Результат обработки устройства&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function processDevice($device_id, $view = '')&lt;br /&gt;
{&lt;br /&gt;
    // Начинаем измерение времени выполнения метода.&lt;br /&gt;
    startMeasure('processDevice');&lt;br /&gt;
    // Выбираем запись устройства из базы данных по его идентификатору.&lt;br /&gt;
    $device_rec = SQLSelectOne(&amp;quot;SELECT * FROM devices WHERE ID=&amp;quot; . (int)$device_id);&lt;br /&gt;
    $result = array('HTML' =&amp;gt; '', 'DEVICE_ID' =&amp;gt; $device_rec['ID']);&lt;br /&gt;
&lt;br /&gt;
    // Получаем шаблон для объекта класса устройства.&lt;br /&gt;
    $template = getObjectClassTemplate($device_rec['LINKED_OBJECT'], $view);&lt;br /&gt;
&lt;br /&gt;
    // Обрабатываем шаблон и сохраняем результат в массив результатов.&lt;br /&gt;
    $result['HTML'] = processTitle($template, $this);&lt;br /&gt;
    // Если тип устройства - 'camera', устанавливаем высоту результата.&lt;br /&gt;
    if ($device_rec['TYPE'] == 'camera') {&lt;br /&gt;
        $result['HEIGHT'] = 5;&lt;br /&gt;
    }&lt;br /&gt;
    // Завершаем измерение времени выполнения метода.&lt;br /&gt;
    endMeasure('processDevice');&lt;br /&gt;
    // Возвращаем результат.&lt;br /&gt;
    return $result;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * getWatchedProperties&lt;br /&gt;
 *&lt;br /&gt;
 * Метод getWatchedProperties возвращает все свойства устройств, которые нужно отслеживать.&lt;br /&gt;
 * Он сначала устанавливает словарь для модуля,&lt;br /&gt;
 * затем выбирает устройства из базы данных и проходит по ним.&lt;br /&gt;
 * Для каждого устройства он получает все свойства текущего типа устройства и добавляет их в результирующий массив.&lt;br /&gt;
 * Если тип устройства - 'html', он обрабатывает содержимое устройства,&lt;br /&gt;
 * удаляет из него все символы, которые не являются частью имени свойства,&lt;br /&gt;
 * ищет все имена свойств в содержимом устройства&lt;br /&gt;
 * и добавляет каждое найденное свойство в результирующий массив.&lt;br /&gt;
 * В конце метод возвращает результирующий массив свойств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array getWatchedProperties($device_id = 0)&lt;br /&gt;
 * @param int $device_id Идентификатор устройства&lt;br /&gt;
 * @return array Все свойства устройств, которые нужно отслеживать&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getWatchedProperties($device_id = 0)&lt;br /&gt;
{&lt;br /&gt;
    // Устанавливаем словарь для модуля.&lt;br /&gt;
    $this-&amp;gt;setDictionary();&lt;br /&gt;
    $properties = array();&lt;br /&gt;
    $qry = 1;&lt;br /&gt;
    if ($device_id) {&lt;br /&gt;
        // Если указан идентификатор устройства, добавляем его в запрос.&lt;br /&gt;
        $qry .= &amp;quot; AND devices.ID IN (&amp;quot; . $device_id . &amp;quot;)&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    // Выбираем устройства из базы данных.&lt;br /&gt;
    $devices = SQLSelect(&amp;quot;SELECT * FROM devices WHERE $qry&amp;quot;);&lt;br /&gt;
    $total = count($devices);&lt;br /&gt;
    // Проходимся по всем устройствам.&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        if (!$devices[$i]['LINKED_OBJECT']) {&lt;br /&gt;
            continue;&lt;br /&gt;
        }&lt;br /&gt;
        // Получаем все свойства текущего типа устройства.&lt;br /&gt;
        $props = $this-&amp;gt;getAllProperties($devices[$i]['TYPE']);&lt;br /&gt;
        if (is_array($props)) {&lt;br /&gt;
            foreach ($props as $k =&amp;gt; $v) {&lt;br /&gt;
                // Если имя свойства начинается с символа подчеркивания, пропускаем его.&lt;br /&gt;
                if (substr($k, 0, 1) == '_') continue;&lt;br /&gt;
                // Добавляем свойство в результирующий массив.&lt;br /&gt;
                $properties[] = array('PROPERTY' =&amp;gt; mb_strtolower($devices[$i]['LINKED_OBJECT'] . '.' . $k, 'UTF-8'), 'DEVICE_ID' =&amp;gt; $devices[$i]['ID']);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        // Если тип устройства - 'html', обрабатываем содержимое устройства.&lt;br /&gt;
        if ($devices[$i]['TYPE'] == 'html') {&lt;br /&gt;
            $content = getGlobal($devices[$i]['LINKED_OBJECT'] . '.data');&lt;br /&gt;
            // Удаляем из содержимого устройства все символы, которые не являются частью имени свойства.&lt;br /&gt;
            $content = preg_replace('/%([\w\d\.]+?)\.([\w\d\.]+?)\|(\d+)%/uis', '%\1.\2%', $content);&lt;br /&gt;
            $content = preg_replace('/%([\w\d\.]+?)\.([\w\d\.]+?)\|(\d+)%/uis', '%\1.\2%', $content);&lt;br /&gt;
            $content = preg_replace('/%([\w\d\.]+?)\.([\w\d\.]+?)\|&amp;quot;.+?&amp;quot;%/uis', '%\1.\2%', $content);&lt;br /&gt;
            // Ищем все имена свойств в содержимом устройства.&lt;br /&gt;
            if (preg_match_all('/%([\w\d\.]+?)%/is', $content, $m)) {&lt;br /&gt;
                $totalm = count($m[1]);&lt;br /&gt;
                for ($im = 0; $im &amp;lt; $totalm; $im++) {&lt;br /&gt;
                    // Добавляем каждое найденное свойство в результирующий массив.&lt;br /&gt;
                    $properties[] = array('PROPERTY' =&amp;gt; mb_strtolower($m[1][$im], 'UTF-8'), 'DEVICE_ID' =&amp;gt; $devices[$i]['ID']);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Возвращаем результирующий массив свойств.&lt;br /&gt;
    return $properties;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * updateGroupObjects&lt;br /&gt;
 *&lt;br /&gt;
 * Метод updateGroupObjects обновляет объекты групп устройств.&lt;br /&gt;
 * Он сначала выбирает все группы устройств из базы данных,&lt;br /&gt;
 * затем проходит по ним и добавляет объект класса 'SGroups'&lt;br /&gt;
 * с указанным именем и описанием для каждой группы.&lt;br /&gt;
 * Затем он устанавливает свойство 'groupName' для каждого объекта&lt;br /&gt;
 * и сохраняет его в массив добавленных объектов.&lt;br /&gt;
 * После этого он получает все объекты класса 'SGroups'&lt;br /&gt;
 * и удаляет те из них, которые не присутствуют в массиве добавленных объектов.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void updateGroupObjects()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function updateGroupObjects()&lt;br /&gt;
{&lt;br /&gt;
    // Выбираем все группы устройств из базы данных.&lt;br /&gt;
    $groups = SQLSelect(&amp;quot;SELECT * FROM devices_groups WHERE 1&amp;quot;);&lt;br /&gt;
    $total = count($groups);&lt;br /&gt;
    $added_objects = array();&lt;br /&gt;
    // Проходимся по всем группам.&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        // Добавляем объект класса 'SGroups' с указанным именем и описанием.&lt;br /&gt;
        $object_id = addClassObject('SGroups', 'group' . $groups[$i]['SYS_NAME'], 'group' . $groups[$i]['SYS_NAME']);&lt;br /&gt;
        $object_rec = SQLSelectOne(&amp;quot;SELECT * FROM objects WHERE ID=&amp;quot; . $object_id);&lt;br /&gt;
        if ($object_rec['ID']) {&lt;br /&gt;
            // Обновляем описание объекта.&lt;br /&gt;
            $object_rec['DESCRIPTION'] = $groups[$i]['TITLE'];&lt;br /&gt;
            SQLUpdate('objects', $object_rec);&lt;br /&gt;
        }&lt;br /&gt;
        // Устанавливаем свойство 'groupName' для объекта.&lt;br /&gt;
        sg($object_rec['TITLE'] . '.groupName', $groups[$i]['SYS_NAME']);&lt;br /&gt;
        $added_objects[] = $object_id;&lt;br /&gt;
    }&lt;br /&gt;
    // Получаем все объекты класса 'SGroups'.&lt;br /&gt;
    $group_objects = getObjectsByClass('SGroups');&lt;br /&gt;
    foreach ($group_objects as $rec) {&lt;br /&gt;
        // Если объект не присутствует в массиве добавленных объектов, удаляем его.&lt;br /&gt;
        if (!in_array($rec['ID'], $added_objects)) {&lt;br /&gt;
            deleteObject($rec['ID']);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * renderStructure&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция отвечает за рендеринг структуры устройств.&lt;br /&gt;
 * Она проходит по всем типам устройств и для каждого типа выполняет следующие действия:&lt;br /&gt;
 * - Добавляет класс устройства, если он не существует.&lt;br /&gt;
 * - Обновляет описание класса, если оно задано.&lt;br /&gt;
 * - Добавляет свойства класса, если они не существуют.&lt;br /&gt;
 * - Добавляет методы класса, если они не существуют.&lt;br /&gt;
 * - Добавляет объекты класса, если они не существуют.&lt;br /&gt;
 * - Подписывается на события 'COMMAND' и 'MINUTELY' для модуля устройств.&lt;br /&gt;
 * - Обновляет превью камер.&lt;br /&gt;
 * - Обновляет объекты устройств.&lt;br /&gt;
 * - Обновляет объекты групп устройств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void renderStructure()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function renderStructure()&lt;br /&gt;
{&lt;br /&gt;
    // Проверяем, определена ли константа DISABLE_SIMPLE_DEVICES и равна ли она 1&lt;br /&gt;
    if (defined('DISABLE_SIMPLE_DEVICES') &amp;amp;&amp;amp; DISABLE_SIMPLE_DEVICES == 1) {&lt;br /&gt;
        // Если условие выполняется, отписываемся от событий 'COMMAND' и 'MINUTELY' для модуля устройств и прекращаем выполнение функции&lt;br /&gt;
        unsubscribeFromEvent('devices', 'COMMAND');&lt;br /&gt;
        unsubscribeFromEvent('devices', 'MINUTELY');&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Проходимся по всем типам устройств&lt;br /&gt;
    foreach ($this-&amp;gt;device_types as $k =&amp;gt; $v) {&lt;br /&gt;
        // Класс устройства&lt;br /&gt;
        if (isset($v['PARENT_CLASS'])) {&lt;br /&gt;
            // Если у устройства есть родительский класс, добавляем класс с указанием родительского класса&lt;br /&gt;
            $class_id = addClass($v['CLASS'], $v['PARENT_CLASS']);&lt;br /&gt;
        } else {&lt;br /&gt;
            // Если у устройства нет родительского класса, добавляем класс без указания родительского класса&lt;br /&gt;
            $class_id = addClass($v['CLASS']);&lt;br /&gt;
        }&lt;br /&gt;
        // Если класс успешно добавлен&lt;br /&gt;
        if ($class_id) {&lt;br /&gt;
            // Получаем информацию о классе из базы данных&lt;br /&gt;
            $class = SQLSelectOne(&amp;quot;SELECT * FROM classes WHERE ID=&amp;quot; . $class_id);&lt;br /&gt;
            // Если у устройства есть описание, обновляем описание класса в базе данных&lt;br /&gt;
            if (isset($v['DESCRIPTION'])) {&lt;br /&gt;
                $class['DESCRIPTION'] = $v['DESCRIPTION'];&lt;br /&gt;
                SQLUpdate('classes', $class);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Свойства класса&lt;br /&gt;
        if (isset($v['PROPERTIES']) &amp;amp;&amp;amp; is_array($v['PROPERTIES'])) {&lt;br /&gt;
            // Проходимся по всем свойствам класса&lt;br /&gt;
            foreach ($v['PROPERTIES'] as $pk =&amp;gt; $pv) {&lt;br /&gt;
                // Добавляем свойство класса с указанием, нужно ли сохранять историю изменений свойства&lt;br /&gt;
                $prop_id = addClassProperty($v['CLASS'], $pk, isset($pv['KEEP_HISTORY']) ? $pv['KEEP_HISTORY'] : 0);&lt;br /&gt;
                // Если свойство успешно добавлено&lt;br /&gt;
                if ($prop_id) {&lt;br /&gt;
                    // Получаем информацию о свойстве из базы данных&lt;br /&gt;
                    $property = SQLSelectOne(&amp;quot;SELECT * FROM properties WHERE ID=&amp;quot; . $prop_id);&lt;br /&gt;
                    // Если свойство является массивом&lt;br /&gt;
                    if (is_array($pv)) {&lt;br /&gt;
                        // Проходимся по всем элементам массива свойства&lt;br /&gt;
                        foreach ($pv as $ppk =&amp;gt; $ppv) {&lt;br /&gt;
                            // Если ключ свойства начинается с символа подчеркивания, пропускаем его&lt;br /&gt;
                            if (substr($ppk, 0, 1) == '_') continue;&lt;br /&gt;
                            // Если свойство 'KEEP_HISTORY' уже установлено, пропускаем его&lt;br /&gt;
                            if ($ppk == 'KEEP_HISTORY' &amp;amp;&amp;amp; $property[$ppk]) continue;&lt;br /&gt;
                            // Обновляем значение свойства&lt;br /&gt;
                            $property[$ppk] = $ppv;&lt;br /&gt;
                        }&lt;br /&gt;
                        // Обновляем информацию о свойстве в базе данных&lt;br /&gt;
                        SQLUpdate('properties', $property);&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Методы класса&lt;br /&gt;
        if (isset($v['METHODS']) &amp;amp;&amp;amp; is_array($v['METHODS'])) {&lt;br /&gt;
            // Проходимся по всем методам класса&lt;br /&gt;
            foreach ($v['METHODS'] as $mk =&amp;gt; $mv) {&lt;br /&gt;
                // Добавляем метод класса с указанием кода метода и класса, к которому он принадлежит&lt;br /&gt;
                $method_id = addClassMethod($v['CLASS'], $mk, &amp;quot;require(DIR_MODULES.'devices/&amp;quot; . $v['CLASS'] . &amp;quot;_&amp;quot; . $mk . &amp;quot;.php');&amp;quot;, 'SDevices');&lt;br /&gt;
                // Если файл метода не существует, создаем его&lt;br /&gt;
                if (!file_exists(dirname(__FILE__) . '/' . $v['CLASS'] . &amp;quot;_&amp;quot; . $mk . &amp;quot;.php&amp;quot;)) {&lt;br /&gt;
                    $code = '&amp;lt;?php' . &amp;quot;\n\n&amp;quot;;&lt;br /&gt;
                    @SaveFile(dirname(__FILE__) . &amp;quot;/&amp;quot; . $v['CLASS'] . &amp;quot;_&amp;quot; . $mk . &amp;quot;.php&amp;quot;, $code);&lt;br /&gt;
                }&lt;br /&gt;
                // Если метод успешно добавлен&lt;br /&gt;
                if ($method_id) {&lt;br /&gt;
                    // Получаем информацию о методе из базы данных&lt;br /&gt;
                    $method = SQLSelectOne(&amp;quot;SELECT * FROM methods WHERE ID=&amp;quot; . $method_id);&lt;br /&gt;
                    // Если метод является массивом&lt;br /&gt;
                    if (is_array($mv)) {&lt;br /&gt;
                        // Проходимся по всем элементам массива метода&lt;br /&gt;
                        foreach ($mv as $mmk =&amp;gt; $mmv) {&lt;br /&gt;
                            // Если ключ метода начинается с символа подчеркивания, пропускаем его&lt;br /&gt;
                            if (substr($mmk, 0, 1) == '_') continue;&lt;br /&gt;
                            // Обновляем значение метода&lt;br /&gt;
                            $method[$mmk] = $mmv;&lt;br /&gt;
                        }&lt;br /&gt;
                        // Обновляем информацию о методе в базе данных&lt;br /&gt;
                        SQLUpdate('methods', $method);&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Внедрение методов&lt;br /&gt;
        if (isset($v['INJECTS']) &amp;amp;&amp;amp; is_array($v['INJECTS'])) {&lt;br /&gt;
            // Проходимся по всем внедренным методам&lt;br /&gt;
            foreach ($v['INJECTS'] as $class_name =&amp;gt; $methods) {&lt;br /&gt;
                // Добавляем класс&lt;br /&gt;
                addClass($class_name);&lt;br /&gt;
                // Проходимся по всем методам внедренного класса&lt;br /&gt;
                foreach ($methods as $mk =&amp;gt; $mv) {&lt;br /&gt;
                    // Разделяем имя объекта и имя метода&lt;br /&gt;
                    list($object, $method_name) = explode('.', $mk);&lt;br /&gt;
                    // Добавляем объект класса&lt;br /&gt;
                    addClassObject($class_name, $object);&lt;br /&gt;
                    // Если файл метода не существует, создаем его&lt;br /&gt;
                    if (!file_exists(dirname(__FILE__) . &amp;quot;/&amp;quot; . $mv . &amp;quot;.php&amp;quot;)) {&lt;br /&gt;
                        $code = '&amp;lt;?php' . &amp;quot;\n\n&amp;quot;;&lt;br /&gt;
                        @SaveFile(dirname(__FILE__) . &amp;quot;/&amp;quot; . $mv . &amp;quot;.php&amp;quot;, $code);&lt;br /&gt;
                    }&lt;br /&gt;
                    // Внедряем код метода в объект&lt;br /&gt;
                    injectObjectMethodCode($mk, 'SDevices', &amp;quot;require(DIR_MODULES.'devices/&amp;quot; . $mv . &amp;quot;.php');&amp;quot;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Подписываемся на события 'COMMAND' и 'MINUTELY' для модуля устройств&lt;br /&gt;
    subscribeToEvent('devices', 'COMMAND');&lt;br /&gt;
    subscribeToEvent('devices', 'MINUTELY');&lt;br /&gt;
&lt;br /&gt;
    // Обновление камер&lt;br /&gt;
    $objects = getObjectsByClass('SCameras');&lt;br /&gt;
    $total = count($objects);&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        $ot = $objects[$i]['TITLE'];&lt;br /&gt;
        callMethod($ot . '.updatePreview');&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Обновление объектов устройств&lt;br /&gt;
    $devices = SQLSelect(&amp;quot;SELECT ID, LINKED_OBJECT FROM devices&amp;quot;);&lt;br /&gt;
    foreach ($devices as $device) {&lt;br /&gt;
        SQLExec(&amp;quot;UPDATE objects SET `SYSTEM`='sdevice&amp;quot; . $device['ID'] . &amp;quot;' WHERE TITLE='&amp;quot; . DBSafe($device['LINKED_OBJECT']) . &amp;quot;' AND `SYSTEM`=''&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Обновление объектов групп устройств&lt;br /&gt;
    $this-&amp;gt;updateGroupObjects();&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * processSubscription&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция обрабатывает подписки на события.&lt;br /&gt;
 * Она обрабатывает различные операции, такие как клик по устройству, получение устройства, получение устройств,&lt;br /&gt;
 * загрузка всех устройств HTML, клик по устройству и получение устройств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void processSubscription($event, &amp;amp;$details)&lt;br /&gt;
 * @param string $event Имя события&lt;br /&gt;
 * @param array $details Детали события&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function processSubscription($event, &amp;amp;$details)&lt;br /&gt;
{&lt;br /&gt;
    // Если событие равно 'COMMAND' и есть идентификатор участника&lt;br /&gt;
    if ($event == 'COMMAND' &amp;amp;&amp;amp; $details['member_id']) {&lt;br /&gt;
        // Включаем файл для обработки команды&lt;br /&gt;
        include_once(dirname(__FILE__) . '/processCommand.inc.php');&lt;br /&gt;
    }&lt;br /&gt;
    // Если событие равно 'MINUTELY'&lt;br /&gt;
    if ($event == 'MINUTELY') {&lt;br /&gt;
        // Выбираем все активные точки планировщика устройств&lt;br /&gt;
        $points = SQLSelect(&amp;quot;SELECT devices_scheduler_points.*, devices.LINKED_OBJECT FROM devices_scheduler_points LEFT JOIN devices ON devices_scheduler_points.DEVICE_ID=devices.ID WHERE ACTIVE=1&amp;quot;);&lt;br /&gt;
        $total = count($points);&lt;br /&gt;
        // Проходимся по всем точкам планировщика&lt;br /&gt;
        for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
            $rec = $points[$i];&lt;br /&gt;
            // Если дни не установлены, пропускаем текущую итерацию&lt;br /&gt;
            if ($rec['SET_DAYS'] === '') {&lt;br /&gt;
                continue;&lt;br /&gt;
            }&lt;br /&gt;
            // Разделяем дни на отдельные элементы&lt;br /&gt;
            $run_days = explode(',', $rec['SET_DAYS']);&lt;br /&gt;
            // Если текущий день не входит в список дней, пропускаем текущую итерацию&lt;br /&gt;
            if (!in_array(date('w'), $run_days)) {&lt;br /&gt;
                continue;&lt;br /&gt;
            }&lt;br /&gt;
            // Преобразуем время запуска в метку времени&lt;br /&gt;
            $tm = strtotime(date('Y-m-d') . ' ' . $rec['SET_TIME']);&lt;br /&gt;
            // Вычисляем разницу между текущим временем и временем запуска&lt;br /&gt;
            $diff = time() - $tm;&lt;br /&gt;
&lt;br /&gt;
            // Преобразуем время последнего запуска в метку времени&lt;br /&gt;
            $latestRun = strtotime($rec['LATEST_RUN']);&lt;br /&gt;
            // Вычисляем разницу между текущим временем и временем последнего запуска&lt;br /&gt;
            $diff2 = time() - $latestRun;&lt;br /&gt;
&lt;br /&gt;
            // Если разница меньше нуля, разница больше или равна 10 минутам или разница между последним запуском и текущим временем меньше или равна 10 минутам, пропускаем текущую итерацию&lt;br /&gt;
            if ($diff &amp;lt; 0 || $diff &amp;gt;= 10 * 60 || $diff2 &amp;lt;= 10 * 60) {&lt;br /&gt;
                continue;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Проверяем доступ к точке планировщика&lt;br /&gt;
            if (!checkAccess('spoint', $rec['ID'])) continue;&lt;br /&gt;
&lt;br /&gt;
            // Получаем связанный объект&lt;br /&gt;
            $linked_object = $rec['LINKED_OBJECT'];&lt;br /&gt;
            // Удаляем связанный объект из записи&lt;br /&gt;
            unset($rec['LINKED_OBJECT']);&lt;br /&gt;
            // Обновляем время последнего запуска&lt;br /&gt;
            $rec['LATEST_RUN'] = date('Y-m-d H:i:s');&lt;br /&gt;
            // Обновляем запись в базе данных&lt;br /&gt;
            SQLUpdate('devices_scheduler_points', $rec);&lt;br /&gt;
            // Записываем сообщение о запуске точки планировщика&lt;br /&gt;
            DebMes(&amp;quot;Running point: &amp;quot; . $linked_object . '.' . $rec['LINKED_METHOD'] . ' (' . $rec['VALUE'] . ')', 'devices_schedule');&lt;br /&gt;
            // Если значение установлено, вызываем метод с этим значением&lt;br /&gt;
            if ($rec['VALUE'] != '') {&lt;br /&gt;
                callMethodSafe($linked_object . '.' . $rec['LINKED_METHOD'], array('value' =&amp;gt; $rec['VALUE']));&lt;br /&gt;
            } else {&lt;br /&gt;
                // Если значение не установлено, вызываем метод без параметров&lt;br /&gt;
                callMethodSafe($linked_object . '.' . $rec['LINKED_METHOD']);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * computePermutations&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция вычисляет все возможные перестановки элементов массива.&lt;br /&gt;
 * Она использует рекурсивный подход для генерации всех возможных комбинаций.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array computePermutations($array)&lt;br /&gt;
 * @param array $array Массив для перестановок&lt;br /&gt;
 * @return array Все возможные перестановки элементов массива&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function computePermutations($array)&lt;br /&gt;
{&lt;br /&gt;
    $result = [];&lt;br /&gt;
    $recurse = function ($array, $start_i = 0) use (&amp;amp;$result, &amp;amp;$recurse) {&lt;br /&gt;
        // Если индекс начала равен индексу последнего элемента массива, добавляем текущую перестановку в результат&lt;br /&gt;
        if ($start_i === count($array) - 1) {&lt;br /&gt;
            array_push($result, $array);&lt;br /&gt;
        }&lt;br /&gt;
        // Проходимся по всем элементам массива, начиная с указанного индекса&lt;br /&gt;
        for ($i = $start_i; $i &amp;lt; count($array); $i++) {&lt;br /&gt;
            // Меняем местами элементы массива по индексам $i и $start_i&lt;br /&gt;
            $t = $array[$i];&lt;br /&gt;
            $array[$i] = $array[$start_i];&lt;br /&gt;
            $array[$start_i] = $t;&lt;br /&gt;
            // Рекурсивно вызываем функцию для следующего индекса&lt;br /&gt;
            $recurse($array, $start_i + 1);&lt;br /&gt;
            // Восстанавливаем исходный порядок элементов массива&lt;br /&gt;
            $t = $array[$i];&lt;br /&gt;
            $array[$i] = $array[$start_i];&lt;br /&gt;
            $array[$start_i] = $t;&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
    // Вызываем рекурсивную функцию для начального массива&lt;br /&gt;
    $recurse($array);&lt;br /&gt;
    // Возвращаем результат, содержащий все возможные перестановки&lt;br /&gt;
    return $result;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * generate_combinations&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция генерирует все возможные комбинации среди набора вложенных массивов.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array generate_combinations(array $data, array &amp;amp;$all = array(), array $group = array(), $value = null, $i = 0)&lt;br /&gt;
 * @param array $data Входной массив-контейнер.&lt;br /&gt;
 * @param array $all Конечный контейнер (используется внутри функции).&lt;br /&gt;
 * @param array $group Подконтейнер (используется внутри функции).&lt;br /&gt;
 * @param mixed $val Значение для добавления (используется внутри функции).&lt;br /&gt;
 * @param int $i Индекс ключа (используется внутри функции).&lt;br /&gt;
 * @return array Все возможные комбинации среди набора вложенных массивов.&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function generate_combinations(array $data, array &amp;amp;$all = array(), array $group = array(), $value = null, $i = 0, $key = null)&lt;br /&gt;
{&lt;br /&gt;
    $keys = array_keys($data);&lt;br /&gt;
    // Если значение установлено, добавляем его в подконтейнер&lt;br /&gt;
    if (isset($value) === true) {&lt;br /&gt;
        $group[$key] = $value;&lt;br /&gt;
    }&lt;br /&gt;
    // Если индекс больше или равен количеству элементов в данных, добавляем подконтейнер в конечный контейнер&lt;br /&gt;
    if ($i &amp;gt;= count($data)) {&lt;br /&gt;
        array_push($all, $group);&lt;br /&gt;
    } else {&lt;br /&gt;
        $currentKey = $keys[$i];&lt;br /&gt;
        $currentElement = $data[$currentKey];&lt;br /&gt;
        // Если в текущем элементе данных нет элементов, рекурсивно вызываем функцию для следующего индекса&lt;br /&gt;
        if (count($data[$currentKey]) &amp;lt;= 0) {&lt;br /&gt;
            $this-&amp;gt;generate_combinations($data, $all, $group, null, $i + 1, $currentKey);&lt;br /&gt;
        } elseif (is_array($currentElement)) {&lt;br /&gt;
            // Если текущий элемент является массивом, проходимся по всем его элементам и рекурсивно вызываем функцию для каждого из них&lt;br /&gt;
            foreach ($currentElement as $val) {&lt;br /&gt;
                $this-&amp;gt;generate_combinations($data, $all, $group, $val, $i + 1, $currentKey);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Возвращаем конечный контейнер с всеми сгенерированными комбинациями&lt;br /&gt;
    return $all;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * homebridgeSync&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция синхронизирует устройства с HomeBridge.&lt;br /&gt;
 * Она проверяет доступность HomeBridge и, если доступна, включает файл для синхронизации.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void homebridgeSync($device_id = 0, $force_refresh = 0)&lt;br /&gt;
 * @param int $device_id Идентификатор устройства (по умолчанию 0).&lt;br /&gt;
 * @param int $force_refresh Принудительное обновление (по умолчанию 0).&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function homebridgeSync($device_id = 0, $force_refresh = 0)&lt;br /&gt;
{&lt;br /&gt;
    // Проверяем доступность HomeBridge&lt;br /&gt;
    if ($this-&amp;gt;isHomeBridgeAvailable()) {&lt;br /&gt;
        // Включаем файл для синхронизации с HomeBridge&lt;br /&gt;
        include_once(dirname(__FILE__) . '/homebridgeSync.inc.php');&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * admin&lt;br /&gt;
 *&lt;br /&gt;
 * Функция обрабатывает административный интерфейс модуля.&lt;br /&gt;
 * Она обрабатывает различные действия, такие как синхронизация с HomeBridge, поиск устройств, управление группами,&lt;br /&gt;
 * управление расписанием, редактирование устройств, быстрое редактирование,&lt;br /&gt;
 * рендеринг структуры и удаление устройств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void admin(&amp;amp;$out)&lt;br /&gt;
 * @param array $out Массив для вывода данных&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function admin(&amp;amp;$out)&lt;br /&gt;
{&lt;br /&gt;
    // Проверяем, установлен ли источник данных и не переданы ли параметры GET или POST&lt;br /&gt;
    if (isset($this-&amp;gt;data_source) &amp;amp;&amp;amp; !$_GET['data_source'] &amp;amp;&amp;amp; !$_POST['data_source']) {&lt;br /&gt;
        $out['SET_DATASOURCE'] = 1;&lt;br /&gt;
    }&lt;br /&gt;
    // Если источник данных равен 'devices' или пустой строке&lt;br /&gt;
    if ($this-&amp;gt;data_source == 'devices' || $this-&amp;gt;data_source == '') {&lt;br /&gt;
&lt;br /&gt;
        // Если режим равен 'homebridgesync', вызываем функцию синхронизации с HomeBridge и перенаправляем на главную страницу&lt;br /&gt;
        if ($this-&amp;gt;mode == 'homebridgesync') {&lt;br /&gt;
            $this-&amp;gt;homebridgeSync();&lt;br /&gt;
            $this-&amp;gt;redirect(&amp;quot;?&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Если режим просмотра пустой или равен 'search_devices', вызываем функцию поиска устройств&lt;br /&gt;
        if ($this-&amp;gt;view_mode == '' || $this-&amp;gt;view_mode == 'search_devices') {&lt;br /&gt;
            $this-&amp;gt;search_devices($out);&lt;br /&gt;
            // Если доступна HomeBridge, устанавливаем флаг ENABLE_HOMEBRIDGE&lt;br /&gt;
            if ($this-&amp;gt;isHomeBridgeAvailable()) {&lt;br /&gt;
                $out['ENABLE_HOMEBRIDGE'] = 1;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Если режим просмотра равен 'manage_groups', вызываем функцию управления группами&lt;br /&gt;
        if ($this-&amp;gt;view_mode == 'manage_groups') {&lt;br /&gt;
            $this-&amp;gt;manage_groups($out);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Если режим просмотра равен 'schedule', вызываем функцию управления расписанием&lt;br /&gt;
        if ($this-&amp;gt;view_mode == 'schedule') {&lt;br /&gt;
            $this-&amp;gt;manage_schedule($out);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Если режим просмотра равен 'edit_devices', вызываем функцию редактирования устройств&lt;br /&gt;
        if ($this-&amp;gt;view_mode == 'edit_devices') {&lt;br /&gt;
            $this-&amp;gt;edit_devices($out, $this-&amp;gt;id);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Если режим просмотра равен 'quick_edit', вызываем функцию быстрого редактирования&lt;br /&gt;
        if ($this-&amp;gt;view_mode == 'quick_edit') {&lt;br /&gt;
            $this-&amp;gt;quick_edit($out);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Если режим просмотра равен 'render_structure', вызываем функцию рендеринга структуры&lt;br /&gt;
        if ($this-&amp;gt;view_mode == 'render_structure') {&lt;br /&gt;
            $this-&amp;gt;renderStructure();&lt;br /&gt;
            $this-&amp;gt;redirect(&amp;quot;?&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Если режим просмотра равен 'delete_devices', вызываем функцию удаления устройств&lt;br /&gt;
        if ($this-&amp;gt;view_mode == 'delete_devices') {&lt;br /&gt;
            $this-&amp;gt;delete_devices($this-&amp;gt;id);&lt;br /&gt;
            $this-&amp;gt;redirect(&amp;quot;?type=&amp;quot; . gr('type') . '&amp;amp;location_id=' . gr('location_id') . '&amp;amp;group_name=' . gr('group_name'));&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * isHomeBridgeAvailable&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция проверяет доступность HomeBridge.&lt;br /&gt;
 * Она выполняет запрос к базе данных, чтобы найти объект с названием 'HomeBridge'.&lt;br /&gt;
 * Если такой объект существует, функция возвращает true, иначе false.&lt;br /&gt;
 *&lt;br /&gt;
 * @method bool isHomeBridgeAvailable()&lt;br /&gt;
 * @return bool true если HomeBridge доступна, иначе false&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function isHomeBridgeAvailable()&lt;br /&gt;
{&lt;br /&gt;
    //return true; // temporary&lt;br /&gt;
    // Выполняем запрос к базе данных, чтобы найти объект с названием 'HomeBridge'&lt;br /&gt;
    $tmp = SQLSelectOne(&amp;quot;SELECT ID FROM objects WHERE TITLE='HomeBridge'&amp;quot;);&lt;br /&gt;
    // Если объект найден, возвращаем true&lt;br /&gt;
    if (isset($tmp['ID'])) {&lt;br /&gt;
        return true;&lt;br /&gt;
    } else {&lt;br /&gt;
        // Если объект не найден, возвращаем false&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * manage_groups&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция управляет группами устройств.&lt;br /&gt;
 * Она включает файл для управления группами устройств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void manage_groups(&amp;amp;$out)&lt;br /&gt;
 * @param array $out Массив для вывода данных&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function manage_groups(&amp;amp;$out)&lt;br /&gt;
{&lt;br /&gt;
    // Включаем файл для управления группами устройств&lt;br /&gt;
    require(dirname(__FILE__) . '/devices_manage_groups.inc.php');&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * manage_schedule&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция управляет расписанием устройств.&lt;br /&gt;
 * Она включает файл для управления расписанием устройств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void manage_schedule(&amp;amp;$out)&lt;br /&gt;
 * @param array $out Массив для вывода данных&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function manage_schedule(&amp;amp;$out)&lt;br /&gt;
{&lt;br /&gt;
    // Включаем файл для управления расписанием устройств&lt;br /&gt;
    require(dirname(__FILE__) . '/devices_manage_schedule.inc.php');&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * usual&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция отвечает за обычный режим работы модуля.&lt;br /&gt;
 * Она обрабатывает различные действия, такие как поиск устройств, управление группами,&lt;br /&gt;
 * управление расписанием, редактирование устройств, быстрое редактирование,&lt;br /&gt;
 * удаление устройств и рендеринг структуры.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void usual(&amp;amp;$out)&lt;br /&gt;
 * @param array $out Массив для вывода данных&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function usual(&amp;amp;$out)&lt;br /&gt;
{&lt;br /&gt;
    // Получаем значение параметра 'view' из запроса&lt;br /&gt;
    $view = gr('view');&lt;br /&gt;
    // Если значение параметра 'view' установлено, присваиваем его свойству класса&lt;br /&gt;
    if ($view) $this-&amp;gt;view = $view;&lt;br /&gt;
&lt;br /&gt;
    // Проверяем, является ли текущий запрос AJAX-запросом&lt;br /&gt;
    if ($this-&amp;gt;ajax) {&lt;br /&gt;
        // Устанавливаем заголовки ответа&lt;br /&gt;
        header(&amp;quot;HTTP/1.0: 200 OK\n&amp;quot;);&lt;br /&gt;
        header('Content-Type: text/html; charset=utf-8');&lt;br /&gt;
        // Получаем значение параметра 'op' из запроса&lt;br /&gt;
        $op = gr('op');&lt;br /&gt;
        // Инициализируем массив для хранения результатов&lt;br /&gt;
        $res = array();&lt;br /&gt;
        // Если значение параметра 'op' равно 'clicked'&lt;br /&gt;
        if ($op == 'clicked') {&lt;br /&gt;
            // Получаем значение параметра 'object' из запроса&lt;br /&gt;
            $object = gr('object');&lt;br /&gt;
            // Если значение параметра 'object' не пустое&lt;br /&gt;
            if ($object != '') {&lt;br /&gt;
                // Выполняем запрос к базе данных, чтобы найти устройство с соответствующим связанным объектом&lt;br /&gt;
                $device_rec = SQLSelectOne(&amp;quot;SELECT ID, TITLE FROM devices WHERE LINKED_OBJECT='&amp;quot; . DBSafe($object) . &amp;quot;'&amp;quot;);&lt;br /&gt;
                // Если устройство найдено&lt;br /&gt;
                if ($device_rec['ID']) {&lt;br /&gt;
                    // Обновляем время последнего клика по устройству в базе данных&lt;br /&gt;
                    SQLExec(&amp;quot;UPDATE devices SET CLICKED=NOW() WHERE ID='&amp;quot; . $device_rec['ID'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
                    // Записываем действие в журнал&lt;br /&gt;
                    logAction('device_clicked', $device_rec['TITLE']);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    // Если значение параметра 'op' равно 'get_device'&lt;br /&gt;
    if ($op == 'get_device') {&lt;br /&gt;
        // Получаем значение параметра 'id' из запроса&lt;br /&gt;
        $id = gr('id');&lt;br /&gt;
        // Обрабатываем устройство с указанным идентификатором и сохраняем результат в массив результатов&lt;br /&gt;
        $res = $this-&amp;gt;processDevice($id, $view);&lt;br /&gt;
    }&lt;br /&gt;
    // Если значение параметра 'op' равно 'get_devices'&lt;br /&gt;
    if ($op == 'get_devices') {&lt;br /&gt;
        // Получаем значение параметра 'ids' из запроса&lt;br /&gt;
        $ids = gr('ids');&lt;br /&gt;
        // Разделяем строку идентификаторов на отдельные элементы&lt;br /&gt;
        $tmp = explode(',', $ids);&lt;br /&gt;
        // Инициализируем массив для хранения результатов&lt;br /&gt;
        $res = array();&lt;br /&gt;
        // Проходимся по всем идентификаторам&lt;br /&gt;
        foreach ($tmp as $id) {&lt;br /&gt;
            // Если идентификатор пустой, пропускаем текущую итерацию&lt;br /&gt;
            if (!$id) continue;&lt;br /&gt;
            // Обрабатываем устройство с указанным идентификатором&lt;br /&gt;
            $record = $this-&amp;gt;processDevice($id, $view);&lt;br /&gt;
            // Если устройство не найдено, пропускаем текущую итерацию&lt;br /&gt;
            if (!$record['DEVICE_ID']) continue;&lt;br /&gt;
            // Добавляем обработанное устройство в массив результатов&lt;br /&gt;
            $res['devices'][] = $record;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Если значение параметра 'op' равно 'loadAllDevicesHTML'&lt;br /&gt;
    if ($op == 'loadAllDevicesHTML') {&lt;br /&gt;
        // Выполняем запрос к базе данных, чтобы получить все устройства, которые не являются системными и не архивированы&lt;br /&gt;
        $devices = SQLSelect(&amp;quot;SELECT ID, LINKED_OBJECT FROM devices WHERE SYSTEM_DEVICE=0 AND ARCHIVED=0&amp;quot;);&lt;br /&gt;
        // Получаем общее количество устройств&lt;br /&gt;
        $total = count($devices);&lt;br /&gt;
        // Проходимся по всем устройствам&lt;br /&gt;
        for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
            // Если устройство имеет связанный объект&lt;br /&gt;
            if ($devices[$i]['LINKED_OBJECT']) {&lt;br /&gt;
                // Обрабатываем устройство и сохраняем результат в переменную&lt;br /&gt;
                $processed = $this-&amp;gt;processDevice($devices[$i]['ID'], $view);&lt;br /&gt;
                // Сохраняем HTML-представление устройства в массиве устройств&lt;br /&gt;
                $devices[$i]['HTML'] = $processed['HTML'];&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        // Сохраняем массив устройств в массив результатов&lt;br /&gt;
        $res['DEVICES'] = $devices;&lt;br /&gt;
    }&lt;br /&gt;
    // Выводим результаты в формате JSON и завершаем выполнение скрипта&lt;br /&gt;
    echo json_encode($res);&lt;br /&gt;
    exit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
    // Проверяем, является ли текущее действие родительского объекта 'apps'&lt;br /&gt;
    if ($this-&amp;gt;owner-&amp;gt;action == 'apps') {&lt;br /&gt;
        // Если действие равно 'apps', перенаправляем на страницу модуля устройств&lt;br /&gt;
        //$this-&amp;gt;redirect(ROOTHTML.&amp;quot;module/devices.html&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Получаем значение параметра 'location_id' из запроса&lt;br /&gt;
    $location_id = gr('location_id');&lt;br /&gt;
    // Получаем значение параметра 'type' из запроса&lt;br /&gt;
    $type = gr('type');&lt;br /&gt;
    // Получаем значение параметра 'collection' из запроса&lt;br /&gt;
    $collection = gr('collection');&lt;br /&gt;
&lt;br /&gt;
    // Инициализируем строку запроса&lt;br /&gt;
    $qry = &amp;quot;1&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    // Получаем значение параметра 'linked_object' из запроса&lt;br /&gt;
    $linked_object = gr('linked_object');&lt;br /&gt;
    // Если значение параметра 'linked_object' установлено&lt;br /&gt;
    if ($linked_object) {&lt;br /&gt;
        // Выполняем запрос к базе данных, чтобы найти устройство с соответствующим связанным объектом&lt;br /&gt;
        $device_rec = SQLSelectOne(&amp;quot;SELECT ID FROM devices WHERE LINKED_OBJECT='&amp;quot; . DbSafe($linked_object) . &amp;quot;'&amp;quot;);&lt;br /&gt;
        // Если устройство найдено&lt;br /&gt;
        if ($device_rec['ID']) {&lt;br /&gt;
            // Присваиваем идентификатор устройства свойству класса&lt;br /&gt;
            $this-&amp;gt;id = $device_rec['ID'];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Генерируем уникальный идентификатор для устройства&lt;br /&gt;
    if (isset($this-&amp;gt;id)) {&lt;br /&gt;
    $out['UNIQ'] = uniqid('dev' . $this-&amp;gt;id);&lt;br /&gt;
        // Добавляем условие в строку запроса, чтобы выбрать устройство с указанным идентификатором&lt;br /&gt;
        $qry .= &amp;quot; AND devices.ID=&amp;quot; . (int)$this-&amp;gt;id;&lt;br /&gt;
        // Устанавливаем флаг, что мы работаем с одним устройством&lt;br /&gt;
        $out['SINGLE_DEVICE'] = 1;&lt;br /&gt;
        // Устанавливаем режим просмотра&lt;br /&gt;
        $out['VIEW'] = $this-&amp;gt;view;&lt;br /&gt;
    }&lt;br /&gt;
    // Если установлены параметры 'location_id', 'type' или 'collection'&lt;br /&gt;
    if ($location_id || $type || $collection) {&lt;br /&gt;
        // Инициализируем строку запроса и порядок сортировки&lt;br /&gt;
        $qry = &amp;quot;1 AND SYSTEM_DEVICE=0 AND ARCHIVED=0&amp;quot;;&lt;br /&gt;
        $orderby = 'locations.PRIORITY DESC, LOCATION_ID, TYPE, TITLE';&lt;br /&gt;
        // Если в параметре 'type' содержится идентификатор локации&lt;br /&gt;
        if (preg_match('/loc(\d+)/', $type, $m)) {&lt;br /&gt;
            // Извлекаем идентификатор локации и очищаем параметр 'type'&lt;br /&gt;
            $location_id = $m[1];&lt;br /&gt;
            $type = '';&lt;br /&gt;
        }&lt;br /&gt;
        // Если в параметре 'type' содержится имя коллекции&lt;br /&gt;
        if (preg_match('/col\_(\w+)/', $type, $m)) {&lt;br /&gt;
            // Извлекаем имя коллекции и очищаем параметр 'type'&lt;br /&gt;
            $collection = $m[1];&lt;br /&gt;
            $type = '';&lt;br /&gt;
        }&lt;br /&gt;
        // Если установлен параметр 'location_id'&lt;br /&gt;
        if ($location_id) {&lt;br /&gt;
            // Если 'location_id' не равен 'all'&lt;br /&gt;
            if ($location_id != 'all') {&lt;br /&gt;
                // Добавляем условие в строку запроса, чтобы выбрать устройства с указанным идентификатором локации&lt;br /&gt;
                $qry .= &amp;quot; AND devices.LOCATION_ID=&amp;quot; . (int)$location_id;&lt;br /&gt;
                // Выполняем запрос к базе данных, чтобы получить информацию о локации&lt;br /&gt;
                $location = SQLSelectOne(&amp;quot;SELECT * FROM locations WHERE ID=&amp;quot; . (int)$location_id);&lt;br /&gt;
                // Сохраняем информацию о локации в массиве вывода&lt;br /&gt;
                foreach ($location as $k =&amp;gt; $v) {&lt;br /&gt;
                    $out['LOCATION_' . $k] = $v;&lt;br /&gt;
                }&lt;br /&gt;
                // Сохраняем название локации в массиве вывода&lt;br /&gt;
                $out['TITLE'] = $location['TITLE'];&lt;br /&gt;
            } else {&lt;br /&gt;
                // Если 'location_id' равен 'all', устанавливаем соответствующий флаг в массиве вывода&lt;br /&gt;
                $out['LOCATION_ID'] = 'All';&lt;br /&gt;
                // Добавляем условие в строку запроса, чтобы выбрать все устройства&lt;br /&gt;
                $qry .= &amp;quot; AND 1&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        // Если установлен параметр 'type'&lt;br /&gt;
        if ($type) {&lt;br /&gt;
            // Если 'type' не равен 'all'&lt;br /&gt;
            if ($type != 'all') {&lt;br /&gt;
                // Добавляем условие в строку запроса, чтобы выбрать устройства с указанным типом&lt;br /&gt;
                $qry .= &amp;quot; AND devices.TYPE LIKE '&amp;quot; . DBSafe($type) . &amp;quot;'&amp;quot;;&lt;br /&gt;
                // Сохраняем название типа устройства в массиве вывода&lt;br /&gt;
                $out['TITLE'] = $this-&amp;gt;device_types[$type]['TITLE'];&lt;br /&gt;
            } else {&lt;br /&gt;
                // Если 'type' равен 'all', изменяем порядок сортировки&lt;br /&gt;
                $orderby = 'TYPE, locations.PRIORITY DESC, locations.TITLE, LOCATION_ID, TITLE';&lt;br /&gt;
            }&lt;br /&gt;
            // Сохраняем тип устройства в массиве вывода&lt;br /&gt;
            $out['TYPE'] = $type;&lt;br /&gt;
        }&lt;br /&gt;
        // Если установлена коллекция&lt;br /&gt;
        if ($collection != '') {&lt;br /&gt;
            // Получаем идентификаторы устройств, входящих в коллекцию&lt;br /&gt;
            $ids = $this-&amp;gt;getCollectionIds($collection);&lt;br /&gt;
            // Добавляем условие в строку запроса, чтобы выбрать устройства с указанными идентификаторами&lt;br /&gt;
            $qry .= &amp;quot; AND devices.ID IN (&amp;quot; . implode(',', $ids) . &amp;quot;)&amp;quot;;&lt;br /&gt;
            // Сохраняем название коллекции в массиве вывода&lt;br /&gt;
            $out['TITLE'] = constant('LANG_DEVICES_COLLECTION_' . strtoupper($collection));&lt;br /&gt;
            // Сохраняем имя коллекции в массиве вывода&lt;br /&gt;
            $out['COLLECTION'] = $collection;&lt;br /&gt;
        }&lt;br /&gt;
        // Инициализируем переменные для хранения названий локации и типа устройства&lt;br /&gt;
        $location_title = '';&lt;br /&gt;
        $type_title = '';&lt;br /&gt;
        // Выполняем запрос к базе данных, чтобы получить устройства, соответствующие условиям запроса&lt;br /&gt;
        $devices = SQLSelect(&amp;quot;SELECT devices.*, locations.TITLE as LOCATION_TITLE FROM devices LEFT JOIN locations ON devices.LOCATION_ID=locations.ID WHERE $qry ORDER BY $orderby&amp;quot;);&lt;br /&gt;
        // Получаем общее количество устройств&lt;br /&gt;
        $total = count($devices);&lt;br /&gt;
        // Проходимся по всем устройствам&lt;br /&gt;
        for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
            // Если тип устройства равен 'all'&lt;br /&gt;
            if ($type == 'all') {&lt;br /&gt;
                // Получаем название типа устройства&lt;br /&gt;
                $devices[$i]['LOCATION_TITLE'] = $this-&amp;gt;device_types[$devices[$i]['TYPE']]['TITLE'];&lt;br /&gt;
                // Если название типа устройства отличается от предыдущего&lt;br /&gt;
                if ($devices[$i]['LOCATION_TITLE'] != $location_title) {&lt;br /&gt;
                    // Устанавливаем флаг, что это новая локация&lt;br /&gt;
                    $devices[$i]['NEW_LOCATION'] = 1;&lt;br /&gt;
                    // Сохраняем текущее название типа устройства&lt;br /&gt;
                    $location_title = $devices[$i]['LOCATION_TITLE'];&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                // Если название типа устройства отличается от предыдущего и не установлено название локации в массиве вывода&lt;br /&gt;
                if ($devices[$i]['LOCATION_TITLE'] != $location_title &amp;amp;&amp;amp; !isset($out['LOCATION_TITLE'])) {&lt;br /&gt;
                    // Устанавливаем флаг, что это новая локация&lt;br /&gt;
                    $devices[$i]['NEW_LOCATION'] = 1;&lt;br /&gt;
                    // Сохраняем текущее название типа устройства&lt;br /&gt;
                    $location_title = $devices[$i]['LOCATION_TITLE'];&lt;br /&gt;
                }&lt;br /&gt;
        // Если название типа устройства отличается от предыдущего&lt;br /&gt;
        if ($this-&amp;gt;device_types[$devices[$i]['TYPE']]['TITLE'] != $type_title) {&lt;br /&gt;
            // Сохраняем текущее название типа устройства&lt;br /&gt;
            $type_title = $this-&amp;gt;device_types[$devices[$i]['TYPE']]['TITLE'];&lt;br /&gt;
            // Устанавливаем флаг, что это новый тип устройства&lt;br /&gt;
            $devices[$i]['NEW_TYPE'] = 1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
} else {&lt;br /&gt;
        // Устанавливаем порядок сортировки&lt;br /&gt;
        $orderby = 'locations.PRIORITY DESC, locations.TITLE, LOCATION_ID, TYPE, TITLE';&lt;br /&gt;
        // Добавляем условие в строку запроса, чтобы выбрать все устройства, которые не являются системными и не архивированы&lt;br /&gt;
        $qry .= &amp;quot; AND SYSTEM_DEVICE=0 AND ARCHIVED=0&amp;quot;;&lt;br /&gt;
        // Устанавливаем флаг, что мы работаем со всеми устройствами&lt;br /&gt;
        $out['ALL_DEVICES'] = 1;&lt;br /&gt;
        // Выполняем запрос к базе данных, чтобы получить все устройства, которые не являются системными и не архивированы&lt;br /&gt;
        $devices = SQLSelect(&amp;quot;SELECT devices.*, locations.TITLE as LOCATION_TITLE FROM devices LEFT JOIN locations ON devices.LOCATION_ID=locations.ID WHERE $qry ORDER BY $orderby&amp;quot;);&lt;br /&gt;
        // Выполняем запрос к базе данных, чтобы получить недавно использованные устройства&lt;br /&gt;
        $recent_devices = SQLSelect(&amp;quot;SELECT devices.* FROM devices WHERE !IsNull(CLICKED) ORDER BY CLICKED DESC LIMIT 10&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если устройства найдены&lt;br /&gt;
    if ($devices[0]['ID']) {&lt;br /&gt;
        // Если установлены параметры 'location_id', 'type' или 'collection'&lt;br /&gt;
        if ($location_id || $type || 1) {&lt;br /&gt;
            // Получаем общее количество устройств&lt;br /&gt;
            $total = count($devices);&lt;br /&gt;
            // Проходимся по всем устройствам&lt;br /&gt;
            for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
                // Если устройство имеет связанный объект&lt;br /&gt;
                if ($devices[$i]['LINKED_OBJECT']) {&lt;br /&gt;
                    // Обрабатываем устройство и сохраняем результат в переменную&lt;br /&gt;
                    $processed = $this-&amp;gt;processDevice($devices[$i]['ID'], $this-&amp;gt;view);&lt;br /&gt;
                    // Сохраняем HTML-представление устройства в массиве устройств&lt;br /&gt;
                    $devices[$i]['HTML'] = $processed['HTML'];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        // Сохраняем массив устройств в массиве вывода&lt;br /&gt;
        $out['DEVICES'] = $devices;&lt;br /&gt;
        // Если свойство класса 'id' установлено&lt;br /&gt;
        if ($this-&amp;gt;id) {&lt;br /&gt;
            // Завершаем выполнение функции&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Выполняем запрос к базе данных, чтобы получить все локации, упорядоченные по приоритету и названию&lt;br /&gt;
    $locations = SQLSelect(&amp;quot;SELECT ID, TITLE FROM locations ORDER BY PRIORITY DESC, TITLE&amp;quot;);&lt;br /&gt;
    // Получаем общее количество устройств&lt;br /&gt;
    $total_devices = count($devices);&lt;br /&gt;
    // Если устройства найдены&lt;br /&gt;
    if ($total_devices) {&lt;br /&gt;
        // Инициализируем массивы для хранения избранных, предупреждающих и проблемных устройств&lt;br /&gt;
        $favorite_devices = array();&lt;br /&gt;
        $warning_devices = array();&lt;br /&gt;
        $problem_devices = array();&lt;br /&gt;
        // Проходимся по всем устройствам&lt;br /&gt;
        for ($idv = 0; $idv &amp;lt; $total_devices; $idv++) {&lt;br /&gt;
            // Если устройство помечено как избранное&lt;br /&gt;
            if ($devices[$idv]['FAVORITE']) {&lt;br /&gt;
                // Добавляем устройство в массив избранных устройств&lt;br /&gt;
                $favorite_devices[] = $devices[$idv];&lt;br /&gt;
            } elseif ($devices[$idv]['LINKED_OBJECT']) {&lt;br /&gt;
                // Если устройство имеет связанный объект&lt;br /&gt;
&lt;br /&gt;
                // Проверяем, является ли устройство предупреждающим&lt;br /&gt;
                if (&lt;br /&gt;
                    gg($devices[$idv]['LINKED_OBJECT'] . '.normalValue') == '0' &amp;amp;&amp;amp;&lt;br /&gt;
                    gg($devices[$idv]['LINKED_OBJECT'] . '.notify') == '1'&lt;br /&gt;
                ) {&lt;br /&gt;
                    // Добавляем устройство в массив предупреждающих устройств&lt;br /&gt;
                    $warning_devices[] = $devices[$idv];&lt;br /&gt;
                    // Устанавливаем флаг, что это новая секция&lt;br /&gt;
                    $warning_devices[0]['NEW_SECTION'] = 1;&lt;br /&gt;
                    // Устанавливаем название секции&lt;br /&gt;
                    $warning_devices[0]['SECTION_TITLE'] = LANG_WARNING;&lt;br /&gt;
                } elseif (&lt;br /&gt;
                    // Проверяем, является ли устройство проблемным&lt;br /&gt;
                    ($devices[$idv]['TYPE'] == 'motion' ||&lt;br /&gt;
                        $devices[$idv]['TYPE'] == 'openclose' ||&lt;br /&gt;
                        $devices[$idv]['TYPE'] == 'leak' ||&lt;br /&gt;
                        $devices[$idv]['TYPE'] == 'smoke' ||&lt;br /&gt;
                        $devices[$idv]['TYPE'] == 'counter' ||&lt;br /&gt;
                        preg_match('/^sensor/', $devices[$idv]['TYPE']) ||&lt;br /&gt;
                        $this-&amp;gt;device_types[$devices[$idv]['TYPE']]['PARENT_CLASS'] == 'SSensors' ||&lt;br /&gt;
                        (int)gg($devices[$idv]['LINKED_OBJECT'] . '.aliveTimeout') &amp;gt; 0&lt;br /&gt;
                    ) &amp;amp;&amp;amp; gg($devices[$idv]['LINKED_OBJECT'] . '.alive') === '0'&lt;br /&gt;
                ) {&lt;br /&gt;
                    // Добавляем устройство в массив проблемных устройств&lt;br /&gt;
                    $problem_devices[] = $devices[$idv];&lt;br /&gt;
                    // Устанавливаем флаг, что это новая секция&lt;br /&gt;
                    $problem_devices[0]['NEW_SECTION'] = 1;&lt;br /&gt;
                    // Устанавливаем название секции&lt;br /&gt;
                    $problem_devices[0]['SECTION_TITLE'] = LANG_OFFLINE;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    // Если в массиве избранных устройств есть элементы&lt;br /&gt;
    if (count($favorite_devices) &amp;gt; 0) {&lt;br /&gt;
        // Сортируем массив избранных устройств по значению 'FAVORITE'&lt;br /&gt;
        usort($favorite_devices, function ($a, $b) {&lt;br /&gt;
            if ($a['FAVORITE'] == $b['FAVORITE']) {&lt;br /&gt;
                return 0;&lt;br /&gt;
            }&lt;br /&gt;
            return ($a['FAVORITE'] &amp;gt; $b['FAVORITE']) ? -1 : 1;&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Добавляем предупреждающие устройства в массив избранных устройств&lt;br /&gt;
    foreach ($warning_devices as $device) {&lt;br /&gt;
        $favorite_devices[] = $device;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если в массиве недавно использованных устройств есть элементы&lt;br /&gt;
    if (isset($recent_devices[0]['ID'])) {&lt;br /&gt;
        // Устанавливаем флаг, что это новая секция&lt;br /&gt;
        $recent_devices[0]['NEW_SECTION'] = 1;&lt;br /&gt;
        // Устанавливаем название секции&lt;br /&gt;
        $recent_devices[0]['SECTION_TITLE'] = LANG_RECENTLY_USED;&lt;br /&gt;
        // Проходимся по всем недавно использованным устройствам&lt;br /&gt;
        foreach ($recent_devices as &amp;amp;$device) {&lt;br /&gt;
            // Если устройство имеет связанный объект&lt;br /&gt;
            if ($device['LINKED_OBJECT']) {&lt;br /&gt;
                // Обрабатываем устройство и сохраняем результат в переменную&lt;br /&gt;
                $processed = $this-&amp;gt;processDevice($device['ID']);&lt;br /&gt;
                // Сохраняем HTML-представление устройства в массиве устройств&lt;br /&gt;
                $device['HTML'] = $processed['HTML'];&lt;br /&gt;
            }&lt;br /&gt;
            // Добавляем устройство в массив избранных устройств&lt;br /&gt;
            $favorite_devices[] = $device;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Добавляем проблемные устройства в массив избранных устройств&lt;br /&gt;
    foreach ($problem_devices as $device) {&lt;br /&gt;
        $favorite_devices[] = $device;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Получаем общее количество устройств в массиве избранных устройств&lt;br /&gt;
    $devices_count = count($favorite_devices);&lt;br /&gt;
&lt;br /&gt;
    // Если в массиве избранных устройств есть элементы&lt;br /&gt;
    if ($devices_count &amp;gt; 0) {&lt;br /&gt;
        // Создаем запись для секции избранных устройств&lt;br /&gt;
        $loc_rec = array();&lt;br /&gt;
        $loc_rec['ID'] = 0;&lt;br /&gt;
        $loc_rec['TITLE'] = LANG_FAVORITES;&lt;br /&gt;
        $loc_rec['DEVICES'] = $favorite_devices;&lt;br /&gt;
        $loc_rec['DEVICES_TOTAL'] = $devices_count;&lt;br /&gt;
        // Добавляем запись в начало массива локаций&lt;br /&gt;
        array_unshift($locations, $loc_rec);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Получаем общее количество локаций&lt;br /&gt;
    $total = count($locations);&lt;br /&gt;
    // Проходимся по всем локациям&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        // Если у локации есть идентификатор&lt;br /&gt;
        if ($locations[$i]['ID']) {&lt;br /&gt;
            // Инициализируем счетчик устройств&lt;br /&gt;
            $devices_count = 0;&lt;br /&gt;
            // Если есть устройства&lt;br /&gt;
            if ($total_devices) {&lt;br /&gt;
                // Проходимся по всем устройствам&lt;br /&gt;
                for ($idv = 0; $idv &amp;lt; $total_devices; $idv++) {&lt;br /&gt;
                    // Если идентификатор локации устройства совпадает с идентификатором текущей локации&lt;br /&gt;
                    if ($devices[$idv]['LOCATION_ID'] == $locations[$i]['ID']) {&lt;br /&gt;
                        // Увеличиваем счетчик устройств&lt;br /&gt;
                        $devices_count++;&lt;br /&gt;
                        // Добавляем устройство в массив устройств текущей локации&lt;br /&gt;
                        $locations[$i]['DEVICES'][] = $devices[$idv];&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            // Сохраняем общее количество устройств в массиве локации&lt;br /&gt;
            $locations[$i]['DEVICES_TOTAL'] = $devices_count;&lt;br /&gt;
        }&lt;br /&gt;
        // Устанавливаем индекс текущей локации&lt;br /&gt;
        $locations[$i]['INDEX'] = $i;&lt;br /&gt;
    }&lt;br /&gt;
    // Сохраняем массив локаций в массиве вывода&lt;br /&gt;
    $out['GROUPS'] = $locations;&lt;br /&gt;
&lt;br /&gt;
    // Инициализируем массив для хранения типов устройств&lt;br /&gt;
    $types = array();&lt;br /&gt;
&lt;br /&gt;
    // Если свойство класса 'device_types' является массивом&lt;br /&gt;
    if (is_array($this-&amp;gt;device_types)) {&lt;br /&gt;
        // Проходимся по всем типам устройств&lt;br /&gt;
        foreach ($this-&amp;gt;device_types as $k =&amp;gt; $v) {&lt;br /&gt;
            // Если у типа устройства есть название&lt;br /&gt;
            if (isset($v['TITLE'])) {&lt;br /&gt;
                // Создаем запись для типа устройства&lt;br /&gt;
                $type_rec = array('NAME' =&amp;gt; $k, 'TITLE' =&amp;gt; $v['TITLE']);&lt;br /&gt;
                // Выполняем запрос к базе данных, чтобы получить количество устройств данного типа&lt;br /&gt;
                $tmp = SQLSelectOne(&amp;quot;SELECT COUNT(*) AS TOTAL FROM devices WHERE SYSTEM_DEVICE=0 AND ARCHIVED=0 AND TYPE='&amp;quot; . $k . &amp;quot;'&amp;quot;);&lt;br /&gt;
                // Сохраняем количество устройств в записи&lt;br /&gt;
                $type_rec['TOTAL'] = (int)$tmp['TOTAL'];&lt;br /&gt;
                // Если количество устройств больше нуля&lt;br /&gt;
                if ($type_rec['TOTAL'] &amp;gt; 0) {&lt;br /&gt;
                    // Добавляем запись в массив типов устройств&lt;br /&gt;
                    $types[] = $type_rec;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        // Сортируем массив типов устройств по названию&lt;br /&gt;
        usort($types, function ($a, $b) {&lt;br /&gt;
            return strcmp($a[&amp;quot;TITLE&amp;quot;], $b[&amp;quot;TITLE&amp;quot;]);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Обрабатываем коллекции устройств&lt;br /&gt;
    $col_name = 'is_heating';&lt;br /&gt;
    $col_ids = $this-&amp;gt;getCollectionIds($col_name);&lt;br /&gt;
    $col_total = count($col_ids) - 1;&lt;br /&gt;
    $col = array('NAME' =&amp;gt; 'col_' . $col_name, 'TITLE' =&amp;gt; LANG_DEVICES_COLLECTION_IS_HEATING, 'TOTAL' =&amp;gt; $col_total);&lt;br /&gt;
    if ($col_total &amp;gt; 0) array_unshift($types, $col);&lt;br /&gt;
&lt;br /&gt;
    $col_name = 'is_on';&lt;br /&gt;
    $col_ids = $this-&amp;gt;getCollectionIds($col_name);&lt;br /&gt;
    $col_total = count($col_ids) - 1;&lt;br /&gt;
    $col = array('NAME' =&amp;gt; 'col_' . $col_name, 'TITLE' =&amp;gt; LANG_DEVICES_COLLECTION_IS_ON, 'TOTAL' =&amp;gt; $col_total);&lt;br /&gt;
    if ($col_total &amp;gt; 0) array_unshift($types, $col);&lt;br /&gt;
&lt;br /&gt;
    $col_name = 'is_open';&lt;br /&gt;
    $col_ids = $this-&amp;gt;getCollectionIds($col_name);&lt;br /&gt;
    $col_total = count($col_ids) - 1;&lt;br /&gt;
    $col = array('NAME' =&amp;gt; 'col_' . $col_name, 'TITLE' =&amp;gt; LANG_DEVICES_COLLECTION_IS_OPEN, 'TOTAL' =&amp;gt; $col_total);&lt;br /&gt;
    if ($col_total &amp;gt; 0) array_unshift($types, $col);&lt;br /&gt;
&lt;br /&gt;
    // Обрабатываем локации&lt;br /&gt;
    $list_locations = $locations;&lt;br /&gt;
    if (is_array($list_locations)) {&lt;br /&gt;
        // Сортируем массив локаций по названию&lt;br /&gt;
        usort($list_locations, function ($a, $b) {&lt;br /&gt;
            return strcmp($a[&amp;quot;TITLE&amp;quot;], $b[&amp;quot;TITLE&amp;quot;]);&lt;br /&gt;
        });&lt;br /&gt;
        // Добавляем запись для локаций в массив типов устройств&lt;br /&gt;
        $types[] = array('NAME' =&amp;gt; '', 'TITLE' =&amp;gt; LANG_LOCATION);&lt;br /&gt;
        // Проходимся по всем локациям&lt;br /&gt;
        foreach ($list_locations as $location) {&lt;br /&gt;
            // Если название локации не равно 'Избранное'&lt;br /&gt;
            if ($location['TITLE'] == LANG_FAVORITES) continue;&lt;br /&gt;
            // Добавляем запись для локации в массив типов устройств&lt;br /&gt;
            $types[] = array('NAME' =&amp;gt; 'loc' . $location['ID'], 'TITLE' =&amp;gt; $location['TITLE'], 'TOTAL' =&amp;gt; $location['DEVICES_TOTAL']);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Сохраняем массив типов устройств в массиве вывода&lt;br /&gt;
    $out['TYPES'] = $types;&lt;br /&gt;
/**&lt;br /&gt;
 * getCollectionIds&lt;br /&gt;
 *&lt;br /&gt;
 * Эта функция возвращает идентификаторы устройств, которые входят в указанную коллекцию.&lt;br /&gt;
 * Она обрабатывает различные коллекции, такие как 'is_on', 'is_open', 'is_heating'.&lt;br /&gt;
 *&lt;br /&gt;
 * @method array getCollectionIds($collection)&lt;br /&gt;
 * @param string $collection Название коллекции&lt;br /&gt;
 * @return array Идентификаторы устройств, которые входят в указанную коллекцию&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function getCollectionIds($collection)&lt;br /&gt;
{&lt;br /&gt;
    $ids = array(0);&lt;br /&gt;
    if ($collection == 'is_on') {&lt;br /&gt;
        // Выполняем запрос к базе данных, чтобы получить устройства типа 'relay', 'dimmer', 'rgb'&lt;br /&gt;
        $devices = SQLSelect(&amp;quot;SELECT ID, LINKED_OBJECT FROM devices WHERE devices.TYPE IN ('relay','dimmer','rgb')&amp;quot;);&lt;br /&gt;
        // Проходимся по всем устройствам&lt;br /&gt;
        foreach ($devices as $device) {&lt;br /&gt;
            // Если статус устройства равен 'on'&lt;br /&gt;
            if (gg($device['LINKED_OBJECT'] . '.status')) {&lt;br /&gt;
                // Добавляем идентификатор устройства в массив идентификаторов&lt;br /&gt;
                $ids[] = $device['ID'];&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    } elseif ($collection == 'is_open') {&lt;br /&gt;
        // Выполняем запрос к базе данных, чтобы получить устройства типа 'openable', 'openclose'&lt;br /&gt;
        $devices = SQLSelect(&amp;quot;SELECT ID, LINKED_OBJECT FROM devices WHERE devices.TYPE IN ('openable','openclose')&amp;quot;);&lt;br /&gt;
        // Проходимся по всем устройствам&lt;br /&gt;
        foreach ($devices as $device) {&lt;br /&gt;
            // Если статус устройства равен 'off'&lt;br /&gt;
            if (!gg($device['LINKED_OBJECT'] . '.status')) {&lt;br /&gt;
                // Добавляем идентификатор устройства в массив идентификаторов&lt;br /&gt;
                $ids[] = $device['ID'];&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    } elseif ($collection == 'is_heating') {&lt;br /&gt;
        // Выполняем запрос к базе данных, чтобы получить устройства типа 'thermostat'&lt;br /&gt;
        $devices = SQLSelect(&amp;quot;SELECT ID, LINKED_OBJECT FROM devices WHERE devices.TYPE IN ('thermostat')&amp;quot;);&lt;br /&gt;
        // Проходимся по всем устройствам&lt;br /&gt;
        foreach ($devices as $device) {&lt;br /&gt;
            // Если статус устройства равен 'on'&lt;br /&gt;
            if (gg($device['LINKED_OBJECT'] . '.relay_status')) {&lt;br /&gt;
                // Добавляем идентификатор устройства в массив идентификаторов&lt;br /&gt;
                $ids[] = $device['ID'];&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // Возвращаем массив идентификаторов устройств&lt;br /&gt;
    return $ids;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * devices search&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для поиска устройств.&lt;br /&gt;
 * Она включает в себя логику поиска, определенную в файле 'devices_search.inc.php'.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void devices_search(&amp;amp;$out)&lt;br /&gt;
 * @param array $out Массив для вывода данных&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function search_devices(&amp;amp;$out)&lt;br /&gt;
{&lt;br /&gt;
    // Включаем файл 'devices_search.inc.php', который содержит логику поиска устройств&lt;br /&gt;
    require(dirname(__FILE__) . '/devices_search.inc.php');&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * devices edit/add&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для редактирования или добавления устройств.&lt;br /&gt;
 * Она включает в себя логику редактирования/добавления,&lt;br /&gt;
 * определенную в файле 'devices_edit.inc.php'.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void edit_devices(&amp;amp;$out, $id)&lt;br /&gt;
 * @param array $out Массив для вывода данных&lt;br /&gt;
 * @param int $id Идентификатор устройства для редактирования (0 для добавления нового устройства)&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function edit_devices(&amp;amp;$out, $id)&lt;br /&gt;
{&lt;br /&gt;
    // Включаем файл 'devices_edit.inc.php', который содержит логику редактирования/добавления устройств&lt;br /&gt;
    require(dirname(__FILE__) . '/devices_edit.inc.php');&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * quick_edit&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для быстрого редактирования устройств.&lt;br /&gt;
 * Она включает в себя логику быстрого редактирования, определенную в файле 'devices_quick_edit.inc.php'.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void quick_edit(&amp;amp;$out)&lt;br /&gt;
 * @param array $out Массив для вывода данных&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function quick_edit(&amp;amp;$out)&lt;br /&gt;
{&lt;br /&gt;
    // Включаем файл 'devices_quick_edit.inc.php', который содержит логику быстрого редактирования устройств&lt;br /&gt;
    require(dirname(__FILE__) . '/devices_quick_edit.inc.php');&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * devices delete record&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для удаления записи об устройстве.&lt;br /&gt;
 * Она также выполняет дополнительные действия, связанные с удалением устройства, такие как удаление связанных элементов, объектов и команд.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void delete_devices($id)&lt;br /&gt;
 * @param int $id Идентификатор устройства для удаления&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function delete_devices($id)&lt;br /&gt;
{&lt;br /&gt;
    // Получаем запись об устройстве по идентификатору&lt;br /&gt;
    $rec = SQLSelectOne(&amp;quot;SELECT * FROM devices WHERE ID='$id'&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Подготовка данных для удаления устройства из HomeBridge&lt;br /&gt;
    $payload = array();&lt;br /&gt;
    $payload['name'] = $rec['LINKED_OBJECT'];&lt;br /&gt;
    sg('HomeBridge.to_remove', json_encode($payload));&lt;br /&gt;
&lt;br /&gt;
    // Удаление связанных элементов&lt;br /&gt;
    $elements = SQLSelect(&amp;quot;SELECT * FROM elements WHERE `SYSTEM`='sdevice&amp;quot; . $rec['ID'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
    $total = count($elements);&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        SQLExec(&amp;quot;DELETE FROM elm_states WHERE ELEMENT_ID=&amp;quot; . $elements[$i]['ID']);&lt;br /&gt;
        SQLExec(&amp;quot;DELETE FROM elements WHERE ID=&amp;quot; . $elements[$i]['ID']);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Удаление связанных объектов&lt;br /&gt;
    $objects = SQLSelect(&amp;quot;SELECT ID FROM objects WHERE `SYSTEM`='sdevice&amp;quot; . $rec['ID'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
    $total = count($objects);&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        deleteObject($objects[$i]['ID']);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Удаление связанных команд&lt;br /&gt;
    $tables = array('commands');&lt;br /&gt;
    $total = count($tables);&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $total; $i++) {&lt;br /&gt;
        SQLExec(&amp;quot;DELETE FROM &amp;quot; . $tables[$i] . &amp;quot; WHERE `SYSTEM`='sdevice&amp;quot; . $rec['ID'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Удаление связей устройств&lt;br /&gt;
    SQLExec(&amp;quot;DELETE FROM devices_linked WHERE DEVICE1_ID='&amp;quot; . $rec['ID'] . &amp;quot;' OR DEVICE2_ID='&amp;quot; . $rec['ID'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Удаление самого устройства&lt;br /&gt;
    SQLExec(&amp;quot;DELETE FROM devices WHERE ID='&amp;quot; . $rec['ID'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * addDevice&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для добавления нового устройства.&lt;br /&gt;
 * Она принимает тип устройства и опции для настройки устройства, такие как связанный объект, название, локация и другие параметры.&lt;br /&gt;
 *&lt;br /&gt;
 * @method int addDevice($device_type, $options = 0)&lt;br /&gt;
 * @param string $device_type Тип устройства&lt;br /&gt;
 * @param array $options Опции для настройки устройства&lt;br /&gt;
 * @return int Идентификатор добавленного устройства или 0 в случае ошибки&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function addDevice($device_type, $options = 0)&lt;br /&gt;
{&lt;br /&gt;
    // Устанавливаем словарь устройств&lt;br /&gt;
    $this-&amp;gt;setDictionary();&lt;br /&gt;
    // Получаем детали типа устройства&lt;br /&gt;
    $type_details = $this-&amp;gt;getTypeDetails($device_type);&lt;br /&gt;
&lt;br /&gt;
    // Если опции не являются массивом, инициализируем их как пустой массив&lt;br /&gt;
    if (!is_array($options)) {&lt;br /&gt;
        $options = array();&lt;br /&gt;
    }&lt;br /&gt;
    // Если тип устройства не определен в словаре устройств, возвращаем 0&lt;br /&gt;
    if (!is_array($this-&amp;gt;device_types[$device_type])) {&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если указаны параметры для связанной таблицы и идентификатор записи в таблице&lt;br /&gt;
    if ($options['TABLE'] &amp;amp;&amp;amp; $options['TABLE_ID']) {&lt;br /&gt;
        // Получаем запись из указанной таблицы&lt;br /&gt;
        $table_rec = SQLSelectOne(&amp;quot;SELECT * FROM &amp;quot; . $options['TABLE'] . &amp;quot; WHERE ID=&amp;quot; . $options['TABLE_ID']);&lt;br /&gt;
        // Если запись не найдена, возвращаем 0&lt;br /&gt;
        if (!$table_rec['ID']) {&lt;br /&gt;
            return 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если указано связанное устройство&lt;br /&gt;
    if ($options['LINKED_OBJECT'] != '') {&lt;br /&gt;
        // Проверяем, существует ли уже устройство с таким связанным объектом&lt;br /&gt;
        $old_device = SQLSelectOne(&amp;quot;SELECT ID FROM devices WHERE LINKED_OBJECT LIKE '&amp;quot; . DBSafe($options['LINKED_OBJECT']) . &amp;quot;'&amp;quot;);&lt;br /&gt;
        // Если устройство найдено, возвращаем его идентификатор&lt;br /&gt;
        if ($old_device['ID']) return $old_device['ID'];&lt;br /&gt;
        // Иначе, сохраняем связанный объект в записи&lt;br /&gt;
        $rec['LINKED_OBJECT'] = $options['LINKED_OBJECT'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Инициализируем запись для нового устройства&lt;br /&gt;
    $rec = array();&lt;br /&gt;
    $rec['TYPE'] = $device_type;&lt;br /&gt;
    // Если указано название, сохраняем его в записи&lt;br /&gt;
    if ($options['TITLE']) {&lt;br /&gt;
        $rec['TITLE'] = $options['TITLE'];&lt;br /&gt;
    } else {&lt;br /&gt;
        // Иначе, устанавливаем название по умолчанию&lt;br /&gt;
        $rec['TITLE'] = 'New device ' . date('H:i');&lt;br /&gt;
    }&lt;br /&gt;
    // Если указана локация, сохраняем ее в записи&lt;br /&gt;
    if ($options['LOCATION_ID']) {&lt;br /&gt;
        $rec['LOCATION_ID'] = $options['LOCATION_ID'];&lt;br /&gt;
    }&lt;br /&gt;
    // Добавляем запись в базу данных и сохраняем идентификатор нового устройства&lt;br /&gt;
    $rec['ID'] = SQLInsert('devices', $rec);&lt;br /&gt;
&lt;br /&gt;
    // Если указана локация, получаем название локации&lt;br /&gt;
    if ($rec['LOCATION_ID']) {&lt;br /&gt;
        $location_title = getRoomObjectByLocation($rec['LOCATION_ID'], 1);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если не указан связанный объект, создаем новый объект для устройства&lt;br /&gt;
    if (!$rec['LINKED_OBJECT']) {&lt;br /&gt;
        $prefix = ucfirst($rec['TYPE']);&lt;br /&gt;
        $new_object_title = $prefix . $this-&amp;gt;getNewObjectIndex($type_details['CLASS']);&lt;br /&gt;
        $object_id = addClassObject($type_details['CLASS'], $new_object_title, 'sdevice' . $rec['ID']);&lt;br /&gt;
        $rec['LINKED_OBJECT'] = $new_object_title;&lt;br /&gt;
        // Если название устройства по умолчанию, обновляем его на название связанного объекта&lt;br /&gt;
        if (preg_match('/New device .+/', $rec['TITLE'])) {&lt;br /&gt;
            $rec['TITLE'] = $rec['LINKED_OBJECT'];&lt;br /&gt;
        }&lt;br /&gt;
        // Обновляем запись в базе данных&lt;br /&gt;
        SQLUpdate('devices', $rec);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если указаны параметры для связанной таблицы и идентификатор записи в таблице&lt;br /&gt;
    if ($table_rec['ID']) {&lt;br /&gt;
        // Добавляем устройство в связанную таблицу&lt;br /&gt;
        $this-&amp;gt;addDeviceToSourceTable($options['TABLE'], $table_rec['ID'], $rec['ID']);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если указано добавление устройства в меню&lt;br /&gt;
    if ($options['ADD_MENU']) {&lt;br /&gt;
        // Добавляем устройство в меню&lt;br /&gt;
        $this-&amp;gt;addDeviceToMenu($rec['ID']);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если указано добавление устройства в сцену&lt;br /&gt;
    if ($options['ADD_SCENE']) {&lt;br /&gt;
        // Добавляем устройство в сцену&lt;br /&gt;
        $this-&amp;gt;addDeviceToScene($rec['ID']);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Возвращаем 1, указывая на успешное добавление устройства&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * addDeviceToSourceTable&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для добавления устройства в связанную таблицу.&lt;br /&gt;
 * Она принимает имя таблицы, идентификатор записи в таблице и идентификатор устройства.&lt;br /&gt;
 * Функция определяет свойства и методы связанного объекта устройства в зависимости от его типа и обновляет запись в таблице.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void addDeviceToSourceTable($table_name, $table_id, $device_id)&lt;br /&gt;
 * @param string $table_name Имя таблицы&lt;br /&gt;
 * @param int $table_id Идентификатор записи в таблице&lt;br /&gt;
 * @param int $device_id Идентификатор устройства&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function addDeviceToSourceTable($table_name, $table_id, $device_id)&lt;br /&gt;
{&lt;br /&gt;
    // Получаем запись об устройстве по идентификатору&lt;br /&gt;
    $rec = SQLSelectOne(&amp;quot;SELECT * FROM devices WHERE ID=&amp;quot; . (int)$device_id);&lt;br /&gt;
    // Устанавливаем словарь устройств&lt;br /&gt;
    $this-&amp;gt;setDictionary();&lt;br /&gt;
    // Получаем детали типа устройства&lt;br /&gt;
    $type_details = $this-&amp;gt;getTypeDetails($rec['TYPE']);&lt;br /&gt;
&lt;br /&gt;
    // Если у устройства нет связанного объекта, возвращаем 0&lt;br /&gt;
    if (!$rec['LINKED_OBJECT']) {&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Получаем запись из указанной таблицы&lt;br /&gt;
    $table_rec = SQLSelectOne(&amp;quot;SELECT * FROM $table_name WHERE ID=&amp;quot; . DBSafe($table_id));&lt;br /&gt;
    // Если запись не найдена, возвращаем 0&lt;br /&gt;
    if (!$table_rec['ID']) {&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Инициализируем переменные для связанного объекта, свойства и метода&lt;br /&gt;
    $linked_object = $rec['LINKED_OBJECT'];&lt;br /&gt;
    $linked_property = '';&lt;br /&gt;
    $linked_method = '';&lt;br /&gt;
&lt;br /&gt;
    // Определяем свойство и метод в зависимости от класса родителя устройства&lt;br /&gt;
    if ($type_details['PARENT_CLASS'] == 'SSensors') {&lt;br /&gt;
        $linked_property = 'value';&lt;br /&gt;
    } elseif ($type_details['PARENT_CLASS'] == 'SControllers') {&lt;br /&gt;
        $linked_property = 'status';&lt;br /&gt;
    }&lt;br /&gt;
    // Определяем свойство в зависимости от типа устройства&lt;br /&gt;
    if ($rec['TYPE'] == 'dimmer') {&lt;br /&gt;
        $linked_property = 'level';&lt;br /&gt;
    }&lt;br /&gt;
    if ($rec['TYPE'] == 'rgb') {&lt;br /&gt;
        $linked_property = 'color';&lt;br /&gt;
    }&lt;br /&gt;
    if ($rec['TYPE'] == 'motion') {&lt;br /&gt;
        $linked_property = 'status';&lt;br /&gt;
        $linked_method = 'motionDetected';&lt;br /&gt;
    }&lt;br /&gt;
    if ($rec['TYPE'] == 'button') {&lt;br /&gt;
        $linked_property = 'status';&lt;br /&gt;
        $linked_method = 'pressed';&lt;br /&gt;
    }&lt;br /&gt;
    if ($rec['TYPE'] == 'switch' || $rec['TYPE'] == 'openclose') {&lt;br /&gt;
        $linked_property = 'status';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если запись найдена, обновляем ее с новыми значениями связанного объекта, свойства и метода&lt;br /&gt;
    if ($table_rec['ID']) {&lt;br /&gt;
        $table_rec['LINKED_OBJECT'] = $linked_object;&lt;br /&gt;
        $table_rec['LINKED_PROPERTY'] = $linked_property;&lt;br /&gt;
        $table_rec['LINKED_METHOD'] = $linked_method;&lt;br /&gt;
        SQLUpdate($table_name, $table_rec);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * addDeviceToMenu&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для добавления устройства в меню.&lt;br /&gt;
 * Она принимает идентификатор устройства и идентификатор родительского элемента меню (необязательно).&lt;br /&gt;
 * Функция определяет тип элемента меню в зависимости от типа устройства и обновляет или создает запись в таблице команд.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void addDeviceToMenu($device_id, $parent_id = 0)&lt;br /&gt;
 * @param int $device_id Идентификатор устройства&lt;br /&gt;
 * @param int $parent_id Идентификатор родительского элемента меню (необязательно)&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function addDeviceToMenu($device_id, $add_menu_id = 0)&lt;br /&gt;
{&lt;br /&gt;
    // Получаем запись об устройстве по идентификатору&lt;br /&gt;
    $rec = SQLSelectOne(&amp;quot;SELECT * FROM devices WHERE ID=&amp;quot; . (int)$device_id);&lt;br /&gt;
    // Если запись не найдена, возвращаем 0&lt;br /&gt;
    if (!$rec['ID']) {&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    // Получаем запись из таблицы команд, связанную с устройством&lt;br /&gt;
    $menu_rec = SQLSelectOne(&amp;quot;SELECT * FROM commands WHERE `SYSTEM`='&amp;quot; . 'sdevice' . $rec['ID'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
    // Если запись не найдена, инициализируем новую запись&lt;br /&gt;
    if (!$menu_rec['ID']) {&lt;br /&gt;
        $menu_rec = array();&lt;br /&gt;
    }&lt;br /&gt;
    // Если заголовок не указан, используем название устройства&lt;br /&gt;
    if (!$menu_rec['TITLE']) {&lt;br /&gt;
        $menu_rec['TITLE'] = $rec['TITLE'];&lt;br /&gt;
    }&lt;br /&gt;
    // Устанавливаем идентификатор родительского элемента меню&lt;br /&gt;
    $menu_rec['PARENT_ID'] = (int)$add_menu_id;&lt;br /&gt;
    // Устанавливаем системный идентификатор&lt;br /&gt;
    $menu_rec['SYSTEM'] = 'sdevice' . $rec['ID'];&lt;br /&gt;
    // Устанавливаем связанный объект&lt;br /&gt;
    $menu_rec['LINKED_OBJECT'] = $rec['LINKED_OBJECT'];&lt;br /&gt;
&lt;br /&gt;
    // Определяем тип элемента меню и связанное свойство в зависимости от типа устройства&lt;br /&gt;
    if ($rec['TYPE'] == 'relay' || $rec['TYPE'] == 'switch') {&lt;br /&gt;
        $menu_rec['TYPE'] = 'switch';&lt;br /&gt;
        $menu_rec['LINKED_PROPERTY'] = 'status';&lt;br /&gt;
        $menu_rec['CUR_VALUE'] = getGlobal($menu_rec['LINKED_OBJECT'] . '.' . $menu_rec['LINKED_PROPERTY']);&lt;br /&gt;
    } elseif ($rec['TYPE'] == 'button') {&lt;br /&gt;
        $menu_rec['TYPE'] = 'button';&lt;br /&gt;
        $menu_rec['LINKED_PROPERTY'] = '';&lt;br /&gt;
        $menu_rec['ONCHANGE_METHOD'] = 'pressed';&lt;br /&gt;
    } elseif ($rec['TYPE'] == 'dimmer') {&lt;br /&gt;
        $menu_rec['TYPE'] = 'sliderbox';&lt;br /&gt;
        $menu_rec['MIN_VALUE'] = '0';&lt;br /&gt;
        $menu_rec['MAX_VALUE'] = '100';&lt;br /&gt;
        $menu_rec['STEP_VALUE'] = '1';&lt;br /&gt;
        $menu_rec['LINKED_PROPERTY'] = 'level';&lt;br /&gt;
        $menu_rec['CUR_VALUE'] = getGlobal($menu_rec['LINKED_OBJECT'] . '.' . $menu_rec['LINKED_PROPERTY']);&lt;br /&gt;
    } else {&lt;br /&gt;
        $menu_rec['TYPE'] = 'object';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если запись уже существует, обновляем ее&lt;br /&gt;
    if ($menu_rec['ID']) {&lt;br /&gt;
        SQLUpdate('commands', $menu_rec);&lt;br /&gt;
    } else {&lt;br /&gt;
        // Иначе, создаем новую запись&lt;br /&gt;
        $menu_rec['ID'] = SQLInsert('commands', $menu_rec);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Возвращаем идентификатор созданного или обновленного элемента меню&lt;br /&gt;
    return $menu_rec['ID'];&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * addDeviceToScene&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для добавления устройства в сцену.&lt;br /&gt;
 * Она принимает идентификатор устройства и идентификатор сцены (необязательно).&lt;br /&gt;
 * Функция определяет тип элемента сцены в зависимости от типа устройства и обновляет или создает запись в таблице элементов.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void addDeviceToScene($device_id, $scene_id = 0)&lt;br /&gt;
 * @param int $device_id Идентификатор устройства&lt;br /&gt;
 * @param int $scene_id Идентификатор сцены (необязательно)&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function addDeviceToScene($device_id, $add_scene_id = 0)&lt;br /&gt;
{&lt;br /&gt;
    // Получаем запись об устройстве по идентификатору&lt;br /&gt;
    $rec = SQLSelectOne(&amp;quot;SELECT * FROM devices WHERE ID=&amp;quot; . (int)$device_id);&lt;br /&gt;
    // Если запись не найдена, возвращаем 0&lt;br /&gt;
    if (!$rec['ID']) {&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Если идентификатор сцены не указан, получаем первую сцену из базы данных&lt;br /&gt;
    if (!$add_scene_id) {&lt;br /&gt;
        $scene_rec = SQLSelectOne(&amp;quot;SELECT ID FROM scenes ORDER BY ID LIMIT 1&amp;quot;);&lt;br /&gt;
        // Если сцена найдена, используем ее идентификатор&lt;br /&gt;
        if ($scene_rec['ID']) {&lt;br /&gt;
            $add_scene_id = $scene_rec['ID'];&lt;br /&gt;
        } else {&lt;br /&gt;
            return 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Получаем запись из таблицы элементов, связанную с устройством и сценой&lt;br /&gt;
    $element_rec = SQLSelectOne(&amp;quot;SELECT * FROM elements WHERE SCENE_ID=&amp;quot; . (int)$add_scene_id . &amp;quot; AND `SYSTEM`='&amp;quot; . 'sdevice' . $rec['ID'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
    // Если запись не найдена, инициализируем новую запись и данные мастера&lt;br /&gt;
    if (!$element_rec['ID']) {&lt;br /&gt;
        $element_rec = array();&lt;br /&gt;
        $wizard_data = array();&lt;br /&gt;
    } else {&lt;br /&gt;
        // Иначе, декодируем данные мастера из записи&lt;br /&gt;
        $wizard_data = json_decode($element_rec['WIZARD_DATA'], true);&lt;br /&gt;
    }&lt;br /&gt;
    // Устанавливаем идентификатор сцены&lt;br /&gt;
    $element_rec['SCENE_ID'] = (int)$add_scene_id;&lt;br /&gt;
    // Устанавливаем системный идентификатор&lt;br /&gt;
    $element_rec['SYSTEM'] = 'sdevice' . $rec['ID'];&lt;br /&gt;
    // Если координаты не указаны, задаем случайные значения&lt;br /&gt;
    if (!$element_rec['TOP'] &amp;amp;&amp;amp; !$element_rec['LEFT']) {&lt;br /&gt;
        $element_rec['TOP'] = 10 + rand(0, 300);&lt;br /&gt;
        $element_rec['LEFT'] = 10 + rand(0, 300);&lt;br /&gt;
    }&lt;br /&gt;
    // Если стиль CSS не указан, используем стиль по умолчанию&lt;br /&gt;
    if (!$element_rec['CSS_STYLE']) {&lt;br /&gt;
        $element_rec['CSS_STYLE'] = 'default';&lt;br /&gt;
    }&lt;br /&gt;
    // Кодируем данные мастера обратно в JSON&lt;br /&gt;
    $element_rec['WIZARD_DATA'] = json_encode($wizard_data) . '';&lt;br /&gt;
    // Устанавливаем флаг фона&lt;br /&gt;
    $element_rec['BACKGROUND'] = 0;&lt;br /&gt;
    // Устанавливаем связанный объект&lt;br /&gt;
    $element_rec['LINKED_OBJECT'] = $rec['LINKED_OBJECT'];&lt;br /&gt;
    // Устанавливаем название&lt;br /&gt;
    $element_rec['TITLE'] = $rec['TITLE'];&lt;br /&gt;
    // Устанавливаем флаг легкой конфигурации&lt;br /&gt;
    $element_rec['EASY_CONFIG'] = 1;&lt;br /&gt;
    // Инициализируем единицу измерения связанного свойства&lt;br /&gt;
    $linked_property_unit = '';&lt;br /&gt;
&lt;br /&gt;
    // Устанавливаем тип элемента сцены&lt;br /&gt;
    $element_rec['TYPE'] = 'device';&lt;br /&gt;
    // Устанавливаем идентификатор устройства&lt;br /&gt;
    $element_rec['DEVICE_ID'] = $rec['ID'];&lt;br /&gt;
    /*&lt;br /&gt;
    // Закомментированный код для определения типа элемента сцены и связанного свойства в зависимости от типа устройства&lt;br /&gt;
    if ($rec['TYPE']=='relay' || $rec['TYPE']=='dimmer' || $rec['TYPE']=='switch') {&lt;br /&gt;
        $element_rec['TYPE'] = 'switch';&lt;br /&gt;
        $element_rec['LINKED_PROPERTY'] = 'status';&lt;br /&gt;
    } elseif ($rec['TYPE']=='button') {&lt;br /&gt;
        $element_rec['TYPE'] = 'button';&lt;br /&gt;
    } elseif ($rec['TYPE']=='motion') {&lt;br /&gt;
        $element_rec['TYPE'] = 'warning';&lt;br /&gt;
        $element_rec['LINKED_PROPERTY'] = 'status';&lt;br /&gt;
        $element_rec['CSS_STYLE']='motion';&lt;br /&gt;
    } elseif ($rec['TYPE']=='sensor_temp') {&lt;br /&gt;
        $element_rec['CSS_STYLE']='temp';&lt;br /&gt;
        $linked_property_unit='&amp;amp;deg;C';&lt;br /&gt;
    } elseif ($rec['TYPE']=='sensor_humidity') {&lt;br /&gt;
        $element_rec['CSS_STYLE']='humidity';&lt;br /&gt;
        $linked_property_unit='%';&lt;br /&gt;
    } else {&lt;br /&gt;
        $element_rec['TYPE']='object';&lt;br /&gt;
    }&lt;br /&gt;
    // Дополнительная логика для типов датчиков температуры и влажности&lt;br /&gt;
    if ($rec['TYPE']=='sensor_temp' || $rec['TYPE']=='sensor_humidity') {&lt;br /&gt;
        $element_rec['TYPE'] = 'informer';&lt;br /&gt;
        $element_rec['LINKED_PROPERTY'] = 'value';&lt;br /&gt;
        $wizard_data['STATE_HIGH']=1;&lt;br /&gt;
        $wizard_data['STATE_HIGH_VALUE']='%'.$element_rec['LINKED_OBJECT'].'.maxValue%';&lt;br /&gt;
        $wizard_data['STATE_LOW']=1;&lt;br /&gt;
        $wizard_data['STATE_LOW_VALUE']='%'.$element_rec['LINKED_OBJECT'].'.maxValue%';&lt;br /&gt;
        $wizard_data['UNIT']=$linked_property_unit;&lt;br /&gt;
    }&lt;br /&gt;
    */&lt;br /&gt;
        // Кодируем данные мастера обратно в JSON&lt;br /&gt;
        $element_rec['WIZARD_DATA'] = json_encode($wizard_data);&lt;br /&gt;
&lt;br /&gt;
        // Если запись уже существует, обновляем ее&lt;br /&gt;
        if ($element_rec['ID']) {&lt;br /&gt;
            SQLUpdate('elements', $element_rec);&lt;br /&gt;
        } else {&lt;br /&gt;
            // Иначе, создаем новую запись&lt;br /&gt;
            $element_rec['ID'] = SQLInsert('elements', $element_rec);&lt;br /&gt;
&lt;br /&gt;
            // Получаем связанный объект&lt;br /&gt;
            $linked_object = $rec['LINKED_OBJECT'];&lt;br /&gt;
&lt;br /&gt;
            // Если тип элемента сцены - переключатель&lt;br /&gt;
            if ($element_rec['TYPE'] == 'switch') {&lt;br /&gt;
&lt;br /&gt;
                // Создаем запись состояния для 'off'&lt;br /&gt;
                $state_rec = array();&lt;br /&gt;
                $state_rec['TITLE'] = 'off';&lt;br /&gt;
                $state_rec['HTML'] = $element_rec['TITLE'];&lt;br /&gt;
                $state_rec['ELEMENT_ID'] = $element_rec['ID'];&lt;br /&gt;
                $state_rec['IS_DYNAMIC'] = 1;&lt;br /&gt;
                $state_rec['LINKED_OBJECT'] = $rec['LINKED_OBJECT'] . '';&lt;br /&gt;
                $state_rec['LINKED_PROPERTY'] = 'status';&lt;br /&gt;
                $state_rec['CONDITION'] = 4;&lt;br /&gt;
                $state_rec['CONDITION_VALUE'] = 1;&lt;br /&gt;
                $state_rec['ACTION_OBJECT'] = $rec['LINKED_OBJECT'] . '';&lt;br /&gt;
                $state_rec['ACTION_METHOD'] = 'turnOn';&lt;br /&gt;
                $state_rec['ID'] = SQLInsert('elm_states', $state_rec);&lt;br /&gt;
&lt;br /&gt;
                // Создаем запись состояния для 'on'&lt;br /&gt;
                $state_rec = array();&lt;br /&gt;
                $state_rec['TITLE'] = 'on';&lt;br /&gt;
                $state_rec['HTML'] = $element_rec['TITLE'];&lt;br /&gt;
                $state_rec['ELEMENT_ID'] = $element_rec['ID'];&lt;br /&gt;
                $state_rec['IS_DYNAMIC'] = 1;&lt;br /&gt;
                $state_rec['LINKED_OBJECT'] = $rec['LINKED_OBJECT'] . '';&lt;br /&gt;
                $state_rec['LINKED_PROPERTY'] = 'status';&lt;br /&gt;
                $state_rec['CONDITION'] = 1;&lt;br /&gt;
                $state_rec['CONDITION_VALUE'] = 1;&lt;br /&gt;
                $state_rec['ACTION_OBJECT'] = $rec['LINKED_OBJECT'] . '';&lt;br /&gt;
                $state_rec['ACTION_METHOD'] = 'turnOff';&lt;br /&gt;
                $state_rec['ID'] = SQLInsert('elm_states', $state_rec);&lt;br /&gt;
&lt;br /&gt;
            } elseif ($element_rec['TYPE'] == 'warning') {&lt;br /&gt;
&lt;br /&gt;
                // Создаем запись состояния для 'default'&lt;br /&gt;
                $state_rec = array();&lt;br /&gt;
                $state_rec['TITLE'] = 'default';&lt;br /&gt;
                $state_rec['ELEMENT_ID'] = $element_rec['ID'];&lt;br /&gt;
                $state_rec['HTML'] = $element_rec['TITLE'] . '&amp;lt;br/&amp;gt;%' . $rec['LINKED_OBJECT'] . '.updatedText%';&lt;br /&gt;
                $state_rec['LINKED_OBJECT'] = $rec['LINKED_OBJECT'] . '';&lt;br /&gt;
                $state_rec['LINKED_PROPERTY'] = 'status';&lt;br /&gt;
                $state_rec['IS_DYNAMIC'] = 1;&lt;br /&gt;
                $state_rec['CONDITION'] = 1;&lt;br /&gt;
                $state_rec['CONDITION_VALUE'] = 1;&lt;br /&gt;
                $state_rec['ID'] = SQLInsert('elm_states', $state_rec);&lt;br /&gt;
&lt;br /&gt;
            } elseif ($element_rec['TYPE'] == 'informer') {&lt;br /&gt;
&lt;br /&gt;
                // Устанавливаем связанное свойство&lt;br /&gt;
                $linked_property = 'value';&lt;br /&gt;
                // Устанавливаем флаги для высокого и низкого состояний&lt;br /&gt;
                $state_high = 1;&lt;br /&gt;
                $state_high_value = '%' . $linked_object . '.maxValue%';&lt;br /&gt;
&lt;br /&gt;
                // Если флаг высокого состояния установлен&lt;br /&gt;
                if ($state_high) {&lt;br /&gt;
                    // Создаем запись состояния для 'high'&lt;br /&gt;
                    $state_rec = array();&lt;br /&gt;
                    $state_rec['TITLE'] = 'high';&lt;br /&gt;
                    $state_rec['ELEMENT_ID'] = $element_rec['ID'];&lt;br /&gt;
                    $state_rec['HTML'] = '%' . $linked_object . '.' . $linked_property . '%';&lt;br /&gt;
                    // Если установлена единица измерения, добавляем ее к HTML&lt;br /&gt;
                    if ($linked_property_unit) {&lt;br /&gt;
                        $state_rec['HTML'] .= ' ' . $linked_property_unit;&lt;br /&gt;
                    }&lt;br /&gt;
                    $state_rec['LINKED_OBJECT'] = $linked_object . '';&lt;br /&gt;
                    $state_rec['LINKED_PROPERTY'] = $linked_property . '';&lt;br /&gt;
                    $state_rec['IS_DYNAMIC'] = 1;&lt;br /&gt;
                    // Если установлено значение высокого состояния, добавляем его к записи&lt;br /&gt;
                    if ($state_high_value) {&lt;br /&gt;
                        $state_rec['CONDITION'] = 2;&lt;br /&gt;
                        $state_rec['CONDITION_VALUE'] = $state_high_value;&lt;br /&gt;
                    }&lt;br /&gt;
                    $state_rec['ID'] = SQLInsert('elm_states', $state_rec);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // Устанавливаем флаги для низкого состояния&lt;br /&gt;
                $state_low = 1;&lt;br /&gt;
                $state_low_value = '%' . $linked_object . '.minValue%';&lt;br /&gt;
&lt;br /&gt;
                // Если флаг низкого состояния установлен&lt;br /&gt;
                if ($state_low) {&lt;br /&gt;
                    // Создаем запись состояния для 'low'&lt;br /&gt;
                    $state_rec = array();&lt;br /&gt;
                    $state_rec['TITLE'] = 'low';&lt;br /&gt;
                    $state_rec['ELEMENT_ID'] = $element_rec['ID'];&lt;br /&gt;
                    $state_rec['HTML'] = '%' . $linked_object . '.' . $linked_property . '%';&lt;br /&gt;
                    // Если установлена единица измерения, добавляем ее к HTML&lt;br /&gt;
                    if ($linked_property_unit) {&lt;br /&gt;
                        $state_rec['HTML'] .= ' ' . $linked_property_unit;&lt;br /&gt;
                    }&lt;br /&gt;
                    $state_rec['LINKED_OBJECT'] = $linked_object . '';&lt;br /&gt;
                    $state_rec['LINKED_PROPERTY'] = $linked_property . '';&lt;br /&gt;
                    $state_rec['IS_DYNAMIC'] = 1;&lt;br /&gt;
                    // Если установлено значение низкого состояния, добавляем его к записи&lt;br /&gt;
                    if ($state_low_value) {&lt;br /&gt;
                        $state_rec['CONDITION'] = 3;&lt;br /&gt;
                        $state_rec['CONDITION_VALUE'] = $state_low_value;&lt;br /&gt;
                    }&lt;br /&gt;
                    $state_rec['ID'] = SQLInsert('elm_states', $state_rec);&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // Создаем запись состояния для 'default'&lt;br /&gt;
                $state_rec = array();&lt;br /&gt;
                $state_rec['TITLE'] = 'default';&lt;br /&gt;
                $state_rec['ELEMENT_ID'] = $element_rec['ID'];&lt;br /&gt;
                $state_rec['HTML'] = '%' . $linked_object . '.' . $linked_property . '%';&lt;br /&gt;
                // Если установлена единица измерения, добавляем ее к HTML&lt;br /&gt;
                if ($linked_property_unit) {&lt;br /&gt;
                    $state_rec['HTML'] .= ' ' . $linked_property_unit;&lt;br /&gt;
                }&lt;br /&gt;
                // Если установлены флаги высокого или низкого состояния&lt;br /&gt;
                if ($state_high || $state_low) {&lt;br /&gt;
                    $state_rec['IS_DYNAMIC'] = 1;&lt;br /&gt;
                    $state_rec['LINKED_OBJECT'] = $linked_object . '';&lt;br /&gt;
                    $state_rec['LINKED_PROPERTY'] = $linked_property . '';&lt;br /&gt;
                    // Если установлены оба флага, устанавливаем is_dynamic в 2 и добавляем условие&lt;br /&gt;
                    if ($state_high &amp;amp;&amp;amp; $state_low) {&lt;br /&gt;
                        $state_rec['IS_DYNAMIC'] = 2;&lt;br /&gt;
                        $state_rec['CONDITION_ADVANCED'] = 'if (gg(\'' . $linked_object . '.' . $linked_property . '\')&amp;gt;=gg(\'' . $linked_object . '.minValue\') &amp;amp;&amp;amp; gg(\'' . $linked_object . '.' . $linked_property . '\')&amp;lt;=gg(\'' . $linked_object . '.maxValue\')) {' . &amp;quot;\n &amp;quot; . '$display=1;' . &amp;quot;\n&amp;quot; . '} else {' . &amp;quot;\n &amp;quot; . '$display=0;' . &amp;quot;\n&amp;quot; . '}';&lt;br /&gt;
                    } elseif ($state_high) {&lt;br /&gt;
                        $state_rec['IS_DYNAMIC'] = 1;&lt;br /&gt;
                        $state_rec['CONDITION'] = 3;&lt;br /&gt;
                        $state_rec['CONDITION_VALUE'] = $state_high_value;&lt;br /&gt;
                    } elseif ($state_low) {&lt;br /&gt;
                        $state_rec['IS_DYNAMIC'] = 1;&lt;br /&gt;
                        $state_rec['CONDITION'] = 2;&lt;br /&gt;
                        $state_rec['CONDITION_VALUE'] = $state_low_value;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                $state_rec['ID'] = SQLInsert('elm_states', $state_rec);&lt;br /&gt;
&lt;br /&gt;
            } elseif ($element_rec['TYPE'] == 'button') {&lt;br /&gt;
                // Устанавливаем метод связанного объекта&lt;br /&gt;
                $linked_method = 'pressed';&lt;br /&gt;
                // Создаем запись состояния для 'default'&lt;br /&gt;
                $state_rec = array();&lt;br /&gt;
                $state_rec['TITLE'] = 'default';&lt;br /&gt;
                $state_rec['ELEMENT_ID'] = $element_rec['ID'];&lt;br /&gt;
                $state_rec['HTML'] = $element_rec['TITLE'];&lt;br /&gt;
                // Если установлены связанный объект и метод, добавляем их к записи&lt;br /&gt;
                if ($linked_object &amp;amp;&amp;amp; $linked_method) {&lt;br /&gt;
                    $state_rec['ACTION_OBJECT'] = $linked_object;&lt;br /&gt;
                    $state_rec['ACTION_METHOD'] = $linked_method;&lt;br /&gt;
                }&lt;br /&gt;
                $state_rec['ID'] = SQLInsert('elm_states', $state_rec);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
/**&lt;br /&gt;
 * checkLinkedDevicesAction&lt;br /&gt;
 *&lt;br /&gt;
 * Функция для проверки действий связанных устройств.&lt;br /&gt;
 * Она принимает название связанного объекта и значение (необязательно).&lt;br /&gt;
 * Функция выполняет поиск устройств, связанных с указанным объектом, и включает файл с действиями связанных устройств.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void checkLinkedDevicesAction($object_name, $value = '')&lt;br /&gt;
 * @param string $object_name Название связанного объекта&lt;br /&gt;
 * @param string $value Значение (необязательно)&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function checkLinkedDevicesAction($object_title, $value = 0)&lt;br /&gt;
{&lt;br /&gt;
    // Начинаем измерение времени выполнения функции&lt;br /&gt;
    startMeasure('checkLinkedDevicesAction');&lt;br /&gt;
    // Получаем запись об устройстве, связанном с указанным объектом&lt;br /&gt;
    $device1 = SQLSelectOne(&amp;quot;SELECT * FROM devices WHERE LINKED_OBJECT LIKE '&amp;quot; . $object_title . &amp;quot;'&amp;quot;);&lt;br /&gt;
    // Если устройство не найдено, завершаем измерение времени и возвращаем 0&lt;br /&gt;
    if (!$device1['ID']) {&lt;br /&gt;
        endMeasure('checkLinkedDevicesAction');&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    // Включаем файл с действиями связанных устройств&lt;br /&gt;
    include(dirname(__FILE__) . '/devices_links_actions.inc.php');&lt;br /&gt;
    // Завершаем измерение времени выполнения функции&lt;br /&gt;
    endMeasure('checkLinkedDevicesAction');&lt;br /&gt;
    // Возвращаем 1, указывая на успешное выполнение функции&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * Install&lt;br /&gt;
 *&lt;br /&gt;
 * Маршрутина установки модуля.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void Install()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 *//&lt;br /&gt;
function install($data = '')&lt;br /&gt;
{&lt;br /&gt;
    // Выполняем установку родительского класса&lt;br /&gt;
    parent::install();&lt;br /&gt;
&lt;br /&gt;
    // Включаем файлы языка модуля для текущего языка сайта и по умолчанию&lt;br /&gt;
    if (file_exists(ROOT . 'languages/' . $this-&amp;gt;name . '_' . SETTINGS_SITE_LANGUAGE . '.php')) {&lt;br /&gt;
        include_once(ROOT . 'languages/' . $this-&amp;gt;name . '_' . SETTINGS_SITE_LANGUAGE . '.php');&lt;br /&gt;
    }&lt;br /&gt;
    if (file_exists(ROOT . 'languages/' . $this-&amp;gt;name . '_default' . '.php')) {&lt;br /&gt;
        include_once(ROOT . 'languages/' . $this-&amp;gt;name . '_default' . '.php');&lt;br /&gt;
    }&lt;br /&gt;
    // Обновляем заголовок модуля в таблице проектных модулей&lt;br /&gt;
    SQLExec(&amp;quot;UPDATE project_modules SET TITLE='&amp;quot; . LANG_DEVICES_MODULE_TITLE . &amp;quot;' WHERE NAME='&amp;quot; . $this-&amp;gt;name . &amp;quot;'&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Устанавливаем словарь устройств&lt;br /&gt;
    $this-&amp;gt;setDictionary();&lt;br /&gt;
    // Рендерим структуру модуля&lt;br /&gt;
    $this-&amp;gt;renderStructure();&lt;br /&gt;
    // Синхронизируем с Homebridge&lt;br /&gt;
    $this-&amp;gt;homebridgeSync();&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * Uninstall&lt;br /&gt;
 *&lt;br /&gt;
 * Маршрутина удаления модуля.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void Uninstall()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function uninstall()&lt;br /&gt;
{&lt;br /&gt;
    // Удаляем таблицу устройств&lt;br /&gt;
    SQLDropTable('devices');&lt;br /&gt;
    // Выполняем удаление родительского класса&lt;br /&gt;
    parent::uninstall();&lt;br /&gt;
}&lt;br /&gt;
/**&lt;br /&gt;
 * dbInstall&lt;br /&gt;
 *&lt;br /&gt;
 * Маршрутина установки базы данных.&lt;br /&gt;
 *&lt;br /&gt;
 * @method void dbInstall()&lt;br /&gt;
 * @return void&lt;br /&gt;
 * @see module&lt;br /&gt;
 * @since 0.1&lt;br /&gt;
 */&lt;br /&gt;
function dbInstall($data = '')&lt;br /&gt;
{&lt;br /&gt;
/*&lt;br /&gt;
* Создание таблиц для устройств и связей между ними.&lt;br /&gt;
*/&lt;br /&gt;
    $data = &amp;lt;&amp;lt;&amp;lt;EOD&lt;br /&gt;
 devices: ID int(10) unsigned NOT NULL auto_increment&lt;br /&gt;
 devices: TITLE varchar(100) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: ALT_TITLES varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: TYPE varchar(100) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: LINKED_OBJECT varchar(100) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: LOCATION_ID int(10) unsigned NOT NULL DEFAULT 0  &lt;br /&gt;
 devices: FAVORITE int(3) unsigned NOT NULL DEFAULT 0 &lt;br /&gt;
 devices: SYSTEM_DEVICE int(3) unsigned NOT NULL DEFAULT 0&lt;br /&gt;
 devices: CLICKED datetime DEFAULT NULL&lt;br /&gt;
 devices: ARCHIVED int(3) unsigned NOT NULL DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
 devices: SYSTEM varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: SUBTYPE varchar(100) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: ENDPOINT_MODULE varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: ENDPOINT_NAME varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: ENDPOINT_TITLE varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
 devices: ROLES varchar(100) NOT NULL DEFAULT ''&lt;br /&gt;
&lt;br /&gt;
 devices_linked: ID int(10) unsigned NOT NULL auto_increment&lt;br /&gt;
 devices_linked: DEVICE1_ID int(10) unsigned NOT NULL DEFAULT 0&lt;br /&gt;
 devices_linked: DEVICE2_ID int(10) unsigned NOT NULL DEFAULT 0&lt;br /&gt;
 devices_linked: LINK_TYPE varchar(100) NOT NULL DEFAULT ''&lt;br /&gt;
 devices_linked: LINK_SETTINGS text&lt;br /&gt;
 devices_linked: COMMENT varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
  &lt;br /&gt;
 devices_groups: ID int(10) unsigned NOT NULL auto_increment&lt;br /&gt;
 devices_groups: SYS_NAME varchar(100) NOT NULL DEFAULT ''&lt;br /&gt;
 devices_groups: TITLE varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
 devices_groups: APPLY_TYPES text&lt;br /&gt;
&lt;br /&gt;
 devices_scheduler_points: ID int(10) unsigned NOT NULL auto_increment&lt;br /&gt;
 devices_scheduler_points: LINKED_METHOD varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
 devices_scheduler_points: VALUE varchar(255) NOT NULL DEFAULT ''&lt;br /&gt;
 devices_scheduler_points: SET_TIME varchar(50) NOT NULL DEFAULT ''&lt;br /&gt;
 devices_scheduler_points: SET_DAYS varchar(50) NOT NULL DEFAULT '' &lt;br /&gt;
 devices_scheduler_points: DEVICE_ID int(10) NOT NULL DEFAULT '0'&lt;br /&gt;
 devices_scheduler_points: ACTIVE int(3) NOT NULL DEFAULT '1'&lt;br /&gt;
 devices_scheduler_points: LATEST_RUN datetime&lt;br /&gt;
&lt;br /&gt;
EOD;&lt;br /&gt;
    // Выполняем установку базы данных&lt;br /&gt;
    parent::dbInstall($data);&lt;br /&gt;
    }&lt;br /&gt;
    // --------------------------------------------------------------------&lt;br /&gt;
}&lt;br /&gt;
/*&lt;br /&gt;
* Зачем эта строка с кодировкой? не понятно.&lt;br /&gt;
* TW9kdWxlIGNyZWF0ZWQgSnVsIDE5LCAyMDE2IHVzaW5nIFNlcmdlIEouIHdpemFyZCAoQWN0aXZlVW5pdCBJbmMgd3d3LmFjdGl2ZXVuaXQuY29tKQ==&lt;br /&gt;
*&lt;br /&gt;
*/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1945</id>
		<title>Safe exec</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1945"/>
		<updated>2024-03-12T03:06:36Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''safe_exec'''($command, $exclusive = 0, $priority = 0, $on_complete = ''); -- param mixed $command Command param mixed $exclusive Exclusive (default 0) param mixed $priority Priority (default 0) param mixed $on_complete On_Complete code (default '') return mixed&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Выполнение команды  в отдельном потоке.''&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
safe_exec (&amp;quot;sudo -u pi /home/pi/myscript.sh&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1944</id>
		<title>Safe exec</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1944"/>
		<updated>2024-03-12T03:06:04Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''safe_exec'''($command, $exclusive = 0, $priority = 0, $on_complete = ''); -- param mixed $command Command param mixed $exclusive Exclusive (default 0) param mixed $priority Priority (default 0) param mixed $on_complete On_Complete code (default '') return mixed&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Выполнение команды от пользователя в отдельном потоке.''&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
safe_exec (&amp;quot;sudo -u pi /home/pi/myscript.sh&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1943</id>
		<title>Safe exec</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1943"/>
		<updated>2024-03-12T03:05:35Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''safe_exec'''($command, $exclusive = 0, $priority = 0, $on_complete = ''); -- param mixed $command Command param mixed $exclusive Exclusive (default 0) param mixed $priority Priority (default 0) param mixed $on_complete On_Complete code (default '') return mixed&lt;br /&gt;
''Выполнение команды от пользователя в отдельном потоке.''&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
safe_exec (&amp;quot;sudo -u pi /home/pi/myscript.sh&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1942</id>
		<title>Safe exec</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1942"/>
		<updated>2024-03-12T03:04:56Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Примеры запросов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''safe_exec'''($command, $exclusive = 0, $priority = 0, $on_complete = ''); -- param mixed $command Command param mixed $exclusive Exclusive (default 0) param mixed $priority Priority (default 0) param mixed $on_complete On_Complete code (default '') return mixed&lt;br /&gt;
''Выполнение команды от пользователя в отдельном потоке.''&lt;br /&gt;
Пример: exec (&amp;quot;sudo -u pi /home/pi/myscript.sh&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
safe_exec (&amp;quot;sudo -u pi /home/pi/myscript.sh&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1941</id>
		<title>Safe exec</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Safe_exec&amp;diff=1941"/>
		<updated>2024-03-12T03:04:25Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''safe_exec'''($command, $exclusive = 0, $priority = 0, $on_complete = ''); -- param mixed $command Command param mixed $exclusive Exclusive (default 0) param mixed $priority Priority (default 0) param mixed $on_complete On_Complete code (default '') return mixed&lt;br /&gt;
''Выполнение команды от пользователя в отдельном потоке.''&lt;br /&gt;
Пример: exec (&amp;quot;sudo -u pi /home/pi/myscript.sh&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82_%D0%BE%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B8_%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B_%D0%91%D0%94&amp;diff=1934</id>
		<title>Скрипт очистки таблицы БД</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82_%D0%BE%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B8_%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B_%D0%91%D0%94&amp;diff=1934"/>
		<updated>2024-01-04T07:53:49Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Юзеркейсы]]&lt;br /&gt;
Сценарий очистки таблицы Базы данных:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SQLExec(&amp;quot;DELETE FROM phistory WHERE TO_DAYS(NOW())-TO_DAYS(ADDED)&amp;gt;30&amp;quot;);&lt;br /&gt;
SQLExec(&amp;quot;OPTIMIZE TABLE phistory&amp;quot;);&lt;br /&gt;
//очистит все старше 30 дней&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
В примере очистка таблицы Phistory, удаляет записи старше 30 дней.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=ShutDown&amp;diff=1933</id>
		<title>ShutDown</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=ShutDown&amp;diff=1933"/>
		<updated>2024-01-04T07:53:28Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Юзеркейсы]]&lt;br /&gt;
shutDown - системный сценарий, перезагрузки системы, входит в базовый образ для Raspbery Pi. Т.к. в базовых образах 4-хх база данных работает в ОЗУ и сохраняет БД на диск (карту памяти) раз в 15 минут (в настройках по по умолчанию), то чтоб не потерять результаты работы, рекомендуется использовать перезагрузку и выключение через соответствующие скрипты. Вызвать их можно: - '''''Главная страница - Меню Сервис - Отключение/перзагрузка''''' .&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$filename  = ROOT . '/database_backup/db.sql';&lt;br /&gt;
$mysqlDumpPath = &amp;quot;/usr/bin/mysqldump&amp;quot;;&lt;br /&gt;
$mysqlDumpParam = &amp;quot; --user=&amp;quot; . DB_USER . &amp;quot; --password=&amp;quot; . DB_PASSWORD;&lt;br /&gt;
$mysqlDumpParam .= &amp;quot; --no-create-db --add-drop-table --databases &amp;quot; . DB_NAME;&lt;br /&gt;
if (file_exists($filename)) rename($filename, $filename . '.prev');&lt;br /&gt;
exec($mysqlDumpPath . $mysqlDumpParam . &amp;quot; &amp;gt; &amp;quot; . $filename);&lt;br /&gt;
say(LANG_GENERAL_STARTING_SHUTDOWN,2);&lt;br /&gt;
setTimeout(&amp;quot;shutdownTimer&amp;quot;,&amp;quot;safe_exec('shutdown -h now');&amp;quot;,15);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''В образах 4-хх'' запуск функции safe_exec выполняется от пользователя pi, которому даны права выполнять команды от имени root без подтверждения.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=RebootSystem&amp;diff=1932</id>
		<title>RebootSystem</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=RebootSystem&amp;diff=1932"/>
		<updated>2024-01-04T07:52:54Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Юзеркейсы]]&lt;br /&gt;
rebootSystem - системный сценарий, перезагрузки системы, входит в базовый образ для Raspbery Pi. Т.к. в базовых образах 4-хх база данных работает в ОЗУ и сохраняет БД на диск (карту памяти) раз в 15 минут (в настройках по по умолчанию), то чтоб не потерять результаты работы, рекомендуется использовать перезагрузку и выключение через соответствующие скрипты. Вызвать их можно: - '''''Главная страница - Меню Сервис - Отключение/перзагрузка''''' .&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$filename  = ROOT . '/database_backup/db.sql';&lt;br /&gt;
$mysqlDumpPath = &amp;quot;/usr/bin/mysqldump&amp;quot;;&lt;br /&gt;
$mysqlDumpParam = &amp;quot; --user=&amp;quot; . DB_USER . &amp;quot; --password=&amp;quot; . DB_PASSWORD;&lt;br /&gt;
$mysqlDumpParam .= &amp;quot; --no-create-db --add-drop-table --databases &amp;quot; . DB_NAME;&lt;br /&gt;
if (file_exists($filename)) rename($filename, $filename . '.prev');&lt;br /&gt;
exec($mysqlDumpPath . $mysqlDumpParam . &amp;quot; &amp;gt; &amp;quot; . $filename);&lt;br /&gt;
say(LANG_GENERAL_STARTING_REBOOT,2);&lt;br /&gt;
setTimeout(&amp;quot;shutdownTimer&amp;quot;,&amp;quot;safe_exec('shutdown -r now');&amp;quot;,15);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''В образах 4-хх'' запуск функции safe_exec выполняется от пользователя pi, которому даны права выполнять команды от имени root без подтверждения.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=OperationalModes&amp;diff=1929</id>
		<title>OperationalModes</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=OperationalModes&amp;diff=1929"/>
		<updated>2023-11-18T04:35:24Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Структура]]&lt;br /&gt;
&lt;br /&gt;
 OperationalModes - класс объектов с изменение режимов УД, таких как &amp;quot;темное / светлое время суток&amp;quot;, &amp;quot;энергосбережение&amp;quot;, &amp;quot;никого нет дома&amp;quot;, &amp;quot;ночной режим&amp;quot;.&lt;br /&gt;
Каждый объект содержит методы activated, deactivated, modeChanged в которых можно изменить поведение системы при работе в этих режимах.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=OperationalModes&amp;diff=1928</id>
		<title>OperationalModes</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=OperationalModes&amp;diff=1928"/>
		<updated>2023-11-18T04:34:57Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Структура]]&lt;br /&gt;
&lt;br /&gt;
 '''OperationalModes''' - класс объектов с изменение режимов УД, таких как &amp;quot;темное / светлое время суток&amp;quot;, &amp;quot;энергосбережение&amp;quot;, &amp;quot;никого нет дома&amp;quot;, &amp;quot;ночной режим&amp;quot;.&lt;br /&gt;
Каждый объект содержит методы activated, deactivated, modeChanged в которых можно изменить поведение системы при работе в этих режимах.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=OperationalModes&amp;diff=1927</id>
		<title>OperationalModes</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=OperationalModes&amp;diff=1927"/>
		<updated>2023-11-18T04:33:44Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: « OperationalModes - класс объектов с изменение режимов УД, таких как &amp;quot;темное / светлое время суток&amp;quot;, &amp;quot;энергосбережение&amp;quot;, &amp;quot;никого нет дома&amp;quot;, &amp;quot;ночной режим&amp;quot;. Каждый объект содержит методы activated, deactivated, modeChanged в которых можно изменить поведение системы при работе в этих...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; OperationalModes - класс объектов с изменение режимов УД, таких как &amp;quot;темное / светлое время суток&amp;quot;, &amp;quot;энергосбережение&amp;quot;, &amp;quot;никого нет дома&amp;quot;, &amp;quot;ночной режим&amp;quot;.&lt;br /&gt;
Каждый объект содержит методы activated, deactivated, modeChanged в которых можно изменить поведение системы при работе в этих режимах.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=OnNewDay&amp;diff=1926</id>
		<title>OnNewDay</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=OnNewDay&amp;diff=1926"/>
		<updated>2023-11-18T04:01:26Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Примеры запросов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Структура]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''OnNewDay''' -- Системный таймер выполняющийся каждый день 00 часов из ядра системы. Реализован методом, находится в классе '''Timer''' объекта '''ClockChime'''&lt;br /&gt;
При установке системы дневного таймера может не быть, в таком случае его необходимо там создать.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Обратите внимание на другие таймеры'''&lt;br /&gt;
&lt;br /&gt;
[[OnNewMinute|OnNewMinute - минутный таймер]]&lt;br /&gt;
&lt;br /&gt;
[[OnNewHour|OnNewHour - часовой таймер]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
Код полностью поддерживает PHP, что позволяет писать&lt;br /&gt;
say('Новый день настал'); //и любой другой код который нужно выполнить раз в день. Рассчитать восход-закат например&lt;br /&gt;
&amp;lt;pre&amp;gt; $d=date('m.d',time()); &lt;br /&gt;
if ($d==&amp;quot;10.15&amp;quot;) { // тут явно заданна дата выполнения кода &lt;br /&gt;
    say('начался зимний период');&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
Дневной таймер&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Systemd-journal-gatewayd&amp;diff=1925</id>
		<title>Systemd-journal-gatewayd</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Systemd-journal-gatewayd&amp;diff=1925"/>
		<updated>2023-11-13T04:38:39Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:другой СОФТ]]&lt;br /&gt;
Есть служба systemd-journal-gatewayd, с помощью которой можно смотреть логи systemd через браузер. Причём настраивается она максимально просто, буквально в пару действий. Показываю на примере базового образа v_44 для Raspberry Pi (Debian 10).&lt;br /&gt;
Так же можно вообще попытаться разобраться у себя в системе, а что там творится :-)&lt;br /&gt;
&lt;br /&gt;
Устанавливаем пакет systemd-journal-remote:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install systemd-journal-remote&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Запускаем службу:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo systemctl start systemd-journal-gatewayd.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При необходимости включение в автозагрузку:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo systemctl enable systemd-journal-gatewayd.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''''Порт по умолчанию 19531.'''''&lt;br /&gt;
Идём смотреть логи в браузер: обзор логов&lt;br /&gt;
http://192.168.1.121:19531/browse&lt;br /&gt;
&lt;br /&gt;
Это обзорный url. Тут в выпадающем списке можно выбирать любой лог системной службы.&lt;br /&gt;
Можно посмотреть логи только текущей загрузки: http://192.168.1.121:19531/entries?boot  или же непосредственно выбрать интересующий тебя сервис.&lt;br /&gt;
&lt;br /&gt;
Можно через curl забирать эти же логи в json формате. Примерно так для юнита ssh:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl --silent -H 'Accept: application/json' \   'http://10.20.1.36:19531/entries?UNIT=ssh.service'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Более подробно параметры и возможности описаны в документации &lt;br /&gt;
[http://(https://www.freedesktop.org/software/systemd/man/systemd-journal-gatewayd.html). Пример документации].&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Systemd-journal-gatewayd&amp;diff=1924</id>
		<title>Systemd-journal-gatewayd</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Systemd-journal-gatewayd&amp;diff=1924"/>
		<updated>2023-11-13T04:37:17Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: «Category:другой СОФТ Есть служба systemd-journal-gatewayd, с помощью которой можно смотреть логи systemd через браузер. Причём настраивается она максимально просто, буквально в пару действий. Показываю на примере базового образа v_44 для Raspberry Pi (Debian 10). Так же можно вообщ...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:другой СОФТ]]&lt;br /&gt;
Есть служба systemd-journal-gatewayd, с помощью которой можно смотреть логи systemd через браузер. Причём настраивается она максимально просто, буквально в пару действий. Показываю на примере базового образа v_44 для Raspberry Pi (Debian 10).&lt;br /&gt;
Так же можно вообще попытаться разобраться у себя в системе, а что там творится :-)&lt;br /&gt;
&lt;br /&gt;
Устанавливаем пакет systemd-journal-remote:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt install systemd-journal-remote&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Запускаем службу:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo systemctl start systemd-journal-gatewayd.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При необходимости включение в автозагрузку:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo systemctl enable systemd-journal-gatewayd.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''''Порт по умолчанию 19531.'''''&lt;br /&gt;
Идём смотреть логи в браузер: обзор логов&lt;br /&gt;
&lt;br /&gt;
Это обзорный url. Тут в выпадающем списке можно выбирать любой лог системной службы.&lt;br /&gt;
Можно посмотреть логи только текущей загрузки: http://192.168.1.121:19531/entries?boot http://192.168.1.121:19531/entries?boot. или же непосредственно выбрать интересующий тебя сервис.&lt;br /&gt;
&lt;br /&gt;
Можно через curl забирать эти же логи в json формате. Примерно так для юнита ssh:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl --silent -H 'Accept: application/json' \   'http://10.20.1.36:19531/entries?UNIT=ssh.service'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Более подробно параметры и возможности описаны в документации &lt;br /&gt;
[http://(https://www.freedesktop.org/software/systemd/man/systemd-journal-gatewayd.html). Пример документации].&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82_%D0%BE%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B8_%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B_%D0%91%D0%94&amp;diff=1904</id>
		<title>Скрипт очистки таблицы БД</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82_%D0%BE%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B8_%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B_%D0%91%D0%94&amp;diff=1904"/>
		<updated>2023-09-26T11:51:50Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Примеры сценариев]]&lt;br /&gt;
Сценарий очистки таблицы Базы данных:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SQLExec(&amp;quot;DELETE FROM phistory WHERE TO_DAYS(NOW())-TO_DAYS(ADDED)&amp;gt;30&amp;quot;);&lt;br /&gt;
SQLExec(&amp;quot;OPTIMIZE TABLE phistory&amp;quot;);&lt;br /&gt;
//очистит все старше 30 дней&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
В примере очистка таблицы Phistory, удаляет записи старше 30 дней.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82_%D0%BE%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B8_%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B_%D0%91%D0%94&amp;diff=1903</id>
		<title>Скрипт очистки таблицы БД</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82_%D0%BE%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B8_%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B_%D0%91%D0%94&amp;diff=1903"/>
		<updated>2023-09-26T11:51:16Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: «Category:Примеры сценариев Сценарий очистки таблицы Базы данных: &amp;lt;pre&amp;gt; SQLExec(&amp;quot;DELETE FROM phistory WHERE TO_DAYS(NOW())-TO_DAYS(ADDED)&amp;gt;30&amp;quot;); SQLExec(&amp;quot;OPTIMIZE TABLE phistory&amp;quot;); //очистит все старше 30 дней &amp;lt;/pre&amp;gt; В примере очистка таблицы Phistory.»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Примеры сценариев]]&lt;br /&gt;
Сценарий очистки таблицы Базы данных:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SQLExec(&amp;quot;DELETE FROM phistory WHERE TO_DAYS(NOW())-TO_DAYS(ADDED)&amp;gt;30&amp;quot;);&lt;br /&gt;
SQLExec(&amp;quot;OPTIMIZE TABLE phistory&amp;quot;);&lt;br /&gt;
//очистит все старше 30 дней&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
В примере очистка таблицы Phistory.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=ShutDown&amp;diff=1902</id>
		<title>ShutDown</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=ShutDown&amp;diff=1902"/>
		<updated>2023-09-02T09:29:48Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: «Category:Примеры сценариев shutDown - системный сценарий, перезагрузки системы, входит в базовый образ для Raspbery Pi. Т.к. в базовых образах 4-хх база данных работает в ОЗУ и сохраняет БД на диск (карту памяти) раз в 15 минут (в настройках по по умолчанию), то чтоб не п...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Примеры сценариев]]&lt;br /&gt;
shutDown - системный сценарий, перезагрузки системы, входит в базовый образ для Raspbery Pi. Т.к. в базовых образах 4-хх база данных работает в ОЗУ и сохраняет БД на диск (карту памяти) раз в 15 минут (в настройках по по умолчанию), то чтоб не потерять результаты работы, рекомендуется использовать перезагрузку и выключение через соответствующие скрипты. Вызвать их можно: - '''''Главная страница - Меню Сервис - Отключение/перзагрузка''''' .&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$filename  = ROOT . '/database_backup/db.sql';&lt;br /&gt;
$mysqlDumpPath = &amp;quot;/usr/bin/mysqldump&amp;quot;;&lt;br /&gt;
$mysqlDumpParam = &amp;quot; --user=&amp;quot; . DB_USER . &amp;quot; --password=&amp;quot; . DB_PASSWORD;&lt;br /&gt;
$mysqlDumpParam .= &amp;quot; --no-create-db --add-drop-table --databases &amp;quot; . DB_NAME;&lt;br /&gt;
if (file_exists($filename)) rename($filename, $filename . '.prev');&lt;br /&gt;
exec($mysqlDumpPath . $mysqlDumpParam . &amp;quot; &amp;gt; &amp;quot; . $filename);&lt;br /&gt;
say(LANG_GENERAL_STARTING_SHUTDOWN,2);&lt;br /&gt;
setTimeout(&amp;quot;shutdownTimer&amp;quot;,&amp;quot;safe_exec('shutdown -h now');&amp;quot;,15);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''В образах 4-хх'' запуск функции safe_exec выполняется от пользователя pi, которому даны права выполнять команды от имени root без подтверждения.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=RebootSystem&amp;diff=1901</id>
		<title>RebootSystem</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=RebootSystem&amp;diff=1901"/>
		<updated>2023-09-02T09:27:51Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: «Category:Примеры сценариев rebootSystem - системный сценарий, перезагрузки системы, входит в базовый образ для Raspbery Pi. Т.к. в базовых образах 4-хх база данных работает в ОЗУ и сохраняет БД на диск (карту памяти) раз в 15 минут (в настройках по по умолчанию), то чтоб н...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Примеры сценариев]]&lt;br /&gt;
rebootSystem - системный сценарий, перезагрузки системы, входит в базовый образ для Raspbery Pi. Т.к. в базовых образах 4-хх база данных работает в ОЗУ и сохраняет БД на диск (карту памяти) раз в 15 минут (в настройках по по умолчанию), то чтоб не потерять результаты работы, рекомендуется использовать перезагрузку и выключение через соответствующие скрипты. Вызвать их можно: - '''''Главная страница - Меню Сервис - Отключение/перзагрузка''''' .&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$filename  = ROOT . '/database_backup/db.sql';&lt;br /&gt;
$mysqlDumpPath = &amp;quot;/usr/bin/mysqldump&amp;quot;;&lt;br /&gt;
$mysqlDumpParam = &amp;quot; --user=&amp;quot; . DB_USER . &amp;quot; --password=&amp;quot; . DB_PASSWORD;&lt;br /&gt;
$mysqlDumpParam .= &amp;quot; --no-create-db --add-drop-table --databases &amp;quot; . DB_NAME;&lt;br /&gt;
if (file_exists($filename)) rename($filename, $filename . '.prev');&lt;br /&gt;
exec($mysqlDumpPath . $mysqlDumpParam . &amp;quot; &amp;gt; &amp;quot; . $filename);&lt;br /&gt;
say(LANG_GENERAL_STARTING_REBOOT,2);&lt;br /&gt;
setTimeout(&amp;quot;shutdownTimer&amp;quot;,&amp;quot;safe_exec('shutdown -r now');&amp;quot;,15);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''В образах 4-хх'' запуск функции safe_exec выполняется от пользователя pi, которому даны права выполнять команды от имени root без подтверждения.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B_%D1%81%D1%86%D0%B5%D0%BD%D0%B0%D1%80%D0%B8%D0%B5%D0%B2&amp;diff=1900</id>
		<title>Категория:Примеры сценариев</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B_%D1%81%D1%86%D0%B5%D0%BD%D0%B0%D1%80%D0%B8%D0%B5%D0%B2&amp;diff=1900"/>
		<updated>2023-09-02T08:56:28Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:root]]&lt;br /&gt;
В данном разделе будут приведены примеры сценариев.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:PHP_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8&amp;diff=1899</id>
		<title>Категория:PHP функции</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:PHP_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8&amp;diff=1899"/>
		<updated>2023-09-02T08:55:06Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Vik Tam переименовал страницу Категория:PHP функции в Категория:Примеры сценариев: В связи с отсутствием наполнения раздела PHP функции предлагаю, чтоб не создавать новую категорию наполнять переименованную &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#перенаправление [[:Категория:Примеры сценариев]]&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B_%D1%81%D1%86%D0%B5%D0%BD%D0%B0%D1%80%D0%B8%D0%B5%D0%B2&amp;diff=1898</id>
		<title>Категория:Примеры сценариев</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B_%D1%81%D1%86%D0%B5%D0%BD%D0%B0%D1%80%D0%B8%D0%B5%D0%B2&amp;diff=1898"/>
		<updated>2023-09-02T08:55:05Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Vik Tam переименовал страницу Категория:PHP функции в Категория:Примеры сценариев: В связи с отсутствием наполнения раздела PHP функции предлагаю, чтоб не создавать новую категорию наполнять переименованную &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:root]]&lt;br /&gt;
Эта страница содержит популярные PHP функции.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Omxplayer&amp;diff=1897</id>
		<title>Omxplayer</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Omxplayer&amp;diff=1897"/>
		<updated>2023-08-09T06:54:50Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:другой СОФТ]]&lt;br /&gt;
Omxplayer - консольный медиаплеер с управлением из командной строки.&lt;br /&gt;
[https://github.com/popcornmix/omxplayer Ссылка на проект Omxplayer на GitHub]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В MajorDoMo используется для проигрывания системных сообщений в базовых образах 4_хх для Raspbery Pi. &lt;br /&gt;
Настройки указаны в файле /var/www/html/config.php 100 строка.&lt;br /&gt;
Пример настроек по умолчанию в образах &lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
Define('AUDIO_PLAYER','omxplayer --no-osd');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Пример изменения громкости системных сообщений (с установкой громкости почти на минимальную) :&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
Define('AUDIO_PLAYER','omxplayer --no-osd --vol -3000');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Для использования устройства вывода звука через USB звуковую карты в строке настроек нужно использовать следующий ключ (для Raspberry Pi 3B):&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
-o alsa:hw:1,0&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Omxplayer&amp;diff=1896</id>
		<title>Omxplayer</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Omxplayer&amp;diff=1896"/>
		<updated>2023-08-09T06:54:19Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:другой СОФТ]]&lt;br /&gt;
Omxplayer - консольный медиаплеер с управлением из командной строки.&lt;br /&gt;
[https://github.com/popcornmix/omxplayer Ссылка на проект Omxplayer на GitHub]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В MajorDoMo используется для проигрывания системных сообщений в базовых образах 4_хх для Raspbery Pi. &lt;br /&gt;
Настройки указаны в файле /var/www/html/config.php 100 строка.&lt;br /&gt;
Пример настроек по умолчанию в образах &lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
Define('AUDIO_PLAYER','omxplayer --no-osd');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Пример изменения громкости системных сообщений (с установкой громкости почти на минимальную) :&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
Define('AUDIO_PLAYER','omxplayer --no-osd --vol -3000');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Для использования устройства вывода звука через USB звуковую карты в строке настроек нужно использовать следующий ключ:&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
-o alsa:hw:1,0&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Omxplayer&amp;diff=1895</id>
		<title>Omxplayer</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Omxplayer&amp;diff=1895"/>
		<updated>2023-08-07T08:25:43Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:другой СОФТ]]&lt;br /&gt;
Omxplayer - консольный медиаплеер с управлением из командной строки.&lt;br /&gt;
[https://github.com/popcornmix/omxplayer Ссылка на проект Omxplayer на GitHub]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В MajorDoMo используется для проигрывания системных сообщений в базовых образах 4_хх для Raspbery Pi. &lt;br /&gt;
Настройки указаны в файле /var/www/html/config.php 100 строка.&lt;br /&gt;
Пример настроек по умолчанию в образах &lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
Define('AUDIO_PLAYER','omxplayer --no-osd');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Пример изменения громкости системных сообщений (с установкой громкости почти на минимальную) :&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
Define('AUDIO_PLAYER','omxplayer --no-osd --vol -3000');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Omxplayer&amp;diff=1894</id>
		<title>Omxplayer</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Omxplayer&amp;diff=1894"/>
		<updated>2023-08-07T08:25:24Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: «Category:другой СОФТ Omxplayer - консольный медиаплеер с управлением из командной строки. [https://github.com/popcornmix/omxplayer Ссылка на проект Omxplayer на GitHub] В MajorDoMo используется для проигрывания системных сообщений в базовых образах 4_хх для Raspbery Pi.  Настройки указаны в файл...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:другой СОФТ]]&lt;br /&gt;
Omxplayer - консольный медиаплеер с управлением из командной строки.&lt;br /&gt;
[https://github.com/popcornmix/omxplayer Ссылка на проект Omxplayer на GitHub]&lt;br /&gt;
В MajorDoMo используется для проигрывания системных сообщений в базовых образах 4_хх для Raspbery Pi. &lt;br /&gt;
Настройки указаны в файле /var/www/html/config.php 100 строка.&lt;br /&gt;
Пример настроек по умолчанию в образах &lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
Define('AUDIO_PLAYER','omxplayer --no-osd');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Пример изменения громкости системных сообщений (с установкой громкости почти на минимальную) :&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
Define('AUDIO_PLAYER','omxplayer --no-osd --vol -3000');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1882</id>
		<title>Установка на Windows с использованием пакета XAMPP</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1882"/>
		<updated>2023-01-05T07:40:02Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
В процессе редактирования ...&lt;br /&gt;
Установка MajorDoMo на Windows 10 с использованием пакета XAMPP (кроссплатформенная сборка веб-сервера, содержащая Apache, MySQL, интерпретатор скриптов PHP, язык программирования Perl и большое количество дополнительных библиотек, позволяющих запустить полноценный веб-сервер). &lt;br /&gt;
Полноценное описание доступно на форуме в первом посте темы &amp;quot;Установка Мажордомо на XAMPP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Шаг первый: скачиваем и устанавливаем пакет XAMPP на ПК с Windows, ссылка на скачивание пакета с пхп 7.3.1 [https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.3.1/ XAMPP с PHP 7.3.1] &lt;br /&gt;
Устанавливаем на любой диск (у меня D). &lt;br /&gt;
&lt;br /&gt;
[[Файл:01 Предупреждение UAC.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
UAC у меня не включен, поэтому игнорирую предупреждение.&lt;br /&gt;
&lt;br /&gt;
Отмечаем галочкой сервисы, которые планируете установить, у меня все отмечены, можно обойтись обязательными Apache, MySQL, PHP, phpMyAdmin.&lt;br /&gt;
&lt;br /&gt;
[[Файл:02 Установка сервисов.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Указываем путь для установки и выбираем из двух языков (больше нет) английский.&lt;br /&gt;
Нажимаем установить. После установки запускается панель управления XAMPP. &lt;br /&gt;
Закрываем её, нажатие на крестик не помогает, закрываем через диспетчер задач. &lt;br /&gt;
&lt;br /&gt;
После этого переходим к файлу xampp-control.exe в папке с установленным xampp и запускаем его от администратора.&lt;br /&gt;
&lt;br /&gt;
[[Файл:03 Control exe.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Переходим к  config в панели правый верхний угол, и устанавливаем  галочки на автостарте модулей, как показано на скрине (Apache и MySQL). Что это значит – при запуске xampp, автоматически запускаются эти модули и не нужно в дальнейшем выполнять запуск в ручную. &lt;br /&gt;
&lt;br /&gt;
Без запуска от админа сохранения не применяются, отказ в доступе.&lt;br /&gt;
Закрываем панель xampp, в том числе из систем трея. &lt;br /&gt;
Скачиваем файлы majordomo одним архивом, на примере из альфа ветки: &lt;br /&gt;
&lt;br /&gt;
[https://github.com/sergejey/majordomo/tree/alpha Файлы MajorDoMo Alpha ветка]&lt;br /&gt;
&lt;br /&gt;
[[Файл:04 Файлы на GIT.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
Удаляем все файлы из папки / htdocs.  Распаковываем и копируем файлы Majordomo, в папку / htdocs, естественно не папкой majordomo-alpha а всем её содержимым.&lt;br /&gt;
&lt;br /&gt;
И еще надо положить папку apps (приложения) из мажордомо в папку XAMPP (корень) (папку miniRelay не смог загрузить, ругалась на вирусы)&lt;br /&gt;
[https://disk.yandex.by/d/4Ui7Up_vZ1VYbA Ссылка на папку apps)&lt;br /&gt;
&lt;br /&gt;
Кроме того не хватает архиваторов, распаковываем в директорию httpdoc&lt;br /&gt;
[https://disk.yandex.by/d/4Ui7Up_vZ1VYbA Ссылка на скачивание архиваторов] &lt;br /&gt;
&lt;br /&gt;
Запускаем *.exe файл с панелью XAMPP (xampp-control.exe), при этом сервисы апача и mySQL  стартуют автоматически и из браузера перейдём в панель управления phpmyadmin набрав адрес:  http://127.0.0.1/phpmyadmin/&lt;br /&gt;
&lt;br /&gt;
[[Файл:05 PHPMyAdmin.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Импортируем базу данных MajorDoMo:&lt;br /&gt;
Нажимаем - создать БД&lt;br /&gt;
и в поле - имя базы - вписываем '''db_terminal'''.&lt;br /&gt;
В соседнем поле изменяем кодировку на '''utf8_general_ci'''.&lt;br /&gt;
Нажимаем кнопку '''Создать'''.&lt;br /&gt;
Теперь нажимем на созданный db_terminal и сверху жмем слово '''Импорт'''.&lt;br /&gt;
Выбираем файл db_terminal.sql (он находится в папке диск:\путь к хамп\htdocs)&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Создание БД.png|600px|центр]] &lt;br /&gt;
и нажимаем '''Вперед'''.&lt;br /&gt;
&lt;br /&gt;
После импорта появится надпись об успешном окончании импортирования.&lt;br /&gt;
Заходим по адресу 127.0.0.1 - появляется стартовая страница, радоваться пока не спешим, нужно произвести некоторые настройки. Закрываем панель управления xamppa (в т.ч. и из систем трея).&lt;br /&gt;
Теперь мажордомо надо настроить.&lt;br /&gt;
Переименуем '''config.php.sample''' в '''config.php'''&lt;br /&gt;
И отредактируем пути в этом файле (config.php):&lt;br /&gt;
а именно - в этих строках:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Define('SERVER_ROOT', '/var/www');&lt;br /&gt;
 Define('PATH_TO_PHP', 'php');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;mysqldump&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на следующее:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Define('SERVER_ROOT', 'диск:/путь к хамп');&lt;br /&gt;
 Define('PATH_TO_PHP', 'диск:/путь к хамп/php/php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;диск:/путь к хамп/mysql/bin/mysqldump.exe&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Пример при размещении папки xampp в корене диска /D:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Define('SERVER_ROOT', 'd:/xampp');&lt;br /&gt;
 Define('PATH_TO_PHP', 'd:\xampp\php\php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', SERVER_ROOT.'/mysql/bin/mysqldump.exe');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Соответственно сохраняем этот файл после внесенных изменений.&lt;br /&gt;
Включаем в PHP сокеты в файле /php/php.ini &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extension=sockets&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Исправление простое - надо в пхп.ини вместо &lt;br /&gt;
''';extension=sockets''' сделать '''extension=sockets''' (удалить символ ''';''')&lt;br /&gt;
&lt;br /&gt;
Напишем простой bat файл для запуска цикла и MajorDoMo  вместе с xampp. &lt;br /&gt;
Пример bat файла mjdm start.bat, расположен в папке /xampp&lt;br /&gt;
 Содержимое:&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
 start диск:\путь к хамп\xampp-control.exe &amp;gt;nul&lt;br /&gt;
диск:\путь к хамп\php\php.exe диск:\путь к хамп\htdocs\cycle.php&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
Или:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
start d:/xampp/xampp-control.exe &amp;gt;nul&lt;br /&gt;
rem Main system cycle start&lt;br /&gt;
1&lt;br /&gt;
d:\xampp\php\php.exe d:\xampp\htdocs\cycle.php&lt;br /&gt;
goto 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ТЕПЕРЬ ВСЕ&lt;br /&gt;
Запускаем Мажордомо этим батником&lt;br /&gt;
&lt;br /&gt;
ПОСЛЕ ЭТОГО ОБЯЗАТЕЛЬНЫЙ РЕБУТ КОМПА&lt;br /&gt;
&lt;br /&gt;
После перезагрузки Запускаем локальный сервер созданным bat-файлом (запуск рекомендую от администратора) заходим по адресу: http://127.0.0.1/&lt;br /&gt;
Попадаем на начальную страницу настройки языка/времени:&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Начальная страница настроек.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
Если страница не открылась, можем открыть набрав: http://127.0.0.1//popup/first_start.html.&lt;br /&gt;
После установки настроек переход на главную страницу majorDoMo.&lt;br /&gt;
&lt;br /&gt;
[[Файл:08 Главное Окно.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Из папки scripts удаляем (переименовываем) ненужные для вашего пользования и запуска скрипты.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1881</id>
		<title>Установка на Windows с использованием пакета XAMPP</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1881"/>
		<updated>2023-01-05T07:39:07Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
В процессе редактирования ...&lt;br /&gt;
Установка MajorDoMo на Windows 10 с использованием пакета XAMPP (кроссплатформенная сборка веб-сервера, содержащая Apache, MySQL, интерпретатор скриптов PHP, язык программирования Perl и большое количество дополнительных библиотек, позволяющих запустить полноценный веб-сервер). &lt;br /&gt;
Полноценное описание доступно на форуме в первом посте темы &amp;quot;Установка Мажордомо на XAMPP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Шаг первый: скачиваем и устанавливаем пакет XAMPP на ПК с Windows, ссылка на скачивание пакета с пхп 7.3.1 [https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.3.1/ XAMPP с PHP 7.3.1] &lt;br /&gt;
Устанавливаем на любой диск (у меня D). &lt;br /&gt;
&lt;br /&gt;
[[Файл:01 Предупреждение UAC.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
UAC у меня не включен, поэтому игнорирую предупреждение.&lt;br /&gt;
&lt;br /&gt;
Отмечаем галочкой сервисы, которые планируете установить, у меня все отмечены, можно обойтись обязательными Apache, MySQL, PHP, phpMyAdmin.&lt;br /&gt;
&lt;br /&gt;
[[Файл:02 Установка сервисов.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Указываем путь для установки и выбираем из двух языков (больше нет) английский.&lt;br /&gt;
Нажимаем установить. После установки запускается панель управления XAMPP. &lt;br /&gt;
Закрываем её, нажатие на крестик не помогает, закрываем через диспетчер задач. &lt;br /&gt;
&lt;br /&gt;
После этого переходим к файлу xampp-control.exe в папке с установленным xampp и запускаем его от администратора.&lt;br /&gt;
&lt;br /&gt;
[[Файл:03 Control exe.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Переходим к  config в панели правый верхний угол, и устанавливаем  галочки на автостарте модулей, как показано на скрине (Apache и MySQL). Что это значит – при запуске xampp, автоматически запускаются эти модули и не нужно в дальнейшем выполнять запуск в ручную. &lt;br /&gt;
&lt;br /&gt;
Без запуска от админа сохранения не применяются, отказ в доступе.&lt;br /&gt;
Закрываем панель xampp, в том числе из систем трея. &lt;br /&gt;
Скачиваем файлы majordomo одним архивом, на примере из альфа ветки: &lt;br /&gt;
&lt;br /&gt;
[https://github.com/sergejey/majordomo/tree/alpha Файлы MajorDoMo Alpha ветка]&lt;br /&gt;
&lt;br /&gt;
[[Файл:04 Файлы на GIT.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
Удаляем все файлы из папки / htdocs.  Распаковываем и копируем файлы Majordomo, в папку / htdocs, естественно не папкой majordomo-alpha а всем её содержимым.&lt;br /&gt;
&lt;br /&gt;
И еще надо положить папку apps (приложения) из мажордомо в папку XAMPP (корень) (папку miniRelay не смог загрузить, ругалась на вирусы)&lt;br /&gt;
[https://disk.yandex.by/d/4Ui7Up_vZ1VYbA Ссылка на папку apps)&lt;br /&gt;
&lt;br /&gt;
Кроме того не хватает архиваторов, распаковываем в директорию httpdoc&lt;br /&gt;
[https://disk.yandex.by/d/4Ui7Up_vZ1VYbA Ссылка на скачивание архиваторов] &lt;br /&gt;
&lt;br /&gt;
Запускаем *.exe файл с панелью XAMPP (xampp-control.exe), при этом сервисы апача и mySQL  стартуют автоматически и из браузера перейдём в панель управления phpmyadmin набрав адрес:  http://127.0.0.1/phpmyadmin/&lt;br /&gt;
&lt;br /&gt;
[[Файл:05 PHPMyAdmin.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Импортируем базу данных MajorDoMo:&lt;br /&gt;
Нажимаем - создать БД&lt;br /&gt;
и в поле - имя базы - вписываем '''db_terminal'''.&lt;br /&gt;
В соседнем поле изменяем кодировку на '''utf8_general_ci'''.&lt;br /&gt;
Нажимаем кнопку '''Создать'''.&lt;br /&gt;
Теперь нажимем на созданный db_terminal и сверху жмем слово '''Импорт'''.&lt;br /&gt;
Выбираем файл db_terminal.sql (он находится в папке диск:\путь к хамп\htdocs)&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Создание БД.png|600px|центр]] &lt;br /&gt;
и нажимаем '''Вперед'''.&lt;br /&gt;
&lt;br /&gt;
После импорта появится надпись об успешном окончании импортирования.&lt;br /&gt;
Заходим по адресу 127.0.0.1 - появляется стартовая страница, радоваться пока не спешим, нужно произвести некоторые настройки. Закрываем панель управления xamppa (в т.ч. и из систем трея).&lt;br /&gt;
Теперь мажордомо надо настроить.&lt;br /&gt;
Переименуем '''config.php.sample''' в '''config.php'''&lt;br /&gt;
И отредактируем пути в этом файле (config.php):&lt;br /&gt;
а именно - в этих строках:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Define('SERVER_ROOT', '/var/www');&lt;br /&gt;
 Define('PATH_TO_PHP', 'php');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;mysqldump&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на следующее:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Define('SERVER_ROOT', 'диск:/путь к хамп');&lt;br /&gt;
 Define('PATH_TO_PHP', 'диск:/путь к хамп/php/php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;диск:/путь к хамп/mysql/bin/mysqldump.exe&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Пример при размещении папки xampp в корене диска /D:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Define('SERVER_ROOT', 'd:/xampp');&lt;br /&gt;
 Define('PATH_TO_PHP', 'd:\xampp\php\php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', SERVER_ROOT.'/mysql/bin/mysqldump.exe');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Соответственно сохраняем этот файл после внесенных изменений.&lt;br /&gt;
Включаем в PHP сокеты в файле /php/php.ini &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extension=sockets&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Исправление простое - надо в пхп.ини вместо &lt;br /&gt;
''';extension=sockets''' сделать '''extension=sockets''' (удалить символ ''';''')&lt;br /&gt;
&lt;br /&gt;
Напишем простой bat файл для запуска цикла и MajorDoMo  вместе с xampp. &lt;br /&gt;
Пример bat файла mjdm start.bat, расположен в папке /xampp&lt;br /&gt;
 Содержимое:&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
 start диск:\путь к хамп\xampp-control.exe &amp;gt;nul&lt;br /&gt;
диск:\путь к хамп\php\php.exe диск:\путь к хамп\htdocs\cycle.php&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
Или:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
start d:/xampp/xampp-control.exe &amp;gt;nul&lt;br /&gt;
rem Main system cycle start&lt;br /&gt;
1&lt;br /&gt;
d:\xampp\php\php.exe d:\xampp\htdocs\cycle.php&lt;br /&gt;
goto 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ТЕПЕРЬ ВСЕ&lt;br /&gt;
Запускаем Мажордомо этим батником&lt;br /&gt;
&lt;br /&gt;
ПОСЛЕ ЭТОГО ОБЯЗАТЕЛЬНЫЙ РЕБУТ КОМПА&lt;br /&gt;
&lt;br /&gt;
После перезагрузки Запускаем локальный сервер созданным bat-файлом (запуск рекомендую от администратора) заходим по адресу: http://127.0.0.1/&lt;br /&gt;
Попадаем на начальную страницу настройки языка/времени:&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Начальная страница настроек.png|мини]] &lt;br /&gt;
&lt;br /&gt;
Если страница не открылась, можем открыть набрав: http://127.0.0.1//popup/first_start.html.&lt;br /&gt;
После установки настроек переход на главную страницу majorDoMo.&lt;br /&gt;
&lt;br /&gt;
[[Файл:08 Главное Окно.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Из папки scripts удаляем (переименовываем) ненужные для вашего пользования и запуска скрипты.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1880</id>
		<title>Установка на Windows с использованием пакета XAMPP</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1880"/>
		<updated>2023-01-05T07:35:39Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
В процессе редактирования ...&lt;br /&gt;
Установка MajorDoMo на Windows 10 с использованием пакета XAMPP (кроссплатформенная сборка веб-сервера, содержащая Apache, MySQL, интерпретатор скриптов PHP, язык программирования Perl и большое количество дополнительных библиотек, позволяющих запустить полноценный веб-сервер). &lt;br /&gt;
Полноценное описание доступно на форуме в первом посте темы &amp;quot;Установка Мажордомо на XAMPP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Шаг первый: скачиваем и устанавливаем пакет XAMPP на ПК с Windows, ссылка на скачивание пакета с пхп 7.3.1 [https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.3.1/ XAMPP с PHP 7.3.1] &lt;br /&gt;
Устанавливаем на любой диск (у меня D). &lt;br /&gt;
&lt;br /&gt;
[[Файл:01 Предупреждение UAC.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
UAC у меня не включен, поэтому игнорирую предупреждение.&lt;br /&gt;
&lt;br /&gt;
Отмечаем галочкой сервисы, которые планируете установить, у меня все отмечены, можно обойтись обязательными Apache, MySQL, PHP, phpMyAdmin.&lt;br /&gt;
&lt;br /&gt;
[[Файл:02 Установка сервисов.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Указываем путь для установки и выбираем из двух языков (больше нет) английский.&lt;br /&gt;
Нажимаем установить. После установки запускается панель управления XAMPP. &lt;br /&gt;
Закрываем её, нажатие на крестик не помогает, закрываем через диспетчер задач. &lt;br /&gt;
&lt;br /&gt;
После этого переходим к файлу xampp-control.exe в папке с установленным xampp и запускаем его от администратора.&lt;br /&gt;
&lt;br /&gt;
[[Файл:03 Control exe.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Переходим к  config в панели правый верхний угол, и устанавливаем  галочки на автостарте модулей, как показано на скрине (Apache и MySQL). Что это значит – при запуске xampp, автоматически запускаются эти модули и не нужно в дальнейшем выполнять запуск в ручную. &lt;br /&gt;
&lt;br /&gt;
Без запуска от админа сохранения не применяются, отказ в доступе.&lt;br /&gt;
Закрываем панель xampp, в том числе из систем трея. &lt;br /&gt;
Скачиваем файлы majordomo одним архивом, на примере из альфа ветки: &lt;br /&gt;
&lt;br /&gt;
[https://github.com/sergejey/majordomo/tree/alpha Файлы MajorDoMo Alpha ветка]&lt;br /&gt;
&lt;br /&gt;
[[Файл:04 Файлы на GIT.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
Удаляем все файлы из папки / htdocs.  Распаковываем и копируем файлы Majordomo, в папку / htdocs, естественно не папкой majordomo-alpha а всем её содержимым.&lt;br /&gt;
&lt;br /&gt;
И еще надо положить папку apps (приложения) из мажордомо в папку XAMPP (корень) (папку miniRelay не смог загрузить, ругалась на вирусы)&lt;br /&gt;
[Ссылка на папку apps](https://disk.yandex.by/d/4Ui7Up_vZ1VYbA)&lt;br /&gt;
&lt;br /&gt;
Кроме того не хватает архиваторов, распаковываем в директорию httpdoc&lt;br /&gt;
[архиваторы](https://disk.yandex.by/d/E7QqMO-C7hYCOA)&lt;br /&gt;
&lt;br /&gt;
Запускаем *.exe файл с панелью XAMPP (xampp-control.exe), при этом сервисы апача и mySQL  стартуют автоматически и из браузера перейдём в панель управления phpmyadmin набрав адрес: &lt;br /&gt;
[](http://127.0.0.1/phpmyadmin/).&lt;br /&gt;
&lt;br /&gt;
[[Файл:05 PHPMyAdmin.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Импортируем базу данных MajorDoMo:&lt;br /&gt;
Нажимаем - создать БД&lt;br /&gt;
и в поле - имя базы - вписываем '''db_terminal'''.&lt;br /&gt;
В соседнем поле изменяем кодировку на '''utf8_general_ci'''.&lt;br /&gt;
Нажимаем кнопку '''Создать'''.&lt;br /&gt;
Теперь нажимем на созданный db_terminal и сверху жмем слово '''Импорт'''.&lt;br /&gt;
Выбираем файл db_terminal.sql (он находится в папке диск:\путь к хамп\htdocs)&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Создание БД.png|600px|центр]] &lt;br /&gt;
и нажимаем '''Вперед'''.&lt;br /&gt;
&lt;br /&gt;
После импорта появится надпись об успешном окончании импортирования.&lt;br /&gt;
Заходим по адресу 127.0.0.1 - появляется стартовая страница, радоваться пока не спешим, нужно произвести некоторые настройки. Закрываем панель управления xamppa (в т.ч. и из систем трея).&lt;br /&gt;
Теперь мажордомо надо настроить.&lt;br /&gt;
Переименуем '''config.php.sample''' в '''config.php'''&lt;br /&gt;
И отредактируем пути в этом файле (config.php):&lt;br /&gt;
а именно - в этих строках:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Define('SERVER_ROOT', '/var/www');&lt;br /&gt;
 Define('PATH_TO_PHP', 'php');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;mysqldump&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на следующее:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Define('SERVER_ROOT', 'диск:/путь к хамп');&lt;br /&gt;
 Define('PATH_TO_PHP', 'диск:/путь к хамп/php/php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;диск:/путь к хамп/mysql/bin/mysqldump.exe&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Пример при размещении папки xampp в корене диска /D:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Define('SERVER_ROOT', 'd:/xampp');&lt;br /&gt;
 Define('PATH_TO_PHP', 'd:\xampp\php\php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', SERVER_ROOT.'/mysql/bin/mysqldump.exe');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Соответственно сохраняем этот файл после внесенных изменений.&lt;br /&gt;
Включаем в PHP сокеты в файле /php/php.ini &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extension=sockets&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Исправление простое - надо в пхп.ини вместо &lt;br /&gt;
''';extension=sockets''' сделать '''extension=sockets''' (удалить символ ''';''')&lt;br /&gt;
&lt;br /&gt;
Напишем простой bat файл для запуска цикла и MajorDoMo  вместе с xampp. &lt;br /&gt;
Пример bat файла mjdm start.bat, расположен в папке /xampp&lt;br /&gt;
 Содержимое:&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
 start диск:\путь к хамп\xampp-control.exe &amp;gt;nul&lt;br /&gt;
диск:\путь к хамп\php\php.exe диск:\путь к хамп\htdocs\cycle.php&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
Или:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
start d:/xampp/xampp-control.exe &amp;gt;nul&lt;br /&gt;
rem Main system cycle start&lt;br /&gt;
1&lt;br /&gt;
d:\xampp\php\php.exe d:\xampp\htdocs\cycle.php&lt;br /&gt;
goto 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ТЕПЕРЬ ВСЕ&lt;br /&gt;
Запускаем Мажордомо этим батником&lt;br /&gt;
&lt;br /&gt;
ПОСЛЕ ЭТОГО ОБЯЗАТЕЛЬНЫЙ РЕБУТ КОМПА&lt;br /&gt;
&lt;br /&gt;
После перезагрузки Запускаем локальный сервер созданным bat-файлом (запуск рекомендую от администратора) заходим по адресу: http://127.0.0.1/&lt;br /&gt;
Попадаем на начальную страницу настройки языка/времени:&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Начальная страница настроек.png|мини]] &lt;br /&gt;
&lt;br /&gt;
Если страница не открылась, можем открыть набрав: http://127.0.0.1//popup/first_start.html.&lt;br /&gt;
После установки настроек переход на главную страницу majorDoMo.&lt;br /&gt;
&lt;br /&gt;
[[Файл:08 Главное Окно.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Из папки scripts удаляем (переименовываем) ненужные для вашего пользования и запуска скрипты.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:08_%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D0%BE%D0%B5_%D0%9E%D0%BA%D0%BD%D0%BE.png&amp;diff=1879</id>
		<title>Файл:08 Главное Окно.png</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:08_%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D0%BE%D0%B5_%D0%9E%D0%BA%D0%BD%D0%BE.png&amp;diff=1879"/>
		<updated>2023-01-05T07:33:26Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;08 Главное Окно&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:06_%D0%9D%D0%B0%D1%87%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0_%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BA.png&amp;diff=1878</id>
		<title>Файл:06 Начальная страница настроек.png</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:06_%D0%9D%D0%B0%D1%87%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0_%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BA.png&amp;diff=1878"/>
		<updated>2023-01-05T07:31:38Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;06 Начальная страница настроек&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1877</id>
		<title>Установка на Windows с использованием пакета XAMPP</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1877"/>
		<updated>2023-01-05T07:06:41Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
В процессе редактирования ...&lt;br /&gt;
Установка MajorDoMo на Windows 10 с использованием пакета XAMPP (кроссплатформенная сборка веб-сервера, содержащая Apache, MySQL, интерпретатор скриптов PHP, язык программирования Perl и большое количество дополнительных библиотек, позволяющих запустить полноценный веб-сервер). &lt;br /&gt;
Полноценное описание доступно на форуме в первом посте темы &amp;quot;Установка Мажордомо на XAMPP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Шаг первый: скачиваем и устанавливаем пакет XAMPP на ПК с Windows, ссылка на скачивание пакета с пхп 7.3.1 [https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.3.1/ XAMPP с PHP 7.3.1] &lt;br /&gt;
Устанавливаем на любой диск (у меня D). &lt;br /&gt;
&lt;br /&gt;
[[Файл:01 Предупреждение UAC.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
UAC у меня не включен, поэтому игнорирую предупреждение.&lt;br /&gt;
&lt;br /&gt;
Отмечаем галочкой сервисы, которые планируете установить, у меня все отмечены, можно обойтись обязательными Apache, MySQL, PHP, phpMyAdmin.&lt;br /&gt;
&lt;br /&gt;
[[Файл:02 Установка сервисов.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Указываем путь для установки и выбираем из двух языков (больше нет) английский.&lt;br /&gt;
Нажимаем установить. После установки запускается панель управления XAMPP. &lt;br /&gt;
Закрываем её, нажатие на крестик не помогает, закрываем через диспетчер задач. &lt;br /&gt;
&lt;br /&gt;
После этого переходим к файлу xampp-control.exe в папке с установленным xampp и запускаем его от администратора.&lt;br /&gt;
&lt;br /&gt;
[[Файл:03 Control exe.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
Переходим к  config в панели правый верхний угол, и устанавливаем  галочки на автостарте модулей, как показано на скрине (Apache и MySQL). Что это значит – при запуске xampp, автоматически запускаются эти модули и не нужно в дальнейшем выполнять запуск в ручную. &lt;br /&gt;
&lt;br /&gt;
Без запуска от админа сохранения не применяются, отказ в доступе.&lt;br /&gt;
Закрываем панель xampp, в том числе из систем трея. &lt;br /&gt;
Скачиваем файлы majordomo одним архивом, на примере из альфа ветки: &lt;br /&gt;
&lt;br /&gt;
[https://github.com/sergejey/majordomo/tree/alpha Файлы MajorDoMo Alpha ветка]&lt;br /&gt;
&lt;br /&gt;
[[Файл:04 Файлы на GIT.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
Удаляем все файлы из папки / htdocs.  Распаковываем и копируем файлы Majordomo, в папку / htdocs, естественно не папкой majordomo-alpha а всем её содержимым.&lt;br /&gt;
&lt;br /&gt;
И еще надо положить папку apps (приложения) из мажордомо в папку XAMPP (корень) (папку miniRelay не смог загрузить, ругалась на вирусы)&lt;br /&gt;
[Ссылка на папку apps](https://disk.yandex.by/d/4Ui7Up_vZ1VYbA)&lt;br /&gt;
&lt;br /&gt;
Кроме того не хватает архиваторов, распаковываем в директорию httpdoc&lt;br /&gt;
[архиваторы](https://disk.yandex.by/d/E7QqMO-C7hYCOA)&lt;br /&gt;
&lt;br /&gt;
Запускаем *.exe файл с панелью XAMPP (xampp-control.exe), при этом сервисы апача и mySQL  стартуют автоматически и из браузера перейдём в панель управления phpmyadmin набрав адрес: &lt;br /&gt;
[](http://127.0.0.1/phpmyadmin/).&lt;br /&gt;
&lt;br /&gt;
[[Файл:05 PHPMyAdmin.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Импортируем базу данных MajorDoMo:&lt;br /&gt;
Нажимаем - создать БД&lt;br /&gt;
и в поле - имя базы - вписываем '''db_terminal'''.&lt;br /&gt;
В соседнем поле изменяем кодировку на '''utf8_general_ci'''.&lt;br /&gt;
Нажимаем кнопку '''Создать'''.&lt;br /&gt;
Теперь нажимем на созданный db_terminal и сверху жмем слово '''Импорт'''.&lt;br /&gt;
Выбираем файл db_terminal.sql (он находится в папке диск:\путь к хамп\htdocs)&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Создание БД.png|600px|центр]] &lt;br /&gt;
и нажимаем '''Вперед'''.&lt;br /&gt;
&lt;br /&gt;
После импорта появится надпись об успешном окончании импортирования.&lt;br /&gt;
Заходим по адресу 127.0.0.1 - появляется стартовая страница, радоваться пока не спешим, нужно произвести некоторые настройки. Закрываем панель управления xamppa (в т.ч. и из систем трея).&lt;br /&gt;
Теперь мажордомо надо настроить.&lt;br /&gt;
Переименуем '''config.php.sample''' в '''config.php'''&lt;br /&gt;
И отредактируем пути в этом файле (config.php):&lt;br /&gt;
а именно - в этих строках&lt;br /&gt;
```&lt;br /&gt;
 Define('SERVER_ROOT', '/var/www');&lt;br /&gt;
 Define('PATH_TO_PHP', 'php');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;mysqldump&amp;quot;);&lt;br /&gt;
```&lt;br /&gt;
на следующее:&lt;br /&gt;
```&lt;br /&gt;
Define('SERVER_ROOT', 'диск:/путь к хамп');&lt;br /&gt;
 Define('PATH_TO_PHP', 'диск:/путь к хамп/php/php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;диск:/путь к хамп/mysql/bin/mysqldump.exe&amp;quot;);&lt;br /&gt;
```&lt;br /&gt;
в моем случае (корень диска D) вышло так:&lt;br /&gt;
```&lt;br /&gt;
 Define('SERVER_ROOT', 'd:/xampp');&lt;br /&gt;
 Define('PATH_TO_PHP', 'd:\xampp\php\php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', SERVER_ROOT.'/mysql/bin/mysqldump.exe');&lt;br /&gt;
 ```&lt;br /&gt;
Соответственно сохраняем этот файл после внесенных изменений.&lt;br /&gt;
Включаем в PHP сокеты в файле /php/php.ini &lt;br /&gt;
 ```&lt;br /&gt;
extension=sockets&lt;br /&gt;
 ```&lt;br /&gt;
Исправление простое - надо в пхп.ини вместо &lt;br /&gt;
;extension=sockets сделать extension=sockets (удалить символ ;)&lt;br /&gt;
&lt;br /&gt;
Напишем простой bat файл для запуска цикла и MajorDoMo  вместе с xampp. К примеру у меня mjdm start.bat , ресположен в папке /xampp&lt;br /&gt;
 Содержимое:&lt;br /&gt;
 ```&lt;br /&gt;
 start диск:\путь к хамп\xampp-control.exe &amp;gt;nul&lt;br /&gt;
диск:\путь к хамп\php\php.exe диск:\путь к хамп\htdocs\cycle.php&lt;br /&gt;
 ```&lt;br /&gt;
У меня:&lt;br /&gt;
 ```&lt;br /&gt;
start d:/xampp/xampp-control.exe &amp;gt;nul&lt;br /&gt;
rem Main system cycle start&lt;br /&gt;
:1&lt;br /&gt;
d:\xampp\php\php.exe d:\xampp\htdocs\cycle.php&lt;br /&gt;
goto 1&lt;br /&gt;
 ```&lt;br /&gt;
ТЕПЕРЬ ВСЕ&lt;br /&gt;
Запускаем Мажордомо этим батником&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ПОСЛЕ ЭТОГО ОБЯЗАТЕЛЬНЫЙ РЕБУТ КОМПА&lt;br /&gt;
&lt;br /&gt;
После перезагрузки Запускаем локальный сервер созданным bat-файлом (запуск рекомендую от администратора) заходим по адресу:&lt;br /&gt;
http://127.0.0.1/&lt;br /&gt;
Попадаем на начальную страницу настройки языка/времени:&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1829_image.png)&lt;br /&gt;
&lt;br /&gt;
Если страница не открылась, можем открыть набрав: http://127.0.0.1//popup/first_start.html.&lt;br /&gt;
После установки настроек переход на главную страницу majorDoMo.&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1830_image.png)&lt;br /&gt;
&lt;br /&gt;
Из папки scripts удаляем (переименоваем ненужные для  запуска скрипты, в моем случае: cycle_connect.php, cycle_mqtt.php cycle_yadevices.php cycle_zigbee2mqtt.php cycle_zigbeedev.php cycle_db_save.php &lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1837_image.png)&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:06_%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%94.png&amp;diff=1876</id>
		<title>Файл:06 Создание БД.png</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:06_%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%94.png&amp;diff=1876"/>
		<updated>2023-01-05T07:05:33Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;06 Создание БД&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:05_PHPMyAdmin.png&amp;diff=1875</id>
		<title>Файл:05 PHPMyAdmin.png</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:05_PHPMyAdmin.png&amp;diff=1875"/>
		<updated>2023-01-05T07:04:37Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;05 PHPMyAdmin&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:04_%D0%A4%D0%B0%D0%B9%D0%BB%D1%8B_%D0%BD%D0%B0_GIT.png&amp;diff=1874</id>
		<title>Файл:04 Файлы на GIT.png</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:04_%D0%A4%D0%B0%D0%B9%D0%BB%D1%8B_%D0%BD%D0%B0_GIT.png&amp;diff=1874"/>
		<updated>2023-01-05T07:01:29Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;04 Файлы на GIT&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:03_Control_exe.png&amp;diff=1873</id>
		<title>Файл:03 Control exe.png</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:03_Control_exe.png&amp;diff=1873"/>
		<updated>2023-01-05T06:58:48Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;03 Control exe&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:02_%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2.png&amp;diff=1872</id>
		<title>Файл:02 Установка сервисов.png</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:02_%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2.png&amp;diff=1872"/>
		<updated>2023-01-05T06:57:09Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;02 Установка сервисов&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:01_%D0%9F%D1%80%D0%B5%D0%B4%D1%83%D0%BF%D1%80%D0%B5%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_UAC.png&amp;diff=1871</id>
		<title>Файл:01 Предупреждение UAC.png</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:01_%D0%9F%D1%80%D0%B5%D0%B4%D1%83%D0%BF%D1%80%D0%B5%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_UAC.png&amp;diff=1871"/>
		<updated>2023-01-05T06:55:13Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;01 Предупреждение UAC&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1870</id>
		<title>Установка на Windows с использованием пакета XAMPP</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1870"/>
		<updated>2023-01-05T06:22:21Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
В процессе редактирования ...&lt;br /&gt;
Установка MajorDoMo на Windows 10 с использованием пакета XAMPP (кроссплатформенная сборка веб-сервера, содержащая Apache, MySQL, интерпретатор скриптов PHP, язык программирования Perl и большое количество дополнительных библиотек, позволяющих запустить полноценный веб-сервер). &lt;br /&gt;
Полноценное описание доступно на форуме в первом посте темы &amp;quot;Установка Мажордомо на XAMPP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Шаг первый: скачиваем и устанавливаем пакет XAMPP на ПК с Windows, ссылка на скачивание пакета с пхп 7.3.1 [https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.3.1/ XAMPP с PHP 7.3.1] &lt;br /&gt;
Устанавливаем на любой диск (у меня D). &lt;br /&gt;
&lt;br /&gt;
UAC у меня не включен, поэтому игнорирую предупреждение.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1823_image.png)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Отмечаем галочкой сервисы, которые планируете установить, у меня все отмечены, можно обойтись обязательными Apache, MySQL, PHP, phpMyAdmin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1824_image.png)&lt;br /&gt;
&lt;br /&gt;
Указываем путь для установки и выбираем из двух языков (больше нет) английский.&lt;br /&gt;
Нажимаем установить. После установки запускается панель управления XAMPP. &lt;br /&gt;
Закрываем её, нажатие на крестик не помогает, закрываем через диспетчер задач. &lt;br /&gt;
&lt;br /&gt;
После этого переходим к файлу xampp-control.exe в папке с установленным xampp и запускаем его от администратора.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1825_image.png)&lt;br /&gt;
&lt;br /&gt;
Переходим к  config в панели правый верхний угол, и устанавливаем  галочки на автостарте модулуй, как показано на скрине (Apache и MySQL). Без запуска от админа сохранения не применяются, отказ в доступе.&lt;br /&gt;
Что это значит – при запуске xampp, автоматически запускаются эти модули и не нужно в дальнейшем выполнять запуск в ручную. &lt;br /&gt;
Закрываем панель xampp, в том числе из систем трея. &lt;br /&gt;
Скачиваем файлы majordomo одним архивом, на примере из альфа ветки: &lt;br /&gt;
&lt;br /&gt;
[https://github.com/sergejey/majordomo/tree/alpha Файлы MajorDoMo Alpha ветка]&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1826_image.png)&lt;br /&gt;
Удаляем все файлы из папки / htdocs.  Распаковываем и копируем файлы Majordomo, в папку / htdocs, естественно не папкой majordomo-alpha а всем её содержимым.&lt;br /&gt;
&lt;br /&gt;
И еще надо положить папку apps из мажордомо в папку ХАМППа (корень) (папку miniRelay не смог загрузить, ругалась на вирусы)&lt;br /&gt;
[Ссылка на папку apps](https://disk.yandex.by/d/4Ui7Up_vZ1VYbA)&lt;br /&gt;
&lt;br /&gt;
Кроме того не хватает архиваторов, распаковываем в директорию httpdoc&lt;br /&gt;
[архиваторы](https://disk.yandex.by/d/E7QqMO-C7hYCOA)&lt;br /&gt;
&lt;br /&gt;
Запускаем *.exe файл с панелью XAMPP (xampp-control.exe), при этом сервисы апача и mySQL  стартуют автоматически и из браузера перейдём в панель управления phpmyadmin набрав адрес: [](http://127.0.0.1/phpmyadmin/).&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1827_image.png)&lt;br /&gt;
Импортируем базу данных MajorDoMo:&lt;br /&gt;
Нажимаем - создать БД&lt;br /&gt;
и в поле - имя базы - вписываем '''db_terminal'''.&lt;br /&gt;
В соседнем поле изменяем кодировку на '''utf8_general_ci'''.&lt;br /&gt;
Нажимаем кнопку '''Создать'''.&lt;br /&gt;
Теперь нажимем на созданный db_terminal и сверху жмем слово '''Импорт'''.&lt;br /&gt;
Выбираем файл db_terminal.sql (он находится в папке диск:\путь к хамп\htdocs)&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1828_image.png)&lt;br /&gt;
&lt;br /&gt;
и жмем слово Вперед.&lt;br /&gt;
&lt;br /&gt;
После импорта появится надпись об успешном окончании импортирования.&lt;br /&gt;
Заходим по адресу 127.0.0.1 - появляется стартовая страница, радоваться пока не спешим, нужно произвести некоторые настройки. Закрываем панель управления xamppa (в т.ч. и из систем трея).&lt;br /&gt;
Теперь мажордомо надо настроить.&lt;br /&gt;
Переименуем '''config.php.sample''' в '''config.php'''&lt;br /&gt;
И отредактируем пути в этом файле (config.php):&lt;br /&gt;
а именно - в этих строках&lt;br /&gt;
```&lt;br /&gt;
 Define('SERVER_ROOT', '/var/www');&lt;br /&gt;
 Define('PATH_TO_PHP', 'php');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;mysqldump&amp;quot;);&lt;br /&gt;
```&lt;br /&gt;
на следующее:&lt;br /&gt;
```&lt;br /&gt;
Define('SERVER_ROOT', 'диск:/путь к хамп');&lt;br /&gt;
 Define('PATH_TO_PHP', 'диск:/путь к хамп/php/php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;диск:/путь к хамп/mysql/bin/mysqldump.exe&amp;quot;);&lt;br /&gt;
```&lt;br /&gt;
в моем случае (корень диска D) вышло так:&lt;br /&gt;
```&lt;br /&gt;
 Define('SERVER_ROOT', 'd:/xampp');&lt;br /&gt;
 Define('PATH_TO_PHP', 'd:\xampp\php\php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', SERVER_ROOT.'/mysql/bin/mysqldump.exe');&lt;br /&gt;
 ```&lt;br /&gt;
Соответственно сохраняем этот файл после внесенных изменений.&lt;br /&gt;
Включаем в PHP сокеты в файле /php/php.ini &lt;br /&gt;
 ```&lt;br /&gt;
extension=sockets&lt;br /&gt;
 ```&lt;br /&gt;
Исправление простое - надо в пхп.ини вместо &lt;br /&gt;
;extension=sockets сделать extension=sockets (удалить символ ;)&lt;br /&gt;
&lt;br /&gt;
Напишем простой bat файл для запуска цикла и MajorDoMo  вместе с xampp. К примеру у меня mjdm start.bat , ресположен в папке /xampp&lt;br /&gt;
 Содержимое:&lt;br /&gt;
 ```&lt;br /&gt;
 start диск:\путь к хамп\xampp-control.exe &amp;gt;nul&lt;br /&gt;
диск:\путь к хамп\php\php.exe диск:\путь к хамп\htdocs\cycle.php&lt;br /&gt;
 ```&lt;br /&gt;
У меня:&lt;br /&gt;
 ```&lt;br /&gt;
start d:/xampp/xampp-control.exe &amp;gt;nul&lt;br /&gt;
rem Main system cycle start&lt;br /&gt;
:1&lt;br /&gt;
d:\xampp\php\php.exe d:\xampp\htdocs\cycle.php&lt;br /&gt;
goto 1&lt;br /&gt;
 ```&lt;br /&gt;
ТЕПЕРЬ ВСЕ&lt;br /&gt;
Запускаем Мажордомо этим батником&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ПОСЛЕ ЭТОГО ОБЯЗАТЕЛЬНЫЙ РЕБУТ КОМПА&lt;br /&gt;
&lt;br /&gt;
После перезагрузки Запускаем локальный сервер созданным bat-файлом (запуск рекомендую от администратора) заходим по адресу:&lt;br /&gt;
http://127.0.0.1/&lt;br /&gt;
Попадаем на начальную страницу настройки языка/времени:&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1829_image.png)&lt;br /&gt;
&lt;br /&gt;
Если страница не открылась, можем открыть набрав: http://127.0.0.1//popup/first_start.html.&lt;br /&gt;
После установки настроек переход на главную страницу majorDoMo.&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1830_image.png)&lt;br /&gt;
&lt;br /&gt;
Из папки scripts удаляем (переименоваем ненужные для  запуска скрипты, в моем случае: cycle_connect.php, cycle_mqtt.php cycle_yadevices.php cycle_zigbee2mqtt.php cycle_zigbeedev.php cycle_db_save.php &lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1837_image.png)&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1869</id>
		<title>Установка на Windows с использованием пакета XAMPP</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1869"/>
		<updated>2023-01-05T06:11:45Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
В процессе редактирования ...&lt;br /&gt;
Установка MajorDoMo на Windows 10 с использованием пакета XAMPP (кроссплатформенная сборка веб-сервера, содержащая Apache, MySQL, интерпретатор скриптов PHP, язык программирования Perl и большое количество дополнительных библиотек, позволяющих запустить полноценный веб-сервер). &lt;br /&gt;
Полноценное описание доступно на форуме в первом посте темы &amp;quot;Установка Мажордомо на XAMPP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Шаг первый: скачиваем и устанавливаем пакет XAMPP на ПК с Windows, ссылка на скачивание пакета с пхп 7.3.1 [https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.3.1/ XAMPP с PHP 7.3.1] &lt;br /&gt;
Устанавливаем на любой диск (у меня D). &lt;br /&gt;
&lt;br /&gt;
UAC у меня не включен, поэтому игнорирую предупреждение.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1823_image.png)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Отмечаем галочкой сервисы, которые планируете установить, у меня все отмечены, можно обойтись обязательными Apache, MySQL, PHP, phpMyAdmin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1824_image.png)&lt;br /&gt;
&lt;br /&gt;
Указываем путь для установки и выбираем из двух языков (больше нет) английский.&lt;br /&gt;
Нажимаем установить. После установки запускается панель управления XAMPP. &lt;br /&gt;
Закрываем её, нажатие на крестик не помогает, закрываем через диспетчер задач. &lt;br /&gt;
&lt;br /&gt;
После этого переходим к файлу xampp-control.exe в папке с установленным xampp и запускаем его от администратора.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1825_image.png)&lt;br /&gt;
&lt;br /&gt;
Переходим к  config в панели правый верхний угол, и устанавливаем  галочки на автостарте модулуй, как показано на скрине (Apache и MySQL). Без запуска от админа сохранения не применяются, отказ в доступе.&lt;br /&gt;
Что это значит – при запуске xampp, автоматически запускаются эти модули и не нужно в дальнейшем выполнять запуск в ручную. &lt;br /&gt;
Закрываем панель xampp, в том числе из систем трея. &lt;br /&gt;
Скачиваем файлы majordomo одним архивом, на примере из альфа ветки: &lt;br /&gt;
&lt;br /&gt;
[https://github.com/sergejey/majordomo/tree/alpha Файлы MajorDoMo Alpha ветка]&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1826_image.png)&lt;br /&gt;
Удаляем все файлы из папки / htdocs.  Распаковываем и копируем файлы Majordomo, в папку / htdocs, естественно не папкой majordomo-alpha а всем её содержимым.&lt;br /&gt;
И еще надо положить папку аппс из мажордомо в папку ХАМППа (корень) (папку miniRelay не смог загрузить, ругалась на вирусы)&lt;br /&gt;
[Ссылка на папку apps](https://disk.yandex.by/d/4Ui7Up_vZ1VYbA)&lt;br /&gt;
&lt;br /&gt;
Кроме того не хватает архиваторов, распаковываем в директорию httpdoc&lt;br /&gt;
[архиваторы](https://disk.yandex.by/d/E7QqMO-C7hYCOA)&lt;br /&gt;
&lt;br /&gt;
Запускаем екзешник с панелью XAMPP (xampp-control.exe), при этом сервисы апача и mySQL  стартуют автоматически и из браузера перейдём в панель управления phpmyadmin набрав адрес: [](http://127.0.0.1/phpmyadmin/).&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1827_image.png)&lt;br /&gt;
Импортируем базу данных MajorDoMo:&lt;br /&gt;
Нажимаем - создать БД&lt;br /&gt;
и в поле - имя базы - вписываем **db_terminal**&lt;br /&gt;
и в соседенем поле изменяем кодировку на **utf8_general_ci**&lt;br /&gt;
и нажимаем кнопку **Создать**.&lt;br /&gt;
Теперь жмем на созданный db_terminal и сверху жмем слово Импорт&lt;br /&gt;
Жмем Выберите файл и выбираем файл db_terminal.sql (он находится в папке диск:\путь к хамп\htdocs)&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1828_image.png)&lt;br /&gt;
и жмем слово Вперед.&lt;br /&gt;
После импорта появится надпись об успешном окончании импортирования.&lt;br /&gt;
Заходим по адресу 127.0.0.1 - появляется стартовая страница, радоваться пока не спешим, нужно произвести некоторые настройки. Закрываем панель управления xamppa (в т.ч. и из систем трея).&lt;br /&gt;
Теперь мажордомо надо настроить.&lt;br /&gt;
Переименуем config.php.sample в config.php&lt;br /&gt;
И отредактируем пути в этом файле (config.php)&lt;br /&gt;
а именно - в этих строках&lt;br /&gt;
```&lt;br /&gt;
 Define('SERVER_ROOT', '/var/www');&lt;br /&gt;
 Define('PATH_TO_PHP', 'php');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;mysqldump&amp;quot;);&lt;br /&gt;
```&lt;br /&gt;
на следующее:&lt;br /&gt;
```&lt;br /&gt;
Define('SERVER_ROOT', 'диск:/путь к хамп');&lt;br /&gt;
 Define('PATH_TO_PHP', 'диск:/путь к хамп/php/php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;диск:/путь к хамп/mysql/bin/mysqldump.exe&amp;quot;);&lt;br /&gt;
```&lt;br /&gt;
в моем случае (корень диска D) вышло так:&lt;br /&gt;
```&lt;br /&gt;
 Define('SERVER_ROOT', 'd:/xampp');&lt;br /&gt;
 Define('PATH_TO_PHP', 'd:\xampp\php\php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', SERVER_ROOT.'/mysql/bin/mysqldump.exe');&lt;br /&gt;
 ```&lt;br /&gt;
Соответственно сохраняем этот файл после внесенных изменений.&lt;br /&gt;
Включаем в PHP сокеты в файле /php/php.ini &lt;br /&gt;
 ```&lt;br /&gt;
extension=sockets&lt;br /&gt;
 ```&lt;br /&gt;
Исправление простое - надо в пхп.ини вместо &lt;br /&gt;
;extension=sockets сделать extension=sockets (удалить символ ;)&lt;br /&gt;
&lt;br /&gt;
Напишем простой bat файл для запуска цикла и MajorDoMo  вместе с xampp. К примеру у меня mjdm start.bat , ресположен в папке /xampp&lt;br /&gt;
 Содержимое:&lt;br /&gt;
 ```&lt;br /&gt;
 start диск:\путь к хамп\xampp-control.exe &amp;gt;nul&lt;br /&gt;
диск:\путь к хамп\php\php.exe диск:\путь к хамп\htdocs\cycle.php&lt;br /&gt;
 ```&lt;br /&gt;
У меня:&lt;br /&gt;
 ```&lt;br /&gt;
start d:/xampp/xampp-control.exe &amp;gt;nul&lt;br /&gt;
rem Main system cycle start&lt;br /&gt;
:1&lt;br /&gt;
d:\xampp\php\php.exe d:\xampp\htdocs\cycle.php&lt;br /&gt;
goto 1&lt;br /&gt;
 ```&lt;br /&gt;
ТЕПЕРЬ ВСЕ&lt;br /&gt;
Запускаем Мажордомо этим батником&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ПОСЛЕ ЭТОГО ОБЯЗАТЕЛЬНЫЙ РЕБУТ КОМПА&lt;br /&gt;
&lt;br /&gt;
После перезагрузки Запускаем локальный сервер созданным bat-файлом (запуск рекомендую от администратора) заходим по адресу:&lt;br /&gt;
http://127.0.0.1/&lt;br /&gt;
Попадаем на начальную страницу настройки языка/времени:&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1829_image.png)&lt;br /&gt;
Если страница не открылась, можем открыть набрав: http://127.0.0.1//popup/first_start.html.&lt;br /&gt;
После установки настроек переход на главную страницу majorDoMo.&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1830_image.png)&lt;br /&gt;
&lt;br /&gt;
Из папки scripts удаляем (переименоваем ненужные для  запуска скрипты, в моем случае: cycle_connect.php, cycle_mqtt.php cycle_yadevices.php cycle_zigbee2mqtt.php cycle_zigbeedev.php cycle_db_save.php &lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1837_image.png)&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Raspberry_Pi_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%BC_%D0%BE%D1%82_SergeJey&amp;diff=1867</id>
		<title>Установка на Raspberry Pi скриптом от SergeJey</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Raspberry_Pi_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%BC_%D0%BE%D1%82_SergeJey&amp;diff=1867"/>
		<updated>2023-01-04T17:34:21Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Vik Tam переименовал страницу Установка на Raspberry Pi скриптом от SerJey в Установка на Raspberry Pi скриптом от SergeJey&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
== Установка образа системы Raspbian OS == &lt;br /&gt;
Первым делом скачиваем установщик образа на карту памяти с официального сайта Raspberry&lt;br /&gt;
[https://www.raspberrypi.com/software/ официальный сайт Raspberry Pi]&lt;br /&gt;
&lt;br /&gt;
[[Файл:!Рисунок1.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
После скачивания запускаем скачанный файл  imager_1.7.3.exe. &lt;br /&gt;
И переходим к выбору Операционной системы.&lt;br /&gt;
[[Файл:!Рисунок2-1.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Сначала выбираем устанавливаемую систему, по умолчанию выделение на пункте с графической оболочкой. Т.к. в большинстве случаев оболочка не нужна и только потребляет итак небольшие ресурсы малины, выбираем другие (Raspberry PI OS (other).&lt;br /&gt;
[[Файл:!Рисунок2-2.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Далее из открывшихся вариантов выбираем установку без графического интерфейса (A port jf Debian Bulsseye with no desktop environment)&lt;br /&gt;
[[Файл:04 Без GUI.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Выбираем появившуюся карту памяти &lt;br /&gt;
Не спешим записывать образ (write)  переходим к окну настроек (иконка шестеренки в правом нижнем углу)&lt;br /&gt;
&lt;br /&gt;
[[Файл:05 Настройки записи.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
И устанавливаем свои необходимые значения.&lt;br /&gt;
&lt;br /&gt;
'''Рекомендую использовать стандартный логин для одноплатных компьютеров pi , т.к. в скрипте есть некоторые команды, связанные с этим логином.'''&lt;br /&gt;
&lt;br /&gt;
После этого можем нажать Write (запись).&lt;br /&gt;
Автоматически после окончания процедуры программа извлекает (размонтирует) карту памяти.&lt;br /&gt;
&lt;br /&gt;
Устанавливаем карточку в малинку и подключаем питание.&lt;br /&gt;
После включения довольно долго (минут пять) происходит процедура первого запуска, немного подождав подключаемся SSH клиентом к малинке и входим используя логин пароль, указанные при выставлении настроек. &lt;br /&gt;
Карта пямяти уже расширена.  &lt;br /&gt;
Можем посмотреть версию ОС:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /proc/version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
В ответ видим:&lt;br /&gt;
&amp;lt;pre&amp;gt; &amp;gt; Linux version 5.15.61-v7+ (dom@buildbot) (arm-linux-gnueabihf-gcc-8 (Ubuntu/Linaro 8.4.0-3ubuntu1) 8.4.0, GNU ld (GNU Binutils for Ubuntu) &lt;br /&gt;
   #1579 SMP Fri Aug 26 11:10:59 BST 2022&lt;br /&gt;
 PRETTY_NAME=&amp;quot;Raspbian GNU/Linux 11 (bullseye)&amp;quot; &lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
     &lt;br /&gt;
=== '''Установка системы Умного Дома MajorDoMo с помощью скрипта''' ===&lt;br /&gt;
Сейчас спокойно можем установить MajorDoMo и необходимые системные сервисы.&lt;br /&gt;
Входим в режим sudo &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo -i&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Вводим команду на скачивание и установку скрипта  [страница скрипта на Гитхабе](https://github.com/sergejey/majordomo-rpi-install):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -s https://raw.githubusercontent.com/sergejey/majordomo-rpi-install/main/install.sh | bash &amp;amp;&amp;amp; bash ~/majordomo-rpi-install/install.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Подождав непродолжительное время (необходимое для начальной установки нужных пакетов) получаем окно начала выполнения скрипта:&lt;br /&gt;
Вводим согласие '''y'''. &lt;br /&gt;
Отмечаем нужные опции установки как самой системы УД MajorDoMo, так и дополнительных системных сервисов:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Опции скрипта.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Далее идёт установка, около 40 минут процедура обновления системы upt-get update, upgrade на экране ничего не меняется, это нормально, далее идёт установка пакетов. Время довольно продолжительное, особенное RHvoice и Zigbee2mqtt, у меня заняло часа 3-4.&lt;br /&gt;
После начала установки никаких внешних действий ака ввода команд и т.д. не требуется. Поэтому можно установку начать вечером и спокойно идти спать,  что кстати я и делал.&lt;br /&gt;
В итоге скрипт отработал, появилось следующее окно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:07 Концовка скрипта.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Перезагрузка. После этого заходим на IP адрес нашей малины и видим стартовое окно выбора языка и тайм зоны:&lt;br /&gt;
&lt;br /&gt;
[[Файл:07-1 Концовка скрипта.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
После выбора необходимых параметров, переход на главную страницу MajorDoMo&lt;br /&gt;
&lt;br /&gt;
[[Файл:09 Главная страница.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Ну вот вкратце и всё, приятного пользования.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1866</id>
		<title>Установка на Windows с использованием пакета XAMPP</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Windows_%D1%81_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%BC_%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%B0_XAMPP&amp;diff=1866"/>
		<updated>2023-01-04T17:15:55Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Новая страница: «Category:Установка  В процессе редактирования ... Установка MajorDoMo на Windows 10 с использованием пакета XAMPP (кроссплатформенная сборка веб-сервера, содержащая Apache, MySQL, интерпретатор скриптов PHP, язык программирования Perl и большое количество дополнительных биб...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
В процессе редактирования ...&lt;br /&gt;
Установка MajorDoMo на Windows 10 с использованием пакета XAMPP (кроссплатформенная сборка веб-сервера, содержащая Apache, MySQL, интерпретатор скриптов PHP, язык программирования Perl и большое количество дополнительных библиотек, позволяющих запустить полноценный веб-сервер). &lt;br /&gt;
Полноценное описание доступно на форуме в первом посте темы &amp;quot;Установка Мажордомо на XAMPP&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Устанавливаю всё по инструкции от Тараса (спасибо ему за подробное описание) [Установка Мажордомо на XAMPP](http://mjdm.ru/forum/viewtopic.php?f=3&amp;amp;t=6388&amp;amp;sid=9be78415e23e83d4f9215c36f816b6b6#p102609 )Установка Мажордомо на XAMPP&lt;br /&gt;
Шаг первый: скачиваем и устанавливаем пакет XAMPP на ПК с Windows, ссылка на скачивание пакета с пхп 7.3.1 [Пакет XAMPP с PHP 7.3.1](https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.3.1/)&lt;br /&gt;
Устанавливаем на любой диск (у меня D). &lt;br /&gt;
UAC у меня не включен, поэтому игнорирую предупреждение.&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1823_image.png)&lt;br /&gt;
Отмечаем галочкой сервисы, которые планируете установить, у меня все отмечены, можно обойтись обязательными Apache, MySQL, PHP, phpMyAdmin.&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1824_image.png)&lt;br /&gt;
Указываем путь для установки и выбираем из двух языков (больше нет) английский.&lt;br /&gt;
Нажимаем установить. После установки запускается панель управления XAMPP. &lt;br /&gt;
Закрываем её, нажатие на крестик не помогает, закрываем через диспетчер задач. &lt;br /&gt;
После этого переходим к файлу xampp-control.exe в папке с установленным xampp и запускаем его от администратора.&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1825_image.png)&lt;br /&gt;
Переходим к  config в панели правый верхний угол, и устанавливаем  галочки на автостарте модулуй, как показано на скрине (Apache и MySQL). Без запуска от админа сохранения не применяются, отказ в доступе.&lt;br /&gt;
Что это значит – при запуске xampp, автоматически запускаются эти модули и не нужно в дальнейшем выполнять запуск в ручную. &lt;br /&gt;
Закрываем панель xampp, в том числе из систем трея. &lt;br /&gt;
Скачиваем файлы majordomo одним архивом, на примере из альфа ветки: https://github.com/sergejey/majordomo/tree/alpha&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1826_image.png)&lt;br /&gt;
Удаляем все файлы из папки / htdocs.  Распаковываем и копируем файлы Majordomo, в папку / htdocs, естественно не папкой majordomo-alpha а всем её содержимым.&lt;br /&gt;
И еще надо положить папку аппс из мажордомо в папку ХАМППа (корень) (папку miniRelay не смог загрузить, ругалась на вирусы)&lt;br /&gt;
[Ссылка на папку apps](https://disk.yandex.by/d/4Ui7Up_vZ1VYbA)&lt;br /&gt;
&lt;br /&gt;
Кроме того не хватает архиваторов, распаковываем в директорию httpdoc&lt;br /&gt;
[архиваторы](https://disk.yandex.by/d/E7QqMO-C7hYCOA)&lt;br /&gt;
&lt;br /&gt;
Запускаем екзешник с панелью XAMPP (xampp-control.exe), при этом сервисы апача и mySQL  стартуют автоматически и из браузера перейдём в панель управления phpmyadmin набрав адрес: [](http://127.0.0.1/phpmyadmin/).&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1827_image.png)&lt;br /&gt;
Импортируем базу данных MajorDoMo:&lt;br /&gt;
Нажимаем - создать БД&lt;br /&gt;
и в поле - имя базы - вписываем **db_terminal**&lt;br /&gt;
и в соседенем поле изменяем кодировку на **utf8_general_ci**&lt;br /&gt;
и нажимаем кнопку **Создать**.&lt;br /&gt;
Теперь жмем на созданный db_terminal и сверху жмем слово Импорт&lt;br /&gt;
Жмем Выберите файл и выбираем файл db_terminal.sql (он находится в папке диск:\путь к хамп\htdocs)&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1828_image.png)&lt;br /&gt;
и жмем слово Вперед.&lt;br /&gt;
После импорта появится надпись об успешном окончании импортирования.&lt;br /&gt;
Заходим по адресу 127.0.0.1 - появляется стартовая страница, радоваться пока не спешим, нужно произвести некоторые настройки. Закрываем панель управления xamppa (в т.ч. и из систем трея).&lt;br /&gt;
Теперь мажордомо надо настроить.&lt;br /&gt;
Переименуем config.php.sample в config.php&lt;br /&gt;
И отредактируем пути в этом файле (config.php)&lt;br /&gt;
а именно - в этих строках&lt;br /&gt;
```&lt;br /&gt;
 Define('SERVER_ROOT', '/var/www');&lt;br /&gt;
 Define('PATH_TO_PHP', 'php');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;mysqldump&amp;quot;);&lt;br /&gt;
```&lt;br /&gt;
на следующее:&lt;br /&gt;
```&lt;br /&gt;
Define('SERVER_ROOT', 'диск:/путь к хамп');&lt;br /&gt;
 Define('PATH_TO_PHP', 'диск:/путь к хамп/php/php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', &amp;quot;диск:/путь к хамп/mysql/bin/mysqldump.exe&amp;quot;);&lt;br /&gt;
```&lt;br /&gt;
в моем случае (корень диска D) вышло так:&lt;br /&gt;
```&lt;br /&gt;
 Define('SERVER_ROOT', 'd:/xampp');&lt;br /&gt;
 Define('PATH_TO_PHP', 'd:\xampp\php\php.exe');&lt;br /&gt;
 Define('PATH_TO_MYSQLDUMP', SERVER_ROOT.'/mysql/bin/mysqldump.exe');&lt;br /&gt;
 ```&lt;br /&gt;
Соответственно сохраняем этот файл после внесенных изменений.&lt;br /&gt;
Включаем в PHP сокеты в файле /php/php.ini &lt;br /&gt;
 ```&lt;br /&gt;
extension=sockets&lt;br /&gt;
 ```&lt;br /&gt;
Исправление простое - надо в пхп.ини вместо &lt;br /&gt;
;extension=sockets сделать extension=sockets (удалить символ ;)&lt;br /&gt;
&lt;br /&gt;
Напишем простой bat файл для запуска цикла и MajorDoMo  вместе с xampp. К примеру у меня mjdm start.bat , ресположен в папке /xampp&lt;br /&gt;
 Содержимое:&lt;br /&gt;
 ```&lt;br /&gt;
 start диск:\путь к хамп\xampp-control.exe &amp;gt;nul&lt;br /&gt;
диск:\путь к хамп\php\php.exe диск:\путь к хамп\htdocs\cycle.php&lt;br /&gt;
 ```&lt;br /&gt;
У меня:&lt;br /&gt;
 ```&lt;br /&gt;
start d:/xampp/xampp-control.exe &amp;gt;nul&lt;br /&gt;
rem Main system cycle start&lt;br /&gt;
:1&lt;br /&gt;
d:\xampp\php\php.exe d:\xampp\htdocs\cycle.php&lt;br /&gt;
goto 1&lt;br /&gt;
 ```&lt;br /&gt;
ТЕПЕРЬ ВСЕ&lt;br /&gt;
Запускаем Мажордомо этим батником&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ПОСЛЕ ЭТОГО ОБЯЗАТЕЛЬНЫЙ РЕБУТ КОМПА&lt;br /&gt;
&lt;br /&gt;
После перезагрузки Запускаем локальный сервер созданным bat-файлом (запуск рекомендую от администратора) заходим по адресу:&lt;br /&gt;
http://127.0.0.1/&lt;br /&gt;
Попадаем на начальную страницу настройки языка/времени:&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1829_image.png)&lt;br /&gt;
Если страница не открылась, можем открыть набрав: http://127.0.0.1//popup/first_start.html.&lt;br /&gt;
После установки настроек переход на главную страницу majorDoMo.&lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1830_image.png)&lt;br /&gt;
&lt;br /&gt;
Из папки scripts удаляем (переименоваем ненужные для  запуска скрипты, в моем случае: cycle_connect.php, cycle_mqtt.php cycle_yadevices.php cycle_zigbee2mqtt.php cycle_zigbeedev.php cycle_db_save.php &lt;br /&gt;
![](https://connect.smartliving.ru/cms/data_images/1837_image.png)&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Raspberry_Pi_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%BC_%D0%BE%D1%82_SergeJey&amp;diff=1865</id>
		<title>Установка на Raspberry Pi скриптом от SergeJey</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Raspberry_Pi_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%BC_%D0%BE%D1%82_SergeJey&amp;diff=1865"/>
		<updated>2023-01-04T17:11:40Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
== Установка образа системы Raspbian OS == &lt;br /&gt;
Первым делом скачиваем установщик образа на карту памяти с официального сайта Raspberry&lt;br /&gt;
[https://www.raspberrypi.com/software/ официальный сайт Raspberry Pi]&lt;br /&gt;
&lt;br /&gt;
[[Файл:!Рисунок1.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
После скачивания запускаем скачанный файл  imager_1.7.3.exe. &lt;br /&gt;
И переходим к выбору Операционной системы.&lt;br /&gt;
[[Файл:!Рисунок2-1.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Сначала выбираем устанавливаемую систему, по умолчанию выделение на пункте с графической оболочкой. Т.к. в большинстве случаев оболочка не нужна и только потребляет итак небольшие ресурсы малины, выбираем другие (Raspberry PI OS (other).&lt;br /&gt;
[[Файл:!Рисунок2-2.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Далее из открывшихся вариантов выбираем установку без графического интерфейса (A port jf Debian Bulsseye with no desktop environment)&lt;br /&gt;
[[Файл:04 Без GUI.png|600px|центр]]&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Выбираем появившуюся карту памяти &lt;br /&gt;
Не спешим записывать образ (write)  переходим к окну настроек (иконка шестеренки в правом нижнем углу)&lt;br /&gt;
&lt;br /&gt;
[[Файл:05 Настройки записи.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
И устанавливаем свои необходимые значения.&lt;br /&gt;
&lt;br /&gt;
'''Рекомендую использовать стандартный логин для одноплатных компьютеров pi , т.к. в скрипте есть некоторые команды, связанные с этим логином.'''&lt;br /&gt;
&lt;br /&gt;
После этого можем нажать Write (запись).&lt;br /&gt;
Автоматически после окончания процедуры программа извлекает (размонтирует) карту памяти.&lt;br /&gt;
&lt;br /&gt;
Устанавливаем карточку в малинку и подключаем питание.&lt;br /&gt;
После включения довольно долго (минут пять) происходит процедура первого запуска, немного подождав подключаемся SSH клиентом к малинке и входим используя логин пароль, указанные при выставлении настроек. &lt;br /&gt;
Карта пямяти уже расширена.  &lt;br /&gt;
Можем посмотреть версию ОС:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat /proc/version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
В ответ видим:&lt;br /&gt;
&amp;lt;pre&amp;gt; &amp;gt; Linux version 5.15.61-v7+ (dom@buildbot) (arm-linux-gnueabihf-gcc-8 (Ubuntu/Linaro 8.4.0-3ubuntu1) 8.4.0, GNU ld (GNU Binutils for Ubuntu) &lt;br /&gt;
   #1579 SMP Fri Aug 26 11:10:59 BST 2022&lt;br /&gt;
 PRETTY_NAME=&amp;quot;Raspbian GNU/Linux 11 (bullseye)&amp;quot; &lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
     &lt;br /&gt;
=== '''Установка системы Умного Дома MajorDoMo с помощью скрипта''' ===&lt;br /&gt;
Сейчас спокойно можем установить MajorDoMo и необходимые системные сервисы.&lt;br /&gt;
Входим в режим sudo &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo -i&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Вводим команду на скачивание и установку скрипта  [страница скрипта на Гитхабе](https://github.com/sergejey/majordomo-rpi-install):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -s https://raw.githubusercontent.com/sergejey/majordomo-rpi-install/main/install.sh | bash &amp;amp;&amp;amp; bash ~/majordomo-rpi-install/install.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Подождав непродолжительное время (необходимое для начальной установки нужных пакетов) получаем окно начала выполнения скрипта:&lt;br /&gt;
Вводим согласие '''y'''. &lt;br /&gt;
Отмечаем нужные опции установки как самой системы УД MajorDoMo, так и дополнительных системных сервисов:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Файл:06 Опции скрипта.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Далее идёт установка, около 40 минут процедура обновления системы upt-get update, upgrade на экране ничего не меняется, это нормально, далее идёт установка пакетов. Время довольно продолжительное, особенное RHvoice и Zigbee2mqtt, у меня заняло часа 3-4.&lt;br /&gt;
После начала установки никаких внешних действий ака ввода команд и т.д. не требуется. Поэтому можно установку начать вечером и спокойно идти спать,  что кстати я и делал.&lt;br /&gt;
В итоге скрипт отработал, появилось следующее окно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:07 Концовка скрипта.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Перезагрузка. После этого заходим на IP адрес нашей малины и видим стартовое окно выбора языка и тайм зоны:&lt;br /&gt;
&lt;br /&gt;
[[Файл:07-1 Концовка скрипта.png|600px|центр]] &lt;br /&gt;
&lt;br /&gt;
После выбора необходимых параметров, переход на главную страницу MajorDoMo&lt;br /&gt;
&lt;br /&gt;
[[Файл:09 Главная страница.png|600px|центр]]&lt;br /&gt;
&lt;br /&gt;
Ну вот вкратце и всё, приятного пользования.&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Raspberry_Pi_%D0%B1%D0%B0%D0%B7%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%B0&amp;diff=1864</id>
		<title>Установка на Raspberry Pi базового образа</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Raspberry_Pi_%D0%B1%D0%B0%D0%B7%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%B0&amp;diff=1864"/>
		<updated>2023-01-04T16:50:42Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: /* Общее */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
==Общее==&lt;br /&gt;
Установка MajorDomo на микрокомпьютер Raspberry Pi чрезвычайно проста! Достаточно распаковать образ на SD карту (16 gb), и у вас полностью настроенный и готовый к работе сервер для Умного Дома.&lt;br /&gt;
Базовый образ вы можете скачать на странице: [https://connect.smartliving.ru/tasks/20.html Базовый образ MajorDoMo для Raspberry]&lt;br /&gt;
https://connect.smartliving.ru/tasks/20.html&lt;br /&gt;
&lt;br /&gt;
==Инструкция:==&lt;br /&gt;
#[https://connect.smartliving.ru/tasks/20.html?utm_source=bazaznanii&amp;amp;utm_medium=link&amp;amp;utm_campaign=kakustanovitraspberri Скачать] образ диска. Это Raspbian с установленными Apache, MySQL, PHP и MajorDoMo.&lt;br /&gt;
#[http://sourceforge.net/projects/win32diskimager/ Скачать] программу Win32DiskImager.&lt;br /&gt;
#Распаковать образ.&lt;br /&gt;
#Распаковать Win32DiskImager.&lt;br /&gt;
#Вставить SD карту (16 gb, class 10 или выше) в картридер, подключить к USB (если картридер внешний)&lt;br /&gt;
#Запустить от имени Администратора Win32DiskImager.exe.&lt;br /&gt;
#Выбрать Image File.&lt;br /&gt;
#Выбрать Device.&lt;br /&gt;
#Нажать кнопку Write. Дождаться сообщения о завершения процесса заливки образа Write Successful.&lt;br /&gt;
#Вставить SD карту в Raspberry Pi.&lt;br /&gt;
&lt;br /&gt;
Поздравляем! У вас установлен сервер MajorDoMo.&lt;br /&gt;
&lt;br /&gt;
Войти можно набрав браузере:&lt;br /&gt;
http://IP_адрес_Raspberry_Pi&lt;br /&gt;
&lt;br /&gt;
В случае успешной установки, система голосом сообщит свой IP-адрес по окончанию загрузки.&lt;br /&gt;
==Особенности и возможности==&lt;br /&gt;
&lt;br /&gt;
*Оптимизация циклов записи базы данных на карту памяти&lt;br /&gt;
*Голосовой движок RHVoice&lt;br /&gt;
*Звук через сервис MPD&lt;br /&gt;
*MQTT-брокер Mosquitto&lt;br /&gt;
*Сервис мониторинга производительности Netdata&lt;br /&gt;
*Apple HomeKit-совместимость (через HomeBridge)&lt;br /&gt;
*Установленные средства разработки: PHP, Python, NodeJS, Perl&lt;br /&gt;
*Последние обновления MajorDoMo и Raspbian (на момент релиза текущей версии)&lt;br /&gt;
*Работает установка дополнений из Маркета, а так же обновления ядра системы&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==SSH/sFTP==&lt;br /&gt;
Login: pi&lt;br /&gt;
&lt;br /&gt;
Password: raspberrymj (либо raspberry)&lt;br /&gt;
&lt;br /&gt;
(для безопасности рекомендуется изменить)&lt;br /&gt;
&lt;br /&gt;
==MySQL==&lt;br /&gt;
&lt;br /&gt;
Login: root/ rootpsw&lt;br /&gt;
&lt;br /&gt;
Password: mysqlserver/ без пароля&lt;br /&gt;
&lt;br /&gt;
(для безопасности рекомендуется изменить и внести изменения в файл /var/www/html/config.php)&lt;br /&gt;
&lt;br /&gt;
==MQTT-брокер==&lt;br /&gt;
без пароля (по IP-адресу сервера)&lt;br /&gt;
&lt;br /&gt;
==Дополнительная настройка:==&lt;br /&gt;
''Расширить образ на всю SD карту'': &amp;lt;pre&amp;gt;sudo raspi-config&amp;lt;/pre&amp;gt; &lt;br /&gt;
Выбрать в меню пункт expand_rootfs Expand root partition to fill SD card.&lt;br /&gt;
&lt;br /&gt;
''Выбор часового пояса''&lt;br /&gt;
&lt;br /&gt;
В Raspberry Pi нет своих часов, поэтому время берется из Интернета. Для выбора своего часового пояса в raspi-config нужно выбрать п.4 Localisation Options / Change Timezone&lt;br /&gt;
&lt;br /&gt;
''Выполнить обновление MajorDoMo через веб-интерфейс'': Панель управления / Резерв. копия / Update to the latest code.&lt;br /&gt;
&lt;br /&gt;
В дальнейшем можно произвести более тонкую настройку компонентов системы.&lt;br /&gt;
&lt;br /&gt;
==Дополнительно==&lt;br /&gt;
Ещё один вариант образа для Raspberry Pi B+ можно скачать [http://smartliving.ru/forum/viewtopic.php?f=3&amp;amp;t=2051 здесь] (образ отличается оптимизацией циклов записи на SD-карту)&lt;br /&gt;
&lt;br /&gt;
Образ для Raspberry Pi 2 можно скачать [http://smartliving.ru/forum/viewtopic.php?f=3&amp;amp;t=2212 здесь]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;9vg9YHcdma8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[installmd|Вариант установки на Raspberry Pi скриптом installmd]]&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Raspberry&amp;diff=1863</id>
		<title>Установка на Raspberry</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BD%D0%B0_Raspberry&amp;diff=1863"/>
		<updated>2023-01-04T16:48:28Z</updated>

		<summary type="html">&lt;p&gt;Vik Tam: Vik Tam переименовал страницу Установка на Raspberry в Установка на Raspberry Pi базового образа&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#перенаправление [[Установка на Raspberry Pi базового образа]]&lt;/div&gt;</summary>
		<author><name>Vik Tam</name></author>
	</entry>
</feed>