Files
Enelix-Utils/tests/ShellyModulTest.php
dh 1baa63f23e
Tests / test (push) Successful in 46s
Shelly Modul generisch erweitern
2026-09-17 10:19:56 +00:00

244 lines
6.9 KiB
PHP

<?php
declare(strict_types=1);
namespace {
class IPSModule
{
protected int $InstanceID;
private array $properties = [];
public function __construct(int $instanceID = 1)
{
$this->InstanceID = $instanceID;
$GLOBALS['ipsObjects'][$instanceID] = ['parent' => 0, 'ident' => '', 'name' => 'Modul'];
$this->Create();
}
public function Create()
{
}
protected function RegisterPropertyBoolean(string $name, bool $value): void
{
$this->properties[$name] = $value;
}
protected function RegisterPropertyString(string $name, string $value): void
{
$this->properties[$name] = $value;
}
protected function ReadPropertyBoolean(string $name): bool
{
return (bool) $this->properties[$name];
}
protected function ReadPropertyString(string $name): string
{
return (string) $this->properties[$name];
}
protected function ConnectParent(string $moduleID): void
{
}
protected function SendDataToParent(string $packet): void
{
$GLOBALS['sentPackets'][] = $packet;
}
protected function SendDebug(string $title, string $message, int $format): void
{
}
public function setTestProperty(string $name, $value): void
{
$this->properties[$name] = $value;
}
}
function IPS_GetObjectIDByIdent(string $ident, int $parentID)
{
foreach ($GLOBALS['ipsObjects'] as $id => $object) {
if ($object['parent'] === $parentID && $object['ident'] === $ident) {
return $id;
}
}
return false;
}
function IPS_CreateCategory(): int
{
return ipsCreateObject('category');
}
function IPS_CreateVariable(int $type): int
{
$id = ipsCreateObject('variable');
$GLOBALS['ipsVariables'][$id] = ['VariableType' => $type];
return $id;
}
function IPS_CreateScript(int $type): int
{
return ipsCreateObject('script');
}
function ipsCreateObject(string $type): int
{
$id = ++$GLOBALS['ipsNextID'];
$GLOBALS['ipsObjects'][$id] = [
'parent' => 0,
'ident' => '',
'name' => '',
'type' => $type,
'profile' => '',
];
return $id;
}
function IPS_SetParent(int $id, int $parentID): void
{
$GLOBALS['ipsObjects'][$id]['parent'] = $parentID;
}
function IPS_SetIdent(int $id, string $ident): void
{
$GLOBALS['ipsObjects'][$id]['ident'] = $ident;
}
function IPS_SetName(int $id, string $name): void
{
$GLOBALS['ipsObjects'][$id]['name'] = $name;
}
function IPS_SetInfo(int $id, string $info): void
{
}
function IPS_SetPosition(int $id, int $position): void
{
}
function IPS_VariableProfileExists(string $profile): bool
{
return in_array($profile, ['~Switch', '~Temperature', '~Humidity'], true);
}
function IPS_SetVariableCustomProfile(int $id, string $profile): void
{
$GLOBALS['ipsObjects'][$id]['profile'] = $profile;
}
function IPS_SetVariableCustomAction(int $id, int $scriptID): void
{
}
function IPS_SetHidden(int $id, bool $hidden): void
{
}
function IPS_SetScriptContent(int $id, string $content): void
{
}
function IPS_VariableExists(int $id): bool
{
return isset($GLOBALS['ipsVariables'][$id]);
}
function IPS_ScriptExists(int $id): bool
{
return ($GLOBALS['ipsObjects'][$id]['type'] ?? '') === 'script';
}
function IPS_GetVariable(int $id): array
{
return $GLOBALS['ipsVariables'][$id];
}
function SetValue(int $id, $value): void
{
$GLOBALS['ipsValues'][$id] = $value;
}
require_once __DIR__ . '/../ShellyModul/module.php';
}
namespace Belevo\EnelixUtils\Tests {
use PHPUnit\Framework\TestCase;
final class ShellyModulTest extends TestCase
{
protected function setUp(): void
{
$GLOBALS['ipsNextID'] = 100;
$GLOBALS['ipsObjects'] = [];
$GLOBALS['ipsVariables'] = [];
$GLOBALS['ipsValues'] = [];
$GLOBALS['sentPackets'] = [];
}
public function testCustomNestedPrefixAndUnknownSourceAreAccepted(): void
{
$module = new \ShellyModul(1);
$module->ReceiveData(json_encode([
'PacketType' => 3,
'Topic' => 'gebaeude/wohnung/symcon/events/rpc',
'Payload' => json_encode([
'src' => 'custom-client-name',
'method' => 'NotifyStatus',
'params' => [
'switch:0' => ['output' => true, 'apower' => 12.5],
'cover:0' => ['current_pos' => 37],
'future:0' => ['new_value' => 99],
],
], JSON_THROW_ON_ERROR),
], JSON_THROW_ON_ERROR));
$names = array_column($GLOBALS['ipsObjects'], 'name');
self::assertContains('gebaeude/wohnung/symcon', $names);
self::assertContains('Output 0', $names);
self::assertContains('Switch 0 - Wirkleistung', $names);
self::assertContains('Cover 0 - Position', $names);
self::assertNotContains('Future 0 - New value', $names);
self::assertContains(true, $GLOBALS['ipsValues']);
self::assertContains(12.5, $GLOBALS['ipsValues']);
}
public function testComponentStatusUsesEnvironmentProfile(): void
{
$module = new \ShellyModul(1);
$module->ReceiveData(json_encode([
'PacketType' => 3,
'Topic' => 'symcon/status/humidity:0',
'Payload' => '{"id":0,"rh":54.3}',
], JSON_THROW_ON_ERROR));
$humidity = array_filter(
$GLOBALS['ipsObjects'],
static fn (array $object): bool => $object['name'] === 'Humidity 0 - Luftfeuchtigkeit'
);
self::assertCount(1, $humidity);
self::assertSame('~Humidity', array_values($humidity)[0]['profile']);
self::assertContains(54.3, $GLOBALS['ipsValues']);
}
public function testOptionalTopicFilterCanRejectOtherPrefixes(): void
{
$module = new \ShellyModul(1);
$module->setTestProperty('UseDeviceTopicFilter', true);
$module->setTestProperty('DeviceTopicPrefix', 'shelly');
$module->ReceiveData(json_encode([
'PacketType' => 3,
'Topic' => 'symcon/online',
'Payload' => 'true',
], JSON_THROW_ON_ERROR));
self::assertCount(1, $GLOBALS['ipsObjects']);
self::assertSame([], $GLOBALS['ipsValues']);
}
}
}