- Implement generation detection logic for Shelly devices using model codes, metadata, and type inference. - Extend relay switch and inventory handling to include generation capabilities. - Ensure compatibility with Gen1, Gen2, and Gen3 devices for relay control and diagnostics. - Update unit tests to validate generation inference, fallback behavior, and API compatibility.
94 lines
6.8 KiB
PHP
94 lines
6.8 KiB
PHP
<?php
|
|
|
|
app_require('classes/edge_gateway_manager.php');
|
|
|
|
use classes\edge_gateway_manager;
|
|
|
|
it('keeps relay dispatch and discovery queueing on the edge gateway manager', function (): void {
|
|
$managerSource = file_get_contents(app_path('classes/edge_gateway_manager.php'));
|
|
$operationServiceSource = file_get_contents(app_path('classes/edge_gateway_operation_service.php'));
|
|
|
|
expect($managerSource)->not->toBeFalse();
|
|
expect($managerSource)->toContain('public function queueDiscovery');
|
|
expect($managerSource)->toContain('public function dispatchRelayStatus');
|
|
expect($managerSource)->toContain('public function dispatchRelayStatusLocalOnly');
|
|
expect($managerSource)->toContain('public function dispatchRelaySwitch');
|
|
expect($managerSource)->toContain('public function dispatchRelaySwitchLocalOnly');
|
|
expect($managerSource)->toContain('public function dispatchRelaySwitchWithTimer');
|
|
expect($managerSource)->toContain('public function dispatchRelaySwitchLocalOnlyWithTimer');
|
|
expect($managerSource)->toContain('private function createCommandJob');
|
|
expect($managerSource)->toContain("'GET_RELAY_STATUS'");
|
|
expect($managerSource)->toContain("'SET_RELAY_STATE'");
|
|
expect($managerSource)->toContain("'relayId' => \$logicalRelayId");
|
|
expect($managerSource)->toContain("'deviceId' => \$binding['device_id']");
|
|
expect($managerSource)->toContain("'localIp' => \$binding['local_ip']");
|
|
expect($managerSource)->toContain("'channel' => (int)\$binding['channel']");
|
|
expect($managerSource)->toContain("'on' => \$on");
|
|
expect($managerSource)->toContain("'require_fast_path' => \$requireFastLocalPath");
|
|
expect($managerSource)->toContain('private function resolveRelayBindingDeviceGeneration');
|
|
expect($managerSource)->toContain('private function normalizeDeviceCapabilities');
|
|
expect($managerSource)->toContain("\$request['device_generation'] = \$deviceGeneration;");
|
|
expect($managerSource)->toContain("\$request['toggle_after'] = \$toggleAfterSeconds;");
|
|
expect($managerSource)->toContain('private function expireTimedOutRelayStatusCommandJobs');
|
|
expect($managerSource)->toContain("AND command_type = 'GET_RELAY_STATUS'");
|
|
expect($managerSource)->toContain("'Edge gateway command timed out', null, 'TIMED_OUT'");
|
|
expect($managerSource)->toContain('private function normalizeCommandFailureStatus');
|
|
expect($managerSource)->toContain('private function isCommandTimeoutError');
|
|
expect($managerSource)->toContain('local_transport_override');
|
|
expect($managerSource)->toContain('private function resolveRelayBindingLocalIp');
|
|
expect($managerSource)->toContain('private function findShellyCloudRelayLocalIp');
|
|
expect($managerSource)->toContain('private function backfillRelayBindingLocalIpFromInventory');
|
|
expect($managerSource)->toContain('$bindingObject->local_ip->set($localIp);');
|
|
expect($managerSource)->toContain("'local_ip' => \$localIp");
|
|
expect($managerSource)->toContain('(new shelly_relay_inventory())->listRelayOptions()');
|
|
expect($managerSource)->toContain('public function buildUpdateOperationRequest');
|
|
expect($managerSource)->toContain('public function rotateGatewayCredentials');
|
|
expect($operationServiceSource)->toContain('public function queueOperation');
|
|
expect($operationServiceSource)->toContain('public function cancelOperation');
|
|
expect($operationServiceSource)->toContain('public function claimNextOperation');
|
|
expect($operationServiceSource)->toContain('public function completeAgentOperation');
|
|
expect($operationServiceSource)->toContain("public const STATUS_CANCEL_REQUESTED = 'CANCEL_REQUESTED';");
|
|
expect($operationServiceSource)->toContain("public const STATUS_CANCELLED = 'CANCELLED';");
|
|
expect($operationServiceSource)->toContain("public const ERROR_CANCELLED = 'EDGE_GATEWAY_CANCELLED';");
|
|
expect($operationServiceSource)->toContain('public const OPERATION_LEASE_SECONDS = 45;');
|
|
expect($operationServiceSource)->toContain('private function refreshOperationLease');
|
|
expect($operationServiceSource)->toContain('agent_instance_id');
|
|
expect($operationServiceSource)->toContain('lease_expires_at');
|
|
expect($operationServiceSource)->toContain("'operation_type' => \$type");
|
|
expect($managerSource)->toContain("command_type");
|
|
});
|
|
|
|
it('loads relay command helpers on the manager and gateway operations on the dedicated service', function (): void {
|
|
$reflection = new ReflectionClass(edge_gateway_manager::class);
|
|
$operationServiceReflection = new ReflectionClass(\classes\edge_gateway_operation_service::class);
|
|
|
|
expect($reflection->hasMethod('queueDiscovery'))->toBeTrue();
|
|
expect($reflection->hasMethod('pollCommand'))->toBeTrue();
|
|
expect($reflection->hasMethod('submitCommandResult'))->toBeTrue();
|
|
expect($reflection->hasMethod('dispatchRelayStatus'))->toBeTrue();
|
|
expect($reflection->hasMethod('dispatchRelayStatusLocalOnly'))->toBeTrue();
|
|
expect($reflection->hasMethod('dispatchRelaySwitch'))->toBeTrue();
|
|
expect($reflection->hasMethod('dispatchRelaySwitchLocalOnly'))->toBeTrue();
|
|
expect($reflection->hasMethod('dispatchRelaySwitchWithTimer'))->toBeTrue();
|
|
expect($reflection->hasMethod('dispatchRelaySwitchLocalOnlyWithTimer'))->toBeTrue();
|
|
expect($reflection->hasMethod('claimNextCommandJob'))->toBeTrue();
|
|
expect($reflection->getMethod('claimNextCommandJob')->isPrivate())->toBeTrue();
|
|
expect($reflection->hasMethod('syncDeviceInventory'))->toBeTrue();
|
|
expect($reflection->getMethod('syncDeviceInventory')->isPrivate())->toBeTrue();
|
|
expect($reflection->hasMethod('resolveRelayBindingDeviceGeneration'))->toBeTrue();
|
|
expect($reflection->getMethod('resolveRelayBindingDeviceGeneration')->isPrivate())->toBeTrue();
|
|
expect($reflection->hasMethod('normalizeDeviceCapabilities'))->toBeTrue();
|
|
expect($reflection->getMethod('normalizeDeviceCapabilities')->isPrivate())->toBeTrue();
|
|
expect($reflection->hasMethod('resolveRelayBindingLocalIp'))->toBeTrue();
|
|
expect($reflection->getMethod('resolveRelayBindingLocalIp')->isPrivate())->toBeTrue();
|
|
expect($reflection->hasMethod('backfillRelayBindingLocalIpFromInventory'))->toBeTrue();
|
|
expect($reflection->getMethod('backfillRelayBindingLocalIpFromInventory')->isPrivate())->toBeTrue();
|
|
expect($reflection->hasMethod('syncGatewayInventory'))->toBeTrue();
|
|
expect($operationServiceReflection->hasMethod('queueOperation'))->toBeTrue();
|
|
expect($operationServiceReflection->hasMethod('cancelOperation'))->toBeTrue();
|
|
expect($operationServiceReflection->hasMethod('listOperations'))->toBeTrue();
|
|
expect($operationServiceReflection->hasMethod('claimNextOperation'))->toBeTrue();
|
|
expect($operationServiceReflection->hasMethod('appendAgentOperationEvent'))->toBeTrue();
|
|
expect($operationServiceReflection->hasMethod('completeAgentOperation'))->toBeTrue();
|
|
});
|