Projektchen mit 59_Weather und MeinWetter-Floorplan

Begonnen von crazystone, 18 August 2013, 09:43:07

Vorheriges Thema - Nächstes Thema

crazystone

Hallo,

dieser Post ist mehr für alle, die auch "erste Gehversuche" machen wollen bzw. eben, falls einige unserer Cracks das lesen, um entsprechendes Feedback zu "wie schreibe ich ordentlichen Code für FHEM" zu bekommen. Alle verwendeten Inhalte stelle ich auf Nachfrage gern zur Verfügung.

ich habe mich an mein erstes kleines Perl-Projektchen gewagt und etwas im Original-Code von 59_Weather.pm gekupfert, bis ich soweit war, eigene Funktionen zu schreiben. Das Ergebnis:

(http://up.picr.de/15535998qy.jpg)

Nachdem ich mit WeatherAsHTML gescheitert war, den Hintergrund dynamisch nach aktueller Wettersituation auszuwählen und danach über diesen Hintergrund die Yahoo Weather Icons zu positionieren sowie meine eigene Windrose mit dynamisch positioniertem und skaliertem Windrichtungsanzeiger-Icon, hatte ich mich entschieden, das mit einem Floorplan zu realisieren, da der ja dann mit einem entsprechenden stylesheet versehen freie Positionierung in x, y und z (top, left, z:index)erlaubt.

Für die Windrose habe mir eine eigene Funktion geschrieben WindAsIcon, die eine TRX_WEATHER Instanz übernimmt. Die Ausgabe erfolgt als <div></div> mit absoluter Positionierung.


use constant WINDROSE_TOP  => 33;
use constant WINDROSE_LEFT => 370;
use constant WINDROSE_SIZE => 180;

sub
WindAsIcon($)
{
  my ($d) = @_;
  $d = "<none>" if(!$d);
  return "$d is not a TRX_WEATHER instance<br>"
        if(!$defs{$d} || $defs{$d}{TYPE} ne "TRX_WEATHER");

  #at max wind_speed of 11.1m/s * 3.6 = 40km/h select max size=180px, min size 40px = 8km/h
  my $wind_speed=ReadingsVal($d,"wind_speed","")*3.6; # wind m/s --> km/h
  my $wind_size=int($wind_speed/40*WINDROSE_SIZE);
  #clipping to min 40px and max WINDROSE_SIZE
  $wind_size = ($wind_size < 40) ? 40 : $wind_size;
  $wind_size = ($wind_size > WINDROSE_SIZE) ? WINDROSE_SIZE : $wind_size;
  #calculate top and left for WindIcon arrow
  my $wind_left=WINDROSE_LEFT+0.5*WINDROSE_SIZE-int($wind_size/2);
  my $wind_top=WINDROSE_TOP+0.5*WINDROSE_SIZE-int($wind_size/2);
  #cut wind_direction in deg from direction letters e.g. ENE and fill to three digits
  my $wind_head=180+int(ReadingsVal($d,"wind_dir",""));
  $wind_head = ($wind_head > 360) ? $wind_head-360 : $wind_head;
 
  #update site every 30sec
  my $ret = '<head><meta http-equiv="Refresh" content="30"></head>';
  #fix print compass rose
  $ret .= sprintf('<div style="position:absolute; top:%dpx; left:%dpx;">
                   <img src=/fhem/icons/weather/Windrose.png alt="Windrose" width="%d" height="%d"></div>',
  WINDROSE_TOP,WINDROSE_LEFT,WINDROSE_SIZE,WINDROSE_SIZE);  
  #print dynamically correctly scaled wind icon
  $ret .= sprintf ('<div style="position:absolute; top:%dpx; left:%dpx">
             <img src=/fhem/icons/weather/%03d.png alt="WindIcon" width="%d" height="%d">
</div>', $wind_top, $wind_left, $wind_head, $wind_size, $wind_size);

  return $ret;
}


Diese Funktion (und auch die folgende) habe ich in 59_Weather.pm ergänzt, so das nach dem Neuladen des Moduls mit zwei weblink entities alles erstellbar ist. Als zweite Funktion habe ich ein WeatherAsHTMLDiv geschrieben, das genau wie WeatherAsHTMLH bzw. V eine Weather Instanz als Argument nimmt:


sub
WeatherAsHtmlDiv($)
{
  my ($d) = @_;
  $d = "<none>" if(!$d);
  return "$d is not a Weather instance<br>"
        if(!$defs{$d} || $defs{$d}{TYPE} ne "Weather");
 
  my $bgn= sprintf ('/fhem/icons/weather/%s_bgn.png',ReadingsVal($d, "icon", ""));
     
  my $ret = sprintf('<div class="weather" style="background-image:url(%s); width:600px; height:441px;">', $bgn);
   
  for(my $i=1; $i<=5; $i++) {
  # retrieve weather icons
    $ret .= sprintf('<div class="weatherIcon"
                 style="position:absolute; top:225px; left:%dpx; width:87px; height:75px;">%s</div>',
 50+100*($i-1),WeatherIconIMGTag(ReadingsVal($d, "fc${i}_icon", "")));
  # retrieve day_of_week  
    $ret .= sprintf('<div class="weatherDay"
                 style="position:absolute; top:295px; left:%dpx; width:87px; height:20px; color:#CCCCCC;text-shadow:black 2px 1px 1px;">%s</div>',
                 65+100*($i-1),ReadingsVal($d,"fc${i}_day_of_week", ""));
  # retrieve min...max temperature
    $ret .= sprintf('<div class="weatherTemp"
                 style="position:absolute; top:320px; left:%dpx; width:87px; height:20px; color:#CCCCCC;text-shadow:black 2px 1px 1px;">%s°C...%s°C</div>',
 65+100*($i-1),ReadingsVal($d, "fc${i}_low_c", ""), ReadingsVal($d, "fc${i}_high_c", ""));
  # retrieve weather condition
    $ret .= sprintf('<div class="weatherCondition"
 style="position:absolute; top:340px; left:%dpx; width:87px; height:20px; color:#CCCCCC;text-shadow:black 2px 1px 1px;">%s</div>',
 65+100*($i-1),ReadingsVal($d,"fc${i}_condition", ""));
  }

  $ret .= "</div>";

  return $ret;
}


Auch hier habe ich mit fest positionierten Elementen gearbeitet, was ja eben nur in <div></div> geht und nicht in <table></table>. Das hat natürlich den Nachteil, dass in den Unsorted bzw. Everything room die Anzeige verwürfelt wird. Ich habe aber keine andere Variante gefunden, um dann im Floorplan das zu erreichen, was ich wollte.

Das letzte war natürlich dann noch das Text-Overlay mit den anderen Raum-Instanzen. Das ist natürlich für jeden hier anders, deswegen macht es auch glaube ich wenig Sinn den straight-forward Code hier zu posten. Er macht auch nichts weiter, als per html z-index:2 den Text der ReadingsVal über position:absolute über das Bild zu legen.

Für mich ist das alles jetzt eine Lösung. Über die Flooplan Definition muss ich jetzt nur noch


define WetterVorhersage Weather <code> <update> <language>
define weblink_WetterVorhersage weblink htmlCode { WeatherAsHTMLDiv ("WetterVorhersage") }
#WindDir is autocreated TRX_WEATHER, used readings are "wind_speed" and "wind_dir"
define weblink_WindDirIcon weblink htmlCode { WindAsIcon ("WindDir") }


als attr zu einem Floorplan hinzufügen (weblink_WetterVorhersage x:0 y:160; weblink_WindDirIcon x:0 y:0).

Allerdings verstehe ich, dass das wohl keine universelle Herangehensweise an das Thema ist. Immerhin musste ich ja keine allgemeinen stylesheets mehr modifizieren (das hatte ich zu Beginn) und habe letztendlich auch nur neue Funktionen zu einem Modul hinzugefügt. Dieses muss jetzt natürlich nach jedem Update wieder migriert werden. Ich hätte wohl besser ein eigenes Modul geschrieben? Wie stelle ich sicher, dass die dann auch geladen werden? Gibt es da Richtlinien, wie solche Module zu benennen sind? Gibt es ein automatisch geladenes Modul, das eigene Funktionen enthalten sollte?

Freue mich auf Euer Feedback! Wenn jemand die Hintergründe, die WindDirIcons (360 individuell verschiedene, Photoshop Script :-) oder die passende Windrose braucht, bitte einfach melden, dann hänge ich sie hier rein.

Viele Grüße
Thorsten

crazystone

...achja, noch eine Frage:

Dankbar wäre ich auch für einen Tipp, wie die Icon-Pfade universell kodiert werden können, denn eine Hart-Kodierung ist wirklich unschön...

Gruß

Klaus Rubik

Hallo Torsten,

konntest du deine am Ende des ersten Threat gemachten Anmerkungen inzwischen umsetzten, b.z.w. gibt es dazu ein Update?

VG

Klaus
FHEM 6.0 auf RPI4 mit CUL868, AEOTEC, RFXTRX 433
CUL_WS  : S300TH              FHT         : FHT80B, FHT80TF
HMS        : HMS100-TF         FBDECT   : DECT!200, FRITZ!Powerline 546E
FS20       : FS20DI10, FS20ST, FS20WS1, FS20DU-2, FS20 FMS

RoBra81

Hallo, klingt sehr interessant - ich hätte auch Interesse an einem Paket zum Installieren :-)

FNIK

Hallo crazystone,
Ich bin absoluter Neuling und habe mit fhem noch sehr wenig Erfahrung.
Deine Version der Wettervorhersage gefällt mir bis jetzt am Besten und ich habe auch schon versucht den Code ein zu binden.
Allerdings kam wie erwartet der Fehlerteufel und ich sehe bei weitem nicht dass was ich eigentlich sehen wollte.
Ich bin wie folgt vor gegangen:

1. 59_Weather gesichert und eine Kopie mit den beschriebenen 2 Sub's erstellt.
2. Datei auf der FB getauscht und neu gestartet
3. fhem.cfg angepasst wie beschrieben:

#Wetter
define WetterVorhersage Weather 653782 900 de
define weblink_WetterVorhersage weblink htmlCode { WeatherAsHTMLDiv ("WetterVorhersage") }
#WindDir is autocreated TRX_WEATHER, used readings are "wind_speed" and "wind_dir"
define weblink_WindDirIcon weblink htmlCode { WindAsIcon ("WindDir") }[/size][/color][/i]
#
4. im Floorplan folgendes eingefügt:
attr weblink_WetterVorhersage fp_01_Wetter 100,160
attr weblink_WindDirIcon fp_01_Wetter 0,300

Als Ergebnis sehen ich nur die beiden Fehler:

Undefined subroutine &main::WeatherAsHTMLDiv called at (eval 1256) line 1.
WindDir is not a TRX_WEATHER instance

Hast DU einen Hinweis für mich?
LG FNIK

mele

Geht es hier noch weiter???

Ich habe die 59_Weather.pm ergänzt, die Definitionen gemacht und erhalte:

Undefined subroutine &main::WeatherAsHTMLDiv called at (eval 2027) line 1. WindDir is not a TRX_WEATHER instance

Die Wetter-Lösung sieht wirklich sehr schick aus.

Aus meiner Sicht wäre es eine Schande, wenn diese verschwindet.

VG
Manuel
FHEM auf NUC/Proxmox (Rpi 2 / Rpi Zero W mit FHEM2FHEM, RFHEM)
Homematic/LaCrosse/PCA301/Shelly, Rollladen, Batterieaktor + Relais zur Schaltung Garagentor (Promatic 2), Xiaomi FlowerSens, Bewässerungssteuerung Garten und Gewächshaus, Weatherman und Landroid

betateilchen

Zitat von: mele am 02 März 2015, 22:13:37
Undefined subroutine &main::WeatherAsHTMLDiv

Die Funktion heisst ja in der Vorlage auch nicht so, sondern WeatherAsHtmlDiv

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rasti


ich wollte mein fhem auch aufhübschen mit der Darstellung,
bekomme es aber nicht ans laufen.

Ich habe die 59_Weather.pm mit die obigen Routinen ergänzt,
und fhem.cfg wie untenstehend. Ich bekomme aber sonst nichts angezeigt.
Der Rahmen wird zwar größer dargestellt aber sonst wie vorher..... Ich vermute,
dass die Bildchen wie Windrose.png usw. da fehlen ???
Muss ich diese noch auf den fhem-Server kopieren oder sind die standardmäßig schon da ?
Oder woran kann es sonst liegen ?

Gruss

Ralf

###########################
####   Wetter      ########
###########################
###########################

# ————– Wetterdaten erfassen ————-
define MeinWetter Weather 641249 3600 de
attr MeinWetter alias Aktuelles Wetter
attr MeinWetter group Wetter
attr MeinWetter room Wettervorhersage

# — Logfile alle Wetter Daten —
define FileLog_MeinWetter FileLog ./log/meinwetter-%Y-%m.log MeinWetter
attr FileLog_MeinWetter logtype text
#attr FileLog_MeinWetter room Wettervorhersage


# — Wetter Icons hinzufügen —
define weblink_meinwetter weblink htmlCode {WeatherAsHtmlDiv("MeinWetter")}
define weblink_WindDirIcon weblink htmlCode { WindAsIcon ("WindDir") }[/size][/color][/i]
attr weblink_meinwetter group Wetter
attr weblink_meinwetter room Wettervorhersage
attr weblink_meinwetter sortby 1

# Satellitenbild
define Satellitenbild weblink image http://img.wetterkontor.de/sat/satanim_europa_450.gif
attr Satellitenbild group Wetter
attr Satellitenbild htmlattr width="500" height="220"
attr Satellitenbild room Wettervorhersage
attr Satellitenbild sortby 2