2016-04-24 4 views
4

Ich habe einfach Enumerator mit 3 Modi LEDOn, LEDBlink, LEDOFF und ich habe einen variablen Modus, der die Modi für bestimmte Objekt verfolgt. Also zum beispiel habe ich eine led im mode led0n gestartet möchte ich zum beispiel nach 5 sekunden zum nächsten element wechseln welches ledblink dann zu ledOFF und dann durchschalten zu ledON wäre da ein einfacher weg sowas zu erreichen?Wechsel von einem Enum-Zustand zum nächsten und durch

import time 
from threading import Thread 
from enum import Enum 

class ledController(Thread): 
    ledModes = Enum('ledModes', 'ledON ledBlink ledOFF') 
    def __init__(self, GPIOID, state=False, blinkDuration=2, mode=ledModes.ledON): 
     self.GPIOID = GPIOID 
     self.state = state 
     self.blinkDuration = blinkDuration 
     self.mode = mode 
     self.blinked = False 
     Thread.__init__(self) 
    def run(self): 
     if(self.mode == self.ledModes.ledON): 
      self.ledON() 
     if(self.mode == self.ledModes.ledBlink): 
      self.ledBlink() 
     if(self.mode == self.ledModes.ledOFF): 
      self.ledOFF() 
     time.sleep(self.blinkDuration) 
     self.mode.next() 
    def ledSwitch(self): 
     self.state = not self.state 
     print(self.ledDetails()) 
    def ledON(self): 
     self.state = True 
     print(self.ledDetails()) 
    def ledOFF(self): 
     self.state = False 
     print(self.ledDetails()) 
    def ledBlink(self, duration): 
     self.ledON() 
     print(self.ledDetails()) 
     time.sleep(self.Blinkduration) 
     self.ledOFF() 
     print(self.ledDetails()) 
     time.sleep(self.Blinkduration) 
    def ledDetails(self): 
     return "Thread: "+self.getName()+", LED: "+str(self.GPIOID)+", State: "+str(self.state)+", Mode: "+str(self.mode.name)+", Blink duration: "+str(self.blinkDuration) 

redLED = ledController(17, blinkDuration = 3) 
blueLED = ledController(18, mode = ledController.ledModes.ledOFF) 

redLED.setName('1') 
blueLED.setName('2') 

redLED.start() 
blueLED.start() 

redLED.join() 
blueLED.join() 

Antwort

1

Die einfachste Lösung für Ihre aktuellen Code ist:

  • ändern Sie Ihre run Methode und
  • fügen Sie ein next_mode Methode:

wie so:

def run(self): 
    while True: 
     set_mode = getattr(self, self.mode) 
     set_mode() 
     time.sleep(self.blinkDuration) 
     self.next_mode() 

def next_mode(self): 
    self.mode = { 
      self.ledModes.ledON: self.ledModes.ledBlink, 
      self.ledModes.ledBlink: self.ledModes.ledOFF, 
      self.ledModes.ledOff: self.ledModes.ledOn, 
      }[self.mode] 
1

Ich würde nur itertools.cycle statt Ihrer ENUM verwenden:

>>> from itertools import cycle 
>>> ledModes = cycle(['ledON', 'ledBlink', 'LedOFF']) 
>>> first = next(ledModes) 
>>> second = next(ledModes) 
>>> third = next(ledModes) 
>>> fourth = next(ledModes) 
>>> 
>>> first 
'ledON' 
>>> second 
'ledBlink' 
>>> third 
'LedOFF' 
>>> fourth 
'ledON' 
>>> 

FYI, können Sie entweder tun next(ledModes) oder ledModes.next(), die beide das gleiche tun.

EDIT: Man könnte so etwas, als Methode Ihrer Klasse verwenden:

from itertools import cycle 

def initialize_cycle(start_mode): 
    states = ['ledON', 'ledBlink', 'ledOFF'] 

    if start_mode not in states: 
     raise ValueError('start_mode invalid') 

    iterable = cycle(states) 
    for _ in states[:states.index(start_mode)]: 
     iterable.next() 

    return iterable 

test1 = initialize_cycle('ledON') 
test2 = initialize_cycle('ledOFF') 
test3 = initialize_cycle('ledBlink') 

# validation 
for test in test1, test2, test3: 
    for _ in range(5): 
     print test.next() 
    print '-' * 20 

Ausgang:

$ python cycle.py 
ledON 
ledBlink 
ledOFF 
ledON 
ledBlink 
-------------------- 
ledOFF 
ledON 
ledBlink 
ledOFF 
ledON 
-------------------- 
ledBlink 
ledOFF 
ledON 
ledBlink 
ledOFF 
-------------------- 
+0

wie würde ich diesen Wert zuweisen, um beispiels so z.B. Modus = ledModes? Damit meine ich, ich möchte nicht immer den Zyklus von ledON starten Ich möchte, dass es was auch immer der Benutzer als erster Staat wählt – Higeath

+0

Ich fügte eine Bearbeitung zu meiner Antwort, nur eine Idee, vielleicht kann es helfen. –

1

Wahrscheinlich zuviel des Guten:

import itertools 

class EnumCycler(object): 
    def __init__(self, enum, start_at=None): 
     self.enum = enum 
     self.members = list(enum.__members__.values()) 
     self.start_at = self.members[0] if start_at is None else start_at 
     self.cycles = 0 

    def __iter__(self): 
     cycle = itertools.cycle(self.members) 
     sanity_check = len(self.members) 
     for value in cycle: 
      if sanity_check: 
       if value != self.start_at: 
        sanity_check -= 1 
        continue 
       sanity_check = 0 
      self.cycles += 1 
      yield value 

Dann:

>>> mode = Enum('ledModes', 'ledON ledBlink ledOFF') 
>>> led_mode_cycler = EnumCycler(mode, start_at=mode.ledOFF) 
>>> for value in led_mode_cycler: 
...  print(led_mode_cycler.cycles, value) 
...  if led_mode_cycler.cycles >= 10: break # infinite loop if we never break off 
1 ledModes.ledOFF 
2 ledModes.ledON 
3 ledModes.ledBlink 
4 ledModes.ledOFF 
5 ledModes.ledON 
6 ledModes.ledBlink 
7 ledModes.ledOFF 
8 ledModes.ledON 
9 ledModes.ledBlink 
10 ledModes.ledOFF 
Verwandte Themen