316 lines
12 KiB
PHP
316 lines
12 KiB
PHP
<?php
|
|
|
|
app_require('classes/shelly_relay_inventory.php');
|
|
|
|
use classes\shelly_relay_inventory;
|
|
|
|
it('normalizes owned Shelly devices into relay select options', function (): void {
|
|
$inventory = (new shelly_relay_inventory())
|
|
->setInventoryFetcher(static function (): array {
|
|
return [
|
|
'isok' => true,
|
|
'data' => [
|
|
'devices_status' => [
|
|
'device-key-1' => [
|
|
'_dev_info' => [
|
|
'id' => 'shelly-plus-01',
|
|
'code' => 'SPSW-001PE16EU',
|
|
'model' => 'Shelly Plus 1PM',
|
|
'online' => 1,
|
|
],
|
|
'name' => 'Entry Gate',
|
|
'wifi_sta' => [
|
|
'ip' => '10.32.0.11',
|
|
],
|
|
'status' => [
|
|
'switch:0' => [
|
|
'output' => false,
|
|
'name' => 'Entrance Relay',
|
|
],
|
|
],
|
|
],
|
|
'device-key-2' => [
|
|
'_dev_info' => [
|
|
'id' => 'shelly-pro-03',
|
|
'code' => 'SPSW-201XE16EU',
|
|
'model' => 'Shelly Pro 2PM',
|
|
],
|
|
'name' => 'Machine Cabinet',
|
|
'status' => [
|
|
'eth' => [
|
|
'ip' => '10.32.0.12',
|
|
],
|
|
],
|
|
'relays' => [
|
|
['ison' => false, 'name' => 'Program Picker'],
|
|
],
|
|
],
|
|
'device-key-3' => [
|
|
'_dev_info' => [
|
|
'id' => 'shelly-legacy-02',
|
|
'code' => 'SHSW-1',
|
|
'model' => 'Shelly 1',
|
|
'online' => 0,
|
|
],
|
|
'relays' => [
|
|
['ison' => false],
|
|
],
|
|
],
|
|
'device-key-4' => [
|
|
'_dev_info' => [
|
|
'id' => 'shelly-sensor-01',
|
|
'code' => 'SHHT-1',
|
|
'model' => 'Shelly H&T',
|
|
'online' => 1,
|
|
],
|
|
'sensor' => [
|
|
'temperature' => 21.5,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
})
|
|
->setDeviceListFetcher(static function (): array {
|
|
return [
|
|
'isok' => true,
|
|
'data' => [
|
|
'devices' => [
|
|
'shelly-plus-01' => [
|
|
'id' => 'shelly-plus-01',
|
|
'name' => 'Gate From Shelly Cloud',
|
|
'type' => 'SPSW-001PE16EU',
|
|
'cloud_online' => true,
|
|
],
|
|
'shelly-pro-03' => [
|
|
'id' => 'shelly-pro-03',
|
|
'name' => 'Program Picker From Shelly Cloud',
|
|
'type' => 'SPSW-201XE16EU',
|
|
'cloud_online' => false,
|
|
],
|
|
],
|
|
],
|
|
];
|
|
});
|
|
|
|
expect($inventory->listRelayOptions())->toBe([
|
|
[
|
|
'id' => 'shelly-plus-01',
|
|
'name' => 'Gate From Shelly Cloud (Shelly Plus 1PM)',
|
|
'device_id' => 'shelly-plus-01',
|
|
'device_name' => 'Gate From Shelly Cloud',
|
|
'cloud_name' => 'Gate From Shelly Cloud',
|
|
'device_type' => 'Shelly Plus 1PM',
|
|
'code' => 'SPSW-001PE16EU',
|
|
'device_model' => 'SPSW-001PE16EU',
|
|
'device_generation' => 2,
|
|
'control_type' => 'Switch',
|
|
'control_name' => 'Entrance Relay',
|
|
'status_color' => 'Green',
|
|
'online' => true,
|
|
],
|
|
[
|
|
'id' => 'shelly-pro-03',
|
|
'name' => 'Program Picker From Shelly Cloud (Shelly Pro 2PM)',
|
|
'device_id' => 'shelly-pro-03',
|
|
'device_name' => 'Program Picker From Shelly Cloud',
|
|
'cloud_name' => 'Program Picker From Shelly Cloud',
|
|
'device_type' => 'Shelly Pro 2PM',
|
|
'code' => 'SPSW-201XE16EU',
|
|
'device_model' => 'SPSW-201XE16EU',
|
|
'device_generation' => 2,
|
|
'control_type' => 'Relay',
|
|
'control_name' => 'Program Picker',
|
|
'status_color' => 'Red',
|
|
'online' => false,
|
|
],
|
|
[
|
|
'id' => 'shelly-legacy-02',
|
|
'name' => 'shelly-legacy-02 (Shelly 1)',
|
|
'device_id' => 'shelly-legacy-02',
|
|
'device_name' => null,
|
|
'cloud_name' => null,
|
|
'device_type' => 'Shelly 1',
|
|
'code' => 'SHSW-1',
|
|
'device_model' => 'SHSW-1',
|
|
'device_generation' => 1,
|
|
'control_type' => 'Relay',
|
|
'control_name' => null,
|
|
'status_color' => 'Red',
|
|
'online' => false,
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('falls back to local device and control names when Shelly cloud list metadata is unavailable', function (): void {
|
|
$inventory = (new shelly_relay_inventory())
|
|
->setInventoryFetcher(static function (): array {
|
|
return [
|
|
'isok' => true,
|
|
'data' => [
|
|
'devices_status' => [
|
|
'device-key-1' => [
|
|
'_dev_info' => [
|
|
'id' => 'shelly-plus-01',
|
|
'code' => 'SPSW-001PE16EU',
|
|
'model' => 'Shelly Plus 1PM',
|
|
'online' => 1,
|
|
],
|
|
'ip' => '10.32.0.21',
|
|
'name' => 'Entry Gate',
|
|
'status' => [
|
|
'switch:0' => [
|
|
'output' => false,
|
|
'name' => 'Entrance Relay',
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
})
|
|
->setDeviceListFetcher(static function (): array {
|
|
return [
|
|
'isok' => false,
|
|
'errors' => [
|
|
'404' => 'Requested method was not found',
|
|
],
|
|
];
|
|
});
|
|
|
|
expect($inventory->listRelayOptions())->toBe([
|
|
[
|
|
'id' => 'shelly-plus-01',
|
|
'name' => 'Entry Gate / Entrance Relay (Shelly Plus 1PM)',
|
|
'device_id' => 'shelly-plus-01',
|
|
'device_name' => 'Entry Gate',
|
|
'cloud_name' => null,
|
|
'device_type' => 'Shelly Plus 1PM',
|
|
'code' => 'SPSW-001PE16EU',
|
|
'device_model' => 'SPSW-001PE16EU',
|
|
'device_generation' => 2,
|
|
'control_type' => 'Switch',
|
|
'control_name' => 'Entrance Relay',
|
|
'status_color' => 'Green',
|
|
'online' => true,
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('keeps Shelly 1 Mini Gen3 type, model, and generation aligned with Shelly metadata', function (): void {
|
|
$inventory = (new shelly_relay_inventory())
|
|
->setInventoryFetcher(static function (): array {
|
|
return [
|
|
'isok' => true,
|
|
'data' => [
|
|
'devices_status' => [
|
|
'device-key-1' => [
|
|
'_dev_info' => [
|
|
'id' => 'e4b3231f6410',
|
|
'model' => 'S3SW-001X8EU',
|
|
'type' => 'Shelly 1 Mini Gen3',
|
|
'online' => 1,
|
|
],
|
|
'name' => 'Roskilde indkørselsport',
|
|
'wifi_sta' => [
|
|
'ip' => '192.168.1.2',
|
|
],
|
|
'status' => [
|
|
'switch:0' => [
|
|
'output' => false,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
})
|
|
->setDeviceListFetcher(static function (): array {
|
|
return [
|
|
'isok' => true,
|
|
'data' => [
|
|
'devices' => [
|
|
'e4b3231f6410' => [
|
|
'id' => 'e4b3231f6410',
|
|
'name' => 'Roskilde indkørselsport',
|
|
'type' => 'S3SW-001X8EU',
|
|
'cloud_online' => true,
|
|
],
|
|
],
|
|
],
|
|
];
|
|
});
|
|
|
|
expect($inventory->listRelayOptions())->toBe([[
|
|
'id' => 'e4b3231f6410',
|
|
'name' => 'Roskilde indkørselsport (Shelly 1 Mini Gen3)',
|
|
'device_id' => 'e4b3231f6410',
|
|
'device_name' => 'Roskilde indkørselsport',
|
|
'cloud_name' => 'Roskilde indkørselsport',
|
|
'device_type' => 'Shelly 1 Mini Gen3',
|
|
'code' => 'S3SW-001X8EU',
|
|
'device_model' => 'S3SW-001X8EU',
|
|
'device_generation' => 3,
|
|
'control_type' => 'Switch',
|
|
'control_name' => null,
|
|
'status_color' => 'Green',
|
|
'online' => true,
|
|
]]);
|
|
});
|
|
|
|
it('only includes local IP addresses for internal relay option lookups', function (): void {
|
|
$inventory = (new shelly_relay_inventory())
|
|
->setInventoryFetcher(static function (): array {
|
|
return [
|
|
'isok' => true,
|
|
'data' => [
|
|
'devices_status' => [
|
|
'device-key-1' => [
|
|
'_dev_info' => [
|
|
'id' => 'shelly-plus-01',
|
|
'code' => 'SPSW-001PE16EU',
|
|
'model' => 'Shelly Plus 1PM',
|
|
'online' => 1,
|
|
],
|
|
'wifi_sta' => [
|
|
'ip' => '10.32.0.11',
|
|
],
|
|
'status' => [
|
|
'switch:0' => [
|
|
'output' => false,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
})
|
|
->setDeviceListFetcher(static function (): array {
|
|
return [
|
|
'isok' => true,
|
|
'data' => [
|
|
'devices' => [],
|
|
],
|
|
];
|
|
});
|
|
|
|
$publicOptions = $inventory->listRelayOptions();
|
|
$internalOptions = $inventory->listRelayOptions(true);
|
|
|
|
expect($publicOptions[0])->not->toHaveKey('local_ip');
|
|
expect($internalOptions[0])->toHaveKey('local_ip');
|
|
expect($internalOptions[0]['local_ip'])->toBe('10.32.0.11');
|
|
});
|
|
|
|
it('fails fast when Shelly inventory does not include owned devices status', function (): void {
|
|
$inventory = (new shelly_relay_inventory())->setInventoryFetcher(static function (): array {
|
|
return [
|
|
'isok' => true,
|
|
'data' => [],
|
|
];
|
|
});
|
|
|
|
expect(fn() => $inventory->listRelayOptions())
|
|
->toThrow(Exception::class, 'Shelly relay inventory response was missing devices_status');
|
|
});
|