FHEMWEB: WebSocket-Abbruch „Invalid frame header“ bei UTF8-geflaggten Readings

Begonnen von schwatter, 14 November 2026, 09:09:44

Vorheriges Thema - Nächstes Thema

schwatter

Morgen Rudi,

bei FHEMWEB über HTTPS reißt ab und zu WebSocket ab. Chrome meldet dann ,,Invalid frame header", und die Seite verbindet sich neu. Ausgelöst wird das bei mir durch HMCCU-Geräte, deren Readings Perl-intern als UTF-8 markiert sind. Über normales HTTP tritt der Fehler (fast) nicht auf.

Ich habe die Ursache in FW_addToWritebuffer gefunden und einen kleinen Patch geschrieben. Zum Nachstellen habe ich eine Demo mit Dummy und Notify erstellt. Mit dem Patch läuft es bei mir seitdem über HTTPS und HTTP stabil.

define wsDemo dummy
attr wsDemo room wsDemo
attr wsDemo setList normal:noArg ascii:noArg grad:noArg euro:noArg gradbytes:noArg lang:noArg mix:noArg
attr wsDemo webCmd normal:ascii:grad:euro:gradbytes:lang:mix
attr wsDemo stateFormat result
define wsDemo_n notify wsDemo:(normal|ascii|grad|euro|gradbytes|lang|mix) { readingsSingleUpdate($defs{wsDemo}, "result", +{ normal => "Test normal ".TimeNow(), ascii => Encode::decode("UTF-8", "Test ascii ".TimeNow()), grad => Encode::decode("UTF-8", "Test grad 17.3 \xc2\xb0C ".TimeNow()), euro => Encode::decode("UTF-8", "Test euro 5 \xe2\x82\xac ".TimeNow()), gradbytes => "Test gradbytes 17.3 \xc2\xb0C ".TimeNow(), lang => Encode::decode("UTF-8", "Test lang ".("x" x 200)." ".TimeNow()), mix => Encode::decode("UTF-8", "Test mix 17.3")." \xc2\xb0C ".TimeNow() }->{$EVENT}, 1) }

--- a/FHEM/01_FHEMWEB.pm    (revision 31693)
+++ b/FHEM/01_FHEMWEB.pm    (working copy)
@@ -749,6 +749,18 @@
           if($hash->{encoding} && !$encoded && ($unicodeEncoding ||
                             (utf8::is_utf8($txt) && $txt =~ m/[^\x00-\xFF]/)));
   if( $hash->{websocket} ) {
+    # The frame must be built from UTF-8 bytes. A remaining UTF8-flagged
+    # string (chars <= 0xFF) would turn the header into UTF-8 (0x81 -> c2 81)
+    # when written by IO::Socket::SSL, or into invalid UTF-8 via plain syswrite.
+    if(utf8::is_utf8($txt)) {
+      my $b = $txt;
+      my $c;
+      if(utf8::downgrade($b, 1) && utf8::decode($c = $b)) {
+        $txt = $b;              # already UTF-8 bytes inside (as plain syswrite sends it)
+      } else {
+        utf8::encode($txt);     # real characters, e.g. from decode_json
+      }
+    }
     my $len = length($txt);
     if( $len < 126 ) {
       $txt = chr(0x81) . chr($len) . $txt;

Gruß schwatter

rudolfkoenig

Mit "attr global encoding bytestream" (Voreinstellung / Normalfall) muessen alle Module die Daten (Reading/etc) als UTF-8 halten, anders forumliert im "utf8:encode" Format.
Mit "attr global encoding unicode" muss alles im sog. Wide-Character (utf8:decode) Format gehalten werden.
Module, die mit der Aussenwelt kommunizieren (FHEMWEB/telnet/etc) konvertieren diese Daten entsprechend.
"attr global encoding unicode" ist nicht so alt, und wird nicht von allen Modulen beachtet.

Dein Demo beachtet das Attribut nicht, und funktioniert dementsprechend in der Voreinstellung nicht.
Wenn ich "attr global encoding unicode" setze, dann gibt es keine Ausfaelle.

Dein Patch wuerde nur einen kleinen Teil der falschen internen Codierung kaschieren, ich ziehe es vor, dass es auch hier sichtbar wird, und die Ursache abgestellt wird.

schwatter

Mh ok,

zu global. Das attr encoding ist nicht von mir gesetzt. Daher ist es intern default bytestream.
Wenn ich bewusst das attr setze, egal welches restartet Fhem bei mir. Im Log sehe ich nichts?
Hast du eine Idee, warum das passieren kann?

Edit:
Ah ein Neustart ist erforderlich und ich habe attr global autosave 1 aus.... Das zusammen wirkt
wie ein Systemabsturz  :)

Zu dem WS-Abbruch. Wenn ich per Perl suche:

{ join "\n", map { my $d = $_;; map { "$d ($defs{$d}{TYPE}): $_" } grep { utf8::is_utf8($defs{$d}{READINGS}{$_}{VAL} // "") } sort keys %{$defs{$d}{READINGS} // {}} } sort keys %defs }
Lande ich oft bei HMCCU
HmIP_BZ_WTH (HMCCUCHN): ACTUAL_TEMPERATURE_STATUS
HmIP_BZ_WTH (HMCCUCHN): HEATING_COOLING
HmIP_BZ_WTH (HMCCUCHN): HUMIDITY_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 1.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 1.VALVE_STATE
HmIP_FALMOT_C12 (HMCCUDEV): 10.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 11.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 12.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 2.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 2.VALVE_STATE
HmIP_FALMOT_C12 (HMCCUDEV): 3.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 3.VALVE_STATE
HmIP_FALMOT_C12 (HMCCUDEV): 4.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 4.VALVE_STATE
HmIP_FALMOT_C12 (HMCCUDEV): 5.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 5.VALVE_STATE
HmIP_FALMOT_C12 (HMCCUDEV): 6.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 7.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 8.LEVEL_STATUS
HmIP_FALMOT_C12 (HMCCUDEV): 9.LEVEL_STATUS
HmIP_KLHR_STHD (HMCCUCHN): ACTUAL_TEMPERATURE_STATUS
HmIP_KLHR_STHD (HMCCUCHN): HEATING_COOLING
HmIP_KLHR_STHD (HMCCUCHN): HUMIDITY_STATUS
HmIP_WZ_WTH (HMCCUCHN): ACTUAL_TEMPERATURE_STATUS
HmIP_WZ_WTH (HMCCUCHN): HEATING_COOLING
HmIP_WZ_WTH (HMCCUCHN): HUMIDITY_STATUS

Dann muss ich wohl da gucken ob die intern als Zeichen markiert sind oder als normale Bytes.

Gruß schwatter

rudolfkoenig

Fuer die UTF-8 Suche gibt es auch fhemdebug utf8check als FHEM Befehl.

schwatter

Ok danke,

bezüglich meines Problems habe ich jetzt zumindest verstanden worum es geht.
Wenn ich hier lese. https://forum.fhem.de/index.php?topic=126088.0
Da war HTTPS bei mir noch kein Thema, erst seit dem du das so einfach integriert hast.

Zitat von dir:
ZitatIch versuchs nochmal:
  Wenn "attr global encoding unicode" gesetzt (und damit $unicodeEncoding=1) ist, dann gilt:
  Alle FHEM-Internen Strings sind Unicode. Darauf muss man beim Einlesen und Rausschreiben der Daten achten, und notfalls passend konvertieren.  Zum Konvertieren sollte man die Encode::encode bzw. Encode::decode Routinen nehmen.

Ist das irgendwo in der Wiki Doku platziert?

Und der zap war das letzte Mal im Juli aktiv...daher bleibt dahin eine Diskussion wohl offen.

Edit:
Ich verwende jetzt erstmal "attr global encoding unicode" und beobachte.

Gruß schwatter