[Gelöst] Hex String generieren

Begonnen von GU!DO, 11 November 2017, 15:13:58

Vorheriges Thema - Nächstes Thema

GU!DO

Hallo Zusammen,

ich wußte nicht, wohin, daher frage ich mal in dieser Rubrik.

Ich versuche grad FHEM mit openHCAN zu verheiraten, und habe folgendes Problem:

Ich würde gerne einen Hex-String an syswrite übergeben, das funktioniert folgender maßen einwandfrei:

$data = "\x00\x8e\x10\x03\x03\x00\x00\x00\x05\x0a\x46\xb7\xec\x6a\x70\xb7";
syswrite($hash->{CD}, $data);


Ein Teil des Strings ist variabel. Diesen würde ich gerne abhängig von den Daten des Devices generieren, und mit dem Rest verknüpfen. Etwa so:


my $nachricht = '050b46bf'
my $data = "\x00\x8e\x10\x03\x03\x00\x00\x00".$nachricht."\xec\x6a\x70\xb7";


Ich habe schon Stunden mit googlen und versuche verbracht, jedoch bekomme ich es nicht hin.

Wie bekomme ich $nachricht in ein passendes Format um es einzufügen???

Schon mal vielen Dank für eure Hilfe

Guido

viegener

Dein Problem ist den String Nachricht von
$nachricht = '050b46bf'

nach

$nachricht = '\x05\x0b\x46\xbf'

zu konvertieren?

Etwas wie
$nachricht =~ s/([0-9a-f][0-9a-f])/\\x$1/g;

sollte das erledigen, ohne das komplett getestet zu haben
Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

GU!DO

Hallo viegener,

Danke für die schnelle Antwort. Das hatte ich auch schon probiert, aber leider löst es mein Problem nicht.

Ich vermute, dass Perl das Ergebnis des Regex anders interprätiert als den in doublequotes eingefassten String.

Wenn ich das Ergebnis nach dem Verknüpfen mit Dumper ausgebe, sieht es so aus:

\\x05\\x0b\\x46\\xbf�jp�'

Ich würde sagen: Die doublequote Strings sind binär?!? und Perl hat die Backslashes escapet?!?

Wenn ich die doublequotes der umfassenden Strings durch singlequotes ersetzte, habe ich das gleiche Ergebnis für alle 3 Komponenten:

'\\x00\\x8e\\x10\\x03\\x03\\x00\\x00\\x00\\x05\\x0b\\x46\\xbf\\xec\\x6a\\x70\\xb7';


Das Problem ist, das ich diesen String nicht senden kann. Der hcand daemon, erwartet 16 Byte große Pakete.
Syswrite gibt als dann jedoch zurück, ein 64Byte großes Paket gesendet zu haben.

viegener

Ich denke Du musst Dich mit etwas mehr perl befassen.
Grundsätzlich gibt es bei doublequotes in perl verschiedene Besonderheiten, dazu gehört auch, dass \ einige Sonderfunktionen hat, z.B. wird "\x41" durch das Zeichen A ersetzt da hex 41 dem A entspricht. Mit einfachen quotes passiert diese Ersetzung nicht.

Mein regexp macht genau das was Du eigentlich haben willst, die Zeichen werden in einzelne Bytes umgewandelt, Genau das willst Du ja für die Ausgabe haben - 16 einzelne Bytes, wenn ich das richtig verstehe?


my $nachricht = '050b46bf'
$nachricht =~ s/([0-9a-f][0-9a-f])/\\x$1/g;
my $data = "\x00\x8e\x10\x03\x03\x00\x00\x00".$nachricht."\xec\x6a\x70\xb7";


Sollte genau das ergeben, analog könntest Du auch mit der perl pack-Funktion arbeiten, die macht etwas ähnliches wie der regexp
Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

GU!DO

Ich habe grad nochmals nachgesehen, ob ich die Frage wirklich in das Forum für Anfängerfragen gepostet habe.

Vielen Dank für Deine Hilfe, und Entschuldigung, dass ich in einem Anfängerforum eine Anfängerfrage stelle.

Die Besonderheiten von Doublequotes (in Bezug auf das escapen von Backslashes) habe ich, als ich vor 2 Wochen angefangen habe mich mit perl zu befassen, gelesen.

Ich habe es zur Sicherheit grad nochmals getestet: Das Ergebnis Deiner "Lösung" ist genau das, was ich in meiner letzen Antwort geschrieben habe.

Gebe ich es mit Dumper aus, bekomme ich "\\x00" angezeigt, gebe ich es mit print aus, bekomme ich "\x00" angezeigt.

Das ändert aber nichts an der Tatsache, dass der erste und der letzte Teil ("\x00\x8e\x10\x03\x03\x00\x00\x00" und "\xec\x6a\x70\xb7") sowohl mit Dumper, als auch mit print binär ausgegeben werden. Der eingefügte Teil jedoch nicht!

Daher ist die Frage offen, wie bekomme ich das hin?

viegener

#5
Kein Grund das als Angriff zu verstehen, ich wollte nur helfen ..

Meine Aussage war etwas durcheinander weil mit nicht klar war, ob Du einzelne Bytes oder \x.. im String stehen haben willst

Also Du möchtest die Daten binär haben und nicht als \x.. im String.

Wie oben erwähnt wäre dann der Ansatz mit pack wohl der Richtige:

my $nachricht = '050b46bf';
my $s = pack( 'H2', $nachricht );
my $data = "\x00\x8e\x10\x03\x03\x00\x00\x00".$s."\xec\x6a\x70\xb7";
Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

GU!DO

Sorry, war nicht so gemeint. :-[

Ich sitze seit heute Vormittag an diesem Sch..., da war Deine Bemerkung der Tropfen, der das Fass zum überlaufen gebracht hat...

Es ist mir klar, dass Du deine Zeit auch mit was schönerem verbringen kannst, als Perl Noobs zu helfen.  ;)

Daher vielen Dank für den Tip. Gefühlt ist es das Beste, was ich heute gesehen habe.  :)

Ich werde das gleich testen, und mich melden, wie es ausgegangen ist.

GU!DO

Also, er sendet 16 Bit, aber leider die falschen...

                                  05 0b 46 b7                     => Das ist der Wert den ich zum Versand gebe.
008e100303000000  05 ec 6a 70  b71173b7   => Das ist die Nachricht, die gesendet wird.
008e100303000000  05 0a 46 b7  ec6a70b7   => Diese Nachricht wird gesendet, wenn ich den String an einem Stück schreibe:
                                                                             "\x00\x8e\x10\x03\x03\x00\x00\x00\x05\x0a\x46\xb7\xec\x6a\x70\xb7"


GU!DO

P.S. der "letzte" Teil des zusammengesetzten Strings passt ebenfalls nicht. Der ist aber für meine Zwecke uninteressant.

amenomade

Probier mal mit H* statt H2:
my $nachricht = '050b46bf';
my $s = pack( 'H*', $nachricht );
my $data = "\x00\x8e\x10\x03\x03\x00\x00\x00".$s."\xec\x6a\x70\xb7";
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

viegener

amenomade war schneller, für 2 muss natürlich die Länge der Konvertierungen stehen (also 8 oder eben *)
Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

GU!DO

Hallo amenomade,

Vielen vielen Dank, es läuft!  ;D

Hab schon fast nicht mehr dran geglaubt.

Kannst Du mir bitte den Unterschied erklären. Habe bisher nur das gefunden:

"Jedem Zeichen (bzw. jeder in runden Klammern stehenden Gruppe von Zeichen) kann eine (optional zwischen [ und ] stehende) Dezimalzahl folgen, die als Wiederholungszähler verwendet wird. Ein Sternchen (*) kennzeichnet alle verbliebenen Argumente"

Aber die Erklärung scheidet ja, wegen der fehlenden Klammern aus - oder gibt es da wieder eine perl Ausnahme?!?  :o

Auf jeden Fall nochmal vielen Dank. Das hat mich schon Stunden gekostet!

amenomade

H bearbeitet nur 1 Zeichen
H2 nur 2
H* alle

In deinem Fall hätte H8 auch funktioniert, da '050b46bf' 8 Zeichen lang ist
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

GU!DO

OK. Vielen Dank.

Ich habe das nochmal probiert, ob man H8 oder H[8] (wie im Buch "Perl kurz & gut" beschrieben) schreibt ist vollkommen egal.

Das treibt mich bei perl wirklich in den Wahnsinn.

Wenn ich ein Problem habe, und mir Quellcode suche um diesen für mich zu nutzen, findet immer wieder Syntax, von der man sich denken kann was sie bedeutet, aber eine Erklärung, dass sie wirklich genau das tut was man erwartet, findet man oft nirgendwo.

so z.B.
my $hash = shift;
Schein ja Standard zu sein. Gefunden habe ich dazu jedoch erstmal nix.

In Einführung in Perl:
$m = shift(@array);

in Perl kurz & gut
Zitat
shift [ @Array ] Verschiebt den ersten Wert aus dem Array

Lediglich als ich mir das Kamelbuch gekauft habe, habe ich es gefunden.
Das konnte ich aber nicht als eBook bekommen und in gedruckt ist es sooo unhandlich, dass es keinen Spaß macht was nachzuschlagen.

viegener

Kann ich nachvollziehen, ich programmiere auch noch häufig via google  ;)
Obwohl ich jetzt schon seit letztem Jahr intensiv in perl arbeite. Es gibt so ein paar Absonderlichkeiten in perl und die Anführungszeichen sowie die "Variable" $_ / @_ gehören dazu, richtig wirr wird es bei unicode.

Das mit dem shift ist aus meienr Sicht so, dass die Parameter einer Routine immer als Array übergeben werden und dann sind quasi folgende Varianten möglich


my ( $par ) = @_ ;

my $par = shift;

my $par = shift( @_ );
/code]

und vermutlich noch ein paar mehr...

Für mich ist dieses $_-Zeug weder elegant, noch gut lesbar und wg. globalem Scope auch fehlerträchtig. Aber ich hoffe das löst jetzt keinen Glaubenskrieg aus, denn das ist nur meine persönliche Meinung
Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können