1
0
mirror of https://github.com/beestat/app.git synced 2025-05-24 02:14:03 -04:00
beestat/api/ecobee_sensor.php
2025-01-31 21:57:33 -05:00

331 lines
10 KiB
PHP

<?php
/**
* An ecobee sensor. This just has a few simple properties like name,
* temperature, humidity, etc.
*
* @author Jon Ziebell
*/
class ecobee_sensor extends cora\crud {
public static $exposed = [
'private' => [
'read_id'
],
'public' => []
];
/**
* Normal read_id, but filter out unsupported sensor types.
*
* @param array $attributes
* @param array $columns
*
* @return array
*/
public function read_id($attributes = [], $columns = []) {
$ecobee_sensors = parent::read_id($attributes, $columns);
$return = [];
foreach($ecobee_sensors as $ecobee_sensor) {
if (
in_array(
$ecobee_sensor['type'],
['ecobee3_remote_sensor', 'thermostat']
) === true
) {
$return[$ecobee_sensor['ecobee_sensor_id']] = $ecobee_sensor;
} else if (
in_array(
$ecobee_sensor['type'],
['monitor_sensor', 'control_sensor']
) === true
) {
foreach($ecobee_sensor['capability'] as $capability) {
if($capability['type'] === 'temperature') {
$return[$ecobee_sensor['ecobee_sensor_id']] = $ecobee_sensor;
}
}
}
}
return $return;
}
/**
* Sync sensors.
*/
public function sync() {
// Get the thermostat list from ecobee with sensors. Keep this identical to
// ecobee_thermostat->sync() to leverage caching.
$include = [
'includeRuntime' => true,
'includeExtendedRuntime' => true,
'includeElectricity' => true,
'includeSettings' => true,
'includeLocation' => true,
'includeProgram' => true,
'includeEvents' => true,
'includeDevice' => true,
'includeTechnician' => true,
'includeUtility' => true,
'includeManagement' => true,
'includeAlerts' => true,
'includeWeather' => true,
'includeHouseDetails' => true,
'includeOemCfg' => true,
'includeEquipmentStatus' => true,
'includeNotificationSettings' => true,
'includeVersion' => true,
'includePrivacy' => true,
'includeAudio' => true,
'includeSensors' => true
/**
* 'includeReminders' => true
*
* While documented, this is not available for general API use unless
* you are a technician user.
*
* The reminders and the includeReminders flag are something extra for
* ecobee Technicians. It allows them to set and receive reminders with
* more detail than the usual alert reminder type. These reminders are
* only available to Technician users, which is why you aren't seeing
* any new information when you set that flag to true. Thanks for
* pointing out the lack of documentation regarding this. We'll get this
* updated as soon as possible.
*
*
* https://getsatisfaction.com/api/topics/what-does-includereminders-do-when-calling-get-thermostat?rfm=1
*/
/**
* 'includeSecuritySettings' => true
*
* While documented, this is not made available for general API use
* unless you are a utility. If you try to include this an
* "Authentication failed" error will be returned.
*
* Special accounts such as Utilities are permitted an alternate method
* of authorization using implicit authorization. This method permits
* the Utility application to authorize against their own specific
* account without the requirement of a PIN. This method is limited to
* special contractual obligations and is not available for 3rd party
* applications who are not Utilities.
*
*
* 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
*/
];
// Get all active thermostats from the database.
$ecobee_thermostats = $this->api(
'ecobee_thermostat',
'read',
[
'attributes' => [
'inactive' => 0
]
]
);
if(count($ecobee_thermostats) === 0) {
return [];
}
$manual_identifiers = [];
foreach($ecobee_thermostats as $ecobee_thermostat) {
$manual_identifiers[] = $ecobee_thermostat['identifier'];
}
// Get a unique list of identifiers.
$identifiers = array_unique(array_merge($manual_identifiers));
// Get all of the thermostats from ecobee.
$response = $this->api(
'ecobee',
'ecobee_api',
[
'method' => 'GET',
'endpoint' => 'thermostat',
'arguments' => [
'body' => json_encode([
'selection' => array_merge(
[
'selectionType' => 'thermostats',
'selectionMatch' => implode(',', $identifiers)
],
$include
)
])
]
]
);
// Loop over the returned sensors and create/update them as necessary.
$sensor_ids_to_keep = [];
foreach($response['thermostatList'] as $api_thermostat) {
$ecobee_thermostat = $this->api(
'ecobee_thermostat',
'get',
[
'attributes' => [
'identifier' => $api_thermostat['identifier']
]
]
);
$thermostat = $this->api(
'thermostat',
'get',
[
'attributes' => [
'ecobee_thermostat_id' => $ecobee_thermostat['ecobee_thermostat_id']
]
]
);
foreach($api_thermostat['remoteSensors'] as $api_sensor) {
$ecobee_sensor = $this->get(
[
'ecobee_thermostat_id' => $ecobee_thermostat['ecobee_thermostat_id'],
'identifier' => $api_sensor['id']
]
);
if ($ecobee_sensor !== null) {
// Sensor exists.
$sensor = $this->api(
'sensor',
'get',
[
'attributes' => [
'ecobee_sensor_id' => $ecobee_sensor['ecobee_sensor_id']
]
]
);
}
else {
// Sensor does not exist.
$ecobee_sensor = $this->create([
'ecobee_thermostat_id' => $ecobee_thermostat['ecobee_thermostat_id'],
'identifier' => $api_sensor['id']
]);
$sensor = $this->api(
'sensor',
'create',
[
'attributes' => [
'ecobee_sensor_id' => $ecobee_sensor['ecobee_sensor_id'],
'thermostat_id' => $thermostat['thermostat_id']
]
]
);
}
$sensor_ids_to_keep[] = $sensor['sensor_id'];
$this->update(
[
'ecobee_sensor_id' => $ecobee_sensor['ecobee_sensor_id'],
'name' => $api_sensor['name'],
'type' => $api_sensor['type'],
'code' => (isset($api_sensor['code']) === true ? $api_sensor['code'] : null),
'in_use' => ($api_sensor['inUse'] === true ? 1 : 0),
'capability' => $api_sensor['capability'],
'inactive' => 0
]
);
$attributes = [];
$attributes['name'] = $api_sensor['name'];
$attributes['type'] = $api_sensor['type'];
$attributes['in_use'] = $api_sensor['inUse'];
$attributes['identifier'] = $api_sensor['id'];
$attributes['capability'] = $api_sensor['capability'];
$attributes['inactive'] = 0;
$attributes['temperature'] = null;
$attributes['humidity'] = null;
$attributes['occupancy'] = null;
foreach($api_sensor['capability'] as $capability) {
switch($capability['type']) {
case 'temperature':
if(
is_numeric($capability['value']) === true &&
($capability['value'] / 10) <= 200 &&
($capability['value'] / 10) >= -200
) {
$attributes['temperature'] = $capability['value'] / 10;
} else {
$attributes['temperature'] = null;
}
break;
case 'humidity':
if(
is_numeric($capability['value']) === true &&
$capability['value'] <= 100 &&
$capability['value'] >= 0
) {
$attributes['humidity'] = $capability['value'] / 10;
} else {
$attributes['humidity'] = null;
}
break;
case 'occupancy':
$attributes['occupancy'] = $capability['value'] === "true";
break;
}
// Update the sensor.
$this->api(
'sensor',
'update',
[
'attributes' => array_merge(
['sensor_id' => $sensor['sensor_id']],
$attributes
)
]
);
}
}
}
// Inactivate any sensors that were no longer returned.
$sensors = $this->api('sensor', 'read', ['attributes' => ['inactive' => false]]);
$ecobee_sensor_ids_to_return = [];
foreach($sensors as $sensor) {
if(in_array($sensor['sensor_id'], $sensor_ids_to_keep) === false) {
$this->update(
[
'ecobee_sensor_id' => $sensor['ecobee_sensor_id'],
'inactive' => true
]
);
$this->api(
'sensor',
'update',
[
'attributes' => [
'sensor_id' => $sensor['sensor_id'],
'inactive' => true
]
]
);
} else {
$ecobee_sensor_ids_to_return[] = $sensor['ecobee_sensor_id'];
}
}
if (count($ecobee_sensor_ids_to_return) === 0) {
return [];
} else {
return $this->read_id(['ecobee_sensor_id' => $ecobee_sensor_ids_to_return]);
}
}
}