[Refactoring] MySensors-Module

Begonnen von Beta-User, 28 April 2020, 17:47:51

Vorheriges Thema - Nächstes Thema

Beta-User

Hallo zusammen,

anbei mal ein Satz aktualisierter MySensors-Module. Habe die auch auf meinem Hauptsystem zum Testen laufen, weiß aber noch nicht, ob das alles stressfrei ist, weil doch einiges umgemodelt wurde.

Es ist einiges an perlcritic-Anregungen drin verarbeitet, aber ob das schon Bronzezeit ist...?

Was auch ging, war die "überflüssigen" Teile aus dem list zu verbannen, sehr schön!

Die verbliebenen perlcritic-Themen werden wohl etwas länger dauern, da ich die Anmerkungen zum Teil (noch) nicht verstehe und erst etwas Zeit (und Lust...) brauchen werde, um mich da einzudenken, was jeweils gemeint sein könnte.

Manche "Merkwürdigkeiten" - v.a. rund um Constants.pm - habe ich nicht wegbekommen, insbesondere geht es nicht so einfach, den EXPORT-Teil einfach nach vorne zu ziehen oder die Doppelungen in EXPORT_OK rauszunehmen... Im Moment habe ich noch keine Ahnung, wieso das so ist.

Zumindest habe ich die "Initialize"-Geschichte bei "Device" jetzt auch im Griff ;) . Immer noch schlammig, aber hoffentlich mit dem wenigsten "Drumrum"...

Ich poste das vorrangig, damit die MySensors-Leute einen Ort haben, um die zu testenden Versionen zu bekommen, aber wenn wer mag, kann er gerne Kommentare abgeben oder Vorschläge zum "Entzerren" der "high complexity"-Codeteile liefern.

Grüße,
Beta-User


Nachtrag:
Anbei nur noch 00_MYSENSORS.pm und 10_MYSENSORS_DEVICE.pm, die beiden anderen braucht man seit der Fassung vom 09.05.2020 nicht mehr!
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

zap

Frage: welchen Vorteil hat

$command eq ... and do {

gegenüber dem klassischen if elsif Konstrukt?
2xCCU3, Fenster, Rollläden, Themostate, Stromzähler, Steckdosen ...)
Entwicklung: FHEM auf AMD NUC (Ubuntu)
Produktiv inzwischen auf Home Assistant gewechselt.
Maintainer: FULLY, Meteohub, HMCCU, AndroidDB

RichardCZ

Zitat von: zap am 28 April 2020, 18:49:47
Frage: welchen Vorteil hat

$command eq ... and do {

gegenüber dem klassischen if elsif Konstrukt?

gar keinen.

           $key eq "altitude" and do {
...
            };


in Massen z.B. in 95_Astro

->

if ($key eq 'altitude') {
...
}


Da wollte jemand einfach nur mit logical shortcuts experimentieren.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

Beta-User

Nun ja, war halt da und hat funktioniert...
perlcritic mosert auch nicht - im Gegensatz zu der elsif-Kaskade, die ich an anderer Stelle eingebaut habe. Die sollte man aber auch irgendwie eleganter als "nur" mit "if" lösen können...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

RichardCZ

Der Punkt ist ja, dass "and do" weniger elegant ist als ein if.
Es ist ja äquivalent zu einer Ansammlung von ifs - keine if-elsif. Wenn man das also ersetzt, meckert perlcritic da auch nicht.

Logische Shortcuts sind eine tolle Sache - in Ausdrücken bei denen ein Wahrheitswert rauskullern soll:

if (mordsfunc(x) && $fast == 1) {...

kann man u.U. erheblich beschleunigen (wenn z.B. $fast == 1 oft nicht zutrifft), indem man die Sache einfach umdreht:

if ($fast == 1 && mordsfunc(x)) {...

dann wird mordsfunc(x) nämlich gar nicht ausgeführt.

Auch in if-elsif Ketten, oder tabular Ternaries... sollte man die wahrscheinlicheren und leicht abzufragenden Fälle
als erstes abhandeln. Im Notfall hilft ein Profiler oder einfache Prints.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

Sidey

If else Schlangen lassen sich teilweise ganz gut mit Dispatch Tables ablösen.

Geht einfach, wenn es nur eine Variable zum Entscheiden gibt. Hat man mehrere kann man ggf. noch geschickt kombinieren oder mehrere Einträge auf den gleichen Code verweisen lassen.


Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

Beta-User

#6
So,
zumindest ein kleiner weiterer update in der Sache...

Ein paar der "COMMAND_HANDLER"-Geschichten sind eliminiert, auch wenn ich "weniger elegant" jetzt nicht unbedingt als "dringenden Handlungsbedarf" übersetzen würde (?).

Etwas "Bauchweh" hatte ich mit den Block-grep-Modifikationen in Zeilen 191/194, aber zumindest ist mir das Testsystem nicht abgeschmiert beim rereadcfg... Scheint also zu passen. Damit wären wir mit überschaubarem Morphiumpflastereinsatz bei diesem Teilstück @perlcritic-level -3 :) .

Zitat von: Sidey am 28 April 2020, 22:17:17
If else Schlangen lassen sich teilweise ganz gut mit Dispatch Tables ablösen.
Klingt interessant, aber irgendwie habe ich Schwierigkeiten, das Stichwort, dieses Fragment

Zitat von: RichardCZ am 28 April 2020, 18:59:21
So bearbeitet, kann man das eventuell später noch weiter zu

my %dispatch = (
    'ThermostatState' => \&_handleDies,
    'WallThermostat' => \&_handleDas,
...
);

und den Code z.B. in diesen Zeilen gedanklich zu einer spontanen Vollsynthese mit
      MESSAGE_TYPE: {
        $type == C_PRESENTATION and do {
          onPresentationMsg($hash,$msg);
          last;
        };
        $type == C_SET and do {
          onSetMsg($hash,$msg);
          last;
        };
        $type == C_REQ and do {
          onRequestMsg($hash,$msg);
          last;
        };
        $type == C_INTERNAL and do {
          onInternalMsg($hash,$msg);
          last;
        };
        $type == C_STREAM and do {
          onStreamMsg($hash,$msg);
          last;
        };
      }

zu bewegen.

Sollte das am Ende einfach nur so sein?!?:
my %dispatch = (
    'C_PRESENTATION' => \&onPresentationMsg($hash,$msg),
    'C_SET'              => \&onSetMsg($hash,$msg),
    'C_REQ'             => \&onRequestMsg($hash,$msg),
    'C_INTERNAL' => \&onInternalMsg($hash,$msg),
    'C_STREAM'   => \&onStreamMsg($hash,$msg),
);


(Aber wie dann abschubsen? Das ist doch erst mal ein "einfacher Hash", man müßte also erst "$dispatch{$type}" abfragen, bevor da was zurückkommt? Sorry, immer noch DAM).

Grüße,

Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Sidey

Hi Beta-User,

Du hast das mit den Dispatch Tables verstanden.
Ich habe das im 00_Signalduino schon so für get und set umgesetzt, weil mir das doch zu unübersichtlich wurde.

Die Referenz auf die Sub rufst du dann so auf:

$dispatch{$Action}->($hash,$msg);

Hier auch ein paar Beispiele. :)
https://www.perlmonks.org/?node_id=456530

Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

RichardCZ

Zitat von: Beta-User am 29 April 2020, 16:37:57
Sollte das am Ende einfach nur so sein?!?:
my %dispatch = (
    'C_PRESENTATION' => \&onPresentationMsg($hash,$msg),
    'C_SET'           => \&onSetMsg($hash,$msg),
    'C_REQ'             => \&onRequestMsg($hash,$msg),
    'C_INTERNAL' => \&onInternalMsg($hash,$msg),
    'C_STREAM'   => \&onStreamMsg($hash,$msg),
);

Aber wie dann abschubsen?
Sidey hat eigentlich schon alle Zutaten beschrieben. Wenn Du es konkret willst,
ich würde es so schreiben:

my $dispatch = {
    C_PRESENTATION => \&onPresentationMsg,
    C_SET          => \&onSetMsg,
    C_REQ          => \&onRequestMsg,
    C_INTERNAL     => \&onInternalMsg,
    C_STREAM       => \&onStreamMsg,
};

$dispatch->{$type}->($hash, $msg);

Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

Wzut

Zitat von: Sidey am 29 April 2020, 16:55:08
Ich habe das im 00_Signalduino schon so für get und set umgesetzt
na also meine Gebete wurde erhört, gleich mal abschreiben gehen.....
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

Beta-User

Ähm, also irgendwie habe ich da jetzt so ziemlich alle Varianten durchgespielt...

Am "längsten lebt" Richards Variante, aber die zieht dann nach Eingang der ersten von einer Node gesendeten Meldung (vermutlich heartbeat=C_INTERNAL)  FHEM komplett in den Abgrund mit einem freundlichen Hinweis auf "Can't use an undefined value as a subroutine reference at ..." (Verweis auf die Zeile mit "$dispatch->{$type}->($hash, $msg);")
Die meisten anderen Kombinationen von %/$, Quotes, Klammern und -> verhindern das Starten der Module... Jetzt habe ich grade keine Lust mehr, dem weiter auf den Grund zu gehen (das Testen mache ich mit dem Hauptsystem) und kann auch einen Typo nicht ausschließen.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

RichardCZ

#11
Zitat von: Beta-User am 29 April 2020, 22:19:05
Ähm, also irgendwie habe ich da jetzt so ziemlich alle Varianten durchgespielt...

Am "längsten lebt" Richards Variante, aber die zieht dann nach Eingang der ersten von einer Node gesendeten Meldung (vermutlich heartbeat=C_INTERNAL)  FHEM komplett in den Abgrund mit einem freundlichen Hinweis auf "Can't use an undefined value as a subroutine reference at ..." (Verweis auf die Zeile mit "$dispatch->{$type}->($hash, $msg);")
Die meisten anderen Kombinationen von %/$, Quotes, Klammern und -> verhindern das Starten der Module... Jetzt habe ich grade keine Lust mehr, dem weiter auf den Grund zu gehen (das Testen mache ich mit dem Hauptsystem) und kann auch einen Typo nicht ausschließen.

Wie wäre es mal den Code zu zeigen? Ich habe in solchen Fällen auch keine Lust auf Wahrsagerei.

Fehlermeldung besagt eigentlich nur, dass  $dispatch->{$type} undefiniert ist. M.a.W. Du bekommst einen $type rein, der nicht im Hash drin ist.

ref $dispatch->{$type} eq 'CODE' ? $dispatch->{$type}->($hash, $msg) : Log("Irgendjemand versucht mir >$type< reinzudrücken");
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

Sidey

Du kannst auch einfach den commit in dein Repo hauen.
Dort kann man auch konkret Hilfestellung geben :)
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker

Beta-User

Bitte etwas Geduld, ich hatte gestern nur keine Lust/Reserven mehr, das vollständige Bild zu liefern, und testen kann man mMn. nur, wenn man Hardware hat (oder das irgendwie aufwändig simmuliert).

(Der Code ist im wesentlichen aber genau das, was hier im ersten Beitrag verfügbar ist, ich habe dann gestern nur die 9 Zeilen von Richard wieder gegen die ursprüngliche MESSAGE_TYPE-Variante rückgetauscht...)

Bei Gelegenheit werde ich mal den Vorschlag mit dem Vorabtest auf den richtigen ref einbauen. Ist irgendwie seltsam, denn lt. Doku unter https://www.mysensors.org/download/serial_api_20#command sollte es wirklich nur diese $type geben; kann aber natürlich sein, dass da sehr viel mehr garbage über die Serielle Schnittstelle reinkommt, als ich bisher dachte...

Fortsetzung folgt :) .

(Und der Tipp mit dem Test war in etwa der Schubs, den ich brauchte, btw.. Mehr Kaffeesatzleserei war gar nicht meine Intention, es ging eher darum, rechtzeitig zu melden, dass "Houston" zu informieren ist, bevor Wzut da von "einfacher Gebetserhörung" ausgeht).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Wzut

Zitat von: Beta-User am 30 April 2020, 12:21:13
bevor Wzut da von "einfacher Gebetserhörung" ausgeht
Was , wie ? also ich bin glücklich, bei mir läuft zum einen die "einfache" Variante von Richard also auch die Luxusversion %get / %set von Sidey aus 00_SIGNALduino
D.h. ich kann nun von Fall zu Fall und je nach Modul unterscheiden ob die einfache Version reicht oder ob es die aufgebohrte sein muß.
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher