FHEM und UNICODE, first aid

Begonnen von herrmannj, 08 Februar 2022, 19:28:02

Vorheriges Thema - Nächstes Thema

herrmannj

#15
ZitatSpezifikation zu lesen bei einem verwaisten Modul, wo man weder Hardware, noch Doku hat, ist auch nicht ohne.
da wirst du am seltensten Probleme haben, das sind nämlich genau die, die am unwahrscheinlichsten mit unicode überhaupt in Berührung kommen. Problematisch: fhemweb oder devio, syswrite etc. Aber so funktioniert aufräumen, irgendwo muss man anfangen.

Ich würde als erstes mit reading-inhalten anfangen. Dazu muss der statefile utf8 geschrieben und gelesen werden, fhem intern unicode. Die Kette bis zum fhemweb lässt sich testen und debuggen. Weitere Auswirkungen wird man sehen. Module müssen nachziehen, sonst sieht man Fehldarstellungen. Funktionelle Einschränkungen wird es auch geben (notify triggert auf Wäsche). Schritt für Schritt




herrmannj

Zitat von: Beta-User am 10 Februar 2022, 18:04:48
Bin zwar nicht ganz sicher, was du mir damit sagen willst, aber mein Anliegen war zu erfahren, wie workarounds denn nun am besten zu beseitigen sind in dem jeweiligen konkreten Umfeld, um das es geht - und zwar unabhängig davon, wer den workaround ursprünglich mal eingebaut hatte (msgDialog habe ich erst vor ein paar Tagen übernommen, und der RHASSPY-Code war an dieser Stelle vorher schon "halbwegs" fertig, als ich dazugestoßen bin und das in Richtung auf "Kompabilität mit MQTT2-IO" umgebaut habe. Soweit mir die "alten Threads" von "davor" dazu in Erinnerung sind, war es dort "richtig seltsam", je nachdem, welches System auf der Gegenseite war (versionsabhängig, docker, schießmichtot, ...).
ich wollte dir nicht zu Nahe treten, das war kein Vorwurf. Du bist gerade dass Beispiel dass man unicode Support benötigt und es keinesfalls nur darum geht ob ein smiley 1 oder 4 Zeichen lang ist. Der mangelnde support im framework ist das Problem. Zu Deiner Frage: es gibt keine einfache Antwort. Solange fhem das nicht unterstützt kannst Du die Workarounds nicht beseitigen sondern musst immer mehr davon einbauen.

justme1968

die größten probleme wird es vermutlich bei den regexen geben. ich denke hier sollten wir:

- die regexen in fhem.pl und fhemweb durchgehen und die workarounds ausbauen

- dabei auch schauen welche regex dabei auf die dann möglichen dinge umgestellt werden können
  z.b. umlaute auch wirklich zulassen, \w statt [A-za-z] verwenden und ähnliches

- für die endanwender dokumentieren was sich warum geändert hat und was neu möglich ist
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

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

rudolfkoenig

ZitatWeitere Auswirkungen wird man sehen.
Genau das meinte ich mit Bauchschmerzen und Supportaufwand, was ich vermeiden will.

Zitatdie größten probleme wird es vermutlich bei den regexen geben.
Aber nur, wenn man die Menge der erlaubten Zeichen bei Namen erweitert.
Sowas wuerde ich erst nach der internen Encoding-Umstellung angehen, ich meine wir werden auch ohne ein Zeichensatz-Erweiterung genug Aerger haben.

herrmannj

ich würde weitere Probleme erwarten wenn zb irgendwo Texte ausgegeben werden und die dann auf ein syswrite welches auch binäre streams verarbeitet. Automatisch konvertieren geht dann "da unten" nicht mehr. Theoretisch hätte fhem eine (logisch selbstgestrickte;) funktion: latin1ToUtf8($) sowie utf8ToLatin1($)

Da aufsetzen und den developern zentral anbieten (bitte nicht selberstricken): unicode_to_utf8
use Encode qw(encode decode find_encoding);
eval {$uc = encode(find_encoding('UTF-8'), $uc, Encode::FB_CROAK)};

sowie utf8_to_unicode
use Encode qw(encode decode find_encoding);
eval {$uc = decode(find_encoding('UTF-8'), $uc, Encode::FB_CROAK)};


Ab dann kann man schonmal jeden dev sagen: wenn Du "illegal widechar.." siehst - nutze bitte "unicode_to_utf8", vor der Ausgabe, in deinem modul.

herrmannj

Zitat von: rudolfkoenig am 10 Februar 2022, 19:13:16
Genau das meinte ich mit Bauchschmerzen und Supportaufwand, was ich vermeiden will.
und statt dessen laufen dutzende devs gegen die Wand weil sie nicht verstehen können wo sie noch workarounds einbauen müssen.

Diesen ganzen Block (ua) muss ich in JsonMod einbauen weil Readingnamen aus JSON keys generiert werden, der JSON kommt von extern und keiner der da draussen irgendwo JSON anbietet ist bereit sich unseren Restriktionen zu unterwerfen. Klar kann man auch ne regex auf [a_zA-Z] durchlaufen lassen. technisch gibts aber weder für das eine noch für das andere einen Grund.
258         # sanitize reading names to comply with fhem naming conventions
259         # (allowed chars: A-Za-z/\d_\.-)
260         my sub sanitizedSetReading {
261                 my ($r, $v) = @_;
262
263                 # convert into valid reading
264                 # special treatment of "umlaute"
265                 my %umlaute = ("ä" => "ae", "Ä" => "Ae", "ü" => "ue", "Ü" => "Ue", "ö" => "oe", "Ö" => "Oe", "ß" => "ss" );
266                 my $umlautkeys = join ("|", keys(%umlaute));
267                 $r =~ s/($umlautkeys)/$umlaute{$1}/g;
268                 # normalize remaining special chars
269                 $r = Unicode::Normalize::NFD($r);
270                 utf8::encode($r) if utf8::is_utf8($r);
271                 $r =~ s/\s/_/g; # whitespace
272                 $r =~ s/([^A-Za-z0-9\/_\.-])//g;
273                 # prevent a totally stripped reading name
274                 # todo, log it?
275                 #$r = "_Identifier_$_index" unless($r);
276                 $v //='';
277                 utf8::encode($v) if utf8::is_utf8($v);
278                 $newReadings->{$r} = $v;
279                 $oldReadings->{$r} = 1;
280                 #printf "1 %s %s %s %s\n", $r, length($r), $v, length($v);
281         };


justme1968

#21
ZitatAber nur, wenn man die Menge der erlaubten Zeichen bei Namen erweitert.
nein. leider nicht nur. mir fällt gerade die konkrete stelle nicht ein aber es gibt mindestens einen fall
wo wir eine regex explizit angepasst haben weil umlaute aktuell als zwei zeichen (bytes) zählen und an dieser stelle umlaute erlaubt waren. nach der umstellung sind umlaute ein zeichen. wie es sich gehört und werden mit \w auch gematched.

auch an stellen wo aktuell explizit nach umlauten gesucht wird um sie für die ausgabe oder html umzuwandeln muss unter umständen angepasst werden.

trozdem wird alles besser wenn wir es angehen und geschafft haben.

edit: ich glaube es hatte mit den raum namen zu tun. da sind umlaute ja auch jetzt schon erlaubt.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

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

rudolfkoenig

Zitateval {$uc = encode(find_encoding('UTF-8'), $uc, Encode::FB_CROAK)};
Wenn schon FB_CROAK, dann sollte das Ergebnis von eval geprueft werden: was genau sollte man im Fehlerfall tun?
Ich bin eher fuer FB_DEFAULT oder FB_WARN.

Zitatund statt dessen laufen dutzende devs gegen die Wand weil sie nicht verstehen können wo sie noch workarounds einbauen müssen.
Ich sehe es z.Zt. genau andersherum. Ich habe damit kaum bzw. keine Probleme, ein paar wenige manchmal etwas.
Die Umstellung wird massiv Aerger bedeuten, und ich werde monatelang Support fuer verwaiste Module leisten duerfen.

Zitattrozdem wird alles besser wenn wir es angehen und geschafft haben.
Das man _danach_ sagen kann: das ist der Standard, selbst schuld, wenn du dich nicht daran haelst, ist mir klar.
Ob es unter dem Strich besser wird, haengt davon ab, wer die Statistik in Auftrag gibt.

herrmannj

ZitatWenn schon FB_CROAK, dann sollte das Ergebnis von eval geprueft werden: was genau sollte man im Fehlerfall tun?
Ich bin eher fuer FB_DEFAULT oder FB_WARN.
Bin bei Dir, kann man diskutieren. In beide Richtungen gibt es die Chance, dass nicht konvertiert werden kann. Was dann zu tun ist weiß nur der dev. Der muss also die Info bekommen, der Rest liegt bei ihm. Abbrechen, Defaults verwenden, user informieren, whatever

justme1968

ZitatIch habe damit kaum bzw. keine Probleme, ein paar wenige manchmal etwas.
wie viel probleme man hat hängt sehr stark davon ab welche module man einsetzt, bzw. wieviel kontakt man damit zur aussenwelt und externen apis hat. jemanden der 'nur' in seiner fhem welt bleibt und ein paar rf devices einsetzt sieht wenig probleme, jemand der viele externe geräte und dienste angebunden hat wie hue, HTTPMOD, harmony, ... wird sehr viel mehr probleme haben. vor allem wenn er wie es eigentlich heutzutage selbstverständlich sein sollte in den externen systemen namen mit umlauten oder ähnlichem verwendet. alles andere ist nicht mehr zeitgemäß und wird von jedem nicht idv futzi als veraltet und unmöglich angesehen. ein 'einfacher' anwender verzweifelt unter umständen schon wenn er per regex in einer per Httputils zurückgelieferten seite einen wert extrahieren will und seine regex mit einem . partout nicht auf den umlaut den internen zwei byte matchen will. oder der. umlaut in der regex nicht matched oder, oder, ...

ZitatDas man _danach_ sagen kann: das ist der Standard, selbst schuld, wenn du dich nicht daran haelst, ist mir klar.
Ob es unter dem Strich besser wird, haengt davon ab, wer die Statistik in Auftrag gibt.
es geht ja nicht darum standards zu verwenden weil es schön ist sondern tatsächlich konkret vorhandene probleme ein mal und richtig zu lösen. auch wenn das am anfang schmerzhaft er ist als immer nur ein bisschen oben drauf zu pfuschen reparieren. das aber immer wieder und irgendwann macht der neue workaround irgend einen alten zu nichte und niemand weiss mehr warum es nicht geht.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

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

rudolfkoenig

Ich habe das global Attribut encoding eingefuehrt, mit den moeglichen Werten unicode und utf8.
utf8 ist default, entspricht dem bisherigen internen Format utf-8.
Mit unicode (das ist EXPERIMENTELL und Work-in-Progess) wird intern Unicode/Wide-Char verwendet, d.h. nach dem Einlesen muss Encode::decode('UTF-8', ...), und vor dem Ausgeben Encode::encode('UTF-8', ...) durchgefuehrt werden.
Mit "attr global encoding unicode" wird die globale Variable $unicodeEncoding gesetzt.

Umgestellt und kurz getestet habe ich:
- fhem.cfg und fhem.state
- FileRead/FileWrite in fhem.pl
- das FHEM Log
- telnet
- FHEMWEB
- HttpUtils.pm

Das Setzen des Attributes im laufenden Betrieb wird nicht empfohlen, getestet habe ich es nicht.
Ich habe darauf geachtet, dass beim nicht gesetzten Attribut der Code gleich bleibt, kann aber sein, dass ich was uebersehen habe.

Ich als Maintainer muss noch eventType, FileLog, MQTT2_CLIENT und MQTT2_SERVER umstellen. Falls ich was vergessen habe, bitte melden.

Natuerlich gibt es eine ganze Reihe anderer Module, die das explizit unterstuetzen muessen, mir faellt im Moment  configDB und DbLog ein.

justme1968

toll. ich schaue mir an was ich in meinen modulen ändern muss.

aber ein kleinlicher kommentar um das risiko für missverständnisse irgendwann später zu minimieren: wir wollen ja zwischen dem perl unicode handling zu dem wir hin wollen und dem aktuellen zustand mit bytefolgen die zwar utf-8 encoded sind aber nicht als perl unicode utf-8 strings markiert sind unterscheiden.

deshalb denke ich das andrere name für die attributwerte besser wäre. z.b. bytestream (fhem legacy utf-8 byte stream, byte semantik) und unicode (perl unicode handling, character semantik). d.h. es sind wirklich zwei gegensätze. was unicode und utf-8 nicht sind.

wie perl intern die strings codiert (utf-8 oder utf-32 oder sogar etwas ganz anderes) ist im prinzip egal und transparent, muss noch nicht mal immer gleich sein, hängt von diversen optimierungen ab, ... das encoding kommt 'nur' und erst dann ins spiel wenn man daten hat die man perl übergeben bzw. aus perl zur weiterverarbeitung abholen möchte. hier gibt man jeweils das encoding an in dem die externen daten vorliegen bzw. vorliegen sollen.



hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

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

rudolfkoenig

habe utf8 nach bytestream geaendert.

betateilchen

Zitat von: rudolfkoenig am 14 Februar 2022, 22:07:11
Das Setzen des Attributes im laufenden Betrieb wird nicht empfohlen, getestet habe ich es nicht.

Wie soll das Attribut denn sonst gesetzt werden, außer im laufenden Betrieb?

Zitat von: rudolfkoenig am 14 Februar 2022, 22:07:11
Natuerlich gibt es eine ganze Reihe anderer Module, die das explizit unterstuetzen muessen, mir faellt im Moment  configDB und DbLog ein.

Sobald ich irgendwann verstanden habe, WAS ich da in configDB unterstützen muss, kann ich das gerne berücksichtigen.
Aus diesem Thread hier kann ich das als Maintainer jedenfalls nicht ableiten.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

ZitatWie soll das Attribut denn sonst gesetzt werden, außer im laufenden Betrieb?
Das ist eine berechtigte Frage.
Vermutlich sollte FHEM bei einer Aenderung des Wertes automatisch  save+shutdown restart machen.

ZitatSobald ich irgendwann verstanden habe, WAS ich da in configDB unterstützen muss, kann ich das gerne berücksichtigen.
Falls $unicodeEncoding gesetzt ist, muss man alles nach Einlesen "von Aussen" in das interne Unicode/Wide-Char Format konvertieren, und vor dem Rausschreiben "nach Aussen" nach UTF-8 Bytestream (bzw. das, was adequat ist).

Bei Dateien erledigt beide Richtungen:
binmode($fh, ":encoding(UTF-8)") if($unicodeEncoding);


Bei sonstigen FH:
Input, nach sysread:
$buf = Encode::decode('UTF-8', $buf) if($unicodeEncoding);
Output, vor syswrite:
$buf = Encode::encode('UTF-8', $buf) if($unicodeEncoding);