diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml new file mode 100644 index 00000000..fe9a14ca --- /dev/null +++ b/.github/workflows/translations.yml @@ -0,0 +1,18 @@ +name: translate + +on: + workflow_dispatch: + push: + branches: + - beta + +jobs: + auto-translate: + runs-on: ubuntu-latest + steps: + - uses: jeedom/jeetranslate@main + with: + deepl_api_key: ${{ secrets.DEEPL_API_KEY }} + include_empty_translation: false + target_languages: "en_US,es_ES,de_DE,it_IT,pt_PT" + use_core_translations: true diff --git a/core/ajax/mobile.ajax.php b/core/ajax/mobile.ajax.php index 08459a87..535bbbfb 100755 --- a/core/ajax/mobile.ajax.php +++ b/core/ajax/mobile.ajax.php @@ -60,6 +60,57 @@ ajax::success($return); } + if (init('action') == 'getNotificationsV2') { + $return = ''; + $iq = init('iq'); + $mobile = eqLogic::byLogicalId($iq, 'mobile'); + if (is_object($mobile)) { + $return = mobile::getNotificationsV2($iq); + } + ajax::success($return); + } + + if (init('action') == 'removeNotificationV2') { + ajax::success(mobile::removeNotificationV2(init('iq', ''), init('id', ''))); + } + + // APP V1 + + if (init('action') == 'AppV1Savescenario') { + $id = init('id'); + $sendApp = init('valueSend'); + $scenario = scenario::byId($id); + if (!is_object($scenario)) { + throw new Exception(__('scenario non trouvé', __FILE__)); + } + $scenario->setDisplay("sendToApp", $sendApp); + $scenario->save(); + ajax::success(); + } + if (init('action') == 'AppV1RegenConfig') { + mobile::makeTemplateJson(); + ajax::success(); + } + if (init('action') == 'AppV2GetSaveFavDash') { + $iq = init('iq'); + $jsonFavDash = mobile::getSaveJson($iq, 'favdash'); + if ($jsonFavDash == "") { + $reponse = false; + } else { + $reponse = true; + } + ajax::success($reponse); + } + if (init('action') == 'AppV2GetSaveDashboard') { + $iq = init('iq'); + $jsonDashboard = mobile::getSaveJson($iq, 'dashboard'); + if ($jsonDashboard == "") { + $reponse = false; + } else { + $reponse = true; + } + ajax::success($reponse); + } throw new Exception(__('Aucune methode correspondante à : ', __FILE__) . init('action')); } catch (Exception $e) { ajax::error(displayException($e), $e->getCode()); diff --git a/core/api/mobile.api.php b/core/api/mobile.api.php index ee0736b3..a185608b 100755 --- a/core/api/mobile.api.php +++ b/core/api/mobile.api.php @@ -26,31 +26,32 @@ } $params = $jsonrpc->getParams(); -log::add('mobile', 'debug', '┌──────────▶︎ :fg-warning: Appel API Mobile :/fg: ◀︎───────────'); -log::add('mobile', 'debug', '| Method > ' . $jsonrpc->getMethod()); +log::add('mobile', 'debug', '┌──────────▶︎:fg-warning: Call API :/fg:◀︎─────────────'); +log::add('mobile', 'debug', '| Method ─▶︎ ' . $jsonrpc->getMethod()); $secureApikeyLog = $params; if (isset($secureApikeyLog['apikey'])) $secureApikeyLog['apikey'] = substr($secureApikeyLog['apikey'], 0, 10) . '...'; -log::add('mobile', 'debug', '| Paramètres passés > ' . json_encode($secureApikeyLog)); +log::add('mobile', 'debug', '| Parameters ─▶︎ ' . json_encode($secureApikeyLog)); if ($params['Iq']) { - if (mobile::whoIsIq($params['Iq']) == 'mobile non detecte') { - //createMobile($params, 3); - log::add('mobile', 'debug', '| [WARNING] mobile non detecté !'); + if (mobile::whoIsIq($params['Iq']) == 'Mobile not detected') { + log::add('mobile', 'debug', '| [WARNING] Mobile not detected !'); } else { - log::add('mobile', 'debug', '| Mobile demandeur > ' . mobile::whoIsIq($params['Iq'])); + log::add('mobile', 'debug', '| Mobile : ' . mobile::whoIsIq($params['Iq'])); } } else { - log::add('mobile', 'debug', '| [WARNING] Paramètre Iq inexistant !'); + log::add('mobile', 'debug', '| [WARNING] Parameter Iq does not exist !'); } log::add('mobile', 'debug', '└───────────────────────────────────────────'); +// APP V2 // /** * Create a new equipment * Call by api setConfigs * @param array * @return new object */ -function createMobile($params, $nbIcones = 3) +function createMobileV2($params, $nbIcones = 3) { + log::add('mobile', 'debug', '|┌──:fg-success: createMobileV2 :/fg:──'); $configs = $params['configs']; $notification = $configs['notification']; $user = user::byHash($params['apikey']); @@ -58,10 +59,9 @@ function createMobile($params, $nbIcones = 3) $mobile = new mobile(); $mobile->setEqType_name('mobile'); $mobile->setName($notification['platform'] . '-' . $params['Iq']); - log::add('mobile', 'debug', ' ---- CREATE_NEW_MOBILE WITH ' . $nbIcones . ' ICONS ----'); + log::add('mobile', 'debug', '|| [NOTICE] Create new mobile with ' . $nbIcones . ' icons ----'); $mobile->setConfiguration('menuCustomArray', mobile::getMenuDefaultV2($nbIcones)); $mobile->setConfiguration('nbIcones', intval($nbIcones)); - //$mobile->setConfiguration('defaultIdMobile', 'default'); moved to postInsert $mobile->setConfiguration('type_mobile', $notification['platform']); $mobile->setConfiguration('affect_user', $userId); $mobile->setConfiguration('validate', 'no'); @@ -69,6 +69,7 @@ function createMobile($params, $nbIcones = 3) $mobile->setLogicalId($params['Iq']); $mobile->setIsEnable(1); $mobile->save(); + log::add('mobile', 'debug', '|└───────────────────'); return $mobile; } @@ -79,7 +80,7 @@ function createMobile($params, $nbIcones = 3) */ function saveMenuFromAppV2($menu, $mobile) { - log::add('mobile', 'debug', '||┌── :fg-success:saveMenuFromAppV2:/fg: ──'); + log::add('mobile', 'debug', '||┌──:fg-success: saveMenuFromAppV2 :/fg:──'); log::add('mobile', 'debug', '||| [INFO] Menu > ' . json_encode($menu)); if (is_object($mobile)) { $menuCustomArray = []; @@ -122,60 +123,62 @@ function saveMenuFromAppV2($menu, $mobile) * @return string ok makeSuccess */ if ($jsonrpc->getMethod() == 'setConfigs') { - log::add('mobile', 'debug', '┌─────▶︎ AppV2 setConfigs ─────────────────'); + log::add('mobile', 'debug', '┌──────────▶︎ setConfigs ──────────────'); $configs = $params['configs']; $geolocs = $params['geolocs']; $menu = $configs['menu']; $notification = $configs['notification']; - log::add('mobile', 'debug', '| [INFO] Configs > ' . json_encode($configs)); - log::add('mobile', 'debug', '| [INFO] Geolocs > ' . json_encode($geolocs)); - //log::add('mobile', 'debug', '| [INFO] Menu > ' . json_encode($menu)); - log::add('mobile', 'debug', '| [INFO] Notification > ' . json_encode($notification)); + log::add('mobile', 'debug', '| [INFO] Configs ─▶︎ ' . json_encode($configs)); + log::add('mobile', 'debug', '| [INFO] Geolocs ─▶︎ ' . json_encode($geolocs)); + //log::add('mobile', 'debug', '| [INFO] Menu ─▶︎ ' . json_encode($menu)); + log::add('mobile', 'debug', '| [INFO] Notification ─▶︎ ' . json_encode($notification)); $mobile = null; if (isset($params['Iq'])) { $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); + if (!is_object($mobile)) { + $mobile = createMobileV2($params, 3); + } } - if (!is_object($mobile)) { - $mobile = createMobile($params,3); - } - $mobile->setConfiguration('type_mobile', $notification['platform']); - if (isset($notification['token'])) { - if ($notification['token'] != '') { - log::add('mobile', 'debug', '| Token à ajouter > ' . $notification['token']); - $mobile->setConfiguration('notificationRegistrationToken', $notification['token']); - if ($notification['token'] == 'notifsBGDisabled') { - message::removeAll("mobile", 'alertNotifs'); - message::add('mobile', 'Les notifications sur votre mobile : ' . $mobile->getName() . ' sont desactivées', 'notifsbg', 'alertNotifs'); + if (is_object($mobile)) { + $mobile->setConfiguration('type_mobile', $notification['platform']); + if (isset($notification['token'])) { + if ($notification['token'] != '') { + log::add('mobile', 'debug', '| Token to add ─▶︎ ' . $notification['token']); + $mobile->setConfiguration('notificationRegistrationToken', $notification['token']); + if ($notification['token'] == 'notifsBGDisabled') { + message::removeAll("mobile", 'alertNotifs'); + message::add('mobile', __('Les notifications sur votre mobile sont desactivées', __FILE__) . ' ─▶︎ ' . $mobile->getName(), 'notifsbg', 'alertNotifs'); + } + } else { + log::add('mobile', 'debug', '| [NOTICE] Empty token'); } - } else { - log::add('mobile', 'debug', '| [NOTICE] Token vide '); } - } - if (isset($notification['notifsTime'])) { - $notifsTime = intval($notification['notifsTime']); - if ($mobile->getConfiguration('notifsTime', 30) != $notifsTime) { - $mobile->setConfiguration('notifsTime', $notifsTime); - log::add('mobile', 'debug', '| [INFO] New notifsTime > ' . intval($notification['notifsTime'])); - $mobile->cleaningNotifications(); + if (isset($notification['notifsTime'])) { + $notifsTime = intval($notification['notifsTime']); + if ($mobile->getConfiguration('notifsTime', 30) != $notifsTime) { + $mobile->setConfiguration('notifsTime', $notifsTime); + log::add('mobile', 'debug', '| [INFO] New notifsTime ─▶︎ ' . intval($notification['notifsTime'])); + $mobile->cleaningNotifications(); + } } - } - if (is_object($user = user::byHash($params['apikey']))) { - log::add('mobile', 'debug', '| [INFO] affect_user > ' . $user->getLogin() . ' (' . $user->getId() . ')'); - $mobile->setConfiguration('affect_user', $user->getId()); - } - $mobile->save(); + if (is_object($user = user::byHash($params['apikey']))) { + log::add('mobile', 'debug', '| [INFO] affect_user ─▶︎ ' . $user->getLogin() . ' (' . $user->getId() . ')'); + $mobile->setConfiguration('affect_user', $user->getId()); + } + $mobile->save(); - if ($geolocs) { - if ($geolocs != [] && !(is_object($geolocs) && empty((array)$geolocs)) && !(is_string($geolocs) && $geolocs == "{}")) { - mobile::createCmdGeoLocV2($params['Iq'], $params['geolocs']); - } else { - log::add('mobile', 'debug', '| Geolocs vide, suppression des commandes précédentes'); - $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); - if (is_object($mobile)) { - $cmds = $mobile->getCmd(); - foreach ($cmds as $cmd) { - if (strpos($cmd->getLogicalId(), 'geoloc_') !== false) { - $cmd->remove(); + if ($geolocs) { + if ($geolocs != [] && !(is_object($geolocs) && empty((array)$geolocs)) && !(is_string($geolocs) && $geolocs == "{}")) { + mobile::createCmdGeoLocV2($params['Iq'], $params['geolocs']); + } else { + log::add('mobile', 'debug', '| Geolocs empty, previous commands deleted'); + $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); + if (is_object($mobile)) { + $cmds = $mobile->getCmd(); + foreach ($cmds as $cmd) { + if (strpos($cmd->getLogicalId(), 'geoloc_') !== false) { + $cmd->remove(); + } } } } @@ -191,16 +194,18 @@ function saveMenuFromAppV2($menu, $mobile) * @return string ok makeSuccess */ if ($jsonrpc->getMethod() == 'setCustomMenu') { - log::add('mobile', 'debug', '┌─────▶︎ AppV2 setCustomMenu ─────────────────'); + log::add('mobile', 'debug', '┌──────────▶︎ AppV2 setCustomMenu ───────────'); $configs = $params['configs']; $menu = $configs['menu']; - log::add('mobile', 'debug', '| [INFO] Configs > ' . json_encode($configs)); - log::add('mobile', 'debug', '| [INFO] Menu > ' . json_encode($menu)); + log::add('mobile', 'debug', '| [INFO] Configs ─▶︎ ' . json_encode($configs)); + log::add('mobile', 'debug', '| [INFO] Menu ─▶︎ ' . json_encode($menu)); $mobile = null; - if (isset($params['Iq']) && is_object($mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'))) { - saveMenuFromAppV2($menu, $mobile); - } else { - log::add('mobile', 'debug', '| [WARNING] Paramètre Iq manquant ou équipement inexistant !'); + if (isset($params['Iq'])) { + if (is_object($mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'))) { + saveMenuFromAppV2($menu, $mobile); + } else { + log::add('mobile', 'debug', '| [WARNING] A required parameter Iq does not exist !'); + } } log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess('ok'); @@ -213,7 +218,7 @@ function saveMenuFromAppV2($menu, $mobile) * @return array makeSuccess */ if ($jsonrpc->getMethod() == 'getPlugins') { - log::add('mobile', 'debug', '┌─────◀︎ AppV2 getPlugins Infos ────────────────────'); + log::add('mobile', 'debug', '┌──────────◀︎ AppV2 getPlugins ────────'); $idBox = jeedom::getHardwareKey(); $return = []; $arrayPlugins = []; @@ -254,7 +259,7 @@ function saveMenuFromAppV2($menu, $mobile) $return[$idBox]['informations']['plugins'] = $arrayPlugins; $return[$idBox]['informations']['changelog'] = $changeLogs; $return[$idBox]['informations']['infosDemon'] = $deamons_infos; - log::add('mobile', 'debug', '| [INFO] Retour vers App > ' . json_encode($return)); + log::add('mobile', 'debug', '| [INFO] Sent to app ─▶︎ ' . json_encode($return)); log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess($return); } @@ -266,7 +271,7 @@ function saveMenuFromAppV2($menu, $mobile) */ if ($jsonrpc->getMethod() == 'getJson') { - log::add('mobile', 'debug', '┌─────◀︎ AppV2 getJson ────────────────────'); + log::add('mobile', 'debug', '┌──────────◀︎ AppV2 getJson ──────────────────'); $registerDevice = $_USER_GLOBAL->getOptions('registerDevice', array()); if (!is_array($registerDevice)) { $registerDevice = array(); @@ -278,7 +283,7 @@ function saveMenuFromAppV2($menu, $mobile) $registerDevice[sha512($rdk)]['session_id'] = session_id(); $_USER_GLOBAL->setOptions('registerDevice', $registerDevice); $_USER_GLOBAL->save(); - log::add('mobile', 'debug', '| RDK :' . $rdk); + log::add('mobile', 'debug', '| RDK ─▶︎ ' . $rdk); $idBox = jeedom::getHardwareKey(); $return = array(); /* -------- MOBILE FIRST ------- */ @@ -335,25 +340,23 @@ function saveMenuFromAppV2($menu, $mobile) $return[$idBox]['jeedom_version'] = jeedom::version(); $return[$idBox]['rdk'] = $rdk; $return[$idBox]['name'] = config::byKey('name') == '' ? 'Jeedom' : config::byKey('name'); - log::add('mobile', 'debug', '| [INFO] Retour de base > ' . json_encode($return)); - log::add('mobile', 'debug', '| Recherche du mobile via sont Iq > ' . $params['Iq']); - $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); $return[$idBox]['configs'] = array(); $return[$idBox]['miscellanousParams'] = array(); - if (is_object($mobile)) { - log::add('mobile', 'debug', '| OK Mobile trouvé > ' . $mobile->getName()); + if (is_object($mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'))) { + log::add('mobile', 'debug', '| OK Mobile found ─▶︎ ' . $mobile->getName()); $return[$idBox]['configs']['menu'] = $mobile->configMenuCustom(); $return[$idBox]['miscellanousParams']['hideMenuCustom'] = intval($mobile->getConfiguration('hideMenuCustom', 0)); $return[$idBox]['miscellanousParams']['hideMenuGeoloc'] = intval($mobile->getConfiguration('hideMenuGeoloc', 0)); $return[$idBox]['miscellanousParams']['sendNFCDirectly'] = intval($mobile->getConfiguration('sendNFCDirectly', 1)); } else { + log::add('mobile', 'debug', '| [WARNING] Mobile not found.'); $return[$idBox]['configs']['menu'] = mobile::getMenuDefaultTab(); $return[$idBox]['miscellanousParams']['hideMenuCustom'] = 0; $return[$idBox]['miscellanousParams']['hideMenuGeoloc'] = 0; $return[$idBox]['miscellanousParams']['sendNFCDirectly'] = 1; } - log::add('mobile', 'debug', '| [INFO] CustomENVOICONFIGSAPI GETJSON > ' . json_encode($return[$idBox]['configs'])); - log::add('mobile', 'debug', '| [INFO] Retour vers App > ' . json_encode($return)); + log::add('mobile', 'debug', '| [INFO] Menu custom ─▶︎ ' . json_encode($return[$idBox]['configs'])); + log::add('mobile', 'debug', '| [INFO] Sent to app ─▶︎ ' . json_encode($return)); log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess($return); @@ -365,44 +368,32 @@ function saveMenuFromAppV2($menu, $mobile) * @return array makeSuccess */ if ($jsonrpc->getMethod() == 'getCustomMenu') { - log::add('mobile', 'debug', '┌─────◀︎ AppV2 getCustomMenu ────────────────────'); - log::add('mobile', 'debug', '| Recherche du mobile via sont Iq > ' . $params['Iq']); - $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); - if (is_object($mobile)) { - log::add('mobile', 'debug', '| OK Mobile trouvé > ' . $mobile->getName()); + log::add('mobile', 'debug', '┌──────────◀︎ AppV2 getCustomMenu ───────────'); + if (is_object($mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'))) { + log::add('mobile', 'debug', '| OK Mobile found ─▶︎ ' . $mobile->getName()); $menu = $mobile->configMenuCustom(); } else { + log::add('mobile', 'debug', '| [WARNING] Mobile not found.'); $menu = mobile::getMenuDefaultTab(); } - log::add('mobile', 'debug', '| [INFO] Retour vers App > ' . json_encode($menu)); + log::add('mobile', 'debug', '| [INFO] Sent to app ─▶︎ ' . json_encode($menu)); log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess($menu); } -/** - * delete message jeedom by id - * - * @return bool makeSuccess - */ -if ($jsonrpc->getMethod() == 'deleteMessage') { - $message = message::byId($params['appInfos']['idmessage']); - if (is_object($message)) { - $message->remove(); - $jsonrpc->makeSuccess("true"); - } - $jsonrpc->makeSuccess("false"); -} - /** * delete message jeedom by type * * @return bool makeSuccess */ if ($jsonrpc->getMethod() == 'deleteAllMessageByType') { + log::add('mobile', 'debug', '┌──────────▶︎ AppV2 deleteAllMessageByType ───────────'); + $return = "false"; if (isset($params['appInfos']['messageType'])) { + log::add('mobile', 'debug', '| deleting of all messages of the type "' . $params['appInfos']['messageType'] . '"'); if ($params['appInfos']['messageType'] == 'jeedom') { message::removeAll('jeedom'); - $jsonrpc->makeSuccess("true"); + $return = "true"; } elseif ($params['appInfos']['messageType'] == 'plugins') { $messages = message::all(); foreach ($messages as $message) { @@ -410,15 +401,13 @@ function saveMenuFromAppV2($menu, $mobile) if ($message->getPlugin() != 'jeedom') { $message->remove(); } - } else { - $jsonrpc->makeSuccess("false"); } } - $jsonrpc->makeSuccess("true"); + $return = "true"; } - } else { - $jsonrpc->makeSuccess("false"); - } + } else log::add('mobile', 'debug', '| A required parameter "messageType" does not exist !'); + log::add('mobile', 'debug', '└───────────────────────────────────────────'); + $jsonrpc->makeSuccess($return); } /* V1 ? @@ -449,32 +438,28 @@ function saveMenuFromAppV2($menu, $mobile) * @return makeSuccess */ if ($jsonrpc->getMethod() == 'askText') { - log::add('mobile', 'debug', '┌─────▶︎ ASK ───────────────────────────────'); - /*$configs = $params['configs']; - $menu = $configs['menu']; - $notification = $configs['notification'];*/ - $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); - if (is_object($mobile)) { + log::add('mobile', 'debug', '┌──────────▶︎ ASK ───────────────────────────'); + if (is_object($mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'))) { $askCasse = config::byKey('askCasse', 'mobile', false); $textCasse = $params['text']; if ($askCasse == false) { $textCasse = strtolower($params['text']); } - $cmd = $mobile->getCmd(null, 'notif'); - log::add('mobile', 'debug', '| Réponse : ' . $textCasse . ' - IQ > ' . $params['Iq'] . ' -- Demande cmd > ' . $cmd->getId()); - if ($cmd->askResponse($textCasse)) { - log::add('mobile', 'debug', '| ASK bien trouvé : Réponse validée'); - } else { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $cmd->generateAskResponseLink($params['text'])); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - $output = curl_exec($ch); - curl_close($ch); - if (!empty($output)) log::add('mobile', 'debug', '| ' . $output); - } - } else { - log::add('mobile', 'debug', __('| [ERROR] EqLogic inconnu : ', __FILE__) . $params['Iq']); - } + if (is_object($cmd = $mobile->getCmd(null, 'notif'))) { + log::add('mobile', 'debug', '| Response ─▶︎ ' . $textCasse); + log::add('mobile', 'debug', '| Cmd ─▶︎ ' . $cmd->getHumanName() . ' (' . $cmd->getId() . ')'); + if ($cmd->askResponse($textCasse)) { + log::add('mobile', 'debug', '| OK Response confirmed'); + } else { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $cmd->generateAskResponseLink($params['text'])); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + $output = curl_exec($ch); + curl_close($ch); + if (!empty($output)) log::add('mobile', 'debug', '| ' . $output); + } + } else log::add('mobile', 'debug', '| [ERROR] Cmd notification not found'); + } else log::add('mobile', 'debug', '| [ERROR] EqLogic unknown ─▶︎ ' . $params['Iq']); log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess(); } @@ -485,110 +470,93 @@ function saveMenuFromAppV2($menu, $mobile) * @return string ok */ if ($jsonrpc->getMethod() == 'getAskResponse') { - log::add('mobile', 'debug', '┌────▶︎ getAskResponse ────────────────────'); - $Iq = $params['Iq']; - $filePath = dirname(__FILE__) . '/../data/notifications/' . $Iq . '.json'; - $idNotif = $params['idNotif']; - $choiceAsk = $params['choiceAsk']; - log::add('mobile', 'debug', '| Réponse ASK > ' . $Iq . ' > ' . $idNotif . ' > ' . $choiceAsk); - if (file_exists($filePath)) { - $notifications = file_get_contents($filePath); - $notificationsArray = json_decode($notifications, true); - foreach ($notificationsArray as $key => $notif) { - if ($notif['data']['idNotif'] == $idNotif) { - $notificationsArray[$key]['data']['choiceAsk'] = $choiceAsk; - break; + log::add('mobile', 'debug', '┌──────────▶︎ getAskResponse ────────────────'); + if (is_object($mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'))) { + $Iq = $params['Iq']; + $filePath = dirname(__FILE__) . '/../data/notifications/' . $Iq . '.json'; + $idNotif = $params['idNotif']; + $choiceAsk = $params['choiceAsk']; + log::add('mobile', 'debug', '| Id notif ─▶︎ ' . $idNotif); + log::add('mobile', 'debug', '| Response ─▶︎ ' . $choiceAsk); + if (file_exists($filePath)) { + $notifications = file_get_contents($filePath); + $notificationsArray = json_decode($notifications, true); + foreach ($notificationsArray as $key => $notif) { + if ($notif['data']['idNotif'] == $idNotif) { + $notificationsArray[$key]['data']['choiceAsk'] = $choiceAsk; + break; + } } - } - $updatedNotifications = json_encode($notificationsArray); - file_put_contents($filePath, $updatedNotifications); - } + $updatedNotifications = json_encode($notificationsArray); + file_put_contents($filePath, $updatedNotifications); + } else log::add('mobile', 'debug', '| [ERROR] Notification file does not exist'); + } else log::add('mobile', 'debug', '| [ERROR] EqLogic unknown ─▶︎ ' . $params['Iq']); log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess('ok'); } -/** - * saveMobile - * - * @return makeSuccess - */ -if ($jsonrpc->getMethod() == 'saveMobile') { - log::add('mobile', 'debug', 'Demande de sauvegarde ' . $params['type'] . ' > ' . $params['Iq'] . ' > ' . mobile::whoIsIq($params['Iq'])); - mobile::makeSaveJson($params['Iq'], $params['Json'], $params['type']); - $jsonrpc->makeSuccess(); -} - /** * save event coming from geofencing and methodeForSpecificChannel * * @return makeSuccess */ if ($jsonrpc->getMethod() == 'mobile::geoloc') { - log::add('mobile', 'debug', '┌─────▶︎ GeoLocV2 geofencing ───────────────'); + log::add('mobile', 'debug', '┌──────────▶︎ GeoLocV2 geofencing ───────────'); $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); if (is_object($mobile)) { - if (isset($params['transmition']) && isset($params['transmition']['extras']) && isset($params['transmition']['extras']['method'])) { - if ($params['transmition']['extras']['method'] == 'getDeviceInformations') { - log::add('mobile', 'debug', '| ───:fg-success: methodeForSpecificChannel in Background :/fg: ───'); - $mobile->cmdForSpecificChannel($params, 'transmition'); - } - } else if (isset($params['transmition']) && isset($params['transmition']['event']) && $params['transmition']['event'] == 'geofence') { - log::add('mobile', 'debug', '| Event > ' . $params['transmition']['event']); - $geofence = $params['transmition']['geofence']; - log::add('mobile', 'debug', '| Event > ' . json_encode($geofence)); - log::add('mobile', 'debug', '| OK Mobile trouvé -> ' . $mobile->getName() . ' (' . $params['Iq'] . ')'); - $cmdgeoloc = cmd::byEqLogicIdAndLogicalId($mobile->getId(), 'geoloc_' . $geofence['identifier']); - if (is_object($cmdgeoloc)) { - if ($geofence['action'] == 'ENTER' || $geofence['action'] == 'EXIT') { - $eventAge = time() - intval(strtotime($geofence['timestamp'])); - if ($eventAge > 1800) { - log::add('mobile', 'debug', '| SKIP stale event (' . round($eventAge / 60) . 'min) ' . $geofence['action'] . ' geoloc_' . $geofence['identifier']); - } else { - $value = ($geofence['action'] == 'ENTER') ? 1 : 0; - log::add('mobile', 'debug', '| OK Commande "' . $cmdgeoloc->getName() . '" -> ' . $value); - $mobile->checkAndUpdateCmd('geoloc_' . $geofence['identifier'], $value); - } - } else { - log::add('mobile', 'debug', '| Event -> ' . $geofence['action']); - } - } - } else { - $transmitions = $params['transmition']; - $errorCount = 0; - foreach ($transmitions as $transmition) { - if (isset($transmition['event']) && $transmition['event'] == 'geofence') { - log::add('mobile', 'debug', '| Transmition :' . json_encode($params['transmition'])); - $geofence = $transmition['geofence']; - log::add('mobile', 'debug', '| Event > ' . json_encode($geofence)); - log::add('mobile', 'debug', '| OK Mobile trouvé -> ' . $mobile->getName() . ' (' . $params['Iq'] . ')'); - $cmdgeoloc = cmd::byEqLogicIdAndLogicalId($mobile->getId(), 'geoloc_' . $geofence['identifier']); - if (is_object($cmdgeoloc)) { - if ($geofence['action'] == 'ENTER' || $geofence['action'] == 'EXIT') { - $eventAge = time() - intval(strtotime($geofence['timestamp'])); - if ($eventAge > 1800) { - log::add('mobile', 'debug', '| SKIP stale event (' . round($eventAge / 60) . 'min) ' . $geofence['action'] . ' geoloc_' . $geofence['identifier']); - } else { - $value = ($geofence['action'] == 'ENTER') ? 1 : 0; - log::add('mobile', 'debug', '| OK Commande "' . $cmdgeoloc->getName() . '" -> ' . $value); - $mobile->checkAndUpdateCmd('geoloc_' . $geofence['identifier'], $value); - } + log::add('mobile', 'debug', '| OK Mobile found ─▶︎ ' . $mobile->getName() . ' (' . $params['Iq'] . ')'); + if (isset($params['transmition'])) { + if (isset($params['transmition']['event']) && $params['transmition']['event'] == 'geofence') { + log::add('mobile', 'debug', '| Event ─▶︎ ' . $params['transmition']['event']); + $geofence = $params['transmition']['geofence']; + log::add('mobile', 'debug', '| Geofence ─▶︎ ' . json_encode($geofence)); + $cmdgeoloc = cmd::byEqLogicIdAndLogicalId($mobile->getId(), 'geoloc_' . $geofence['identifier']); + if (is_object($cmdgeoloc)) { + if ($geofence['action'] == 'ENTER' || $geofence['action'] == 'EXIT') { + $eventAge = time() - intval(strtotime($geofence['timestamp'])); + if ($eventAge > 1800) { + log::add('mobile', 'debug', '| [WARNING] SKIP stale event (' . round($eventAge / 60) . 'min)'); } else { - log::add('mobile', 'debug', '| [INFO] Event -> ' . $geofence['action']); + $value = ($geofence['action'] == 'ENTER') ? 1 : 0; + log::add('mobile', 'debug', '| OK Command "' . $cmdgeoloc->getName() . '" ( geoloc_' . $geofence['identifier'] . ' ) ─▶︎ ' . $value . ' ( eventAge = ' . $eventAge . 'sec )'); + $mobile->checkAndUpdateCmd('geoloc_' . $geofence['identifier'], $value); } - } else { - log::add('mobile', 'debug', '| [ERROR] Commande geoloc_' . $geofence['identifier'] . ' inexistante.'); + } else log::add('mobile', 'debug', '| [WARNING] Action unknown ─▶︎ ' . $geofence['action']); + } else log::add('mobile', 'debug', '| [ERROR] geofencing command unknown ─▶︎ ' . 'geoloc_' . $geofence['identifier']); + $mobile->cmdForSpecificChannel($params, 'transmition'); + } else if (is_array($transmitions = $params['transmition'])) { + log::add('mobile', 'debug', '| [INFO] transmition is array'); + $nbTransmition = count($transmitions); + foreach ($transmitions as $key => $transmition) { + log::add('mobile', 'debug', '|┌────────── [' . $key . '] ──────────'); + if (isset($transmition['event']) && $transmition['event'] == 'geofence') { + log::add('mobile', 'debug', '|| Event ─▶︎ ' . $transmition['event']); + $geofence = $transmition['geofence']; + log::add('mobile', 'debug', '|| Geofence ─▶︎ ' . json_encode($geofence)); + $cmdgeoloc = cmd::byEqLogicIdAndLogicalId($mobile->getId(), 'geoloc_' . $geofence['identifier']); + if (is_object($cmdgeoloc)) { + if ($geofence['action'] == 'ENTER' || $geofence['action'] == 'EXIT') { + $eventAge = time() - intval(strtotime($geofence['timestamp'])); + if ($eventAge > 1800) { + log::add('mobile', 'debug', '|| [WARNING] SKIP stale event (' . round($eventAge / 60) . 'min)'); + } else { + $value = ($geofence['action'] == 'ENTER') ? 1 : 0; + log::add('mobile', 'debug', '|| OK Command "' . $cmdgeoloc->getName() . '" ( geoloc_' . $geofence['identifier'] . ' ) ─▶︎ ' . $value . ' ( eventAge = ' . $eventAge . 'sec )'); + $mobile->checkAndUpdateCmd('geoloc_' . $geofence['identifier'], $value); + } + } else log::add('mobile', 'debug', '|| [WARNING] Action unknown ─▶︎ ' . $geofence['action']); + } else log::add('mobile', 'debug', '|| [ERROR] geofencing command unknown ─▶︎ ' . 'geoloc_' . $geofence['identifier']); + } else log::add('mobile', 'debug', '|| [ERROR] No geofencing settings'); + log::add('mobile', 'debug', '|└────────────────────────'); + if ($key == $nbTransmition - 1) { + $mobile->cmdForSpecificChannel($transmitions, $key); } - } else { - $errorCount++; } } - if ($errorCount > 0) { - log::add('mobile', 'debug', __('| Pas de paramètre de geofencing', __FILE__)); - } } } else { - if (isset($params['Iq'])) log::add('mobile', 'debug', __('| [ERROR] EqLogic inconnu : ', __FILE__) . $params['Iq']); - else log::add('mobile', 'debug', __('| [ERROR] Paramètre Iq inexistant !', __FILE__)); + if (isset($params['Iq'])) log::add('mobile', 'debug', '| [ERROR] EqLogic unknown ─▶︎ ' . $params['Iq']); + else log::add('mobile', 'debug', '[WARNING] Parameter Iq does not exist !'); } log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess(); @@ -600,16 +568,16 @@ function saveMenuFromAppV2($menu, $mobile) * @return makeSuccess */ if ($jsonrpc->getMethod() == "qrcodemethod") { - log::add('mobile', 'debug', '┌─────▶︎ qrcodemethod ──────────────────────'); + log::add('mobile', 'debug', '┌──────────▶︎ qrcodemethod ──────────────────'); if ($params['appInfos']) { - log::add('mobile', 'debug', '| [INFO] Valeur du QrCode > ' . json_encode($params['appInfos']['qrCode'])); + log::add('mobile', 'debug', '| [INFO] QR Code Value > ' . json_encode($params['appInfos']['qrCode'])); if (isset($params['appInfos']['qrCode']['displayValue'])) { mobile::cmdForApi($params['Iq'], "barrecodemethod", $params['appInfos']['qrCode']['displayValue'], "CodeBarre"); } else { mobile::cmdForApi($params['Iq'], "qrcodemethod", json_encode($params['appInfos']['qrCode']), "QrCode"); } - log::add('mobile', 'debug', '└───────────────────────────────────────────'); } + log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess(); } @@ -619,21 +587,21 @@ function saveMenuFromAppV2($menu, $mobile) * @return makeSuccess || makeError */ if ($jsonrpc->getMethod() == "methodeForSpecificChannel") { - log::add('mobile', 'debug', '┌─────▶︎ methodeForSpecificChannel ──────────────────────'); - log::add('mobile', 'debug', '| [INFO] params > ' . json_encode($params)); + log::add('mobile', 'debug', '┌──────────▶︎ methodeForSpecificChannel ──────────────────────'); + log::add('mobile', 'debug', '| [INFO] params ─▶︎ ' . json_encode($params)); $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); if (is_object($mobile)) { $mobile->cmdForSpecificChannel($params, 'location'); } else { if (isset($params['Iq'])) { - log::add('mobile', 'debug', __('| [ERROR] EqLogic inconnu : ', __FILE__) . $params['Iq']); + log::add('mobile', 'debug', '| [ERROR] EqLogic unknown ─▶︎ ' . $params['Iq']); $jsonrpc->makeError('EqLogic inconnu'); } else { - log::add('mobile', 'debug', __('| [ERROR] Paramètre Iq inexistant !', __FILE__)); + log::add('mobile', 'debug', '[WARNING] Parameter Iq does not exist !'); $jsonrpc->makeError('Paramètre Iq inexistant'); } } - log::add('mobile', 'debug', '└───────────────────────────────────────────'); + log::add('mobile', 'debug', '└─────────────────────────────────────────────────────────────'); $jsonrpc->makeSuccess(); } @@ -643,13 +611,13 @@ function saveMenuFromAppV2($menu, $mobile) * @return makeSuccess */ if ($jsonrpc->getMethod() == "nfc") { - log::add('mobile', 'debug', '┌─────▶︎ nfc ───────────────────────────────'); + log::add('mobile', 'debug', '┌──────────▶︎ NFC ───────────────────────────'); $id = (isset($params['appInfos']['payload']['id'])) ? $params['appInfos']['payload']['id'] : ""; $payload = (isset($params['appInfos']['payload']['payload'])) ? $params['appInfos']['payload']['payload'] : ""; mobile::cmdForApi($params['Iq'], "nfcId", $id, "Nfc Id"); mobile::cmdForApi($params['Iq'], "nfcPayload", json_encode($payload), "Nfc Payload"); - log::add('mobile', 'debug', '| [INFO] Id > ' . $id); - log::add('mobile', 'debug', '| [INFO] Payload > ' . $payload); + log::add('mobile', 'debug', '| [INFO] Id ─▶︎ ' . $id); + log::add('mobile', 'debug', '| [INFO] Payload ─▶︎ ' . $payload); log::add('mobile', 'debug', '└───────────────────────────────────────────'); $jsonrpc->makeSuccess(); } @@ -660,8 +628,8 @@ function saveMenuFromAppV2($menu, $mobile) * @return */ if ($jsonrpc->getMethod() == "syncBella") { - log::add('mobile', 'debug', '┌─────▶︎ syncBella ─────────────────────────'); - log::add('mobile', 'debug', '| JeedomApp > syncBella'); + log::add('mobile', 'debug', '┌──────────▶︎ syncBella ─────────────────────'); + log::add('mobile', 'debug', '| JeedomApp ─▶︎ syncBella'); log::add('mobile', 'debug', '└───────────────────────────────────────────'); } @@ -671,7 +639,7 @@ function saveMenuFromAppV2($menu, $mobile) * @return array */ if ($jsonrpc->getMethod() == 'getNotificationsFromFile') { - log::add('mobile', 'debug', '┌──────────▶︎ :fg-warning: Recuperation des Notifications :/fg: ──────────'); + log::add('mobile', 'debug', '┌──────────▶︎:fg-warning: getNotificationsFromFile :/fg:──────────'); $Iq = $params['Iq']; $filePath = dirname(__FILE__) . '/../data/notifications/' . $Iq . '.json'; $notifications = 'noNotifications'; @@ -681,8 +649,8 @@ function saveMenuFromAppV2($menu, $mobile) $notifications = 'noNotifications'; } } - log::add('mobile', 'debug', '| [INFO] Notifications > ' . $notifications); - log::add('mobile', 'debug', '└───────────────────────────────────────────'); + log::add('mobile', 'debug', '| [INFO] Notifications ─▶︎ ' . $notifications); + log::add('mobile', 'debug', '└─────────────────────────────────────────────────────'); $jsonrpc->makeSuccess($notifications); } @@ -692,7 +660,7 @@ function saveMenuFromAppV2($menu, $mobile) * @return string ok */ if ($jsonrpc->getMethod() == 'deleteNotificationInJsonFile') { - log::add('mobile', 'debug', '┌────▶︎ deleteNotificationInJsonFile ──────'); + log::add('mobile', 'debug', '┌──────────▶︎ deleteNotificationInJsonFile ──────'); $Iq = $params['Iq']; $filePath = dirname(__FILE__) . '/../data/notifications/' . $Iq . '.json'; $idNotif = $params['IdNotif']; @@ -708,7 +676,7 @@ function saveMenuFromAppV2($menu, $mobile) file_put_contents($filePath, $notifications); } } - log::add('mobile', 'debug', '└───────────────────────────────────────────'); + log::add('mobile', 'debug', '└───────────────────────────────────────────────'); $jsonrpc->makeSuccess('ok'); } @@ -718,7 +686,7 @@ function saveMenuFromAppV2($menu, $mobile) * @return string ok */ if ($jsonrpc->getMethod() == 'deleteGeolocCommand') { - log::add('mobile', 'debug', '┌────▶︎ Commande suppression GeoLoc ───────'); + log::add('mobile', 'debug', '┌──────────▶︎ deleteGeolocCommand ───────'); $geolocId = $params['geoloc_id']; $eqLogic = eqLogic::byLogicalId($params['Iq'], 'mobile'); if (is_object($eqLogic)) { @@ -727,10 +695,9 @@ function saveMenuFromAppV2($menu, $mobile) log::add('mobile', 'debug', '| [WARNING] Suppression de la commande "' . $cmd->getName() . '"'); $cmd->remove(); } - } else { - log::add('mobile', 'debug', __('| [ERROR] EqLogic inconnu : ', __FILE__) . $params['Iq']); - } - log::add('mobile', 'debug', '└───────────────────────────────────────────'); + } else if (isset($params['Iq'])) log::add('mobile', 'debug', '| [ERROR] EqLogic unknown ─▶︎ ' . $params['Iq']); + else log::add('mobile', 'debug', '[WARNING] Parameter Iq does not exist !'); + log::add('mobile', 'debug', '└───────────────────────────────────────────────'); $jsonrpc->makeSuccess('ok'); } @@ -740,14 +707,14 @@ function saveMenuFromAppV2($menu, $mobile) * @return array */ if ($jsonrpc->getMethod() == 'getScenarios') { - log::add('mobile', 'debug', '┌────◀︎ Get Scénarios ─────────────────────'); + log::add('mobile', 'debug', '┌──────────◀︎ getScenarios ─────────────────'); $scenarios = array(); $hasScenario = false; $scenarioListGroup = scenario::listGroup(); $emptyListGroup = false; $emptyNoGroup = false; if (empty($scenarioListGroup)) { - log::add('mobile', 'debug', '| Scénarios > Aucun groupe de scénario'); + log::add('mobile', 'debug', '| Scenarios ─▶︎ No scenario group'); $emptyListGroup = true; } if (is_array($scenarioListGroup)) { @@ -761,15 +728,15 @@ function saveMenuFromAppV2($menu, $mobile) $scenarios['{{Aucun}}'] = $scenarioNoGroup; $hasScenario = true; } else { - log::add('mobile', 'debug', '| Scénarios > Aucun "sans groupe" de scénario'); + log::add('mobile', 'debug', '| Scenarios ─▶︎ No scenario "without a group"'); $emptyNoGroup = true; } - log::add('mobile', 'debug', '| Scénarios > ' . json_encode($scenarios)); + log::add('mobile', 'debug', '| Scenarios ─▶︎ ' . json_encode($scenarios)); $scenarioTemp = array(); foreach ($scenarios as $key => $scenario) { $scenarioTemp[$key][] = utils::o2a($scenario); } - log::add('mobile', 'debug', '| $scenarioTemp > ' . json_encode($scenarioTemp)); + log::add('mobile', 'debug', '| $scenarioTemp ─▶︎ ' . json_encode($scenarioTemp)); if ($emptyListGroup && $emptyNoGroup) { $return = 'noScenarios'; } else { @@ -779,44 +746,232 @@ function saveMenuFromAppV2($menu, $mobile) $jsonrpc->makeSuccess($return); } -// /** -// * command scenarios by id -// * -// * @return array -// */ -// if ($jsonrpc->getMethod() == 'handleScenario'){ -// log::add('mobile', 'debug', '┌────▶︎ handleScenario ────────────────────'); -// $scenarioId = $params['scenario_id']; -// $action = $params['action']; -// $result = 'ko'; -// log::add('mobile', 'debug', '| Scénario > ' . $scenarioId); -// log::add('mobile', 'debug', '| Action > ' . $action); -// if (is_object($scenario = scenario::byId($scenarioId))) { -// switch($action) { -// case 'start': -// $scenario->launch(); -// $result = 'ok'; -// break; -// case 'stop': -// $scenario->stop(); -// $result = 'ok'; -// break; -// case 'activate': -// $scenario->setIsActive(1); -// $scenario->save(); -// $result = 'ok'; -// break; -// case 'desactivate': -// $scenario->setIsActive(0); -// $scenario->save(); -// $result = 'ok'; -// break; -// } -// } else { -// log::add('mobile', 'debug', '| [ERROR] Scénario > ' . $scenarioId . ' inexistant !'); -// } -// log::add('mobile', 'debug', '└───────────────────────────────────────────'); -// $jsonrpc->makeSuccess($result); -// } +// APP V1 // + +if ($jsonrpc->getMethod() == 'sync') { + log::add('mobile', 'debug', '┌──────────▶︎ Sync App V1 ───────────────────'); + if (jeedom::version() >= '3.2.0') { + log::add('mobile', 'debug', '| Demande du RDK ....'); + $registerDevice = $_USER_GLOBAL->getOptions('registerDevice', array()); + if (!is_array($registerDevice)) { + $registerDevice = array(); + } + $rdk = (!isset($params['rdk']) || !isset($registerDevice[sha512($params['rdk'])])) ? config::genKey() : $params['rdk']; + $registerDevice[sha512($rdk)] = array(); + $registerDevice[sha512($rdk)]['datetime'] = date('Y-m-d H:i:s'); + $registerDevice[sha512($rdk)]['ip'] = getClientIp(); + $registerDevice[sha512($rdk)]['session_id'] = session_id(); + $_USER_GLOBAL->setOptions('registerDevice', $registerDevice); + $_USER_GLOBAL->save(); + log::add('mobile', 'debug', '| RDK : ' . $rdk); + } + $mobile = null; + if (isset($params['Iq'])) { + $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); + } + if (!is_object($mobile)) { + $user = user::byHash($params['apikey']); + $userId = $user->getId(); + $mobile = new mobile(); + $mobile->setEqType_name('mobile'); + $mobile->setName($params['platform'] . '-' . config::genKey(3)); + $mobile->setConfiguration('type_mobile', $params['platform']); + $mobile->setConfiguration('affect_user', $userId); + $mobile->setConfiguration('validate', 'no'); + if (isset($params['notificationProvider']) && $params['notificationProvider'] != '') { + $mobile->setConfiguration('notificationArn', substr($params['notificationProvider'], 1, -1)); + } + if (isset($params['notificationRegistrationToken']) && $params['notificationRegistrationToken'] != '') { + if ($params['notificationRegistrationToken'] != 'nok') { + $mobile->setConfiguration('notificationRegistrationToken', $params['notificationRegistrationToken']); + } + } + $mobile->setIsEnable(1); + $mobile->save(); + $params['Iq'] = $mobile->getLogicalId(); + } + + if (isset($params['notificationProvider']) && $params['notificationProvider'] != '') { + log::add('mobile', 'debug', '| notificationProvider available'); + $arn = $mobile->getConfiguration('notificationArn', ''); + $arnMobile = substr($params['notificationProvider'], 1, -1); + if ($arn != $arnMobile) { + $mobile->setConfiguration('notificationArn', $arnMobile); + $mobile->save(); + } + } + + if (isset($params['notificationRegistrationToken']) && $params['notificationRegistrationToken'] != '') { + log::add('mobile', 'debug', '| notificationRegistrationToken available'); + $token = $mobile->getConfiguration('notificationRegistrationToken', 'nok'); + $tokenMobile = $params['notificationRegistrationToken']; + if ($token == 'nok') { + log::add('mobile', 'debug', '| notificationRegistrationToken null in the configuration ─▶︎ ' . $token); + $mobile->setConfiguration('notificationRegistrationToken', $tokenMobile); + $mobile->save(); + } else { + log::add('mobile', 'debug', '| Token in the configuration ─▶︎ ' . $token); + if ($token != $tokenMobile) { + log::add('mobile', 'debug', '| Token config != Token mobile ─▶︎ ' . $token . ' != ' . $tokenMobile); + $mobile->setConfiguration('notificationRegistrationToken', $tokenMobile); + $mobile->save(); + } + } + } + + if (isset($params['gen_json']) && $params['gen_json'] == 1) { + mobile::makeTemplateJson(); + } + $return = mobile::getTemplateJson(); + $return['messages'] = mobile::discovery_message(); + $return['summaryValue'] = mobile::discovery_summaryValue($return['objects']); + $return['config']['datetime'] = getmicrotime(); + $return['config']['Iq'] = $params['Iq']; + $return['config']['NameMobile'] = $mobile->getName(); + if (isset($rdk)) { + $return['config']['rdk'] = $rdk; + } + log::add('mobile', 'debug', '| Return $discovery_summaryValue ─▶︎ ' . json_encode($return['summaryValue'])); + log::add('mobile', 'debug', '└───────────────────────────────────────────'); + $jsonrpc->makeSuccess($return); +} + +if ($jsonrpc->getMethod() == 'cmdsbyEqlogicID') { + log::add('mobile', 'debug', 'Querying the ID module ' . $params['id'] . ' for cmds'); + $PluginToSend = mobile::PluginToSend(); + $discover_eqLogic = mobile::discovery_eqLogic($PluginToSend); + $sync_new = mobile::change_cmdAndeqLogic(mobile::discovery_cmd($PluginToSend, $discover_eqLogic, true), $discover_eqLogic); + $i = 0; + $cmdAPI = array(); + foreach ($sync_new['cmds'] as $cmd) { + if (isset($cmd["eqLogic_id"])) { + if ($cmd["eqLogic_id"] != $params['id']) { + unset($commandes[$i]); + } else { + array_push($cmdAPI, $commandes[$i]); + } + } + $i++; + } + log::add('mobile', 'debug', 'Commands ─▶︎ ' . json_encode($cmdAPI)); + $jsonrpc->makeSuccess($cmdAPI); +} + +if ($jsonrpc->getMethod() == 'version') { + $mobile_update = update::byLogicalId('mobile'); + $jsonrpc->makeSuccess($mobile_update->getLocalVersion()); +} + +if ($jsonrpc->getMethod() == 'event') { + $eqLogic = eqLogic::byId($params['eqLogic_id']); + if (!is_object($eqLogic)) { + throw new Exception(__('EqLogic inconnu : ', __FILE__) . $params['eqLogic_id']); + } + $cmd = $eqLogic->getCmd(null, $params['cmd_logicalId']); + if (!is_object($cmd)) { + throw new Exception(__('Cmd inconnu : ', __FILE__) . $params['cmd_logicalId']); + } + $cmd->event($params['value']); + $jsonrpc->makeSuccess(); +} + +if ($jsonrpc->getMethod() == 'saveMobile') { + log::add('mobile', 'debug', '┌──────────▶︎:fg-warning: saveMobile V1 :/fg:──────────────'); + if (isset($params['Iq'])) { + log::add('mobile', 'debug', '| Backup request ─▶︎ ' . $params['type'] . ' ─▶︎ ' . $params['Iq'] . ' (' . mobile::whoIsIq($params['Iq']) . ')'); + log::add('mobile', 'debug', '| Data to save ─▶︎ ' . json_encode($params['Json'])); + mobile::makeSaveJson($params['Iq'], $params['Json'], $params['type']); + } + log::add('mobile', 'debug', '└───────────────────────────────────────────'); + $jsonrpc->makeSuccess(); +} + +if ($jsonrpc->getMethod() == 'getMobile') { + log::add('mobile', 'debug', '┌──────────▶︎:fg-warning: getMobile V1 :/fg:──────────────'); + log::add('mobile', 'debug', '| Recovery request ─▶︎ ' . $params['type'] . ' ─▶︎ ' . $params['Iq'] . ' (' . mobile::whoIsIq($params['Iq']) . ')'); + log::add('mobile', 'debug', '| Backup recovery ─▶︎ ' . $params['IqRestore'] . ' (' . mobile::whoIsIq($params['IqRestore']) . ')'); + $saveJson = mobile::getSaveJson($params['IqRestore'], $params['type']); + log::add('mobile', 'debug', '| Data sent to the app ─▶︎ ' . json_encode($saveJson)); + log::add('mobile', 'debug', '└───────────────────────────────────────────'); + $jsonrpc->makeSuccess($saveJson); +} + +if ($jsonrpc->getMethod() == 'geoloc') { + log::add('mobile', 'debug', '┌──────────▶︎:fg-warning: geoloc V1 :/fg:──────────────'); + if (isset($params['Iq'])) { + $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); + if (is_object($mobile)) { + if (isset($params['id']) && $params['id'] != '' && isset($params['name']) && $params['name'] != '' && isset($params['value']) && $params['value'] != '') { + log::add('mobile', 'debug', '| geoId_' . $params['id'] . ' ─▶︎ ' . $params['name'] . ' ─▶︎ ' . $params['value']); + if ($mobile->checkAndUpdateCmd('geoId_' . $params['id'], $params['value'])) { + log::add('mobile', 'debug', '| ↳ Update geofence point ─▶︎ ' . $params['value']); + } + } else log::add('mobile', 'debug', '| [WARNING] A required parameter does not exist !'); + } else log::add('mobile', 'debug', '| [ERROR] EqLogic unknown ─▶︎ ' . $params['Iq']); + } + log::add('mobile', 'debug', '└───────────────────────────────────────────'); + $jsonrpc->makeSuccess(); +} + +if ($jsonrpc->getMethod() == 'geolocSave') { + log::add('mobile', 'debug', '┌──────────▶︎:fg-warning: geolocSave V1 :/fg:──────────────'); + if (isset($params['Iq'])) { + $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); + if (is_object($mobile)) { + if (isset($params['id']) && $params['id'] != '') { + $cmdgeoloc = cmd::byEqLogicIdAndLogicalId($mobile->getId(), 'geoId_' . $params['id']); + if ($params['name'] == "") { + $name = $params['id']; + } else { + $name = $params['name']; + } + if (!is_object($cmdgeoloc)) { + $cmdgeoloc = new mobileCmd(); + $cmdgeoloc->setLogicalId('geoId_' . $params['id']); + $cmdgeoloc->setEqLogic_id($mobile->getId()); + $cmdgeoloc->setType('info'); + $cmdgeoloc->setSubType('binary'); + $cmdgeoloc->setTemplate('dashboard', 'core::presence'); + $cmdgeoloc->setTemplate('mobile', 'core::presence'); + $cmdgeoloc->setDisplay('icon', ''); + $cmdgeoloc->setDisplay('showIconAndNamedashboard', 1); + $cmdgeoloc->setIsHistorized(1); + $cmdgeoloc->setGeneric_type('PRESENCE'); + $cmdgeoloc->setIsVisible(1); + $cmdgeoloc->setName($name); + } + $cmdgeoloc->setConfiguration('latitude', $params['latitude']); + $cmdgeoloc->setConfiguration('longitude', $params['longitude']); + $cmdgeoloc->setConfiguration('subtitle', $params['subtitle']); + $cmdgeoloc->setConfiguration('radius', $params['radius']); + $cmdgeoloc->save(); + log::add('mobile', 'debug', '| geoId_' . $params['id'] . ' ─▶︎ ' . $name . ' ─▶︎ ' . $params['value']); + if ($mobile->checkAndUpdateCmd('geoId_' . $params['id'], $params['value'])) { + log::add('mobile', 'debug', '| ↳ Update geofence point ─▶︎ ' . $params['value']); + } + } else log::add('mobile', 'debug', '| [WARNING] A required parameter does not exist or is empty !'); + } else log::add('mobile', 'debug', '| [ERROR] EqLogic unknown ─▶︎ ' . $params['Iq']); + } + log::add('mobile', 'debug', '└───────────────────────────────────────────'); + $jsonrpc->makeSuccess(); +} + +if ($jsonrpc->getMethod() == 'geolocDel') { + log::add('mobile', 'debug', '┌──────────▶︎:fg-warning: geolocDel V1 :/fg:──────────────'); + if (isset($params['Iq'])) { + $mobile = eqLogic::byLogicalId($params['Iq'], 'mobile'); + if (is_object($mobile)) { + if (isset($params['id']) && $params['id'] != '') { + $cmdgeoloc = cmd::byEqLogicIdAndLogicalId($mobile->getId(), 'geoId_' . $params['id']); + if (is_object($cmdgeoloc)) { + $cmdgeoloc->remove(); + log::add('mobile', 'debug', '| geoId_' . $params['id'] . ' (' . $params['name'] . ') is deleted with success.'); + } + } else log::add('mobile', 'debug', '| [WARNING] A required parameter Id does not exist or is empty !'); + } else log::add('mobile', 'debug', '| [ERROR] EqLogic unknown ─▶︎ ' . $params['Iq']); + } + log::add('mobile', 'debug', '└───────────────────────────────────────────'); + $jsonrpc->makeSuccess(); +} throw new Exception(__('Aucune demande', __FILE__)); diff --git a/core/class/mobile.class.php b/core/class/mobile.class.php index bcb5901d..0fdaf818 100755 --- a/core/class/mobile.class.php +++ b/core/class/mobile.class.php @@ -24,13 +24,52 @@ class mobile extends eqLogic { + /* AppV1 */ + public static $_pluginSuported = array('mobile', 'openzwave', 'rfxcom', 'edisio', 'mpower', 'mySensors', 'Zibasedom', 'virtual', 'camera', 'weather', 'philipsHue', 'enocean', 'wifipower', 'alarm', 'mode', 'apcupsd', 'btsniffer', 'dsc', 'rflink', 'mysensors', 'relaynet', 'remora', 'unipi', 'eibd', 'thermostat', 'netatmoThermostat', 'espeasy', 'jeelink', 'teleinfo', 'tahoma', 'protexiom', 'boilerThermostat', 'lifx', 'wattlet', 'rfplayer', 'openenocean', 'netatmoWeather', 'Volets', 'vmczehnder', 'zigbee'); + public static $_pluginWidget = array('alarm', 'camera', 'thermostat', 'netatmoThermostat', 'weather', 'mode', 'mobile'); + public static $_pluginMulti = array('LIGHT_STATE', 'ENERGY_STATE', 'FLAP_STATE', 'HEATING_STATE', 'SIREN_STATE', 'LOCK_STATE'); + public static $_listenEvents = array('cmd::update', 'scenario::update', 'jeeObject::summary::update'); + /* * ***********************Methode static*************************** */ + /** + * Core callback to returns the directory of data not to be saved in the Jeedom backup + * + * @return array + */ + public static function backupExclude() + { + return ['data/images']; + } + + /** + * cron callback + * clean notification V2 + * makeTemplate V1 + */ public static function cronDaily() { + // APP V2 foreach (eqLogic::byType('mobile') as $mobile) { - $mobile->cleaningNotifications(); + if ($mobile->getConfiguration('appVersion', 1) == 2) { + $mobile->cleaningNotifications(); + } } + // App V1 + mobile::makeTemplateJson(); + } + + /** + * wizard AppV2 + * Call by wizard.php + * @return array + */ + public static function getWizardSteps(): array + { + $wizard['doc1'] = __('Accueil', __FILE__); + $wizard['doc2'] = __('Page2', __FILE__); + $wizard['doc3'] = __('Page3', __FILE__); + return $wizard; } /** @@ -47,11 +86,11 @@ public static function getConfigForCommunity() $res = '
```
'; $res .= 'OS : ' . $distrib . ' on ' . $hw; $res .= ' - PHP : ' . phpversion(); - $res .= '
'; + $res .= '
'; $res .= 'Etat Clé Api Core : ' . config::byKey('api::core::mode'); - $res .= '
'; - $res .= 'Etat Clé Api Mobile : ' . config::byKey('api::mobile::mode') . '
```'; - $res .= '

'; + $res .= '
'; + $res .= 'Etat Clé Api Mobile : ' . config::byKey('api::mobile::mode') . '
```'; + $res .= '

'; $res .= '[details="Equipement(s)"]
'; $res .= '|Id | LogicalId | Type | App | defaultIdMobile | Profil | hideMenuGeoloc | hideMenuCustom|
'; $res .= '|--- | --- | --- | --- | --- | --- | --- | ---|
'; @@ -79,10 +118,489 @@ public static function whoIsIq($iq) if (is_object($search)) { return $search->getName(); } else { - return 'mobile non detecte'; + return 'Mobile not detected'; + } + } + + /******************************************************/ + /******************** APP V1 *************************/ + /******************************************************/ + + public static function pluginToSend() + { + $return = []; + $plugins = plugin::listPlugin(true); + foreach ($plugins as $plugin) { + $plugId = $plugin->getId(); + //if ($plugId == 'mobile') { + // continue; + //} else if (in_array($plugId, self::$_pluginWidget)) { + if (in_array($plugId, self::$_pluginWidget)) { + $return[] = $plugId; + } else if (in_array($plugId, self::$_pluginSuported) && !in_array($plugId, self::$_pluginWidget) && config::byKey('sendToApp', $plugId, 1) == 1) { + $return[] = $plugId; + } else if (!in_array($plugId, self::$_pluginSuported) && config::byKey('sendToApp', $plugId, 0) == 1) { + $subClasses = config::byKey('subClass', $plugId, ''); + if ($subClasses != '') { + $subClassesList = explode(';', $subClasses); + foreach ($subClassesList as $subClass) { + $return[] = $subClass; + } + } + $return[] = $plugId; + } + } + return $return; + } + + public static function makeTemplateJson() + { + log::add(__CLASS__, 'debug', '┌──────────▶︎ makeTemplateJson ──────────────'); + $pluginToSend = mobile::pluginToSend(); + $discover_eqLogic = mobile::discovery_eqLogic($pluginToSend); + $sync_new = mobile::change_cmdAndeqLogic(mobile::discovery_cmd($pluginToSend, $discover_eqLogic), $discover_eqLogic); + $config = array( + 'url_internal' => network::getNetworkAccess('internal'), + 'url_external' => network::getNetworkAccess('external'), + ); + $objectReturn = mobile::delete_object_eqlogic_null(mobile::discovery_object(), $sync_new['eqLogics']); + $data = array( + 'eqLogics' => $sync_new['eqLogics'], + 'cmds' => $sync_new['cmds'], + 'objects' => mobile::delete_object_eqlogic_null(mobile::discovery_object(), $sync_new['eqLogics']), + 'scenarios' => mobile::discovery_scenario(), + 'plans' => mobile::discovery_plan(), + 'summary' => mobile::discovery_summary(), + 'config' => $config, + ); + $path = dirname(__FILE__) . '/../../data/mobile.json'; + if (!file_exists(dirname(__FILE__) . '/../../data')) { + mkdir(dirname(__FILE__) . '/../../data'); + } + if (file_exists(dirname(__FILE__) . '/../../data/mobile.json')) { + unlink(dirname(__FILE__) . '/../../data/mobile.json'); + } + file_put_contents(dirname(__FILE__) . '/../../data/mobile.json', json_encode($data)); + log::add(__CLASS__, 'debug', '| mobile.json > ' . json_encode($data)); + $event_cmd = array(); + foreach ($data['cmds'] as $cmd) { + $event_cmd[] = $cmd['id']; + } + cache::set('mobile::event', $event_cmd); + log::add(__CLASS__, 'debug', '| cache set mobile::event ─▶︎ ' . json_encode($event_cmd)); + log::add(__CLASS__, 'debug', '└───────────────────────────────────────────'); + } + + public static function getTemplateJson() + { + if (!file_exists(dirname(__FILE__) . '/../../data/mobile.json')) { + self::makeTemplateJson(); + } + return json_decode(cmd::cmdToValue(file_get_contents(dirname(__FILE__) . '/../../data/mobile.json')), true); + } + + public static function makeSaveJson($mobileID, $_data = array(), $type = 'dashboard') + { + $path = dirname(__FILE__) . '/../../data/' . $mobileID . '/' . $type . '.json'; + if (!file_exists(dirname(__FILE__) . '/../../data')) { + mkdir(dirname(__FILE__) . '/../../data'); + } + if (!file_exists(dirname(__FILE__) . '/../../data/' . $mobileID)) { + mkdir(dirname(__FILE__) . '/../../data/' . $mobileID); + } + if (file_exists(dirname(__FILE__) . '/../../data/' . $mobileID . '/' . $type . '.json')) { + unlink(dirname(__FILE__) . '/../../data/' . $mobileID . '/' . $type . '.json'); + } + file_put_contents(dirname(__FILE__) . '/../../data/' . $mobileID . '/' . $type . '.json', json_encode($_data)); + } + + public static function getSaveJson($mobileID, $type = 'dashboard') + { + if (!file_exists(dirname(__FILE__) . '/../../data/' . $mobileID . '/' . $type . '.json')) { + self::makeSaveJson($mobileID, array(), $type); + } + return json_decode(file_get_contents(dirname(__FILE__) . '/../../data/' . $mobileID . '/' . $type . '.json'), true); + } + + public static function discovery_eqLogic($plugin = array(), $hash = null) + { + $return = array(); + foreach ($plugin as $plugin_type) { + $eqLogics = eqLogic::byType($plugin_type, true); + if (!is_array($eqLogics)) { + continue; + } + foreach ($eqLogics as $eqLogic) { + if ($eqLogic->getEqType_name() != 'mobile') { + if ($eqLogic->getIsEnable() != 1) { + continue; + } + if ($eqLogic->getObject_id() == null) { + continue; + } + $objectNow = $eqLogic->getObject(); + if (!is_object($objectNow)) { + continue; + } + if (($eqLogic->getIsVisible() != 1 && (!in_array($eqLogic->getEqType_name(), self::$_pluginWidget)) || $objectNow->getDisplay('sendToApp', 1) != 1)) { + continue; + } + } + $eqLogic_array = utils::o2a($eqLogic); + if ($eqLogic->getEqType_name() == 'mobile') { + if (isset($eqLogic_array["logicalId"])) { + $eqLogic_array["localApiKey"] = $eqLogic_array["logicalId"]; + } + } + if (isset($eqLogic_array["configuration"]["localApiKey"])) { + $eqLogic_array["localApiKey"] = $eqLogic_array["configuration"]["localApiKey"]; + } + if ($eqLogic_array['eqType_name'] == 'jeelink') { + if (isset($eqLogic_array['configuration']['real_eqType'])) { + $eqLogic_array['eqType_name'] = $eqLogic_array['configuration']['real_eqType']; + } + } + unset($eqLogic_array['eqReal_id'], $eqLogic_array['comment'], $eqLogic_array['configuration'], $eqLogic_array['specificCapatibilities'], $eqLogic_array['timeout'], $eqLogic_array['category'], $eqLogic_array['display']); + unset($eqLogic_array['status']); + unset($eqLogic_array['generic_type']); + unset($eqLogic_array['logicalId']); + unset($eqLogic_array['isVisible']); + unset($eqLogic_array['isEnable']); + if (!in_array($eqLogic_array['eqType_name'], self::$_pluginWidget)) { + unset($eqLogic_array['eqType_name']); + } + $return[] = $eqLogic_array; + } + } + return $return; + } + + public static function discovery_cmd($plugin = array(), $eqLogics = null, $_withValue = false) + { + $return = array(); + $genericisvisible = array(); + foreach (jeedom::getConfiguration('cmd::generic_type') as $key => $info) { + if ($info['family'] !== 'Generic') { + $genericisvisible[] = $key; + } + } + if ($eqLogics == null) { + $eqLogics = self::discovery_eqLogic($plugin); + } + $eqLogics_id = array(); + foreach ($eqLogics as $eqLogic) { + $eqLogics_id[] = $eqLogic['id']; + } + if (count($eqLogics_id) > 0) { + foreach (cmd::byEqLogicId($eqLogics_id, null, null, null, true) as $cmd) { + if (in_array($cmd->getGeneric_type(), ['GENERIC_ERROR', 'DONT'])) { + continue; + } + if (!isset($eqLogic['eqType_name'])) { + $eqLogic['eqType_name'] = ''; + } + if ($cmd->getIsVisible() != 1 && !in_array($cmd->getGeneric_type(), $genericisvisible) && !in_array($eqLogic['eqType_name'], self::$_pluginWidget)) { + continue; + } + $info = $cmd->exportApi(); + unset($info['isHistorized']); + unset($info['template']); + unset($info['html']); + unset($info['alert']); + unset($info['isVisible']); + unset($info['logicalId']); + unset($info['eqType']); + unset($info['order']); + $info['configuration'] = array(); + $info['configuration']['actionCodeAccess'] = $cmd->getConfiguration('actionCodeAccess'); + $info['configuration']['actionConfirm'] = $cmd->getConfiguration('actionConfirm'); + $info['configuration']['maxValue'] = $cmd->getConfiguration('maxValue'); + $info['configuration']['minValue'] = $cmd->getConfiguration('minValue'); + $info['display'] = array(); + $info['display']['invertBinary'] = $cmd->getDisplay('invertBinary'); + $info['display']['icon'] = $cmd->getDisplay('icon'); + $info['display']['title_disable'] = $cmd->getDisplay('title_disable'); + $info['display']['title_placeholder'] = $cmd->getDisplay('title_placeholder'); + $info['display']['message_placeholder'] = $cmd->getDisplay('message_placeholder'); + if (!in_array($cmd->getGeneric_type(), ['GENERIC_INFO', 'GENERIC_ACTION', 'HEATING_ON', 'HEATING_OTHER', 'MODE_SET_STATE']) && isset($info['display']['icon'])) { + unset($info['display']['icon']); + } + if (isset($info['display']['icon'])) { + $info['display']['icon'] = str_replace(array(''), '', $info['display']['icon']); + if (strstr($info['display']['icon'], ' icon_')) { + $info['display']['icon'] = strstr($info['display']['icon'], ' icon_', true); + } + } + foreach ($info['display'] as $key => $value) { + if (trim($value) == '') { + unset($info['display'][$key]); + } + } + if (count($info['display']) == 0) { + unset($info['display']); + } + foreach ($info['configuration'] as $key => $value) { + if (trim($value) == '') { + unset($info['configuration'][$key]); + } + } + if (count($info['configuration']) == 0) { + unset($info['configuration']); + } + if ($info['type'] == 'action') { + unset($info['currentValue']); + } else if (!$_withValue) { + $info['currentValue'] = '#' . $info['id'] . '#'; + } + if ($info['value'] == null) { + unset($info['value']); + } + if ($info['unite'] == '') { + unset($info['unite']); + } + $return[] = $info; + } + } + return $return; + } + + public static function discovery_multi($cmds) + { + $array_final = array(); + $tableData = self::$_pluginMulti; + foreach ($cmds as $cmd) { + if (in_array($cmd['generic_type'], $tableData)) { + $result = array_intersect( + array_keys(array_column($cmds, 'eqLogic_id'), $cmd['eqLogic_id']), + array_keys(array_column($cmds, 'generic_type'), $cmd['generic_type']) + ); + if (count($result) > 1) { + $array_final = array_merge_recursive($array_final, $result); + } + } + } + $dif = array(); + $array_cmd_multi = array(); + foreach ($array_final as $array_fi) { + if (!in_array($array_fi, $dif)) { + array_push($dif, $array_fi); + array_push($array_cmd_multi, $array_fi); + } + } + return $array_cmd_multi; + } + + public static function change_cmdAndeqLogic($_cmds, $_eqLogics) + { + $findEqLogic = array(); + foreach ($_cmds as $cmd) { + $findEqLogic[$cmd['eqLogic_id']] = $cmd['eqLogic_id']; + } + $eqLogics = array(); + foreach ($_eqLogics as $eqLogic) { + if (!isset($findEqLogic[$eqLogic['id']])) { + continue; + } + $eqLogics[] = $eqLogic; + } + $plage_cmds = mobile::discovery_multi($_cmds); + if (count($plage_cmds) == 0) { + return array('cmds' => $_cmds, 'eqLogics' => $eqLogics); + } + $eqLogic_array = array(); + foreach ($plage_cmds as $plage_cmd) { + $eqLogic_id = $_cmds[$plage_cmd]['eqLogic_id']; + $name_cmd = $_cmds[$plage_cmd]['name']; + foreach ($eqLogics as $eqLogic) { + if ($eqLogic['id'] == $eqLogic_id) { + $eqLogic_name = $eqLogic['name'] . ' / ' . $name_cmd; + } + } + $id = $_cmds[$plage_cmd]['id']; + $new_eqLogic_id = '999' . $eqLogic_id . '' . $id; + $_cmds[$plage_cmd]['eqLogic_id'] = $new_eqLogic_id; + $keys = array_keys(array_column($_cmds, 'eqLogic_id'), $eqLogic_id); + foreach ($keys as $key) { + if (isset($_cmds[$key]['value']) && $_cmds[$key]['value'] == $_cmds[$plage_cmd]['id'] && $_cmds[$key]['type'] == 'action') { + $_cmds[$key]['eqLogic_id'] = $new_eqLogic_id; + } + } + $eqLogic_array[] = array($eqLogic_id, $new_eqLogic_id, $eqLogic_name); + //$i++; + } + $column_eqlogic = array_column($eqLogics, 'id'); + foreach ($eqLogic_array as $eqlogic_array_one) { + $keys = array_keys($column_eqlogic, $eqlogic_array_one[0]); + $new_eqLogic = $eqLogics[$keys[0]]; + $new_eqLogic['id'] = $eqlogic_array_one[1]; + $new_eqLogic['name'] = $eqlogic_array_one[2]; + $eqLogics[] = $new_eqLogic; + } + return array('cmds' => $_cmds, 'eqLogics' => $eqLogics); + } + + public static function discovery_object() + { + $all = utils::o2a(jeeObject::all()); + $return = array(); + foreach ($all as $object) { + if (isset($object['display']['sendToApp']) && $object['display']['sendToApp'] == "0") { + continue; + } + unset($object['configuration']); + unset($object['display']['tagColor']); + unset($object['display']['tagTextColor']); + unset($object['display']['desktop::summaryTextColor']); + unset($object['display']['dashboard::size']); + unset($object['display']['summaryTextColor']); + unset($object['image']); + unset($object['img']); + unset($object['father_id']); + if (isset($object['display']['icon'])) { + if ($object['display']['icon'] == '') { + unset($object['display']['icon']); + } else { + $object['display']['icon'] = str_replace(array(''), '', $object['display']['icon']); + $tableEx = array(); + $explodes = explode(' ', $object['display']['icon']); + foreach ($explodes as $explode) { + if (substr($explode, 0, 5) != 'icon_') { + $tableEx[] = $explode; + } + } + $object['display']['icon'] = implode(' ', $tableEx); + } + } + $return[] = $object; + } + return $return; + } + + public static function discovery_scenario() + { + $all = utils::o2a(scenario::all()); + $return = array(); + foreach ($all as &$scenario) { + if (isset($scenario['display']['sendToApp']) && $scenario['display']['sendToApp'] == "0") { + continue; + } + if (!isset($scenario['display']['sendToApp'])) { + continue; + } + if ($scenario['display']['name'] != '') { + $scenario['name'] = $scenario['display']['name']; + } + if (isset($scenario['display'])) { + unset($scenario['display']); + } + unset($scenario['mode'], $scenario['schedule'], $scenario['scenarioElement'], $scenario['trigger'], $scenario['timeout'], $scenario['description'], $scenario['configuration'], $scenario['type'], $scenario['display']['name']); + $return[] = $scenario; + } + return $return; + } + + public static function discovery_message() + { + //return utils::o2a(message::all()); + return array(); + } + + public static function discovery_plan() + { + $plans = utils::o2a(planHeader::all()); + foreach ($plans as &$plan) { + if (isset($plan['image'])) { + unset($plan['image']); + } + if (isset($plan['configuration'])) { + if (!isset($plan['configuration']['simee'])) { + unset($plan['configuration']); + } + } } + return $plans; } + public static function discovery_summary() + { + $return = array(); + $def = config::byKey('object:summary'); + foreach ($def as $key => &$value) { + //$value['value'] = jeeObject::getGlobalSummary($key); + if (isset($value['icon'])) { + if ($value['icon'] == '') { + unset($value['icon']); + } else { + $value['icon'] = str_replace(array(''), '', $value['icon']); + $tableEx = array(); + $explodes = explode(' ', $value['icon']); + foreach ($explodes as $explode) { + if (substr($explode, 0, 5) != 'icon_') { + $tableEx[] = $explode; + } + } + $value['icon'] = implode(' ', $tableEx); + } + } + } + return $def; + } + + public static function discovery_summaryValue($jeeObjectEnvoi) + { + $def = config::byKey('object:summary'); + $tableKey = array(); + foreach ($def as $key => $value) { + $tableKey[] = $key; + } + $table = array(); + foreach ($jeeObjectEnvoi as $jeeobject) { + $object = jeeObject::byId($jeeobject['id']); + if (is_object($object)) { + foreach ($tableKey as $key) { + if ($object->getSummary($key) != null) { + $tableObject = array(); + $tableObject['object_id'] = $object->getId(); + $tableObject['key'] = $key; + $tableObject['value'] = $object->getSummary($key); + $table[] = $tableObject; + } + } + } + } + foreach ($tableKey as $key) { + if (jeeObject::getGlobalSummary($key) != null) { + $tableObject = array(); + $tableObject['object_id'] = 'global'; + $tableObject['key'] = $key; + $tableObject['value'] = jeeObject::getGlobalSummary($key); + $table[] = $tableObject; + } + } + + return $table; + } + + public static function delete_object_eqlogic_null($objects, $eqLogics) + { + $return = array(); + $object_id = array(); + foreach ($eqLogics as $eqLogic) { + $object_id[$eqLogic['object_id']] = $eqLogic['object_id']; + } + foreach ($objects as $object) { + if (!isset($object_id[$object['id']])) { + continue; + } + $return[] = $object; + } + return $return; + } + + /************************************************************/ + /******************** APP V1 && V2 *************************/ + /************************************************************/ + /** * get json for notification * Call by class notification @@ -91,8 +609,8 @@ public static function whoIsIq($iq) public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answer, $timeout, $token, $photo, $version, $optionsNotif = [], $critical = false, $Iq = null, $specific = false, $silent = false) { log::add('mobile', 'debug', '||┌──:fg-success: jsonPublish :/fg:──'); - log::add('mobile', 'debug', '||┌──:fg-success: PARAMS :/fg:──'.$silent); - if (isset($Iq)) log::add('mobile', 'debug', '||| IQ for jsonPublish > ' . $Iq); + if ($silent) log::add('mobile', 'debug', '||| Silent notification'); + if (isset($Iq)) log::add('mobile', 'debug', '||| IQ for jsonPublish ─▶︎ ' . $Iq); $dateNotif = date("Y-m-d H:i:s"); $newDate = date("Y-m-d"); @@ -121,6 +639,7 @@ public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answ } } else { if ($version == 2) { + //App V2 if ($addAsk != '') { $askParams = [ 'choices' => $answer, @@ -142,25 +661,7 @@ public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answ if ($os == 'android' && $critical == true) { $channelId = "critical"; } - if ($critical == true) { - $criticalString = 'true'; - } else { - $criticalString = 'false'; - } - // $customData = [ - // 'title' => $titre, - // 'body' => $message, - // 'idNotif' => strval($idNotif), - // 'channelId' => $channelId, - // 'date' => $dateNotif, - // 'critical' => $criticalString, - // 'boxName' => $defaultName, - // 'boxApiKey' => jeedom::getHardwareKey(), - // "askParams" => $askParams, - // 'textToDisplay' => 'none', - // 'newDate' => $newDate, - // 'horaireFormat' => $horaireFormat - // ]; + $criticalString = ($critical == true) ? 'true' : 'false'; $customData = [ 'title' => $titre, 'body' => $message, @@ -174,7 +675,7 @@ public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answ 'textToDisplay' => 'none', 'newDate' => $newDate, 'horaireFormat' => $horaireFormat, - 'silent' => $silent ? 'true' : 'false' + 'silent' => $silent ? 'true' : 'false' ]; $notification = [ @@ -200,6 +701,7 @@ public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answ 'aps' => array_merge([ 'content-available' => true, ], $silent ? [] : [ + 'mutable-content' => 1, 'sound' => [ 'name' => 'default', 'critical' => $critical @@ -222,8 +724,6 @@ public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answ ] ] ]; - - if ($photo != null) { $data['image'] = $photo; @@ -255,9 +755,8 @@ public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answ 'data' => $data, ]; - if (isset($Iq) && !$specific) { - // SAVE NOTIFS IN JSON + // SAVE NOTIFS IN FILE $pathNotificationData = '/../data/notifications'; if (!is_dir(dirname(__FILE__) . $pathNotificationData)) { mkdir(dirname(__FILE__) . $pathNotificationData, 0775, true); @@ -278,20 +777,59 @@ public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answ if (isset($notification['data']['askParams'])) { $askParams = json_decode($notification['data']['askParams'], true); if ($askParams !== null && isset($askParams['timeout'])) { - //log::add('mobile', 'debug', 'Timeout Ask remis à zero'); $askParams['timeout'] = 0; $notification['data']['askParams'] = json_encode($askParams); } } } $notifications[$idNotif] = $publishJson; - log::add('mobile', 'debug', '||| [INFO] Notification enregistrée : ' . json_encode($notifications)); + log::add('mobile', 'debug', '||| [INFO] Notification logged ─▶︎ ' . json_encode($notifications)); file_put_contents($filePath, json_encode($notifications)); } + } else { + // APP V1 + if ($os == 'android' && $version == 1) { + $android = [ + 'notification' => [ + 'title' => $titre, + 'body' => $message, + 'channel_id' => 'default', + 'color' => '#0000FF' + ] + ]; + + $data = [ + 'title' => $titre, + 'text' => $message, + 'idNotif' => strval($idNotif), + 'channelId' => 'default', + 'date' => $dateNotif + ]; + + if ($photo != null) { + $notification = [ + 'title' => $titre, + 'body' => $message, + 'image' => $photo + ]; + } else { + $notification = [ + 'title' => $titre, + 'body' => $message + ]; + } + + $publish = [ + 'token' => $token, + 'notification' => $notification, + 'android' => $android, + 'data' => $data + ]; + } } } - log::add('mobile', 'debug', '||| [INFO] JSON publish > ' . json_encode($publish)); - log::add('mobile', 'debug', '||└────────────────────'); + log::add('mobile', 'debug', '||| [INFO] JSON publish ─▶︎ ' . json_encode($publish)); + log::add('mobile', 'debug', '||└─────────────────'); return $publish; } @@ -302,70 +840,115 @@ public static function jsonPublish($os, $titre, $message, $type, $idNotif, $answ */ public static function notification($arn, $os, $titre, $message, $type, $idNotif, $answer, $timeout, $token, $photo, $version = 1, $optionsNotif = [], $critical = false, $Iq = null, $specific = false, $silent = false) { - log::add('mobile', 'debug', '|┌──:fg-success: Notification en cours ! :/fg:──'); - if ($version == 2) { - $publish = mobile::jsonPublish($os, $titre, $message, $type, $idNotif, $answer, $timeout, $token, $photo, $version, $optionsNotif, $critical, $Iq, $specific, $silent); - if ($token != null) { - if ($token == 'notifsBGDisabled') { - log::add('mobile', 'debug', '|| [ERROR] NOTIFICATION NON ENVOYEE : LE SERVICE NOTIF EST DESACTIVE SUR LE TELEPHONE'); - message::add(__CLASS__, 'Échec de l\'envoie de notification : le service est désactivé dans les paramètres du téléphone', 'notifsbgSend', 'alertNotifsSend'); - return; - } - if ($token == 'desactivate') { - log::add('mobile', 'debug', '|| [ERROR] NOTIFICATION NON ENVOYEE : LES NOTIFICATIONS SONT DESACTIVEES DANS L\'APP : '); - message::add(__CLASS__, 'Échec de l\'envoie de notification : le service est désactivé dans les paramètres de l\'application', 'notifsbgSend', 'alertNotifsSend'); - return; - } - $url = config::byKey('service::cloud::url', 'core', 'https://cloud.jeedom.com') . '/service/fcm'; - $options = [ - 'contentAvailable' => true, - 'mutableContent' => true, - 'priority' => 'high', - 'collapseKey' => strval($publish['data']['idNotif']) - ]; - - $post = ['message' => $publish, 'options' => $options]; - log::add('mobile', 'debug', '|| [INFO] JSON envoyé en mode FCM > ' . json_encode($post)); - } elseif ($token == null && $version == 2) { - log::add('mobile', 'debug', '|| [ERROR] NOTIFICATION NON ENVOYEE : PAS DE TOKEN ENREGISTRE SUR LE TELEPHONE : '); - //message::removeAll(__CLASS__, 'noValidToken'); - message::add(__CLASS__, '| NOTIFICATION NON ENVOYÉE : PAS DE TOKEN ENREGISTRE SUR LE TÉLÉPHONE :', 'noValidTok', 'noValidToken'); + log::add('mobile', 'debug', '|┌──:fg-success: notification :/fg:──'); + //if ($version == 2) { + $publish = mobile::jsonPublish($os, $titre, $message, $type, $idNotif, $answer, $timeout, $token, $photo, $version, $optionsNotif, $critical, $Iq, $specific, $silent); + if ($token != null) { + if ($token == 'notifsBGDisabled') { + log::add('mobile', 'debug', '|| [ERROR] NOTIFICATION NOT SENT ─▶︎ The notification service is disabled on the phone.'); + message::add(__CLASS__, __('Echec de l\'envoi de la notification', __FILE__) . ' ─▶︎ ' . __('le service est désactivé dans les paramètres du téléphone', __FILE__), 'notifsbgSend', 'alertNotifsSend'); return; - } else { - log::add('mobile', 'debug', '|| [INFO] JSON envoyé : APN' . $publish); - $post = [ - 'arn' => $arn, - 'text' => $publish, - ]; - $url = config::byKey('service::cloud::url', 'core', 'https://cloud.jeedom.com') . '/service/notif'; } + if ($token == 'desactivate') { + log::add('mobile', 'debug', '|| [ERROR] NOTIFICATION NOT SENT ─▶︎ The notification service is disabled on the application.'); + message::add(__CLASS__, __('Echec de l\'envoi de la notification', __FILE__) . ' ─▶︎ ' . __('le service est désactivé dans les paramètres de l\'application', __FILE__), 'notifsbgSend', 'alertNotifsSend'); + return; + } + $url = config::byKey('service::cloud::url', 'core', 'https://cloud.jeedom.com') . '/service/fcm'; + $options = [ + 'contentAvailable' => true, + 'mutableContent' => true, + 'priority' => 'high', + 'collapseKey' => strval($publish['data']['idNotif']) + ]; + + $post = ['message' => $publish, 'options' => $options]; + log::add('mobile', 'debug', '|| [INFO] JSON sent in FCM mode ─▶︎ ' . json_encode($post)); + } elseif ($token == null && $version == 2) { + log::add('mobile', 'debug', '|| [ERROR] NOTIFICATION NOT SENT ─▶︎ No token registered on the phone'); + message::add(__CLASS__, __('Echec de l\'envoi de la notification', __FILE__) . ' ─▶︎ ' . __('pas de token enregistré sur le téléphone', __FILE__), 'noValidTok', 'noValidToken'); + return; + } else { + log::add('mobile', 'debug', '|| [INFO] JSON sent in APN mode ─▶︎ ' . $publish); + $post = [ + 'arn' => $arn, + 'text' => $publish, + ]; + $url = config::byKey('service::cloud::url', 'core', 'https://cloud.jeedom.com') . '/service/notif'; + } - $request_http = new com_http($url); - $request_http->setHeader(array( - 'Content-Type: application/json', - 'Autorization: ' . sha512(strtolower(config::byKey('market::username')) . ':' . config::byKey('market::password')) - )); - //$request_http->setLogError(true); - $request_http->setPost(json_encode($post)); + $request_http = new com_http($url); + $request_http->setHeader(array( + 'Content-Type: application/json', + 'Autorization: ' . sha512(strtolower(config::byKey('market::username')) . ':' . config::byKey('market::password')) + )); + //$request_http->setLogError(true); + $request_http->setPost(json_encode($post)); + $result = json_decode($request_http->exec(30, 3), true); + if (!isset($result['state']) || $result['state'] != 'ok') { + log::add('mobile', 'debug', '|| [WARNING] First attempt to send notification failed.'); + log::add('mobile', 'debug', '|| New attempt ....'); + sleep(rand(1, 10)); $result = json_decode($request_http->exec(30, 3), true); - if (!isset($result['state']) || $result['state'] != 'ok') { - log::add('mobile', 'info', '|| [WARNING] Echec Première Tentative d\'envoi de la notification'); - log::add('mobile', 'info', '|| Nouvelle tentative ....'); - sleep(rand(1, 10)); - $result = json_decode($request_http->exec(30, 3), true); + } + if (!isset($result['state']) || $result['state'] != 'ok') { + if (isset($result['error']) && strpos($result['error'], 'Quotas exceeded') !== false) { + log::add('mobile', 'error', __("Les quotas pour fcm sont dépassés. Le maximum autorisé est de 5 requêtes par minute.", __FILE__)); + log::add('mobile', 'debug', __('Echec de l\'envoi de la notification', __FILE__) . ' ─▶︎ ' . json_encode($result)); + } else { + throw new Exception(__('Echec de l\'envoi de la notification', __FILE__) . ' ─▶︎ ' . json_encode($result)); } - if (!isset($result['state']) || $result['state'] != 'ok') { - if (isset($result['error']) && strpos($result['error'], 'Quotas exceeded') !== false) { - log::add('mobile', 'error', __("Les quotas pour fcm sont dépassés. Le maximum autorisé est de 5 requêtes par minute.", __FILE__)); - log::add('mobile', 'debug', __('Echec de l\'envoi de la notification :', __FILE__) . json_encode($result)); - } else { - throw new Exception(__('Echec de l\'envoi de la notification :', __FILE__) . json_encode($result)); - } + } + //} else { + //log::add('mobile', 'error', __('Echec de l\'envoi de la notification', __FILE__) . ' ─▶︎ ' . __('la version 1 de l\'app n\'est plus prise en charge', __FILE__)); + //} + log::add('mobile', 'debug', '|└─────────────────────────────'); + } + + /*****************************************************/ + /******************** APP V2 *************************/ + /*****************************************************/ + + /** + * Get all notifications from Iq + * Call by ajax getNotificationsV2 + * @return array + */ + public static function getNotificationsV2($Iq) + { + $return = __('Aucune notification.', __FILE__); + $filePath = dirname(__FILE__) . '/../data/notifications/' . $Iq . '.json'; + if (file_exists($filePath)) { + $notifs = json_decode(file_get_contents($filePath), true); + if (is_array($notifs) && count($notifs) > 0) $return = json_encode(array_reverse($notifs)); + } + return $return; + } + + /** + * remove notification from Id into filepath id + * Call by ajax removeNotificationV2 + */ + public static function removeNotificationV2($_iq, $_id) + { + $pathNotificationData = '/../data/notifications'; + $filePath = dirname(__FILE__) . $pathNotificationData . '/' . $_iq . '.json'; + if (file_exists($filePath)) { + $notificationsContent = file_get_contents($filePath); + $notifications = json_decode($notificationsContent, true); + if ($notifications === null) { + throw new Exception(__('Fichier de notification vide.', __FILE__)); + } + if (isset($notifications[$_id])) { + unset($notifications[$_id]); + file_put_contents($filePath, json_encode($notifications)); + return count($notifications); + } else { + throw new Exception(__('Id notification inexistant', __FILE__) . ' ─▶︎ ' . $_id); } } else { - log::add('mobile', 'error', __("Échec de l'envoi de notification : la version 1 de l'app n'est plus prise en charge !", __FILE__)); + throw new Exception(__('Fichier de notifications inexistant', __FILE__) . ' ─▶︎ ' . $filePath); } - log::add('mobile', 'debug', '|└────────────────────'); } /** @@ -374,26 +957,26 @@ public static function notification($arn, $os, $titre, $message, $type, $idNotif */ public static function createCmdGeoLocV2($Iq, $geolocs) { - log::add('mobile', 'debug', '|┌──:fg-success: GeoLocV2 :/fg:──'); + log::add('mobile', 'debug', '|┌──:fg-success: createCmdGeoLocV2 :/fg:──'); $mobile = eqLogic::byLogicalId($Iq, 'mobile'); if (is_object($mobile)) { - log::add('mobile', 'debug', '|| OK Mobile existant > ' . $mobile->getName()); - log::add('mobile', 'debug', '|| [INFO] GEOLOCS > ' . $geolocs); - + log::add('mobile', 'debug', '|| OK Mobile found ─▶︎ ' . $mobile->getName()); + log::add('mobile', 'debug', '|| [INFO] GEOLOCS ─▶︎ ' . $geolocs); $order = count($mobile->getCmd()); - $noExistCmd = 0; $decodedGeolocs = json_decode($geolocs, true); foreach ($decodedGeolocs as $index => $geoloc) { if (!isset($geoloc['name'])) continue; - log::add('mobile', 'debug', '|| geoloc_' . $index . ' > ' . $geoloc['name']); - $cmd = cmd::byEqLogicIdAndLogicalId($mobile->getId(), 'geoloc_' . $index); $logicalId = 'geoloc_' . $index; + log::add('mobile', 'debug', '|| ' . $logicalId . ' ─▶︎ ' . $geoloc['name'] . ' ─▶︎ ' . $geoloc['value']); + $cmd = cmd::byEqLogicIdAndLogicalId($mobile->getId(), 'geoloc_' . $index); if (!is_object($cmd)) { if (!preg_match('/^geoloc_\d+$/', $logicalId)) { foreach ($mobile->getCmd() as $existing) { - if (preg_match('/^geoloc_\d+$/', $existing->getLogicalId()) - && $existing->getName() === $geoloc['name']) { - log::add('mobile', 'debug', '|| Migration UUID : renommage ' . $existing->getLogicalId() . ' -> ' . $logicalId); + if ( + preg_match('/^geoloc_\d+$/', $existing->getLogicalId()) + && $existing->getName() === $geoloc['name'] + ) { + log::add('mobile', 'debug', '|| ↳ Migrate UUID ─▶︎ renaming ' . $existing->getLogicalId() . ' to ' . $logicalId); $existing->setLogicalId($logicalId); $existing->save(); $cmd = $existing; @@ -403,7 +986,6 @@ public static function createCmdGeoLocV2($Iq, $geolocs) } } if (!is_object($cmd)) { - $noExistCmd = 1; $cmd = new mobileCmd(); $cmd->setLogicalId($logicalId); $cmd->setEqLogic_id($mobile->getId()); @@ -416,7 +998,7 @@ public static function createCmdGeoLocV2($Iq, $geolocs) $cmd->setIsHistorized(1); $cmd->setOrder($order); $order++; - log::add('mobile', 'debug', '|| Ajout geofencing > ' . $geoloc['name']); + log::add('mobile', 'debug', '|| ↳ Adding geofence point ─▶︎ ' . $geoloc['name']); } $cmd->setName($geoloc['name']); $cmd->setType('info'); @@ -425,16 +1007,14 @@ public static function createCmdGeoLocV2($Iq, $geolocs) $cmd->setConfiguration('longitude', $geoloc['longitude']); $cmd->setConfiguration('radius', $geoloc['radius']); if ($cmd->getChanged() === true) $cmd->save(); - if ($noExistCmd == 1) { - $mobile->checkAndUpdateCmd($logicalId, $geoloc['value']); - log::add('mobile', 'debug', '|| Valeur enregistrée > ' . $geoloc['value']); + if ($mobile->checkAndUpdateCmd($logicalId, $geoloc['value'])) { + log::add('mobile', 'debug', '|| ↳ Update geofence point ─▶︎ ' . $geoloc['value']); } - $noExistCmd = 0; } } else { - log::add('mobile', 'debug', '| [ERROR] Mobile inexistant !'); + log::add('mobile', 'debug', '| [WARNING] Mobile not detected !'); } - log::add('mobile', 'debug', '|└────────────────────'); + log::add('mobile', 'debug', '|└──────────────'); } /** @@ -486,20 +1066,18 @@ public static function handleMenuDefaultBySelect($eqId, $eqDefault) log::add('mobile', 'debug', '┌──:fg-success: handleMenuDefaultBySelect( ' . $eqId . ', ' . $eqDefault . ') :/fg:──'); // ATTRIBUTION D'UN MENU AU MOBILE if ($eqDefault == 'default') { //reset menuCustom - log::add('mobile', 'debug', '| menu souce : default'); + log::add('mobile', 'debug', '| source menu ─▶︎ default'); $menuCustomArray = mobile::getMenuDefaultV2(); $mobile->setConfiguration('menuCustomArray', $menuCustomArray); $mobile->setConfiguration('nbIcones', 3); $mobile->setConfiguration('defaultIdMobile', 'default'); $mobile->save(); } else if (is_object($mobileDefault = eqLogic::byId($eqDefault, 'mobile'))) { - log::add('mobile', 'debug', '| menu souce : ' . $mobileDefault->getHumanName()); // ATTRIBUTION DU MENU DUN AUTRE MOBILE + log::add('mobile', 'debug', '| source menu ─▶︎ ' . $mobileDefault->getHumanName()); $mobile->setConfiguration('defaultIdMobile', $eqDefault); if ($mobile->getId() == $mobileDefault->getId()) { - log::add('mobile', 'debug', '| souce et cible identique '); - //$mobile->save(); - //return; + log::add('mobile', 'debug', '| same source and target'); } $nbIcones = $mobileDefault->getConfiguration('nbIcones', 3); $menuCustomArray = $mobileDefault->getConfiguration('menuCustomArray'); @@ -517,23 +1095,19 @@ public static function handleMenuDefaultBySelect($eqId, $eqDefault) public static function generateTabIcon($menuCustomArray, $i) { $result = array(); - $tabIconName = isset($menuCustomArray[$i]['spanIcon']) ? $menuCustomArray[$i]['spanIcon'] : 'none'; if ($tabIconName != 'none') { $arrayIcon = explode(' ', $tabIconName); $tabIconName = substr(strstr($arrayIcon[1], '-'), 1); $tabLibName = strstr($arrayIcon[1], '-', true); - if ($tabLibName == 'mdi') { - $tabLibName = 'Mdi'; - } + if ($tabLibName == 'mdi') $tabLibName = 'Mdi'; } else { $tabIconName = 'in'; $tabLibName = 'jeedomapp'; } $tabRenameInput = (isset($menuCustomArray[$i]['renameIcon']) && $menuCustomArray[$i]['renameIcon'] != 'none') ? $menuCustomArray[$i]['renameIcon'] : 'Accueil'; - $result['tabIconName'] = $tabIconName; $result['tabLibName'] = $tabLibName; $result['tabRenameInput'] = $tabRenameInput; @@ -663,22 +1237,22 @@ public static function cmdForApi($Iq, $logicalId, $value, $name = "", $subtype = */ public function configMenuCustom() { - log::add('mobile', 'debug', '|┌──:fg-success: CONFIGMENU CUSTOM JEEDOM ' . jeedom::version() . ' :/fg:──'); + log::add('mobile', 'debug', '|┌──:fg-success: configMenuCustom (' . jeedom::version() . ') :/fg:──'); $menuCustomArray = mobile::getMenuDefaultV2(); $pluginPanelMobile = config::byKey('pluginPanelMobile', 'mobile'); $defaultIdMobile = $this->getConfiguration('defaultIdMobile'); if ($defaultIdMobile == 'default') { - log::add('mobile', 'debug', '|| [WARNING] Envoi menu par défaut'); + log::add('mobile', 'debug', '|| [WARNING] Send default menu'); $this->setConfiguration('menuCustomArray', $menuCustomArray); $this->save(); } else if (is_object($eqDefault = eqLogic::byId($defaultIdMobile)) && $this->getId() != $defaultIdMobile) { - log::add('mobile', 'debug', '|| [WARNING] Envoi menu de ' . $eqDefault->getHumanName()); + log::add('mobile', 'debug', '|| [WARNING] source menu ─▶︎ ' . $eqDefault->getHumanName()); $menuCustomArray = $eqDefault->getConfiguration('menuCustomArray'); $this->setConfiguration('menuCustomArray', $menuCustomArray); $this->save(); } else { - log::add('mobile', 'debug', '|| [INFO] Envoi menu de ' . $this->getHumanName()); + log::add('mobile', 'debug', '|| [INFO] source menu ─▶︎ ' . $this->getHumanName()); $menuCustomArray = $this->getConfiguration('menuCustomArray'); } if (empty($menuCustomArray)) { @@ -705,14 +1279,8 @@ public function configMenuCustom() $tabIconName = $resultTabIcon['tabIconName']; $tabLibName = $resultTabIcon['tabLibName']; $tabRenameInput = $resultTabIcon['tabRenameInput']; - //$objectId = $menuCustomArray[$i]['selectNameMenu']; - //$objectId = isset($menuCustomArray[$i]['selectNameMenu']) ? $menuCustomArray[$i]['selectNameMenu'] : ''; $isActive = true; - //$webviewUrl = 'd'; - //if (!empty($objectId)) log::add('mobile', 'debug', '|| - objectId > ' . $objectId); - - // GENERATE URLS FOR MENU CUSTOM - //$result = self::generateTypeObject($objectId, $i, $webviewUrl, $pluginPanelMobile); + // GENERATE URLS FOR MENU CUSTOM $result = self::generateTypeObject($pluginPanelMobile, isset($menuCustomArray[$i]) ? $menuCustomArray[$i] : ''); $typeObject = $result['typeObject']; $typewebviewurl = $result['typewebviewurl']; @@ -742,7 +1310,7 @@ public function configMenuCustom() $j++; $count++; } - log::add('mobile', 'debug', '|| [INFO] arrayElements > ' . json_encode($arrayElements)); + log::add('mobile', 'debug', '|| [INFO] arrayElements ─▶︎ ' . json_encode($arrayElements)); log::add('mobile', 'debug', '|└────────────────────'); return $arrayElements; } @@ -829,93 +1397,143 @@ public static function getQrCodeV2($userId) */ public function cmdForSpecificChannel($params = array(), $_trigger = 'location') { - if (isset($params['Iq'])) { - if (isset($params[$_trigger])) { - $order = count($this->getCmd()); + log::add('mobile', 'debug', '|┌──:fg-success: cmdForSpecificChannel :/fg:──'); + if (isset($params[$_trigger])) { + $order = count($this->getCmd()); + $getDeviceInformations = (isset($params[$_trigger]['extras']) && isset($params[$_trigger]['extras']['method']) && $params[$_trigger]['extras']['method'] == 'getDeviceInformations'); + $eventAge = time() - intval(strtotime($params[$_trigger]['timestamp'])); + if ($eventAge > 1800) { + log::add('mobile', 'debug', '|| SKIP stale specific event (' . round($eventAge / 60) . 'min) '); + } else { + log::add('mobile', 'debug', '|| eventAge = ' . $eventAge . ' s'); // Battery if (isset($params[$_trigger]['battery'])) { // level if (isset($params[$_trigger]['battery']['level'])) { - $cmd = $this->getCmd(null, 'phoneBattery'); - if (!is_object($cmd)) { - $cmd = new mobileCmd(); - $cmd->setLogicalId('phoneBattery'); - $cmd->setName(__('Batterie du téléphone', __FILE__)); - $cmd->setDisplay('icon', ''); - $cmd->setDisplay('showIconAndNamedashboard', 1); - $cmd->setDisplay('showIconAndNamemobile', 1); - $cmd->setDisplay('forceReturnLineAfter', 1); - $cmd->setConfiguration('historizeRound', 2); - $cmd->setConfiguration('minValue', 0); - $cmd->setConfiguration('maxValue', 100); - $cmd->setUnite('%'); - $cmd->setIsVisible(0); - $cmd->setOrder($order); - $order++; - log::add('mobile', 'debug', 'Create cmd for phoneBattery'); + if ($getDeviceInformations) { + $cmd = $this->getCmd(null, 'battery::level'); + if (!is_object($cmd)) { + $cmd = new mobileCmd(); + $cmd->setLogicalId('battery::level'); + $cmd->setName(__('Batterie du téléphone', __FILE__)); + $cmd->setDisplay('icon', ''); + $cmd->setDisplay('showIconAndNamedashboard', 1); + $cmd->setDisplay('showIconAndNamemobile', 1); + $cmd->setDisplay('forceReturnLineAfter', 1); + $cmd->setConfiguration('historizeRound', 2); + $cmd->setConfiguration('minValue', 0); + $cmd->setConfiguration('maxValue', 100); + $cmd->setUnite('%'); + $cmd->setIsVisible(0); + $cmd->setOrder($order); + $order++; + log::add('mobile', 'debug', '|| Creating the "phone battery" command'); + } + $cmd->setEqLogic_id($this->getId()); + $cmd->setType('info'); + $cmd->setConfiguration('calculValueOffset', '#value# * 100'); + $cmd->setSubType('numeric'); + if ($cmd->getChanged() === true) $cmd->save(); + } + if ($params[$_trigger]['battery']['level'] != -1) { + if ($this->checkAndUpdateCmd('battery::level', $params[$_trigger]['battery']['level'])) { + log::add('mobile', 'debug', '|| Updating "phone battery" value ─▶︎ ' . $params[$_trigger]['battery']['level'] * 100 . '%'); + } + } else { + log::add('mobile', 'debug', '|| [WARNING] No data available for battery level ─▶︎ ' . $params[$_trigger]['battery']['level']); } - $cmd->setEqLogic_id($this->getId()); - $cmd->setType('info'); - $cmd->setSubType('numeric'); - if ($cmd->getChanged() === true) $cmd->save(); - log::add('mobile', 'debug', '| OK phoneBattery = ' . $params[$_trigger]['battery']['level'] * 100); - $this->checkAndUpdateCmd('phoneBattery', $params[$_trigger]['battery']['level'] * 100); } // charging if (isset($params[$_trigger]['battery']['is_charging'])) { - $cmd = $this->getCmd(null, 'phoneCharging'); - if (!is_object($cmd)) { - $cmd = new mobileCmd(); - $cmd->setLogicalId('phoneCharging'); - $cmd->setName(__('En charge', __FILE__)); - $cmd->setDisplay('icon', ''); - $cmd->setDisplay('showIconAndNamedashboard', 1); - $cmd->setDisplay('showIconAndNamemobile', 1); - $cmd->setDisplay('forceReturnLineAfter', 1); - $cmd->setTemplate('dashboard', 'core::line'); - $cmd->setTemplate('mobile', 'core::line'); - $cmd->setIsVisible(0); - $cmd->setOrder($order); - $order++; - log::add('mobile', 'debug', 'Create cmd for phoneCharging'); + if ($getDeviceInformations) { + $cmd = $this->getCmd(null, 'battery::isCharging'); + if (!is_object($cmd)) { + $cmd = new mobileCmd(); + $cmd->setLogicalId('battery::isCharging'); + $cmd->setName(__('En charge', __FILE__)); + $cmd->setDisplay('icon', ''); + $cmd->setDisplay('showIconAndNamedashboard', 1); + $cmd->setDisplay('showIconAndNamemobile', 1); + $cmd->setDisplay('forceReturnLineAfter', 1); + $cmd->setTemplate('dashboard', 'core::line'); + $cmd->setTemplate('mobile', 'core::line'); + $cmd->setIsVisible(0); + $cmd->setOrder($order); + $order++; + log::add('mobile', 'debug', '|| Creating the "in charge" command'); + } + $cmd->setEqLogic_id($this->getId()); + $cmd->setType('info'); + $cmd->setSubType('binary'); + if ($cmd->getChanged() === true) $cmd->save(); + } + if ($this->checkAndUpdateCmd('battery::isCharging', intval($params[$_trigger]['battery']['is_charging']))) { + log::add('mobile', 'debug', '|| Updating "in charge" value ─▶︎ ' . intval($params[$_trigger]['battery']['is_charging'])); } - $cmd->setEqLogic_id($this->getId()); - $cmd->setType('info'); - $cmd->setSubType('binary'); - if ($cmd->getChanged() === true) $cmd->save(); - log::add('mobile', 'debug', '| OK phoneCharging = ' . intval($params[$_trigger]['battery']['is_charging'])); - $this->checkAndUpdateCmd('phoneCharging', intval($params[$_trigger]['battery']['is_charging'])); } } // coords if (isset($params[$_trigger]['coords'])) { if (isset($params[$_trigger]['coords']['latitude']) && isset($params[$_trigger]['coords']['longitude'])) { - $cmd = $this->getCmd(null, 'coords'); - if (!is_object($cmd)) { - $cmd = new mobileCmd(); - $cmd->setLogicalId('coords'); - $cmd->setName(__('Coordonnées', __FILE__)); - $cmd->setDisplay('icon', ''); - $cmd->setDisplay('showIconAndNamedashboard', 1); - $cmd->setDisplay('showIconAndNamemobile', 1); - $cmd->setDisplay('forceReturnLineAfter', 1); - $cmd->setTemplate('dashboard', 'core::line'); - $cmd->setTemplate('mobile', 'core::line'); - $cmd->setIsVisible(0); - $cmd->setOrder($order); - $order++; - log::add('mobile', 'debug', 'Create cmd for coords'); + if ($getDeviceInformations) { + $cmd = $this->getCmd(null, 'coords'); + if (!is_object($cmd)) { + $cmd = new mobileCmd(); + $cmd->setLogicalId('coords'); + $cmd->setName(__('Coordonnées', __FILE__)); + $cmd->setDisplay('icon', ''); + $cmd->setDisplay('showIconAndNamedashboard', 1); + $cmd->setDisplay('showIconAndNamemobile', 1); + $cmd->setDisplay('forceReturnLineAfter', 1); + $cmd->setTemplate('dashboard', 'core::line'); + $cmd->setTemplate('mobile', 'core::line'); + $cmd->setIsVisible(0); + $cmd->setOrder($order); + $order++; + log::add('mobile', 'debug', '|| Creating the "coordinates" command'); + } + $cmd->setEqLogic_id($this->getId()); + $cmd->setType('info'); + $cmd->setSubType('string'); + if ($cmd->getChanged() === true) $cmd->save(); + } + $coord = $params[$_trigger]['coords']['latitude'] . ',' . $params[$_trigger]['coords']['longitude']; + if ($this->checkAndUpdateCmd('coords', $coord)) { + log::add('mobile', 'debug', '|| Updating "coordinates" value ─▶︎ ' . $coord); + } + } + if (isset($params[$_trigger]['coords']['altitude'])) { + if ($getDeviceInformations) { + $cmd = $this->getCmd(null, 'altitude'); + if (!is_object($cmd)) { + $cmd = new mobileCmd(); + $cmd->setLogicalId('altitude'); + $cmd->setName(__('Altitude', __FILE__)); + $cmd->setDisplay('icon', ''); + $cmd->setDisplay('showIconAndNamedashboard', 1); + $cmd->setDisplay('showIconAndNamemobile', 1); + $cmd->setDisplay('forceReturnLineAfter', 1); + $cmd->setTemplate('dashboard', 'core::line'); + $cmd->setTemplate('mobile', 'core::line'); + $cmd->setIsVisible(0); + $cmd->setUnite('m'); + $cmd->setOrder($order); + $order++; + log::add('mobile', 'debug', '|| Creating the "altitude" command'); + } + $cmd->setEqLogic_id($this->getId()); + $cmd->setType('info'); + $cmd->setSubType('string'); + if ($cmd->getChanged() === true) $cmd->save(); + } + if ($this->checkAndUpdateCmd('altitude', $params[$_trigger]['coords']['altitude'])) { + log::add('mobile', 'debug', '|| Updating "Altitude" value ─▶︎ ' . $params[$_trigger]['coords']['altitude'] . 'm'); } - $cmd->setEqLogic_id($this->getId()); - $cmd->setType('info'); - $cmd->setSubType('string'); - if ($cmd->getChanged() === true) $cmd->save(); - log::add('mobile', 'debug', '| OK coords = ' . $params[$_trigger]['coords']['latitude'] . ',' . $params[$_trigger]['coords']['longitude']); - $this->checkAndUpdateCmd('coords', $params[$_trigger]['coords']['latitude'] . ',' . $params[$_trigger]['coords']['longitude']); } } } } + log::add('mobile', 'debug', '|└──────────────'); } /** @@ -925,8 +1543,8 @@ public function cmdForSpecificChannel($params = array(), $_trigger = 'location') public function cleaningNotifications() { $notifsTime = $this->getConfiguration('notifsTime', 30); - log::add('mobile', 'debug', '┌──────────▶︎ :fg-warning: Nettoyage des Notifications et Images :/fg: ──────────'); - log::add('mobile', 'debug', '| Durée de retention actuelle : ' . $notifsTime . ' jours'); + log::add('mobile', 'debug', '┌──────────▶︎ :fg-warning: cleaningNotifications :/fg: ──────────'); + log::add('mobile', 'debug', '| Current retention period ─▶︎ ' . $notifsTime . ' days'); // Images $retentionSeconds = intVal($notifsTime) * 24 * 60 * 60; $currentTime = time(); @@ -938,9 +1556,9 @@ public function cleaningNotifications() $fileCreationTime = filemtime($image); if ($fileCreationTime < ($currentTime - $retentionSeconds)) { if (!unlink($image)) { - log::add('mobile', 'error', 'Erreur lors de la suppression de: ' . $image); + log::add('mobile', 'error', __("Erreur lors de la suppression", __FILE__) . ' ─▶︎ ' . $image); } else { - log::add('mobile', 'debug', '| ─▶︎ :fg-danger:suppression image:/fg: > ' . $image); + log::add('mobile', 'debug', '| [WARNING] image removal ─▶︎ ' . $image); } } } @@ -954,7 +1572,7 @@ public function cleaningNotifications() if ($notifications) { $notifications = json_decode($notifications, true); if (json_last_error() !== JSON_ERROR_NONE) { - log::add('mobile', 'error', 'Erreur decodage du JSON : ' . json_last_error_msg()); + log::add('mobile', 'error', __("Erreur decodage du JSON", __FILE__) . ' ─▶︎ ' . json_last_error_msg()); return; } $notificationsModified = false; @@ -962,7 +1580,7 @@ public function cleaningNotifications() foreach ($notifications as $id => $value) { $notificationDate = strtotime($value['data']['date']); if (($currentTime - $notificationDate) > $retentionSeconds) { - log::add('mobile', 'debug', '| ─▶︎ :fg-danger:suppression notification:/fg: > N°' . $id); + log::add('mobile', 'debug', '| [WARNING] notification removal ─▶︎ N°' . $id); unset($notifications[$id]); $notificationsModified = true; } @@ -985,7 +1603,9 @@ public function postInsert() $key = config::genKey(32); $this->setLogicalId($key); } - $this->setConfiguration('defaultIdMobile', $this->getId()); + if ($this->getConfiguration('appVersion', 1) == 2) { + $this->setConfiguration('defaultIdMobile', $this->getId()); + } $this->save(); } @@ -994,15 +1614,36 @@ public function postInsert() */ public function postSave() { + $order = count($this->getCmd()); + + // Notification command + $cmd = $this->getCmd(null, 'notif'); + if (!is_object($cmd)) { + $cmd = new mobileCmd(); + $cmd->setIsVisible(1); + $cmd->setName(__('Notification', __FILE__)); + $cmd->setLogicalId('notif'); + $cmd->setGeneric_type('GENERIC_ACTION'); + $cmd->setDisplay('icon', ''); + $cmd->setDisplay('forceReturnLineAfter', 1); + $cmd->setDisplay('showIconAndNamedashboard', 1); + $cmd->setDisplay('showIconAndNamemobile', 1); + $cmd->setOrder($order); + $order++; + } + $cmd->setEqLogic_id($this->getId()); + $cmd->setType('action'); + $cmd->setSubType('message'); + if ($cmd->getChanged() === true) $cmd->save(); + if ($this->getConfiguration('appVersion', 1) == 2) { - $order = count($this->getCmd()); - // Commande notification - $cmd = $this->getCmd(null, 'notif'); + // Critical Notification Command + $cmd = $this->getCmd(null, 'notifCritical'); if (!is_object($cmd)) { $cmd = new mobileCmd(); $cmd->setIsVisible(1); - $cmd->setName(__('Notification', __FILE__)); - $cmd->setLogicalId('notif'); + $cmd->setName(__('Notification Critique', __FILE__)); + $cmd->setLogicalId('notifCritical'); $cmd->setGeneric_type('GENERIC_ACTION'); $cmd->setDisplay('icon', ''); $cmd->setDisplay('forceReturnLineAfter', 1); @@ -1016,22 +1657,8 @@ public function postSave() $cmd->setSubType('message'); if ($cmd->getChanged() === true) $cmd->save(); - // Commande notification Critique - $cmd = $this->getCmd(null, 'notifCritical'); - if (!is_object($cmd)) { - $cmd = new mobileCmd(); - $cmd->setIsVisible(1); - $cmd->setName(__('Notification Critique', __FILE__)); - $cmd->setLogicalId('notifCritical'); - $cmd->setGeneric_type('GENERIC_ACTION'); - $cmd->setDisplay('icon', ''); - $cmd->setDisplay('forceReturnLineAfter', 1); - $cmd->setDisplay('showIconAndNamedashboard', 1); - $cmd->setDisplay('showIconAndNamemobile', 1); - $cmd->setOrder($order); - $order++; - } - $cmd = $this->getCmd(null, 'notifSilent'); + // Silent notification command + $cmd = $this->getCmd(null, 'notifSilent'); if (!is_object($cmd)) { $cmd = new mobileCmd(); $cmd->setIsVisible(1); @@ -1050,7 +1677,7 @@ public function postSave() $cmd->setSubType('message'); if ($cmd->getChanged() === true) $cmd->save(); - // Commande récupération infos du téléphone + // command to retrieve specific information $cmd = $this->getCmd(null, 'notifSpecific'); if (!is_object($cmd)) { $cmd = new mobileCmd(); @@ -1070,7 +1697,7 @@ public function postSave() $cmd->setSubType('other'); if ($cmd->getChanged() === true) $cmd->save(); - // Commande suppression des nodifications + // Command to delete notifications $cmd = $this->getCmd(null, 'removeNotifs'); if (!is_object($cmd)) { $cmd = new mobileCmd(); @@ -1093,15 +1720,15 @@ public function postSave() if ($cmd->getChanged() === true) $cmd->save(); } - - - $cmdaskText = $this->getCmd(null, 'ask_Text'); - if (is_object($cmdaskText)) { - $cmdaskText->remove(); - } - $cmdaskYN = $this->getCmd(null, 'ask_YN'); - if (is_object($cmdaskYN)) { - $cmdaskYN->remove(); + if ($this->getConfiguration('appVersion', 1) != 2) { + $cmdaskText = $this->getCmd(null, 'ask_Text'); + if (is_object($cmdaskText)) { + $cmdaskText->remove(); + } + $cmdaskYN = $this->getCmd(null, 'ask_YN'); + if (is_object($cmdaskYN)) { + $cmdaskYN->remove(); + } } } @@ -1118,18 +1745,18 @@ public function preRemove() if ($mobile->getConfiguration('defaultIdMobile', 'none') == $Iq) { $mobile->setConfiguration('defaultIdMobile', $mobile->getId()); $mobile->save(); - log::add('mobile', 'debug', '| Modification du defaultIdMobile pour le mobile ' . $mobile->getHumanName(false) . ' ( ' . $mobile->getId() . ' ) '); + log::add('mobile', 'debug', '| Update defaultIdMobile for mobile ' . $mobile->getHumanName(false) . ' ( ' . $mobile->getId() . ' ) '); } } $fileNotif = dirname(__FILE__) . '/../data/notifications/' . $this->getLogicalId() . '.json'; if (file_exists($fileNotif)) { - log::add('mobile', 'debug', '| Suppression du fichier des notifications : ' . $fileNotif); + log::add('mobile', 'debug', '| Deleting notifications file ─▶︎ ' . $fileNotif); shell_exec('rm ' . $fileNotif); } /* App V1 */ $path = dirname(__FILE__) . '/../../data/' . $this->getLogicalId(); if (file_exists($path)) { - log::add('mobile', 'debug', '| Suppression du dossier : ' . $path); + log::add('mobile', 'debug', '| Deleting folder ─▶︎ ' . $path); shell_exec('rm -rf ' . $path); } log::add('mobile', 'debug', '└────────────────────'); @@ -1165,7 +1792,6 @@ public static function fileInMessage($data) $dataArray = explode('|', $data); $result = array(); foreach ($dataArray as $item) { - $arg = explode('=', trim($item), 2); if (count($arg) == 2) { $result[trim($arg[0])] = trim($arg[1]); @@ -1174,17 +1800,16 @@ public static function fileInMessage($data) $result['message'] = $dataArray[0]; $decodedMessage = json_decode($result['message']); if (json_last_error() === JSON_ERROR_NONE) { - log::add('mobile', 'DEBUG', '|| [INFO] Message : ' . $decodedMessage); + log::add('mobile', 'debug', '|| [INFO] Message ─▶︎ ' . $decodedMessage); } else { - log::add('mobile', 'DEBUG', '|| [INFO] Message : ' . $result['message']); + log::add('mobile', 'debug', '|| [INFO] Message ─▶︎ ' . str_replace(["\r", "\n"], "", $result['message'])); } if (array_key_exists('file', $result)) { - log::add('mobile', 'debug', '|| file > ' . $result['file']); + log::add('mobile', 'debug', '|| file ─▶︎ ' . $result['file']); log::add('mobile', 'debug', '|└────────────────────'); return $result; } else { log::add('mobile', 'debug', '|└────────────────────'); - //log::add('mobile', 'debug', '| null'); return null; } } @@ -1201,12 +1826,15 @@ public function execute($_options = array()) if ($this->getLogicalId() == 'removeNotifs') { $filePath = dirname(__FILE__) . '/../data/notifications/' . $Iq . '.json'; - if (!file_exists($filePath)) log::add('mobile', 'info', '| Fichier de notifications non trouvé : ' . $filePath); + if (!file_exists($filePath)) { + log::add('mobile', 'debug', '| ' . __('Fichier de notifications inexistant', __FILE__) . ' ─▶︎ ' . $filePath); + return; + } $valueUser = $_options['select']; switch ($valueUser) { case 1: file_put_contents($filePath, ''); - log::add('mobile', 'info', '| Suppression des notifications effectuée'); + log::add('mobile', 'debug', '| Deleting all notifications'); break; case 2: $notifs = json_decode(file_get_contents($filePath), true); @@ -1214,27 +1842,28 @@ public function execute($_options = array()) $askParams = json_decode($notif['data']['askParams'], true); $notifTime = strtotime($notif['data']['date']); $currentTime = time(); - $timeout = $askParams['timeout'] / 1000; + $timeout = (isset($askParams['timeout'])) ? $askParams['timeout'] / 1000 : 0; return $notif['data']['askVariable'] == 'rien' || ($currentTime - $notifTime) < $timeout; }); file_put_contents($filePath, json_encode($notifs)); - log::add('mobile', 'info', '| Suppression des asks expirés effectuée'); + log::add('mobile', 'debug', '| Deleting all ask expired'); break; case 3: $notifs = json_decode(file_get_contents($filePath), true); $notifs = array_filter($notifs, function ($notif) { - return $notif['data']['choiceAsk'] == ''; + return !isset($notif['data']['choiceAsk']) || $notif['data']['choiceAsk'] == ''; }); file_put_contents($filePath, json_encode($notifs)); - log::add('mobile', 'info', '| Suppression des asks répondus effectuée'); + log::add('mobile', 'debug', '| Deleting all ask answered'); break; } log::add('mobile', 'debug', '└────────────────────'); } - if ($this->getLogicalId() == 'notif' || $this->getLogicalId() == 'notifCritical' || $this->getLogicalId() == 'notifSpecific' || $this->getLogicalId() == 'notifSilent') { + $notificationArn = $eqLogic->getConfiguration('notificationArn', null); + $typeMobile = $eqLogic->getConfiguration('type_mobile', null); $critical = false; $silent = false; $specific = false; @@ -1258,41 +1887,35 @@ public function execute($_options = array()) $_options['message'] = $file['message']; log::add('mobile', 'debug', '| file detected ' . json_encode($file)); } - log::add('mobile', 'DEBUG', '| [INFO] Title : ' . $_options['title']); - log::add('mobile', 'DEBUG', '| [INFO] Message : ' . $_options['message']); - if ($eqLogic->getConfiguration('type_mobile') == 'android') $_options['message'] = nl2br($_options['message']); + log::add('mobile', 'DEBUG', '| [INFO] Title ─▶︎ ' . $_options['title']); + log::add('mobile', 'DEBUG', '| [INFO] Message ─▶︎ ' . str_replace(["\r", "\n"], "", $_options['message'])); + if ($typeMobile == 'android') $_options['message'] = nl2br($_options['message']); $answer = (isset($_options['answer']) && $_options['answer']) ? join(';', $_options['answer']) : null; $askVariable = isset($_options['variable']) ? $_options['variable'] : null; $askType = isset($_options['answer']) && $_options['answer'] ? 'ask_Text' : 'notif'; if ($askType == 'ask_Text') $_options['title'] = $defaultName; $timeout = isset($_options['timeout']) && $_options['timeout'] ? $_options['timeout'] : 'nok'; $optionsNotif['askVariable'] = $askVariable; - //log::add('mobile', 'debug', '|-----------------------------------'); - log::add('mobile', 'debug', '| Commande de notification : ' . $askType); - if (($eqLogic->getConfiguration('notificationArn', null) != null || $eqLogic->getConfiguration('notificationRegistrationToken', null) != null) && $eqLogic->getConfiguration('type_mobile', null) != null) { + log::add('mobile', 'debug', '| Notification command ─▶︎ ' . $askType); + if (($notificationArn != null || $eqLogic->getConfiguration('notificationRegistrationToken', null) != null) && $typeMobile != null) { $idNotif = $eqLogic->getConfiguration('idNotif', 0); $idNotif = $idNotif + 1; $eqLogic->setConfiguration('idNotif', $idNotif); $eqLogic->save(); - - log::add('mobile', 'debug', '| [INFO] Notif > ' . json_encode($_options)); - log::add('mobile', 'debug', '| eqLogic > ' . $eqLogic->getId() . ' | LogicalId > ' . $this->getLogicalId() . ' | idNotif > ' . $idNotif); + log::add('mobile', 'debug', '| [INFO] Notif ─▶︎ ' . json_encode($_options)); + log::add('mobile', 'debug', '| eqLogic ─▶︎ ' . $eqLogic->getId() . ' | LogicalId ─▶︎ ' . $this->getLogicalId() . ' | idNotif ─▶︎ ' . $idNotif); if (isset($options['file'])) { - //log::add('mobile', 'debug', '| [NOTICE] FILE'); - //unset($data['file']); $_options['files'] = explode(',', $options['file']); } if (isset($_options['files']) && is_array($_options['files'])) { - log::add('mobile', 'debug', '| [NOTICE] FILE'); + log::add('mobile', 'debug', '| file detected'); foreach ($_options['files'] as $file) { - log::add('mobile', 'debug', '| FILES as FILE'); - if (trim($file) == '') { - continue; - } + if (trim($file) == '') continue; $ext = pathinfo($file, PATHINFO_EXTENSION); - log::add('mobile', 'debug', '| ' . $ext . ' pour > ' . $file); + $url = null; + log::add('mobile', 'debug', '| ' . $file); if (in_array($ext, array('gif', 'jpeg', 'jpg', 'png'))) { - log::add('mobile', 'debug', '| type photo !'); + log::add('mobile', 'debug', '| ↳ type photo !'); if ($ext == "gif") { $typeHint = "com.compuserve.gif"; } else if ($ext == "jpeg") { @@ -1305,31 +1928,29 @@ public function execute($_options = array()) $typeHint = "public.jpeg"; } $optionsNotif['typeHint'] = $typeHint; - $url = network::getNetworkAccess('external'); - $url .= '/plugins/mobile/core/php/image.php?'; $nameFile = $Iq . '__' . base64_encode($file) . '.' . $ext; $path = dirname(__FILE__) . '/../../data/images'; $newfile = $path . '/' . $nameFile; - log::add('mobile', 'debug', '| copie sur > ' . $newfile); + log::add('mobile', 'debug', '| ↳ copy on ─▶︎ ' . $newfile); if (!file_exists($path)) { mkdir($path); } if (!copy($file, $newfile)) { - log::add('mobile', 'error', 'la copie de l\'image a echoué'); + log::add('mobile', 'error', __("la copie de l\'image a échouée", __FILE__)); + } else { + $keyFile = md5_file($newfile); + $url = network::getNetworkAccess('external') . '/plugins/mobile/core/php/image.php?key=' . $keyFile . '&name=' . $nameFile; + log::add('mobile', 'debug', '| ↳ url ─▶︎ ' . $url); } - $keyFile = md5_file($newfile); - $url .= 'key=' . $keyFile . '&name=' . $nameFile; - log::add('mobile', 'debug', '| url > ' . $url); - mobile::notification($eqLogic->getConfiguration('notificationArn', null), $eqLogic->getConfiguration('type_mobile', null), $_options['title'], $_options['message'], $askType, $idNotif, $answer, $timeout, $eqLogic->getConfiguration('notificationRegistrationToken', null), $url, $eqLogic->getConfiguration('appVersion', 1), $optionsNotif, $critical, $eqLogic->getLogicalId(), $specific, $silent); - } else { - mobile::notification($eqLogic->getConfiguration('notificationArn', null), $eqLogic->getConfiguration('type_mobile', null), $_options['title'], $_options['message'], $askType, $idNotif, $answer, $timeout, $eqLogic->getConfiguration('notificationRegistrationToken', null), null, $eqLogic->getConfiguration('appVersion', 1), $optionsNotif, $critical, $eqLogic->getLogicalId(), $specific, $silent); } + mobile::notification($notificationArn, $typeMobile, $_options['title'], $_options['message'], $askType, $idNotif, $answer, $timeout, $eqLogic->getConfiguration('notificationRegistrationToken', null), $url, $eqLogic->getConfiguration('appVersion', 1), $optionsNotif, $critical, $Iq, $specific, $silent); } } else { - mobile::notification($eqLogic->getConfiguration('notificationArn', null), $eqLogic->getConfiguration('type_mobile', null), $_options['title'], $_options['message'], $askType, $idNotif, $answer, $timeout, $eqLogic->getConfiguration('notificationRegistrationToken', null), null, $eqLogic->getConfiguration('appVersion', 1), $optionsNotif, $critical, $eqLogic->getLogicalId(), $specific, $silent); + mobile::notification($notificationArn, $typeMobile, $_options['title'], $_options['message'], $askType, $idNotif, $answer, $timeout, $eqLogic->getConfiguration('notificationRegistrationToken', null), null, $eqLogic->getConfiguration('appVersion', 1), $optionsNotif, $critical, $Iq, $specific, $silent); } } else { - log::add('mobile', 'debug', '| [ERROR] ARN non configuré '); + if ($typeMobile == null) log::add('mobile', 'debug', '| [ERROR] Mobile type not configured'); + else log::add('mobile', 'debug', '| [ERROR] ARN not configured'); } log::add('mobile', 'debug', '└────────────────────'); } diff --git a/core/template/mobile/cmd.info.numeric.arcSlider.html b/core/template/mobile/cmd.info.numeric.arcSlider.html index 404d502d..750c1a11 100644 --- a/core/template/mobile/cmd.info.numeric.arcSlider.html +++ b/core/template/mobile/cmd.info.numeric.arcSlider.html @@ -40,7 +40,7 @@ .css("transform", "scale(0.94) rotate(" + angle + "deg)"); cmd.find(".state strong").first().text(_options.display_value); }); - + if (is_numeric("#state#")) { jeedom.cmd.refreshValue([ { diff --git a/desktop/css/notification.css b/desktop/css/notification.css new file mode 100644 index 00000000..75786447 --- /dev/null +++ b/desktop/css/notification.css @@ -0,0 +1,129 @@ +.notification-box { + padding: 32px; +} + +.notification-step { + display: flex; + margin-bottom: 32px; + position: relative; +} + +.notification-step:last-child { + margin-bottom: 0px; +} + +.notification-line { + position: absolute; + left: 114px; + top: 40px; + bottom: -32px; + width: 2px; + background-color: var(--logo-primary-color); + z-index: 1; +} + +.notification-date { + display: flex; + height: 40px; + align-items: center; + margin-right: 16px; + width: 79px; + font-size: 12px; + padding: 5px; + text-align: center; + border-radius: var(--border-radius) var(--border-radius) var(--border-radius) var(--border-radius) !important; + background-color: var(--form-bg-color); + /* z-index: 1;*/ +} + +.notification-step:last-child .notification-line { + display: none; +} + +.notification-circle { + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 16px; + background-color: var(--form-bg-color); + border: 2px solid var(--txt-color); + z-index: 2; +} + +.ask-timeout .notification-circle { + color: var(--linkHoverLight-color) !important; + background-color: var(--al-info-color) !important; + border: none; +} + +.ask-success .notification-circle { + color: var(--linkHoverLight-color) !important; + background-color: var(--al-success-color) !important; + border: none; +} + +.ask-in-progress .notification-circle { + color: var(--linkHoverLight-color) !important; + background-color: var(--al-warning-color) !important; + border: none; +} + +.stepper-critical .notification-circle { + border: 1px solid red; +} + +.notification-content { + flex: 1; + padding: 10px; + border-radius: var(--border-radius) var(--border-radius) var(--border-radius) var(--border-radius); + background-color: var(--form-bg-color); +} + +.notification-img { + margin-top: 10px; +} + +.notification-img img { + max-width: 250px; +} + +.notification-title { + font-weight: 600; + margin-bottom: 4px; + font-size: 18px; +} + +.notification-status { + font-size: 13px; + display: inline-block; + padding: 2px 8px; + border-radius: 12px; + margin-top: 4px; +} + +.ask-success .notification-status { + color: var(--linkHoverLight-color) !important; + background-color: var(--al-success-color) !important; + border: none; +} + +.ask-timeout .notification-status { + color: var(--linkHoverLight-color) !important; + background-color: var(--al-info-color) !important; + border: none; +} + +.ask-in-progress .notification-status { + color: var(--linkHoverLight-color) !important; + background-color: var(--al-warning-color) !important; + border: none; +} + +.notification-button { + display: flex; + margin-bottom: 32px; + justify-content: end; +} \ No newline at end of file diff --git a/desktop/css/wizard.css b/desktop/css/wizard.css new file mode 100644 index 00000000..13612994 --- /dev/null +++ b/desktop/css/wizard.css @@ -0,0 +1,372 @@ +body { + padding-top: unset; +} + +#jeedomMenuBar { + display: none; +} + +#div_mainContainer { + display: flex; + justify-content: center; + align-items: center; +} + +#div_pageContainer { + background-color: rgba(var(--eq-bg-color), var(--opacity)); + border-radius: var(--border-radius); +} + +#mobile_wizard .flex-evenly { + width: 100%; + height: 100%; + display: flex; + justify-content: space-evenly; + align-items: center; +} + +#mobile_wizard .flex-column { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +#bt_quitmobile { + position: absolute; + top: 5%; + right: 5%; +} + +/* #wizard_container { + height: 600px; + display: grid; + justify-items: center; + align-items: center; + grid-template-columns: 100%; + grid-template-rows: 50px 225px 0 25px auto; +} */ + +#wizard_container { + height: 600px; + display: flex; + flex-direction: column; + justify-items: center; + align-items: center; +} + + +#wizard_container>h3 { + grid-row-start: 1 +} + +#wizard_container>img { + max-width: 350px; + max-height: 500px; + grid-row-start: 2 +} + +#wizard_container>.logo { + grid-row-start: 2 +} + +#wizard_container .input-group { + max-width: 450px; + margin: auto; +} + +#wizard_container .form-control { + font-weight: bold; + text-align-last: center; +} + +.bold { + font-weight: bold; +} + +/*** OBJECTS ***/ +#wizard_container>.step_father .sel_father, +#wizard_container>.step_childs .sel_child { + border-radius: var(--border-radius); + background-color: var(--el-defaultColor); + overflow: hidden; +} + +#wizard_container>.step_father .sel_father:hover, +#wizard_container>.step_father .sel_father.selected { + transform: scale(1.2); +} + +#wizard_container>.step_childs .sel_child { + opacity: .25; +} + +#wizard_container>.step_childs .sel_child:hover { + opacity: 1; +} + +#wizard_container>.step_childs .sel_child.selected { + opacity: 1; + border: solid 3px var(--logo-primary-color); +} + +#wizard_container>.step_father img { + width: 250px; + max-width: 100%; + max-height: 150px; +} + +#wizard_container>.step_childs .panel { + width: 100%; + max-width: 1000px; +} + +#wizard_container>.step_childs .panel-body { + padding: 12px 0 10px 10px; +} + +#wizard_container>.step_childs img { + width: 180px; + max-width: 100%; + max-height: 100px; +} + +#wizard_container>.step_father .object_name, +#wizard_container>.step_childs .object_name { + font-weight: bold; + color: white; + padding: 2px; + background-color: var(--al-info-color); +} + +/*** PLUGINS ***/ +#wizard_container>#plugins { + min-height: 250px; +} + +#wizard_container>#plugins>.plugin { + max-height: 50%; + min-width: 10%; + opacity: .5; + border: solid 3px var(--linkHover-color); + border-radius: var(--border-radius); + padding: 6px 0; +} + +#wizard_container>#plugins>.plugin:hover { + opacity: 1; +} + +#wizard_container>#plugins>.plugin.selected { + opacity: 1; + border: solid 3px var(--logo-primary-color); +} + +#wizard_container>#plugins>.plugin.selected[data-installed="true"] { + border: solid 3px var(--al-info-color); +} + +#wizard_container>#plugins>.plugin>img { + max-height: 95px; + max-width: 85%; +} + +/*** NAVIGATION ***/ +#wizard_navigation { + margin: 15px auto; +} + +#wizard_navigation>div { + margin: auto 10px; + min-width: 50px; +} + +.navBtn, +#bt_jeedom_ready { + font-size: 45px; + cursor: pointer !important; + color: #F18D15; +} + +.navDot { + width: 25px; + height: 25px; + margin: 5px; + border-radius: 50%; + display: inline-flex; + align-items: center; + justify-content: center; + color: white; + background-color: rgb(var(--contrast-color), .7); + user-select: none; +} + +.navDot:hover, +.navDot.active { + transform: scale(1.5); +} + +.navDot.active { + margin: 0 10px; +} + +.navDot.blocked { + opacity: .5; +} + + + +/* + +@media (max-width: 768px) { + #wizard_container { + height: auto; + grid-template-rows: auto auto auto auto auto; + padding: 10px; + } + + #wizard_container>img { + max-width: 250px; + max-height: 150px; + } + + #wizard_navigation { + flex-direction: row; + justify-content: center; + position: fixed; + bottom: 10px; + width: 100%; + padding-bottom: 10px; + background-color: rgba(var(--panel-bg-color), 0.9); + } + + #wizard_navigation>div { + margin: 0 5px; + } + + .navBtn, + #bt_jeedom_ready { + font-size: 30px; + } + + .navDot { + width: 20px; + height: 20px; + margin: 3px; + } + + .navDot:hover, + .navDot.active { + transform: scale(1.2); + } + + #wizard_container>#updates>.update, + #wizard_container>#plugins>.plugin { + width: 70px; + height: auto; + } + + #wizard_container>#updates>.update>img, + #wizard_container>#plugins>.plugin>img { + width: 60px; + } + + #wizard_container>.services .service { + height: 150px; + max-width: 100%; + } +} */ + + + +/* TABLETS (portrait) */ +@media (max-width: 1024px) { + #div_mainContainer { + flex-direction: column; + padding: 10px; + } + + #wizard_container { + height: auto; + grid-template-rows: auto auto auto auto auto; + } + + #wizard_container>img, + #wizard_container>.logo { + max-width: 250px; + max-height: 180px; + } + + #wizard_container .input-group { + width: 90%; + } + + #wizard_container>#plugins>.plugin { + max-height: 120px; + min-width: 25%; + } +} + +/* PHONES */ +@media (max-width: 768px) { + #wizard_container .input-group { + width: 100%; + flex-direction: column; + align-items: stretch; + } + + #wizard_container .input-group label { + display: block; + margin-bottom: 5px; + width: 100%; + text-align: left; + font-size: 14px; + } + + #wizard_container .input-group select, + #wizard_container .input-group input, + #wizard_container .form-control { + width: 100%; + box-sizing: border-box; + } + #bt_quitJeeasyWizard { + top: 10px; + right: 10px; + } + + #wizard_container { + padding: 10px; + grid-template-rows: auto auto auto auto auto; + text-align: center; + } + + #wizard_container>img, + #wizard_container>.logo { + max-width: 200px; + max-height: 150px; + } + + #wizard_container .form-control { + font-size: 16px; + } + + #wizard_container>#plugins>.plugin { + min-width: 40%; + margin-bottom: 10px; + } + + .navBtn, + #bt_jeedom_ready { + font-size: 30px; + } + + .navDot { + width: 18px; + height: 18px; + margin: 3px; + } +} + + + diff --git a/desktop/js/mobile.js b/desktop/js/mobile.js index 3dfa1d0b..5861fb3f 100755 --- a/desktop/js/mobile.js +++ b/desktop/js/mobile.js @@ -14,13 +14,7 @@ * along with Jeedom. If not, see . */ -document.querySelector("#info_app")?.addEventListener("click", function (event) { - jeeDialog.dialog({ - id: "infosApp", - title: "{{Informations envoyées à l'app}}", - contentUrl: "index.php?v=d&plugin=mobile&modal=info_app.mobile" - }) -}) +// AppV2 \\\ document.querySelector("#bt_handlePhones")?.addEventListener("click", function (event) { jeeDialog.dialog({ @@ -39,30 +33,259 @@ document.querySelector("#bt_qrCodev2")?.addEventListener("click", function (even }) }) -function printEqLogic(_eqLogic) { +document.querySelector("#bt_doc")?.addEventListener("click", function (event) { + jeedomUtils.loadPage('index.php?v=d&m=mobile&p=wizard') +}); + +// AppV1 \\ + +document.querySelector("#info_app")?.addEventListener("click", function (event) { + jeeDialog.dialog({ + id: "infosApp", + title: "{{Informations envoyées - Application V1}}", + contentUrl: "index.php?v=d&plugin=mobile&modal=AppV1Info" + }) +}) + +document.querySelector("#bt_pluginmobile")?.addEventListener("click", function (event) { + jeeDialog.dialog({ + id: "pluginsCompatibles", + title: "{{Plugins compatibles - Application V1}}", + contentUrl: "index.php?v=d&plugin=mobile&modal=AppV1Plugin", + }); +}); + +document.querySelector("#bt_piecemobile")?.addEventListener("click", function (event) { + jeeDialog.dialog({ + id: "objectsModal", + title: "{{Objets / Pièces - Application V1}}", + contentUrl: "index.php?v=d&plugin=mobile&modal=AppV1Piece", + }); +}); + +document.querySelector("#bt_scenariomobile")?.addEventListener("click", function (event) { + jeeDialog.dialog({ + id: "scenariosModal", + title: "{{Scénarios - Application V1}}", + contentUrl: "index.php?v=d&plugin=mobile&modal=AppV1Scenario", + }); +}); + +document.querySelector("#bt_regenConfig")?.addEventListener("click", function (event) { domUtils.ajax({ type: "POST", url: "plugins/mobile/core/ajax/mobile.ajax.php", data: { - action: "getAffectUserByEqlogic", - id: _eqLogic.id, + action: "AppV1RegenConfig", }, dataType: "json", - global: false, error: function (request, status, error) { - domUtils.handleAjaxError(request, status, error) + domUtils.handleAjaxError(request, status, error) }, success: function (data) { if (data.state != "ok") { jeedomUtils.showAlert({ message: data.result, level: "danger" }) return } - let el = document.querySelector(".affect_user") - if (el != null) { - el.innerHTML = data.result + jeedomUtils.showAlert({ message: "{{Configuration mise à jour}}", level: "success"}); + }, + }); +}); + +// NotificationsV2 +document.querySelector(".notification-box")?.addEventListener("click", function (event) { + var _target = null + if (_target = event.target.closest('.bt_removeNotification')) { + let notification = _target.closest('.notification-step') + let id = notification.getAttribute('data-id'); + let iq = notification.getAttribute('data-iq'); + domUtils.ajax({ + type: "POST", + url: "plugins/mobile/core/ajax/mobile.ajax.php", + data: { + action: "removeNotificationV2", + id: id, + iq: iq + }, + dataType: "json", + error: function (request, status, error) { + domUtils.handleAjaxError(request, status, error) + }, + success: function (data) { + if (data.state != "ok") { + jeedomUtils.showAlert({ message: data.result, level: "danger" }) + return + } + notification.remove() + if (data.result == '0' && is_object(el = document.querySelector(".notification-box"))) { + el.innerHTML = '
{{Aucune notifications}}
' + } + jeedomUtils.showAlert({ message: "{{Notification supprimées.}}", level: "success"}); + }, + }); + return + } + + if (_target = event.target.closest('.bt_refreshNotifications')) { + let iq = _target.getAttribute('data-iq') + printNotification(iq) + jeedomUtils.showAlert({ message: "{{Terminé.}}", level: "success"}); + return + } +}); + +// Copie pour monitoring +var toCopy = document.getElementById("to-copy-monitoring"); +var arnComplet = document.getElementById("arnComplet"); +document.getElementById("copy-monitoring")?.addEventListener("click", function () { + if (arnComplet.jeeValue() != '') { + var fichier = arnComplet.jeeValue(); + var fichierCouper = fichier.substr(44); + toCopy.value = fichierCouper; + toCopy.select(); + document.execCommand("copy"); + return false; + } +}); +///////////////// + + +function printEqLogic(_eqLogic) { + let appVersion = _eqLogic.configuration.appVersion; + if (appVersion == 2) { + document.querySelectorAll(".paramV1").unseen() + document.querySelectorAll(".paramV2").seen() + printNotification(_eqLogic.logicalId) + } else { + document.querySelectorAll(".paramV2").unseen() + document.querySelectorAll(".paramV1").seen() + let el = document.querySelector(".notification-box"); + el.innerHTML = '
Compatible AppV2 uniquement.
' + } + + // AppV1 + if (appVersion != 2) { + domUtils.ajax({ + type: "POST", + url: "plugins/mobile/core/ajax/mobile.ajax.php", + data: { + action: "getQrCode", + id: _eqLogic.id, + }, + dataType: "json", + global: false, + error: function (request, status, error) { + domUtils.handleAjaxError(request, status, error) + }, + success: function (data) { + if (data.state != "ok") { + jeedomUtils.showAlert({ message: data.result, level: "danger" }) + return + } + let el = document.querySelector(".qrCodeImg"); + el.innerHTML = ""; + if (data.result == "internalError") { + el.innerHTML = "{{Erreur pas d'adresse interne (voir configuration de votre Jeedom !)}}"; + } else if (data.result == "externalError") { + el.innerHTML = "{{Erreur pas d'adresse externe (voir configuration de votre Jeedom !)}}"; + } else if (data.result == "UserError") { + el.innerHTML = "{{Erreur pas d'utilisateur selectionné}}"; + } else { + el.innerHTML = ''; + } + }, + }); + + domUtils.ajax({ + type: "POST", + url: "plugins/mobile/core/ajax/mobile.ajax.php", + data: { + action: "AppV2GetSaveFavDash", + iq: _eqLogic.logicalId, + }, + dataType: "json", + global: false, + error: function (request, status, error) { + domUtils.handleAjaxError(request, status, error) + }, + success: function (data) { + if (data.state != "ok") { + jeedomUtils.showAlert({ message: data.result, level: "danger" }) + return + } + let saveFav = document.querySelector("#SaveFav") + if (is_object(saveFav)) { + if (data.result == true) { + saveFav.removeClass('label-warning', 'label-danger').addClass('label-success') + saveFav.innerHTML = "OK" + } else if (data.result == false) { + saveFav.removeClass('label-success', 'label-warning').addClass('label-danger') + saveFav.innerHTML = "NOK" + } + } } - } - }) + }); + + domUtils.ajax({ + type: "POST", + url: "plugins/mobile/core/ajax/mobile.ajax.php", + data: { + action: "AppV2GetSaveDashboard", + iq: _eqLogic.logicalId, + }, + dataType: "json", + global: false, + error: function (request, status, error) { + domUtils.handleAjaxError(request, status, error) + }, + success: function (data) { + if (data.state != "ok") { + jeedomUtils.showAlert({ message: data.result, level: "danger" }) + return + } + let savedash = document.querySelector("#SaveDash"); + if (is_object(savedash)) { + if (data.result == true) { + savedash.removeClass('label-warning', 'label-danger').addClass('label-success') + savedash.innerHTML = "OK"; + } else if (data.result == false) { + savedash.removeClass('label-success', 'label-warning').addClass('label-danger') + savedash.innerHTML = "NOK"; + } + } + }, + }); + + document.getElementById("copy-monitoring")?.click() + } + + /// if delete code AppV1 in mobile.php into Paramètres spécifiques -> + /// change by + let el_type = document.querySelector(".type_mobile") + let select_type = document.querySelector('.eqLogicAttr[data-l1key="configuration"][data-l2key="type_mobile"]') + let value_type = '' + if (is_object(select_type)) { + value_type = select_type.options[select_type.selectedIndex]?.text || 'INCONNU' + } + if (is_object(el_type)) { + el_type.innerHTML = value_type + if (value_type == 'INCONNU') el_type.removeClass('label-primary').addClass('label-danger') + else el_type.removeClass('label-danger').addClass('label-primary') + } + + /// if delete code AppV1 in mobile.php into Paramètres spécifiques -> + /// change by + let el_affect_user = document.querySelector(".affect_user") + let select_affect_user = document.querySelector('.eqLogicAttr[data-l1key="configuration"][data-l2key="affect_user"]') + let value_affect_user = '' + if (is_object(select_affect_user)) { + value_affect_user = select_affect_user.options[select_affect_user.selectedIndex]?.text || 'INCONNU' + } + if (is_object(el_affect_user)) { + el_affect_user.innerHTML = value_affect_user + if (value_affect_user == 'INCONNU' || value_affect_user == 'Aucun') el_affect_user.removeClass('label-primary').addClass('label-danger') + else el_affect_user.removeClass('label-danger').addClass('label-primary') + } } function addCmdToTable(_cmd) { @@ -106,7 +329,7 @@ function addCmdToTable(_cmd) { } tr += "" tr += "" - if (init(_cmd.logicalId) !== "notif" && init(_cmd.logicalId) !== "notifCritical") { + if (init(_cmd.logicalId) !== "notif" && init(_cmd.logicalId) !== "notifCritical" && init(_cmd.logicalId) !== "notifSilent") { tr += '' } tr += "" @@ -128,3 +351,288 @@ function addCmdToTable(_cmd) { } }) } + +function printNotification(_iq) { + domUtils.ajax({ + type: "POST", + url: "plugins/mobile/core/ajax/mobile.ajax.php", + data: { + action: "getNotificationsV2", + iq: _iq, + }, + dataType: "json", + global: false, + error: function (request, status, error) { + domUtils.handleAjaxError(request, status, error) + }, + success: function (data) { + if (data.state != "ok") { + jeedomUtils.showAlert({ message: data.result, level: "danger" }) + return + } + + let el = document.querySelector(".notification-box"); + + try { + var objectData = JSON.parse(data.result); + } catch { + el.innerHTML = '
' + data.result + '
' + return + } + + if (typeof objectData == "object") { + let notification = '' + notification += '
Rafraichir
' + moment.locale(jeeFrontEnd.language.substring(0, 2)) + for (var i in objectData) { + // ASK + let askStatus = '' + let askChoice = '' + if (isset(objectData[i].data.choiceAsk)) { + askStatus = 'ask-success' + askChoice = objectData[i].data.choiceAsk + } else if (objectData[i].data.askVariable != 'rien') { + let notifTime = moment(objectData[i].data.date, "YYYY-MM-DD hh:mm:ss").unix() + let currentTime = moment().unix() + try { + let askParams = (isset(objectData[i].data.askParams)) ? JSON.parse(objectData[i].data.askParams) : '' + if (isset(askParams.timeout)) { + let timeout = askParams.timeout / 1000 + if ((currentTime - notifTime) > timeout) { + askStatus = 'ask-timeout' + askChoice = '{{Timeout}}' + } else { + askStatus += 'ask-in-progress' + askChoice = '{{En cours...}}' + } + } + } catch { } + } + + notification += '
' + notification += '
' + objectData[i].data.date + '
' + if (objectData[i].data.askVariable != 'rien') { + notification += '
ASK
' + } else if (objectData[i].data.critical == 'true') { + notification += '
N
' + } else if (objectData[i].data.silent == 'true') { + notification += '
NS
' + } else { + notification += '
N
' + } + notification += '
' + notification += '
' + //notification += ' {{Supprimer}}' + notification += '' + notification += '
' + objectData[i].data.title + '
' + notification += '
' + objectData[i].data.body + '
' + if (isset(objectData[i].data.image)) { + notification += '
' + } + if (askChoice != '') notification += '
' + askChoice + '
' + notification += '
' + notification += '
' + //console.log(objectData[i]) + } + el.innerHTML = notification + jeedomUtils.initTooltips(el) + } + }, + }); + +} + +// WIZARD + +var _contentContainer = document.getElementById('wizard_container'); +var currentStep = getUrlVars('step'); + +if (!currentStep) { + currentStep = localStorage.getItem('wizardStep') || document.querySelector('.navDot')?.dataset.step; +} +document.querySelector('.navDot[data-step="' + currentStep + '"]')?.classList.add('active'); +if (window.updateQuitButtonVisibility) window.updateQuitButtonVisibility(); +loadStep(currentStep); + +var slideOut = { + opacity: [1, 0], + transform: ['translateX(0)', 'translateX(-10%)'] +} +var slideIn = { + opacity: [0, 1], + transform: ['translateX(10%)', 'translateX(0)'] +} +var slideOutReverse = { + opacity: [1, 0], + transform: ['translateX(0)', 'translateX(10%)'] +} +var slideInReverse = { + opacity: [0, 1], + transform: ['translateX(-10%)', 'translateX(0)'] +} + +document.querySelectorAll('.navDot').forEach(_dot => { + _dot.addEventListener('click', function() { + let current = document.querySelector('.navDot.active') + + if (this == current || this.classList.contains('blocked')) { + return false + } + if (current.nextElementSibling?.classList.contains('blocked')) { + allowNavigation() + } + + let outAnimation = slideOut + let inAnimation = slideIn + if (Number(this.innerText) < Number(current.innerText)) { + outAnimation = slideOutReverse + inAnimation = slideInReverse + } + + _contentContainer.animate(outAnimation, { + duration: 500 + }) + setTimeout(() => { + document.querySelector('.navDot.active').classList.remove('active') + this.classList.add('active') + _contentContainer.empty() + localStorage.setItem('wizardStep', this.dataset.step); + loadStep(this.dataset.step) + _contentContainer.animate(inAnimation, { + duration: 500 + }) + if (window.updateQuitButtonVisibility) window.updateQuitButtonVisibility(); + }, 450) + }) +}) + +document.querySelectorAll('.navBtn').forEach(_navBtn => { + _navBtn.addEventListener('click', function() { + let activeNavDot = document.querySelector('.navDot.active') + if (this.classList.value.includes('bt_next')) { + activeNavDot.nextElementSibling.triggerEvent('click') + } else if (this.classList.value.includes('bt_prev')) { + activeNavDot.previousElementSibling.triggerEvent('click') + } + }) +}) + + +var quitBtn = document.getElementById('bt_quitmobileWizard'); +if (quitBtn) { + quitBtn.addEventListener('click', function() { + let confirm + confirm = "{{Voulez-vous vraiment fermer la documentation ?}}" + confirm += '

' + + bootbox.confirm(confirm, function(result) { + if (result) { + exitWizard() + } + }) + }) +} + +var readyBtn = document.getElementById('bt_jeedom_ready'); +if (readyBtn) { + readyBtn.addEventListener('click', function() { + exitWizard() + }) +} + +function loadStep(_step) { + updateNavigation(_step); + updateContent('index.php?v=d&plugin=mobile&modal=' + _step); +} + +function updateContent(_url) { + if (!_contentContainer) return; + _contentContainer.style.visibility = 'hidden'; + fetch(_url) + .then(response => response.text()) + .then(data => { + if (!_contentContainer) return; + _contentContainer.innerHTML = data; + + _contentContainer.querySelectorAll('script').forEach(_script => { + let newScript = document.createElement('script'); + if (_script.src) { + newScript.src = _script.src; + } else { + newScript.textContent = _script.textContent; + } + _contentContainer.appendChild(newScript); + _contentContainer.removeChild(newScript); + }); + + _contentContainer.style.visibility = 'visible'; + jeedomUtils.initTooltips(_contentContainer); + const stepOrder = Array.from(document.querySelectorAll('.navDot')).map(dot => dot.dataset.step); + }) + .catch(error => { + console.error('{{Erreur au chargement de la page}}:', error); + domUtils.hideLoading(); + if (_contentContainer) { + _contentContainer.style.visibility = 'visible'; + } + }); +} + + + +function updateNavigation(_step) { + let current = document.querySelector('.navDot[data-step="' + _step + '"]'); + if (!current) { + return; + } + document.querySelector('.navBtn.bt_next').dataset.step = _step + if (!current.previousElementSibling) { + document.querySelector('.navBtn.bt_prev')?.classList.add('hidden') + } else { + document.querySelector('.navBtn.bt_prev').title = current.previousElementSibling.dataset.title + document.querySelector('.navBtn.bt_prev.hidden')?.classList.remove('hidden') + } + if (!current.nextElementSibling) { + document.querySelector('.navBtn.bt_next')?.classList.add('hidden') + if (_step == 'ready') { + document.getElementById('bt_jeedom_ready')?.classList.remove('hidden') + } + } else { + document.getElementById('bt_jeedom_ready')?.classList.add('hidden') + document.querySelector('.navBtn.bt_next').title = current.nextElementSibling.dataset.title + document.querySelector('.navBtn.bt_next.hidden')?.classList.remove('hidden') + } + jeedomUtils.addOrUpdateUrl('step', _step); + localStorage.setItem('wizardStep', _step); + if (window.updateQuitButtonVisibility) window.updateQuitButtonVisibility(); +} + +function allowNavigation(_direction = 'both', _allowed = true) { + let current = document.querySelector('.navDot.active'); + if (_direction != 'next') { + let prevDot = current.previousElementSibling; + while (prevDot) { + if (!_allowed) { + prevDot.classList.add('blocked'); + } else { + prevDot.classList.remove('blocked'); + } + prevDot = prevDot.previousElementSibling; + } + } + if (_direction != 'prev') { + let nextDot = current.nextElementSibling; + while (nextDot) { + if (!_allowed) { + nextDot.classList.add('blocked'); + } else { + nextDot.classList.remove('blocked'); + } + nextDot = nextDot.nextElementSibling; + } + } +} + +function exitWizard() { + window.location.href = 'index.php?v=d&m=mobile&p=mobile'; +} diff --git a/desktop/modal/AppV1Info.php b/desktop/modal/AppV1Info.php new file mode 100644 index 00000000..d58f00b6 --- /dev/null +++ b/desktop/modal/AppV1Info.php @@ -0,0 +1,68 @@ +. + */ +if (!isConnect('admin')) { + throw new Exception('{{401 - Accès non autorisé}}'); +} +mobile::makeTemplateJson(); +$data = mobile::getTemplateJson(); +$data['messages'] = mobile::discovery_message(); +$data['config'] = array('datetime' => getmicrotime()); +$replace = array(' '\<\i'); +?> +{{JSON valide}} () + + + + +
+
+

+		
+
+
+

+		
+
+
+

+		
+
+
+

+		
+
+
+

+		
+
+
+

+		
+
+
+

+	
+
+
\ No newline at end of file diff --git a/desktop/modal/AppV1Object.mobile.php b/desktop/modal/AppV1Object.mobile.php new file mode 100644 index 00000000..75b7e4b5 --- /dev/null +++ b/desktop/modal/AppV1Object.mobile.php @@ -0,0 +1,277 @@ +. + */ + +ini_set('display_errors', 0); +if (!isConnect('admin')) { + throw new Exception('{{401 - Accès non autorisé}}'); +} + +$object = jeeObject::byId($_GET['object_id']); +sendVarToJS('object', $_GET['object_id']); +?> + + +
+'; +echo '{{Envoyer cette pièce vers l\'application}}'; +$check = 'checked'; +if ($object->getDisplay('sendToApp', 1) == 0) { + $check = 'unchecked'; +} +echo ''; +?> + + + +
+ {{Type Générique de cet objet}} + {{Sauvegarder}} + + +
+ getEqLogic(); + $checkHomebridge = ''; + echo '
'; + foreach ($eqLogics as $eqLogic) { + echo '
'; + echo ' '; + echo '
'; + echo '
'; + $cmds = null; + $cmds = cmd::byEqLogicId($eqLogic->getId()); + echo ''; + echo ' + + + + '; + foreach ($cmds as $cmd) { + array_push($tableau_cmd, $cmd->getId()); + echo ''; + echo ''; + echo ''; + echo ''; + } + echo '
{{Id Cmd}}{{Nom de la Commande}}{{Type Générique}}
'; + echo '' . $cmd->getId() . ''; + echo ''; + echo $cmd->getName(); + $display_icon = 'none'; + $icon = ''; + if (in_array($cmd->getGeneric_type(), ['GENERIC_INFO', 'GENERIC_ACTION'])) { + $display_icon = 'block'; + $icon = $cmd->getDisplay('icon'); + } + echo '
+
+ ' . $icon . ' + {{Icône}} +
+
'; + echo '
'; + ?> + + '; + echo '
'; + echo '
'; + echo '
'; + echo '
'; + } + echo '
'; + ?> + {{Sauvegarder}} + + '; + ?> +
+ + \ No newline at end of file diff --git a/desktop/modal/AppV1Piece.php b/desktop/modal/AppV1Piece.php new file mode 100644 index 00000000..b739228e --- /dev/null +++ b/desktop/modal/AppV1Piece.php @@ -0,0 +1,66 @@ +. + */ + +if (!isConnect('admin')) { + throw new Exception('{{401 - Accès non autorisé}}'); +} +sendVarToJS('eqType', 'mobile'); +$eqLogics = eqLogic::byType('mobile'); +$plugins = plugin::listPlugin(true); +$plugin_compatible = mobile::$_pluginSuported; +$plugin_widget = mobile::$_pluginWidget; +?> + + {{Les Pièces - Application V1}} +
+ getDisplay('sendToApp', 1) == 0) { + $opacity = 'opacity:0.3;'; + } + $_echo .= '
'; + $_echo .= $object->getDisplay('icon', ''); + $_echo .= '
' . $object->getName() . '
'; + $_echo .= '
'; + } + echo $_echo; + ?> +
+ + + \ No newline at end of file diff --git a/desktop/modal/AppV1Plugin.mobile.php b/desktop/modal/AppV1Plugin.mobile.php new file mode 100644 index 00000000..9f0d031b --- /dev/null +++ b/desktop/modal/AppV1Plugin.mobile.php @@ -0,0 +1,332 @@ +. + */ +ini_set('display_errors', 0); +if (!isConnect('admin')) { + throw new Exception('{{401 - Accès non autorisé}}'); +} + +$plugin_compatible = mobile::$_pluginSuported; +$plugin_widget = mobile::$_pluginWidget; +$plugin = plugin::byId($_GET['plugin_id']); +sendVarToJS('pluginId', $_GET['plugin_id']); +?> + + + + +
+ {{Envoi auprès de l'app mobile}} + getId(), $plugin_widget)) { + $div = ''; + $div .= '
'; + $path = dirname(__FILE__) . '/../../core/template/images/' . $plugin->getId(); + if (file_exists($path)) { + $files = scandir($path); + foreach ($files as $imgname) { + if (!in_array($imgname, ['.', '..'])) { + $div .= ''; + } + } + } + $div .= '
'; + echo $div; + $generique_ok = false; + } else if (in_array($plugin->getId(), $plugin_compatible)) { + $div = ''; + echo $div; + $generique_ok = true; + } else { + $div = ''; + echo $div; + $generique_ok = true; + } + ?> +
+'; + echo ' {{Type Générique du Plugin}} {{Sauvegarder}}'; +?> +
+ '; + foreach ($eqLogics as $eqLogic) { + echo '
'; + if ($eqLogic->getEqType_name() != $_GET['plugin_id']) { + $subClassName = ' (' . $eqLogic->getEqType_name() . ') '; + } else { + $subClassName = ''; + } + $eqLogicId = $eqLogic->getId(); + echo ' '; + echo '
'; + echo '
'; + $cmds = null; + $cmds = cmd::byEqLogicId($eqLogicId); + echo ''; + echo ' + + + + '; + foreach ($cmds as $cmd) { + array_push($tableau_cmd, $cmd->getId()); + echo ''; + echo ''; + echo ''; + echo ''; + } + echo '
{{Id Cmd}}{{Nom de la Commande}}{{Type Générique}}
'; + echo '' . $cmd->getId() . ''; + echo ''; + echo $cmd->getName(); + $display_icon = 'none'; + $icon = ''; + if (in_array($cmd->getGeneric_type(), ['GENERIC_INFO', 'GENERIC_ACTION'])) { + $display_icon = 'block'; + $icon = $cmd->getDisplay('icon'); + } + echo '
+
+ ' . $icon . ' + {{Icône}} +
+
'; + echo '
'; + ?> + + '; + echo '
'; + echo '
'; + echo '
'; + echo '
'; + } + echo ''; + ?> + {{Sauvegarder}} +'; +} +?> + + + + + \ No newline at end of file diff --git a/desktop/modal/AppV1Plugin.php b/desktop/modal/AppV1Plugin.php new file mode 100644 index 00000000..11e11f40 --- /dev/null +++ b/desktop/modal/AppV1Plugin.php @@ -0,0 +1,207 @@ +. + */ + +if (!isConnect('admin')) { + throw new Exception('{{401 - Accès non autorisé}}'); +} +sendVarToJS('eqType', 'mobile'); +$eqLogics = eqLogic::byType('mobile'); +$plugins = plugin::listPlugin(true); +$plugin_compatible = mobile::$_pluginSuported; +$plugin_widget = mobile::$_pluginWidget; +?> + +{{Plugins Spéciaux Compatibles}} + + +
+ getId() != 'mobile' && $plugin->getId() != 'homebridge') { + if (in_array($plugin->getId(), $plugin_compatible)) { + if (in_array($plugin->getId(), $plugin_widget)) { + $_echo .= '
'; + $_echo .= '
'; + $_echo .= ''; + $_echo .= '
'; + $_echo .= '' . $plugin->getName() . ''; + $_echo .= '
'; + $num++; + } + } + } + } + echo $_echo; + if ($num == 0) { + echo ''; + } + ?> +
+ +{{Plugins Validés Type générique}} + + +
+ getId() != 'mobile' && $plugin->getId() != 'homebridge') { + if (in_array($plugin->getId(), $plugin_compatible)) { + if (config::byKey('sendToApp', $plugin->getId(), 1) == 1 && !in_array($plugin->getId(), $plugin_widget)) { + $_echo .= '
'; + $_echo .= '
'; + $_echo .= ''; + $_echo .= '
'; + $_echo .= '' . $plugin->getName() . ''; + $_echo .= '
'; + $num++; + } + } + } + } + echo $_echo; + if ($num == 0) { + echo ''; + } + ?> +
+ +{{Plugins compatibles non transmis}} + + +
+ getId() != 'mobile' && $plugin->getId() != 'homebridge') { + if (in_array($plugin->getId(), $plugin_compatible)) { + if (config::byKey('sendToApp', $plugin->getId(), 1) != 1 && !in_array($plugin->getId(), $plugin_widget)) { + $opacity = jeedom::getConfiguration('eqLogic:style:noactive'); + $_echo .= '
'; + $_echo .= '
'; + $_echo .= ''; + $_echo .= '
'; + $_echo .= '' . $plugin->getName() . ''; + $_echo .= '
'; + $num++; + } + } + } + } + echo $_echo; + if ($num == 0) { + echo ''; + } + ?> +
+ +{{Plugins non testés transmis}} + + +
+ getId() != 'mobile' && $plugin->getId() != 'homebridge') { + if (!in_array($plugin->getId(), $plugin_compatible)) { + if (config::byKey('sendToApp', $plugin->getId(), 0) == 1) { + $_echo .= '
'; + $_echo .= '
'; + $_echo .= ''; + $_echo .= '
'; + $_echo .= '' . $plugin->getName() . ''; + $_echo .= '
'; + $num++; + } + } + } + } + echo $_echo; + if ($num == 0) { + echo ''; + } + ?> +
+ +{{Plugins non testés et non transmis}} + + +
+ getId() != 'mobile' && $plugin->getId() != 'homebridge') { + if (!in_array($plugin->getId(), $plugin_compatible)) { + if (config::byKey('sendToApp', $plugin->getId(), 0) != 1) { + //$opacity = ''; jeedom::getConfiguration('eqLogic:style:noactive') + $_echo .= '
'; + $_echo .= '
'; + $_echo .= ''; + $_echo .= '
'; + $_echo .= '' . $plugin->getName() . ''; + $_echo .= '
'; + $num++; + } + } + } + } + echo $_echo; + if ($num == 0) { + echo ''; + } + ?> +
+ + + \ No newline at end of file diff --git a/desktop/modal/AppV1Scenario.php b/desktop/modal/AppV1Scenario.php new file mode 100644 index 00000000..e8d8c417 --- /dev/null +++ b/desktop/modal/AppV1Scenario.php @@ -0,0 +1,112 @@ +. + */ + +ini_set('display_errors', 0); +if (!isConnect('admin')) { + throw new Exception('{{401 - Accès non autorisé}}'); +} +?> +
+ {{Scénarios}} + + + +
+ + + + + + + + + + + getId(); + if ($scenario->getDisplay('sendToApp', 0) == 1) { + $check = 'checked'; + } + $tr = ''; + $tr .= ''; + $tr .= ''; + /*$tr .= ''; + echo $tr; + } + ?> + +
{{ID}}{{Scénario}}{{Transmis}}
' . $scenario_id . '' . $scenario->getHumanName() . '';*/ + $tr .= '
+
+
+ + \ No newline at end of file diff --git a/desktop/modal/doc1.php b/desktop/modal/doc1.php new file mode 100644 index 00000000..5e070e52 --- /dev/null +++ b/desktop/modal/doc1.php @@ -0,0 +1,13 @@ + + + + +Pour connecter votre téléphone, deux méthodes sont disponibles : +Sur le premier écran de l'application, vous pouvez soit connecter votre compte Market pour retrouver toutes les Box associées à ce compte, soit ajouter une Box manuellement. + diff --git a/desktop/modal/doc2.php b/desktop/modal/doc2.php new file mode 100644 index 00000000..5e070e52 --- /dev/null +++ b/desktop/modal/doc2.php @@ -0,0 +1,13 @@ + + + + +Pour connecter votre téléphone, deux méthodes sont disponibles : +Sur le premier écran de l'application, vous pouvez soit connecter votre compte Market pour retrouver toutes les Box associées à ce compte, soit ajouter une Box manuellement. + diff --git a/desktop/modal/doc3.php b/desktop/modal/doc3.php new file mode 100644 index 00000000..5e070e52 --- /dev/null +++ b/desktop/modal/doc3.php @@ -0,0 +1,13 @@ + + + + +Pour connecter votre téléphone, deux méthodes sont disponibles : +Sur le premier écran de l'application, vous pouvez soit connecter votre compte Market pour retrouver toutes les Box associées à ce compte, soit ajouter une Box manuellement. + diff --git a/desktop/modal/menuCustom.php b/desktop/modal/menuCustom.php index ceac7a1f..db635fdb 100755 --- a/desktop/modal/menuCustom.php +++ b/desktop/modal/menuCustom.php @@ -106,12 +106,18 @@ }, success: function(data) { if (data.state != 'ok') { - jeedomUtils.showAlert({ message: data.result, level: "danger"}) + jeedomUtils.showAlert({ + message: data.result, + level: "danger" + }) return } - jeedomUtils.showAlert({ message: '{{Configuration Menu Enregistrée}}', level: "success"}) + jeedomUtils.showAlert({ + message: '{{Configuration Menu Enregistrée}}', + level: "success" + }) } }) }) }) - + \ No newline at end of file diff --git a/desktop/modal/qrcodev2.php b/desktop/modal/qrcodev2.php index d3b32841..b89a2822 100755 --- a/desktop/modal/qrcodev2.php +++ b/desktop/modal/qrcodev2.php @@ -54,8 +54,6 @@ + \ No newline at end of file diff --git a/desktop/php/mobile.php b/desktop/php/mobile.php index 4f7db9c3..31ffb5f0 100755 --- a/desktop/php/mobile.php +++ b/desktop/php/mobile.php @@ -15,18 +15,19 @@ } } $isApi = config::byKey('api::mobile::mode'); -if($isApi == 'whiteip' || $isApi == 'disable'){ +if ($isApi == 'whiteip' || $isApi == 'disable') { message::add('mobile', 'L\'API mobile est désactivée ou en mode whitelist IP'); } $isCoreApi = config::byKey('api::core::mode'); -if($isCoreApi == 'whiteip' || $isCoreApi == 'disable'){ +if ($isCoreApi == 'whiteip' || $isCoreApi == 'disable') { message::add('mobile', 'L\'API core est désactivée ou en mode whitelist IP'); } ?>
+
- {{App V2 - (VERSION BETA SEULEMENT)}} + {{App V2}}

@@ -40,6 +41,10 @@
{{QR Code}}
+
+
+ {{Documentation}} +
{{Mes Téléphones Mobiles}}
@@ -53,59 +58,78 @@ = 1) { // AppV2 foreach ($eqLogicsV2 as $eqLogic) { - if ($eqLogic->getConfiguration('appVersion', '1') == '2') { - $opacity = ($eqLogic->getIsEnable()) ? '' : 'disableCard'; - echo '
'; - /* getImage : - core 4.4 - returns plugin image - core 4.5 - returns the custom image if exist or else the plugin image - */ - if ($eqLogic->getImage() != 'plugins/mobile/plugin_info/mobile_icon.png') $logoV2 = $eqLogic->getImage(); - else if (file_exists('plugins/mobile/plugin_info/mobileV2_icon.png')) $logoV2 = 'plugins/mobile/plugin_info/mobileV2_icon.png'; - else $logoV2 = $eqLogic->getImage(); - echo ''; - echo ''; - if ($eqLogic->getConfiguration('type_mobile') == 'android') { - echo ''; - } else { - echo ''; - } - echo ''; - echo '
'; - echo '' . $eqLogic->getHumanName(true, true) . ''; - echo ''; - echo '
'; + $opacity = ($eqLogic->getIsEnable()) ? '' : 'disableCard'; + echo '
'; + /* getImage : + core 4.4 - returns plugin image + core 4.5 - returns the custom image if exist or else the plugin image + */ + if ($eqLogic->getImage() != 'plugins/mobile/plugin_info/mobile_icon.png') $logoV2 = $eqLogic->getImage(); + else if (file_exists('plugins/mobile/plugin_info/mobileV2_icon.png')) $logoV2 = 'plugins/mobile/plugin_info/mobileV2_icon.png'; + else $logoV2 = $eqLogic->getImage(); + echo ''; + echo ''; + if ($eqLogic->getConfiguration('type_mobile') == 'android') { + echo ''; + } else { + echo ''; } + echo ''; + echo '
'; + echo '' . $eqLogic->getHumanName(true, true) . ''; + echo ''; + echo '
'; } } else { echo '
'; echo '{{Pour ajouter un téléphone, il y a 2 méthodes possible :}}
{{Sur le premier écran de l\'application, il vous est proposé de connecter votre compte market, et ainsi de retrouver toutes les boxs associées à ce compte, ou bien simplement ajouter une box.}}'; echo '
'; - } + } ?>
- = 1) { // AppV1 - ?> -
- {{App V1}} -
-
- {{Attention, en beta il n'est plus possible d'utiliser l'APP V1}}
-
- {{Mes Téléphones Mobiles}} -
- +
+ {{App V1}} +
+
+
+ {{Ajouter}} +
+
+
+ {{Plugins}} +
+
+
+ {{Objets/Pièces}} +
+
+
+ {{Scénarios}} +
+
+
+ {{Régénérer la configuration}} +
+
+ {{Mes Téléphones Mobiles}} +
+ {{Attention, l'APP V1 ne sera plus mise à jour}} +
+
+ = 0) { // AppV1 foreach ($eqLogicsV1 as $eqLogic) { if ($eqLogic->getConfiguration('appVersion', '1') != '2') { $opacity = ($eqLogic->getIsEnable()) ? '' : 'disableCard'; @@ -137,15 +161,16 @@ echo '
'; } } - ?> -
+ } + ?>
- +
@@ -53,21 +49,20 @@
Prises
2/3 Allumées
-
+
+
+ a 15.9155 15.9155 0 0 1 0 -31.831" /> + a 15.9155 15.9155 0 0 1 0 -31.831" />
@@ -76,21 +71,20 @@
Portes
1 Fermée
-
+
+
+ a 15.9155 15.9155 0 0 1 0 -31.831" /> + a 15.9155 15.9155 0 0 1 0 -31.831" />
@@ -115,21 +109,21 @@
Lumière Salon
Eteinte
-
+
-
- -
-
- -
+
+
-
-
Lumière Cuisine
-
Allumée à 30%
+
+
+
+
+
Lumière Cuisine
+
Allumée à 30%
+
@@ -168,301 +162,306 @@
-
- - + .iconTile { + font-size: 3.5em; + color: #a4a4a3; + } - + .circular-chart.green .circle { + stroke: #4CC790; + } + .circular-chart.blue .circle { + stroke: #3c9ee5; + } - \ No newline at end of file + .percentage { + fill: #666; + font-family: sans-serif; + font-size: 0.5em; + text-anchor: middle; + } + + + + + + \ No newline at end of file diff --git a/desktop/php/wizard.php b/desktop/php/wizard.php new file mode 100644 index 00000000..77080e47 --- /dev/null +++ b/desktop/php/wizard.php @@ -0,0 +1,78 @@ + + + + + +
+ +
+
+ +
+
+ $title) { + $finalAttr = ($step == 'finalization') ? ' data-finalization="1"' : ''; + echo ''; + echo $i; + echo ''; + $i++; + } + ?> +
+
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/docs/fr_FR/changelog.md b/docs/fr_FR/changelog.md index de0a875e..f16f9a7a 100755 --- a/docs/fr_FR/changelog.md +++ b/docs/fr_FR/changelog.md @@ -4,6 +4,20 @@ > > Pour rappel s'il n'y a pas d'information sur la mise à jour, c'est que celle-ci concerne uniquement de la mise à jour de documentation, de traduction ou de texte +# 17/05/2026 + +- Réintégration de l'Application V1 (cohabitation V1/V2) +- Exclusion du répertoire "data" des sauvegardes + +### Notifications + +- Nouvel onglet de visualisation des notifications sur la page d'un équipement mobile. + + +### Géofencing + +- Correction : un même événement ENTER/EXIT n'est plus traité plusieurs fois en cas d'envoi dupliqué par l'app +- Correction : les événements géofence trop anciens (> 30 min) sont ignorés pour éviter de déclencher des scénarios hors contexte # 11/05/2026 @@ -26,26 +40,14 @@ - Ajout pour Max 8 Icones sur le menuCustom - # 24/04/2025 - Ajout Commande Notifications Silencieuses pour Builds : IOS 491 et Android 875 - # 11/04/2025 - Ajout paramètre Envoi NFC Direct au plugin après lecture -# xx/08/2024 - -> **App V1** -> -> Attention, à partir de cette version, l'appV1 n'est plus prise en charge. -> Il sera toujours possible d'accéder à votre équipement, pour éventuellement, remplacer vos commandes de géolocalisation et de notification. - -- Suppression des fichiers concernant l'AppV1. -- Nettoyage des infos stockées en BDD (config). - # 20/08/2024 - Déplacement des infos notifications dans l'onglet "Mobile" diff --git a/plugin_info/info.json b/plugin_info/info.json index d1951588..82c54028 100755 --- a/plugin_info/info.json +++ b/plugin_info/info.json @@ -2,7 +2,7 @@ "id": "mobile", "name": "App Mobile", "description": { - "fr_FR": "Attention : la version BETA ne supporte plus l'app V1, elle est réservée à la nouvelle app V2 (beta actuellement). Nécessite Android14 ou IOS 12.4 minimum.Attention, l'app v1 n'est pas compatible avec le dernier Android. L'application officielle Jeedom permet le pilotage de votre système domotique Jeedom, que ce soit en Wifi local, ou sur le réseau 3G\/4G de votre opérateur.L'app se connecte automatiquement à votre Jeedom avec une initialisation automatique par QRcode, aucune configuration n'est nécessaire. (possibilité de le faire manuellement)Vous retrouverez sur votre mobile toutes les fonctionnalités de votre Jeedom.Vous pourrez personnaliser votre application avec des raccourcis et plus encore...Fonctionnalités actuelles:- Gestion de vos scénarios.- Gestion de votre domotique en fonction de vos pièces et équipements.- Maj et retour d'état automatique- Compatibilité aves les plugins, tel que thermostat, alarme, caméra etc...- Interface personnalisable avec les raccourcis.- Résumé domotique général et par pièce- Notifications (avec prise en charge du ASK)- Affichage des Designs D'autres fonctionnalités et compatibilités sont à venir dans les prochaines mises à jour !Respect de la vie privée.Aucune donnée (domotique ou personnelle) n'est stockée ou conservée sur nos serveurs.", + "fr_FR": "L’app V2 nécessite Android14 ou IOS 12.4 minimum. Attention, l'app v1 n'est pas compatible avec le dernier Android. L'application officielle Jeedom permet le pilotage de votre système domotique Jeedom, que ce soit en Wifi local, ou sur le réseau 4G/%G de votre opérateur. L'app se connecte automatiquement à votre Jeedom avec une initialisation automatique par QRcode, aucune configuration n'est nécessaire. (possibilité de le faire manuellement)Vous retrouverez sur votre mobile toutes les fonctionnalités de votre Jeedom.Vous pourrez personnaliser votre application avec des raccourcis et plus encore...Fonctionnalités actuelles:- Gestion de vos scénarios.- Gestion de votre domotique en fonction de vos pièces et équipements.- Maj et retour d'état automatique - Interface personnalisable avec les raccourcis Notifications (avec prise en charge du ASKD'autres fonctionnalités et compatibilités sont à venir dans les prochaines mises à jour !Respect de la vie privée.Aucune donnée (domotique ou personnelle) n'est stockée ou conservée sur nos serveurs.", "en_US": "Warning: the BETA version no longer supports the V1 app, it is reserved for the new V2 app (currently beta). Requires Android14 or IOS 12.4 minimum. Please note that the v1 app is not compatible with the latest Android. The official Jeedom application allows you to control your Jeedom home automation system, whether in local WiFi, or on your operator's 3G\/4G network. The app automatically connects to your Jeedom with automatic initialization by QRcode, no configuration is necessary. (possibility to do it manually) You will find all the features of your Jeedom on your mobile. You will be able to customize your application with shortcuts and more... Current features: - Management of your scenarios. - Management of your home automation based on your rooms and equipment. - Automatic shift and return to state - Compatibility with plugins, such as thermostat, alarm, camera etc... - Customizable interface with shortcuts. - General and room-by-room home automation summary - Notifications (with ASK support) - Displaying Designs More features and compatibilities are coming in future updates! Respect for privacy. No data (home automation or personal) is stored or kept on our servers", "es_ES": "Tenga en cuenta: la versión BETA ya no es compatible con la aplicación V1, está reservada para la nueva aplicación V2 (actualmente beta). Requiere Android14 o IOS 12.4 mínimo. Tenga en cuenta que la aplicación v1 no es compatible con la última versión de Android. La aplicación oficial Jeedom te permite controlar tu sistema domótico Jeedom, ya sea a través de WiFi local o en la red 3G\/4G de tu operador. La aplicación se conecta automáticamente a tu Jeedom con inicialización automática mediante código QR, no es necesaria ninguna configuración. (posibilidad de hacerlo manualmente) Encontrarás todas las funciones de tu Jeedom en tu móvil. Podrás personalizar tu aplicación con atajos y más... Características actuales: - Gestión de tus escenarios. - Gestión de tu domótica en función de tus estancias y equipamientos. - Cambio y retorno automático de estado. - Compatibilidad con complementos, como termostato, alarma, cámara, etc... - Interfaz personalizable con atajos. - Resumen general de domótica y por estancias - Notificaciones (con soporte ASK) - Exhibición de Diseños ¡Más funciones y compatibilidad estarán disponibles en futuras actualizaciones! Respeto a la privacidad. No se almacena ni retiene ningún dato (domótico o personal) en nuestros servidores", "de_DE": "Bitte beachten Sie: Die BETA-Version unterstützt die V1-App nicht mehr, sie ist für die neue V2-App (derzeit Beta) reserviert. Erfordert mindestens Android14 oder IOS 12.4. Bitte beachten Sie, dass die v1-App nicht mit dem neuesten Android kompatibel ist. Mit der offiziellen Jeedom-Anwendung können Sie Ihr Jeedom-Hausautomationssystem steuern, sei es über lokales WLAN oder über das 3G\/4G-Netzwerk Ihres Betreibers. Die App verbindet sich automatisch mit Ihrem Jeedom mit automatischer Initialisierung per QR-Code, eine Konfiguration ist nicht erforderlich. (Möglichkeit, dies manuell zu tun) Sie finden alle Funktionen Ihres Jeedom auf Ihrem Handy. Sie können Ihre Anwendung mit Verknüpfungen und mehr personalisieren ... Aktuelle Funktionen: - Verwaltung Ihrer Szenarien. - Verwaltung Ihrer Hausautomation entsprechend Ihren Räumen und Ihrer Ausstattung. - Automatische Statusverschiebung und -rückkehr - Kompatibilität mit Plugins wie Thermostat, Alarm, Kamera usw. - Anpassbare Benutzeroberfläche mit Verknüpfungen. - Allgemeine Zusammenfassung der Hausautomation und nach Raum - Benachrichtigungen (mit ASK-Unterstützung) - Anzeige von Designs Weitere Funktionen und Kompatibilität folgen in zukünftigen Updates! Respekt vor der Privatsphäre. Auf unseren Servern werden keine Daten (hausautomatische oder persönliche) gespeichert oder aufbewahrt", diff --git a/plugin_info/install.php b/plugin_info/install.php index 0d653d98..22a65e99 100755 --- a/plugin_info/install.php +++ b/plugin_info/install.php @@ -43,6 +43,7 @@ function mobile_update() } $mobiles = eqLogic::byType('mobile'); + $migrateLogicalId = array('phoneBattery' => 'battery::level', 'phoneCharging' => 'battery::isCharging'); foreach ($mobiles as $mobile) { /* Delete mobile with bad logicalId */ if ($mobile->getLogicalId() == null || $mobile->getLogicalId() == "") { @@ -60,6 +61,16 @@ function mobile_update() $mobile->setConfiguration('menuCustomArray', $menuCustomArray); } $mobile->save(); + /* Migrate logicalId for cmdForSpecificChannel */ + if ($mobile->getConfiguration('appVersion', 1) == '1') continue; + foreach ($migrateLogicalId as $oldLogical => $newLogical) { + $cmd = cmd::byEqLogicIdAndLogicalId($mobile->getId(), $oldLogical); + if (is_object($cmd)) { + log::add('mobile', 'debug', '| Migrate logicalId ' . $oldLogical . ' to ' . $newLogical . ' for the command ' . $cmd->getHumanName()); + $cmd->setLogicalId($newLogical); + $cmd->save(); + } + } } /* Delete old "menuCustom_" and "NoCut" save into config of plugin */ @@ -100,7 +111,7 @@ function mobile_update() '/../desktop/modal/sixPage.php', '/../desktop/modal/wizard.php', '/../core/data/wizard.json', - '/../data/mobile.json' + //'/../data/mobile.json' ]; foreach ($oldFiles as $oldFile) { if (file_exists(dirname(__FILE__) . $oldFile)) { @@ -159,12 +170,12 @@ function mobile_update() } } - /* cleaning data folder */ + /* cleaning data folder AppV1 $path = dirname(__FILE__) . '/../data/'; foreach (scandir($path) as $file) { if ($file != "." && $file != ".." && $file != ".htaccess" && $file != "images") { if (is_dir($path . '/' . $file)) { - /* delete dashboard.json and favdash.json if exists */ + // delete dashboard.json and favdash.json if exists // if (file_exists($path . $file . '/dashboard.json')) { log::add('mobile', 'debug', '| Deleting ' . $path . $file . '/dashboard.json'); shell_exec('rm ' . $path . $file . '/dashboard.json'); @@ -173,7 +184,7 @@ function mobile_update() log::add('mobile', 'debug', '| Deleting ' . $path . $file . '/favdash.json'); shell_exec('rm ' . $path . $file . '/favdash.json'); } - /* delete folder if empty */ + // delete folder if empty // if (!glob($path . $file . '/*')) { log::add('mobile', 'debug', '| Deleting empty folder : ' . $path . $file); shell_exec('rm -rf ' . $path . $file); @@ -181,7 +192,7 @@ function mobile_update() } } } - + */ /* Generate ApiKey if no exist */ jeedom::getApiKey('mobile');