<project version="4">
<component name="ChangeListManager">
<list default="true" id="352ce63a-b52a-41a2-979b-becda7920939" name="Default" comment=".">
+ <change afterPath="$PROJECT_DIR$/scripts/homeconnect.php" afterDir="false" />
+ <change afterPath="$PROJECT_DIR$/scripts/lib/homeconnect.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/scripts/lib/kodi.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/kodi.php" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/config/global.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/global.php" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/config/salon.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/salon.php" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/images/rooms/medium/cuisine.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/images/rooms/medium/cuisine.jpg" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/images/rooms/medium/salon.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/images/rooms/medium/salon.jpg" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/images/rooms/originaux/cuisine.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/images/rooms/originaux/cuisine.jpg" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/images/rooms/originaux/salon.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/images/rooms/originaux/salon.jpg" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/images/rooms/small/cuisine.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/images/rooms/small/cuisine.jpg" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/images/rooms/small/salon.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/images/rooms/small/salon.jpg" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/scripts/lib/http.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/http.php" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/scripts/lib/lib.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/lib.php" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/scripts/lib/redis.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/redis.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/scripts/lib/scenes.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/scenes.php" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/scripts/lib/state.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/state.php" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1553247665857" />
<property name="dumpAutoload T:/Drive/Works/home/composer.json" value="--no-interaction --ansi --verbose --optimize" />
<property name="editor.config.ad.shown" value="true" />
- <property name="last_opened_file_path" value="$PROJECT_DIR$/images" />
+ <property name="last_opened_file_path" value="$PROJECT_DIR$/images/rooms/small" />
<property name="list.type.of.created.stylesheet" value="Less" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
+ <recent name="T:\Drive\Works\home\images\rooms\small" />
+ <recent name="T:\Drive\Works\home\images\rooms\medium" />
<recent name="T:\Drive\Works\home\images" />
<recent name="T:\Drive\Works\home\style\fonts\fontawesome" />
<recent name="T:\Drive\Works\home" />
- <recent name="T:\Drive\Works\home\servers" />
- <recent name="T:\Drive\Works\home\config" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="T:\Drive\Works\home\images" />
<option name="Make" enabled="true" />
</method>
</configuration>
+ <configuration default="true" type="ArquillianJUnit" factoryName="" nameIsGenerated="true">
+ <option name="arquillianRunConfiguration">
+ <value>
+ <option name="containerStateName" value="" />
+ </value>
+ </option>
+ <option name="TEST_OBJECT" value="class" />
+ <method v="2">
+ <option name="Make" enabled="true" />
+ </method>
+ </configuration>
<configuration default="true" type="ArquillianTestNG" factoryName="">
<option name="arquillianRunConfiguration">
<value>
<workItem from="1617801536336" duration="4107000" />
<workItem from="1618050897134" duration="4462000" />
<workItem from="1618158049208" duration="20700000" />
- <workItem from="1618426400216" duration="472000" />
- </task>
- <task id="LOCAL-00419" summary=".">
- <created>1607418039594</created>
- <option name="number" value="00419" />
- <option name="presentableId" value="LOCAL-00419" />
- <option name="project" value="LOCAL" />
- <updated>1607418039594</updated>
+ <workItem from="1618426400216" duration="1138000" />
+ <workItem from="1618656192286" duration="2313000" />
+ <workItem from="1618682288258" duration="2117000" />
+ <workItem from="1618740509693" duration="11544000" />
</task>
<task id="LOCAL-00420" summary=".">
<created>1607546493721</created>
<option name="project" value="LOCAL" />
<updated>1618342660944</updated>
</task>
- <option name="localTasksCounter" value="468" />
+ <task id="LOCAL-00468" summary=".">
+ <created>1618426951296</created>
+ <option name="number" value="00468" />
+ <option name="presentableId" value="LOCAL-00468" />
+ <option name="project" value="LOCAL" />
+ <updated>1618426951296</updated>
+ </task>
+ <option name="localTasksCounter" value="469" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
define('HUE_BRIDGE', '192.168.13.85');
define('HUE_USER', 'zZigF7nPQq9nTZ3GTB1zkntn98trOJVFHWAwFiqQ');
+define('HOMECONNECT_CLIENT_ID','97C087A66769555561D14306F34336C5D05AD97B56ED813E6BD44ECCFA980CE5');
+define('HOMECONNECT_CLIENT_SECRET','540F102E39E86F7F92C3A534C31017264A47458589E9E66D27427F35DD4F7BFC');
+define('HOMECONNECT_USERNAME','vincent@enhydra.fr');
+define('HOMECONNECT_PASSWORD','YcR%vNmYnu%e$3dx2idM');
+
define('LATITUDE', 48.8758392);
define('LONGITUDE', 2.3422104);
config('VOLUME_DEVICE', 'DenonAVR');
config('VIDEOPLAYER_DEVICE', 'salon');
config('HIDEMASK_TIMEOUT', 250);
-config('THEME','#7a6854');
+config('THEME','#d0a25b');
config('SLEEPSCREEN', 15);
config('SCREENSAVER_BRIGHTNESS', 100);
config('SLEEPTYPE', 'screensaver');
--- /dev/null
+<?php
+require_once "import.php";
+echo '<pre>';
+hc_setpower_state('Machine à café',false);
\ No newline at end of file
--- /dev/null
+<?php
+function _hc_cmd($cmd, $data = [], $method = 'get', $auth = true)
+{
+ $client = getHttpClient(false);
+ $base = 'https://api.home-connect.com';
+ $uri = $base . '/' . $cmd;
+ $headers = [];
+ if ($auth) {
+ $headers['Authorization'] = 'Bearer ' . getState('hc_access_token');
+ $headers['Accept'] = 'application/vnd.bsh.sdk.v1+json';
+ }
+ $res = httpRequest($uri, $method, $data, null, 10, true, $headers);
+ $c = $res->getBody()->getContents();
+
+ if ($decoded = json_decode($c)) {
+ return $decoded;
+ } else {
+ return $c;
+ }
+}
+
+
+function hc_appliances()
+{
+ hc_connect();
+ $cacheId = 'hc_appliances';
+ $res = getStateIfMoreRecent($cacheId, time() - (86400 * 7), null);
+ if (null === $res) {
+ $res = [];
+ $appliances = _hc_cmd('api/homeappliances')->data->homeappliances;
+ foreach ($appliances as $item) {
+ $res[$item->name] = ['haid' => $item->haId, 'type' => $item->type];
+ }
+ setState($cacheId, $res);
+ }
+ return $res;
+}
+
+function hc_haid($name)
+{
+ $appliances = hc_appliances();
+ return $appliances[$name]['haid'];
+}
+
+function hc_type($name)
+{
+ $appliances = hc_appliances();
+ return $appliances[$name]['type'];
+}
+
+function hc_command($appliance, $cmd)
+{
+ $haid = hc_haid($appliance);
+}
+
+
+function hc_setpower_state($appliance, $state)
+{
+ $data = [];
+ $aptype = hc_type($appliance);
+ $stby = ['Oven', 'CoffeeMaker'];
+ if (in_array($aptype, $stby)) {
+ $states = ['On', 'Standby'];
+ } else {
+ $states = ['On', 'Off'];
+ }
+ $value = $state ? $states[0] : $states[1];
+ $data = ['key' => 'BSH.Common.Setting.PowerState',
+ 'value' => 'BSH.Common.EnumType.PowerState.' . $value,
+ 'type' => 'BSH.Common.EnumType.PowerState',
+ 'contraints' => ['allowedvalues' => ['BSH.Common.EnumType.Powerstate.' . $states[0], 'BSH.Common.EnumType.Powerstate.' . $states[1]]]];
+
+ return _hc_cmd("api/homeappliances/" . hc_haid($appliance) . "/settings/BSH.Common.Setting.PowerState", ['data'=>$data], 'put');
+}
+
+function coffee_on(){
+ hc_setpower_state('Machine à café',true);
+}
+
+function coffee_off(){
+ hc_setpower_state('Machine à café',false);
+}
+
+function hc_connect()
+{
+ $scope = 'IdentifyAppliance Monitor Settings';
+ $appName = 'Tortuga';
+ $locale = 'fr';
+
+ if (null === getStateIfMoreRecent('hc_access_token', null, time() - 86400)) {
+ // Init connection
+ $connect = _hc_cmd('security/oauth/device_authorization', [
+ 'client_id' => HOMECONNECT_CLIENT_ID,
+ 'scope' => $scope,
+ ], 'post', false);
+ print_r($connect);
+
+ // Login
+ $login = _hc_cmd('security/oauth/device_login', [
+ 'client_id' => HOMECONNECT_CLIENT_ID,
+ 'user_code' => $connect->user_code,
+ 'email' => HOMECONNECT_USERNAME,
+ 'password' => HOMECONNECT_PASSWORD,
+ ], 'post', false);
+ preg_match('/<input type="hidden" name="session_id" value="([-a-z0-9]*)"\/>/', $login, $matches);
+ $session_id = $matches[1];
+
+ // Grant
+ $grant = _hc_cmd('security/oauth/device_grant',
+ [
+ 'client_id' => HOMECONNECT_CLIENT_ID,
+ 'app_name' => $appName,
+ 'session_id' => $session_id,
+ 'user_code' => $connect->user_code,
+ 'input_aborted' => 'false',
+ 'accept_language' => $locale,
+ 'email' => HOMECONNECT_USERNAME,
+ "region" => "EU", "environment" => "PRD",
+ 'scope' => $scope
+ ], 'post', false);
+
+ // Token request
+ $token = _hc_cmd('security/oauth/token',
+ [
+ 'grant_type' => 'device_code',
+ 'device_code' => $connect->device_code,
+ 'client_id' => HOMECONNECT_CLIENT_ID,
+ ], 'post', false);
+ } else if (getState('hc_access_token_expires' < time())) {
+ $token = _hc_cmd('security/oauth/token',
+ [
+ 'grant_type' => 'refresh_token',
+ 'refresh_token' => getState('hc_refresh_token'),
+ 'client_id' => HOMECONNECT_CLIENT_ID,
+ ], 'post', false);
+ } else {
+ return;
+ }
+
+ setState('hc_access_token', $token->access_token);
+ setState('hc_refresh_token', $token->refresh_token);
+}
\ No newline at end of file
}
if ($method == 'GET') {
$options['query'] = $data;
+ }
+ if ($method === 'PUT') {
+ $options['json']=$data;
} else {
+
if (is_string($data)) {
$options['body'] = $data;
} else {
require_once ROOT . '/scripts/lib/shield.php';
require_once ROOT . '/scripts/lib/kodi.php';
require_once ROOT . '/scripts/lib/climacell.php';
+require_once ROOT . '/scripts/lib/homeconnect.php';
profile('Loaded libraries', __FILE__, __LINE__);
use Predis\Client;
+
+
class StringSetIb
extends Predis\Command\StringSet
{
['type' => 'scene', 'scene' => 'chambre/planetarium/off'],
['type' => 'function', 'function' => 'bedbrightness', 'args' => [255]],
['type' => 'phonetask', 'phone' => 'vincent', 'task' => 'Matin'],
- ['type' => 'ifttt', 'event' => 'coffee_on'],
+ ['type' => 'function', 'function' => 'coffee_on'],
['type' => 'scene', 'scene' => 'chambre/auto', 'delay' => 35],
],
'chambre/deshumidificateur/on' => [
['type' => 'scene', 'scene' => 'chambre/deshumidificateur/on'],
['type' => 'phonetask', 'phone' => 'vincent', 'task' => 'Stop All Sounds'],
['type' => 'scene', 'scene' => 'chambre/planetarium/off'],
- ['type' => 'ifttt', 'event' => 'coffee_off'],
+ ['type' => 'function', 'function' => 'coffee_off'],
['type' => 'scene', 'scene' => 'home/hueoff'],
['type' => 'scene', 'scene' => 'salon/media/off'],
['type' => 'scene', 'scene' => 'salon/off', 'delay' => 2],
- //['type' => 'ifttt', 'event' => 'oven_off'],
],
'home/welcome' => [
['type' => 'scene', 'scene' => 'cuisine/on'],
<?php
require_once __DIR__ . '/redis.php';
-function setState($key, $value)
+function setState($key, $value, $expires = false)
{
if (is_string($value)) {
$value = trim($value);
}
- connectRedis()->igbset('state_' . $key, $value);
+ if (!$expires) {
+ connectRedis()->igbset('state_' . $key, $value);
+ } else {
+ connectRedis()->igbsetex('state_' . $key, $value, $expires);
+ }
}
function getState($key, $default = null)
function getStateIfMoreRecent($key, $time, $default = null)
{
$redis = connectRedis();
- $redis->expireAt($key, $time);
+ //$redis->expireAt($key, $time);
return getState($key, $default);
}
\ No newline at end of file