HTMLBox für Anwesenheit

Für eine bessere Übersicht aktualisiere ich jetzt immer diesen Beitrag mit der aktuellsten Version.

HTMLBox für die Visualisierung und das schalten der Anwesenheit von Bewohnern

Die Box kann bis zu 5 Bewohner abbilden.
Je Bewohner kann ein Foto hinterlegt werden. Wenn der Bewohner anwesend ist wird das Foto in Farbe dargestellt, bei Abwesenheit in sw. Bei bedarf kann über das Foto der Status des Bewohners umgeschaltet werden falls mal die Smartphone Ortung nicht funktioniert hat oder wie in meinem Beispiel der Besuchermodus aktiviert werden soll.

Installationsanleitung im Script.

Skript für die HTMLBox:

<?php

/*
Installation: 
1. Eine String Variable erstellen und das Variablenprofil HTMLBox zuweisen. Diesen Code hier in ein Script kopieren, anpassen und ausführen. Für jeden Bewohner muss ein Ereigniss erstellt werden das bei Variablenänderung der Bool-Variable des Bewohners dieses Script hier ausführt.
2. Ein php Script erstellen (ich nenne es jetzt einfach mal webhook). Dieses Script ist das Ziel für den Webhook. Code aus dem Forum einfügen und speichern.
3. Webhook einrichten (Kategorie Kern Instanzen/Webhook) Neuen Webhook erstellen. Im Feld Hook anwesenheit eintragen.Bei Script das eben erstellte php Script (webhook) auswählen. Speichern...
4. Fotos der Bewohner: Seitenverhältnis am besten 1:1 (quadratisch) Die Schwarzweiss Darstellung (bei Abwesenheit) wird automatisch über CSS realisiert. 
Es muss also je Bewohner nur 1 Farbbild bereitgestellt werden. Die Kreisdarstellung erfolgt ebenfalls über CSS und kann in diesem Script auch konfiguriert werden. (in Zeile 115, border-radius: 50% 50% 50% 50%)
Die Bilder müssen ins entsprechende Verzeichnis eurer Symcon Installation kopiert werden. Voreingestellt ist: /user/img/bewohner/
5. In diesem Script die Anwohner konfigurieren
*/
// Anwohner 1
$bewohner1_active = true; //Anwohner ein- oder ausblenden. true = aktiv, false = deaktiviert
$bewohner1_bool = "54558"; // Variablen ID einer Bool Variable die den aktuellen Status des Bewohners enthält. true = anwesend, false = abwesend 
$bewohner1_id=1; //NICHT ÄNDERN
$bewohner1 = GetValueBoolean($bewohner1_bool); //NICHT ÄNDERN
$greyscale_bewohner1 = $bewohner1 ? "0%" : "100%"; //bei abwesenheit wird das Bild des Anwohners in Graustufen abgebildet
$name_bewohner1 = "Stephan"; // Anzeigename in der Visualisierung
$image_bewohner1 = "/user/img/bewohner/ssp.png"; //Dateiname vom Foto

// Anwohner 2
$bewohner2_active = true;
$bewohner2_bool = "38676";// Variablen ID einer Bool Variable die den aktuellen Status des Bewohners enthält. true = anwesend, false = abwesend 
$bewohner2_id=2;//NICHT ÄNDERN
$bewohner2 = GetValueBoolean($bewohner2_bool);//NICHT ÄNDERN
$greyscale_bewohner2 = $bewohner2 ? "0%" : "100%";
$name_bewohner2 = "Simone"; // Anzeigename
$image_bewohner2 = "/user/img/bewohner/si.png";

// Anwohner 3
$bewohner3_active = true;
$bewohner3_bool = "57762";// Variablen ID einer Bool Variable die den aktuellen Status des Bewohners enthält. true = anwesend, false = abwesend 
$bewohner3_id=3;//NICHT ÄNDERN
$bewohner3 = GetValueBoolean($bewohner3_bool);//NICHT ÄNDERN
$greyscale_bewohner3 = $bewohner3 ? "0%" : "100%";
$name_bewohner3 = "Besucher"; // Anzeigename
$image_bewohner3 = "/user/img/bewohner/besucher.png";

// Anwohner 4
$bewohner4_active = false;
$bewohner4_bool = "57762";// Variablen ID einer Bool Variable die den aktuellen Status des Bewohners enthält. true = anwesend, false = abwesend 
$bewohner4_id=4;//NICHT ÄNDERN
$bewohner4 = GetValueBoolean($bewohner4_bool);//NICHT ÄNDERN
$greyscale_bewohner4 = $bewohner4 ? "0%" : "100%";
$name_bewohner4 = "Besucher"; // Anzeigename
$image_bewohner4 = "/user/img/bewohner/besucher.png";

// Anwohner 5
$bewohner5_active = false;
$bewohner5_bool = "57762";// Variablen ID einer Bool Variable die den aktuellen Status des Bewohners enthält. true = anwesend, false = abwesend 
$bewohner5_id=5;//NICHT ÄNDERN
$bewohner5 = GetValueBoolean($bewohner5_bool);//NICHT ÄNDERN
$greyscale_bewohner5 = $bewohner5 ? "0%" : "100%";
$name_bewohner5 = "Besucher"; // Anzeigename
$image_bewohner5 = "/user/img/bewohner/besucher.png";

//URL zum Symcon Server
$serverIP = "http://192.168.0.134:3777";
$benutzername = "Benutzername";
$passwort = "Passwort";
//Schriftgröße der Namen
$schriftgroesse= '0.8em';

//Hier die Variablen ID der String Variable mit dem HTMLBox Profil eintragen.
$htmlbox = 46220;



// Ab hier nichts mehr ändern!!!!!!!!
$html = '
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body {
            margin: 0px;
            position: fixed;
            width: 100%;
            height: 100%;
            font-size: '. $schriftgroesse .'
        }

        .container_anwesenheit {
            width: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .box {
            width: 33.33%;
            text-align: center;
            border: 0px solid #ccc;
        }

        .row2 {
            padding-top: 5px;
        }

   </style>
      <script>
  window.console = window.console || function(t) {};
</script>
</head>
<body>


 <div class="container_anwesenheit row1">
';

$bewohner_data = [
    [$bewohner1_active, $name_bewohner1, $image_bewohner1, $greyscale_bewohner1, $bewohner1_id, $bewohner1_bool, $benutzername, $passwort],
    [$bewohner2_active, $name_bewohner2, $image_bewohner2, $greyscale_bewohner2, $bewohner2_id, $bewohner2_bool, $benutzername, $passwort],
    [$bewohner3_active, $name_bewohner3, $image_bewohner3, $greyscale_bewohner3, $bewohner3_id, $bewohner3_bool, $benutzername, $passwort],
    [$bewohner4_active, $name_bewohner4, $image_bewohner4, $greyscale_bewohner4, $bewohner4_id, $bewohner4_bool, $benutzername, $passwort],
    [$bewohner5_active, $name_bewohner5, $image_bewohner5, $greyscale_bewohner5, $bewohner5_id, $bewohner5_bool, $benutzername, $passwort],
];

foreach ($bewohner_data as list($active, $name, $image, $greyscale, $id, $id_bool, $benutzername, $passwort)) {
    if ($active) {
        $name = "bewohner" . $id;
        $html .= <<<HTML
        <div class="box">
            <img
                type="button"
                src="{$image}"
                onclick="anwesenheit('{$name}', '{$id_bool}', '{$benutzername}', '{$passwort}')"
                style="width: 80%; filter: grayscale({$greyscale}); border-radius: 50% 50% 50% 50%;"
            />
        </div>
HTML;
    }
}

$html .= '
    </div>
    
    <div class="container_anwesenheit row2">
';

foreach ($bewohner_data as list($active, $name)) {
    if ($active) {
        $html .= <<<HTML
        <div class="box">{$name}</div>
HTML;
    }
}

$html .= '
    </div>
<script>
    function anwesenheit(name, id_bool, benutzername, passwort) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function () {
            // Hier kannst du auf die Antwort des Servers reagieren, wenn nötig
            if (xhttp.readyState == 4 && xhttp.status == 200) {
                console.log(xhttp.responseText);
            }
        };

        // Öffnen Sie die Anfrage mit der POST-Methode
        xhttp.open("POST", "' . $serverIP . '/hook/anwesenheit");

        // Setze den Content-Type Header für POST-Anfragen
        xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

        // Erstelle die Daten, die du senden möchtest (hier als URL-codierter String)
var data = "name=" + encodeURIComponent(name) + "&id_bool=" + encodeURIComponent(id_bool) + "&benutzername=" + encodeURIComponent(benutzername) + "&passwort=" + encodeURIComponent(passwort);

        // Sende die Anfrage mit den Daten
        xhttp.send(data);
    }
</script>



</body>
</html>
';

SetValueString($htmlbox, $html);

Script für den Webhook:


<?php
$erwartete_benutzername = "Benutzername"; // Setze dies auf den tatsächlichen Benutzernamen in deinem System
$erwartetes_passwort = "Passwort"; // Setze dies auf das tatsächliche Passwort in deinem System


// Überprüfe, ob die benötigten Parameter gesetzt sind
if (!isset($_POST['benutzername']) || !isset($_POST['passwort']) || !isset($_POST['id_bool']) || !isset($_POST['name'])) {
    header('HTTP/1.1 400 Bad Request');
    echo "Fehlende Parameter";
    exit();
}

// Überprüfe die Anmeldedaten
$benutzername = $_POST['benutzername'];
$passwort = $_POST['passwort'];

if ($benutzername !== $erwartete_benutzername || $passwort !== $erwartetes_passwort) {
    header('HTTP/1.1 401 Unauthorized');
    echo "Ungültige Anmeldedaten";
    exit();
}

// Verarbeite die Anwesenheitsinformationen
$id_bool = $_POST['id_bool'];
$bewohner = $_POST['name'];

function toggleValue($id_bool) {
    $value = GetValueBoolean($id_bool);
    SetValue($id_bool, !$value);
}

switch ($bewohner) {
    case 'bewohner1':
        toggleValue($id_bool);
        break;
    case 'bewohner2':
        toggleValue($id_bool);
        break;
    case 'bewohner3':
        toggleValue($id_bool);
        break;
    case 'bewohner4':
        toggleValue($id_bool);
        break;
    case 'bewohner5':
        toggleValue($id_bool);
        break;
}


viele Spaß mit der Box und gebt gerne Feedback ob alles funktioniert hat.

Viele Grüße
Stephan

1 „Gefällt mir“

Wie haste das mit der Anwesenheit gemacht - auch HTML, oder?

ja, ist html.
Das ganze ist etwas komplizierter weil man über die Fotos auch den Status schalten kann falls mal die Ortung über Smartphone nicht funktioniert hat oder Besuch da ist.

Ist jemand abwesend wird das Bild in Graustufen angezeigt. Das wird über CSS realisiert. Die Bilder werden also nur in Farbe benötigt!

Leider muss man für jeden Webhook ein Script erstellen welches dann die Variable UMschaltet. Falls das jemand über die Symcon API hinbekommt immer her mit dem Code :wink:

<?php


//Prüfen wer anwesend ist (true = anwesend, false = abwesend)
$ssp = GetValueBoolean(54558);
$si  = GetValueBoolean(38676);
$besucher = GetValueBoolean(57762);

if ($ssp == true) {
   $greyscale_ssp = "0%"; // Wenn anwesend dann Graustufenfilter auf 0% (aus)
} else {
   $greyscale_ssp = "100%"; // Wenn abwesend dann Graustufenfilter auf 100% (an)
}

if ($si == true) {
   $greyscale_si = "0%"; // Wenn anwesend dann Graustufenfilter auf 0% (aus)
} else {
   $greyscale_si = "100%"; // Wenn abwesend dann Graustufenfilter auf 100% (an)
}

if ($besucher == true) {
   $greyscale_besucher = "0%"; // Wenn anwesend dann Graustufenfilter auf 0% (aus)
} else {
   $greyscale_besucher = "100%"; // Wenn abwesend dann Graustufenfilter auf 100% (an)
}
    $html = '
    
    <style>
        .container {
            width: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            
        }

        /* Stilvorgaben für die erste Reihe mit 3 Divs */
        .row1 {
            height: 250px;
        }

        /* Stilvorgaben für die zweite Reihe mit 3 Divs */
        .row2 {
            height: 50px;
        }

        /* Gemeinsame Stilvorgaben für alle Divs */
        .box {
            width: 33.33%;
            text-align: center;
            border: 0px solid #ccc;
        }

        /* Stilvorgaben für die Bilder in den Divs */
        .box img {
            width: 200px;
            height: 200px;
        }


    </style>
</head>
<body>
    <div class="container row1">
        <div class="box">
        <img
        type="button"
        src="/user/img/bewohner/ssp.png"
        type="button"
        onclick="stephan()" style="filter: grayscale('.$greyscale_ssp.');"/>
        </div>
        <div class="box">
        <img
        type="button"
        src="/user/img/bewohner/si.png"
        type="button"
        onclick="simone()" style="filter: grayscale('.$greyscale_si.');"/>
        </div>
        <div class="box">
        <img
        type="button"
        src="/user/img/bewohner/besucher.png"
        type="button"
        onclick="besucher()" style="filter: grayscale('.$greyscale_besucher.');"/>
        </div>
    </div>
    <div class="container row2">
        <div class="box">Stephan</div>
        <div class="box">Simone</div>
        <div class="box">Besucher</div>
    </div>

 <script>
    function stephan() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {};
      xhttp.open("GET", "http://192.168.0.134:3777/hook/stephan", true);
      xhttp.send();
    }
  </script>
  
  <script>
    function simone() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {};
      xhttp.open("GET", "http://192.168.0.134:3777/hook/simone", true);
      xhttp.send();
    }
  </script>
  
  <script>
    function besucher() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {};
      xhttp.open("GET", "http://192.168.0.134:3777/hook/besucher", true);
      xhttp.send();
    }
  </script>
  
</body>
';

SetValueString(45502, $html);

Auch wenn wir immer mehr OT werden :wink:

Klar geht das.
Du kannst die URL so aufbauen:
http://192.168.0.134:3777/hook/anwesend/person
Und den Hook nur auf
http://192.168.0.134:3777/hook/anwesend
setzen.

Im Script kannst du dann die ganze URL in $_SERVER['REQUEST_URI'] auswerten.

Oder mit Get Payload arbeiten:
http://192.168.0.134:3777/hook/anwesend?Person=Name
Und im Script dann $_GET['Person'] nutzen.

Siehe auch hier:
https://www.php.net/manual/de/reserved.variables.server.php

Michael

Stimmt, jetzt wo du es schreibst… hab ich selbst auch so schon mal umgesetzt.

Zum Thema offtopic: vielleicht ist ja ein Moderator so nett und gliedert die Script Sachen in einen eigenen Beitrag aus.

Danke schon mal vorab. Ich bin das gerade am nachbauen, im Prinzip geht es auch, aber irgendwie zerreißt mir der String mit der ~HTMLBox die ganze Seite.
Aus so:


wird

Spiel mal etwas mit den Höhen bei height: 250px; und height: 50px;

Die sind leider noch fest eingestellt.

Hab die nie mit dem alten Webfront getestet, die Kachel hab ich für die iOS Tile Visu erstellt. Warum der z.b. die Headlines zerschießt… leider keinen Plan.

So, ich habe es getan :slight_smile: Habe die Begrüßung, Automation und Favoriten deaktiviert und @da8ter 's wunderschöne Vorarbeit eingebaut. Vorteil, Platzgewinn und sieht lustig aus :slight_smile:

Wie immer muss ich das für mich etwas umbauen :banghead:

image

Freu mich! Danke @da8ter !

1 „Gefällt mir“

Das mit der Größe hat hingehauen, aber dennoch zerreißt es den Rest.
Hab es auch mal auf einer anderen Seite versucht, welche noch keine htmlBox hatte - aber es bleibt das gleiche in grün.

Im alten WebFront wird der Code der HTMLBoxen direkt in die gesamte Seite integriert, sodass es zu Konflikten mit Klassen kommen kann (ich vermute hier die Klasse „container“). Du müsstest vermutlich den Klassen einen eindeutigen Namen geben, die nicht denen des WebFronts gleichen.

In der Tile-Visu werden HTMLBoxen als iFrame eingebunden, sodass hier die Klassen in der HMTLBox keinen Einfluss auf den Rest der Seite haben.

2 „Gefällt mir“

Du Fuchs - habe nur ein r drangesetzt - schon rennt es :smiley:

1 „Gefällt mir“

Ich habe den Thread mal in die neue Kategorie „Kacheln“ verschoben, hier wollen wir die Anleitungen für Kacheln sammeln. :slight_smile:

Grüße,
Kai

Ist das nur für die Neue Visu zu empfehlen?

Du kannst das auch für das alte Webfront nutzen.

Grüße,
Kai

1 „Gefällt mir“

Kannst du deine Anpassung hier zur Verfügung stellen.

Gruß Lutz :v:

Kann ich gern mach @DeejayT, aber das drum herum ist bei mir schon sehr speziell :frowning:

Hintergrund:

  • Infos basieren auf meiner Anwesenheitserkennung via Fritzbox und mit Handy eingeloggt Zustand

  • Ich habe ein binäres Integer-Profil mit entsprechender Textzuweisung

    • bei 4-Personenhaushalt = 16 Kombinationen (0 - 15)
    • 1, 2,4 und 8 sind die einzelnen Personen; 12 = Person (4) & Person(8) usw.
    • also bei 4 = Heiko und 8 = Luise steht bei 12 Heiko, Luise usw.
  • dann habe ich die Bilder (pro Person 2) in IPS als Medienobjekt angelegt

Das Script zum Anzeigen des Bildes sieht so aus und ist als Hook hinterlegt (/hook/medien):

<?php
# ID Medienordner
$media = 15953;

// AUFRUF WEBHOOK
if($_IPS['SENDER'] == "WebHook") {
    $root = isset($_GET['root'])?$_GET['root']: $media;
    $name = isset($_GET['name'])?$_GET['name']: '';
    $type = isset($_GET['type'])?$_GET['type']: 'image/png'; // default: immage/png | oder audio/mpeg ...

    // AUFRUF WEBHOOK
    if($_IPS['SENDER'] == "WebHook") {
        if($name != '') {
            $mid = IPS_GetMediaIDByName($name, $root);
            if ($mid === false) {
                header("HTTP/1.0 404 Not Found");
                echo 'Medienobjekt mit Namen ="' . $name . '" konnte nicht in ' . $root . ' gefunden!';
            }
            else {
                header("Content-Type: " . $type);
                echo base64_decode(IPS_GetMediaContent($mid));
            }
        }
        else {
            header("HTTP/1.0 404 Not Found");
            echo 'Kein Medienobjekt angefordert!';
        }
    }
}

In meinem Script zur Steuerung der Anwesenheit gibt es dann eine Funktion die das Rendern für die neue Visu übernimmt …

// $greeting VariableID mit Profil ~HTMLBox, wird dann in Visu als Link hinterlegt
// $presence VariableID wer daheim ist (0-15, die Kombis aus "Name1, Name2, Name3, Name4")
// $medien CategoryID welche die Bilder der Personen enthält (<name>-hands & <name>-stop) 
function Greeting($greeting, $presence, $medien) 
{
    // Begrüßungstext
    $hallo = '';
    // Wie spät ist es?
    $hours = date('H');
    if($hours >= 3 && $hours < 12) {
          $hallo = 'Guten Morgen';
    } elseif($hours >= 12 && $hours < 18) {
          $hallo = 'Guten Tag';
    } elseif($hours >= 18 && $hours < 22) {
          $hallo = 'Guten Abend';
    } else { // if($hours >= 22 ||  $hours < 3)
          $hallo = 'Gute Nacht';
    }
    // Wer ist daheim?
    $value = GetValueFormatted($presence);
    $names = explode(',', $value);
    $count = count($names);
    $i = 1;
    foreach($names as &$name) {
        $name = trim($name);
        if (($count > 1) && ($i == $count)) {
            $hallo .= ' & '. $name;
        } else {
            $hallo .= ', '. $name;
        }
        $i++;
    }
    $hallo.= '!';
    IPS_SetName($greeting, $hallo);

    // Anwesenheitsbilder
    $html = '
    <style>
        body { margin: 0px; overflow: hidden;}
        .container { width: 100%;height: 100%; display: flex; justify-content: center; align-items: center; }
        .box {width: 25%; text-align: center; }
        .box img { width: 100%; height: 100%; object-fit: scale-down;}
    </style>
    <body>
        <div class="container">
            <div class="box"><img type="button" src="/hook/medien?root=' . $medien . '&name=heiko-' . (in_array( "Heiko" ,$names ) ? 'hands' : 'stop') . '" /></div>
            <div class="box"><img type="button" src="/hook/medien?root=' . $medien . '&name=anja-' . (in_array( "Anja" ,$names ) ? 'hands' : 'stop') . '" /></div>
            <div class="box"><img type="button" src="/hook/medien?root=' . $medien . '&name=pia-' . (in_array( "Pia" ,$names ) ? 'hands' : 'stop') . '" /></div>
            <div class="box"><img type="button" src="/hook/medien?root=' . $medien . '&name=luise-' . (in_array( "Luise" ,$names ) ? 'hands' : 'stop') . '" /></div>
        </div>
    </body>
    ';
    SetValueString($greeting, $html);
}

Bitteschön, aber nicht klagen wenn nicht 1:1 verwendbar :wink:

Gruß Heiko

1 „Gefällt mir“

Guten Morgen @da8ter und Danke für das Tolle Skript.

Es funktioniert mit der Erkennung von Handy bei mir. Nur manuell umschalten mit Klick auf PNG funktioniert leider nicht.

Und dann gibts noch 4 Webhooks mit den Namen die alle auf das gleiche Skript (Anwesenheit von Personen) zeigen. Ich denke da liegt der Fehler. Aber wie müsste das Skript für die Umschaltung aussehen?

Danke und lg

@ da8ter
Hallo. Darf, ich fragen wie du das „W“ in die Energie Kachel bekommen hast?


Ich hole die Werte per json Decoder und runde. Bei einem String kann er ja die Animation nicht mehr Rechnen. Link zu Doku funktioniert nicht.

Sg

Ich würde darauf tippen, dass es aus einem Profil genommen wird, das du bei deiner Variablen nicht gesetzt hast.

Hast Du Dir schon mal Profile angesehen? Denke das fehlt bei Deinem Wert einfach.
Cheers Seppm