fireworker72
Anmeldungsdatum: 11. März 2017
Beiträge: Zähle...
|
Grüß euch Hab Schon wider eine Frage Ich möchte in Bash von Hex zu Bin wandeln hab aber folgendes Problem 19 hex = 25 dez = 00011001 bin | echo "ibase=16 ; obase=2 ; 19" | bc Ergebnis 11001
|
01 hex = 01 dez = 00000001 bin
| echo "ibase=16 ; obase=2 ; 01" | bc Ergebnis 1
|
Wo ist der Rest auf die 8 Bits?
00011001 11001 Wie kann Ich es anstellen das die Ausgabe immer automatisch auf 8 Bits erfolgt? Danke und LG
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17413
Wohnort: Berlin
|
Meines Wissens macht bc das nicht - das musst Du wohl mit printf machen.
| printf "%08d" $(echo "scale=8; ibase=16 ; obase=2 ; 01" | bc)
|
|
fireworker72
(Themenstarter)
Anmeldungsdatum: 11. März 2017
Beiträge: 59
|
user_unknown schrieb: Meines Wissens macht bc das nicht - das musst Du wohl mit printf machen.
| printf "%08d" $(echo "scale=8; ibase=16 ; obase=2 ; 01" | bc)
|
Danke prinzipiell funktioniert das, aber nur bei einem Hexwert xx
wenn aber mehr kommen stimmt das wider nicht z.B.: 0C 92 1 1 0 0 1 0 0 1 0 0 1 0 sind 12 Stellen statt 16 es kommen manchmal 2,4 oder 14 Doppel Hexzahlen wo kann Ich noch schrauben? LG
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10940
Wohnort: München
|
Verstehe ich das richtig, dass du ankommende Hex-Zahlen in binär Repräsentation mit führenden Nullen auffüllen willst, damit ein ganzzahliges Vielfaches von 8 Bits entsteht?
1
2
3
4
5
6
7
8
9
10
11
12 | #!/usr/bin/env python3
import fileinput
import math
for line in fileinput.input():
values = (int(h, 16) for h in line.split())
for v in values:
n_bits = math.ceil(math.log2(v)) if v else 1
n_byteblocks, rest = divmod(n_bits, 8)
if rest or not n_byteblocks:
n_byteblocks += 1
print(f"{v:0{n_byteblocks * 8}b}")
|
Das macht dann sowas mit Eingaben, die es auf stdin (oder aus als Argumenten übergebenen Dateien) bekommt:
$ ./hex2bin.py <<< '0C 92 0 1 FFF FACED DEADBEEF'
00001100
10010010
00000000
00000001
0000111111111111
000011111010110011101101
11011110101011011011111011101111
|
fireworker72
(Themenstarter)
Anmeldungsdatum: 11. März 2017
Beiträge: 59
|
also was Ich genau vorhabe
Berechnung nach IEEE 754 Ich bekomme Hex werte vom KNX Bus xx oder xx xx oder xx xx xx xx die muss Ich umwandeln in Bin 19 hex = 25 dez = 00011001 bin 01 hex = 01 dez = 00000001 bin dann muss Ich aus den Bin Zahlen einzelne Bereiche extrahieren 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 1 VEEEEMMM MMMMMMMM V= Vorzeichen
E= Exponent
M= Mantisse
$Vbin = 0
$Ebin = 0011
$Mbin = 00100000001 die Variablen dann in Dez umrechnen $Vdez=0 (bedeutet Vorzeichen positiv
$Edez=3
$Mdez=257 und dann rechnen $Mdez*0101*2^$Edez 257x0,01=2,57 2^3=8 2,75x8=20,56 $Val=20,56 und die $Val dann versenden Vielleicht geht das auch irgendwie einfacher als das jetzt genau so Schritt für Schritt in Bash zu machen LG
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10940
Wohnort: München
|
fireworker72 schrieb: Vielleicht geht das auch irgendwie einfacher als das jetzt genau so Schritt für Schritt in Bash zu machen
Klar, das ist eines der Probleme wo man mit ausgewachsenen Programmiersprachen mehr Spaß hat - aus https://github.com/smurfix/pknyx/blob/master/pknyx/core/dptXlator/dptXlator2ByteFloat.py#L105 (GPL V2+ Code):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | #!/usr/bin/env python3
import fileinput
def dataToValue(data):
sign = (data & 0x8000) >> 15
exp = (data & 0x7800) >> 11
mant = data & 0x07ff
if sign != 0:
mant = -(~(mant - 1) & 0x07ff)
value = (1 << exp) * 0.01 * mant
return value
for line in fileinput.input():
raw_half_floats = (int(p, 16) for p in line.split())
for e in raw_half_floats:
print(dataToValue(e))
|
echo 1901 | ./hex_half_floats.py
20.56
|
fireworker72
(Themenstarter)
Anmeldungsdatum: 11. März 2017
Beiträge: 59
|
OK werd Ich mal probieren bei mir läuft es jetzt so in Bash 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | echo Dpt9-1
BinHex5=$(printf "%08d" $(echo "scale=8; ibase=16 ; obase=2 ; ${strarr[5]}" | bc))
#echo Binhex5 "$BinHex5"
ar1=($(echo "$BinHex5" | sed -r 's/(.)/\1 /g'))
#echo "${ar1[*]}"
BinHex6=$(printf "%08d" $(echo "scale=8; ibase=16 ; obase=2 ; ${strarr[6]}" | bc))
#echo BinHex6 "$BinHex6"
ar2=($(echo "$BinHex6" | sed -r 's/(.)/\1 /g'))
#echo "${ar2[*]}"
V="${ar1[0]}"
E="${ar1[1]}""${ar1[2]}""${ar1[3]}""${ar1[4]}"
M="${ar1[5]}""${ar1[6]}""${ar1[7]}""${ar2[0]}""${ar2[1]}""${ar2[2]}""${ar2[3]}""${ar2[4]}""${ar2[5]}""${ar2[6]}""${ar2[7]}"
#echo v= "$V"
#echo E= "$E"
#echo M= "$M"
Edec=$(echo "obase=10; ibase=2; $E" | bc )
Mdec=$(echo "obase=10; ibase=2; $M" | bc )
#echo Mdec "$Mdec"
#echo Edez "$Edec"
Value=`echo "scale=2; ($Mdec*0.01)*(2^"$Edec")" | bc `
echo $Value
mosquitto_pub -h $MqttIp -t knx/$ga -m "$Value" -u $user -P $pw;
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10940
Wohnort: München
|
Und für floats (32 Bit):
| #!/usr/bin/env python3
import fileinput
import struct
def dataToValue(data):
return struct.unpack('f', struct.pack('I', data))[0]
for line in fileinput.input():
raw_half_floats = (int(p, 16) for p in line.split())
for e in raw_half_floats:
print(dataToValue(e))
|
$ ./hex_floats.py <<< 4048f5c3
3.140000104904175
|
fireworker72
(Themenstarter)
Anmeldungsdatum: 11. März 2017
Beiträge: 59
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12431
|
seahawk1986 schrieb:
Klar, das ist eines der Probleme wo man mit ausgewachsenen Programmiersprachen mehr Spaß hat
Nur mal so ein paar Ruby-Lösungen: | $ ruby -e 's=Integer(ARGV.first, 16).to_s(2);until s.length % 8 == 0;s="0"+s;end; puts s' f
00001111
$ ruby -e 's=sprintf("%08b", Integer(ARGV.first, 16)); until s.length % 8 == 0; s="0"+s;end; puts s' f
00001111
|
|
shiro
Anmeldungsdatum: 20. Juli 2020
Beiträge: 578
|
Jetzt fehlt nur noch awk als "richtige" Programmiersprache:
echo -e "1901\n9901" | awk '{data=strtonum("0X"$0);v=rshift(data,15);e=and(rshift(data,11),0xf);m=and(data,0x7ff);w=(1-2*v)*m*0.01*2^e;printf "%s, %08x, %02x, %02x, %03x, %f\n",$0,data,v,e,m,w}'
1901, 00001901, 00, 03, 101, 20.560000
9901, 00009901, 01, 03, 101, -20.560000
Das kann man auch noch wesentlich kürzer schreiben, aber ich wollte die Definition von fireworker72's Post hier verwenden.
echo -e "1901\n9901" | awk '{d=strtonum("0X"$0);print (1-2*rshift(d,15))*and(d,0x7ff)*0.01*2^and(rshift(d,11),0xf)}'
20.56
-20.56
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17413
Wohnort: Berlin
|
fireworker72 schrieb: also was Ich genau vorhabe
Berechnung nach IEEE 754
Habe ich bestimmt in dem Zusammenhang schon gesehen, aber vertraut ist es mir nicht.
Ich bekomme Hex werte vom KNX Bus xx oder xx xx oder xx xx xx xx die muss Ich umwandeln in Bin 19 hex = 25 dez = 00011001 bin 01 hex = 01 dez = 00000001 bin dann muss Ich aus den Bin Zahlen einzelne Bereiche extrahieren 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 1 VEEEEMMM MMMMMMMM V= Vorzeichen
E= Exponent
M= Mantisse
$Vbin = 0
$Ebin = 0011
$Mbin = 00100000001 die Variablen dann in Dez umrechnen $Vdez=0 (bedeutet Vorzeichen positiv
$Edez=3
$Mdez=257 und dann rechnen $Mdez*0101*2^$Edez 257x0,01=2,57
Wo kommt die 0,01 her? 0101 ist dezimal ja auch 5 - wo geht die hin? Oder soll das eigentlich 0011 heißen, also dez=3, und bedeuten (3-1) Stellen das Komma nach links verschieben UND mit 2^3 multiplizieren?
2^3=8 2,75x8=20,56
Wo kommt die 2,75 her? Ah, das soll 2.57 lauten, dann stimmt auch die Multiplikation.
$Val=20,56
Mir ist noch unklar, wo die 0,01 herkommt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 |
#!/bin/bash
dual2float () {
abyte=$1
bbyte=$2
dual=$abyte$bbyte
vorzeichen=${dual:0:1}
exponent=${dual:1:4}
mantisse=${dual:5:12}
echo "$vorzeichen:$exponent:$mantisse"
}
while read -d " " fst
do
read -d " " snd
erg=$(dual2float $fst $snd)
echo fst $fst snd $snd $erg
done < <(
for b in $(echo "scale=8; ibase=16 ; obase=2; $(echo 0C 92 1 1 0 0 1 0 0 1 0 0 1 0 | tr ' ' ';')" | bc)
do
printf "%08d " $b
done)
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10940
Wohnort: München
|
user_unknown schrieb: Habe ich bestimmt in dem Zusammenhang schon gesehen, aber vertraut ist es mir nicht.
Ich musste auch erst etwas suchen: Half-precision_floating-point_format
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17413
Wohnort: Berlin
|
Ja, unter IEEE 754 habe ich auch was gefunden, und dann beschlossen nicht so tief einzutauchen, der Bias, das war mir dann doch zu viel für eine rasche Antwort.
|
fireworker72
(Themenstarter)
Anmeldungsdatum: 11. März 2017
Beiträge: 59
|
user_unknown schrieb: Wo kommt die 0,01 her?
Servus die 0,01 ist bei DPT9 Datenformat von KNX vorgegeben 2 octets: F16
Encoding:
FloatValue = (0,01*M)*2(E)
E = [0 … 15]
M = [-2 048 … 2 047], two’s complement notation
For all Datapoint Types 9.xxx, the encoded value 7FFFh shall always be used to denote invalid data.
Range:
[-671 088,64 … 670 433,28]
PDT:
PDT_KNX_FLOAT LG
|