Integrate Shelly module with new routes, classes, helpers, and configurations
- Added `shelly` class to manage API operations, handle requests, and validate configurations. - Introduced `shelly_i` interface and supporting helpers: `shelly_device_state`, `shelly_request_body_get_states`, and `shelly_response_body_get_states`. - Created new routes for fetching and updating Shelly configurations (`/shelly/config`). - Added Shelly module configurations: `enabled`, `secret_key`, and `server_url`. - Implemented `shelly_c` for module setup and configuration handling. - Integrated Shelly initialization in `index.php`.
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace classes;
|
||||
|
||||
require_once WD . '/modules/shelly/shelly_c.php';
|
||||
/** Actions */
|
||||
require_once WD . '/modules/shelly/actions/shelly_search_a.php';
|
||||
|
||||
use Exception;
|
||||
use interfaces\shelly_i;
|
||||
use shelly\actions\shelly_search_a;
|
||||
use shelly\shelly_c;
|
||||
|
||||
class shelly implements shelly_i
|
||||
{
|
||||
/**
|
||||
* Configuration of the shelly module
|
||||
* @var shelly_c
|
||||
*/
|
||||
public shelly_c $config;
|
||||
|
||||
/**
|
||||
* API URL
|
||||
* @var string
|
||||
*/
|
||||
private string $api_url = 'https://api.shelly.com/';
|
||||
|
||||
/**
|
||||
* ACTION: shelly_SEARCH
|
||||
* @see shelly_search_a
|
||||
* @notation This action is when a company search request is made, and logs the request in the database
|
||||
* @var shelly_search_a $shelly_search
|
||||
*/
|
||||
private shelly_search_a $shelly_search;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = new shelly_c();
|
||||
/** Actions */
|
||||
$this->shelly_search = new shelly_search_a();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the module is not enabled, the license plate is invalid, the daily limit is exceeded, or the secret key is invalid
|
||||
*/
|
||||
function sendRequest(
|
||||
string $endpoint,
|
||||
array $data = [],
|
||||
string $method = 'GET'
|
||||
): object
|
||||
{
|
||||
// Validate the module is enabled
|
||||
self::requireModuleEnabled();
|
||||
// Validate the secret key
|
||||
self::requireValidSecretKey();
|
||||
// Send the request
|
||||
$response = match ($method) {
|
||||
//'GET' => self::sendGetRequest($endpoint, $data),
|
||||
//'POST' => self::sendPostRequest($search, $endpoint, $data),
|
||||
//'PUT' => self::sendPutRequest($search, $endpoint, $data),
|
||||
//'DELETE' => self::sendDeleteRequest($search, $endpoint, $data),
|
||||
default => self::exception(
|
||||
[
|
||||
'method' => $method,
|
||||
'endpoint' => $endpoint,
|
||||
'data' => $data,
|
||||
'response' => null,
|
||||
'status_code' => 400,
|
||||
'error' => 'Invalid request method',
|
||||
],
|
||||
500
|
||||
),
|
||||
};
|
||||
// Add the usage to the request log
|
||||
$this->shelly_search->shelly_search($response, 200);
|
||||
// Return the response
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function requireModuleEnabled(): void
|
||||
{
|
||||
// Check if the module is enabled
|
||||
if (!$this->config->enabled->isTrue()) {
|
||||
throw new Exception('The shelly module is not enabled');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function requireValidSecretKey(): void
|
||||
{
|
||||
// Check if the secret key is valid
|
||||
if ($this->config->secret_key->getVariableValue() === null) {
|
||||
self::exception(
|
||||
[
|
||||
'status_code' => 500,
|
||||
'error' => 'Invalid secret key defined in the config (shelly_secret_key_c)',
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
function exception(array $data, int $status_code = 500): object
|
||||
{
|
||||
// Check if the response is valid JSON
|
||||
if (!json_decode($data['response'])) {
|
||||
throw new Exception('Invalid response');
|
||||
}
|
||||
// Add the request to the log
|
||||
$this->shelly_search->shelly_search($data, $status_code);;
|
||||
return throw new Exception($data['error'] ?? 'An error occurred while processing the request, in ' . $this->config->getModuleName() . ' module');
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,7 @@ require_once 'classes/upload_store.php';
|
||||
require_once 'classes/attachments.php';
|
||||
require_once 'classes/attachment_store.php';
|
||||
require_once 'classes/virkdata.php';
|
||||
require_once 'classes/shelly.php';
|
||||
|
||||
/**
|
||||
* Modules
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace interfaces;
|
||||
|
||||
use Exception;
|
||||
|
||||
interface shelly_i
|
||||
{
|
||||
/**
|
||||
* Send a request to the shelly api
|
||||
* @param string $endpoint The endpoint to send the request to (e.g. "latest")
|
||||
* @param array $data The data to send with the request (e.g. ["key" => "value"])
|
||||
* @param string $method The method to use for the request (e.g. "GET")
|
||||
* @return object The response from the shelly module
|
||||
*/
|
||||
function sendRequest(string $endpoint, array $data, string $method): object;
|
||||
|
||||
/**
|
||||
* Require the module to be enabled
|
||||
* @return void
|
||||
* @throws Exception If the module is not enabled
|
||||
*/
|
||||
function requireModuleEnabled(): void;
|
||||
|
||||
|
||||
/**
|
||||
* Require the secret key to be valid
|
||||
* @return void
|
||||
* @throws Exception If the secret key is not valid
|
||||
*/
|
||||
function requireValidSecretKey(): void;
|
||||
|
||||
/**
|
||||
* Send a GET request to the shelly
|
||||
* @param string $endpoint The endpoint to send the request to (e.g. "latest")
|
||||
* @param array $data The data to send with the request (e.g. ["key" => "value"])
|
||||
* @return object The response from the shelly
|
||||
*/
|
||||
//Todo: add function sendGetRequest(string $endpoint, array $data): object;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace shelly\actions;
|
||||
|
||||
use Exception;
|
||||
use traits\module_action_t;
|
||||
|
||||
class shelly_search_a
|
||||
{
|
||||
use module_action_t;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the module name is invalid
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
self::set_module_name('shelly');
|
||||
|
||||
/** Add the action to the list of valid actions */
|
||||
// Search
|
||||
self::add_action(
|
||||
'SHELLY_SEARCH',
|
||||
'This action is when a search is performed',
|
||||
// Method to call
|
||||
self::class . '::shelly_search',
|
||||
[
|
||||
'search' => 'The search term',
|
||||
'data' => 'The data returned from the conversion (If any)',
|
||||
'status_code' => 'The status code of the action',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search action
|
||||
* @param array|object $data The data returned from the conversion (If any)
|
||||
* @param int $status_code The status code of the action
|
||||
* @throws Exception If the action name is invalid
|
||||
* @throws Exception If the action data is invalid
|
||||
* @throws Exception If the action status code is invalid
|
||||
* @throws Exception If the action is not valid
|
||||
*/
|
||||
public function shelly_search(array|object $data = [], int $status_code = 0): void
|
||||
{
|
||||
self::set_action('SHELLY_SEARCH');
|
||||
// If the data is an object, convert it to an array
|
||||
if (is_object($data)) {
|
||||
$data = (array)$data;
|
||||
}
|
||||
// Validate the action data
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Action data is invalid');
|
||||
}
|
||||
// Validate the action status code
|
||||
self::set_data($data);
|
||||
self::set_status($status_code);
|
||||
// Add the action to the log
|
||||
self::add_action_log(
|
||||
self::get_action_name(),
|
||||
(int)self::get_status(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace shelly\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class shelly_enabled_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'shelly',
|
||||
'enabled',
|
||||
'bool',
|
||||
true,
|
||||
null,
|
||||
'Whether the shelly module is enabled or not',
|
||||
'1',
|
||||
false,
|
||||
'false'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace shelly\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class shelly_secret_key_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'shelly',
|
||||
'secret_key',
|
||||
'string',
|
||||
false,
|
||||
null,
|
||||
'The API token for shelly',
|
||||
'1',
|
||||
true,
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace shelly\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class shelly_server_url_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'shelly',
|
||||
'server_url',
|
||||
'string',
|
||||
true,
|
||||
null,
|
||||
'The API server URL for shelly',
|
||||
'',
|
||||
false,
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace modules\shelly\helpers;
|
||||
|
||||
/**
|
||||
* @class shelly_device_state
|
||||
* @description The universal device state object
|
||||
* @docs https://shelly-api-docs.shelly.cloud/cloud-control-api/communication-v2#get-devices-state
|
||||
*/
|
||||
class shelly_device_state
|
||||
{
|
||||
/**
|
||||
* @var string $id
|
||||
* @description The device id
|
||||
*/
|
||||
public string $id;
|
||||
/**
|
||||
* @var string $type
|
||||
* @description The device type
|
||||
*/
|
||||
public string $type;
|
||||
/**
|
||||
* @var string $code
|
||||
* @description The device code
|
||||
*/
|
||||
public string $code;
|
||||
/**
|
||||
* @var string $gen
|
||||
* @description The device generation
|
||||
*/
|
||||
public string $gen;
|
||||
/**
|
||||
* @var int $online
|
||||
* @description The device online status
|
||||
* @values 0 | 1
|
||||
*/
|
||||
public int $online;
|
||||
/**
|
||||
* @var array $status
|
||||
* @description The device status
|
||||
*/
|
||||
public array $status;
|
||||
/**
|
||||
* @var array $settings
|
||||
* @description The device settings
|
||||
*/
|
||||
public array $settings;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace modules\shelly\helpers;
|
||||
|
||||
/**
|
||||
* @class shelly_request_body_get_states
|
||||
* @description Get device states
|
||||
* @docs https://shelly-api-docs.shelly.cloud/cloud-control-api/communication-v2#get-devices-state
|
||||
*/
|
||||
class shelly_request_body_get_states
|
||||
{
|
||||
/**
|
||||
* @var string[] $ids
|
||||
* @description List of device ids (between 1 and 10).
|
||||
*/
|
||||
public array $ids;
|
||||
/**
|
||||
* @var string[] $select
|
||||
* @description List containing any of: `"status"`,`"settings"`. Additional data to fetch.
|
||||
*/
|
||||
public array $select;
|
||||
/**
|
||||
* @var array $pick
|
||||
* @description Fetch only specified properties of the additional data. Fetch all if not provided.
|
||||
*/
|
||||
public array $pick;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace modules\shelly\helpers;
|
||||
|
||||
class shelly_response_body_get_states
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace shelly;
|
||||
require_once WD . '/modules/shelly/config/shelly_enabled_c.php';
|
||||
require_once WD . '/modules/shelly/config/shelly_secret_key_c.php';
|
||||
require_once WD . '/modules/shelly/config/shelly_server_url_c.php';
|
||||
// Require helpers
|
||||
require_once WD . '/modules/shelly/helpers/shelly_device_state.php';
|
||||
|
||||
require_once WD . '/modules/shelly/helpers/shelly_request_body_get_states.php';
|
||||
require_once WD . '/modules/shelly/helpers/shelly_response_body_get_states.php';
|
||||
|
||||
use shelly\config\shelly_server_url_c;
|
||||
use shelly\config\shelly_enabled_c;
|
||||
use shelly\config\shelly_secret_key_c;
|
||||
use traits\module_config_t;
|
||||
|
||||
class shelly_c
|
||||
{
|
||||
use module_config_t;
|
||||
|
||||
/**
|
||||
* The status of the shelly module
|
||||
* @var shelly_enabled_c
|
||||
*/
|
||||
public shelly_enabled_c $enabled;
|
||||
/**
|
||||
* The secret key for the shelly module (API token)
|
||||
* @var shelly_secret_key_c
|
||||
*/
|
||||
public shelly_secret_key_c $secret_key;
|
||||
/**
|
||||
* The server url for the shelly module
|
||||
* @var shelly_server_url_c
|
||||
*/
|
||||
public shelly_server_url_c $server_url;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setupConfig('shelly');
|
||||
$this->allowUpdate([
|
||||
shelly_enabled_c::class,
|
||||
shelly_secret_key_c::class,
|
||||
shelly_server_url_c::class
|
||||
]);
|
||||
$this->enabled = new shelly_enabled_c();
|
||||
$this->secret_key = new shelly_secret_key_c();
|
||||
$this->server_url = new shelly_server_url_c();
|
||||
}
|
||||
}
|
||||
@@ -638,5 +638,36 @@ class moduleConfigRoute
|
||||
'modules_virkdata_config' => 'Update virkdata config'
|
||||
]
|
||||
);
|
||||
/** Shelly config -> GET */
|
||||
$this->get('/shelly/config', function () {
|
||||
global $response;
|
||||
$this->requirePermission('modules_shelly_config');
|
||||
$user = (new authentication())->get_user();
|
||||
if ($user) {
|
||||
(new logs_o())->add('shelly_config', 'global', 1, $user->id, 'SHELLY_CONFIG', 'Successfully fetched shelly config');
|
||||
$response->success(
|
||||
(new \classes\shelly())->config->getConfigRequest()
|
||||
);
|
||||
} else {
|
||||
(new logs_o())->add('shelly_config', 'global', 1, 0, 'VIRKDATA_CONFIG', 'No user found, or invalid session');
|
||||
}
|
||||
},
|
||||
[
|
||||
'modules_shelly_config' => 'Get shelly config'
|
||||
]
|
||||
);
|
||||
$this->post('/shelly/config', function () {
|
||||
global $response;
|
||||
$this->requirePermission('modules_shelly_config');
|
||||
$user = (new authentication())->get_user();
|
||||
if ($user) {
|
||||
(new logs_o())->add('shelly_config', 'global', 1, $user->id, 'SHELLY_CONFIG', 'Successfully updated shelly config');
|
||||
$response->success(
|
||||
(new \classes\shelly())->config->postConfigRequest()
|
||||
);
|
||||
} else {
|
||||
(new logs_o())->add('shelly_config', 'global', 1, 0, 'SHELLY_CONFIG', 'No user found, or invalid session');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user