In Python Array auslesen und interpretieren?

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.
gooogle
User
Beiträge: 66
Registriert: Freitag 15. Mai 2009, 19:13
Wohnort: burghausen

Hallo

ich habe einen Array bzw Puffer, welches über eine schnittstelle mit daten gefüllt wird.
nun ist es so, dass eine bestimmte anzahl an Bytes eine Bedeutung haben, wie z.B. hier -> Rx: http://www.google.de

Sowas würdich gerne in Python umsetzen aber weiss nicht wie ich da rangehen will. möchte nur den array in textform interpretieren und irgendwohin speichern.

habt ihr tipps wie man sowas machen. vielleicht ibt es schon was?

danke und gruss
Zuletzt geändert von gooogle am Samstag 6. März 2010, 17:44, insgesamt 1-mal geändert.
fff gh
BlackJack

@gooogle: Sorry, aber ich verstehe nicht was Du willst. Was genau ist das Problem?
gooogle
User
Beiträge: 66
Registriert: Freitag 15. Mai 2009, 19:13
Wohnort: burghausen

Hallo

sorry, hab mich vlt unverständlich ausgedrückt.



Nun ist es so dass "34, 00, 78, 89, 01, 11, 88" " Relais wurde aktiviert" bedeutet.
Ich möchte nun in Phyton den Puffer auslesen und dann wenn eine bestimmte Bytefolge auftritt, dann soll der entsprechende String bzw Text wie im obigen beispiel ausgegeben werden.

Ganz trivial:

if("999,34, 00, 78, 89, 01, 11, 88")
{

print (" Relais wurde aktiviert" )

}


usw...

die "999" ist ein kennzeichen dafür dass die Bytes zwischen den "999" zusammengehören (Frame) und eine Bedeutung haben.
Hoffe jetzt klappts mit dem verständnis...
Zuletzt geändert von gooogle am Samstag 6. März 2010, 17:44, insgesamt 1-mal geändert.
fff gh
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

So was?

Code: Alles auswählen

In [1]: p = [ 999, 34, 00, 78, 89, 01, 11, 88,999,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

In [2]: p = ''.join((str(x) for x in p))

In [3]: p.split('999')
Out[3]: ['', '340788911188', '00000000000000']
Über diese veränderte Darstellung könntest Du ja iterieren und Bedingungen abfragen:

Code: Alles auswählen

In [4]: relais_msg = '340788911188'

In [5]: relais_msg in p
Out[5]: True
HTH
Christian
BlackJack

@CM: Und wenn in den Daten 99, 9 oder 9, 99 oder 9, 9, 9 vorkommt!?

@gooogle: Wo kommt denn die 999 her? Wie bekommst Du die Daten? In welcher Form genau?
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Was spricht denn dagegen, ein dictionary zu nehmen, dessen Schlüssel die entsprechend auszuwertenden Byte-Folgen sind (als Tupel) und den Klartext als Wert; und dann aus der Liste mit den Bytefolgen jeweils die Teile zwischen zweimal 999 herauszunehmen und (nach Umwandlung in Tupel) den Klartext aus dem dict abzurufen?

Oder übersehe ich irgendetwas?
gooogle
User
Beiträge: 66
Registriert: Freitag 15. Mai 2009, 19:13
Wohnort: burghausen

hallo

danke für die tipps.



wie gesagt, es ist eine einfache serielle schnittstelle, (9600 Buad,1 stop/startbit, 8 Datenbits...)
insgesamt gibt es ca. 100 sequenzen, also 100 Strings die von den frames abhängig sind.

deshalb ist es so schwierig. ich muss den puffer, nachdem dieser gefült wurde, analysieren bzw die frames rausfiltern und schauen welcher text zu welchem frame gehört ..
numerix, hast du da ein beispiel. das klingt sehr interessant und eventuell für meine anwendung sehr geeignet?
Zuletzt geändert von gooogle am Samstag 6. März 2010, 17:45, insgesamt 1-mal geändert.
fff gh
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Ich meine so etwas (kein optimaler Code, zeigt aber die Grundidee):

Code: Alles auswählen

from random import randrange

puffer = [randrange(7) or 999 for k in xrange(50000)]+[999] # zufällige Zahlensequenz anlegen zur Simulation
events = {(3,4,6):"Relais aktiviert", (5,2,1):"Relais deaktiviert"} # Dictionary mit den zu identifizierenden Teilsequenzen
while 999 in puffer: # solange wie noch eine 999 drin steht: weiter auswerten
    p = puffer.index(999) # erstes Vorkommen in der Sequenz suchen
    seq = tuple(puffer[:p]) # Teilsequenz bis dahin separieren
    del puffer[:p+1] # Sequenz bis dahin abschnippeln
    if seq in events: # Falls die Teilsequenz als Schlüssel im dict vorkommt
        print events[seq] # Wert zum Schlüssel ausgeben


Edit: Kommentare ergänzt.

Falls du es nicht ausprobiert hast: Der Code ist so lauffähig. Experimentiere doch ein wenig damit.

Statt den Puffer scheibchenweise abzuschneiden wäre es vermutlich performanter, einen Zeiger mitzuführen und die index-Methode dann mit dem start-Parameter zu verwenden.
Zuletzt geändert von numerix am Samstag 16. Mai 2009, 06:34, insgesamt 1-mal geändert.
gooogle
User
Beiträge: 66
Registriert: Freitag 15. Mai 2009, 19:13
Wohnort: burghausen

hallo

danke dir numerix. leider bin ich relativ neu auf diesem gebiet und brauche immer kommentare zu den jeweiligen zeilen (um es zu verstehen). wäre super wenn du es kurz mit kommentaren versehst ;)

eine andere frage: ich habe die möglichkeit dictionaries anzulgene. würde sowas auch mit dictionarys gehen? falls ja wie könnte man das machen.
so in der art?:

'Relai aktiviert': ' 34, 00, 78, 89, 01, 11, 88'...

würde sowas gehen bzw gibt es beispiel codes? :)
fff gh
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Hier auch noch ein Ansatz, der von Numerix gar nicht
so weit entfernt ist.

Code: Alles auswählen

class ChunkDispatcher(object):

  def __init__(self, marker=999):

    self.marker = marker
    self.state = 0
    self.buf = []
    self.dispatching = {(1,2,3): self.on,
                        (11,22,33): self.off}
    
  def check(self, c):
    
    if c == self.marker:
      self.state ^= 1
      if not self.state:
        self.dispatch()
        self.state ^= 1
    else:
      if self.state:
        self.buf.append(c)


  def dispatch(self):

    self.dispatching.get(tuple(self.buf), lambda: None)()
    self.buf = []

        
  def on(self):

    print 'Relais on'


  def off(self):

    print 'Relais off'


def main():

  output = (1,2, 999,
            2,999,
            1, 2, 3, 999,
            1, 2, 3, 4, 999,
            11, 22, 33, 999,
            1, 2, 3,999,
            0, 0, 999,
            11, 22, 33,999)

  disp = ChunkDispatcher()

  for c in output:
    print c
    disp.check(c)


if __name__ == '__main__':

  main()
:wink:
yipyip
BlackJack

@gooogle: Also ich würde noch einmal bei der 999 einhaken wollen. Wo kommt die in den Puffer? Warum kannst Du an *der* Stelle nicht etwas sinnvolleres machen, zum Beispiel eine weitere Liste einführen, so dass sich das Problem was Du hier lösen möchtest so gar nicht erst ergibt. Der Puffer, den Du analysieren müsstest, würde dann so aussehen:

[[34, 00, 78, 89, 01, 11, 88], [77, 56, 89, 89, 78], ...]

Eine IMHO sehr viel sinnvollere Datenstruktur für das Problem. Wenn Du aus den inneren Listen Tupel machst, dann kannst Du auch ganz einfach den Vorlschlag mit dem Nachschlagen der Nachrichtentexte in einem Dictionary umsetzen.
gooogle
User
Beiträge: 66
Registriert: Freitag 15. Mai 2009, 19:13
Wohnort: burghausen

hallo

danke numerix für die kommentare :)

hallo yipyip. Könntest du dein Programm vielleicht auch kommentieren :) wäre super für mich anfänger ;)


blackjack: die 999 kommt dann immer in den puffer wenn ein neuer frame erkannt wird..das passiert zeitgesteuert über ein separates programm und hat mit python nichts zu tun ;) man sollte einfach davon ausgehen dass ein derartiger puffer einfach zu verfügung steht.




So ein Array soll einfach als gegeben angesehen werden, welcher dann analysiiert wird und entsprechend auf die Bedeutungen in textform referenziert werden ;).

deine idee ist gut aber in meinem fall nicht möglich da das puffern nicht über python geschieht. lediglich as auswerten soll über python gehen weil es einfacher gehen soll :)
es ist wirklich nur so, dass man den array durchgeht und die Bytes zwischen 999 hheruasfiltert und zu den dazugehörigen Texten in Listen oder Dictionaries referenziert um so nicht die Bytes zu sehen sondern den dazugehörigen text.
ich will einfach später in einer datei oder was auch immer einen Text sehen in der Form:

15:30:45 Relais wurde aktiviert
15:31:56 Relais wurde deaktiviert
15:33:57 Spannung weg geschaltet
15:36:12 Spannung eingeschaltet
15:55:14 Relais wurde aktiviert
....
usw

Ich hoffe ihr habt mein anliegen verstanden :)
Zuletzt geändert von gooogle am Samstag 6. März 2010, 17:45, insgesamt 1-mal geändert.
fff gh
gooogle
User
Beiträge: 66
Registriert: Freitag 15. Mai 2009, 19:13
Wohnort: burghausen

Hallo

noch ein ekurze Frage:

in dem codebeispiel von numerix kommt folgendes vor:

Code: Alles auswählen

events = {(3,4,6):"Relais aktiviert", (5,2,1):"Relais deaktiviert"}
Was ist wenn z.B das zweite element der ersten 3 bytes nicht wichtig ist, also in der form:

Code: Alles auswählen

events = {(3,' ',6):"Relais aktiviert", (5,2,1):"Relais deaktiviert"}
habe die stelle einfach durch hochkomme gekennzeichnet. soll heissen dass das zweite byte eigentlich jeden wert haben könnte und für die referenzierung des texts nicht notwendig ist, sondern nur die anderen beiden? wie würd man sowas in python ergänzen?kann man das mit hochkomme machen oder "None" ? :)
fff gh
BlackJack

Wenn so etwas vorkommen kann, dann kannst Du nicht mehr so einfach Dictionaries verwenden.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

So, jetzt habe ich es Dir (hoffentlich nicht zu unverständlich,
aber eine Python Doku kann es natürlich nicht ersetzen)
kommentiert:
http://paste.pocoo.org/show/117642/

Zu Deiner letzten Frage:
Dann nimm einfach ein Dictionary mit den 2erTupeln.
Zuvor musst Du die Sequenz entprechend
Deinen Anforderungen transformieren.

z.B.:

Code: Alles auswählen

a, b, c = [1, 2, 3]
lookup_seq = a, c
mydict.get(lookup_seq, ....
:wink:
yipyip
gooogle
User
Beiträge: 66
Registriert: Freitag 15. Mai 2009, 19:13
Wohnort: burghausen

hallo

coole sache yipyip...danke dir. werd ich ausprobieren :)

grüsse
fff gh
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

@yipyip:

self.state ^= 1 solltest du besser mit Wahrheitswerten und self.state = not self.state umsetzen.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Klar, bei nur 2 Zuständen reichen boolsche Werte aus.
Ich denke bei diesen Problemstellungen immer an
endliche Automaten, deshalb habe ich mir die Anzahl der Zustände
zunächst offengelassen und deshalb Integer-Werte verwendet.

:wink:
yipyip
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

warum ist denn der code für "relais aktiviert" so lang?
sicher dass da nicht noch einiges an balast bei ist? (ack, seq, crc, ...)
http://www.kinderpornos.info
gooogle
User
Beiträge: 66
Registriert: Freitag 15. Mai 2009, 19:13
Wohnort: burghausen

Hallo Dill

ja, da ist auch balast dabei aber dieser ist für meine anwendung uninteressant ;) ich möchte einfach später nur den kurzen Text "Relais wurde aktiviert" sehen.
Zuletzt geändert von gooogle am Samstag 6. März 2010, 17:46, insgesamt 1-mal geändert.
fff gh
Antworten