staging.inyokaproject.org

hex 2 Bin

Status: Ungelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

fireworker72

Anmeldungsdatum:
11. März 2017

Beiträge: 64

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

1
echo "ibase=16 ; obase=2 ; 19" | bc    Ergebnis  11001

01 hex = 01 dez = 00000001 bin

1
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

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Meines Wissens macht bc das nicht - das musst Du wohl mit printf machen.

1
printf "%08d" $(echo "scale=8; ibase=16 ; obase=2 ; 01" | bc)

fireworker72

(Themenstarter)

Anmeldungsdatum:
11. März 2017

Beiträge: 64

user_unknown schrieb:

Meines Wissens macht bc das nicht - das musst Du wohl mit printf machen.

1
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: 11278

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: 64

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: 11278

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: 64

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: 11278

Und für floats (32 Bit):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/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: 64

Danke!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

seahawk1986 schrieb:

Klar, das ist eines der Probleme wo man mit ausgewachsenen Programmiersprachen mehr Spaß hat

Nur mal so ein paar Ruby-Lösungen:

1
2
3
4
$ 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 Team-Icon

Supporter

Anmeldungsdatum:
20. Juli 2020

Beiträge: 1303

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

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

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: 11278

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

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

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: 64

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

Antworten |