Bits in einem Byte mit symbolischen Namen ansprechen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
markus_
User
Beiträge: 12
Registriert: Samstag 25. April 2015, 14:22

Hallo zusammen,

bin neu in Python, hoffe und glaube, dass ihr mir helfen könnt. Hintergrund ist, dass ich die Kommunikationsschnittstelle eines Busteilnehmers virtuell nachbilden muss. Mein Programm bekommt Daten von einer SPS - diese sind bytebasiert. Pythonseitig extrahiere ich die einzelnen Bits und verarbeite diese. Soweit alles klar. Nun müssen natürlich auch an die SPS wieder Daten zurückgeschickt werden, in der Regel sind dies einzelne Bits, die jedoch bytebasiert übertragen werden müssen.

Wenn ich also in meinem Byte an die SPS das 3. Bit setzen wollte, so könnte man das so machen: byte2 = byte2 | 4, beim Rücksetzen byte2 = byte2 & 251 - nicht gerade gut wartbarer Code. Ich hatte mir nun überlegt, ein Dictionary byte2 zu definieren, indem die einzelnen Bits mit einem Key über ihre sprechenden Namen ansprechbar sind. Also z.B. etwas in der Art:

Code: Alles auswählen

byte2 = {"motor_an":0, "spannung_an":0, "fehler":0, "b5":0, "b4":0, "b5":0, "b6":0, "b7":0}
byte2["fehler"] = 1
Jetzt habe ich natürlich das Problem, dass der Inhalt des Dictionary wieder in ein Byte gewandelt werden muss, bevor ich die Daten an die SPS schicken kann. Jedoch ist die Anordnung der verschiedenen Keys in einem Dict. ja zufällig, was dann in einem falschen Bytewert resultiert. Wäre nett, wenn jemand einen Tipp hätte, wie ich das Problem lösen kann, sodass am Ende übersichtlicher Code herauskommt.

Viele Grüße
markus
Zuletzt geändert von Anonymous am Samstag 25. April 2015, 14:40, insgesamt 1-mal geändert.
Grund: Code in Python-Tags gesetzt.
BlackJack

@markus_: Da würde man einen eigenen Datentyp für nehmen. Entweder selber schreiben, oder etwas fertiges wie `construct` oder `BitPacket` installieren.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@markus_: Probier es mal mit `OrderedDict` aus dem `collections`-Modul. Achtung: Bei der Initialisierung darf natürlich *kein* Wörterbuch übergeben werden, da du ja sonst direkt wieder die Reihenfolge kaputt hast und `OrderedDict` nicht magisch wissen kann, was die Original-Reihenfolge war. Es bietet sich folgende alternative Form an:

Code: Alles auswählen

byte2 = collections.OrderedDict(
    [('key1', 'val1'), ('key2', 'val2')]
)
Natürlich setzt man für die Strings an den entsprechenden Stellen die gewünschten Bezeichungen ein.

Wie schon angeregt wurde (und was ja auch naheliegt), kann man aber auch eine externe Bibliothek zur Hilfe nehmen, anstatt das Konstruieren der Bitwerte händisch zu erledigen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also der Name ``byte2`` klingt an sich schon mal komisch - das nur am Rande.

Da BlackJack Deinen beitrag vor 20 Minuten formatiert, aber noch nicht geantwortet hat, vermute ich mal, dass er an einer ziemlich "sophisticated" Lösung für Dein Problem bastelt.

Dennoch mal kurz einige Ideen dazu:

Du müsstest uns (bzw. Dir selber) erst einmal klar machen, *was* Du genau machen willst! Also wie sollen die Aufrufe an sich aussehen? Schreib Dir ruhig mal Code auf, wie Du ihn gerne funktional verwenden würdest. Das hilft ungemein sich klar zu machen, welche Infos man von einem API braucht und welche man diesem geben muss und was ggf. reine Komfortfunktion wäre...

Also z.B. so etwas:

Code: Alles auswählen

bus = connection.bus()
if bus.status["motor"]:
    bus.status["licht"] = True
Zuletzt geändert von Anonymous am Samstag 25. April 2015, 15:53, insgesamt 1-mal geändert.
Grund: Im Code herumgepfuscht. :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Ich habe doch geantwortet. :-)

Dafür pfusche ich jetzt mal in Deinem Code herum und sorge dafür das der syntaktisch richtig und ”symmetrisch” ist was abfrage und setzen angeht. :-P
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben:@Hyperion: Ich habe doch geantwortet. :-)
Ich schrieb das zuvor und sah dann beim Absenden, dass Du schon was gesagt hattest
BlackJack hat geschrieben: Dafür pfusche ich jetzt mal in Deinem Code herum und sorge dafür das der syntaktisch richtig und ”symmetrisch” ist was abfrage und setzen angeht. :-P
Ja, ist nicht so gelungen... hatte da Zeitdruck beim Absenden...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

am besten schreibst Du Dir eine eigene Klasse:

Code: Alles auswählen

class SomeByte(namedtuple("SomeByte", "motor_an,spannung_an,fehler,b3,b4,b5,b6,b7")):
    def to_byte(self):
        result = 0
        for b in reversed(self):
            result = (result << 1) | bool(b)
        return result

byte2 = SomeByte(0,0,1,0,0,0,0,0)
print byte2._replace(motor_an=1).to_byte()
markus_
User
Beiträge: 12
Registriert: Samstag 25. April 2015, 14:22

Vielen Dank für die vielen Tipps. Ich werde versuchen, morgen ausführlicher zu antworten, habe im Moment keinen gescheiten Internetzugang.

Übrigens läuft die API meines Programmes, mit dem ich arbeite, mit einem Python 2 Interpreter. Wird bestimmt für Lösungsvorschläge relevant sein.
markus_
User
Beiträge: 12
Registriert: Samstag 25. April 2015, 14:22

Habe nun die Beispiele von snafu und Sirius3 bei mir (privat mit einem Python 2.7 Interpreter) getestet und sie funktionieren wunderbar.

Leider arbeitet das Programm zur virtuellen Inbetriebnahme, mit dem ich in der Firma arbeite, mit einem Python 2.5 Interpreter. Es wird dort immer der Fehler NameError: global name 'OrderedDict' is not defined geworfen. Unter ..\Python 2.5\Lib konnte ich auch das Modul "collections" nicht finden. Habe nun händisch die "collections.py" und "collections.pyc" von einem anderen Python 2.7 System in den Ordner Libs kopiert. Der Fehler tritt totzdem noch auf. Hat jemand eine Idee wie man das zum Laufen bekommen kann? Eine Möglichkeit die API des VIBN-Programms mit einem aktuellen Interpreter laufen zu lassen, besteht wohl nicht.

Grüße
Markus
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Mal einfach lustig irgendwas in diese zentralen Python-Ordner zu kopieren ist nicht nur eine schlechte Idee. Es ist sogar eine verdammt beschissene Idee.

Verwende den Backport für OrderedDict und installiere ihn so wie vorgesehen.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:


GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten