[ '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]); } } }