Paßt zwar nicht 100%, aber bei der Durchsicht von ein paar "Ausgangsversionen" von jüngst im Forum veröffentlichten Modulen sind ein paar Sachen dabei gewesen, die wir (bisher leider nur per pm) besprochen haben, und die die betreffenden "Gelegenheits-Modul-Autoren" dann anscheinend hilfreich fanden.
Daher hier eine kurze Zusammenfassung:
decode_json, encode_jsona) evalDiese Funktionen wurden teils ohne schützendes "eval" aufgerufen. Das kann FHEM abschießen, wenn die Rückmeldung kein JSON ist! (dafür reicht es uU., wenn eine "nicht erreichbar"-Meldung im Klartext zurückkommt). Gilt umgekehrt (für encode_json) genauso, wenn man "kaputte" Daten reinkippt => sicher ist sicher...
Ginge in etwa so (Es gibt im Forum ein paar weitere Varianten, aber so ist das m.E. am saubersten):
my $ref;
if ( !eval { $ref = decode_json($data) ; 1 } ) {
#sonstige Fehlerbehandlungsroutinen hierher, dann ;
return Log3($hash->{NAME}, 1, "JSON decoding error: $@");
}
In $ref stehen dann die dekodierten Daten.
b) Alternativenaa) JSON->new->decode()decode_json und encode_json gehen davon aus, dass man die Daten in einem Format hat:
decode_json() nimmt an, dass $DEF als utf-8 Bytestream vorliegt, und konvertiert es nach Unicode / Wide-Char.
JSON->new->decode() ist nicht ganz so mutig, und laesst die Daten unveraendert.
Es hat sich gezeigt, dass z.B. beim Dekodieren von per MQTT2_CLIENT angelieferten Daten "JSON->new->decode()" stressfreier ist. Aber auch das sollte man "einpacken":
my $decoded;
if ( !eval { $decoded = JSON->new->decode($content) ; 1 } ) {
Log3($hash->{NAME}, 1, "JSON decoding error in ...: $@");
return "... seems not to contain valid JSON!";
}
bb) toJSONfhem.pl bietet mit der Funktion eine Alternative zu encode_json etc. (das im Übrigen anscheinen auch nicht immer "sauberen JSON" erzeugt (manche Gegenstellen akzeptieren Zahlen und/oder bool'sche Werte nicht, wenn sie in Quotes stehen!)). Na jedenfalls an alle, die per
Data::Dumper irgendwelche Logausgaben machen, um die internen Datenstrukturen auf Loglevel 4 oder 5 auszugeben: Das ist Speicherloch-verdächtig und die Ausgabe könnte auch mit "toJSON" erfolgen (allerdings nicht so "hübsch"). Ist evtl. einen Versuch wert... Und wenn alles klappt, kann man diese Log-Ausgaben ggf. auch einfach komplett auskommentieren? (Dann ist FHEM nicht mit irgendwas beschäftigt, was im Zweifel keiner mehr braucht/sehen will....)
PrototypesEndloses Thema, aber wenn Prototypes genutzt werden, sollte man es korrekt machen...
Wenn man ohne Prototypes arbeitet, (was ich grundsätzlich begrüße), muss (!) man aber m.E. abfangen, wenn Fehleingaben erfolgen!
"shift" iVm. "defined-or" ist dabei die Variante, die ich selbst bevorzuge.
ZugangsdatenInsbes. Passwörter als Attribute vorzuhalten sollte man vermeiden. Besser set nutzen (iVm. setKeyValue()), gerne über CoolTux Passwort-Code.
return;"return undef;" ist oft zu finden, aber meistens (!) geht es ohne (es reicht also ein einfaches "return;"!), und man kann sich bei der Auswertung der Rückmeldung aus Perlcritic (stressfrei und informativ unter perlcritic.com/ zu finden) auf die interessanteren Sachen konzentrieren...
Kein (explizites) return am Ende einer Funktion wiederum braucht definitiv keiner! Macht klar, wenn eine Funktion aufgerufen wird, was die zurückliefern soll (und wenn nicht: "return;"). Raten ist für Helfer unschön, und scheinbar erratisches Verhalten ist dann für alle "Kunden" unschön...
FormatierungÜber Formatierungsfragen kann man auch lange diskutieren, ich nutze jedenfalls keine Tabs mehr, und mit
https://perltidy.com/ kommt man stressfrei zu hübsch formatiertem (=lesbarem) Code. Tabs haben den Nachteil, dass nicht jeder Editor die gleich darstellt, und damit sieht der Code immer anders aus, je nachdem, mit was man ihn ansieht. Wer nur für sich selbst coded, dem mag das egal sein...
packageTendenziell tut man sich vermutlich nicht allzu schwer, wenn man gleich in dieser Form anfängt... Man ist freier in der Benennung von Routinen und stolpert ggf. nicht über Probleme mit Funktionen wie "min" etc. (die im Main-Kontext was anderes zurückgibt wie die meisten denken!).
Wenn man das nicht macht, darf man bitte auch seine Funktionen und Variablen nicht generisch benennen!
Readings-updatesBitte prüfen, ob man nicht alles/größere Blöcke per "bulkUpdate" wegschreiben könnte.
Wer dekodiertes JSON hat, kann das ggf. einfach in Schleifen packen.
Wer nicht alles braucht, kann ja die benötigten Schlüssel vorher in einen Hash schubsen (und dabei ggf. auch "true" nach "on" umwandeln etc.), und den dann auf einen Rutsch durchgehen etwa in diese Richtung:
readingsBeginUpdate ($hash);
for my $record ($entries) {
for my $key (keys(%$record)) {
my $new = $record->{$key};
# Alten Reading-Wert auslesen
$old = ReadingsVal( $name, $key, '' );
next if $old eq $new;
# Readings schreiben, wenn es einen anderen Wert hat
readingsBulkUpdate($hash, $key, $new);
}
}
readingsEndUpdate($hash, 1);
use xyz; Module aus cpan ect.Wer wirklich Bedarf hat, libraries aus cpan zu nutzen, darf das gerne tun. Ähnliches gilt für features etc.. Wenn dann aber effektiv nur an einer kleinen Stelle Gebrauch davon gemacht wird, und/oder man das ganze dann auch mit etwas anderen Methoden (z.B. einen grep { } statt des vermutlich irgendwann deprecateten "smartmatch") hinbekommen würde, sollte man m.E. davon Abstand nehmen, die Welt für die anderen Anwender komplizierter zu machen als notwendig...
(Was anderes gilt für "core" Module! Insbesondere List::Util enthält ein paar sehr hilfreiche Funktionen...).
Quotes in Perlhttps://www.perlmonks.org/?node_id=401006 = ca. 2 Seiten Infos, die man kennen sollte. Mich wundert immer wieder, dass manche anscheinend nichts anderes kennen wie "doppel-Quotes" und sich dann einen Abbrechen mit concatenations und escape-Sequenzen... Das geht einfacher

.
commandrefDa viele mit der "copy-paste"-Methode an die Sache rangehen, wird oft auch "alte" Doku als Basis genommen. Nicht wirklich hilfreich...
"name"-Anker sind nämlcih irgendwann nicht mehr erlaubt (das ist was, was HTML allgemein betrifft und nichts mit FHEM oder dessen Entwicklungsvorgaben zu tun hat!), und mit der "id"-Variante (
https://wiki.fhem.de/wiki/Guidelines_zur_Dokumentation#id) bekommt man ohne allzu großen Zusatzaufwand auch direkt Hilfetextchen an setter, getter und Attribute (sichtbar für die Anwender in fHEMWEB) dran. Also: Why not?!?
Das war erst mal meine Summary, hoffe, sie hilft jemandem weiter

.
EDIT: kleinere Klarstellungen