Map Widget reloaded - Neue Version des Map Widgets

Begonnen von eki, 05 Oktober 2018, 16:04:19

Vorheriges Thema - Nächstes Thema

Stelaku

#135
Hallo eki

Jup hab mit den dummy schon herumgespielt und etliche male set point mit x y werten gefüttert ein riesen langes Reading für heatmap habe ich auch bekommen. Was sich auch jedesmal etwas ändert wenn ich set point mache.

Gruß

Stephan

EDIT: Ich habe gestern und heute herumgespielt und die Datei leaflet-heat.js auf verschiedenen Wegen in das lib Verzeichnis kopiert mit dem Ergebnis das die Fehlermedlung sich etwas verändert hat.
         Ich habe mal einen sreenshot angehängt was beim öffnen der Seite alles für Meldungen nacheinander angezeigt werden.

eki

#136
Das Problem liegt in Deiner HTML Definition. Du gibst für die äußeren divs keine Höhe und Breite an, die inneren rechnen daraus eine Höhe und Breite aus, die dann auch wieder null wird und das führt dann zu dem Fehler (wahrscheinlich, weil das heatmap script versucht, daraus irgendein Array zu bauen).
Wenn Du folgendes änderst, dann sollte es klappen:


<body>
<div class="gridster" style="height: 100%">
<ul style="height: 100%">
  <div class="cell" style="height: 100%">
  <div id="Test1"


Ach ja, damit das Auto zu sehen ist, muss Du noch folgende Zeile in den Header packen:


<link rel="stylesheet" href="./lib/font-awesome.min.css" />

Stelaku

Hallo eki

Vielen dank für Deine Hilfe. Jetz bekomme ich was angezeigt.
Dann kann ich mich daran machen zu verstehen wie ich meinen Grundriss auch auf die Richtige Position bekommen.
Im Moment saugt Martha laut Anzeige bei unserem Bahnhof  :D. Hoffentlich kommt sie nicht unter die Räder  ;D.

Viele Grüsse

Stephan

eki

Da Ihr ja schon mit Grundrissen auf Basis von Polygonen gearbeitet habt, könntet Ihr auch ein geojson file mit den Grundrisspolygonen als Darstellung verwenden. Dazu gibt es einige Beispiele weiter oben.

eki

#139
Angehängt, hier noch mal ein Update. Folgende Dinge sind geändert:


  • Heatmaps gehen jetzt auch mit Google Maps
  • Die Overlays und die Heatmaps können mit einer Opacity versehen werden und sind dann entsprechend teilweise durchsichtig.
  • Die Farben für die Heatmap können angepasst werden. Dazu kann ein Array von Farbwerten (mit Opacity) angegeben werden das dann auf die verschiedenen Gewichteten Punkte angewendet wird.
  • Die größe der Punkte (radius) kann für die Heatmap eingestellt werden
  • Für Heatmap und Overlay können min und max Zoom Level angegeben werden um diese Layer nur bei bestimmten Zoom Leveln zu sehen.

Format für Overlay:
data-overlay="<url>,<lat-nw>,<lng-nw>,<lat-se>,<lng-se>,<opacity>,<zoom-min>,<zoom-max>"

Format für Heatmap:
data-heatmap="<reading>,<opacity>,<zoom-min>,<zoom-max>,<radius>"

Format für Heatmap Farbgradient:
data-heatmap_gradient='[<color-1>,<color-2>,...,<color-n>]'
Farben können als "rgba(red,green,blue,opacity)" (wobei red,green,blue Werte zwischen 0 and 255 sind und opacity zwischen 0 und 1 liegen kann) oder als #rrggbb (rr,gg,bb als zweistellige hex Werte) angegeben werden (Länge des Arrays und damit Anzahl der Farben ist beliebig).

Beispiel:

<div id="Test1"
style="height: calc(100% - 1.6em); width:100%"
data-type="maps"
data-map_type="OSM"
data-showdetails="false"
data-device="testVCRobot"
data-traffic="true"
data-mapgroup="2"
data-overlay="../images/fp_Dachgeschoss_turned.png,48.831014929044535, 9.075971602274373,48.83088043906973, 9.076093642600654,0.5,19,25"
data-heatmap="heatmap,0.5,19,25,25"
data-heatmap_gradient='["rgba(255,255,255,0)","rgba(128,128,128,0.5)","rgba(0,0,0,1)"]'
data-center="48.830989, 9.076057"
data-scrollgroup="2"
data-maxzoom="25"
data-zoom="20"
data-icon="no-icon"
data-label=" "
data-stroke="#33ddff,5,60">
</div>

Stelaku

Hallo eki

Hab jetzt auch mal mit Deiner neuen Version herumgetestet. Mit den Punkten habe ich noch nicht ganz verstanden wozu die gut sein sollen.
Eine ununterbrochene Linie auf der zu sehen ist wo der Sauger war finde ich vollkommen ausreichend. Hab mal den Parameter
data-heatmap="heatmap,0.5,20,25,25
auf
data-heatmap="heatmap,0.5,20,25,1
gestellt


damit sind die Punkte nicht mehr zu sehen sind,
und das Limit für die Anzahl der Polygone im dummy auf 10000000 gestellt.
Jetzt wird eine Linie hinter den Auto Symbol hergezogen.

So richtig mit den zoom Einstellungen komme ich nicht klar.
Rufe ich die Map mit den im Beispiel eingestellten Werten auf wird mir die Karte noch sehr klein angezeigt.
Klicke ich jetzt zweimal auf das plus Symbol passt es.


Einstellungen für id="Test1"

data-overlay="../images/fp_Grundriss-1.png,54.47915, 9.321220,54.47904, 9.321605,1,20,25"
data-heatmap="heatmap,0.5,20,25,1"
data-zoom="20"

Einstellungen für id=Test2

data-zoom="20"


Nun hab ich mir gedacht stelle ich doch einfach alle Werte für min zoom auf 22.
Klappt leider nicht dann bekomme ich eine Fehlermeldung siehe Bild zoom22test.jpg.

Danach habe ich noch wild alle möglichen kombinationen ausprobiert aber keine hat so richtig geklappt.

Ist es eigentlich auch noch möglich die polygon linie schmaler zu bekommen ?

Viele Grüsse

Stephan









eki

#141
Zitat
Hab jetzt auch mal mit Deiner neuen Version herumgetestet. Mit den Punkten habe ich noch nicht ganz verstanden wozu die gut sein sollen.
Eine ununterbrochene Linie auf der zu sehen ist wo der Sauger war finde ich vollkommen ausreichend. Hab mal den Parameter
Die Punkte zeigen Dir, wie häufig der Staubsauger an welcher Stelle war. Je dichter und roter, desto häufiger wurde diese Position angefahren. Wenn Du die Heatmap nicht willst, dann lass die data-heatmap Zeile weg, anstatt die Punktgröße auf 1 zu setzen (lustige Idee ???).

Zum Zoom: Die Karte zoomt in Stufen. 0 zeigt die ganze Welt 20 einzelne Häuser, je höher die Zahl, desto kleiner wird das dargestellt Gebiet und desto größer und mehr werden die Einzelheiten. Mit data-zoom stellst Du ein, mit welcher initialen Zoomstufe das Widget startet. Mit minzoom und maxzoom stellst Du für jeden Layer (Heatmap, Overlay) den Zoombereichein, bei dem der Layer zu sehen ist (wenn also data-zoom=,,20" ist und minzoom für den Overlay Layer auf 22, dann wird das Overlay Bild am Anfang nicht angezeigt, wenn du dann 2 mal plus drückst wird der Zoom auf 22 gesetzt und das Bild erscheint). Das Gleiche gilt unabhängig für den Heatmap Layer.

Die Dicke der Linie kannst Du über den Parameter data-stroke einstellen (der 2. Wert gibt die Dicke in Pixeln an). Wenn Du das Auto größer als die Linie haben willst, musst Du, wie in meinem Beispiel weiter oben 2 Map Divs definieren und unterschiedliche Stroke Werte verwenden.

Stelaku

#142
Hallo eki

Vielen dank für Deine Erklärung. Für mich als kompletter FTUI  Neuling ist das Gold wert. Ich habe das dann auch gleich erfolgreich ausprobiert.

Zitatdann lass die data-heatmap Zeile weg, anstatt die Punktgröße auf 1 zu setzen (lustige Idee ???).

Als unwissender kommt man auf die verücktesten Idee ein Problem zu umgehen  :) . Hab die beiden Zeilen jetzt ohne Probleme gelöscht.


data-heatmap="heatmap,0.5,19,25,25"
data-heatmap_gradient='["rgba(255,255,255,0)","rgba(128,128,128,0.5)","rgba(0,0,0,1)"]'


Auch die data strocke hab ich jetzt dank Deiner Erklärung besser verstanden und gleich mit umgesetzt.

Das zoom Problem ist jetzt auch keins mehr. Bin immer wieder darüber gestolpert weil ich beide definitionen für data-zoom="20" geändert habe.
Es funktioniert aber nur wenn die letzte z.b 23 hat und die erste muss dann einen kleineren oder grösseren Wert haben als 23. Sonst zoom das widgert immer nur auf 20.
Nach mehrfachen ausprobieren funktioniert es jetzt wie ich es haben möchte.

Morgen lasse ich Martha wieder auf das ganze Haus los und wenn Sie die Karte schön bemahlt hat werde ich das hier mal posten.

Viele Grüsse

Stephan



curt

Hallo @eki und @Stelaku und allerseits,

aus irgend einem Grund bekomme ich keine Benachrichtigungen für diesen Thread, obwohl das eingeschaltet ist. Danke @eki für die Benachrichtigung und Deine PN.

Ich habe das gerade eben durchgelesen - und sehe nicht durch. :(
Stephan, wärst Du bitte so freundlich, eine Anleitung mit Deinem Installationsstand zu geben (wie Du es schon mal gemacht hast)? Das wäre toll - ich muss ja nicht unbedingt alle Deine Fehler nachmachen ... und eki könnte das gleich in die Wiki-Doku übernehmen. Also falls er mag.

eki, was vielleicht schon geht, ich frage einfach mal:
Es gibt ein Reading run_state. Da sehe ich textlich ob er geladen wird, saugt, der Akku runter ist und vor allem ob er sich unter dem Sofa festgefahren hat. Da wäre doch eine sehr schöne Idee, dass ich in meinem Palast gleich sehe, wo ich Putzi eigentlich suchen muss, wenn der kleine Gnubbel rot dargestellt wird.
Ginge sowas denn ohne großen Aufwand?

RPI 4 - Jeelink HomeMatic Z-Wave

eki

Es ist eingentlich nicht so schwer. Grundsätzlich gibt es 2 Möglichkeiten der Darstellung:

1. Linie, die den Weg auf der Karte anzeigt
Dazu muss ein Reading "polygon" erzeugt werden, das die letzten Aufenthaltspunkte in Geokoordinaten enthält (kann man, wie in meinem Beipiel gezeigt, als userReading aus den aktuellen Punkten und einem als userAttribut gesetzten Referenzpunkt generieren).
2. Heatmap (farbliche Kodierung der geographischen Aufenthaltshäufigkeit, also je häufiger der Staubsauger an einer Stelle war desto farbiger)
Dazu muss ein Reading "heatmap" erzeugt werden, das Punkte und die zughörige Häufigkeit enthält. Geht genauso wie das Polygon über ein userReading, wie in meinem Beispiel oben.

Zusätzlich kann man noch ein Bild z.B. des Grundrisses auf die Karte legen (data-overlay) oder den Grundriss als geojson File mit einem Polygon hinterlegen, und den letzten Punkt z.B. als icon darstellen (dazu braucht es die readings "longitude" und "latitude", die ich ebenfalls als userReadings in meinem Beispiel habe).

Das Einfärben oder Ändern des Icons auf Grundlage von Reading Inhalten geht bisher noch nicht, ist aber grundsätzlich einbaubar. Ich mache mich da bei Gelegenheit mal dran.

Stelaku

#145
Hallo alle zusammen

Ich versuche mal eine kleine Anleitung zu schreiben wie ich bis zu den heutigen stand gekommen bin.

1. aktuelles Widget_maps.js ins Verzeichnis /opt/fhem/www/tablet/js kopieren derzeit aus post #157

2. Eine neue html datei im Verzeichnis /opt/fhem/www/tablet erstellt. Bei mir habe ich Sie map.html genannt. Der Aufruf geht dann über http://<serverip>:8083/fhem/ftui/map.html

3. dann den Quelltext in die neue Datei map.html einfügen.

<!DOCTYPE html>
<html>
<head>
    <!--
     /* FHEM tablet ui */
     /*
     * UI builder framework for FHEM
     *
     * Version: 2.2.*
     * URL: https://github.com/knowthelist/fhem-tablet-ui
     *
     * Copyright (c) 2015-2016 Mario Stephan <mstephan@shared-files.de>
     * Under MIT License (http://www.opensource.org/licenses/mit-license.php)
     *
     * !!!! Evaluation version - run only in a staging enviroment !!!!
     *
     * - create a new folder named 'tablet_eval' in /<fhem-path>/www
     * - copy all files incl. sub folders into /<fhem-path>/www/tablet_eval
     * - add 'define TABLETUIEVAL HTTPSRV ftui_eval ./www/tablet_eval Tablet-EVAL' in fhem.cfg
     * - Tadaaa! A new fhem ui in http://<fhem-url>:8083/fhem/tablet_eval/
     *
     * Create a Demo Device in FHEM
     * define ftuitest dummy
     */
    -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <meta name="widget_base_width" content="74">
    <meta name="widget_base_height" content="71">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="gridster_disable" content="1">
    <meta name="longpoll" content="1"> <!-- 1=longpoll;0=shortpoll every 30sec -->
    <meta name="debug" content="2"> <!-- verbose level 1-6 = output to console;0 = not output -->
    <meta http-equiv="Cache-Control" content="no-store" />


    <script src="js/fhem-tablet-ui.js" defer></script>

<link rel="stylesheet" href="./lib/font-awesome.min.css" />

    <title>Martha Karte</title>
</head>
<body>
<div class="gridster" style="height: 100%">
<ul style="height: 100%">
  <div class="cell" style="height: 100%">
  <div id="Test1"
  style="height: calc(100% - 1.6em); width:100%"
  data-type="maps"
  data-map_type="OSM"
  data-showdetails="false"
  data-device="testVCRobot"
  data-traffic="false"
  data-mapgroup="2"
  data-overlay="../images/default/fp_Grundriss.png,54.6351533, 8.358227,54.6350360, 8.358580,1,0,25"
  data-center="54.6351000, 8.35836945128062"
  data-scrollgroup="2"
  data-maxzoom="25"
  data-zoom="20"
  data-icon="no-icon"
  data-label=" "
  data-stroke="#FF0000,3,60">
  </div>
  <div id="Test2"
  style="height: calc(100% - 1.6em); width:100%"
  data-type="maps"
  data-map_type="OSM"
  data-polygon="none"
  data-showdetails="false"
  data-get="longitude"
  data-device="testVCRobot"
  data-mapgroup="2"
  data-center="54.6351000, 8.35836945128062"
  data-scrollgroup="2"
  data-maxzoom="25"
  data-zoom="22"
  data-icon="no-icon"
  data-readingstyles='[
"voll:fa-home,,#000000,25,60",
"clean:fa-circle,,#0c00a4,25,60",
"zwischenl:fa-circle,,#ff0000,25,60",
"laden:fa-home,,#ff0000,25,60"
]'
data-stylereading="state">

               
  </div>
  </div>

</ul>
</div>
</body>
</html>


data-readingstyles=
je nach reading vom dummy testVCRobot state wird das Icon bestimmt

data-stylereading="state"
gibt an welches reading von dummy testVCRobot für data-readingstyles ausgewertet wird hier im Beispiel ist es state




4. Das dummy Device aus eki seinem Beispiel in Deinem Fhem importieren. Anbei mein Dummy mit den heutigen polygonen dann solltest Du auch schon ein paar linien sehen.
   hänge ich mal als .txt mit an. Die vielen polygone sprengen sonnst die 100 Zeilen :-).

5. Eine Verpnüpfung zwischen XiaomiDevices zum Dummy herstellen. Bei mir habe ich ein DOIF welches auf das reading pos_x_y regiert und dieses dann in point vom testVCRobot dummy schreibt.
   und ein zweites DOIF welches auf state vom XiaomiDevices horcht und dann dementsprechend den state vom testVCRobot  dummy setzt.


defmod Martha_position DOIF ([Martha_1:pos_x_y])\
(setreading testVCRobot point [Martha_1:pos_x_y])
attr Martha_position do always


defmod run_state DOIF ([Martha_1] eq "Fully charged")\
(set testVCRobot voll)\
\
DOELSEIF\
([Martha_1] eq "Charging")\
(\
set testVCRobot laden\
)\
(\
{fhem("setreading testVCRobot point -1.4,1.5")}\
)\
\
DOELSEIF\
([Martha_1] =~ "recharge")\
(\
set testVCRobot zwischenl\
)\
\
DOELSEIF\
([Martha_1] =~ "cleaning")\
(set testVCRobot clean)\
\
\

attr run_state room KARTE



6. Ich lasse über ein at jeden tag die reading für heatmap und polygon löschen. Damit jeden Tag ein neuer Verlauf zu sehen ist.


defmod Karte_loeschen at *23:00 \
deletereading testVCRobot polygon;;\
deletereading testVCRobot heatmap
attr Karte_loeschen room KARTE

Was ich beobachtet habe ist das nach dem löschen der beiden readings der Reinigungsverlauf beim Aufruf von der map.html Seite immer noch zu sehen ist.
erst wenn das Dummy testVCRobot einen neuen point Wert bekommt wird der letzte Verlauf nicht mehr angezeigt. Dieses Verhalten finde ich sehr gut.
Eine möglichkeit die ich aber noch nicht ausgetestet habe wäre das man das reading polygon nicht löscht, sonder einfach mit den letzten Positionstdaten vom Sauger setzt.

7. Jetzt wird es frickelig. die Längen und Breitengrade passen ja noch nicht zu Deinen Heimatkoordinaten. Unter Googelmaps habe ich mir meine Längen und Breitengrade herausgesucht.

8. Ermittelte Längen und Breitengrad im dummy testVCRobot mit dem attr referencepoint eingeben ACHTUNG das attr will erst den Längengrad und dann den Breitengrad. Das ist dann im
    Quelltext der map.html immer andersherum.

9. Im Quelltext der map.html data-center="Breitengrad, Längengrad" mit Deinen ermittelten Werten füttern.

10. Über data-overlay="../images/default/fp_Grundriss.png,BreitengradLinkeEcke, LängengradLinkeEcke,BreitengradRechteEcke, LängengradRechteEcke,1,20,25" legst Du, wenn vorhanden den Pfad fest,
      wo sich Dein Eigener Grundriss befindet. Die beiden Breiten und Längengrad angaben bilden die Eckpunkte für Deinen Grundriss.
      Mit diesen Werten habe ich dann so lange herumgespielt bis der Reinigungs Verlauf von Martha genau auf der Karte war.

11. Sich freuen das der Sauger auf der Karte seine Bahnen zieht :-) .

Ich hoffe ich habe nichts vergessen.

Doch noch was vergessen. Ein ganz großes Dankeschön an eki, ohne Deine arbeit hätte ich das nie hinbekommen.


Gruß

Stephan


eki

So, jetzt gibt es nochmal ein Update mit dem man nun auch die Darstellung von Icons auf Basis von Reading Inhalten anpassen kann. Dazu gibe es 2 neue Parameter:

1. data-readingstyles: Hier kann ein Array angegeben werden. Die einzelnen Werte des Arrays enthalten <Wert>:<Label>,<Icon>,<Farbe>,<Größe>,<Transparenz>. Für Wert kann auch eine regular Expression angegeben werden.
2. data-stylereading: Hier kann der Name des Readings angegeben werden, das für die Einfärbung verwendet werden soll. Wird nichts angegeben, ist der Default "STATE" (also das Internal)

Ein Beispiel (ist state 'on' oder 'On' so wird ein Autosymbol in blau halb transparent gemalt, ist state 'off' oder 'Off' wird ein Icon mit Haus auf einem runden Verkehrsschild in rot gemalt):

data-readingstyles='["on|On:fa-car,,rgba(0,0,255,0.5),20,60","off|Off:fa-home,../images/blitzer2.png,#ff0000,30,60"]'
data-stylereading="state"

curt

@Stelaku
Ich habe Deine Anleitung 1:1 nachvollzogen, nichts geändert (ok, tomtom auch nicht angepasst). Das geht nicht - kann vermutlich nicht gehen.

Ich vermute, dass da irgend ein Schritt fehlt: Das Dummy Device weiß doch gar nicht, dass bei mir Putzi wienert ... irgendwie muss ja diese Datenverknüpfung gemacht werden?
RPI 4 - Jeelink HomeMatic Z-Wave

Stelaku

Hallo curt

Du hast recht. Ich habe die Verknüpfung von Marha zu testVCRobot  vergessen. Ich habe da ein DOIF welches bei Änderung des reading pos_x_y bei Martha reagiert und pos_x_y ins
dummy testVCRobot  schreibt.

Anbei eine raw Definition.


defmod Martha_position DOIF ([Martha_1:pos_x_y])\
(setreading testVCRobot point [Martha_1:pos_x_y])
attr Martha_position do always


Nur noch auf putzi umschreiben und es sollte funktionieren. ich werde das dann später noch in den weiter oben stehen post mit einfügen.

Gruß

Stephan

eki

Zitat von: curt am 05 Februar 2021, 01:07:28
@Stelaku
Ich habe Deine Anleitung 1:1 nachvollzogen, nichts geändert (ok, tomtom auch nicht angepasst). Das geht nicht - kann vermutlich nicht gehen.


Wenn Du data-traffic="false" setzt, sollte es auch ohne tomtom Key gehen (der wird nur für die Darstellung der Verkehrssituation gebraucht).