Implementierung/Aufruf eines proprietären Protokolls (RSCP von E3/DC) - wie?

Begonnen von Dirk070, 25 August 2022, 17:28:18

Vorheriges Thema - Nächstes Thema

Dirk070

Hallo zusammen,

kurz zu mir, damit meine Frage für Euch einzuordnen ist: ich bin Entwickler im betriebswirtschaftlichen Kontext, vor Urzeiten gestartet mit Cobol und dann später zu ABAP (SAP) gewechselt.
Stand heute lässt der Job wenig Zeit, programmieren macht mir immer noch Spaß und so bastel ich mit PERL hier FHEM, immer wieder unterstützt durch das tolle Forum hier.
Meine FHEM-Instanz läuft auf einer Syno in einem Docker-Container.

Zur Sache: ich habe ein E3DC Hauskraftwerk. Dieses kann per MODBUS aus FHEM adressiert werden: https://forum.fhem.de/index.php/topic,109735.0.html
Darüber kommen leider nicht alle verfügbaren Daten und der Zugriff geschieht nur lesend.

Daher habe ich nach einer Möglichkeit gesucht, das proprietäre RSCP zu nutzen.
Einen Ansatz habe ich über einen Docker-Container mit REST-API gefunden https://forum.fhem.de/index.php/topic,128659.0.html

Was mir fehlt: das Protokoll kann auch historische Werte liefern und dies pro Tag in einem 15-Minuten Intervall (ist z.B. bei ioBroker beschrieben https://forum.iobroker.net/topic/49217/test-adapter-e3dc-rscp-v0-0-x-github/329).
Das bietet die REST-API leider nicht, sondern nur die kummulierten Werte pro Tag.

Es gibt diverse Code-Beispiele und Projekte zur Implementierung des RSCP-Protokolls:

Was wären denn aus Eurer Sicht ein geeigneter Ansatz, das Protokoll für FHEM nutzbar zu machen?
Alles in PERL von scratch neu zu programmieren, dürfte den Rahmen sprengen (meinen auf jeden Fall  ;))
Lässt sich aus den vorhandenen Implementierungen etwas für FHEM nutzbar machen oder übernehmen?
Optimal wäre ja tatsächlich eine Abbildung in PERL, so wären wir maximal flexibel und blieben im FHEM-Kontext.

Bevor ich weiter suche und immer noch mehr Fragezeichen für mich generiere, wollte ich bei Euch mal anfragen, wie Ihr so etwas angehen würdet.

Vielen Dank an jeden, der bis hierhin überhaupt gelesen hat und dann hoffentlich auch noch eine Idee hat. :)

Viele Grüße
Dirk

Beta-User

Schwierig...
Bei dem Python-link war ein weiterer zu einer MQTT-Implementierung zu finden. Falls das eine umfassende Implementierung ist, ist das vermutlich der schnellste Weg. Also externer Python-Dienst+M2Server.

Vielleicht auch fhempy (dominik).
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

Dirk070

Danke für Deine Einschätzung. Parallel habe ich ein C++ Beispiel auf dem Mac unter Xcode ausführen können.
Das bringt zumindest die Möglichkeit des Debuggings und vielleicht lohnt sich dann doch eine Portierung zu Perl.

Sobald ich da weiterkomme, frage ich hier sicher mal das ein oder andere an.

Dirk070

Hallo zusammen,

ich versuche nun, die wesentlichen Funktionen aus dem Python-Programm in Perl zu übernehmen.
Die Verbindung zum E3DC wird mit dem Senden eines Frames begonnen. Dieser besteht aus 2 Teilen.

Der 1. Teil ist so in Pthon programmiert:

def rscpFrame(data):
    """Generates RSCP frame."""
    magic = endianSwapUint16(0xE3DC)
    ctrl = endianSwapUint16(0x11)
    t = time.time()
    sec1 = math.ceil(t)
    sec2 = 0
    ns = round((t - int(t)) * 1000)
    length = len(data)
    packFmt = "<HHIIIH" + str(length) + "s"
    frame = struct.pack(packFmt, magic, ctrl, sec1, sec2, ns, length, data)
    crc = zlib.crc32(frame) % (1 << 32)  # unsigned crc32
    frame += struct.pack("<I", crc)
    return frame


In Perl habe ich in der 99_myUtils eine Test-Routine definiert, die aber noch nicht komplett ist.

sub StartFrame($) {
my ($Input) = @_;
my $Status = 0;

my $be = pack('n', 0xE3DC);
my $le = pack ('v', $be);
my $magic = $le;

$be = pack('n', 0x11);
$le = pack ('v', $be);
my $ctrl = $le;

Log 1,"Test aus 99_myUtils, Magic: $magic";
Log 1,"Test aus 99_myUtils, CTRL: $ctrl";
##print $magic . "\n";
##print $ctrl. "\n";

use Time::HiRes qw(time);
use POSIX;

my $epoc = time();
Log 1,"Test aus 99_myUtils, EPOC: $epoc";
##print $epoc. "\n";

my $sec1 = ceil($epoc);
my $sec2 = 0;

my $zwns = (($epoc - int($epoc)) * 1000);

my $ns = sprintf ("%.0f", $zwns);
Log 1,"Test aus 99_myUtils, Nanosek: $ns";

##print $ns. "\n";

return $Status
};


Im Web-Perl-Editor gibt es keine Fehlermeldungen, in FHEM aber diese hier:
2022.09.23 17:01:06 1: --> Test-Start <--
2022.09.23 17:01:06 1: PERL WARNING: Argument "��" isn't numeric in pack at ./FHEM/99_myUtils.pm line 586.
2022.09.23 17:01:06 3: eval: { Log 1, "--> Test-Start <--";             StartFrame("Test");    Log 1, "--> Test-Ende <--"; }
2022.09.23 17:01:06 1: PERL WARNING: Argument "\0^Q" isn't numeric in pack at ./FHEM/99_myUtils.pm line 590.
2022.09.23 17:01:06 3: eval: { Log 1, "--> Test-Start <--";             StartFrame("Test");    Log 1, "--> Test-Ende <--"; }
2022.09.23 17:01:06 1: Test aus 99_myUtils, Magic:
2022.09.23 17:01:06 1: Test aus 99_myUtils, CTRL:
2022.09.23 17:01:06 1: Test aus 99_myUtils, EPOC: 1663945266.92828
2022.09.23 17:01:06 1: Test aus 99_myUtils, Nanosek: 928
2022.09.23 17:01:06 1: --> Test-Ende <--


Dadurch sind die Variablen Magic und CTRL leer.

Kann mir jemand bei der Portierung an diesen Stellen helfen?

Danke Euch und schöne Grüße
Dirk