Welcome, guest | Sign In | My Account | Store | Cart

FreshFish is a function decorator for functions with no arguments (hardware query).

The first time the function is called, the wrapper caches the result (the fish). Subsequent calls to the wrapped function simply return the cached result as long as the fish is still fresh. When the fish goes stale, FreshFish calls the underlying function again for FreshFish.

I used this on a BeagleBone project to monitor heart rate, speed, and cadence.

Python, 58 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import math
import time
import serial ## for heart rate monitor

try:
    import Adafruit_BBIO.GPIO as GPIO
    BBB = True
except:
    ## easier to write code on laptop then transfer to the BBB
    BBB = False

try:
    port = '/dev/ttyUSB0'
    ser = serial.Serial(port, baudrate=9600, timeout=.1)
except Exception, e:
    print 'No heartrate monitor detected', e
    ser = None

class FreshFish:
    '''
    Keep result around for specified time.  Refresh when "fish" goes bad
    '''
    def __init__(self, shelf_life=1):
        self.shelf_life = shelf_life
        self.last_time = 0
        self.last_result = None

    def __call__(self, f):
        def out():
            if time.time() - self.last_time < self.shelf_life:
                res = self.last_result
            else:
                res = f()
                self.last_time = time.time()
                self.last_result = res
            return res
        return out

@FreshFish(2)
def getHR():
    if BBB and ser:
        ser.write('G1' + chr(13))
        res = readline()
        if len(res) > 5:
            out = int(res.split()[2])
        else:
            out = 0
    else:
        ### return a dummy result
        out = int(50 * math.sin(time.time() / 20) + 50)
    return out

# ... in GUI

while True:
    ### getHR() gets called 10x / sec, but FreshFish limits hardware calls to 1x / 2 sec
    print getHR()
    time.sleep(.1) 

Result (depends on time) 91 91 91 91 91 91 91 91 91 88 88 88 88