<?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=Mixman</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=Mixman"/>
	<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/Mixman"/>
	<updated>2026-06-02T09:44:37Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.38.4</generator>
	<entry>
		<id>https://mdminfo.ru/index.php?title=RemoveLinkedProperty&amp;diff=2140</id>
		<title>RemoveLinkedProperty</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=RemoveLinkedProperty&amp;diff=2140"/>
		<updated>2025-01-18T10:49:06Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Примеры запросов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''removeLinkedProperty'''($object, $property, $module); -- Summary of removeLinkedProperty&lt;br /&gt;
@param mixed $object Object&lt;br /&gt;
@param mixed $property Property&lt;br /&gt;
@param mixed $module Module&lt;br /&gt;
@return int&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
&lt;br /&gt;
removeLinkedProperty(объект, свойство, zigbee2mqtt);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
пример ниже чистит связи, которые остались после удаления модуля &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$query = &amp;quot;SELECT `PROPERTY_NAME`,`LINKED_MODULES` FROM `pvalues` WHERE `LINKED_MODULES` LIKE '%zigbee2mqtt%' ORDER BY `UPDATED` DESC;&amp;quot;;&lt;br /&gt;
$res = SQLSelect($query,$ignore_errors = false); &lt;br /&gt;
//print_r($res);&lt;br /&gt;
&lt;br /&gt;
foreach($res as $obj){&lt;br /&gt;
   $obj_prop = explode(&amp;quot;.&amp;quot;, $obj['PROPERTY_NAME']);&lt;br /&gt;
   //echo $obj_prop[0] . &amp;quot; &amp;quot; . $obj_prop[1] . &amp;quot; = &amp;quot;;&lt;br /&gt;
&lt;br /&gt;
   removelinkedproperty( $obj_prop[0], $obj_prop[1], &amp;quot;zigbee2mqtt&amp;quot; ); //zigbee2mqtt&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
linked&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=RemoveLinkedProperty&amp;diff=2139</id>
		<title>RemoveLinkedProperty</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=RemoveLinkedProperty&amp;diff=2139"/>
		<updated>2025-01-18T10:48:45Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Примеры запросов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''removeLinkedProperty'''($object, $property, $module); -- Summary of removeLinkedProperty&lt;br /&gt;
@param mixed $object Object&lt;br /&gt;
@param mixed $property Property&lt;br /&gt;
@param mixed $module Module&lt;br /&gt;
@return int&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
&lt;br /&gt;
removeLinkedProperty(объект, свойство, zigbee2mqtt);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
пример ниже чистит связи, которые остались после удаления модуля &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$query = &amp;quot;SELECT `PROPERTY_NAME`,`LINKED_MODULES` FROM `pvalues` WHERE `LINKED_MODULES` LIKE '%zigbee2mqtt%' ORDER BY `UPDATED` DESC;&amp;quot;;&lt;br /&gt;
$res = SQLSelect($query,$ignore_errors = false); &lt;br /&gt;
//print_r($res);&lt;br /&gt;
&lt;br /&gt;
foreach($res as $obj){&lt;br /&gt;
   $obj_prop = explode(&amp;quot;.&amp;quot;, $obj['PROPERTY_NAME']);&lt;br /&gt;
   //echo $obj_prop[0] . &amp;quot; &amp;quot; . $obj_prop[1] . &amp;quot; = &amp;quot;;&lt;br /&gt;
&lt;br /&gt;
   removelinkedproperty( $obj_prop[0], $obj_prop[1], &amp;quot;zigbee2mqtt&amp;quot; ); //zigbee2mqtt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
linked&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=RemoveLinkedProperty&amp;diff=2138</id>
		<title>RemoveLinkedProperty</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=RemoveLinkedProperty&amp;diff=2138"/>
		<updated>2025-01-18T10:48:14Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Примеры запросов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''removeLinkedProperty'''($object, $property, $module); -- Summary of removeLinkedProperty&lt;br /&gt;
@param mixed $object Object&lt;br /&gt;
@param mixed $property Property&lt;br /&gt;
@param mixed $module Module&lt;br /&gt;
@return int&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
&lt;br /&gt;
removeLinkedProperty(объект, свойство, zigbee2mqtt);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
пример ниже чистит связи, которые остались после удаления модуля &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$query = &amp;quot;SELECT `PROPERTY_NAME`,`LINKED_MODULES` FROM `pvalues` WHERE `LINKED_MODULES` LIKE '%zigbee2mqtt%' ORDER BY `UPDATED` DESC;&amp;quot;;&lt;br /&gt;
$res = SQLSelect($query,$ignore_errors = false); &lt;br /&gt;
//print_r($res);&lt;br /&gt;
&lt;br /&gt;
foreach($res as $obj){&lt;br /&gt;
$obj_prop = explode(&amp;quot;.&amp;quot;, $obj['PROPERTY_NAME']);&lt;br /&gt;
//echo $obj_prop[0] . &amp;quot; &amp;quot; . $obj_prop[1] . &amp;quot; = &amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
removelinkedproperty( $obj_prop[0], $obj_prop[1], &amp;quot;zigbee2mqtt&amp;quot; ); //zigbee2mqtt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
linked&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Removelinkedpropertyifnotused&amp;diff=2137</id>
		<title>Removelinkedpropertyifnotused</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Removelinkedpropertyifnotused&amp;diff=2137"/>
		<updated>2025-01-18T10:46:25Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример ниже чистит свойства от несуществующих связей в mqtt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$query = &amp;quot;SELECT `PROPERTY_NAME`,`LINKED_MODULES` FROM `pvalues` WHERE `LINKED_MODULES` LIKE '%mqtt%' ORDER BY `UPDATED` DESC;&amp;quot;;&lt;br /&gt;
$res = SQLSelect($query,$ignore_errors = false); &lt;br /&gt;
//print_r($res);&lt;br /&gt;
&lt;br /&gt;
foreach($res as $obj){&lt;br /&gt;
$obj_prop = explode(&amp;quot;.&amp;quot;, $obj['PROPERTY_NAME']);&lt;br /&gt;
//echo $obj_prop[0] . &amp;quot; &amp;quot; . $obj_prop[1] . &amp;quot; = &amp;quot;;&lt;br /&gt;
&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, $obj_prop[0], $obj_prop[1], &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2136</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2136"/>
		<updated>2025-01-18T10:15:55Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Addlinkedproperty ===&lt;br /&gt;
Добавление ссылки, [[Addlinkedproperty|подробнее]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
Удаление неиспользуемой ссылки, [[Removelinkedpropertyifnotused|подробнее]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
Удаление связей в модуле [[RemoveLinkedProperty|подробнее]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===     ===&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2135</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2135"/>
		<updated>2025-01-18T10:15:34Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Removelinkedpropertyifnotused */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Addlinkedproperty ===&lt;br /&gt;
Добавление ссылки, подробнее [[Addlinkedproperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
Удаление неиспользуемой ссылки, [[Removelinkedpropertyifnotused|подробнее]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
Удаление связей в модуле [[RemoveLinkedProperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===     ===&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2134</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2134"/>
		<updated>2025-01-18T10:14:18Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Addlinkedproperty ===&lt;br /&gt;
Добавление ссылки, подробнее [[Addlinkedproperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
Удаление неиспользуемой ссылки, подробнее[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
Удаление связей в модуле [[RemoveLinkedProperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===     ===&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2133</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2133"/>
		<updated>2025-01-18T10:14:03Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* RemoveLinkedProperty */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Addlinkedproperty ===&lt;br /&gt;
Добавление ссылки, подробнее [[Addlinkedproperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
Удаление неиспользуемой ссылки, подробнее[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
Удаление связей в модуле [[RemoveLinkedProperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== текст ===&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2132</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2132"/>
		<updated>2025-01-18T10:09:03Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Removelinkedpropertyifnotused */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Addlinkedproperty ===&lt;br /&gt;
Добавление ссылки, подробнее [[Addlinkedproperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
Удаление неиспользуемой ссылки, подробнее[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
[[RemoveLinkedProperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== текст ===&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2131</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2131"/>
		<updated>2025-01-18T10:08:23Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Addlinkedproperty */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Addlinkedproperty ===&lt;br /&gt;
Добавление ссылки, подробнее [[Addlinkedproperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
[[RemoveLinkedProperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== текст ===&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2130</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2130"/>
		<updated>2025-01-18T10:07:51Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* addlinkedproperty */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Addlinkedproperty ===&lt;br /&gt;
[[Addlinkedproperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
[[RemoveLinkedProperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== текст ===&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2129</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2129"/>
		<updated>2025-01-18T10:07:29Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== addlinkedproperty ===&lt;br /&gt;
[[Addlinkedproperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
[[RemoveLinkedProperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== текст ===&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2128</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2128"/>
		<updated>2025-01-18T10:06:45Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== addlinkedproperty ===&lt;br /&gt;
[[Addlinkedproperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removelinkedpropertyifnotused ===&lt;br /&gt;
[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RemoveLinkedProperty ===&lt;br /&gt;
[[RemoveLinkedProperty]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2127</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2127"/>
		<updated>2025-01-18T10:04:45Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[RemoveLinkedProperty]]&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2126</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2126"/>
		<updated>2025-01-18T10:04:08Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[removelinkedpropertyifnotused]]&lt;br /&gt;
[[Removelinkedpropertyifnotused]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[RemoveLinkedProperty]]&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Removelinkedpropertyifnotused&amp;diff=2125</id>
		<title>Removelinkedpropertyifnotused</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Removelinkedpropertyifnotused&amp;diff=2125"/>
		<updated>2025-01-18T10:02:18Z</updated>

		<summary type="html">&lt;p&gt;Mixman: Новая страница: «Category:Встроенные функции &amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;  пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt) &amp;lt;pre&amp;gt; removelinkedpropertyifnotused ( &amp;quot;m...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2124</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2124"/>
		<updated>2025-01-18T10:00:19Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
пример проверяет в таблице mqtt наличие связи с объектом, и если ее нет, то удаляет у свойства объекта  (таблица pvalues) связь с модулем mqtt (последний аргумент mqtt)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
removelinkedpropertyifnotused ( &amp;quot;mqtt&amp;quot;, &amp;quot;SvetLunaChildren&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;mqtt&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module );&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2123</id>
		<title>Связи</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A1%D0%B2%D1%8F%D0%B7%D0%B8&amp;diff=2123"/>
		<updated>2025-01-18T09:34:33Z</updated>

		<summary type="html">&lt;p&gt;Mixman: Новая страница: «[39] =&amp;gt; addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module )  [40] =&amp;gt; removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module )  [41] =&amp;gt; removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module )»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[39] =&amp;gt; addlinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module )&lt;br /&gt;
&lt;br /&gt;
[40] =&amp;gt; removelinkedpropertyifnotused ( &amp;amp;table_name, &amp;amp;object, &amp;amp;property, &amp;amp;module )&lt;br /&gt;
&lt;br /&gt;
[41] =&amp;gt; removelinkedproperty ( &amp;amp;object, &amp;amp;property, &amp;amp;module )&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=PHP_cURL_%D0%BD%D0%B0_Windows&amp;diff=2120</id>
		<title>PHP cURL на Windows</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=PHP_cURL_%D0%BD%D0%B0_Windows&amp;diff=2120"/>
		<updated>2024-12-13T06:56:15Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Как заставить работать библиотеку cURL на Windows */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Возникающие ошибки]]&lt;br /&gt;
&lt;br /&gt;
==PHP cURL на Windows и штатной установке== &lt;br /&gt;
===Как заставить работать библиотеку cURL на Windows===&lt;br /&gt;
&lt;br /&gt;
Выяснилось тут намедни, что в штатном установщике на Windows (это который 18 года), не работает библиотека PHP cURL. Полез разбираться и оказалось все очень просто и прозаично. За прошедшие 5 лет в мире почти не осталось сайтов, работающих по http, а для httpS, как известно, нужен сертификат. Так вот, тот самый сертификат в установщике и отсутствовал. &lt;br /&gt;
Что делаем: &lt;br /&gt;
# Качаем сертификат отсюдова: https://curl.se/docs/caextract.html, закидываем куда-нибудь, например в c:_majordomo\server\php\ext\  &lt;br /&gt;
# Прописываем в файле php.ini путь до сертификата в этой секции:  &lt;br /&gt;
# [curl]&lt;br /&gt;
# A default value for the CURLOPT_CAINFO option. This is required to be an absolute path.  &lt;br /&gt;
# curl.cainfo = c:\_majordomo\server\php\ext\cacert.pem  &lt;br /&gt;
# ) &lt;br /&gt;
Решение:  Правим файл по пути c:_majordomo\server\config_tpl\ - именно им и заменяется основной файл при перезапуске, перезапускаем MDM (кто умеет) или комп (все остальные), и радуемся работе модулей, которые используют cURL. &lt;br /&gt;
 &lt;br /&gt;
Обязательно в файле ищем именно строчку CURL и вместо нее вставляем&lt;/div&gt;</summary>
		<author><name>Mixman</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&amp;diff=2119</id>
		<title>Установка на Windows</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&amp;diff=2119"/>
		<updated>2024-12-13T06:54:17Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
==Описание==&lt;br /&gt;
[http://majordomo.smartliving.ru/download/setup_majordomo_120b.exe Установщик. Версия 1.2.0b от 28.02.2018 (полная, ~100Mb)]&lt;br /&gt;
&lt;br /&gt;
Для корректной работы системы в '''Windows XP''' обязательно наличие установленных '''Microsoft Visual C++ Runtime'''&lt;br /&gt;
&lt;br /&gt;
В процессе установки будет предложено обновление MajorDoMo до самой последней версии компонентов.&lt;br /&gt;
&lt;br /&gt;
''В нижеприведенном видео мы можете увидеть процесс установки MajorDoMo на Windows.''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;wrD1Z-ZrhhQ&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==Установка==&lt;br /&gt;
Для установки под windows-систему достаточно скачать установочный пакет, и запустить exe-файл. В процессе установки будет запрашиваться путь, однако на данный момент его рекомендуется оставить предложенным (c:\_majordomo), т.к. в коде в нескольких местах он жёстко указан. Система будет запущена и при установке в другое место, но тогда надо будет пройтись поиском по файлам и заменить строчку c:\_majordomo на новый путь.&lt;br /&gt;
&lt;br /&gt;
После установки будет предложено запустить приложение, либо его можно будет запустить позже через ярлык в стартовом меню Windows.&lt;br /&gt;
&lt;br /&gt;
==PHP cURL на Windows и штатной установке. Как заставить работать библиотеку cURL на Windows==&lt;br /&gt;
&lt;br /&gt;
[[PHP cURL на Windows]]&lt;br /&gt;
&lt;br /&gt;
==Альтеранативная установка==&lt;br /&gt;
Альтеранативный вариант установки описан на форуме - https://mjdm.ru/forum/viewtopic.php?f=3&amp;amp;t=6388&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Запуск==&lt;br /&gt;
При запуске приложения осуществляется последовательность команд, описанная в файле c:\_majordomo\start.bat . Этот файл можно модифицировать, чтобы запускать какие-то свои сервисы.&lt;br /&gt;
&lt;br /&gt;
По-умолчанию идёт запуск следующих компонент:&lt;br /&gt;
&lt;br /&gt;
1 Пакет server2go (apache+mysql+php)&lt;br /&gt;
&lt;br /&gt;
2 Приложение USBDeview.exe (слежение за подключаемыми USB-устройствами)&lt;br /&gt;
&lt;br /&gt;
3 Основной скрипт системы cycle.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#ff0000&amp;quot;&amp;gt;Важно:&amp;lt;/span&amp;gt; Пакет server2go пытается запуститься как стандартный веб-сервер на 80-ом порту, но если он занят, то будет автоматически использован альтернативный порт, что не хорошо, т.к. остальные компоненты системы рассчитаны на работу на стандартном порту. Проблема с 80-м портом может быть только в том случае, если он занят другим приложением -- такое часто случается из-за запущенного Skype-а, который так же использует 80-ый порт для своих нужд. Чтобы такого не происходило, нужно в настройках Skype отключить опцию &amp;quot;Use port 80 and 443 as alternatives for incoming connections&amp;quot; (раздел Advanced -&amp;gt; Connection).&lt;br /&gt;
&lt;br /&gt;
Корректность запуска можно (и нужно) проверить открыв в браузере ссылку http://localhost/ -- должна открыться стартовая страница сервиса. Если всё установилось правильно, то поздравляю -- вы стали счастливым обладателем системы MajorDoMo 🙂&lt;br /&gt;
&lt;br /&gt;
Важно проверить на компьютере на котором работает система, что по адресу http://localhost/ и http://127.0.0.1/ она открывается. Иначе некоторые сервисы могут не работать.&lt;br /&gt;
Доступ к системе осуществляется по адресу http://[адрес компьютера]/, с мобильного телефона по адресу http://[адрес компьютера]/menu.html&lt;br /&gt;
В дальнейшем можно произвести более тонкую настройку компонентов системы.&lt;br /&gt;
&lt;br /&gt;
Имя пользователя/пароль для входа в настройки системы: admin / admin&lt;br /&gt;
&lt;br /&gt;
==Дополнительно==&lt;br /&gt;
Дополнительно: В файле start.bat закомментировано несколько встроенных приложений, которые можно раскомментировать при необходимости:&lt;br /&gt;
&lt;br /&gt;
*neutron.exe -- синхронизация времени по атомным часам&lt;br /&gt;
&lt;br /&gt;
*batteryrun.exe -- реакция на тип питания компьютера (от батареии или от сети)&lt;br /&gt;
&lt;br /&gt;
*USBDeview.exe -- реакция на подключаемые USB-устройства&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=PHP_cURL_%D0%BD%D0%B0_Windows&amp;diff=2118</id>
		<title>PHP cURL на Windows</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=PHP_cURL_%D0%BD%D0%B0_Windows&amp;diff=2118"/>
		<updated>2024-12-13T06:52:08Z</updated>

		<summary type="html">&lt;p&gt;Mixman: Новая страница: «Category:Возникающие ошибки  ==PHP cURL на Windows и штатной установке==  ===Как заставить работать библиотеку cURL на Windows===  Выяснилось тут намедни, что в штатном установщике на Windows (это который 18 года), не работает библиотека PHP cURL. Полез разбираться и оказалось все...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Возникающие ошибки]]&lt;br /&gt;
&lt;br /&gt;
==PHP cURL на Windows и штатной установке== &lt;br /&gt;
===Как заставить работать библиотеку cURL на Windows===&lt;br /&gt;
&lt;br /&gt;
Выяснилось тут намедни, что в штатном установщике на Windows (это который 18 года), не работает библиотека PHP cURL. Полез разбираться и оказалось все очень просто и прозаично. За прошедшие 5 лет в мире почти не осталось сайтов, работающих по http, а для httpS, как известно, нужен сертификат. Так вот, тот самый сертификат в установщике и отсутствовал. &lt;br /&gt;
Что делаем: &lt;br /&gt;
1. Качаем сертификат отсюдова: https://curl.se/docs/caextract.html, закидываем куда-нибудь, например в c:_majordomo\server\php\ext\ &lt;br /&gt;
2. Прописываем в файле php.ini путь до сертификата в этой секции: &lt;br /&gt;
3. [curl] &lt;br /&gt;
4. ; A default value for the CURLOPT_CAINFO option. This is required to be an &lt;br /&gt;
5. ; absolute path. &lt;br /&gt;
curl.cainfo = c:\_majordomo\server\php\ext\cacert.pem &lt;br /&gt;
) &lt;br /&gt;
Решение:  Правим файл по пути c:_majordomo\server\config_tpl\ - именно им и заменяется основной файл при перезапуске, перезапускаем MDM (кто умеет) или комп (все остальные), и радуемся работе модулей, которые используют cURL. &lt;br /&gt;
 &lt;br /&gt;
Обязательно в файле ищем именно строчку CURL и вместо нее вставляем&lt;/div&gt;</summary>
		<author><name>Mixman</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&amp;diff=2117</id>
		<title>Установка на Windows</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&amp;diff=2117"/>
		<updated>2024-12-13T06:46:55Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Установка]]&lt;br /&gt;
&lt;br /&gt;
==Описание==&lt;br /&gt;
[http://majordomo.smartliving.ru/download/setup_majordomo_120b.exe Установщик. Версия 1.2.0b от 28.02.2018 (полная, ~100Mb)]&lt;br /&gt;
&lt;br /&gt;
Для корректной работы системы в '''Windows XP''' обязательно наличие установленных '''Microsoft Visual C++ Runtime'''&lt;br /&gt;
&lt;br /&gt;
В процессе установки будет предложено обновление MajorDoMo до самой последней версии компонентов.&lt;br /&gt;
&lt;br /&gt;
''В нижеприведенном видео мы можете увидеть процесс установки MajorDoMo на Windows.''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;wrD1Z-ZrhhQ&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==Установка==&lt;br /&gt;
Для установки под windows-систему достаточно скачать установочный пакет, и запустить exe-файл. В процессе установки будет запрашиваться путь, однако на данный момент его рекомендуется оставить предложенным (c:\_majordomo), т.к. в коде в нескольких местах он жёстко указан. Система будет запущена и при установке в другое место, но тогда надо будет пройтись поиском по файлам и заменить строчку c:\_majordomo на новый путь.&lt;br /&gt;
&lt;br /&gt;
После установки будет предложено запустить приложение, либо его можно будет запустить позже через ярлык в стартовом меню Windows.&lt;br /&gt;
&lt;br /&gt;
==PHP cURL на Windows и штатной установке. Как заставить работать библиотеку cURL на Windows==&lt;br /&gt;
Выяснилось тут намедни, что в штатном установщике на Windows (это который 18 года), не работает библиотека PHP cURL. Полез разбираться и оказалось все очень просто и прозаично. За прошедшие 5 лет в мире почти не осталось сайтов, работающих по http, а для httpS, как известно, нужен сертификат. Так вот, тот самый сертификат в установщике и отсутствовал. &lt;br /&gt;
Что делаем: &lt;br /&gt;
1. Качаем сертификат отсюдова: https://curl.se/docs/caextract.html, закидываем куда-нибудь, например в c:_majordomo\server\php\ext\ &lt;br /&gt;
2. Прописываем в файле php.ini путь до сертификата в этой секции: &lt;br /&gt;
3. [curl] &lt;br /&gt;
4. ; A default value for the CURLOPT_CAINFO option. This is required to be an &lt;br /&gt;
5. ; absolute path. &lt;br /&gt;
curl.cainfo = c:\_majordomo\server\php\ext\cacert.pem &lt;br /&gt;
) &lt;br /&gt;
Решение:  Правим файл по пути c:_majordomo\server\config_tpl\ - именно им и заменяется основной файл при перезапуске, перезапускаем MDM (кто умеет) или комп (все остальные), и радуемся работе модулей, которые используют cURL. &lt;br /&gt;
 &lt;br /&gt;
Обязательно в файле ищем именно строчку CURL и вместо нее вставляем&lt;br /&gt;
&lt;br /&gt;
==Альтеранативная установка==&lt;br /&gt;
Альтеранативный вариант установки описан на форуме - https://mjdm.ru/forum/viewtopic.php?f=3&amp;amp;t=6388&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Запуск==&lt;br /&gt;
При запуске приложения осуществляется последовательность команд, описанная в файле c:\_majordomo\start.bat . Этот файл можно модифицировать, чтобы запускать какие-то свои сервисы.&lt;br /&gt;
&lt;br /&gt;
По-умолчанию идёт запуск следующих компонент:&lt;br /&gt;
&lt;br /&gt;
1 Пакет server2go (apache+mysql+php)&lt;br /&gt;
&lt;br /&gt;
2 Приложение USBDeview.exe (слежение за подключаемыми USB-устройствами)&lt;br /&gt;
&lt;br /&gt;
3 Основной скрипт системы cycle.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#ff0000&amp;quot;&amp;gt;Важно:&amp;lt;/span&amp;gt; Пакет server2go пытается запуститься как стандартный веб-сервер на 80-ом порту, но если он занят, то будет автоматически использован альтернативный порт, что не хорошо, т.к. остальные компоненты системы рассчитаны на работу на стандартном порту. Проблема с 80-м портом может быть только в том случае, если он занят другим приложением -- такое часто случается из-за запущенного Skype-а, который так же использует 80-ый порт для своих нужд. Чтобы такого не происходило, нужно в настройках Skype отключить опцию &amp;quot;Use port 80 and 443 as alternatives for incoming connections&amp;quot; (раздел Advanced -&amp;gt; Connection).&lt;br /&gt;
&lt;br /&gt;
Корректность запуска можно (и нужно) проверить открыв в браузере ссылку http://localhost/ -- должна открыться стартовая страница сервиса. Если всё установилось правильно, то поздравляю -- вы стали счастливым обладателем системы MajorDoMo 🙂&lt;br /&gt;
&lt;br /&gt;
Важно проверить на компьютере на котором работает система, что по адресу http://localhost/ и http://127.0.0.1/ она открывается. Иначе некоторые сервисы могут не работать.&lt;br /&gt;
Доступ к системе осуществляется по адресу http://[адрес компьютера]/, с мобильного телефона по адресу http://[адрес компьютера]/menu.html&lt;br /&gt;
В дальнейшем можно произвести более тонкую настройку компонентов системы.&lt;br /&gt;
&lt;br /&gt;
Имя пользователя/пароль для входа в настройки системы: admin / admin&lt;br /&gt;
&lt;br /&gt;
==Дополнительно==&lt;br /&gt;
Дополнительно: В файле start.bat закомментировано несколько встроенных приложений, которые можно раскомментировать при необходимости:&lt;br /&gt;
&lt;br /&gt;
*neutron.exe -- синхронизация времени по атомным часам&lt;br /&gt;
&lt;br /&gt;
*batteryrun.exe -- реакция на тип питания компьютера (от батареии или от сети)&lt;br /&gt;
&lt;br /&gt;
*USBDeview.exe -- реакция на подключаемые USB-устройства&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=SetGlobal&amp;diff=2116</id>
		<title>SetGlobal</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=SetGlobal&amp;diff=2116"/>
		<updated>2024-12-13T06:41:22Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''setGlobal($varname, $value, $no_linked, $source); -- установка значения глобального свойства объекта, где (Object-объект, Value-свойство), а  $value устанавливаемое значение. $no_linked, $source  - не обязательные параметры.&lt;br /&gt;
&lt;br /&gt;
$no_linked - отвечает за то, что не нужно вызывать связанные со свойствам модули и обычно используется что б не было цикличного вызова того же модуля, который инициировал изменение. Туда можно передать либо просто '''true (или 1)''' и тогда никакие модули не будут вызываться, или туда можно передать ассоциативный массив тех модулей, которые надо проигнорировать. например array('moduleName1'=&amp;gt;1,'moduleName2'=&amp;gt;1)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Если проигнорировать третий параметр ($no_linked), то можно использовать его, как четвертый, то есть, третьим параметром можно написать '''source'''. А '''source''' - это источник, который обновил свойство, например, туда можно записать ”''mqtt module''” и в будущем будет понятно, кто же записал туда это значение.&lt;br /&gt;
&lt;br /&gt;
'''sg'''(&amp;quot;Object.Value&amp;quot;, $value); -- альтернативное имя setGlobal&lt;br /&gt;
&lt;br /&gt;
'''Примечание:''' Конструкция запроса предусматривает возможность увеличения пути установки свойства до Класса. Класс.Объект.Свойство '''SetGlobal'''(&amp;quot;Class.Object.Value&amp;quot;, $value); , но данный метод в системе не приветствуется, так как одинаковые объекты могут причинить другие неудобства. В системе принято не создавать одинаковые объекты, а значит и указание класса в запросе не требуется.&lt;br /&gt;
&lt;br /&gt;
'''Примечание 2:''' При отсутствии в запросе указанного объекта &amp;quot;Object&amp;quot; система самостоятельно дополнит его объектом &amp;quot;[[ThisComputer]]&amp;quot; и все данные запишутся в данный объект системы. &lt;br /&gt;
&lt;br /&gt;
'''Примечание 3:''' Если в объекте отсутствует свойство &amp;quot;Value&amp;quot;, то система самостоятельно создаст его на уровне объекта и запишет данные в него. Такой подход лишает нас истории свойства и остальных возможностей свойств созданных на уровне класса.&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
Присвоить свойству timeNow объекта ThisComputer значение 17:12. Данный объект и свойство используются в дефолтной поставке МДМ.&lt;br /&gt;
&amp;lt;pre&amp;gt;setGlobal(&amp;quot;ThisComputer.timeNow&amp;quot;, &amp;quot;17:12&amp;quot;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Полностью равно предыдущей записи:&lt;br /&gt;
&amp;lt;pre&amp;gt;sg(&amp;quot;ThisComputer.timeNow&amp;quot;, &amp;quot;17:12&amp;quot;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
cг, cетглобал, &lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=SetGlobal&amp;diff=2115</id>
		<title>SetGlobal</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=SetGlobal&amp;diff=2115"/>
		<updated>2024-11-13T12:58:04Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
==Описание==&lt;br /&gt;
'''setGlobal($varname, $value, $no_linked, $source); -- установка значения глобального свойства объекта, где (Object-объект, Value-свойство), а  $value устанавливаемое значение. $no_linked, $source  - не обязательные параметры.&lt;br /&gt;
&lt;br /&gt;
$no_linked - отвечает за то, что не нужно вызывать связанные со свойствам модули и обычно используется что б не было цикличного вызова того же модуля, который инициировал изменение. Туда можно передать либо просто '''true (или 1)''' и тогда никакие модули не будут вызываться, или туда можно передать ассоциативный массив тех модулей, которые надо проигнорировать. например array('moduleName1'=&amp;gt;1,'moduleName2'=&amp;gt;1)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''sg'''(&amp;quot;Object.Value&amp;quot;, $value); -- альтернативное имя setGlobal&lt;br /&gt;
&lt;br /&gt;
'''Примечание:''' Конструкция запроса предусматривает возможность увеличения пути установки свойства до Класса. Класс.Объект.Свойство '''SetGlobal'''(&amp;quot;Class.Object.Value&amp;quot;, $value); , но данный метод в системе не приветствуется, так как одинаковые объекты могут причинить другие неудобства. В системе принято не создавать одинаковые объекты, а значит и указание класса в запросе не требуется.&lt;br /&gt;
&lt;br /&gt;
'''Примечание 2:''' При отсутствии в запросе указанного объекта &amp;quot;Object&amp;quot; система самостоятельно дополнит его объектом &amp;quot;[[ThisComputer]]&amp;quot; и все данные запишутся в данный объект системы. &lt;br /&gt;
&lt;br /&gt;
'''Примечание 3:''' Если в объекте отсутствует свойство &amp;quot;Value&amp;quot;, то система самостоятельно создаст его на уровне объекта и запишет данные в него. Такой подход лишает нас истории свойства и остальных возможностей свойств созданных на уровне класса.&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
Присвоить свойству timeNow объекта ThisComputer значение 17:12. Данный объект и свойство используются в дефолтной поставке МДМ.&lt;br /&gt;
&amp;lt;pre&amp;gt;setGlobal(&amp;quot;ThisComputer.timeNow&amp;quot;, &amp;quot;17:12&amp;quot;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Полностью равно предыдущей записи:&lt;br /&gt;
&amp;lt;pre&amp;gt;sg(&amp;quot;ThisComputer.timeNow&amp;quot;, &amp;quot;17:12&amp;quot;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
cг, cетглобал, &lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Devices_class_php&amp;diff=1953</id>
		<title>Devices class php</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Devices_class_php&amp;diff=1953"/>
		<updated>2024-03-30T06:01:06Z</updated>

		<summary type="html">&lt;p&gt;Mixman: Новая страница: «Category:SDevices Devices.class.php Возможно где-то ошибки с закрывающими или открывающими {} в связи с добавлением коментов, мог гдето херакнуть, прошу заранее прощения, сам ищу косяки и поправлю если найду. Но вроде бы не должно быть. &amp;lt;pre&amp;gt; &amp;lt;?php /**  * Общий коммент к понима...»&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>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Modules/devices/devices.class.php&amp;diff=1952</id>
		<title>Modules/devices/devices.class.php</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Modules/devices/devices.class.php&amp;diff=1952"/>
		<updated>2024-03-30T05:57:09Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Devices|devices.class]]&lt;br /&gt;
&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>Mixman</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&amp;diff=1935</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&amp;diff=1935"/>
		<updated>2024-01-04T07:54:56Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:root]]&lt;br /&gt;
Неполные куски кода для применения их в своих целях.&lt;/div&gt;</summary>
		<author><name>Mixman</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%AE%D0%B7%D0%B5%D1%80%D0%BA%D0%B5%D0%B9%D1%81%D1%8B&amp;diff=1931</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%AE%D0%B7%D0%B5%D1%80%D0%BA%D0%B5%D0%B9%D1%81%D1%8B&amp;diff=1931"/>
		<updated>2024-01-04T07:52:20Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:root]]&lt;br /&gt;
Законченые решения реализации определенных целей.&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=MediaWiki:Sidebar&amp;diff=1930</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=MediaWiki:Sidebar&amp;diff=1930"/>
		<updated>2024-01-04T07:45:18Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*Общее&lt;br /&gt;
**Правила оформления страницы|Как создать страницу&lt;br /&gt;
**Описание системы|Описание системы&lt;br /&gt;
**Описание сайта|Описание сайта&lt;br /&gt;
**Donate|Поддержать проект&lt;br /&gt;
**&lt;br /&gt;
* Система&lt;br /&gt;
** Category:Установка|Установка&lt;br /&gt;
** Category:Первые шаги|Первые шаги&lt;br /&gt;
** Category:Базовые переменные|Базовые переменные&lt;br /&gt;
** Category:Встроенные функции|Встроенные функции&lt;br /&gt;
** Category:Самописные функции|Самописные функции&lt;br /&gt;
** Category:Прочие функции|Прочие функции&lt;br /&gt;
** Category:php функции|php функции&lt;br /&gt;
** Category:Возникающие ошибки|Возникающие ошибки&lt;br /&gt;
*Основы&lt;br /&gt;
*** Category:Структура|Структура&lt;br /&gt;
*** Category:Интерфейс|Интерфейс&lt;br /&gt;
*** Category:Модули|Модули&lt;br /&gt;
*Опыт использования&lt;br /&gt;
** Category:другой СОФТ|другой СОФТ&lt;br /&gt;
** Category:Примеры|Примеры&lt;br /&gt;
** Category:Юзеркейсы|Юзеркейсы&lt;br /&gt;
** Category:Опыт в оборудовании|Опыт в оборудовании&lt;br /&gt;
* Оборудование&lt;br /&gt;
** Category:Сервер|Сервер&lt;br /&gt;
** Category:Взаимодействие|Взаимодействие&lt;br /&gt;
** Category:Датчики|Датчики&lt;br /&gt;
** Category:Исполнительные устройства|Исполнительные устройства&lt;br /&gt;
** Category:Опыт в оборудовании|Опыт в оборудовании&lt;br /&gt;
* О сайте&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1923</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1923"/>
		<updated>2023-10-04T23:38:08Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
488 Меняем &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    foreach ($to_start as $title =&amp;gt; $tm) {&lt;br /&gt;
        if ($tm &amp;lt;= time()) {&lt;br /&gt;
            if (!isset($is_running[$title])) {&lt;br /&gt;
                $cmd = './scripts/' . $title . '.php';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на это&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
foreach ($to_start as $title =&amp;gt; $tm) {&lt;br /&gt;
        if ($tm &amp;lt;= time()) {&lt;br /&gt;
            if (!isset($is_running[$title])) {&lt;br /&gt;
                $cmd = './scripts/' . $title . '.php';&lt;br /&gt;
                if (!file_exists($cmd)) &lt;br /&gt;
                    $cmd = './scripts/' . $title . '.py';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
509&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//$closePattern = '/THREAD CLOSED:.+?(\.\/scripts\/cycle\_.+?\.php)/is';&lt;br /&gt;
$closePattern = '/THREAD CLOSED:.+?(\.\/scripts\/cycle\_.+?\.(php|py))/is';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в '''/lib/threads.php''' после &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Добавляем&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public $pyPath = PYTHON_PATH;&amp;lt;/pre&amp;gt;&lt;br /&gt;
получаем:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
   public $pyPath = PYTHON_PATH;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в '''/modules/xray/xray.class.php.php''' 777 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  $title = preg_replace('/\.php$/', '', $entry);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
меняем&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  $title = preg_replace('/\.(php|py)$/', '', $entry);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1922</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1922"/>
		<updated>2023-10-04T14:21:03Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
488 Меняем &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    foreach ($to_start as $title =&amp;gt; $tm) {&lt;br /&gt;
        if ($tm &amp;lt;= time()) {&lt;br /&gt;
            if (!isset($is_running[$title])) {&lt;br /&gt;
                $cmd = './scripts/' . $title . '.php';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на это&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
foreach ($to_start as $title =&amp;gt; $tm) {&lt;br /&gt;
        if ($tm &amp;lt;= time()) {&lt;br /&gt;
            if (!isset($is_running[$title])) {&lt;br /&gt;
                $cmd = './scripts/' . $title . '.php';&lt;br /&gt;
                if (!file_exists($cmd)) &lt;br /&gt;
                    $cmd = './scripts/' . $title . '.py';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
509&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//$closePattern = '/THREAD CLOSED:.+?(\.\/scripts\/cycle\_.+?\.php)/is';&lt;br /&gt;
$closePattern = '/THREAD CLOSED:.+?(\.\/scripts\/cycle\_.+?\.(php|py))/is';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в '''/lib/threads.php''' после &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Добавляем&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public $pyPath = PYTHON_PATH;&amp;lt;/pre&amp;gt;&lt;br /&gt;
получаем:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
   public $pyPath = PYTHON_PATH;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1921</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1921"/>
		<updated>2023-10-04T14:19:02Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
488 Меняем &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    foreach ($to_start as $title =&amp;gt; $tm) {&lt;br /&gt;
        if ($tm &amp;lt;= time()) {&lt;br /&gt;
            if (!isset($is_running[$title])) {&lt;br /&gt;
                $cmd = './scripts/' . $title . '.php';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на это&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
foreach ($to_start as $title =&amp;gt; $tm) {&lt;br /&gt;
        if ($tm &amp;lt;= time()) {&lt;br /&gt;
            if (!isset($is_running[$title])) {&lt;br /&gt;
                $cmd = './scripts/' . $title . '.php';&lt;br /&gt;
                if (!file_exists($cmd)) &lt;br /&gt;
                    $cmd = './scripts/' . $title . '.py';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в '''/lib/threads.php''' после &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Добавляем&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public $pyPath = PYTHON_PATH;&amp;lt;/pre&amp;gt;&lt;br /&gt;
получаем:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
   public $pyPath = PYTHON_PATH;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1920</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1920"/>
		<updated>2023-10-04T14:06:27Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в '''/lib/threads.php''' после &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Добавляем&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public $pyPath = PYTHON_PATH;&amp;lt;/pre&amp;gt;&lt;br /&gt;
получаем:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
   public $pyPath = PYTHON_PATH;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1919</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1919"/>
		<updated>2023-10-04T14:05:49Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в '''/lib/threads.php''' после &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Добавляем&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public $pyPath = PYTHON_PATH;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
   public $pyPath = PYTHON_PATH;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1918</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1918"/>
		<updated>2023-10-04T13:51:05Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в '''/lib/threads.php''' после &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Добавляем&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$pyPath = 'python3';&amp;lt;/pre&amp;gt; или если стоит python3 &lt;br /&gt;
&amp;lt;pre&amp;gt; $pyPath = 'python';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
        $pyPath = 'python3';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1917</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1917"/>
		<updated>2023-10-04T13:50:42Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в '''/lib/threads.php''' после &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Добавляем&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$pyPath = 'python3';&amp;lt;/pre&amp;gt; или если стоит python3 &lt;br /&gt;
&amp;lt;pre&amp;gt; $pyPath = 'python3';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Threads&lt;br /&gt;
{&lt;br /&gt;
   public $phpPath = 'php';&lt;br /&gt;
        $pyPath = 'python3';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1916</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1916"/>
		<updated>2023-10-04T13:44:58Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1915</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1915"/>
		<updated>2023-10-04T13:44:18Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
расскоменчиваем в config.php&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;pre&amp;gt;Define('PYTHON_PATH','python3'); // path to python&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1914</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1914"/>
		<updated>2023-10-04T12:44:39Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&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;
if (preg_match('/(cycle_.+?)\.php/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (preg_match('/(cycle_.+?)\.(php|py)/is', $path, $m)) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1913</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1913"/>
		<updated>2023-10-04T12:27:27Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py] &lt;br /&gt;
в папку /scripts . Даем соответствующие права (0777)&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1912</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1912"/>
		<updated>2023-10-04T12:07:32Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php (примерно 308 строка) заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py]&lt;br /&gt;
в папку /scripts&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1911</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1911"/>
		<updated>2023-10-04T12:05:33Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Уважаемый '''Eraser''' сделал для majordomo альтернативные вебсокеты.&lt;br /&gt;
Чтобы установить, нужно проделать следущее:&lt;br /&gt;
&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
скопировать файл [https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py /scripts/cycle_websockets.py]&lt;br /&gt;
в папку /scripts&lt;br /&gt;
Там же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1910</id>
		<title>Вебсокеты Eraser</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%92%D0%B5%D0%B1%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D1%8B_Eraser&amp;diff=1910"/>
		<updated>2023-10-04T12:01:41Z</updated>

		<summary type="html">&lt;p&gt;Mixman: Новая страница: « в консоли  сервера  (SSH) &amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt; или для python3 &amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;  возможно, понадобится вначале с судо &amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt; или для python3 &amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;  в cycle.php заменить  &amp;lt;pre&amp;gt; if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file))) &amp;lt;/pre&amp;gt; на  &amp;lt;pre&amp;gt; if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_fil...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
в консоли  сервера  (SSH)&lt;br /&gt;
&amp;lt;pre&amp;gt;pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
возможно, понадобится вначале с судо&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
или для python3&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo pip3 install websockets&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в cycle.php заменить &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.php$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
на &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ((preg_match(&amp;quot;/^cycle_.+?\.(php|py)$/&amp;quot;, $lib_file)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
скопировать файл https://github.com/Anisan/majordomo/blob/ba718d7048f39ea9a22a84e04f422590795480b2/scripts/cycle_websockets.py&lt;br /&gt;
в папку /scripts&lt;br /&gt;
В той же папке переименовать или удалить стандартный цикл вебсокетов '''cycle_websockets.php'''&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1909</id>
		<title>CleanUpValueHistory</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1909"/>
		<updated>2023-09-27T11:54:20Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Описание==&lt;br /&gt;
'''cleanUpValueHistory'''($value_id, $max_age_days, $data_type = 0)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
функция, которая чистит историю точечно по конкретно указанному свойству конкретного объекта на нужную глубину в днях. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''$value_id'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''$max_age_days''' - удалять не моложе возраста (в днях)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''$data_type = 0'''&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1908</id>
		<title>CleanUpValueHistory</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1908"/>
		<updated>2023-09-27T11:54:03Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Описание==&lt;br /&gt;
'''cleanUpValueHistory'''($value_id, $max_age_days, $data_type = 0)'''Полужирное начертание'''&lt;br /&gt;
функция, которая чистит историю точечно по конкретно указанному свойству конкретного объекта на нужную глубину в днях. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''$value_id'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''$max_age_days''' - удалять не моложе возраста (в днях)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''$data_type = 0'''&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1907</id>
		<title>CleanUpValueHistory</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1907"/>
		<updated>2023-09-27T11:53:45Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Описание==&lt;br /&gt;
cleanUpValueHistory($value_id, $max_age_days, $data_type = 0)&lt;br /&gt;
функция, которая чистит историю точечно по конкретно указанному свойству конкретного объекта на нужную глубину в днях. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''$value_id'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''$max_age_days''' - удалять не моложе возраста (в днях)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''$data_type = 0'''&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1906</id>
		<title>CleanUpValueHistory</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1906"/>
		<updated>2023-09-27T11:53:05Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Описание==&lt;br /&gt;
cleanUpValueHistory($value_id, $max_age_days, $data_type = 0)&lt;br /&gt;
функция, которая чистит историю точечно по конкретно указанному свойству конкретного объекта на нужную глубину в днях. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$value_id&lt;br /&gt;
$max_age_days - удалять не моложе возраста (в днях)&lt;br /&gt;
$data_type = 0&lt;br /&gt;
.&lt;br /&gt;
==Примеры запросов==&lt;br /&gt;
&lt;br /&gt;
==Альтернативные названия функции (сленг)==&lt;br /&gt;
&lt;br /&gt;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1905</id>
		<title>CleanUpValueHistory</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=CleanUpValueHistory&amp;diff=1905"/>
		<updated>2023-09-27T11:50:28Z</updated>

		<summary type="html">&lt;p&gt;Mixman: Новая страница: «Category:Встроенные функции cleanUpValueHistory($value_id, $max_age_days, $data_type = 0)  ==Описание== функция, которая чистит историю точечно по конкретно указанному свойству конкретного объекта на нужную глубину в днях.   ==Примеры запросов==  ==Альтернативные названия функции (сле...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Встроенные функции]]&lt;br /&gt;
cleanUpValueHistory($value_id, $max_age_days, $data_type = 0)&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;
==Просто для проверки появления разделов==&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=%D0%A2%D0%B5%D0%BB%D0%B5%D0%B3%D1%80%D0%B0%D0%BC_%D0%9E%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81_IP_%D0%BA%D0%B0%D0%BC%D0%B5%D1%80%D1%8B_.&amp;diff=1892</id>
		<title>Телеграм Отправка изображения с IP камеры .</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=%D0%A2%D0%B5%D0%BB%D0%B5%D0%B3%D1%80%D0%B0%D0%BC_%D0%9E%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81_IP_%D0%BA%D0%B0%D0%BC%D0%B5%D1%80%D1%8B_.&amp;diff=1892"/>
		<updated>2023-05-23T10:43:43Z</updated>

		<summary type="html">&lt;p&gt;Mixman: /* Код */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Юзеркейсы]]&lt;br /&gt;
==Описание==&lt;br /&gt;
Телеграмм. Отправка изображения с IP камеры.&lt;br /&gt;
==Код==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include_once(DIR_MODULES . 'telegram/telegram.class.php');&lt;br /&gt;
$telegram_module = new telegram();&lt;br /&gt;
&lt;br /&gt;
exec('sudo ffmpeg -i rtsp://IP:port/user=admin_password=imfzZCJe_channel=0_stream=0.sdp?real_stream -y -f mjpeg -t 0.110 -s 1280x720 mnt/Backup/Video/out.jpg');&lt;br /&gt;
$jpg=&amp;quot;/mnt/Backup/Video/out.jpg&amp;quot;;&lt;br /&gt;
$this-&amp;gt;sendImageToUser($chat_id,$jpg);&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
'''rtsp://IP:port''' - адрес и порт камеры.&lt;br /&gt;
 &lt;br /&gt;
'''mnt/Backup/Video/out.jpg''' - путь куда сохранять снимок, у вас он может быть другой.&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
	<entry>
		<id>https://mdminfo.ru/index.php?title=Donate&amp;diff=1841</id>
		<title>Donate</title>
		<link rel="alternate" type="text/html" href="https://mdminfo.ru/index.php?title=Donate&amp;diff=1841"/>
		<updated>2023-01-02T20:16:58Z</updated>

		<summary type="html">&lt;p&gt;Mixman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&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;
&lt;br /&gt;
[https://yoomoney.ru/fundraise/Z6Wc4ARVLTI.230102 Пожертвование через Ю.Money]&lt;/div&gt;</summary>
		<author><name>Mixman</name></author>
	</entry>
</feed>