From d26cba1f669e628c3e86cedec5b98ccd93df4d53 Mon Sep 17 00:00:00 2001 From: malle-pietje Date: Thu, 22 Oct 2020 14:23:29 +0200 Subject: [PATCH] API client class v1.1.58 - changed several references from UniFi SDN controller to UniFi Network controller - added optional payload parameter to the list_alarms() method/function, contributed by @MikeSiekkinen through PR #68 - added example showing how to disable/enable a UniFi switch port - updated restart_device() function/method, thanks go to @leonardogyn for reporting this - added example to modify outlet settings on a UniFi SmartPower PDU Pro, thanks go to @panthergm for providing access --- README.md | 4 +- examples/disable_switch_port.php | 78 +++++++++++++++++++++ examples/modify_smartpower_pdu_outlet.php | 84 +++++++++++++++++++++++ src/Client.php | 82 ++++++++++++---------- 4 files changed, 210 insertions(+), 38 deletions(-) create mode 100755 examples/disable_switch_port.php create mode 100755 examples/modify_smartpower_pdu_outlet.php diff --git a/README.md b/README.md index ac2af42..69acc46 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## UniFi Controller API client class -A PHP class that provides access to Ubiquiti's [**UniFi SDN Controller**](https://unifi-sdn.ui.com/) API, versions 4.X.X and 5.X.X of the UniFi SDN Controller software are supported (version 5.12.72 has been confirmed to work) as well as UbiOS-based controllers (version 5.12.59 has been confirmed to work). This class is used by our API browser tool which can be found [here](https://github.com/Art-of-WiFi/UniFi-API-browser). +A PHP class that provides access to Ubiquiti's [**UniFi Network Controller**](https://unifi-network.ui.com/) API, versions 4.X.X and 5.X.X of the UniFi Network Controller software are supported (version 5.12.72 has been confirmed to work) as well as UbiOS-based controllers (version 5.12.59 has been confirmed to work). This class is used by our API browser tool which can be found [here](https://github.com/Art-of-WiFi/UniFi-API-browser). The package can be installed manually or using composer/[packagist](https://packagist.org/packages/art-of-wifi/unifi-api-client) for easy inclusion in your projects. @@ -92,7 +92,7 @@ Please refer to the `examples/` directory for some more detailed examples which #### IMPORTANT NOTES: -1. In the above example, `$site_id` is the short site "name" (usually 8 characters long) that is visible in the URL when managing the site in the UniFi SDN Controller. For example with this URL: +1. In the above example, `$site_id` is the short site "name" (usually 8 characters long) that is visible in the URL when managing the site in the UniFi Network Controller. For example with this URL: `https://:8443/manage/site/jl3z2shm/dashboard` diff --git a/examples/disable_switch_port.php b/examples/disable_switch_port.php new file mode 100755 index 0000000..88c8941 --- /dev/null +++ b/examples/disable_switch_port.php @@ -0,0 +1,78 @@ +'; + +/** + * the MAC address of the UniFi switch to re-configure + */ +$device_mac = ''; + +/** + * index of port to modify/add + */ +$port_idx = 24; + +/** + * port configuration id to apply when enabling/disabling the port + * + * NOTE: + * port configurations are available through list_portconf() + */ +$port_conf_id = ''; + +/** + * initialize the UniFi API connection class and log in to the controller and do our thing + */ +$unifi_connection = new UniFi_API\Client($controlleruser, $controllerpassword, $controllerurl, $site_id, $controllerversion, false); +$set_debug_mode = $unifi_connection->set_debug($debug); +$loginresults = $unifi_connection->login(); +$data = $unifi_connection->list_devices($device_mac); +$device_id = $data[0]->device_id; +$existing_overrides = $data[0]->port_overrides; + +foreach ($existing_overrides as $key => $value) { + if (!empty($value->port_idx) && $value->port_idx === $port_idx) { + $updated_override = [ + 'portconf_id' => $port_conf_id, + 'port_idx' => $port_idx, + 'poe_mode' => $value->poe_mode, + 'name' => 'Your-port-name', + ]; + + $existing_overrides[$key] = $updated_override; + } +} + +$payload = [ + 'port_overrides' => $existing_overrides +]; + +$update_device = $unifi_connection->set_device_settings_base($device_id, $payload); + +/** + * provide feedback in json format + */ +echo json_encode($update_device, JSON_PRETTY_PRINT); \ No newline at end of file diff --git a/examples/modify_smartpower_pdu_outlet.php b/examples/modify_smartpower_pdu_outlet.php new file mode 100755 index 0000000..0ad40f3 --- /dev/null +++ b/examples/modify_smartpower_pdu_outlet.php @@ -0,0 +1,84 @@ +'; + +/** + * index value of the outlet to modify + */ +$outlet_idx = 20; + +/** + * new values for relay_state (enable/disable Power) and cycle_enabled (disable/enable Modem Power Cycle) for the above outlet, + * values must be boolean (true/false) + * + * NOTES: + * - here you can choose to also change the name of the outlet + * - outlet overrides are structured like this: + * { + * "index": 1, + * "name": "USB Outlet 1", + * "cycle_enabled": false, + * "relay_state": true + * } + */ +$new_relay_state = true; +$new_cycle_enabled = false; + +/** + * initialize the UniFi API connection class and log in to the controller and do our thing + */ +$unifi_connection = new UniFi_API\Client($controlleruser, $controllerpassword, $controllerurl, $site_id, $controllerversion); +$set_debug_mode = $unifi_connection->set_debug($debug); +$loginresults = $unifi_connection->login(); +if ($loginresults) { + $pdu_details = $unifi_connection->list_devices($pdu_mac); + + if (!empty($pdu_details) && property_exists($pdu_details[0], 'model') && $pdu_details[0]->model === 'USPPDUP' && property_exists($pdu_details[0], 'outlet_overrides')) { + $device_id = $pdu_details[0]->_id; + $outlet_overrides = $pdu_details[0]->outlet_overrides; + + foreach ($outlet_overrides as $key => $value) { + if ($value->index === $outlet_idx) { + $outlet_overrides[$key]->relay_state = $new_relay_state; + $outlet_overrides[$key]->cycle_enabled = $new_cycle_enabled; + } + } + + $pdu_update = $unifi_connection->set_device_settings_base($device_id, ['outlet_overrides' => $outlet_overrides]); + + /** + * provide feedback in json format + */ + echo 'results:' . PHP_EOL . PHP_EOL; + echo json_encode($pdu_update, JSON_PRETTY_PRINT); + echo PHP_EOL; + } else { + echo 'not a PDU device?'; + echo PHP_EOL; + } +} else { + echo 'we encountered a login error!'; + echo PHP_EOL; +} \ No newline at end of file diff --git a/src/Client.php b/src/Client.php index fe0cc6f..000cba0 100755 --- a/src/Client.php +++ b/src/Client.php @@ -31,7 +31,7 @@ class Client protected $is_loggedin = false; protected $is_unifi_os = false; protected $exec_retries = 0; - protected $class_version = '1.1.57'; + protected $class_version = '1.1.58'; private $cookies = ''; private $request_type = 'GET'; private $request_types_allowed = ['GET', 'POST', 'PUT', 'DELETE']; @@ -131,7 +131,10 @@ public function login() * first we check whether we have a "regular" controller or one based on UniFi OS, * prepare cURL and options */ - $ch = $this->get_curl_resource(); + if (!($ch = $this->get_curl_resource())) { + return false; + } + $curl_options = [ CURLOPT_HEADER => true, CURLOPT_POST => true, @@ -157,16 +160,17 @@ public function login() $curl_options = [ CURLOPT_NOBODY => false, CURLOPT_POSTFIELDS => json_encode(['username' => $this->user, 'password' => $this->password]), - CURLOPT_HTTPHEADER => ['content-type: application/json; charset=utf-8'] + CURLOPT_HTTPHEADER => ['content-type: application/json; charset=utf-8'], + CURLOPT_REFERER => $this->baseurl . '/login', + CURLOPT_URL => $this->baseurl . '/api/login' ]; + /** + * specific to UniFi OS-based controllers + */ if ($http_code === 200) { - $this->is_unifi_os = true; - $curl_options[CURLOPT_REFERER] = $this->baseurl . '/login'; - $curl_options[CURLOPT_URL] = $this->baseurl . '/api/auth/login'; - } else { - $curl_options[CURLOPT_REFERER] = $this->baseurl . '/login'; - $curl_options[CURLOPT_URL] = $this->baseurl . '/api/login'; + $this->is_unifi_os = true; + $curl_options[CURLOPT_URL] = $this->baseurl . '/api/auth/login'; } curl_setopt_array($ch, $curl_options); @@ -212,7 +216,7 @@ public function login() */ if ($http_code >= 200 && $http_code < 400 && !empty($body)) { preg_match_all('|Set-Cookie: (.*);|Ui', $headers, $results); - if (isset($results[1])) { + if (array_key_exists(1, $results)) { $this->cookies = implode(';', $results[1]); /** @@ -244,7 +248,10 @@ public function logout() /** * prepare cURL and options */ - $ch = $this->get_curl_resource(); + if (!($ch = $this->get_curl_resource())) { + return false; + } + $curl_options = [ CURLOPT_HEADER => true, CURLOPT_POST => true @@ -309,19 +316,19 @@ public function authorize_guest($mac, $minutes, $up = null, $down = null, $MByte /** * if we have received values for up/down/MBytes/ap_mac we append them to the payload array to be submitted */ - if (!empty($up)) { + if (!is_null($up)) { $payload['up'] = intval($up); } - if (!empty($down)) { + if (!is_null($down)) { $payload['down'] = intval($down); } - if (!empty($MBytes)) { + if (!is_null($MBytes)) { $payload['bytes'] = intval($MBytes); } - if (isset($ap_mac)) { + if (!is_null($ap_mac)) { $payload['ap_mac'] = strtolower($ap_mac); } @@ -1661,7 +1668,7 @@ public function stat_payment($within = null) public function create_hotspotop($name, $x_password, $note = null) { $payload = ['name' => $name, 'x_password' => $x_password]; - if (isset($note)) { + if (!is_null($note)) { $payload['note'] = trim($note); } @@ -1709,19 +1716,19 @@ public function create_voucher( 'quota' => intval($quota) ]; - if (isset($note)) { + if (!is_null($note)) { $payload['note'] = trim($note); } - if (!empty($up)) { + if (!is_null($up)) { $payload['up'] = intval($up); } - if (!empty($down)) { + if (!is_null($down)) { $payload['down'] = intval($down); } - if (!empty($MBytes)) { + if (!is_null($MBytes)) { $payload['bytes'] = intval($MBytes); } @@ -1791,7 +1798,7 @@ public function list_dpi_stats_filtered($type = 'by_cat', $cat_filter = null) $payload = ['type' => $type]; - if ($cat_filter !== null && $type == 'by_app' && is_array($cat_filter)) { + if (!is_null($cat_filter) && $type == 'by_app' && is_array($cat_filter)) { $payload['cats'] = $cat_filter; } @@ -1879,18 +1886,18 @@ public function adopt_device($mac) * Reboot a device * ---------------------- * return true on success - * required parameter = device MAC address - * optional parameter = string; two options: 'soft' or 'hard', defaults to soft - * soft can be used for all devices, requests a plain restart of that device - * hard is special for PoE switches and besides the restart also requests a - * power cycle on all PoE capable ports. Keep in mind that a 'hard' reboot - * does *NOT* trigger a factory-reset, as it somehow could suggest. + * required parameter = device MAC address + * optional parameter = string; two options: 'soft' or 'hard', defaults to soft + * soft can be used for all devices, requests a plain restart of that device + * hard is special for PoE switches and besides the restart also requests a + * power cycle on all PoE capable ports. Keep in mind that a 'hard' reboot + * does *NOT* trigger a factory-reset. */ - public function restart_device($mac, $type = 'soft') + public function restart_device($mac, $reboot_type = 'soft') { $payload = ['cmd' => 'restart', 'mac' => strtolower($mac)]; - if (!empty($type) && in_array($type, ['soft', 'hard'])) { - $payload['type'] = strtolower($type); + if (!empty($reboot_type) && in_array($reboot_type, ['soft', 'hard'])) { + $payload['reboot_type'] = strtolower($reboot_type); } return $this->fetch_results_boolean('/api/s/' . $this->site . '/cmd/devmgr', $payload); @@ -2501,10 +2508,13 @@ public function list_events($historyhours = 720, $start = 0, $limit = 3000) * List alarms * ----------- * returns an array of known alarms + * optional parameter = array of flags to filter by + * Example: ["archived" => false, "key" => "EVT_GW_WANTransition"] + * return only unarchived for a specific key */ - public function list_alarms() + public function list_alarms($payload = []) { - return $this->fetch_results('/api/s/' . $this->site . '/list/alarm'); + return $this->fetch_results('/api/s/' . $this->site . '/list/alarm', $payload); } /** @@ -2755,7 +2765,7 @@ public function create_radius_account($name, $x_password, $tunnel_type, $tunnel_ 'tunnel_medium_type' => (int) $tunnel_medium_type ]; - if (isset($vlan)) { + if (!is_null($vlan)) { $payload['vlan'] = (int) $vlan; } @@ -3037,7 +3047,7 @@ public function get_debug() */ public function get_last_results_raw($return_json = false) { - if ($this->last_results_raw !== null) { + if (!is_null($this->last_results_raw)) { if ($return_json) { return json_encode($this->last_results_raw, JSON_PRETTY_PRINT); } @@ -3055,7 +3065,7 @@ public function get_last_results_raw($return_json = false) */ public function get_last_error_message() { - if ($this->last_error_message !== null) { + if (!is_null($this->last_error_message)) { return $this->last_error_message; } @@ -3414,7 +3424,7 @@ protected function exec_curl($path, $payload = null) CURLOPT_URL => $url ]; - if ($payload !== null) { + if (!is_null($payload)) { $json_payload = json_encode($payload, JSON_UNESCAPED_SLASHES); $curl_options[CURLOPT_POST] = true; $curl_options[CURLOPT_POSTFIELDS] = $json_payload;