Hallo,
ein Anwender meldet, dass save config ein deleteattr aus der fhem.conf entfernt, dass von Hand dort hinein geschrieben wurde.
Bug oder Feature?
Warum braucht man dies? ECMD verwendet requestSeparator und replySeparator. Diese können als Attribute gesetzt werden. Wenn sie gesetzt werden, werden die gesetzten Werte als Separatoren verwendet. Wenn sie nicht gesetzt sind, werden keine Separatoren verwendet. Der Default ist \000 und kann folglich nicht über ein nicht gesetztes Attribut erkannt werden. Stattdessen werden die Attribute beim define angelegt und müssen mit deleteattr gelöscht werden. Wenn jemand eine gefälligere Lösung dafür hat, würde ich auch diese implementieren.
Der Workaround ist derzeit, Werte für die Separatoren zu verwenden, die bestimmt nie vorkommen.
Viele Grüße
Boris
hallo boris,
warum kann man \000 nicht von einem nicht gesetzten attribut unterscheiden?
oder wird das zeichen 1:1 ins attribut geschrieben? ich glaube das wäre keine gute idee weil du ja auf diese art unkontrolliert alle möglichen steuerzeichen ins config file und sonst wohin bekommst.
wie wäre es denn alles außer \w zeichen. nur octal oder json oder anders codiert zu erlauben?
gruss
andre
Hallo Andre,
\000 ist ein Nullbyte und als solches gemeint. Wenn der Anwender foo\000bar an das ECMD-Gerät schickt und den requestSeparator auf \000 gesetzt hat, wird erst foo und dann bar gesendet. Wenn das Attribut requestSeparator nicht gesetzt ist und der Anwender foo\000bar an das ECMD-Gerät schickt, wird foo\000bar gesendet.
Ja, es kommen unkontrolliert alle möglichen Steuerzeichen vor. Mir ist nicht klar, an welchen Stellen FHEM Zeichen perl-kodiert und wann nicht. Ob z.B. in attr myDevice \000 das Attribut als Nullbyte oder als Literal BackslashNullNullNull erkannt wird.
Viele Grüße
Boris
ein
attr <name> xyz \000
wird als 4 einzelne zeichen im config file gespeichert und auch so wieder eingelesen.
gruss
andre
Zitatsave config ein deleteattr aus der fhem.conf entfernt, dass von Hand dort hinein geschrieben wurde.
Klar. save schreibt die interne Struktur in die Datei. Genauso wird set/get/etc "entfernt". Wenn man sowas unbedingt haben will, dann bitte per "define lastinclude notify global:INITIALIZED include myFhem.cfg"
ZitatWenn sie nicht gesetzt sind, werden keine Separatoren verwendet.
Der Default ist \000 und kann folglich nicht über ein nicht gesetztes Attribut erkannt werden.
Diese zwei Saetze sind mAn widerspruechlich, und ich verstehe den Sinn trotz wiederholtes Lesen nicht.
\ hat in FHEM (bis aufs Zeilenende) keine besondere Bedeutung: ich habe jetzt mit "attr dummy comment \000" herumexperimentiert, und ich sehe keine Probleme.
Danke für die Infos und Tests. Ich mache erstmal meine Hausaufgaben und analysiere, an welchen Stellen i.V.m. ECMD Steuerzeichen vorkommen können (Attribute, Logs, etc.) und inwiefern dort lediglich Dokumentationsbedarf oder auch Programmierbedarf besteht.
Ich muss die zu Grunde liegende Thematik verständlich beschreiben. Hier:
Wenn das Attribut requestSeparator auf einen Wert gesetzt ist, werden die als Requests gesendeten Zeichenketten vor Überstellung an das ECMD-Gerät zunächst an diesem gesetzten Wert aufgetrennt und dann werden die einzelnen Teilzeichenketten nacheinander an das als ECMD-Gerät definierte physikalische Gerät gesendet.
Der Default ist das Zeichen mit dem Zeichenwert 0 (\000).
Verwendung von AttrVal($name, "requestSeparator", "\000") ist ausgeschlossen, da ein nicht gesetztes Attribut eben nicht bedeutet, dass der Defaultwert genommen wird.
Daher setze ich das Attribut beim Define.
Wenn der Anwender keinen requestSeparator benötigt, muss er das Attribut mit deleteattr löschen.
Der Grund für den Default ist Abwärtskompatibilität gewesen (\000 war in einer frühen Version der hardkodierte requestSeparator).
Ich sehe drei Möglichkeiten:
1. Es lassen wie es ist und den Anwendern von Save-Config-per-FHEMWEB die Lösung mit lastinclude vorschlagen.
2. Nach Ankündigung mit einigem Vorlauf den Default auf "kein requestSeparator" ändern.
3. Eine andere Lösung, für die ich eine Eingebung benötige.
Ich präferiere 2.
Viele Grüße
Boris
Würde ich ebenfalls bevorzugen.
Alternativvorschlag:
In der Define-Funktion jetzt wird folgende Zeile aufgenommen:
$attr{$name}{requestSeparator} ='\000';
Während der Initialisierung wird es durch das usereigene Attribut aus der Konfiguration überschrieben, sofern der Nutzer einen eigenen Wert gesetzt hat. Andernfalls bleibt es so als "Defaultwert" gesetzt und wird in der Konfiguration bei der nächsten Save-Gelegenheit gespeichert. Dann wartest du ein paar Wochen ab und änderst dann in ECMD den Default-Wert auf [kein separator] ab.
Damit hast du dann einen Großteil der aktiven Update-Nutzer direkt abgefrühstückt und dein Supportaufwand minimiert sich.
Gruß
Markus
zu 3: schön ist anders, aber ein 'spezialwert' wie no-requestSeparator im attribut als kennzeichen das kein separator verwendet werden soll wäre eine möglichkeit. oder ein zusätzliches attribut noSeparator.
2. ist glaube ich am saubersten.
gruss
andre
Zitat von: Markus Bloch am 22 November 2016, 19:01:08
In der Define-Funktion jetzt wird folgende Zeile aufgenommen:
$attr{$name}{requestSeparator} ='\000';
Während der Initialisierung wird es durch das usereigene Attribut aus der Konfiguration überschrieben, sofern der Nutzer einen eigenen Wert gesetzt hat. Andernfalls bleibt es so als "Defaultwert" gesetzt und wird in der Konfiguration bei der nächsten Save-Gelegenheit gespeichert. Dann wartest du ein paar Wochen ab und änderst dann in ECMD den Default-Wert auf [kein separator] ab.
Damit hast du dann einen Großteil der aktiven Update-Nutzer direkt abgefrühstückt und dein Supportaufwand minimiert sich.
Danke Markus für den Alternativvorschlag. Die oben erwähnte Zeile ist ja jetzt schon drin. Möglicherweise sind damit alle Anwender von Save-Config-per-FHEMWEB bereits abgefrühstückt. ECMD/ECMDDevice ist allerdings ein Hackerdevice. Ich nehme an, dass die meisten Anwender lieber die fhem.conf per Hand bearbeiten.
Viele Grüße
Boris
Danke an Euch beide für die Bestätigung, dass Nummer 2 der Weg der Wahl ist.
Zitat von: Dr. Boris Neubert am 22 November 2016, 18:46:32
1. Es lassen wie es ist und den Anwendern von Save-Config-per-FHEMWEB die Lösung mit lastinclude vorschlagen.
2. Nach Ankündigung mit einigem Vorlauf den Default auf "kein requestSeparator" ändern.
3. Eine andere Lösung, für die ich eine Eingebung benötige.
4. Endlich akzeptieren, dass Attribute dem Benutzer gehören und nicht dem Entwickler oder dem xx_Define() :)
Lösung 1 ist keine schöne/gute Lösung, denn Anwender der configDB müssten somit mit der Datenbank UND einer zusätzlichen Konfigurationsdatei arbeiten oder für jedes benötigte deleteattr ein eigenes notify definieren. Eventuell wäre noch eine Funktion in der 99_myUtils.pm denkbar, die bei mehreren deleteattr nur einmal (per notify) aufgerufen werden müsste.
Irgendwo steht m.W. geschrieben, dass in Konfigurationsdaten (egal ob Datei oder Datenbank) nur vier Zeilentypen vorkommen sollen:
- define...
- attr...
- # Kommentar
- <Leerzeile>
Wobei die configDB bereits die Typen 3+4 komplett ignoriert.
In diesem Sinne könnte man vielleicht überlegen, ein attr <device> <attrName> ohne einen angegebenen Attributwert zukünftig so zu interpretieren, dass das Attribut gelöscht werden soll. Bei den configDB-eigenen Attributen zur Parametrierung der Datenbank funktioniert das schon sehr lange so.
ja. attribute gehören dem benutzer.
aber trotzdem ist es sinnvoll das ein modul die intern verwendeten defaults sichtbar macht in dem es attribute auf diese defaults initialisiert.
wenn man dies richtig macht ist das eine hilfe für den anwender ohne ihn beim setzen, ändern oder löschen der attribute eintuschränken.
Zitatattr <device> <attrName> ohne einen angegebenen Attributwert zukünftig so zu interpretieren, dass das Attribut gelöscht werden soll.
Aktuell wird bei so einem Attribut das Wert 1 gesetzt.
Bei einer Aenderung haette ich das Bedenken, dass relativ viel Doku und Code ueberprueft werden muss.
Zitat von: rudolfkoenig am 23 November 2016, 09:49:07
Aktuell wird bei so einem Attribut das Wert 1 gesetzt.
Und diese Logik habe ich bis heute nicht verstanden. Eigentlich ist ein fehlender Attributwert beim Setzen eines Attributes für mich (bisher) ein Syntaxfehler, der als solcher gemeldet werden müsste.
Fuer ja/nein Werte ist es bequem, und mAn auch verstaendlich:
attr global mseclog
attr global stacktrace
attr global updateInBackground
usw.
beim setzen geht wenigstens (fast) nichts kaputt.
viel problematischer finde ich das ein vergessener attribut name beim deleteattr dafür sorgt das alle attribute weg sind.
Hmm. Irgendwie sind wir in eine Grundsatz-/Methoden-/Standarddiskussion geraten und meine Erfahrung lehrte mich, dass dies nicht zu einer grundsätzlichen Änderung führt.
On-Topic:
Attribute können nicht gesetzt sein, gesetzt sein, und auf einen Wert gesetzt sein. Die Verwendung von AttrVal($name, $attribut, $default) ist nicht für den Fall geeignet, dass ein nicht gesetztes Attribut als getrennter dritter Zustand in Unterschied zu gesetztem oder auf Wert gesetzten Attribut verstanden wird. Die Schwierigkeit entsteht durch die Vermengung der Aussagen.
Ich schließe mich Rudi an, dass die Form "Attribut ist gesetzt aber ohne Wert/Wert ist egal" probat ist. Er ist auch nicht problematisch, weil der Anwender ein z.B. per AttrVal($name, $attribut, 1) defaultmäßig gesetztes Attribut mit attr <name> 0 abschalten kann. Aber auch nur, wenn im Code mit if(...) und nicht mit if(defined(...)) geprüft wird, was ein Entwickler tun würde, wenn er AttrVal($name, $attribut, undef) verwendet. Ich habe mir gerade mal einen Querschnitt durch die Verwendung von AttrVal angesehen und da gibt es alle möglichen Varianten für den dritten Parameter: 0, 1, "1", undef, "eintext", ...
Die semantische Lücke entsteht dadurch, dass der Anwender ein Attribut nicht auf "nicht gesetzt" konfigurieren kann, wenn der Default "auf einen Wert gesetzt" ist. Ein naives attr <name> (ohne Angabe eines Wertes) wäre die semantische Entsprechung von deleteattr <name>. Aber leider ist das schon mit attr <name> 1 vorbelegt. Es ließe sich zwar in der AttrFn überschreiben, aber diese Inkonsistenz ist hässlich.
Fazit: wir stecken tief im Sumpf und der Default in meinem Modul muss sich ändern und dieses Thema in die Wikiabteilung FHEM-Development für Fortgeschrittene.
Viele Grüße
Boris
eigentlich inzwischen etwas off toppic... aber vielleicht nützt es ja doch noch jemandem.
ja. solche diskussionen führen selten zu grundsätzlichen änderungen im bestehenden. aber sie können helfen das ein entwickler bei einem neuen modul nicht wieder in genau die selben probleme läuft.
ich würde sagen es gibt in der aktuellen implementierung keine drei zustande sondern nur zwei. nicht gesetzt oder auf einen wert gesetzt. ein teil der probleme kommen daher das man manchmal drei zustände möchte, es aber eben nur zwei gibt.
das die 0 semantisch bei manchen datentypen einem nicht gesetzten attribut gleich kommt ist mehr oder weniger zufall denn man natürlich konkret ausnutzen kann. aber eben nicht immer problemlos und abhängig on der verwendung des attributs.
ein anderer teil der probleme kommt daher das entwickler der dritten parameter mit etwas anderem als undef verwenden. das sollte eher dem endanwender überlassen sein. für entwickler ist es besser beim initialen define eines moduls (ob von hand oder durch autocreate) attribute mit den gewünschten defaults vorzubelegen. das ist zum einen da verhalten für den endanwender sichtbar und zum anderen kann er das attribut anpassen und löschen und wird von unsichtbaren modul internen defaults nicht überstimmt.
das fhem default verhalten zu ändern würde vermutlich alle möglichen probleme mit bestehenden modulen verursachen. deshalb ist es glaube ich besser die obige vorgehensweise zu empfehlen d.h. das im modul der dritte parameter von AttrVal in der regel undef sein sollte und statt dessen im initialen ersten define nötige attribute vorbelegt werden.
gruss
andre
Zitat von: justme1968 am 23 November 2016, 20:58:47
das fhem default verhalten zu ändern würde vermutlich alle möglichen probleme mit bestehenden modulen verursachen. deshalb ist es glaube ich besser die obige vorgehensweise zu empfehlen d.h. das im modul der dritte parameter von AttrVal in der regel undef sein sollte und statt dessen im initialen ersten define nötige attribute vorbelegt werden.
Und wie komme ich dann zu meinem internen Default-Wert, wenn der User aus Unwissenheit oder auch Absicht das Attribut löscht, sich aber 5min später nicht mehr erinnern kann und sich beschwert, dass das Modul gar nicht mehr funktioniert, weil ihm ein Wert für die Funktion fehlt? Ich bin der Meinung, dass hier ein interner, auch nicht sichtbarer Default-Wert völlig ok ist und den User keineswegs einschränkt, denn mit setzen des Attributes kann er es ja nach wie vor anpassen und überschreiben. Ob man die internen Default-Werte unbedingt immer als Attribute anlegen muss ist eine Geschmacksfrage. Ich hab es nach einem Define lieber aufgeräumter (ja, ich bin trotzdem ein Fan devStateIcon u.ä. beim 1. define vorzubelegen). Es ist vermutlich wie so häufig: Die Autoren lieben ihre eigenen Module und leben mit den in ihren Augen seltsamen Verhalten der anderen Module, sofern sie sie benutzen müssen/wollen.
das oben bezog sich auf defaults/attribut bei denen es sinnvoll ist das ein anwender sie komplette löscht.
wenn es um dinge geht bei denen komplett löschen nicht sinnvoll ist passt das natürlich nicht ganz. ob man dann tatsächlich nur einen sinnvolle meldung ausspuckt oder sich die defaults von woanders holt (bis hin zum wieder setzen des attributes) hängt vom modul ab.
übrigens kann man das löschen eines attributes in der AttrFn auch verhindern.
Zitat von: justme1968 am 26 November 2016, 09:04:28
übrigens kann man das löschen eines attributes in der AttrFn auch verhindern.
was dem Sinn eines dem Benutzer gehörenden Attributes allerdings völlig zuwiderlaufen würde...