fhemweb.js Umbau

Begonnen von rudolfkoenig, 31 Dezember 2014, 16:45:43

Vorheriges Thema - Nächstes Thema

rudolfkoenig

Ich habe fhemweb.js umgebaut, damit man die widgets wie slider, time, etc. nicht doppelt (einmal in perl, einmal in JavaScript) implementieren muss.
Jquery & jquery-ui sind jetzt immer dabei, longpoll handling und loadScript habe ich auch verbessert.

Ein widget wird implementiert, indem man in www/pgm2/fhemweb_XXX.js eine (oder mehrere) createFn's definiert, Beispiele (textfield, select, slider, etc) sind in fhemweb.js zu sehen. Die bisherigen Methoden um Widgets anzulegen (d.h. in perl) sind zwar auch noch funktional, aber unerwuenscht.
createFn wird mit einer Reihe von Parametern aufgerufen, die nicht alle gefuellt sind, jenachdem ob man sich auf der Detailseite befindet und per set/get/attr die Widgets aufruft, oder diese wegen webCmd in der Raum-Ansicht dargestellt sind.

Ich habe es mit fhem.cfg.demo getestet, und ich meine da sind jetzt keine Probleme zu sehen, ich moechte aber die widgets von andre (colorpicker, readingsGroup, readingsHistory) geprueft haben, bevor es in trunk eingecheckt wird.
@andre: koenntest du in fhem.cfg.demo fuer diese widgets ein Beispiel einbauen?

Ich habe mein code in SVN nach /branches/FHEMWEB_JS_UMBAU eingecheckt.

justme1968

ich schaue es mir an und baue beispiele für fhem.cfg.demo.

dazu gleich zwei fragen:

- im colorpicker wird für bestimte modi automatisch auf einen slider umgebogen und dieser passend parametrisiert. geht das mit der neuen js only version auch? bzw. wie stelle ich für diesen fall dann sicher das fhemweb_slider.js geladen ist?

- das zweite ist eine erweiterung von oben bei dem ich einen normalen slider verwende aber eine eigene/zusätzliche class geben um ihn im css extra zu behandeln. in der 'alten' perl version würde ich einfach per search/replace das class=... ersetzen/erweitern. wie würde das in der js version aussehen?

die anwendung dafür wäre z.b. einen slider zur auswahl von farbe, farbtemperatur oder helligkeit mit dem passenden hintergrund zu versehen und so einen hue-slider, ct-slider, ... zu bekommen ohne den kompletten slider neu zu implementieren. siehe hier: http://forum.fhem.de/index.php/topic,18958.msg237965.html#msg237965.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

- Es werden alle fhemweb_XXX.js Dateien weiterhin geladen
- fhemweb_slider, time, multiple, noArg und textField habe ich in fhemweb.js integriert, damit der Browser nicht so viele Dateien beim (ersten) Anzeige einer FHEM Seite laden muss. Da fhemweb.js vor allen anderen fhemweb_XXX.js geladen wird, ist der Slider-code fuer alle vorhanden.
- wie man einen Slider fuer eigene Zewecke anlegt, sieht man auch in fhemweb.js/FW_createTime(). Hier eine Skizze angepasst fuer deinen Fall:
  var sl = FW_createSlider(undefined, devName+"Slider1", ["slider", min, step, max],
                currentValue, undefined, function(arg) { DoSomethingWithResult(arg) });
  $(colorpicker).append(sl);
  colorpicker.activateFn = function() { sl.activateFn() }
  $(sl).addClass("colorSlider");

Falls der Slider in einem "colorpicker" div ist, dann ist addClass eigentlich nicht notwendig, da man CSS Regeln fuer diesen kombinierten Fall erstellen kann:
div.colorpicker div.slider { color:green; }
... oder so.

   

justme1968

bin gerade dabei die createFn einzubauen und in der cfg.demo zu verwenden. dabei sind mir schon zwei dinge aufgefallen:

- ich verwende die möglichkeit einem widget in den webCmd auch ein argument mit zu geben. also z.b. rgb:rgb ff0000. das zeigt dann einen normalen colorpicker und einen roten preset button hat. das geht zur zeit mit der neuen version nicht wegen 'webCmd "temp 30" should remain text'. ich würde vorschlagen das wie bisher im widget zu entscheiden. d.h. das widget blendet den text ein oder entcheidet das es nicht zuständig ist wenn es einen parameter gibt.

ich würde vorschlagen das:
- in FW_widgetFallbackFn return auf return auf if(!$values || $values eq "noArg"); zu beschränken
- der createFn einen zusätzlichen parameter args zu geben. nach reading und in reading nur den namen des readings zu haben
- in den createFn auf das vorhanden sein der args zu prüfen und gegebenenfalls nichts zu machen
- FW_replaceWidget genau so um args zu erweitern und dort  die informId nur auf das reading zu setzen
- das splitten schon in FW_widgetFallbackFn zu machen und als eigenes attribut zu übergeben oder wenn alles in einem attribut bleiben soll das attribut in set oder cmd umzubenennen und in FW_jqueryReadyFn nach set und args zu splitten.

ich habe zum testen schon einen teil davon umgesetzt. wenn du magst mache ich es fertig und poste es als patch.


- wenn man in der detail ansicht zwei mehr als ein mal auf den attribut namen geklickt hat wird anschliessend nicht der inhalt des text Feldes übernommen sondern immer eine 1
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

justme1968

#4
das setzen der inform id in FW_replaceWidget ist glaube ich zur zeit komplett falsch.

du setzt die informId immer auf devName. das muss doch eigentlich devName-reading sein.

das es mit der .cfg.demo geht ist zufall und liegt daran das bei den dort verwendeten devices state mehr oder weniger passt.

mit der richtigen reading abhängigen informid funktionieren die dropdown und slider für state in der .cfg.demo aber nicht mehr. da passt für state noch etwas nicht.

die informId sollte auch nur dann automatisch gesetzt werden wenn in der createFn noch keine gesetzt wurde.

edit: statt der informid devName-reading könnte man auch die dev und reading attribute der ersetzten fhemWidget übernehmen und damit arbeiten. ich weiss nicht was besser wäre.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

rgp Parameter: Waere es nicht einfacher widgetOverride zu verwenden?
attr x webCmd rgb
attr x widgetOverride rgb:rgb,#ff00000

Sonst muss man im JavaScript zwei Arten uterstuetzten, Parameter an einem Widget zu uebergeben. Ist zwar fuer den Endanwender etwas komplexer, er lernt aber dann auch, wie man Widgets komplett umstellt.

Detail Attribut klicken: kann nicht nachvollziehen. Habs mit Chrome und Firefox getestet, und wie ein Irrer auf die Attribute geklickt.

informId: ich habe mit devName-reading angefangen, aber da haben die beiden Slider im Demo/Cinema nicht mehr funktioniert. Habe eine Weile ueberlegt, was wichtiger ist, mehrere unterschiedliche Reading-widgets pro Zeile zu unterstuetzen, oder eins, der auf alle Aenderungen reagiert, und da ich eher Letzteres haben will (damit die Leute es einfacher haben), habe informId auf devName gesetzt. Wenn du eine gute (und einfache :) ) Loesung fuer das Demo-Problem hast, dann lasse ich mich umstimmen.

Ich habe FW_replaceWidget angepasst, damit sie informId nur dann setzt, falls informId im zurueckgelieferten Baum noch nicht gesetzt ist.


justme1968

widgetOverride ist nicht mehr einfacher wenn es mehr als ein oder zwei einträge mit parametern sind.

es funktioniert auch nur wenn alle gleichartigen parameter direkt nebeneinander im webCmd kommen. rückwärtskompatibel ist es auch nicht.

für die farb presets der lampen kommen schnell 5 oder 10 buttons zusammen. die nicht alle zum gleichen kommando gehören.

für den anwender wären es mit der widgetOverride zwei arten. ein mal direkt im 'temp 30' beispiel und ein mal wie von dir mit widgetOverride vorgeschlagen. das ist nicht nur komplex sondern auch verwirrend weil es dann vom widget abhängt wie er es angeben muss.

das im javascript zu unterstützen ist ein kein problem mit dem obigen vorschlag. die widgets die keine paramtere akzeptieren tun einfach nichts.


das attribut klicken:zwei mal auf den namen des gleichen attributs klicken und dann im text feld enter oder auf attr klicken. bei mir steht danach reproduzierbar immer ein 1 im attribut. mit safari und chrome zu 100% reproduzierbar.

devName-reading ist aber unbedingte voraussetzung um z.b. bei einem device mit zwei readings in webCmd einen slider für beide readings zu haben. oder auch für jedes device bei dem state nicht vom gerade verwendeten reading abhängt. mit der aktuellen version wird kein slider oder dropDown für homematic und hue funktionieren.

das problem an den beiden slidern in der .cfg.demo (und bei fs20) ist das es kein reading gibt das wirklich zum slider gehört. d.h. das kommando heisst dim xxx aber der longpoll update geht auf state. eigentlich ist das die ausnahme.

hier ist ja auch beim initialen seiten aufbau ein fallback eingebaut. wenn es das reading (das zum widget gehört) für current nicht gibt weichst du auf Value aus. eigentlich müsste man nur dafür sorgen das in der inform id device-state verwendet wird wenn es das reading nicht gab und statt dessen Value verwendet wurde.

die lösung (nicht nur für das demo problem sondern für die meisten devices :) ) ist das set (für das das widget definiert wurde) und das reading (aus dem der default wert kommt un das im fallback zu state wird) getrennt zu übergeben und nicht implizit davon auszugehen das beide identisch sind obwohl state als fallback verwendet wird.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

justme1968

ich habe eine version gebaut die den obigen vorschlag implementiert.

damit gehen die alten/fs20 demo slider und alle oben angesprochenen anderen devices.

ich hänge die version morgen mal hier an.

mir ist übrigens noch ein problem aufgefallen. beim ersten laden einer seite wenn noch nichts gecached ist funktioniert das timing für den aufruf von FW_jqueryReadyFn nicht. wenn man bei google danach sucht findet man auch das document.ready nicht dafür empfohlen/geeignet ist weil es genau diese timing probleme gibt.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

> das attribut klicken...

Habs gefixt.

rudolfkoenig

Zitatfunktioniert das timing für den aufruf von FW_jqueryReadyFn nicht.

Welches Timing? Ich habe es sowohl mit FHEMWEB (jquery wird vorher geladen), wie auch mit FLOORPLAN (jquery wird dynamisch geladen) getestet, mit jeweils vorher geloeschten Cache.

rudolfkoenig

Ich habe in diesem Zweig dem SVG beigebracht, mehrere Quellen (FileLog/DbLog/logProxy) zu akzeptieren.

Syntax im gplotFile ist entweder wie bisher (#FileLog, #DbLog, etc), in diesem Fall wird die in der SVG definierte Quelle genommen, oder (neu) #<fhemDeviceName>, womit man die Quellen nach belieben mischen kann.

Der SVG-Editor unterstuetzt das auch (ueber eine neue Spalte in jeder Zeile kann man die Quelle auswaehlen), eine Aenderung der sampleDataFn in den Lieferanten (logProxy, DbLog) ist dafuer nicht notwendig. Allerdings habe ich SVG_sel um eine Klasse erweitert, damit das Ergebnis etwas ordentlicher ausschaut, sowas koennte man evtl. in logProxy/DbLog auch nachziehen.
Die Ausgabe von "Show preprocessed input" erfolgt jetzt in einem Dialog, da betateilchen sich beschwert hat.
Die angezeigten Beispiele haengen vom aktuellen Focus ab (wird per JS eingeblendet), und sinnvolle Spaltenwerte bzw. Beispiele bekommt man erst nachdem man die neue Quelle ausgewaehlt, und die Datei gespeichert hat, das ist nicht ganz intuitiv.

@andre: koenntest du in fhem.cfg.demo auch Beispiel(e) fuer logproxy eibauen, damit ich sowas einfacher testen kann?

justme1968

anbei eine erweiterung der .cfg.demo um einen raum Color mit zwei farbigen lampen:

  • die CT lampe lässt sich in der farbtemperatur verstellen und hat vier presets sowie on und off
  • die RGB lampe lässt sich im farbton und der farbe verstellen und hat drei presets sowie on und off

testen kann man damit:

  • die widgets funktionieren auch für readings. nicht nur für state.
    das ist unter anderem für homematic,hue,swap, alle(?) heizungen und fast alles ausser dummy und fs20 wichtig

  • eine änderung von state ändert nicht mehr die widgets für andere readings

  • bei der RGB lampe hängen die hue und rgb readings von einander ab.
    das setzen des einen wertes ändert auch den jeweils anderen. die widgets werden alle korrekt per longpoll aktualisiert

  • für farbtemperatur und farbton verwendet der colorpicker einen passend parametrisierten slider mit entsprechendem hintergund.

  • der colorpicker geht jetzt auch in der detail ansicht :)

damit es nach dem ersten starten auch schon funktioniert ist es wichtig das es die readings die zu den widgets gehören tatsächlich gibt. dafür ist fhem.save angepasst.
für die 'spezial' slider muss das hintergrundbild in den styles gesetzt werden. im patch ist nur defaultCommon.css angepasst. die anderen styles müssen noch nachgezogen werden.


der patch für alles ist angehängt. ich habe auch 'meine' files noch nicht eingecheckt weil ich die signatur der createFn erweitert habe und alles zusammen passen muss.

todo: readingsGroup, readingsHistory, logProxy


die änderungen an 01_FHEMWEB.pm und fhemweb.js im einzelnen:

  • trennen von reading und set in FW_widgetFallbackFn für class fhemWidget
      -> informId wird korrekt auf 'device-reading' gesetzt. sonst funktionieren widgets nur für state und nicht für andere readings

  • die reinen text kommandos wie 'dim 25' oder 'temp 30' werden nicht mehr in FW_widgetFallbackFn in 01_FHEMWEB.pm
    erzeugt sondern auch in FW_replaceWidget. sonst funktionieren die colorpicker presets nicht mehr.

  • in FW_detailSelect für FW_queryValue bei cmd=set den gleichen fallback auf Value(devName) eingebaut wie in FW_widgetFallbackFn.
      -> fs20 dim slider sind auch in der detail ansicht passend initialisiert
      frage: ist Value für beide fälle wirklich der richtige fallback oder wäre ReadingsVal auf state besser?

  • longpoll aktualisierung auch in der detail ansicht für die set widgets die zu echten readings gehören.
    für die widgets die zu einem kommando ohne eingenes reading (z.b. fs20 dim) gehören funktioniert das (noch) nicht weil der obige fallback die trennung von reading und set noch nicht kennt. dazu müsste man in FW_queryValue rausfinden ob der wert aus dem reading oder aus dem fallback kommt.

  • für slider in der detail ansicht hat ein klick auf 'set' das jeweilige reading auf 0 gesetzt hat wenn der der slider vorher nicht bewegt wurde.
    das lag daran das bei aufruf der setValueFn durch FW_queryValue das value attribut nicht aktualisiert wurde.
      -> slider.nextSibling.setAttribute('value', currVal); in activateFn hinzugefügt

fragen:

  • elName wird in FW_detailSelect zwar zusammengebaut aber nicht verwendet.
    der name kommt scheinbar immer noch aus 01_FHEMWEB. ist das absicht?
  • gibt es einen grund das der slider in der detail ansicht einen anderen style hat?
 
vorschläge:

  • wie wäre es in der detail ansicht auf das post zu verzichten und bei set/get/attr das kommando auch per xhr an fhem zu senden. damit würde der seitenaufbau vermieden und vor allem auch das zurückspringen der dropDowns auf den ersten wert.dazu müsste man noch ein bauen das die widgets ersetzt werden wenn sich die set/get/attr liste veränder hat.

  • dazu könnte man den widgets auch eine getValueFn verpassen um den eingestellten wert zu bekommen und nicht implizit über ein value attribut zu gehen.

  • wie wäre es neben der longpoll nachricht mit den durch << getrennten segmenten eine zweite nachricht z.b mit >> getrennt zu spendieren. und eine kleine api funktion in fhemweb um eine solche nachricht per longpoll zu senden. dann könnte ich damit die updates für readingsGroup und readingsHistory senden ohne events/DoTrigger zu verwenden und diese nachrichten könnte man im eventmonitor ausblenden.

  • oder wenn wir beim umstellen sind: wie wäre es das format der longpoll nachrichten gleich auf z.b. json umzustellen?
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

rudolfkoenig

Habe die beiden farbigen Lampen in fhem.cfg.demo ins Light room gepackt, und den restlichen Patch ohne wesentliche Aenderungen uebernommen. Der Patch ist aber noch nicht Fehlerfrei: wenn man in Light/Single Lights/Office auf Detail geht, dann steht "set Office blink off" in der ersten Zeile, und das ist Mumpitz. Loesungsvorschlag: ReadingsValue default leerlassen. Das habe ich aber nicht eingecheckt.

Weiss nicht genau was du mit elName meinst, das Auskommentierte (inzwischen entfernte) ist Zwischenstand beim Umbau gewesen.
Slider-Style: ich sehe kein Unterschied.

An den Vorschlaegen Arbeite ich noch.


rudolfkoenig

in der detail ansicht auf das post zu verzichten: Habs programmiert, und erstmal auskommentiert, da weder die Internals (STATE), noch die Attribute neu gesetzt werden, und das finde ich sehr irritierend. Weiterhin erstellen manche Module bei einem neuen get ein Reading, andere nicht.

getValueFn: verstehe den Sinn nicht

zweite Nachricht z.b mit >>: Den Sinn von >> vs. << verstehe ich nicht, ich habe aber ein FW_directNotify gebaut, als Parameter muss man ein hash mit CHANGED Array uebergeben, dieser ruft dann alle FHEMWEBs die ein notify erwarten auf. Falls andere Frontends das auch haben wollen, dann kann ich das von FHEMWEB nach fhem.pl schieben.

format der longpoll nachrichten auf json umzustellen: habs umgestellt, bin aber noch nicht sicher, ob es besser ist.

P.S.: habe Value aus dem ReadingsValue Aufruf entfernt, hat zu sehr genervt :)

justme1968

#14
wenn die farbigen lampen im Light room sind kannst du sie auch gleich noch zur AllLights structure hinzufügen.

das mit dem slider style:
in defaultCommon.css gibt es
  .slider     { float:left; width:250px; height:26px; }
und
  .makeSelect .slider {background:#F0F0D8; border-radius:8px;} /* detail only */
das hat dann zur folge das ich für die abgeleiteten slider auch jeweils zwei einträge brauche.

das mit dem Value fallback ist schade. bei den dim slidern wäre es schön gewesen. aber das problem lässt sich vermutlich nicht lösen so lange es die kommandos ohne eigenes reading gibt.

das mit den internals stimmt leider auch. da würde es nur helfen wenn das frontend die werte erneut abfragt. auch nicht schön.

als 'kleine' lösung wäre es vielleicht gut wenn die set/get/attr drop down nach dem seiten aufbau wieder auf den gleichen zuletzt ausgewählten eintrag stehen würden. dazu müsste man das im post mit schicken und beim dann im FW_makeSelect wieder zurück geben.

ohne getValueFn 'weiss' fhemweb.js nicht wo es den aktuellen wert eines widget her bekommt. zur zeit ist es implizit das attribut value in einem versteckten input field. das wäre dann nicht mehr nötig. so lange es beim post bleibt ist es aber egal.

die zweite nachricht bzw. die umstellung auf json hat den hintergrund von fhem nachrichten ans frontend zu senden die nicht im eventmonitor auftauchen und ohne nebenwirkungen zu parsen und einem widget zuzuordnen sind.

für die readingsGroup (und auch readingHistory) wird html code und icons und formatierter text ans frontend gesendet der auch im eventmonitor auftaucht und da eigentlich nicht hin gehört und auch geloggt wird wenn die regex im log device passt. die idee für das api (FW_directNotify) wäre jetzt kein format vorzugeben sondern einen adressaten (per device namen) und die nachricht anzugeben. d.h. die eine longpoll verbinundung wird für unterschiedliche daten verwendet. die events/reading updates zum einen und 'private' nachrichten die z.b. eine readingsGroup nur an ihr zugehöriges wirdget im frontend senden kann und die nicht mit andere nachrichten vermischt werden. mir json könenn die nachrichten inhaltsunabhängig verarbeitet werden. nur das adress schema muss vorgegeben werden. z.b. 'fhemweb:longpoll' für das was bisher longpoll ist und 'readingsGroup:xxx' für die nachrichten für die nur die readingsGroup zuständig ist. das xxx wäre wieder modul spezifisch. ich würde hier den device namen rein stecken.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968