Pour info, ma solution à mon problème, si ça en intéresse certain.
Scénario « Situation » pour détecter la sortie du geofence « Maison » (géré par Jeedom Connect)
$trigger = cmd::cmdToHumanReadable($scenario->getRealTrigger());
$cmd = cmd::byString($trigger);
$cmd_name = $cmd->getName();
$cmd_value = $cmd->execCmd();
$eqLogicName = $cmd->getEqLogic()->getName();
$eqLogic = eqLogic::byId($cmd->getEqLogic()->getId());
$object = $eqLogic->getObject()->getName();
// Le geofence recherché ici est : #[Utilisateur][Telephone][Maison]#
if($object == "Utilisateur")
{
if($cmd_value == 0)
{
cmd::byString("#[Utilisateur][Statut][Situation]#")->event("Route");
if($cmd_name == "Maison") // L'utilisateur est parti de la maison
{
// Lancement scénario "getWorkPlace" afin de déterminer le lieu "Boulot" du jour
scenario::byId("41")->launch("Scénario", "Lancé par " . $scenario->getHumanName());
}
}
else // L'utilisateur est arrivé à destination "Maison"
{
// On calcule le temps du trajet depuis le départ de "Boulot"
cmd::byString("#[Utilisateur][Statut][Situation]#")->event($cmd_name);
$duration = time() - $scenario->getData(departUtilisateur);
($duration >= 3600) ? $duration = ($duration / 3600 % 24).'h '.($duration / 60 % 60).'m' : $duration = ($duration / 60 % 60).'m';
// Préparation du message de notification
$titre = $object." situation"; $message = "Arrivée à \"".$cmd_name."\"<br>Durée du trajet : ".$duration;
$options = array("title" => $titre, "message" => $message);
}
}
cmd::byString("#[Dukei][Telephone][Notification]#")->execCmd($options);
cmd::byString("#[Utilisateur][Telephone][Notification]#")->execCmd($options);
Le scénario « getWorkPlace » est alors lancé, afin de déterminer le lieu « Boulot » du jour :
$cmd = cmd::byString("#[Utilisateur][Telephone][Position]#");
$GPS = $cmd->execCmd();
$valueDate = $cmd->getValueDate();
$scenario->setLog("Value date : ".$valueDate);
$tags = $scenario->getTags();
$tags["#delay#"] = time() - strtotime($valueDate);
if($tags["#delay#"] >= 300) // Si les coordonnées GPS n'ont pas été mise à jour depuis plus de 5 minutes
{
// On récupère les coordonnées GPS pour les mettre en forme et les sauvegarder
list($lat, $lon) = explode(",", $GPS);
$lat_degree = intval($lat);
$lat_degree_minute = intval(($lat - $lat_degree) * 60);
$lat_degre_seconde = round((($lat - $lat_degree) * 60 - intval($lat_degree_minute)) * 60, 1);
$lon_degree = intval($lon);
$lon_degree_minute = intval(($lon - $lon_degree) * 60);
$lon_degre_seconde = round((($lon - $lon_degree) * 60 - intval($lon_degree_minute)) * 60, 1);
cmd::byString("#[Utilisateur][Localisation][GPS]#")->event($GPS);
cmd::byString("#[Utilisateur][Statut][Situation]#")->event("Boulot");
// Construction de l'url attendu par Maps pour afficher correctement la localisation
// Encodage des URL HTML : %C2%B0 = ° et %22 = " (voir https://www.w3schools.com/tags/ref_urlencode.ASP)
$url = "https://www.google.com/maps/place/".$lat_degree."%C2%B0".$lat_degree_minute."'".$lat_degre_seconde."%22N+".$lon_degree."%C2%B0".$lon_degree_minute."'".$lon_degre_seconde."%22E/@".$GPS.",15z";
$options = array("title" => "L'utilisateur ne bouge plus", "message" => "Boulot du jour : <a href=".$url.">".$GPS."</a>");
cmd::byString("#[Dukei][Telephone][Notification]#")->execCmd($options);
cmd::byString("#[Utilisateur][Telephone][Notification]#")->execCmd($options);
}
$scenario->setTags($tags);
Et enfin, le scénario « Calcul distance » , qui est déclenché à la mise à jour de l’info #[Utilisateur][Telephone][Position]# , qui vérifie la distance entre le point « Boulot du jour » et le téléphone et qui permet donc de savoir si l’utilisateur a quitté ce geofence « perso » , et de déclencher les notifications qui vont bien :
$work = cmd::byString("#[Utilisateur][Localisation][GPS]#")->execCmd(); // Lieu "Boulot" du jour
list($lat1, $lon1) = explode(",", $work); $lat1 = round($lat1, 7); $lon1 = round($lon1, 7);
$phone = cmd::byString("#[Utilisateur][Telephone][Position]#")->execCmd(); // Position actuelle du téléphone
list($lat2, $lon2) = explode(",", $phone); $lat2 = round($lat2, 7); $lon2 = round($lon2, 7);
// Calcul de la distance entre deux points GPS
$R = 6371;
$dLat = deg2rad($lat2-$lat1); $dLon = deg2rad($lon2-$lon1);
$lat1 = deg2rad($lat1); $lat2 = deg2rad($lat2);
$a = sin($dLat/2) * sin($dLat/2) + sin($dLon/2) * sin($dLon/2) * cos($lat1) * cos($lat2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
$d = round($R * $c, 2);
cmd::byString("#[Utilisateur][Localisation][Distance]#")->event($d); $scenario->setLog("Distance = ".$d." km");
if($d > 0.5) // Si la distance est supérieur à 500 m
{
cmd::byString("#[Utilisateur][Statut][Situation]#")->event("Route");
// Calcul du temps moyen du trajet vers la maison (via le plugin "Waze in time")
cmd::byString("#[Utilisateur][vers Maison][Rafraichir]#")->execCmd(); // Ces durées sont en minutes, et non pas en secondes
$duration1 = cmd::byString("#[Utilisateur][vers Maison][Durée 1]#")->execCmd();
$duration2 = cmd::byString("#[Utilisateur][vers Maison][Durée 2]#")->execCmd();
$duration3 = cmd::byString("#[Utilisateur][vers Maison][Durée 3]#")->execCmd();
$scenario->setData(departUtilisateur, time()); $average = 0; $sum = 3;
($duration1 > 0) ? $average += $duration1 * 60 : $sum--;
($duration2 > 0) ? $average += $duration2 * 60 : $sum--;
($duration3 > 0) ? $average += $duration3 * 60 : $sum--;
if($sum > 1) $average = round($average / $sum);
($average >= 3600) ? $duration = ($average / 3600 % 24).'h '.($average / 60 % 60).'m' : $duration = ($average / 60 % 60).'m';
$arrival = date('H:i', time() + $average);
// Préparation du message de notification
$titre = "Utilisateur situation"; $message = "Départ de \"Boulot\"<br>Arrivée estimée à ".$arrival." (".$duration.")";
$options = array("title" => $titre, "message" => $message);
cmd::byString("#[Dukei][Telephone][Notification]#")->execCmd($options);
cmd::byString("#[Utilisateur][Telephone][Notification]#")->execCmd($options);
}
Ce scénario est désactivé une fois le « geofence » quitté (pour éviter les déclenchements inutiles par la suite) et est (ré)activé par le scénario « getWorkPlace »