1
0
mirror of https://github.com/beestat/app.git synced 2025-08-07 09:01:32 -04:00

Fixed #373 - beestat loads for home owner but not member

This commit is contained in:
Jon Ziebell 2023-01-24 17:44:13 -05:00
parent dd0ddd4452
commit dff338b580
3 changed files with 332 additions and 144 deletions

View File

@ -163,6 +163,11 @@ class ecobee extends external_api {
} }
$curl['url'] = 'https://api.ecobee.com' . $full_endpoint; $curl['url'] = 'https://api.ecobee.com' . $full_endpoint;
// Allow a completely custom endpoint if desired.
if(str_starts_with($endpoint, 'https://') === true) {
$curl['url'] = $endpoint;
}
if ($method === 'GET') { if ($method === 'GET') {
$curl['url'] .= '?' . http_build_query($arguments); $curl['url'] .= '?' . http_build_query($arguments);
} }
@ -221,6 +226,13 @@ class ecobee extends external_api {
$this->api('ecobee_token', 'delete', $ecobee_token['ecobee_token_id']); $this->api('ecobee_token', 'delete', $ecobee_token['ecobee_token_id']);
throw new cora\exception('Ecobee access was revoked by user.', 10508, false, null, false); throw new cora\exception('Ecobee access was revoked by user.', 10508, false, null, false);
} }
else if (isset($response['status']) === true && $response['status']['code'] === 9) {
// Invalid selection. No thermostats in selection. Ensure permissions and selection.
if($this::$log_mysql !== 'all') {
$this->log_mysql($curl_response, true);
}
throw new cora\exception('No thermostats found.', 10511, false, null, false);
}
else if (isset($response['status']) === true && $response['status']['code'] === 3) { else if (isset($response['status']) === true && $response['status']['code'] === 3) {
if ( if (
isset($response['status']['message']) === true && isset($response['status']['message']) === true &&

View File

@ -58,17 +58,7 @@ class ecobee_sensor extends cora\crud {
public function sync() { public function sync() {
// Get the thermostat list from ecobee with sensors. Keep this identical to // Get the thermostat list from ecobee with sensors. Keep this identical to
// ecobee_thermostat->sync() to leverage caching. // ecobee_thermostat->sync() to leverage caching.
$response = $this->api( $include = [
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'thermostat',
'arguments' => [
'body' => json_encode([
'selection' => [
'selectionType' => 'registered',
'selectionMatch' => '',
'includeRuntime' => true, 'includeRuntime' => true,
'includeExtendedRuntime' => true, 'includeExtendedRuntime' => true,
'includeElectricity' => true, 'includeElectricity' => true,
@ -94,16 +84,16 @@ class ecobee_sensor extends cora\crud {
/** /**
* 'includeReminders' => true * 'includeReminders' => true
* *
* While documented, this is not available for general API use * While documented, this is not available for general API use unless
* unless you are a technician user. * you are a technician user.
* *
* The reminders and the includeReminders flag are something extra * The reminders and the includeReminders flag are something extra for
* for ecobee Technicians. It allows them to set and receive * ecobee Technicians. It allows them to set and receive reminders with
* reminders with more detail than the usual alert reminder type. * more detail than the usual alert reminder type. These reminders are
* These reminders are only available to Technician users, which * only available to Technician users, which is why you aren't seeing
* is why you aren't seeing any new information when you set that * any new information when you set that flag to true. Thanks for
* flag to true. Thanks for pointing out the lack of documentation * pointing out the lack of documentation regarding this. We'll get this
* regarding this. We'll get this updated as soon as possible. * updated as soon as possible.
* *
* *
* https://getsatisfaction.com/api/topics/what-does-includereminders-do-when-calling-get-thermostat?rfm=1 * https://getsatisfaction.com/api/topics/what-does-includereminders-do-when-calling-get-thermostat?rfm=1
@ -112,27 +102,125 @@ class ecobee_sensor extends cora\crud {
/** /**
* 'includeSecuritySettings' => true * 'includeSecuritySettings' => true
* *
* While documented, this is not made available for general API * While documented, this is not made available for general API use
* use unless you are a utility. If you try to include this an * unless you are a utility. If you try to include this an
* "Authentication failed" error will be returned. * "Authentication failed" error will be returned.
* *
* Special accounts such as Utilities are permitted an alternate * Special accounts such as Utilities are permitted an alternate method
* method of authorization using implicit authorization. This * of authorization using implicit authorization. This method permits
* method permits the Utility application to authorize against * the Utility application to authorize against their own specific
* their own specific account without the requirement of a PIN. * account without the requirement of a PIN. This method is limited to
* This method is limited to special contractual obligations and * special contractual obligations and is not available for 3rd party
* is not available for 3rd party applications who are not * applications who are not Utilities.
* Utilities. *
* *
* https://www.ecobee.com/home/developer/api/documentation/v1/objects/SecuritySettings.shtml * https://www.ecobee.com/home/developer/api/documentation/v1/objects/SecuritySettings.shtml
* https://www.ecobee.com/home/developer/api/documentation/v1/auth/auth-intro.shtml * https://www.ecobee.com/home/developer/api/documentation/v1/auth/auth-intro.shtml
*
*/ */
] ];
try {
$response = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'thermostat',
'arguments' => [
'body' => json_encode([
'selection' => array_merge(
[
'selectionType' => 'registered',
'selectionMatch' => ''
],
$include
)
]) ])
] ]
] ]
); );
if(count($response['thermostatList']) === 0) {
throw new cora\exception('No thermostats found.', 10511, false, null, false);
}
} catch(cora\exception $e) {
// If no thermostats found (ie. not the owner of any homes that contain a thermostat)
if($e->getCode() === 10511) {
$homes = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'https://home.hm-prod.ecobee.com/homes',
'arguments' => [
]
]
);
$home_ids = array_column($homes['homes'], 'homeID');
$serial_numbers = [];
foreach($home_ids as $home_id) {
$devices = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'https://home.hm-prod.ecobee.com/home/' . $home_id . '/devices',
'arguments' => [
]
]
);
/**
* This is a select distinct from ecobee_thermostat. Ideally it
* would be possible to send *all* serial numbers from the devices
* call to the GET->thermostat API call, but that throws an error if
* you include a serial number for something that's not a
* thermostat. So I have to keep this array to identify valid serial
* numbers.
*/
$model_numbers = [
'athenaSmart',
'apolloSmart',
'idtSmart',
'nikeSmart',
'siSmart',
'corSmart',
'vulcanSmart',
'aresSmart',
'artemisSmart'
];
foreach($devices['devices'] as $device) {
if(in_array($device['modelNumber'], $model_numbers) === true) {
$serial_numbers[] = $device['serialNumber'];
}
}
}
$response = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'thermostat',
'arguments' => [
'body' => json_encode([
'selection' => array_merge(
[
'selectionType' => 'thermostats',
'selectionMatch' => implode(',', $serial_numbers),
],
$include
)
])
]
]
);
} else {
throw $e;
}
}
// Loop over the returned sensors and create/update them as necessary. // Loop over the returned sensors and create/update them as necessary.
$sensor_ids_to_keep = []; $sensor_ids_to_keep = [];

View File

@ -21,17 +21,7 @@ class ecobee_thermostat extends cora\crud {
public function sync() { public function sync() {
// Get the thermostat list from ecobee with sensors. Keep this identical to // Get the thermostat list from ecobee with sensors. Keep this identical to
// ecobee_sensor->sync() to leverage caching. // ecobee_sensor->sync() to leverage caching.
$response = $this->api( $include = [
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'thermostat',
'arguments' => [
'body' => json_encode([
'selection' => [
'selectionType' => 'registered',
'selectionMatch' => '',
'includeRuntime' => true, 'includeRuntime' => true,
'includeExtendedRuntime' => true, 'includeExtendedRuntime' => true,
'includeElectricity' => true, 'includeElectricity' => true,
@ -57,16 +47,16 @@ class ecobee_thermostat extends cora\crud {
/** /**
* 'includeReminders' => true * 'includeReminders' => true
* *
* While documented, this is not available for general API use * While documented, this is not available for general API use unless
* unless you are a technician user. * you are a technician user.
* *
* The reminders and the includeReminders flag are something extra * The reminders and the includeReminders flag are something extra for
* for ecobee Technicians. It allows them to set and receive * ecobee Technicians. It allows them to set and receive reminders with
* reminders with more detail than the usual alert reminder type. * more detail than the usual alert reminder type. These reminders are
* These reminders are only available to Technician users, which * only available to Technician users, which is why you aren't seeing
* is why you aren't seeing any new information when you set that * any new information when you set that flag to true. Thanks for
* flag to true. Thanks for pointing out the lack of documentation * pointing out the lack of documentation regarding this. We'll get this
* regarding this. We'll get this updated as soon as possible. * updated as soon as possible.
* *
* *
* https://getsatisfaction.com/api/topics/what-does-includereminders-do-when-calling-get-thermostat?rfm=1 * https://getsatisfaction.com/api/topics/what-does-includereminders-do-when-calling-get-thermostat?rfm=1
@ -75,27 +65,125 @@ class ecobee_thermostat extends cora\crud {
/** /**
* 'includeSecuritySettings' => true * 'includeSecuritySettings' => true
* *
* While documented, this is not made available for general API * While documented, this is not made available for general API use
* use unless you are a utility. If you try to include this an * unless you are a utility. If you try to include this an
* "Authentication failed" error will be returned. * "Authentication failed" error will be returned.
* *
* Special accounts such as Utilities are permitted an alternate * Special accounts such as Utilities are permitted an alternate method
* method of authorization using implicit authorization. This * of authorization using implicit authorization. This method permits
* method permits the Utility application to authorize against * the Utility application to authorize against their own specific
* their own specific account without the requirement of a PIN. * account without the requirement of a PIN. This method is limited to
* This method is limited to special contractual obligations and * special contractual obligations and is not available for 3rd party
* is not available for 3rd party applications who are not * applications who are not Utilities.
* Utilities. *
* *
* https://www.ecobee.com/home/developer/api/documentation/v1/objects/SecuritySettings.shtml * https://www.ecobee.com/home/developer/api/documentation/v1/objects/SecuritySettings.shtml
* https://www.ecobee.com/home/developer/api/documentation/v1/auth/auth-intro.shtml * https://www.ecobee.com/home/developer/api/documentation/v1/auth/auth-intro.shtml
*
*/ */
] ];
try {
$response = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'thermostat',
'arguments' => [
'body' => json_encode([
'selection' => array_merge(
[
'selectionType' => 'registered',
'selectionMatch' => ''
],
$include
)
]) ])
] ]
] ]
); );
if(count($response['thermostatList']) === 0) {
throw new cora\exception('No thermostats found.', 10511, false, null, false);
}
} catch(cora\exception $e) {
// If no thermostats found (ie. not the owner of any homes that contain a thermostat)
if($e->getCode() === 10511) {
$homes = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'https://home.hm-prod.ecobee.com/homes',
'arguments' => [
]
]
);
$home_ids = array_column($homes['homes'], 'homeID');
$serial_numbers = [];
foreach($home_ids as $home_id) {
$devices = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'https://home.hm-prod.ecobee.com/home/' . $home_id . '/devices',
'arguments' => [
]
]
);
/**
* This is a select distinct from ecobee_thermostat. Ideally it
* would be possible to send *all* serial numbers from the devices
* call to the GET->thermostat API call, but that throws an error if
* you include a serial number for something that's not a
* thermostat. So I have to keep this array to identify valid serial
* numbers.
*/
$model_numbers = [
'athenaSmart',
'apolloSmart',
'idtSmart',
'nikeSmart',
'siSmart',
'corSmart',
'vulcanSmart',
'aresSmart',
'artemisSmart'
];
foreach($devices['devices'] as $device) {
if(in_array($device['modelNumber'], $model_numbers) === true) {
$serial_numbers[] = $device['serialNumber'];
}
}
}
$response = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'thermostat',
'arguments' => [
'body' => json_encode([
'selection' => array_merge(
[
'selectionType' => 'thermostats',
'selectionMatch' => implode(',', $serial_numbers),
],
$include
)
])
]
]
);
} else {
throw $e;
}
}
// Loop over the returned thermostats and create/update them as necessary. // Loop over the returned thermostats and create/update them as necessary.
$thermostat_ids_to_keep = []; $thermostat_ids_to_keep = [];