Python hex JSON

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
error404
User
Beiträge: 18
Registriert: Montag 24. Oktober 2016, 09:14

Hallo erstmal,

ich habe zur Zeit eine Aufgabe, bei der ich leider irgendwie auf dem Schlauch stehe...
Folgendes soll das Script können: eine hex Zahl soll mit hilfe des Scriptes ausgelesen werden und die einzelnen Stellen der hex Zahl sollen
mit benennung in JASON ausgegeben werden.

Also der Bediener gibt einmal die Hex Zahl an, Welche Stelle für was steht und wie lang die einzelnen stellen sind Beispiel:
hex = x01111222233334444
list = ['PersonNr1':Stelle3-4,'AbteilungsNr2':Stelle5-10,'Büronummer3':Stelle11-17]

Dies soll halt als JSON ausgegeben werden:
{
Sensor1: 11,
Sensor2: 122223,
und so weiter...
}

Leider weiß ich nicht, wie ich das umsetzen kann, da ich noch absolut neu in Python bin... über jede hilfe würde ich mich freuen ^^
Mein Script bis jetzt:

Code: Alles auswählen

#!/usr/bin/python
import json

hex = x01111222233334444
list = ['Sensor1':[2:4],'Sensor2':[5:8],'Sensor3':[9:10]]
json.dumps(list)
Zuletzt geändert von Anonymous am Montag 19. Dezember 2016, 12:29, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@error404: In der Python-Dokumentation gibt es ein Tutorial wo die grundlegenden Datentypen von Python und viele Operationen darauf erklärt werden. Das was Du da als „Script bis jetzt“ zeigst, ist kein gültiges Python, und zeigt, das Dir noch Grundlagen fehlen.
[codebox=text file=Unbenannt.txt] list = ['Sensor1':[2:4],'Sensor2':[5:8],'Sensor3':[9:10]]
^
SyntaxError: invalid syntax[/code]

Den Namen des Typs `list` an etwas anderes zu binden ist zudem keine gute Idee. Auch `hex` ist bereits vergeben, an die `hex()`-Funktion.
error404
User
Beiträge: 18
Registriert: Montag 24. Oktober 2016, 09:14

Code: Alles auswählen

#!/usr/bin/python
import json
text ="x01202159746756"

stname1="HausNr."
stname2="PersonNr."
stname3="StraszenNr."
stname4="BueroNr."
Stelle1 = 2
Stelle2 = 4
Stelle3 = 2
Stelle4 = 5
	
ausgabe1 = text[2:2+Stelle1]
ausgabe2 = text[2+Stelle1:2+Stelle2+Stelle1]
ausgabe3 = text[2+Stelle2+Stelle1:2+Stelle2+Stelle1+Stelle3]
ausgabe4 = text[2+Stelle2+Stelle1+Stelle3:2+Stelle2+Stelle1+Stelle3+Stelle4]

print(json.dumps({stname1: ausgabe1, stname2:ausgabe2,  stname3:ausgabe3,  stname4:ausgabe4}))
So sieht es jetzt aus und funktioniert auch. Wie schon geschrieben ich kenne mich nicht mit Python aus und habe daher auf hilfe gehofft ^^
Zuletzt geändert von Anonymous am Dienstag 20. Dezember 2016, 12:25, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@error404: was erwartest Du, wenn Du nicht einmal korrekte Syntax schreiben kannst? Aus der "Zahl" `hex` ist jetzt ja auch ein String `text` geworden. Namen durchzunummerieren ist selten eine gute Idee. Was sagt einem `stname2`? Ein Standardname? Eine Straßenname? Woher kommt `text` überhaupt? Das Format sieht sehr seltsam aus.

Laut Aufgabenstellung hätte die Lösung eher so auszusehen:

Code: Alles auswählen

#!/usr/bin/python
import json
text ="x01202159746756"
felder = {"HausNr.": (2, 4), "PersonNr.": (4, 8), "StraszenNr.": (8, 10), "BueroNr.": (10, 15)}
print(json.dumps({k: text[s:e] for k, (s,e) in felder.items()}))
oder

Code: Alles auswählen

print(json.dumps({k: int(text[s:e], 16) for k, (s,e) in felder.items()}))
Da keine expliziten Hex-Ziffern vorkommen, könnte auch das richtig sein:

Code: Alles auswählen

print(json.dumps({k: int(text[s:e]) for k, (s,e) in felder.items()}))
Wer weiß??
error404
User
Beiträge: 18
Registriert: Montag 24. Oktober 2016, 09:14

Neues jahr neues Script:

Code: Alles auswählen

#!/usr/bin/python
import json
data=list()
hexdata=list()
count = 0

# oeffne die Textdatei, inder sich die Hex-Zahlen abspeichern
file = open("hexdatei","r")
for line in file:
    hexdata.append(line.rstrip())
file.close()

# oeffne die config inder angegeben wird welcher Wert der hexdatei was bedeutet und wie viele Stellen er besitzt 
file = open("config","r")
for line in file:
    data.append(line.rstrip())
file.close()

count = len(hexdata) -1

print("start loop")
#wiederhole so lange, bis alle Hex-Zahlen ausgewertet sind
while count >=1:
    count = count -1
    text=hexdata[count]
    
    #Ausgabe Config Text (trennung Text von Wert)#
    stelle1split=data[0].index(" ")
    stelle1text=data[0]
    stelle1text1=stelle1text[:stelle1split]
    stelle1nr=stelle1text[stelle1split:len(stelle1text)]
    
    stelle2split=data[1].index(" ")
    stelle2text=data[1]
    stelle2text2=stelle2text[:stelle2split]
    stelle2nr=stelle2text[stelle2split:len(stelle2text)]
    
    stelle3split=data[2].index(" ")
    stelle3text=data[2]
    stelle3text3=stelle3text[:stelle3split]
    stelle3nr=stelle3text[stelle3split:len(stelle3text)]
    
    stelle4split=data[3].index(" ")
    stelle4text=data[3]
    stelle4text4=stelle4text[:stelle4split]
    stelle4nr=stelle4text[stelle4split:len(stelle4text)]
    
    #Berechnung der Stelle der Hex Zahl
    ausgabe1 = text[2:2+int(stelle1nr)]
    ausgabe2 = text[2+int(stelle1nr):2+int(stelle2nr)+int(stelle1nr)]
    ausgabe3 = text[2+int(stelle2nr)+int(stelle1nr):2+int(stelle2nr)+int(stelle1nr)+int(stelle3nr)]
    ausgabe4 = text[2+int(stelle2nr)+int(stelle1nr)+int(stelle3nr):2+int(stelle2nr)+int(stelle1nr)+int(stelle3nr)+int(stelle4nr)]
    
    #Ausgarbe der Stelle mit angabe der Bedeutung umgerechnet in dezimal
    print(json.dumps({stelle1text1: int(ausgabe1,  16),  stelle2text2: int(ausgabe2,  16),  stelle3text3: int(ausgabe3,  16),  stelle4text4: int(ausgabe4,  16)}))
print("loop exit")
Die Config Datei als txt:

HausNr. 3
PersonNr. 4
StraszenNr. 2
BueroNr. 3


Die hexdatei als txt:

x436543543543
x345435243242
x678680967067
x357467536536
x257254744552
x614611416544

Hier nochmal eine kleine Beschreibung: In der Config wird angegeben, welche Stellen was bedeuten. So kann der User halt sagen, das die ersten 3 Ziffern der hexdatei eine HausNr seihen sollen. Dies kann er aber nach belieben ändern. So können auch die ersten 5 Ziffern halt eine Telefonnummer oder sonst was sein. Die Länge ist bestimmbar und was es seinsoll auch. Es tut mir leid, dass ich das halt nicht so gut erklärt habe und ich halt auch nicht so eine ahnung von Python habe.
Zuletzt geändert von Anonymous am Montag 2. Januar 2017, 12:43, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@error404: Woher kommen die Hex-Daten? Wer hat sich dieses Format ausgedacht? Und warum ist das Format konfigurierbar? Wie sieht die Konfigurationsdatei des Programms aus, das die Daten erzeugt?

Wenn Du Dir die Konfigurationsdatei selbst ausdenken kannst, warum nimmst Du dann kein Format, das sich einfach lesen läßt? JSON!

Variablennamen sind dazu da, den Sinn eines Programms zu verstehen. Wenn die Konfiguration einfach »data« heißt, dann trägt das nichts zum Verständnis bei. Eher im Gegenteil.
Variablen werden in Python dann eingeführt, wenn sie gebraucht werden und nicht schon 20 Zeilen davor. »count = 0« wird gar nicht gebraucht, weil später die Variable mit einem anderen Wert belegt wird. Die while-Schleife sollte eine for-Schleife sein. Will man eine Liste von Hinten durchgehen, dann nimmt man »reversed«:

Code: Alles auswählen

#!/usr/bin/python
import json

hexdata = []
with open("hexdatei", "r") as lines:
    for line in lines:
        hexdata.append(line.rstrip())

names_and_places = []
with open("config", "r") as lines:
    for line in lines:
        names_and_places.append(line.rstrip())

for text in reversed(hexdata):
    tu_was_mit_text(text)


Statt bei jeder Hex-Zeile die Konfiguration neu zu parsen, macht man das einmal, am besten gleich beim Einlesen. Du solltest Dich dringend mit den Methoden, die ein String so mit sich bringt, auseinandersetzen. Dieses Indexgefummel ist fast nicht lesbar. Dass man nicht Variablen durchnummeriert und dass man keinen Code kopiert und leicht abwandelt, wurde Dir glaube ich schonmal gesagt. Das Aufspalten vom Hex-String hab ich Dir ja schon gezeigt:

Code: Alles auswählen

print(json.dumps({k: int(text[s:e], 16) for k, (s,e) in felder.items()}))
Jetzt wäre nur noch Dein Aufgabe, die Konfigurationsdatei gleich als Wörterbuch, im richtigen Format zu schreiben, oder eine Funktion zu schreiben, die Deine jetzige Konfigurationsdatei in solch ein Wörterbuch überführt.
error404
User
Beiträge: 18
Registriert: Montag 24. Oktober 2016, 09:14

Die Hexdaten kommen von bluetooth Geräten. Das Format ist konfigurierbar, da unterscheidliche bluetooth Geräte unterschiedliche Werte übermitteln, dies muss halt immer zuvor über die Config eingestellt werden. Der Aufbau der Config kann ich nicht ändern, da dies so vorgegeben ist. Diese Configurationsdatei ist eine Textdatei, diese sieht wie folgt aus:

HausNr. 3
PersonNr. 4
StraszenNr. 2
BueroNr. 3

Hier soll später mal der User auch noch mehrere Sachen angeben können (mehr Einträge oder weniger Einträge). Soweit bin ich aber noch nicht. Ich werde deine Vorschläge versuchen zu beachten und bei gelegenheit eine neue Version posten.


Hier nochmal die Grundidee:

Man hat X (eine ungenaue mänge) hexzahlen welche in einer textdatei gespeichert sind, dies sieht wievolgt aus:
x436543543543
x345435243242
x678680967067
x357467536536

Diese Werte haben je nach Stelle eine andere Bedeutung.
So kann von der Hexzahl die ersten 3 Zahlen eine Hausnummer sein. Dies soll der User in einer Config eingeben. Beispiel Config:
HausNr. 3
PersonNr. 4
StraszenNr. 2
BueroNr. 3

Hier steht die Zahl hinter den Namen für die Stelle der hexzahl. Die Bedeutung schreibt er User vor die Zahl. Die ersten Stellen der hexzahl sind dann die ersten 3 Zahlen und haben die Bedeutung HausNr. die nechsten 4 Zahlen der hexzahl haben dann die Bedeutung PersonNr. Dies geht halt dann so weiter. Das x zu beginn muss immer weggenommen werden. Die Ausgabe soll aus dezimal Zahlen bestehen, dies soll so aussehen:

{"StraszenNr.": 116, "PersonNr.": 26454, "HausNr.": 1124, "BueroNr.": 103}
{"StraszenNr.": 117, "PersonNr.": 26472, "HausNr.": 135, "BueroNr.": 101}

Wie schon weiter oben geschrieben werde ich, sobald ich Zeit habe, eine neue Version erstellen.
error404
User
Beiträge: 18
Registriert: Montag 24. Oktober 2016, 09:14

Neue Version:

Code: Alles auswählen

#!/usr/bin/python
import json
configData=list()
hexdata=list()
nummerderstelle=0
hexergebnis = 0
hex=2
# oeffne die Textdatei, inder sich die Hex-Zahlen abspeichern
file = open("hexdatei","r")
for line in file:
    hexdata.append(line.rstrip())
file.close()

# oeffne die config in der angegeben wird welcher Wert der hexdatei was bedeutet und wie viele Stellen er besitzt 
file = open("config","r")
for line in file:
    configData.append(line.rstrip())
file.close()
 


def ausgabe22(text, anzahl):
    hexdata[0]

def config(config, hexdatei):
    global hex
    
    stelle1split=config.index(" ")  
    stelletext=config   
    textderConfig=stelletext[:stelle1split]
    stellenLaenge=stelletext[stelle1split:len(stelletext)]
    hexergebnis = hexdatei[hex:hex+int(stellenLaenge)]
    hex = hex + int(stellenLaenge)
    #print(hex)
    #print(textderConfig)
    #print(stellenLaenge)
    #print(hexergebnis)
    print(json.dumps({textderConfig: int(hexergebnis,  16)}))
    
for x in xrange(len(hexdata)):    
    for i in xrange(len(configData)):
        config(configData[i], hexdata[x])
    print ("-----------------------------------------------------------------------")
    hex=2
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@error404: und was willst Du damit sagen?
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Ich wollte noch eine Erklärung dazuschreiben, aber ich hatte den Beitrag schon abgeschickt.

Code: Alles auswählen

#!/usr/bin/env python3
# coding: utf-8

from pprint import pprint

def parse_hex_string(hex_string, split_info):
    result = {}
    start = 1
    for key, length in split_info:
        result[key] = int(hex_string[start:start + length], base=16)
        start += length
    return result

def parse(hex_strings, split_info):
    return [parse_hex_string(each, split_info) for each in hex_strings]

def main():
    hex_strings = [
        'x123123412123',
        'x111222233444',
        'x555666677888',
        'xAAABBBBCCDDD',
    ]
    config = [
        'HausNr. 3',
        'PersonNr. 4',
        'StraszenNr. 2',
        'BueroNr. 3',
    ]
    config_lines = [line.strip().split() for line in config]
    config_lines = [[key, int(value)] for key, value in config_lines]
    pprint(parse(hex_strings, config_lines))

if __name__ == '__main__':
    main()
Ergebnis:

Code: Alles auswählen

[{'BueroNr.': 291, 'HausNr.': 291, 'PersonNr.': 4660, 'StraszenNr.': 18},
 {'BueroNr.': 1092, 'HausNr.': 273, 'PersonNr.': 8738, 'StraszenNr.': 51},
 {'BueroNr.': 2184, 'HausNr.': 1365, 'PersonNr.': 26214, 'StraszenNr.': 119},
 {'BueroNr.': 3549, 'HausNr.': 2730, 'PersonNr.': 48059, 'StraszenNr.': 204}]
In specifications, Murphy's Law supersedes Ohm's.
error404
User
Beiträge: 18
Registriert: Montag 24. Oktober 2016, 09:14

Danke, das hat mir sehr weitergeholfen ^^
error404
User
Beiträge: 18
Registriert: Montag 24. Oktober 2016, 09:14

Könntest du vielleicht doch noch deinen Code ein bischen beschreiben, ich muss nimmlich nun noch einmal ein paar Sachen abändern...
in der Config soll nun zusätzlich angegeben werden, welcher Ausgabewert gewünscht wird also int, chr, bool, hex.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@error404: was genau verstehst Du denn nicht?

@pillmuncher: das erste `config_lines` würde ich zum Generator machen und das zweite `config_lines` sollte Tuple statt Listen enthalten und eigentlich auch `split_info` heißen.
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Sirius3: Ja, so hatte ich es zuerst auch. Aber dann habe ih mir gedacht, es ist besser, nicht noch ein Konzept einzuführen (genexps) und auch den Namen config_lines zu verwenden, damit niemand meint, der Name hätte beim Funktionsaufruf irgendeine besondere Bedeutung.
In specifications, Murphy's Law supersedes Ohm's.
Antworten