Da ich einige Readings und Datenquellen mit utf8 Encoding habe, habe ich einmal das (experimentelle) globale Attribut encoding=unicode ausprobiert. Im großen und ganzen tut es das, was ich mir erhofft habe: Ein- und Ausgaben (insbesondere Filelog und fhem.save) werden jetzt explizit als utf8-kodiert behandelt. Damit beschwert sich Perl auch nicht mehr über einen "wide character in print" bei jedem Sonderzeichen.
Allerdings habe ich auch einige über MQTT mittels MQTT2_SERVER angebundene Geräte, die Binärdaten senden bzw. bekommen möchten. Mit encoding=unicode werden nun aber auch alle über MQTT ein- und ausgehenden Daten als utf8 kodiert. Das ist natürlich sinnvoll für Textdaten (insbesondere JSON), zerschießt aber meine Binärdaten.
Nun gibt es bei MQTT2_SERVER das Attribut binaryTopicRegexp, mit dem man Topics definieren kann, die als Binärdaten behandelt werden - dachte ich, gemäß Commandref:
ZitatbinaryTopicRegexp <regular-expression>
this attribute is only relevant, if the global attribute "encoding unicode" is set.
In this case the MQTT payload is automatically assumed to be UTF-8, which may cause conversion-problems if the payload is binary. This conversion wont take place, if the topic matches the regular expression specified. Note: as is the case with other modules, ^ and $ is added to the regular expression.
Das stimmt auch, wenn man Daten empfängt:
487 if($unicodeEncoding) {
488 if(!$shash->{binaryTopicRegexp} ||
489 $tp !~ m/^$shash->{binaryTopicRegexp}$/) {
490 $val = Encode::decode('UTF-8', $val);
491 }
492 }
Allerdings nicht beim Senden:
680 if($unicodeEncoding) {
681 $ltopic = Encode::encode('UTF-8', $topic);
682 $lval = Encode::encode('UTF-8', $val);
683 }
Würde etwas dagegen sprechen, die gleiche Abfrage auch beim Senden (publish) einzubauen, oder alternativ zwei verschiedene Attribute zu haben, die dann jeweils für eine Richtung gelten? (Ein Attribut fände ich ausreichend, da man ja für gewöhnlich das selbe Topic nicht bidirektional benutzt, also ergibt sich die Datenrichtung ja bereits aus dem Topic selbst. Und wenn gerade empfangene Daten wieder gesendet werden sollen, an andere Subscriber, will man sie ja im gleichen Format senden, in dem man sie empfangen hat. Aktuell werden empfangene Binärdaten als utf8 kodiert wieder gesendet und damit verändert.) Ich habe mal experimentell folgende Änderung eingebaut, die bei mir gut funktioniert, und so weit ich sehen kann keine Nebenwirkungen hat:
680 if($unicodeEncoding) {
681 if(!$shash->{binaryTopicRegexp} ||
682 $topic !~ m/^$shash->{binaryTopicRegexp}$/) {
683 $ltopic = Encode::encode('UTF-8', $topic);
684 $lval = Encode::encode('UTF-8', $val);
685 }
686 }
In jedem Fall greift die Änderung nur, wenn das als experimentell eingeführte Attribute encoding=unicode gesetzt ist.