Control Scripts — это PHP-классы автоматизации. Базовый класс находится в server/SHServ/Middleware/ControlScripts.php, интерфейс — в server/SHServ/Implements/ControlScriptsInterface.php.
Scope-классы располагаются в server/ControlScripts/Scopes/ (или другом месте, если настроено иначе). Все Scope-файлы загружаются автоматически при старте сервера.
Все Scope-классы наследуют \SHServ\Middleware\ControlScripts и реализуют \SHServ\Implements\ControlScriptsInterface:
<?php
namespace ControlScripts\Scopes;
class MyScope extends \SHServ\Middleware\ControlScripts
implements \SHServ\Implements\ControlScriptsInterface {
// ...
}
Автоматическая загрузка:
При старте сервера каждый Scope-класс:
scripts, тип scope, имя = название класса)Каждый Scope-класс обязан реализовать 4 метода. Они вызываются при старте сервера (если scope включён в БД).
register_sync_map(): voidРегистрирует связи «реле ↔ кнопки» для синхронизации индикаторов.
public function register_sync_map(): void {
$this->add_sync_connection([
// Первый элемент — источник состояния (обычно реле)
["type" => "relay", "alias" => "kitchen_relay", "channel" => 0],
// Остальные — кнопки, чьи индикаторы синхронизируются
["type" => "button", "alias" => "kitchen_btns", "channel" => 1],
["type" => "button", "alias" => "hall_btns", "channel" => 0],
]);
}
Sync map хранится в статической переменной ControlScripts::$sync_map_storage.
register_events_handlers(): voidПодписывается на события от устройств. Обработчик вызывается асинхронно после ответа устройству (fastcgi_finish_request).
public function register_events_handlers(): void {
// Нажатие кнопки (канал 1) конкретного устройства
$this->add_event_handler("button@kitchen_btns(1).press", function(Device $device, array $data) {
$relay = $this->devices()->by_alias("kitchen_relay");
$relay->device_api()->toggle_channel(0);
$this->helper()->sync_relay_to_btns($this->sync_map(), "kitchen_relay");
});
// Устройство вышло в сеть (после перезагрузки)
$this->add_event_handler("button@kitchen_btns.online", function(Device $device, array $data) {
$this->helper()->sync_btn_channels($this->sync_map(), $device->alias);
});
}
Паттерны имён событий:
| Паттерн | Пример | Описание |
|---|---|---|
{event_name} |
press |
Любое устройство, любое событие |
{type}.{event_name} |
button.press |
Все устройства типа button |
{type}@{alias}.{event_name} |
button@kitchen_btns.press |
Конкретное устройство (все каналы) |
{type}({ch}).{event_name} |
button(1).press |
Все устройства типа, канал 1 |
{type}@{alias}({ch}).{event_name} |
button@kitchen_btns(1).press |
Конкретное устройство, канал 1 |
Полное описание: docs/events-from-devices.md.
register_actions_scripts(): voidРегистрирует action-скрипты (ручной запуск через UI/API).
public function register_actions_scripts(): void {
$this->add_action_script([
"alias" => "kitchen_light_toggle",
"name" => "Свет на кухне",
"icon" => '<i class="ph ph-lightbulb"></i>',
"description" => "Включить/выключить основной свет",
"author" => "Eugene Sukhodolskiy"
], function($params) {
$relay = $this->devices()->by_alias("kitchen_relay");
$relay->device_api()->toggle_channel(0);
$this->helper()->sync_relay_to_btns($this->sync_map(), "kitchen_relay");
return ["result" => true];
});
}
API:
POST /api/v1/scripts/actions/run — запустить скриптGET /api/v1/scripts/actions/alias/{alias}/enable — включитьGET /api/v1/scripts/actions/alias/{alias}/disable — выключитьregister_regular_scripts(): voidРегистрирует regular-скрипты (периодический запуск по cron).
public function register_regular_scripts(): void {
$this->add_regular_script([
"alias" => "check_door_sensor",
"name" => "Проверка датчика двери",
], function() {
$sensor = $this->devices()->by_alias("door_sensor");
// ...
});
}
API:
GET /cron/regular-scripts — запустить все enabled regular-скрипты (cron)GET /api/v1/scripts/regular/alias/{alias}/enable — включитьGET /api/v1/scripts/regular/alias/{alias}/disable — выключить| Метод | Возвращает | Описание |
|---|---|---|
$this->devices() |
\SHServ\Models\Devices |
Поиск устройств по alias, id, hard_id |
$this->helper() |
\SHServ\Helpers\DeviceScriptsHelper |
Хелперы синхронизации реле/кнопок |
$this->sync_map() |
array |
Текущий sync_map (статическое хранилище) |
$this->add_event_handler($name, $cb) |
void |
Подписаться на событие |
$this->add_action_script($attrs, $cb) |
bool |
Зарегистрировать action-скрипт |
$this->add_regular_script($attrs, $cb) |
bool |
Зарегистрировать regular-скрипт |
$this->add_sync_connection($entries) |
void |
Добавить связь в sync_map |
Класс \SHServ\Helpers\DeviceScriptsHelper предоставляет методы для синхронизации индикаторов кнопок с состоянием реле.
| Метод | Описание |
|---|---|
sync_relay_to_btn_channel($relay_api, $btn_api, $relay_ch, $btn_ch) |
Синхронизировать один канал реле с одним каналом кнопки |
sync_relay_to_btns($sync_map, $relay_alias) |
Синхронизировать все кнопки из sync_map с указанным реле |
sync_btn_channels($sync_map, $btn_alias) |
Синхронизировать индикаторы указанной кнопки с реле из sync_map |
get_sync_entries_by_type($sync_map, $type) |
Получить все записи указанного типа из sync_map |
prepare_sync_map_by_alias($sync_map, $alias) |
Подготовить sync_map для указанного устройства |
// В event-хендлере: переключить реле и синхронизировать кнопки
$relay = $this->devices()->by_alias("kitchen_relay");
$relay_api = $relay->device_api();
$relay_api->toggle_channel(0);
// Синхронизировать все кнопки, связанные с этим реле
$this->helper()->sync_relay_to_btns($this->sync_map(), "kitchen_relay");
// Или: синхронизировать конкретную кнопку с реле
$this->helper()->sync_btn_channels($this->sync_map(), "kitchen_btns");
| Endpoint | Описание |
|---|---|
GET /api/v1/scripts/actions/scope/{name}/enable |
Включить Scope (в БД) |
GET /api/v1/scripts/actions/scope/{name}/disable |
Выключить Scope (в БД) |
GET /api/v1/scripts/scopes/list |
Список всех Scope с состоянием |
GET /api/v1/scripts/scopes/name/{name} |
Исходный код PHP-файла Scope |
POST /api/v1/scripts/scopes/update |
Обновить код Scope |
Важно: Scope отключается через БД — при следующем запуске сервера его скрипты не зарегистрируются.
Некоторые проекты используют trait \ControlScripts\Common с готовыми хелперами:
use \ControlScripts\Common;
class MyScope extends \SHServ\Middleware\ControlScripts {
use Common;
public function register_sync_map(): void {
// Зарегистрировать глобальный sync_map (все реле и кнопки системы)
$this->register_global_device_sync_map();
}
public function register_events_handlers(): void {
// Установить обработчики нажатий для кнопок из sync_map
$this->set_btns_click_handlers("kitchen_btns");
}
}
Проверьте наличие trait в вашем проекте: server/ControlScripts/Common.php.