]> _ Git - tortuga-home.git/commitdiff
.
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Tue, 4 Jul 2023 09:25:45 +0000 (11:25 +0200)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Tue, 4 Jul 2023 09:25:45 +0000 (11:25 +0200)
13 files changed:
.docker/config/httpd/httpd.conf
.idea/dataSources.local.xml
.idea/workspace.xml
config/dnsmasq.conf
scripts/cron/cron.php
scripts/domoticz_device_event.php
scripts/homeassistant.php [new file with mode: 0644]
scripts/homeassistant_device_event.php [new file with mode: 0644]
scripts/lib/harmony.php
scripts/lib/homeassistant.php [new file with mode: 0644]
scripts/lib/lib.php
scripts/lib/scenes.php
scripts/lib/weatherstation.php

index 36ef7e9ab3294e27a5464a9dfc588414cf782c63..9956ab241e95e89d2b5fbb7dff06941de8b652ca 100644 (file)
@@ -297,7 +297,7 @@ RemoteIPInternalProxy nginx-proxy
 
 <Location />
    <RequireAny>
-        Require ip 127.0.0.0/8 192.168.13.0/24 172.0.0.0/8
+        Require ip 127.0.0.0/8 192.168.0.0/16 172.0.0.0/8
    </RequireAny>
 </Location>
 
index 2427b23630319b1d629b907e4e03535b651bd26c..8edb0f691406f5be2aa1160f8a04015dff3ff6f0 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="dataSourceStorageLocal" created-in="IU-231.9011.34">
+  <component name="dataSourceStorageLocal" created-in="IU-231.9161.38">
     <data-source name="LFY(3).db" uuid="e5a3291d-855f-44b2-be41-76fe6b0c2136">
       <database-info product="SQLite" version="3.25.1" jdbc-version="2.1" driver-name="SQLite JDBC" driver-version="3.25.1" dbms="SQLITE" exact-version="3.25.1" exact-driver-version="3.25">
         <identifier-quote-string>&quot;</identifier-quote-string>
index 3f18f3d3e475e0e8f39d35798f7dfdd4a1806428..7cce9f21da1755be09646335cb19e08f5a4164d3 100644 (file)
@@ -5,12 +5,19 @@
   </component>
   <component name="ChangeListManager">
     <list default="true" id="352ce63a-b52a-41a2-979b-becda7920939" name="Default" comment=".">
+      <change afterPath="$PROJECT_DIR$/scripts/homeassistant.php" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/scripts/homeassistant_device_event.php" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/scripts/lib/homeassistant.php" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.docker/config/httpd/httpd.conf" beforeDir="false" afterPath="$PROJECT_DIR$/.docker/config/httpd/httpd.conf" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/.idea/dataSources.local.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources.local.xml" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/config/dnsmasq.conf" beforeDir="false" afterPath="$PROJECT_DIR$/config/dnsmasq.conf" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/config/global.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/global.php" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/config/rooms.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/rooms.php" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/scripts/cron/cron.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/cron/cron.php" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/scripts/domoticz_device_event.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/domoticz_device_event.php" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/scripts/lib/harmony.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/harmony.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/scenes.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/scenes.php" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/scripts/lib/weatherstation.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/weatherstation.php" afterDir="false" />
     </list>
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
     <option name="hideEmptyMiddlePackages" value="true" />
     <option name="showLibraryContents" value="true" />
   </component>
-  <component name="PropertiesComponent">{
-  &quot;keyToString&quot;: {
-    &quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
-    &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
-    &quot;WebServerToolWindowFactoryState&quot;: &quot;true&quot;,
-    &quot;WebServerToolWindowPanel.toolwindow.highlight.mappings&quot;: &quot;true&quot;,
-    &quot;WebServerToolWindowPanel.toolwindow.highlight.symlinks&quot;: &quot;true&quot;,
-    &quot;WebServerToolWindowPanel.toolwindow.show.date&quot;: &quot;false&quot;,
-    &quot;WebServerToolWindowPanel.toolwindow.show.permissions&quot;: &quot;false&quot;,
-    &quot;WebServerToolWindowPanel.toolwindow.show.size&quot;: &quot;false&quot;,
-    &quot;deletionFromPopupRequiresConfirmation&quot;: &quot;false&quot;,
-    &quot;git-widget-placeholder&quot;: &quot;master&quot;,
-    &quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
-    &quot;last_opened_file_path&quot;: &quot;D:/Works/tortuga-home/node_modules&quot;,
-    &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
-    &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
-    &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
-    &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
-    &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
-    &quot;project.structure.last.edited&quot;: &quot;Project&quot;,
-    &quot;project.structure.proportion&quot;: &quot;0.0&quot;,
-    &quot;project.structure.side.proportion&quot;: &quot;0.2&quot;,
-    &quot;ruby.rails.projectView.checked&quot;: &quot;true&quot;,
-    &quot;settings.editor.selected.configurable&quot;: &quot;editor.preferences.fonts.default&quot;,
-    &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
+  <component name="PropertiesComponent"><![CDATA[{
+  "keyToString": {
+    "RunOnceActivity.OpenProjectViewOnStart": "true",
+    "RunOnceActivity.ShowReadmeOnStart": "true",
+    "WebServerToolWindowFactoryState": "true",
+    "WebServerToolWindowPanel.toolwindow.highlight.mappings": "true",
+    "WebServerToolWindowPanel.toolwindow.highlight.symlinks": "true",
+    "WebServerToolWindowPanel.toolwindow.show.date": "false",
+    "WebServerToolWindowPanel.toolwindow.show.permissions": "false",
+    "WebServerToolWindowPanel.toolwindow.show.size": "false",
+    "deletionFromPopupRequiresConfirmation": "false",
+    "git-widget-placeholder": "master",
+    "ignore.virus.scanning.warn.message": "true",
+    "last_opened_file_path": "D:/Works/tortuga-home/scripts",
+    "node.js.detected.package.eslint": "true",
+    "node.js.detected.package.tslint": "true",
+    "node.js.selected.package.eslint": "(autodetect)",
+    "node.js.selected.package.tslint": "(autodetect)",
+    "nodejs_package_manager_path": "npm",
+    "project.structure.last.edited": "Project",
+    "project.structure.proportion": "0.0",
+    "project.structure.side.proportion": "0.2",
+    "ruby.rails.projectView.checked": "true",
+    "settings.editor.selected.configurable": "editor.preferences.fonts.default",
+    "vue.rearranger.settings.migration": "true"
   }
-}</component>
+}]]></component>
   <component name="RecentsManager">
     <key name="CopyFile.RECENT_KEYS">
+      <recent name="D:\Works\tortuga-home\scripts" />
       <recent name="T:\Drive\Works\home" />
       <recent name="T:\Drive\Works\home\config" />
       <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" />
     </key>
     <key name="MoveFile.RECENT_KEYS">
       <recent name="D:\Works\tortuga-home\lib" />
       <workItem from="1685817600522" duration="1168000" />
       <workItem from="1687000958068" duration="1421000" />
       <workItem from="1687160328629" duration="978000" />
-      <workItem from="1687258922316" duration="610000" />
-    </task>
-    <task id="LOCAL-00501" summary=".">
-      <created>1641578230504</created>
-      <option name="number" value="00501" />
-      <option name="presentableId" value="LOCAL-00501" />
-      <option name="project" value="LOCAL" />
-      <updated>1641578230506</updated>
+      <workItem from="1687258922316" duration="1906000" />
+      <workItem from="1687300707540" duration="20000" />
+      <workItem from="1687301078170" duration="848000" />
+      <workItem from="1687359859243" duration="1495000" />
+      <workItem from="1688295154056" duration="11039000" />
+      <workItem from="1688414368761" duration="9903000" />
     </task>
     <task id="LOCAL-00502" summary=".">
       <created>1641726946298</created>
       <option name="project" value="LOCAL" />
       <updated>1680507757929</updated>
     </task>
-    <option name="localTasksCounter" value="550" />
+    <task id="LOCAL-00550" summary=".">
+      <created>1687259667913</created>
+      <option name="number" value="00550" />
+      <option name="presentableId" value="LOCAL-00550" />
+      <option name="project" value="LOCAL" />
+      <updated>1687259667913</updated>
+    </task>
+    <option name="localTasksCounter" value="551" />
     <servers />
   </component>
   <component name="TypeScriptGeneratedFilesManager">
       <breakpoints>
         <line-breakpoint enabled="true" type="php">
           <url>file://$PROJECT_DIR$/scripts/lib/lib.php</url>
-          <line>97</line>
+          <line>98</line>
           <option name="timeStamp" value="1" />
         </line-breakpoint>
       </breakpoints>
index 68721dd2ea6d452b38cf949e6f726b0c187890ee..bc9815a7f111a53b397f5bf7480a44bb6674e195 100644 (file)
@@ -17,4 +17,6 @@ address=/potainersalon.home.tortuga.enhydra.fr/192.168.13.66
 address=/transmission.home.tortuga.enhydra.fr/192.168.13.7
 address=/paperless.home.tortuga.enhydra.fr/192.168.13.7
 address=/piwigo.home.tortuga.enhydra.fr/192.168.13.7
-address=/dockerbackup.home.tortuga.enhydra.fr/192.168.13.70
\ No newline at end of file
+address=/dockerbackup.home.tortuga.enhydra.fr/192.168.13.70
+address=/zigbee2mqtt.home.tortuga.enhydra.fr/192.168.13.70
+address=/homeassistant.home.tortuga.enhydra.fr/192.168.13.8
\ No newline at end of file
index 129243dc3c55e5d0aeb91596006d32b41a896c40..4c2b3221626c507524eff058936e034a3d70c614 100644 (file)
@@ -294,12 +294,6 @@ function cronHarmony($cronmin)
     } else if ($currentActivity == 'poweroff' || $currentActivity == 'off') {
         setPlaying('mycanal', 'bureau');
     }
-
-//    if ($currentActivity === 'poweroff' || $currentActivity === 'off' || $currentActivity === 'musique') {
-//        harmonyDeviceCommand('sony-projecteur', 'power-off');
-//    } else {
-//        harmonyDeviceCommand('sony-projecteur', 'power-on');
-//    }
 }
 
 function cronHeartbeat($cronmin, $devices = false)
index c7af3427f78075db82c7bc470a3c5c31f33dc24a..df53b154253c65e71d787539d096c3b9af9d5427 100644 (file)
 define('TIMELIMIT', 1);
 $_GET['im'] = '5';
 
-$wcswitch = 6448;
+$wcswitch = [6448, 6894, 6895];
 $cubesalon = [6844, 6846, 6848];
 $bar = 6890;
 $device = (int)$_GET['device'];
 
 if (in_array($device, $cubesalon)) {
-    $forceConfig = 'salon';
+       $forceConfig = 'salon';
 } elseif ($device == $wcswitch) {
-    $forceConfig = 'wc';
+       $forceConfig = 'wc';
 } elseif ($device == 4600) {
-    $forceConfig = 'bureau';
+       $forceConfig = 'bureau';
 } elseif ($device == 4711) {
-    $forceConfig = 'sdb';
+       $forceConfig = 'sdb';
 } else if ($device == $bar) {
-    $forceConfig = 'salon';
-} else if ($device == 6894) {
-    $forceConfig = 'cour';
-} else if ($device == 6895) {
-    $forceConfig = 'cour';
+       $forceConfig = 'salon';
 }
+//} else if ($device == 6894) {
+//    $forceConfig = 'cour';
+//} else if ($device == 6895) {
+//    $forceConfig = 'cour';
+//}
 
 require_once "import.php";
 
 
-if ($device === 6894) {
-    domoticzCmd(6898, 'Toggle');
-} elseif ($device == 6895) {
-    domoticzCmd(6899, 'Toggle');
-} elseif ($device == $bar) {
-    execScene('salon/bar/' . mb_strtolower($_GET['state']));
+//if ($device === 6894) {
+//     domoticzCmd(6898, 'Toggle');
+//} elseif ($device == 6895) {
+//     domoticzCmd(6899, 'Toggle');
+//} else
+       if ($device == $bar) {
+       execScene('salon/bar/' . mb_strtolower($_GET['state']));
 } elseif ($device == 480) {
-    chambreToggle(true);
+       chambreToggle(true);
 } else if (in_array($device, $cubesalon)) {
-    // Cube
-    if (gloria()) {
-        die('0');
-    }
-    switch ($_GET['state']) {
-        case 'Shake':
-            execScene('home/alert', true);
-            break;
-        case 'Flip_90':
-            execScene('salon/cinema', true);
-            break;
-        case 'Flip_180':
-            execScene('salon/auto', true);
-            break;
-        case 'Free_Fall':
-            off('salon');
-            break;
-        case 'Move':
-            _remoteCmd('pause', 'salon');
-            break;
-        case 'Clock_Wise':
-            volume(config('VOLUME_STEP'), '+');
-            break;
-        case 'Anti_Clock_Wise':
-            volume(config('VOLUME_STEP'), '-');
-            break;
-        case 'Tap':
-            squeezePlayByName('FIP', $squeezeboxPlayers['Salon']);
-            break;
-        case 'Alert':
-        default:
-            break;
-    }
+       // Cube
+       if (gloria()) {
+               die('0');
+       }
+       switch ($_GET['state']) {
+               case 'Shake':
+                       execScene('home/alert', true);
+                       break;
+               case 'Flip_90':
+                       execScene('salon/cinema', true);
+                       break;
+               case 'Flip_180':
+                       execScene('salon/auto', true);
+                       break;
+               case 'Free_Fall':
+                       off('salon');
+                       break;
+               case 'Move':
+                       _remoteCmd('pause', 'salon');
+                       break;
+               case 'Clock_Wise':
+                       volume(config('VOLUME_STEP'), '+');
+                       break;
+               case 'Anti_Clock_Wise':
+                       volume(config('VOLUME_STEP'), '-');
+                       break;
+               case 'Tap':
+                       squeezePlayByName('FIP', $squeezeboxPlayers['Salon']);
+                       break;
+               case 'Alert':
+               default:
+                       break;
+       }
 } else if ($device == 1451) {
-    domoticzSwitch(1450);
-} else if ($device == $wcswitch) {
-    $forceConfig = 'wc';
-    switch ($_GET['state']) {
-        case 'Double_Click':
-            execScene('wc/spa', true);
-            setState('wc', 1);
-            break;
-        case 'Long_Click':
-            if (isJerome(false) && isVincent()) {
-                execScene('home/alert', true);
-            } else {
-                wcToggle();
-            }
-            break;
-        case 'Click':
-        default:
-            wcToggle();
-            break;
-    }
-} else if ($device == 4600) {
-    if (gloria()) {
-        die('0');
-    }
-    // Cube bureau
-    switch ($_GET['state']) {
-        case 'Shake':
-            execScene('home/alert', true);
-            break;
-        case 'Flip_90':
-            execScene('bureau/rideaux/toggle', true);
-            break;
-        case 'Flip_180':
-            execScene('bureau/auto', true);
-            break;
-        case 'Free_Fall':
-            execScene('bureau/off', true);
-            off('bureau');
-            break;
-        case 'Move':
-            if (getCurrentHarmonyActivity() === 'tv') {
-                _remoteCmd('pause', 'bureau');
-            } else {
-                stopPlayersIn('bureau');
-                stopHarmony();
-            }
-            break;
-        case 'Clock_Wise':
-            volume(config('VOLUME_STEP'), '+',);
-            break;
-        case 'Anti_Clock_Wise':
-            volume(config('VOLUME_STEP'), '-');
-            break;
-        case 'Tap':
-            harmonyActivity('musique');
-            $lastTap = getState('bureau_squeeze_tap', 0);
-            $musics = ['FIP', 'Samba'];
-            $i = ($lastTap + 1) % count($musics);
-            setState('bureau_squeeze_tap', $i);
-            squeezePlayByName($musics[$i], 'Bureau');
-            break;
-        case 'Alert':
-        default:
-            break;
-    }
+       domoticzSwitch(1450);
+} else if (in_array($device, $wcswitch)) {
+       $forceConfig = 'wc';
+       switch ($_GET['state']) {
+               case 'Double_Click':
+                       execScene('wc/spa', true);
+                       setState('wc', 1);
+                       break;
+               case 'Long_Click':
+                       if (isJerome(false) && isVincent()) {
+                               execScene('home/alert', true);
+                       } else {
+                               wcToggle();
+                       }
+                       break;
+               case 'Click':
+               default:
+                       wcToggle();
+                       break;
+       }
 } else if ($device == 4711) {
-    if (gloria()) {
-        die('0');
-    }
-    // Cube SDB
-    switch ($_GET['state']) {
-        case 'Shake':
-            execScene('home/alert', true);
-            break;
-        case 'Flip_90':
-            execScene('sdb/off', true);
-            break;
-        case 'Flip_180':
-            execScene('sdb/on', true);
-            break;
-        case 'Free_Fall':
-            off('sdb');
-            break;
-        case 'Move':
-            //_remoteCmd('pause', 'salon');
-            break;
-        case 'Clock_Wise':
-            volume(config('VOLUME_STEP'), '+');
-            break;
-        case 'Anti_Clock_Wise':
-            volume(config('VOLUME_STEP'), '-');
-            break;
-        case 'Tap':
-            squeezePlayByName('FIP', $squeezeboxPlayers['Salle de bains']);
-            break;
-        case 'Alert':
-        default:
-            break;
-    }
+       if (gloria()) {
+               die('0');
+       }
+       // Cube SDB
+       switch ($_GET['state']) {
+               case 'Shake':
+                       execScene('home/alert', true);
+                       break;
+               case 'Flip_90':
+                       execScene('sdb/off', true);
+                       break;
+               case 'Flip_180':
+                       execScene('sdb/on', true);
+                       break;
+               case 'Free_Fall':
+                       off('sdb');
+                       break;
+               case 'Move':
+                       //_remoteCmd('pause', 'salon');
+                       break;
+               case 'Clock_Wise':
+                       volume(config('VOLUME_STEP'), '+');
+                       break;
+               case 'Anti_Clock_Wise':
+                       volume(config('VOLUME_STEP'), '-');
+                       break;
+               case 'Tap':
+                       squeezePlayByName('FIP', $squeezeboxPlayers['Salle de bains']);
+                       break;
+               case 'Alert':
+               default:
+                       break;
+       }
 }
 echo '1';
\ No newline at end of file
diff --git a/scripts/homeassistant.php b/scripts/homeassistant.php
new file mode 100644 (file)
index 0000000..1902707
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+require_once "import.php";
+if (!isset($_GET['action']) || $_GET['action'] === 'state') {
+       print_r(haGetState($_GET['id']));
+} else {
+       print_r(haAction($_GET['id'], $_GET['action']));
+}
\ No newline at end of file
diff --git a/scripts/homeassistant_device_event.php b/scripts/homeassistant_device_event.php
new file mode 100644 (file)
index 0000000..f7ab055
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+const TIMELIMIT = 1;
+$_GET['im'] = '5';
+
+if ($_GET['state'] === 'None') {
+       exit;
+}
+$wcswitch = 'sensor.0x0c4314fffe7ce957_action';
+$cubebureau = 'sensor.0x00158d00042d7082_action';
+
+if ($_GET['id'] === $wcswitch) {
+       $forceConfig = 'wc';
+} else if ($_GET['id'] == $cubebureau) {
+       $forceConfig = 'bureau';
+}
+
+require_once "import.php";
+
+print_r($_GET);
+
+if ($_GET['id'] === $wcswitch) {
+       switch ($_GET['state']) {
+               case '1_double':
+               case '2_double':
+                       execScene('wc/spa', true);
+                       setState('wc', 1);
+                       break;
+               case '1_hold':
+               case '2_hold':
+                       if (isJerome(false) && isVincent()) {
+                               execScene('home/alert', true);
+                       } else {
+                               wcToggle();
+                       }
+                       break;
+               case '1_single':
+               case '2_single':
+                       wcToggle();
+                       break;
+               default:
+                       break;
+       }
+} else if ($_GET['id'] === $cubebureau) {
+       if (gloria()) {
+               die('0');
+       }
+
+       // Cube bureau
+       switch ($_GET['state']) {
+               case 'shake':
+                       execScene('home/alert', true);
+                       break;
+               case 'flip90':
+                       execScene('bureau/rideaux/toggle', true);
+                       break;
+               case 'flip180':
+                       execScene('bureau/auto', true);
+                       break;
+               case 'fall':
+                       execScene('bureau/off', true);
+                       off('bureau');
+                       break;
+               case 'slide':
+                       if (getCurrentHarmonyActivity() === 'tv') {
+                               _remoteCmd('pause', 'bureau');
+                       } else {
+                               stopPlayersIn('bureau');
+                               stopHarmony();
+                       }
+                       break;
+               case 'rotate_right':
+                       volume(config('VOLUME_STEP'), '+');
+                       break;
+               case 'rotate_left':
+                       volume(config('VOLUME_STEP'), '-');
+                       break;
+               case 'tap':
+                       harmonyActivity('musique');
+                       $lastTap = getState('bureau_squeeze_tap', 0);
+                       $musics = ['FIP', 'Samba'];
+                       $i = ($lastTap + 1) % count($musics);
+                       setState('bureau_squeeze_tap', $i);
+                       squeezePlayByName($musics[$i], 'Bureau');
+                       break;
+               case 'Alert':
+               default:
+                       break;
+       }
+}
\ No newline at end of file
index 66926c2e6eeba98e50fb21af57c701cd75b720b7..84138813857b5c42422462ff559eed82fd0c0cfc 100644 (file)
@@ -1,80 +1,53 @@
 <?php
 
-
-function harmonyRequest($uri, $method = 'GET', $hub = 'bureau')
-{
-    global $harmonyClient;
-
-    $ip = 'harmonyapi.home.tortuga.enhydra.fr';
-    $uri = 'http://' . $ip . ':8282/hubs/' . $hub . '/' . ltrim($uri, '/');
-
-    if (null == $harmonyClient) {
-        $harmonyClient = new Zend\Http\Client();
-    }
-
-    $harmonyClient->setMethod($method);
-    $harmonyClient->setUri($uri);
-    $harmonyClient->setOptions(['timeout' => 60]);
-    try {
-        $response = $harmonyClient->send();
-        $res = json_decode($response->getBody(), true);
-        if (!$res) {
-            return $response->getBody();
-        }
-        return $res;
-    } catch (Exception $e) {
-        return $e->getMessage();
-    }
-}
-
-function harmonyActivity($activity)
-{
-    if ($activity == 'poweroff' || $activity == 'off') {
-        setPlaying('mycanal', 'bureau');
-    }
-    $wait = 0;
-    $current = getCurrentHarmonyActivity();
-    if ($current == 'off' || $current == 'poweroff' || !$current) {
-        if ($activity == 'tv') {
-            $wait = 10;
-        }
-    }
-    if ($activity !== 'off' && $activity !== 'poweroff') {
-        ecoMode('0');
-    }
-    if ($activity === 'tv') {
-        shieldWakeup('bureau');
-    }
-    $res = harmonyRequest('activities/' . $activity, 'POST');
-    $map = ['musique' => 2200, 'tv' => 2199, 'off' => 2198];
-    domoticzSwitch($map[$activity], true, 'light', false);
-    if ($wait > 0) {
-        sleep($wait);
-    }
-    if ($activity == 'tv') {
-        runAtEnd('sleep(15);harmonyDeviceCommand(\'sony-projecteur\', \'power-on\');');
-    }
-    return $res;
+$harmonymap = ['musique' => 'Musique', 'tv' => 'TV', 'switch' => 'Switch', 'poweroff' => 'Power Off'];
+function harmonyActivity($activity) {
+       global $harmonymap;
+       if($activity=='off'){
+               $activity='poweroff';
+       }
+       if ($activity == 'poweroff' ) {
+               setPlaying('mycanal', 'bureau');
+       }
+       $wait = 0;
+       $current = getCurrentHarmonyActivity();
+       if ($current == 'poweroff' || !$current) {
+               if ($activity == 'tv') {
+                       $wait = 10;
+               }
+       }
+       if ($activity !== 'poweroff') {
+               ecoMode('0');
+       }
+       if ($activity === 'tv') {
+               shieldWakeup('bureau');
+       }
+
+
+       haAction("select.bureau_activities", $harmonymap[$activity]);
+       if ($wait > 0) {
+               sleep($wait);
+       }
+       if ($activity == 'tv') {
+               runAtEnd('sleep(15);harmonyDeviceCommand(\'sony-projecteur\', \'power-on\');');
+       }
 }
 
 
-function getCurrentHarmonyActivity()
-{
-    $status = harmonyRequest('status');
-    if (is_string($status)) {
-        return false;
-    }
-    return $status['current_activity']['slug'];
+function getCurrentHarmonyActivity() {
+       global $harmonymap;
+       $a = haGetState('select.bureau_activities');
+       if (in_array($a, $harmonymap)) {
+               return array_search($a, $harmonymap);
+       }
+       return false;
 }
 
-function stopHarmony()
-{
-    $res = harmonyRequest('off', 'PUT');
-    domoticzSwitch(2198, true, 'light', false);
-    return $res;
+function stopHarmony() {
+       harmonyActivity('off');
 }
 
-function harmonyDeviceCommand($device, $command)
-{
-    return harmonyRequest('devices/' . $device . '/commands/' . $command, 'POST');
+function harmonyDeviceCommand($device, $command) {
+       haEvent();
+       return harmonyRequest('devices/' . $device . '/commands/' . $command, 'POST');
 }
\ No newline at end of file
diff --git a/scripts/lib/homeassistant.php b/scripts/lib/homeassistant.php
new file mode 100644 (file)
index 0000000..0833bb4
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+const HA_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJiMjJlOWU2YzQ5ZTM0OTk5YTc3YTFjYzE3MDdiNTViNyIsImlhdCI6MTY4ODMxNTk0NywiZXhwIjoyMDAzNjc1OTQ3fQ.HS-KUXxaFE2esRydhqTfzCS7sc7eaZPVv0BE6NNGWas';
+const HA_URL = 'http://homeassistant.home.tortuga.enhydra.fr:8123/';
+
+const HA_WC_VMC = 'switch.0x847127fffe280f20';
+const HA_SDB_AMPLI = 'switch.0xa4c138168147c1b6';
+const HA_ECO_BASIC = 'switch.ecomode_basic';
+const HA_ECO_SUPER = 'switch.ecomode_super';
+const HA_HOTTE = 'switch.0xa4c138a2685057c8';
+const HA_BAR='switch.bar';
+
+function haGetState($id) { //ID to read - for example sensor.foo
+
+
+       $opts = [
+               "http" => [
+                       "method" => "GET",
+                       "header" =>
+                               "Content-Type: application/json\r\n" .
+                               "Authorization: Bearer " . HA_KEY . "\r\n"
+               ]
+       ];
+       $ctx = stream_context_create($opts);
+       $data = @file_get_contents(HA_URL . 'api/states/' . $id, false, $ctx);
+       if (!$data)
+               return false;
+       $data = json_decode($data);
+       if (!$data)
+               return false;
+       if (!isset($data->state))
+               return false;
+       return $data->state;
+}
+
+function haAction($id, $action='turn_on', $domain = null) {
+       $opts = [
+               "http" => [
+                       "method" => "POST",
+                       'content' => json_encode(['entity_id' => $id]),
+                       "header" =>
+                               "Content-Type: application/json\r\n" .
+                               "Authorization: Bearer " . HA_KEY . "\r\n"
+               ]
+       ];
+
+       if (null === $domain) {
+               $e = explode('.', $id);
+               $domain = $e[0];
+       }
+
+       $ctx = stream_context_create($opts);
+       $data = @file_get_contents(HA_URL . 'api/services/' . $domain . '/' . $action, false, $ctx);
+       if (!$data)
+               return false;
+       $data = json_decode($data);
+       if (!$data)
+               return false;
+       if (!isset($data->state))
+               return false;
+       return [$data->state, $data->last_updated];
+}
index 4089440c90ebfc546ae2dbfcd14ff0588d6f285a..df9237d63b2a3595cf3194d94982def4db5dc6f5 100644 (file)
@@ -10,6 +10,7 @@ require_once ROOT . '/vendor/autoload.php';
 require_once ROOT . '/scripts/lib/profile.php';
 require_once ROOT . "/config/global.php";
 require_once ROOT . '/config/rooms.php';
+require_once ROOT . '/scripts/lib/homeassistant.php';
 require_once ROOT . '/scripts/lib/redis.php';
 require_once ROOT . '/scripts/lib/state.php';
 require_once ROOT . '/scripts/lib/hue.php';
@@ -465,19 +466,10 @@ function volume($volume, $increase = '', $device = null) {
                case 'squeezebox':
                        return squeezeVolume($volume, $increase, config('SQUEEZEBOX_PLAYER'));
                case 'harmony':
-                       $lastHarmonyVolume = min(time(), getState('last_harmony_volume', 0));
-                       $limit = time() - 2;
-                       if ($lastHarmonyVolume > $limit) {
-                               return;
-                       }
-                       setState('last_harmony_volume', time());
-
-                       $volume = min(5, max(1, $volume));
-
                        if ($increase == '-') {
-                               return harmonyRequest('commands/volume-down?repeat=' . $volume, 'POST');
+                               return haAction('script.bureau_volume_down');
                        } else {
-                               return harmonyRequest('commands/volume-up?repeat=' . $volume, 'POST');
+                               return haAction('script.bureau_volume_up');
                        }
                case 'vlc':
                        return VLCCmd(['command' => 'volume', 'val' => $increase . '20'], $device);
index 703ca368338f3ef2d80a027d3423441cad79d6f6..7f6280a3515519977a95bfd2573daf0db8e082e8 100644 (file)
@@ -21,7 +21,6 @@ $home = 15;
 $alert = 16;
 
 $chambrefan = 6952;
-$amplisdb = 6956;
 $bar = 6985;
 
 $scenes = [
@@ -340,13 +339,13 @@ $scenes = [
                ['type' => 'function', 'function' => 'salonAuto', 'args' => [true]],
        ],
        'salon/bar/on' => [
-               ['type' => 'domoticz', 'device' => $bar, 'command' => true, 'priority' => true],
+               ['type' => 'ha', 'device' => HA_BAR, 'command' => 'turn_on', 'priority' => true],
        ],
        'salon/bar/off' => [
-               ['type' => 'domoticz', 'device' => $bar, 'command' => false, 'priority' => true],
+               ['type' => 'ha', 'device' => HA_BAR, 'command' => 'turn_off', 'priority' => true],
        ],
        'salon/bar/toggle' => [
-               ['type' => 'domoticz', 'device' => $bar, 'command' => 'Toggle', 'priority' => true],
+               ['type' => 'ha', 'device' => HA_BAR, 'command' => 'toggle', 'priority' => true],
        ],
        'salon/day' => [
                ['type' => 'domoticz', 'scene' => 45, 'command' => true, 'priority' => true],
@@ -768,13 +767,15 @@ $scenes = [
                ['type' => 'function', 'function' => 'wcVMCOn'],
        ],
        'wc/vmc/off' => [
-               ['type' => 'domoticz', 'device' => '6449', 'command' => false, 'priority' => true],
+               ['type' => 'ha', 'device' => HA_WC_VMC, 'command' => 'turn_off', 'priority' => true],
        ],
        'sdb/ampli/on' => [
-               ['type' => 'domoticz', 'device' => $amplisdb, 'command' => true, 'priority' => true],
+               ['type' => 'ha', 'device' => HA_SDB_AMPLI, 'command' => 'turn_on', 'priority' => true],
+               //['type' => 'domoticz', 'device' => $amplisdb, 'command' => true, 'priority' => true],
        ],
        'sdb/ampli/off' => [
-               ['type' => 'domoticz', 'device' => $amplisdb, 'command' => false, 'priority' => true],
+               ['type' => 'ha', 'device' => HA_SDB_AMPLI, 'command' => 'turn_off', 'priority' => true],
+               //['type' => 'domoticz', 'device' => $amplisdb, 'command' => false, 'priority' => true],
        ],
        'sdb/hotwater/auto' => [
                ['type' => 'function', 'function' => 'hotwaterAutoMode', 'args' => ['1']],
@@ -825,10 +826,10 @@ $scenes = [
                ['type' => 'domoticz', 'device' => '1439', 'command' => false],
        ],
        'cuisine/hotte/on' => [
-               ['type' => 'domoticz', 'scene' => 52, 'command' => true],
+               ['type' => 'ha', 'device' => HA_HOTTE, 'command' => 'turn_on'],
        ],
        'cuisine/hotte/off' => [
-               ['type' => 'domoticz', 'scene' => 52, 'command' => false],
+               ['type' => 'ha', 'device' => HA_HOTTE, 'command' => 'turn_off'],
        ],
        'cuisine/base/on' => [
                ['type' => 'hue', 'group' => $cuisine, 'scene' => 'UDlNCnVQjTHZJFF'],
@@ -892,14 +893,14 @@ $scenes = [
                ['type' => 'domoticz', 'device' => '6898', 'command' => false],
        ],
        'ecomode/basic' => [
-               ['type' => 'domoticz', 'device' => '1', 'switchtype' => 'scene', 'command' => false],
+               ['type' => 'ha', 'device' => HA_ECO_BASIC, 'command' => 'turn_off'],
        ],
        'ecomode/super' => [
                ['type' => 'scene', 'scene' => 'ecomode/basic'],
-               ['type' => 'domoticz', 'device' => '2', 'switchtype' => 'scene', 'command' => false],
+               ['type' => 'ha', 'device' => HA_ECO_SUPER, 'command' => 'turn_off'],
        ],
        'ecomode/notsuper' => [
-               ['type' => 'domoticz', 'device' => '2', 'switchtype' => 'scene', 'command' => true],
+               ['type' => 'ha', 'device' => HA_ECO_SUPER, 'command' => 'turn_on'],
        ],
        'ecomode/on' => [
                ['type' => 'scene', 'scene' => 'ecomode/basic'],
@@ -907,7 +908,7 @@ $scenes = [
        ],
        'ecomode/off' => [
                ['type' => 'scene', 'scene' => 'ecomode/notsuper'],
-               ['type' => 'domoticz', 'device' => '1', 'switchtype' => 'scene', 'command' => true, 'priority' => false],
+               ['type' => 'ha', 'device' => HA_ECO_BASIC, 'command' => 'turn_on'],
        ],
 ];
 
@@ -1007,6 +1008,8 @@ function execScene($name, $fromUserAction = false, $transitionTime = null) {
                                $action['switchtype'] = 'scene';
                        }
                        domoticzSwitch($action['device'], $action['command'], isset($action['switchtype']) ? $action['switchtype'] : 'light', $action['priority'] ?? false);
+               } else if ($action['type'] === 'ha') {
+                       haAction($action['device'], $action['command']);
                } else if ($action['type'] == 'ir') {
                        irsend($action['room'], $action['device'], $action['command']);
                } else if ($action['type'] == 'ifttt') {
@@ -1328,7 +1331,8 @@ function updateCourAuto() {
 function wcVMCOn() {
        setState('lastVMCOn', time());
        // Start VMC
-       domoticzSwitch(6449, true, 'light', true);
+       haAction(HA_WC_VMC, 'turn_on');
+       //domoticzSwitch(6449, true, 'light', true);
 }
 
 function wcVMCOff($timeout = 'auto') {
index 0a241b35b29ac82a4366b51d6fdc65f4d4857774..c31d09c6fef5736ea270f252ac9e212b26e35cec 100644 (file)
 <?php
 
-function getWeather()
-{
-    $place = 623;
-    $apikey = 'fM7z3yrWwnUuXuAPPYIM5EqTl2iBAGB6';
-
-    $cache = ROOT . '/cache/accuweather.json';
-    $limit = max(time() - 3600, 0);
-
-    if (!file_exists($cache) || filemtime($cache) < $limit) {
-        copy('http://dataservice.accuweather.com/currentconditions/v1/' . $place . '?apikey=' . $apikey . '&language=fr-FR&details=true', $cache);
-    }
-
-    $res = [];
-    $weather = json_decode(file_get_contents($cache), true);
-    $weather = $weather[0];
-    $res['temp'] = round(($weather['Temperature']['Metric']['Value']/* + getState('airtemperature')*/));
-    $res['outdoor_temp'] = toNumber(getDomoticzDeviceStatus(1467), 1);
-    $res['outdoor_humidity'] = toNumber($weather['RelativeHumidity'], true);
-    $res['outdoor_pressure'] = toNumber(getDomoticzDeviceStatus(6886), true);
-    $res['backyard_temp'] = toNumber(getDomoticzDeviceStatus(6884), 1);
-    $res['backyard_humidity'] = toNumber(getDomoticzDeviceStatus(6885), true);
-    $res['backyard_pressure'] = toNumber(getDomoticzDeviceStatus(6886), true);
-    $res['bathroom_temp'] = toNumber(getDomoticzDeviceStatus(1346), 1);
-    $res['bathroom_humidity'] = toNumber(getDomoticzDeviceStatus(1347), true);
-    $res['bedroom_temp'] = toNumber(getDomoticzDeviceStatus(6851), 1);
-    $res['bedroom_humidity'] = toNumber(getDomoticzDeviceStatus(6852), true);
-    $res['bedroom_airquality'] = toNumber(getDomoticzDeviceStatus(6853), true);
-    $res['livingroom_temp'] = toNumber(getDomoticzDeviceStatus(6453), 1);
-    $res['livingroom_humidity'] = toNumber(getDomoticzDeviceStatus(6454), true);
-    $res['kitchen_temp'] = toNumber(getDomoticzDeviceStatus(1506), 1);
-    $res['kitchen_humidity'] = toNumber(getDomoticzDeviceStatus(1507), true);
-    $res['wc_temp'] = toNumber(getDomoticzDeviceStatus(6868), 1);
-    $res['wc_humidity'] = toNumber(getDomoticzDeviceStatus(6869), true);
-    $res['office_temp'] = toNumber(getDomoticzDeviceStatus(6876), 1);
-    $res['office_humidity'] = toNumber(getDomoticzDeviceStatus(6877), true);
-    $res['cellar_humidity'] = toNumber(getDomoticzDeviceStatus(4818), true);
-    $res['cellar_temp'] = toNumber(getDomoticzDeviceStatus(4817), 1);
-    $res['pressure'] = round($weather['Pressure']['Metric']['Value']);
-    $res['pressureTendency'] = $weather['PressureTendency']['Code'];
-    $res['precipitations24'] = round($weather['PrecipitationSummary']['Past24Hours']['Metric']['Value']);
-    $res['cloudCover'] = $weather['CloudCover'];
-    $res['ceiling'] = $weather['Ceiling']['Imperial']['Value'];
-    $res['icon'] = $weather['WeatherIcon'];
-    if ($res['icon'] < 10) {
-        $res['icon'] = '0' . $res['icon'];
-    }
-
-    $cache = ROOT . '/cache/accuforecasts.json';
-    if (!file_exists($cache) || filemtime($cache) < $limit) {
-        copy('http://dataservice.accuweather.com/forecasts/v1/daily/5day/' . $place . '?apikey=' . $apikey . '&language=fr-FR&metric=true&details=true', $cache);
-    }
-    $forecasts = json_decode(file_get_contents($cache), true);
-    $f = $forecasts['DailyForecasts'][0];
-    $res['dayIcon'] = $f['Day']['Icon'];
-
-    if ($res['dayIcon'] < 10) {
-        $res['dayIcon'] = '0' . $res['dayIcon'];
-    }
-    $res['nightIcon'] = $f['Night']['Icon'];
-    if ($res['nightIcon'] < 10) {
-        $res['nightIcon'] = '0' . $res['nightIcon'];
-    }
-    $res['min'] = round($f['Temperature']['Minimum']['Value']);
-    $res['max'] = round($f['Temperature']['Maximum']['Value']);
-
-    $res['sunrise'] = $f['Sun']['EpochRise'];
-    $res['sunset'] = $f['Sun']['EpochSet'];
-    $res['moon'] = $f['Moon']['Phase'];
-    $res['moonage'] = $f['Moon']['Age'];
-    $res['moonrise'] = $f['Moon']['EpochRise'];
-    $res['moonset'] = $f['Moon']['EpochSet'];
-
-    $res['forecasts'] = [];
-    $days = ['D', 'L', 'M', 'M', 'J', 'V', 'S'];
-    for ($i = 1; $i <= 4; $i++) {
-        $j = $i - 1;
-        $res['forecasts'][$j] = [];
-        $f = $forecasts['DailyForecasts'][$i];
-        $res['forecasts'][$j]['dayIcon'] = $f['Day']['Icon'];
-
-        if ($res['forecasts'][$j]['dayIcon'] < 10) {
-            $res['forecasts'][$j]['dayIcon'] = '0' . $res['forecasts'][$j]['dayIcon'];
-        }
-        $res['forecasts'][$j]['nightIcon'] = $f['Night']['Icon'];
-        if ($res['forecasts'][$j]['nightIcon'] < 10) {
-            $res['forecasts'][$j]['nightIcon'] = '0' . $res['forecasts'][$j]['nightIcon'];
-        }
-        $res['forecasts'][$j]['min'] = round($f['Temperature']['Minimum']['Value']);
-        $res['forecasts'][$j]['max'] = round($f['Temperature']['Maximum']['Value']);
-        $res['forecasts'][$j]['day'] = $days[date('w', $f['EpochDate'])];
-    }
-
-    file_put_contents(ROOT . '/cache/weather.json', json_encode($res));
-    return $res;
+function getWeather() {
+       $place = 623;
+       $apikey = 'fM7z3yrWwnUuXuAPPYIM5EqTl2iBAGB6';
+
+       $cache = ROOT . '/cache/accuweather.json';
+       $limit = max(time() - 3600, 0);
+
+       if (!file_exists($cache) || filemtime($cache) < $limit) {
+               copy('http://dataservice.accuweather.com/currentconditions/v1/' . $place . '?apikey=' . $apikey . '&language=fr-FR&details=true', $cache);
+       }
+
+       $res = [];
+       $weather = json_decode(file_get_contents($cache), true);
+       $weather = $weather[0];
+       $res['temp'] = round(($weather['Temperature']['Metric']['Value']/* + getState('airtemperature')*/));
+       $res['outdoor_temp'] = toNumber(haGetState('sensor.flower_power_balcon_air_temperature'), 1);
+       $res['outdoor_humidity'] = toNumber($weather['RelativeHumidity'], true);
+       $res['outdoor_pressure'] = toNumber(haGetState('sensor.0x00158d000464c885_pressure'), true);
+       $res['backyard_temp'] = toNumber(haGetState('sensor.0x00158d000464c885_temperature'), 1);
+       $res['backyard_humidity'] = toNumber(haGetState('sensor.0x00158d000464c885_humidity'), true);
+       $res['backyard_pressure'] = toNumber(haGetState('sensor.0x00158d000464c885_pressure'), true);
+       $res['bathroom_temp'] = toNumber(haGetState('sensor.0x00158d0004658cc2_temperature'), 1);
+       $res['bathroom_humidity'] = toNumber(haGetState('sensor.0x00158d0004658cc2_humidity'), true);
+       $res['bedroom_temp'] = toNumber(haGetState('sensor.0x54ef4410003596e5_temperature'), 1);
+       $res['bedroom_humidity'] = toNumber(haGetState('sensor.0x54ef4410003596e5_humidity'), true);
+       $res['bedroom_airquality'] = toNumber(haGetState('sensor.0x54ef4410003596e5_voc'), true);
+       $res['livingroom_temp'] = toNumber(haGetState('sensor.temperature_salon_temperature'), 1);
+       $res['livingroom_humidity'] = toNumber(haGetState('sensor.temperature_salon_humidity'), true);
+       $res['kitchen_temp'] = toNumber(haGetState('sensor.0x00158d000418441f_temperature'), 1);
+       $res['kitchen_humidity'] = toNumber(haGetState('sensor.0x00158d000418441f_humidity'), true);
+       $res['wc_temp'] = toNumber(haGetState('sensor.0x00158d00046574da_temperature'), 1);
+       $res['wc_humidity'] = toNumber(haGetState('sensor.0x00158d00046574da_humidity'), true);
+       $res['office_temp'] = toNumber(haGetState('sensor.meter_c7c3_temperature'), 1);
+       $res['office_humidity'] = toNumber(haGetState('sensor.meter_c7c3_humidite'), true);
+       $res['cellar_humidity'] = toNumber(getDomoticzDeviceStatus(4818), true);
+       $res['cellar_temp'] = toNumber(getDomoticzDeviceStatus(4817), 1);
+       $res['pressure'] = round($weather['Pressure']['Metric']['Value']);
+       $res['pressureTendency'] = $weather['PressureTendency']['Code'];
+       $res['precipitations24'] = round($weather['PrecipitationSummary']['Past24Hours']['Metric']['Value']);
+       $res['cloudCover'] = $weather['CloudCover'];
+       $res['ceiling'] = $weather['Ceiling']['Imperial']['Value'];
+       $res['icon'] = $weather['WeatherIcon'];
+       if ($res['icon'] < 10) {
+               $res['icon'] = '0' . $res['icon'];
+       }
+
+       $cache = ROOT . '/cache/accuforecasts.json';
+       if (!file_exists($cache) || filemtime($cache) < $limit) {
+               copy('http://dataservice.accuweather.com/forecasts/v1/daily/5day/' . $place . '?apikey=' . $apikey . '&language=fr-FR&metric=true&details=true', $cache);
+       }
+       $forecasts = json_decode(file_get_contents($cache), true);
+       $f = $forecasts['DailyForecasts'][0];
+       $res['dayIcon'] = $f['Day']['Icon'];
+
+       if ($res['dayIcon'] < 10) {
+               $res['dayIcon'] = '0' . $res['dayIcon'];
+       }
+       $res['nightIcon'] = $f['Night']['Icon'];
+       if ($res['nightIcon'] < 10) {
+               $res['nightIcon'] = '0' . $res['nightIcon'];
+       }
+       $res['min'] = round($f['Temperature']['Minimum']['Value']);
+       $res['max'] = round($f['Temperature']['Maximum']['Value']);
+
+       $res['sunrise'] = $f['Sun']['EpochRise'];
+       $res['sunset'] = $f['Sun']['EpochSet'];
+       $res['moon'] = $f['Moon']['Phase'];
+       $res['moonage'] = $f['Moon']['Age'];
+       $res['moonrise'] = $f['Moon']['EpochRise'];
+       $res['moonset'] = $f['Moon']['EpochSet'];
+
+       $res['forecasts'] = [];
+       $days = ['D', 'L', 'M', 'M', 'J', 'V', 'S'];
+       for ($i = 1; $i <= 4; $i++) {
+               $j = $i - 1;
+               $res['forecasts'][$j] = [];
+               $f = $forecasts['DailyForecasts'][$i];
+               $res['forecasts'][$j]['dayIcon'] = $f['Day']['Icon'];
+
+               if ($res['forecasts'][$j]['dayIcon'] < 10) {
+                       $res['forecasts'][$j]['dayIcon'] = '0' . $res['forecasts'][$j]['dayIcon'];
+               }
+               $res['forecasts'][$j]['nightIcon'] = $f['Night']['Icon'];
+               if ($res['forecasts'][$j]['nightIcon'] < 10) {
+                       $res['forecasts'][$j]['nightIcon'] = '0' . $res['forecasts'][$j]['nightIcon'];
+               }
+               $res['forecasts'][$j]['min'] = round($f['Temperature']['Minimum']['Value']);
+               $res['forecasts'][$j]['max'] = round($f['Temperature']['Maximum']['Value']);
+               $res['forecasts'][$j]['day'] = $days[date('w', $f['EpochDate'])];
+       }
+
+       file_put_contents(ROOT . '/cache/weather.json', json_encode($res));
+       return $res;
 }
 
-function weatherStationScreenSaver()
-{
-    $weather = json_decode(file_get_contents(ROOT . '/cache/weather.json'), true);
-
-    $pressureTendency = $weather['pressureTendency'] == 'F' ? 'down' : 'up';
-    $pressure = $weather['outdoor_pressure'] == '--' ? $weather['backyard_pressure'] : $weather['outdoor_pressure'];
-
-    $res = '<div id="weatherstation" class="screensaver">';
-    $res .= '<div class="contents">';
-    $res .= '<div class="time"></div>';
-    $res .= '<div class="current">';
-    $res .= '<div class="icon">' . accuweatherIcon($weather['icon']) . '</div>';
-    $res .= '<div class="icons">';
-    $res .= '<div class="night">' . accuweatherIcon($weather['nightIcon']) . '</div>';
-    $res .= '<div class="day">' . accuweatherIcon($weather['dayIcon']) . '</div>';
-    $res .= '</div>';
-    $res .= '<div class="temps">';
-    $res .= '<div class="temp-min">' . $weather['min'] . '°C</div>';
-    $res .= '<div class="temp"> ' . $weather['outdoor_temp'] . '°C <span style="font-size:20%;"> ' . $weather['temp'] . '°C</span></div>';
-    $res .= '<div class="temp-max">' . $weather['max'] . '°C</div>';
-    $res .= '</div>';
-    $res .= '<div class="pp">';
-    $res .= '<i class="fas fa-cloud-rain"></i> ' . $weather['precipitations24'] . ' mm | <i class="fas fa-tachometer-alt"></i> ' . $pressure . ' hPa <i class="fa fa-arrow-circle-' . $pressureTendency . '"></i> | <i class="fa fa-tint"></i> ' . $weather['outdoor_humidity'] . '%';
-    $res .= '</div>';
-    $res .= '<table class="house">';
-    $res .= '<tr><td class="hicon backyard"><i class="fa fa-flower-tulip"></i></td><td class="backyard">' . $weather['backyard_temp'] . ' °C</td><td class="hicon hum backyard"><i class="fa fa-tint"></i></td><td class="hum backyard">' . $weather['backyard_humidity'] . '%</td>';
-    $res .= '<td class="sep"></td><td class="hicon kitchen"><i class="fa fa-knife-kitchen"></i></td><td class="kitchen">' . $weather['kitchen_temp'] . ' °C</td><td class="hicon hum kitchen"><i class="fa fa-tint"></i></td><td class="hum kitchen">' . $weather['kitchen_humidity'] . '%</td></tr>';
-    $res .= '<tr><td class="hicon livingroom"><i class="fa fa-cocktail"></i></td><td class="livingroom">' . $weather['livingroom_temp'] . ' °C</td><td class="hicon hum livingroom"><i class="fa fa-tint"></i></td><td class="hum livingroom">' . $weather['livingroom_humidity'] . '%</td>';
-    $res .= '<td class="sep"></td><td class="hicon office"><i class="fa fa-plane"></i></td><td class="office">' . $weather['office_temp'] . ' °C</td><td class="hicon hum office"><i class="fa fa-tint"></i></td><td class="hum office">' . $weather['office_humidity'] . '%</td></tr>';
-    $res .= '<tr><td class="hicon wc"><i class="fa fa-toilet"></i></td><td class="wc">' . $weather['wc_temp'] . ' °C</td><td class="hicon hum wc"><i class="fa fa-tint"></i></td><td class="hum wc">' . $weather['wc_humidity'] . '%</td>';
-    $res .= '<td class="sep"></td><td class="hicon bedroom"><i class="fa fa-bed"></i></td><td class="bedroom">' . $weather['bedroom_temp'] . ' °C</td><td class="hicon hum bedroom"><i class="fa fa-tint"></i></td><td class="hum bedroom">' . $weather['bedroom_humidity'] . '%</td>';
-    $res .= '<tr><td class="hicon bathroom"><i class="fa fa-bath"></i></td><td class="bathroom">' . $weather['bathroom_temp'] . ' °C</td><td class="hicon hum bathroom"><i class="fa fa-tint"></i></td><td class="hum bathroom">' . $weather['bathroom_humidity'] . '%</td>';
-    $res .= '<td class="sep"></td><td class="hicon cellar"><i class="fa fa-bat"></i></td><td class="cellar">' . $weather['cellar_temp'] . ' °C</td><td class="hicon hum cellar"><i class="fa fa-tint"></i></td><td class="hum cellar">' . $weather['cellar_humidity'] . '%</td></tr>';
-    $res .= '</table>';
-    $res .= '</div>';
-    $res .= '<div class="forecasts">';
-    foreach ($weather['forecasts'] as $forecast) {
-        $res .= '<div class="forecast">';
-        $res .= '<div class="weekday">' . $forecast['day'] . '</div>';
-        $res .= '<div class="night">' . accuweatherIcon($forecast['nightIcon']) . '</div>';
-        $res .= '<div class="day">' . accuweatherIcon($forecast['dayIcon']) . '</div>';
-        $res .= '<div class="temp-min">' . $forecast['min'] . '°C</div>';
-        $res .= '<div class="temp-max">' . $forecast['max'] . '°C</div>';
-        $res .= '</div>';
-    }
-    $res .= '</div>';
-
-    $res .= '<div class="curves">';
-    $res .= _curve($weather, 'sun');
-    $res .= _curve($weather, 'moon');
-    $res .= '</div>';
-    $res .= '</div>';
-
-    return $res;
+function weatherStationScreenSaver() {
+       $weather = json_decode(file_get_contents(ROOT . '/cache/weather.json'), true);
+
+       $pressureTendency = $weather['pressureTendency'] == 'F' ? 'down' : 'up';
+       $pressure = $weather['outdoor_pressure'] == '--' ? $weather['backyard_pressure'] : $weather['outdoor_pressure'];
+
+       $res = '<div id="weatherstation" class="screensaver">';
+       $res .= '<div class="contents">';
+       $res .= '<div class="time"></div>';
+       $res .= '<div class="current">';
+       $res .= '<div class="icon">' . accuweatherIcon($weather['icon']) . '</div>';
+       $res .= '<div class="icons">';
+       $res .= '<div class="night">' . accuweatherIcon($weather['nightIcon']) . '</div>';
+       $res .= '<div class="day">' . accuweatherIcon($weather['dayIcon']) . '</div>';
+       $res .= '</div>';
+       $res .= '<div class="temps">';
+       $res .= '<div class="temp-min">' . $weather['min'] . '°C</div>';
+       $res .= '<div class="temp"> ' . $weather['outdoor_temp'] . '°C <span style="font-size:20%;"> ' . $weather['temp'] . '°C</span></div>';
+       $res .= '<div class="temp-max">' . $weather['max'] . '°C</div>';
+       $res .= '</div>';
+       $res .= '<div class="pp">';
+       $res .= '<i class="fas fa-cloud-rain"></i> ' . $weather['precipitations24'] . ' mm | <i class="fas fa-tachometer-alt"></i> ' . $pressure . ' hPa <i class="fa fa-arrow-circle-' . $pressureTendency . '"></i> | <i class="fa fa-tint"></i> ' . $weather['outdoor_humidity'] . '%';
+       $res .= '</div>';
+       $res .= '<table class="house">';
+       $res .= '<tr><td class="hicon backyard"><i class="fa fa-flower-tulip"></i></td><td class="backyard">' . $weather['backyard_temp'] . ' °C</td><td class="hicon hum backyard"><i class="fa fa-tint"></i></td><td class="hum backyard">' . $weather['backyard_humidity'] . '%</td>';
+       $res .= '<td class="sep"></td><td class="hicon kitchen"><i class="fa fa-knife-kitchen"></i></td><td class="kitchen">' . $weather['kitchen_temp'] . ' °C</td><td class="hicon hum kitchen"><i class="fa fa-tint"></i></td><td class="hum kitchen">' . $weather['kitchen_humidity'] . '%</td></tr>';
+       $res .= '<tr><td class="hicon livingroom"><i class="fa fa-cocktail"></i></td><td class="livingroom">' . $weather['livingroom_temp'] . ' °C</td><td class="hicon hum livingroom"><i class="fa fa-tint"></i></td><td class="hum livingroom">' . $weather['livingroom_humidity'] . '%</td>';
+       $res .= '<td class="sep"></td><td class="hicon office"><i class="fa fa-plane"></i></td><td class="office">' . $weather['office_temp'] . ' °C</td><td class="hicon hum office"><i class="fa fa-tint"></i></td><td class="hum office">' . $weather['office_humidity'] . '%</td></tr>';
+       $res .= '<tr><td class="hicon wc"><i class="fa fa-toilet"></i></td><td class="wc">' . $weather['wc_temp'] . ' °C</td><td class="hicon hum wc"><i class="fa fa-tint"></i></td><td class="hum wc">' . $weather['wc_humidity'] . '%</td>';
+       $res .= '<td class="sep"></td><td class="hicon bedroom"><i class="fa fa-bed"></i></td><td class="bedroom">' . $weather['bedroom_temp'] . ' °C</td><td class="hicon hum bedroom"><i class="fa fa-tint"></i></td><td class="hum bedroom">' . $weather['bedroom_humidity'] . '%</td>';
+       $res .= '<tr><td class="hicon bathroom"><i class="fa fa-bath"></i></td><td class="bathroom">' . $weather['bathroom_temp'] . ' °C</td><td class="hicon hum bathroom"><i class="fa fa-tint"></i></td><td class="hum bathroom">' . $weather['bathroom_humidity'] . '%</td>';
+       $res .= '<td class="sep"></td><td class="hicon cellar"><i class="fa fa-bat"></i></td><td class="cellar">' . $weather['cellar_temp'] . ' °C</td><td class="hicon hum cellar"><i class="fa fa-tint"></i></td><td class="hum cellar">' . $weather['cellar_humidity'] . '%</td></tr>';
+       $res .= '</table>';
+       $res .= '</div>';
+       $res .= '<div class="forecasts">';
+       foreach ($weather['forecasts'] as $forecast) {
+               $res .= '<div class="forecast">';
+               $res .= '<div class="weekday">' . $forecast['day'] . '</div>';
+               $res .= '<div class="night">' . accuweatherIcon($forecast['nightIcon']) . '</div>';
+               $res .= '<div class="day">' . accuweatherIcon($forecast['dayIcon']) . '</div>';
+               $res .= '<div class="temp-min">' . $forecast['min'] . '°C</div>';
+               $res .= '<div class="temp-max">' . $forecast['max'] . '°C</div>';
+               $res .= '</div>';
+       }
+       $res .= '</div>';
+
+       $res .= '<div class="curves">';
+       $res .= _curve($weather, 'sun');
+       $res .= _curve($weather, 'moon');
+       $res .= '</div>';
+       $res .= '</div>';
+
+       return $res;
 }
 
-function _curve($weather, $curve)
-{
-    $time = time();
-
-    if ($curve == 'sun') {
-        $set = $weather['sunset'];
-        $rise = $weather['sunrise'];
-        $icon = '/images/weather/sun.svg';
-        $radius = 75;
-        $pointXOffset = 44;
-        $pointYOffset = 33;
-    } else {
-        $set = $weather['moonset'];
-        $rise = $weather['moonrise'];
-        $icon = '/images/weather/moon/' . (round(($weather['moonage'] / 28) * 12) % 12) . '.svg';
-        $radius = 50;
-        $pointXOffset = 33;
-        $pointYOffset = 21;
-    }
-
-    $diameter = $radius * 2;
-
-    $duration = 360 * (($set - $rise) / (3600 * 24));
-    $riseAngle = (180 - $duration) / 2;
-    $setAngle = $riseAngle + $duration;
-
-    //die('d '.$sunduration.';r '.$sunriseAngle.';s '.$sunsetAngle);
-
-    $sunrisePos = getPosOnCircle($riseAngle, $radius, $pointXOffset, $pointYOffset);
-    $sunsetPos = getPosOnCircle($setAngle, $radius, $pointXOffset, $pointYOffset);
-    $sunangle = $riseAngle + (($time - $rise) / (3600 * 24)) * 360;
-
-    $res = '<div class="curve curve-' . $curve . '">';
-    $res .= '<div class="astre" style="transform: rotate(' . $sunangle . 'deg)"><img src="' . $icon . '" width="20" height="20" style="transform: rotate(' . (-$sunangle) . 'deg)" /></div>';
-    if ($curve === 'sun') {
-        $res .= '<div class="orbit earth" style="background-image:url(\'/images/earth.png?j=' . filemtime(ROOT . '/images/earth.png') . '\'"></div>';
-    } else {
-        $res .= '<div class="orbit"></div>';
-    }
-    $res .= '<div class="horizon" style="top:' . ($sunrisePos['y'] + 3) . 'px;"></div>';
-    $res .= '<div class="point rise" style="top:' . $sunrisePos['y'] . 'px;left:' . $sunrisePos['x'] . 'px;"><span>' . date('H:i', $rise) . '</span></div>';
-    $res .= '<div class="point set" style="top:' . $sunsetPos['y'] . 'px;left:' . $sunsetPos['x'] . 'px;"><span>' . date('H:i', $set) . '</span></div>';
-    $res .= '</div>';
-
-    return $res;
+function _curve($weather, $curve) {
+       $time = time();
+
+       if ($curve == 'sun') {
+               $set = $weather['sunset'];
+               $rise = $weather['sunrise'];
+               $icon = '/images/weather/sun.svg';
+               $radius = 75;
+               $pointXOffset = 44;
+               $pointYOffset = 33;
+       } else {
+               $set = $weather['moonset'];
+               $rise = $weather['moonrise'];
+               $icon = '/images/weather/moon/' . (round(($weather['moonage'] / 28) * 12) % 12) . '.svg';
+               $radius = 50;
+               $pointXOffset = 33;
+               $pointYOffset = 21;
+       }
+
+       $diameter = $radius * 2;
+
+       $duration = 360 * (($set - $rise) / (3600 * 24));
+       $riseAngle = (180 - $duration) / 2;
+       $setAngle = $riseAngle + $duration;
+
+       //die('d '.$sunduration.';r '.$sunriseAngle.';s '.$sunsetAngle);
+
+       $sunrisePos = getPosOnCircle($riseAngle, $radius, $pointXOffset, $pointYOffset);
+       $sunsetPos = getPosOnCircle($setAngle, $radius, $pointXOffset, $pointYOffset);
+       $sunangle = $riseAngle + (($time - $rise) / (3600 * 24)) * 360;
+
+       $res = '<div class="curve curve-' . $curve . '">';
+       $res .= '<div class="astre" style="transform: rotate(' . $sunangle . 'deg)"><img src="' . $icon . '" width="20" height="20" style="transform: rotate(' . (-$sunangle) . 'deg)" /></div>';
+       if ($curve === 'sun') {
+               $res .= '<div class="orbit earth" style="background-image:url(\'/images/earth.png?j=' . filemtime(ROOT . '/images/earth.png') . '\'"></div>';
+       } else {
+               $res .= '<div class="orbit"></div>';
+       }
+       $res .= '<div class="horizon" style="top:' . ($sunrisePos['y'] + 3) . 'px;"></div>';
+       $res .= '<div class="point rise" style="top:' . $sunrisePos['y'] . 'px;left:' . $sunrisePos['x'] . 'px;"><span>' . date('H:i', $rise) . '</span></div>';
+       $res .= '<div class="point set" style="top:' . $sunsetPos['y'] . 'px;left:' . $sunsetPos['x'] . 'px;"><span>' . date('H:i', $set) . '</span></div>';
+       $res .= '</div>';
+
+       return $res;
 }
 
-function getPosOnCircle($angle, $radius, $x, $y)
-{
-    $angle -= 180;
-    $cos = $radius / 2 + (cos(deg2rad($angle)) * $radius);
-    $sin = $radius / 2 + (sin(deg2rad($angle)) * $radius);
+function getPosOnCircle($angle, $radius, $x, $y) {
+       $angle -= 180;
+       $cos = $radius / 2 + (cos(deg2rad($angle)) * $radius);
+       $sin = $radius / 2 + (sin(deg2rad($angle)) * $radius);
 
-    return ['x' => $x + $cos, 'y' => $y + $sin];
+       return ['x' => $x + $cos, 'y' => $y + $sin];
 }
 
-function accuweatherIcon($icon)
-{
-    return '<img src="/images/weather/' . $icon . '.svg" />';
-    // return '<img src="https://www.accuweather.com/images/weathericons/' . $icon . '.svg" />';
+function accuweatherIcon($icon) {
+       return '<img src="/images/weather/' . $icon . '.svg" />';
+       // return '<img src="https://www.accuweather.com/images/weathericons/' . $icon . '.svg" />';
 }
 
-function isDay()
-{
-    return getPeriodOfDay()['day'];
+function isDay() {
+       return getPeriodOfDay()['day'];
 }
 
-function getPeriodOfDay()
-{
-    $time = new DateTime('now', new DateTimeZone('Europe/Paris'));
-    $timestamp = $time->getTimestamp();
-    $offset = $time->getOffset() / 3600;
+function getPeriodOfDay() {
+       $time = new DateTime('now', new DateTimeZone('Europe/Paris'));
+       $timestamp = $time->getTimestamp();
+       $offset = $time->getOffset() / 3600;
 
-    $hours = intval(date('H'));
+       $hours = intval(date('H'));
 
-    $sunrise = date_sunrise($timestamp, SUNFUNCS_RET_TIMESTAMP, LATITUDE, LONGITUDE, 90, $offset);
-    $sunset = date_sunset($timestamp, SUNFUNCS_RET_TIMESTAMP, LATITUDE, LONGITUDE, 90, $offset);
+       $sunrise = date_sunrise($timestamp, SUNFUNCS_RET_TIMESTAMP, LATITUDE, LONGITUDE, 90, $offset);
+       $sunset = date_sunset($timestamp, SUNFUNCS_RET_TIMESTAMP, LATITUDE, LONGITUDE, 90, $offset);
 
-    if ($timestamp > $sunset && $sunrise < $sunset) {
-        $sunrise += 3600 * 24;
-    }
+       if ($timestamp > $sunset && $sunrise < $sunset) {
+               $sunrise += 3600 * 24;
+       }
 
 
-    $start_twilight = $sunset - 3600;
-    $end_twilight = $sunset + 3600;
+       $start_twilight = $sunset - 3600;
+       $end_twilight = $sunset + 3600;
 
-    $start_dawn = $sunrise - 3600;
-    $end_dawn = $sunrise + 3600;
+       $start_dawn = $sunrise - 3600;
+       $end_dawn = $sunrise + 3600;
 
-    $day = !($timestamp < $sunrise || $timestamp >= $sunset);
+       $day = !($timestamp < $sunrise || $timestamp >= $sunset);
 
-    if ($timestamp >= $start_twilight && $timestamp < $end_twilight) {
-        $period = 'twilight';
-    } else if ($timestamp >= $start_dawn && $timestamp < $end_dawn) {
-        $period = 'dawn';
-    } else if ($day) {
+       if ($timestamp >= $start_twilight && $timestamp < $end_twilight) {
+               $period = 'twilight';
+       } else if ($timestamp >= $start_dawn && $timestamp < $end_dawn) {
+               $period = 'dawn';
+       } else if ($day) {
 
-    } else {
-        $period = 'night';
-    }
+       } else {
+               $period = 'night';
+       }
 
-    if ($day) {
-        $midday = ($sunset + $sunrise) / 2;
-    } else {
+       if ($day) {
+               $midday = ($sunset + $sunrise) / 2;
+       } else {
 
-    }
+       }
 
-    return ['day' => $day, 'period' => $period];
+       return ['day' => $day, 'period' => $period];
 }
\ No newline at end of file