0

I'm really new to python and coding in general so I'm sorry if this is a stupid question... I'm working on a python 3 script that will automate a greenhouse with a raspberry pi. To check on temperature, light, moisture etc. and to upload pictures of the plant I have multiple functions. Now I want to call those functions individually after a certain amount of time has passed. So for example call the temperature function every 30 seconds, the light function every 45 and take a picture every 5 minutes. What would be the best way to do this?

lucluc
  • 13
  • 5
  • 1
    Take a look at the `threading` module, in particular the `Timer` class. – PM 2Ring Feb 07 '18 at 11:21
  • yess threading will be good option here – Narendra Feb 07 '18 at 11:23
  • 1
    Threading is one possible solution indeed, scheduled jobs is another. In all cases, just beware that unless you have a hard realtime os, notions like "every 30s" etc will be quite approximative. Shouldn't be a problem here but you may want to keep this in mind nonetheless. Oh and yes: better make sure a given call has finished before launching the next else you might have race conditions or other concurrency issues. – bruno desthuilliers Feb 07 '18 at 11:26

2 Answers2

2

Try something like this:

import logging
from threading import Timer

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(message)s')

CHK_TMP_IVAL = 30.0
CHK_LGHT_IVAL = 45.0
TAKE_PIC_IVAL = 5*60.0

def check_temp():
    logging.info('Checking temperature...')

def check_light():
    logging.info('Checking lighting...')

def take_pic():
    logging.info('Taking picture...')

def schedule_timing(interval, callback):
    timer = Timer(interval, callback)
    timer.start()
    return timer

if __name__ == '__main__':

    logging.info('Start execution...')
    t1 = schedule_timing(CHK_TMP_IVAL, check_temp)
    t2 = schedule_timing(CHK_LGHT_IVAL, check_light)
    t3 = schedule_timing(TAKE_PIC_IVAL, take_pic)


    while True:
        if t1.finished.is_set():
            t1 = schedule_timing(CHK_TMP_IVAL, check_temp)
        if t2.finished.is_set():
            t2 = schedule_timing(CHK_LGHT_IVAL, check_light)
        if t3.finished.is_set():
            t3 = schedule_timing(TAKE_PIC_IVAL, take_pic)

Hope it helps.

Szabolcs
  • 3,990
  • 18
  • 38
  • Thank you guys, this was exactly what I was looking for. I will try both these as soon as I get my hands back on the pi :) – lucluc Feb 07 '18 at 16:01
0

This is a minimal scheduler if you want to keep your program very simple. Perhaps too basic for a real-world usage, but it shows the concept.

import heapq
import time

class Sched:
    def __init__(self):
        self._queue = []

    def later(self, func, *args, delay):
        heapq.heappush(self._queue, (time.time() + delay, func, args))

    def loop(self):
        while True:
            ftime, func, args = heapq.heappop(self._queue)
            time.sleep(max(0.0, ftime - time.time()))
            func(*args)


sched = Sched()

def f2():
    sched.later(f2, delay=2.0)
    print("2 secs")

def f5():
    sched.later(f5, delay=5.0)
    print("5 secs")

f2()
f5()
sched.loop()
VPfB
  • 14,927
  • 6
  • 41
  • 75
  • Thank you guys, this was exactly what I was looking for. I will try both these as soon as I get my hands back on the pi :) – lucluc Feb 07 '18 at 16:01