Transition from one enumeration state to the next and

I just have a counter with 3 modes ledOn, ledBlink, ledOFF, and I have a variable mode that tracks the modes for a particular object. So, for example, I have one LED that starts in ledOn mode, which I would like, for example, after 5 seconds to go to the next element, which will be ledBlink, and then to ledOFF, and then go to ledON, is there an easy way to achieve something like that?

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()
+4
source share
3 answers

The easiest fix for your current code:

  • change your method runand
  • add method next_mode:

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
source

itertools.cycle :

>>> 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, next(ledModes), ledModes.next(), .

EDIT: - , :

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

:

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

Probably busting:

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

Then:

>>> 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
+1
source

All Articles