<?php
namespace SHServ\Helpers;
use \SHServ\Models\Devices;
class DeviceScriptsHelper {
protected $devices_model;
public function __construct(Devices $devices_model) {
$this -> devices_model = $devices_model;
}
public function devices(): Devices {
return $this -> devices_model;
}
/**
* Синхронизировать указанный канал реле с указанным каналом устройства кнопки.
* Синхронизация низкоуровневая и одностороняя, от реле к кнопке.
* @param Relay $relay
* @param Button $btn
* @param int|integer $relay_channel
* @param int|integer $btn_channel
* @return void
*/
public function sync_relay_to_btn_channel(\SHServ\Tools\DeviceAPI\Relay $relay_api, \SHServ\Tools\DeviceAPI\Button $btn_block_api, int $relay_channel = 0, int $btn_channel = 0): void {
$relay_channels = ($relay_api -> get_status())["channels"] ?? [];
if(!isset($relay_channels[$relay_channel]["state"])) {
return;
}
$btn_block_api -> set_channel_state(
$relay_channels[$relay_channel]["state"] == "on" ? "enabled" : "disabled",
$btn_channel
);
}
/**
* Синхронизировать состояние каналов реле с соответствующими блоками кнопок с указанными каналами.
* Синхронизация односторонняя от реле к кнопкам
* @param Array $sync_map [
* relay_channel_num => [
* ["alias" => "button_alias", "channel" => 1],
* ["alias" => "button_alias_2", "channel" => 0],
* ]
* ]
* @param String $relay_alias
* @return Bool
*/
public function sync_relay_to_btns(Array $sync_map, String $relay_alias): Bool {
if(isset($sync_map["connections"])) {
$sync_map = $this -> prepare_sync_map_by_alias($sync_map, $relay_alias);
}
$relay = $this -> devices() -> by_alias($relay_alias);
if(!$relay) {
return false;
}
$relay_api = $relay -> device_api();
if(!($relay_api instanceof \SHServ\Tools\DeviceAPI\Relay)) {
return false;
}
foreach($sync_map as $relay_channel => $btns) {
foreach($btns as $item) {
$btn = $this -> devices() -> by_alias($item["alias"]);
if(!$btn) {
continue;
}
$btn_api = $btn -> device_api();
if(!($btn_api instanceof \SHServ\Tools\DeviceAPI\Button)) {
continue;
}
$this -> sync_relay_to_btn_channel($relay_api, $btn_api, $relay_channel, intval($item["channel"]));
}
}
return true;
}
/**
* Синхронизировать состояние каналов устройства "кнопка" с соответствующими реле с указанными каналами.
* Синхронизация односторонняя от реле к кнопкам
* @param Array $sync_map [
* button_channel_num => [
* ["alias" => "relay_alias", "channel" => 1],
* ["alias" => "relay_alias_2", "channel" => 0],
* ]
* ]
* @param String $btn_alias
* @return Bool
*/
public function sync_btn_channels(Array $sync_map, String $btn_alias): Bool {
if(isset($sync_map["connections"])) {
$sync_map = $this -> prepare_sync_map_by_alias($sync_map, $btn_alias);
}
$btn = $this -> devices() -> by_alias($btn_alias);
if(!$btn) {
return false;
}
$btn_api = $btn -> device_api();
if(!($btn_api instanceof \SHServ\Tools\DeviceAPI\Button)) {
return false;
}
foreach($sync_map as $btn_channel => $relays) {
foreach($relays as $item) {
$relay = $this -> devices() -> by_alias($item["alias"]);
if(!$relay) {
continue;
}
$relay_api = $relay -> device_api();
if(!($relay_api instanceof \SHServ\Tools\DeviceAPI\Relay)) {
continue;
}
$this -> sync_relay_to_btn_channel($relay_api, $btn_api, intval($item["channel"]), $btn_channel);
}
}
return true;
}
public function get_sync_entries_by_type(Array $sync_map, String $type): Array {
$map = $sync_map["connections"];
$device_entries = [];
foreach($map as $connection) {
foreach($connection as $device_entry) {
if(!isset($device_entry["type"]) or $device_entry["type"] != $type) {
continue;
}
if(!isset($device_entry["alias"])) {
continue;
}
$device_entries[] = $device_entry;
}
}
return $device_entries;
}
public function prepare_sync_map_by_alias(Array $sync_map, String $alias): Array {
$result = [];
if(!isset($sync_map["connections"])) {
return $result;
}
foreach($sync_map["connections"] as $connection) {
foreach($connection as $device_entry) {
if($device_entry["alias"] != $alias) {
continue;
}
$result[$device_entry["channel"]] = array_filter($connection, function($i) use($alias) {
return $i["alias"] != $alias;
});
break;
}
}
return $result;
}
/**
* Групповая установка состояния (on/off) для списка реле.
* Targets: строка (alias одноканального реле) или [alias, channel] для многоканального.
* Автоматически синхронизирует индикаторы кнопок через sync_map.
* Возвращает массив результатов по каждому target.
*/
public function group_set_state(Array $targets, bool $state, Array $sync_map): Array {
$results = [];
foreach($targets as $target) {
$relay_alias = null;
$channel = null;
if(is_string($target)) {
$relay_alias = $target;
} elseif(is_array($target) && count($target) >= 2) {
$relay_alias = $target[0];
$channel = intval($target[1]);
} else {
continue;
}
$relay = $this -> devices() -> by_alias($relay_alias);
$key = $relay_alias . ($channel !== null ? ":{$channel}" : "");
if(!$relay) {
$results[$key] = false;
continue;
}
$relay_api = $relay -> device_api();
$result = false;
if($relay_api instanceof \SHServ\Tools\DeviceAPI\Relay) {
if($channel === null) {
$result = $relay_api -> set_state($state);
} else {
$status = $relay_api -> get_status();
$current = $status["channels"][$channel]["state"] ?? null;
if($current != ($state ? "on" : "off")) {
$result = $relay_api -> set_channel_state($state, $channel);
} else {
$result = true;
}
}
$this -> sync_relay_to_btns($sync_map, $relay_alias);
}
$results[$key] = $result;
}
return $results;
}
/**
* Групповой toggle для списка реле.
* Targets: строка (alias) или [alias, channel].
* Автоматически синхронизирует индикаторы кнопок через sync_map.
*/
public function group_toggle(Array $targets, Array $sync_map): Array {
$results = [];
foreach($targets as $target) {
$relay_alias = null;
$channel = null;
if(is_string($target)) {
$relay_alias = $target;
} elseif(is_array($target) && count($target) >= 2) {
$relay_alias = $target[0];
$channel = intval($target[1]);
} else {
continue;
}
$relay = $this -> devices() -> by_alias($relay_alias);
$key = $relay_alias . ($channel !== null ? ":{$channel}" : "");
if(!$relay) {
$results[$key] = false;
continue;
}
$relay_api = $relay -> device_api();
$result = false;
if($relay_api instanceof \SHServ\Tools\DeviceAPI\Relay) {
$result = $relay_api -> toggle_channel($channel ?? 0);
$this -> sync_relay_to_btns($sync_map, $relay_alias);
}
$results[$key] = $result;
}
return $results;
}
}