Fahrzeugstandortüberwachung mit statisch definierten Standorten und Umkreis

Begonnen von ReneR1986, 10 Januar 2025, 16:33:02

Vorheriges Thema - Nächstes Thema

ReneR1986

Ich wollte unter Angabe definierter Standorte wie z.B. ZuHause, Arbeit, etc. und eines Radius in Km als Ergebnis eine Meldung bzw. Readings, ob meine Autos sich noch innerhalb des Radius befinden und wie weit sie von den definierten Standorten entfernt sind.

Warum? Keine Ahnung... Vielleicht fällt mir noch was ein 😊

Das ganze ist recht statisch (sowohl im Dummy als auch in der Funktion), scheint aber zu funktionieren, es sind aber sicher Anpassungen notwendig für weitere Verwendung.
-   Es gibt einen Dummy über den man die gewünschten Werte eingeben kann --> Sollte angepasst werden
-   Eine Funktion die das ganze berechnet und in Readings des Dummies zurückschreibt --> Muss angepasst werden (%locations,ReadingsVal,etc.)
-   Und natürlich Fahrzeuge, die die aktuelle Position (Längen- und Breitengrad) bereitstellen

Dummy:
defmod dummy_Standortueberwachung_Autos dummy
attr dummy_Standortueberwachung_Autos group Tracking Autos
attr dummy_Standortueberwachung_Autos readingList ZuUeberwachenderStandortID4 GesetzterUmkreisID4 ZuUeberwachenderStandortEUp GesetzterUmkreisEUp
attr dummy_Standortueberwachung_Autos room Tracking
attr dummy_Standortueberwachung_Autos setList ZuUeberwachenderStandortID4:ZuHause,ReneArbeit GesetzterUmkreisID4:5,10,15 ZuUeberwachenderStandortEUp:ZuHause,ReneArbeit GesetzterUmkreisEUp:5,10,15

Funktion (in 99_myUtils.pm):
sub ueberwache_standort {
    my ($target_location_eup, $target_location_id4, $radius_eup, $radius_id4) = @_;

    # Koordinaten für bekannte Orte
    my %locations = (
        'ZuHause' => [X.XX, X.XX],
        'ReneArbeit' => [X.XX, X.XX],
    );

    # Aktuelle Standorte der Fahrzeuge aus FHEM-Readings holen
    my ($current_lat_eup, $current_lon_eup) = split(",", ReadingsVal('MQTT_eUP','GoogleMapsCenter', '0'));
    my ($current_lat_id4, $current_lon_id4) = split(",", ReadingsVal('MQTT_ID4','GoogleMapsCenter', '0'));

    # Helper-Funktion zur Berechnung der Entfernung
    sub calculate_distance {
        my ($current_lat, $current_lon, $target_lat, $target_lon, $radius_km) = @_;

        # Radius der Erde in Kilometern
        my $R = 6371;

        # Umrechnung von Grad in Radiant
        my $pi = 3.141592653589793;
        my $phi1 = $current_lat * ($pi / 180);
        my $phi2 = $target_lat * ($pi / 180);
        my $delta_phi = ($target_lat - $current_lat) * ($pi / 180);
        my $delta_lambda = ($target_lon - $current_lon) * ($pi / 180);

        # Haversine-Formel zur Berechnung der Entfernung
        my $a = sin($delta_phi / 2)**2 + cos($phi1) * cos($phi2) * sin($delta_lambda / 2)**2;
        my $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
        my $distance_km = $R * $c;

        # Überprüfung, ob der aktuelle Standort innerhalb des Radius liegt
        my $is_within_radius = $distance_km <= $radius_km ? 'Ja' : 'Nein';

        return ($distance_km, $is_within_radius);
    }

    # Zielkoordinaten bzw. Koordinaten um die der Radius gezogen wird für EUp
    if (!exists $locations{$target_location_eup}) {
        fhem("setreading dummy_Standortueberwachung_Autos Fehler Unbekannter Standort: $target_location_eup");
        return;
    }
    my ($target_lat_eup, $target_lon_eup) = @{$locations{$target_location_eup}};

    # Zielkoordinaten bzw. Koordinaten um die der Radius gezogen wird für ID4
    if (!exists $locations{$target_location_id4}) {
        fhem("setreading dummy_Standortueberwachung_Autos Fehler Unbekannter Standort: $target_location_id4");
        return;
    }
    my ($target_lat_id4, $target_lon_id4) = @{$locations{$target_location_id4}};

    # Berechnung für EUp
    my ($distance_eup, $is_within_radius_eup) = calculate_distance($current_lat_eup, $current_lon_eup, $target_lat_eup, $target_lon_eup, $radius_eup);
    fhem("setreading dummy_Standortueberwachung_Autos EntfernungVonEUp " . sprintf("%.2f", $distance_eup));
    fhem("setreading dummy_Standortueberwachung_Autos InnerhalbRadiusEUp $is_within_radius_eup");

    # Berechnung für ID4
    my ($distance_id4, $is_within_radius_id4) = calculate_distance($current_lat_id4, $current_lon_id4, $target_lat_id4, $target_lon_id4, $radius_id4);
    fhem("setreading dummy_Standortueberwachung_Autos EntfernungVonID4 " . sprintf("%.2f", $distance_id4));
    fhem("setreading dummy_Standortueberwachung_Autos InnerhalbRadiusID4 $is_within_radius_id4");
}

Der Funktionsaufruf:
{ueberwache_standort(ReadingsVal("dummy_Standortueberwachung_Autos", "ZuUeberwachenderStandortEUp",""),ReadingsVal("dummy_Standortueberwachung_Autos", "ZuUeberwachenderStandortID4",""),ReadingsVal("dummy_Standortueberwachung_Autos", "GesetzterUmkreisEUp",""),ReadingsVal("dummy_Standortueberwachung_Autos", "GesetzterUmkreisID4",""))}