seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11180
Wohnort: München
|
Wenn du in eine ASCII-Tabelle schaust, siehst du, dass ein S den Dezimal-Wert 83 bzw. den Hex-Wert 0x53 hat:
$ printf '%02x\n' 83
53
$ echo $'\x53'
S
$ echo -n $'\x53' | od -x
0000000 0053
0000001
Damit ist das bei gleicher Byte-Reihenfolge am Zielgerät eigentlich genau das was du willst - das Low-Byte enthält die Information. Zur Erklärung: die Bash erlaubt es mit dem \x -Prefix 8-Bit Zeichen anzugeben (vgl. info bash , Abschnitt zum Quoting):
Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped
characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are
decoded as follows:
[...]
\nnn the eight-bit character whose value is the octal value nnn (one to three digits)
\xHH the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
\uHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four
hex digits)
\UHHHHHHHH
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to
eight hex digits)
\cx a control-x character
The expanded result is single-quoted, as if the dollar sign had not been present.
A double-quoted string preceded by a dollar sign ($"string") will cause the string to be translated
according to the current locale. If the current locale is C or POSIX, the dollar sign is ignored. If the
string is translated and replaced, the replacement is double-quoted.
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4578
Wohnort: Berlin
|
@fllopi: Nein das ist nicht zu viel denn Du willst ja nicht die Zeichenkette '53' senden, die aus zwei Bytes besteht, sondern ein Byte mit dem Wert 83 (dezimal) beziehungsweise 53 (hexadezimal). Und dieser Wert als Zeichen ist ein grosses 'S'. Da der Wert unter 128 liegt, kannst Du das in der ASCII-Tabelle nachlesen. Oder anders herum: Das Zeichen 'S' hat den Bytewert 83 (dezimal).
|
fllopi
(Themenstarter)
Anmeldungsdatum: 31. August 2015
Beiträge: Zähle...
|
Ok habe es erst einmal so weit verstanden vielen dank euch allen 😀
Ich werde es hoffentlich in den nächsten Tagen noch testen können.
|
fllopi
(Themenstarter)
Anmeldungsdatum: 31. August 2015
Beiträge: 26
|
Ich hatte es nun getestet und es geht schon am Anfang nicht -_-
Aber habe ich es richtig verstanden? Der Befehl | echo -e "\x$(printf '%02x' "5")" >> /dev/ttyS0
|
sendet einen Byte an die Serielle schnittstelle.
Das Problem könnte doch sein das der Wert 5 im nicht darstellbarem Bereich liegt und ich versuche das Zeichen zu senden. Mit anderen Worten ich versuche etwas darzustellen was nicht darzustellen geht.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Einmal sollte doch das Newline unterdrückt werden:
Zum anderen verstehe ich nicht, wieso Du echo und printf schachtelst. Was kann man damit erreichen?
Einfach:
| echo -en "\x5" >> /dev/ttyS0
|
| for foo in {0..255}
do
echo -en "\x$foo" >> /dev/ttyS0
done
|
Das sollte nacheinander alle Bytes von 0 bis 255 verschicken.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12832
|
fllopi schrieb: Ich hatte es nun getestet und es geht schon am Anfang nicht -_-
Was genau hast Du getestet? Richtig fragen
Aber habe ich es richtig verstanden? Der Befehl | echo -e "\x$(printf '%02x' "5")" >> /dev/ttyS0
|
sendet einen Byte an die Serielle schnittstelle.
Tatsächlich zwei Bytes. Du kannst das einfach mit den hier bereits schon genannten Werkzeugen nachvollziehen. Probier das doch einfach mal aus: | $ echo -e "\x$(printf '%02x' "5")" | od -tx1c
0000000 05 0a
005 \n
0000002
|
Da sieht man schon, dass ein Zeichen zu viel gesendet wird.
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4578
Wohnort: Berlin
|
@user_unknown: Dein zweites Beispiel funktioniert nicht weil foo die Dezimaldarstellung von den Zahlen enthält, hinter dem \x aber die Hexadezimaldarstellung stehen muss. Da wird dann vielleicht auch der Sinn der Schachtelung von printf und echo klar: printf wandelt die Dezimaldarstellung in die Hexadezimaldarstellung um. Wenn man einen festen Wert hat, kann man gleich '\x05' schreiben, aber wenn man eine Variable mit einem Wert in Dezimalschreibweise hat…
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Marc_BlackJack_Rintsch schrieb: @user_unknown: Dein zweites Beispiel funktioniert nicht weil foo die Dezimaldarstellung von den Zahlen enthält, hinter dem \x aber die Hexadezimaldarstellung stehen muss. Da wird dann vielleicht auch der Sinn der Schachtelung von printf und echo klar: printf wandelt die Dezimaldarstellung in die Hexadezimaldarstellung um. Wenn man einen festen Wert hat, kann man gleich '\x05' schreiben, aber wenn man eine Variable mit einem Wert in Dezimalschreibweise hat…
Ah, ja, jetzt dämmert es mir. Bin zu sehr mit dem Advent-of-Code beschäftigt, um mich tiefer mit anderen Sachen zu beschäftigen. ☺ Aber für eine kleine Bashhandarbeit hat es dann doch gereicht. Ich glaube ich habe ein printf-Trauma. Mir wird schlecht, wenn ich es sehe, aber ich habe keine rationale Begründung. Vielleicht doch - als ich das kennenlernte haben die Compiler nicht in die Ausdrücke reingeschaut und keine Typprüfung gemacht. Heute gibt es äquivalente Befehle bei Scala beispielsweise, da meckert der Compiler, wenn es nicht passt. | #!/bin/bash
tohex () {
val=$1
hi=$((val/16))
lo=$((val%16))
hexis=($(echo {0..9} {a..f}))
echo -en \x${hexis[hi]}${hexis[lo]}
}
|
Und der Test:
| for i in {0..255}; do tohex $i; done | od -tx1c
|
Eine Absicherung für Werte < 0, größer 255, Nichzahlen usw. fehlt noch.
Dafür gibt es das auch als Einzeiler:
| tohex () { val=$1; hi=$((val/16)); lo=$((val%16)); hexis=($(echo {0..9} {a..f})); echo -en "\x${hexis[hi]}${hexis[lo]}"; }
|
|
fllopi
(Themenstarter)
Anmeldungsdatum: 31. August 2015
Beiträge: 26
|
OK, OK das geht.
Ich prüfe es an dem Gerät welches durch das Script einen Befehl erhalten soll, welcher demnach ausgeführt werden muss.
Was mir nun aber noch aufgefallen ist, ist das ich das was das Gerät zurückgibt wohl auch umwandeln muss, da ich eine if funktion innerhalb meines Skriptes habe.
Oder geht das (unter der Voraussetzung das was eingelesen werden soll die Wertigkeit 4d hat)?
| varA=$(echo -e "\x$(printf '%02x' "4")")
varB=$(cat < /dev/ttyS0)
if [ "varA" = "varB" ]
then
.
.
.
|
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
fllopi schrieb: Was mir nun aber noch aufgefallen ist, ist das ich das was das Gerät zurückgibt wohl auch umwandeln muss, da ich eine if funktion innerhalb meines Skriptes habe.
Oder geht das (unter der Voraussetzung das was eingelesen werden soll die Wertigkeit 4d hat)?
Das entspricht einem Groß-M.
|
fllopi
(Themenstarter)
Anmeldungsdatum: 31. August 2015
Beiträge: 26
|
Sorry hatte mich nicht ganz klar ausgedrückt.
Ich meinte nicht 4D in Hexadezimal sondern die 4 als Dezimal.
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
fllopi schrieb: Sorry hatte mich nicht ganz klar ausgedrückt.
Ich meinte nicht 4D in Hexadezimal sondern die 4 als Dezimal.
Das ist nun auch nicht ganz eindeutig ... was soll dort "dezimal" bedeuten ?? Denn über die (serielle) Schnittstelle gehen nur und ausschließlich hexadezimale Zeichen. (m.a.W.: "pure Zahlen" gibt es dort überhaupt nicht !) Deshalb war es ja die ganze Zeit die Frage, ob Deine 4 das ASCII-Zeichen 0x4D (="4") sein soll, oder ob Du 0x04 (= Hex-Zahl 04) meinst. Grundsätzlich ist es sowohl für echo / printf als auch für die Schnittstelle egal, was Du da drüber schickst. Du musst halt nur das richtige 'reinfüttern, dann geht das alles. LG, track
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Nein, über die serielle Schnittstelle gehen Daten. Auf einer technischen Ebene wollen die meisten von uns gar nicht so genau wissen, was das ist. Die Schnittstelle übersetzt es aber für uns in Datenpäckchen, die kleinste Einheit, die wohl ankommt, ist wohl ein Byte. Das können wir zwar wieder bitweise zerlegen, aber ein einzelnes Bit kann man m.W. nicht schicken. Für Bytes gibt es konventionelle Darstellungsformen und weniger konventionelle, hexadezimal, oktal, dezimal, Buchstaben, Farben, Noten. Der Buchstabe kann eine Ziffer sein, was den Zahlenformaten eine weitere Verwechslungsmöglichkeit zufügt. 0x04 konventionelles Hexadezimalformat 0004 konventionelles, aber weithin unbekanntes Oktalformat 4 dezimal ist in unserer Kultur der Normalfall und ohne Auszeichnung '4' Zeichen, die Ziffer 4 '♦' Karozeichen, in alten Asciitabellen für Byte 0x04 oft zu finden, wenn ich recht liege. Hier habe ich etwas aus einer UTF-8-Tabelle für ♦ ♦ verwendet 0000:0100 binäres Format, schlecht zu erraten, solange nicht mindestens ein Bit auf 1 gesetzt ist. ☺ IIII simples, römisches Format IV römisches Format mit Komprimierung.
Dass 4d für Dezimal stehen soll ist wirklich schlecht zu erraten. Ich glaube selbst im Matheunterricht, wenn man Zahlenbasen durchnimmt, verwendet man ein Niedriggestelltes d, was die Forensoftware zumindest nicht per Button unterstützt, und ich meine auch als Präfix, nicht Postfix, oder? Die verbreitete Krankheit jedes Wort, das nicht im Wortschatz eines 3jährigen ist, in Anführungsstriche zu setzen, durchkreuzt aber jeden vernünftigen Versuch damit umzugehen - immerhin sind auch Anführungsstriche als Zeichendarstellung eines Hexadezimalcodes zu interpretieren - das paarweise Auftreten hilft hier aber der Erfassung.
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4578
Wohnort: Berlin
|
Über serielle Schnittstellen gehen einzelne Bits. Ob da eventuell eine Hardware zwischen ist, die ein Byte puffert und einen nur ganze Bytes senden/empfangen lässt ist dann noch einmal eine andere Frage. Aber selbst dann können und werden oft noch zusätzliche Bits gesendet und empfangen, zum Beispiel „start“, „parity“, und „stop“ bits, so das beispielsweise 9, 10, oder 11 Bits pro Byte gesendet/empfangen werden. Es kann auch sein das die Hardware erlaubt per Programm jede einzelne Leitung beliebig zu schalten. Dann kann man wirklich einzelne Bits senden und sich eigene Protokolle ausdenken, oder übliche serielle Protokolle rein in Software zu implementieren (Stichwort „bit banging“). Das Karozeichen (♦) wird wohl eher nicht in einer ASCII-Tabelle stehen. Der Bytewert 4 ist dort das „end of transmission“ (EOT) Steuerzeichen. Das Karozeichen ist normalerweise das 4. Zeichen im IBM VGA-Zeichensatz. Und auch wenn die meisten Programmiersprachen unter DOS den Bytewert einfach unverändert weiterreichen für die Ausgabe und dann so ein Karo auf dem Bildschirm steht, ist das an der Stelle kein Wert der offiziell in einer der Codepages auftaucht, denn die sind als Obermenge von ASCII definiert. Man kann also das Karozeichen beispielsweise nicht in CP437 (die normale Kodierung von DOS) oder CP850 (deutsche Kodierung für DOS) konvertieren:
$ echo ♦ | iconv -f utf8 -t cp437
iconv: illegal input sequence at position 0
$ echo ♦ | iconv -f utf8 -t cp850
iconv: illegal input sequence at position 0 Und umgekehrt wird aus einem Bytewert 4 auch kein Karozeichen in UTF-8, sondern das bleibt der Bytewert 4:
$ echo -ne '\x04' | iconv -f cp437 -t utf8 | hd
00000000 04 |.|
00000001 Das tiefgestellte „d“ als Notation kenne ich übrigens nicht aus Mathe, bei uns wurde die Zahlenbasis tiefergestellt angehängt. Also beispielsweise 4d₁₆=77₁₀=115₈=1001101₂. Für die tiefgestellten Zahlen habe ich die Forensoftware übrigens gar nicht gebraucht, das sind eigene Zeichen in Unicode. ☺
|