import atexit from time import perf_counter try: import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) rpi = True except: rpi = False class GPIO(): LOW = 0 HIGH = 1 class Actuator(): def __init__(self, *args, **kwargs): self.wattage = kwargs.pop('wattage') self.total_seconds_on = 0 self.logging = False self.started_at = 0 def log_on(self): if self.logging: return self.started_at = perf_counter() self.logging = True def elapsed(self): return perf_counter() - self.started_at def log_off(self): if not self.logging: return self.total_seconds_on += self.elapsed() self.logging = False def s_to_hr(self, s): return s / 60 / 60 def consumption(self): total_time = self.total_seconds_on if self.logging: # If we are on, count this time too total_time += self.elapsed() return self.s_to_hr(total_time) * self.wattage class GPIOPin(Actuator): def __init__(self, *args, **kwargs): self.pin = kwargs.pop('pin') self.initial = kwargs.pop('initial') self.onstate = kwargs.pop('onstate') self.offstate = kwargs.pop('offstate') GPIO.setup(self.pin, GPIO.OUT, initial=self.initial) atexit.register(self.deinit) super().__init__(*args, **kwargs) def deinit(self): # Be sure everything is off at exit print('Cleaning before exit') GPIO.output(self.pin, self.initial) GPIO.cleanup() def enable(self, enable=True): GPIO.output(self.pin, self.onstate) if enable else self.disable() if enable: self.log_on() else: self.log_off() def disable(self): GPIO.output(self.pin, self.offstate) self.log_off() class MockPIN(Actuator): def __init__(self, *args, **kwargs): self.pin = kwargs.pop('pin') self.initial = kwargs.pop('initial') self.onstate = kwargs.pop('onstate') self.offstate = kwargs.pop('offstate') super().__init__(*args, **kwargs) def enable(self, enable=True): if enable: self.log_on() else: self.log_off() # print('FAKE ENABLE') if enable else self.disable() def disable(self): self.log_off() # print('FAKE DISABLE') def PIN(*args, **kwargs): return (GPIOPin if rpi else MockPIN)(*args, **kwargs) actuators = { 'heater': PIN(pin=22, initial=GPIO.HIGH, onstate=GPIO.LOW, offstate=GPIO.HIGH, wattage=100), 'fan': PIN(pin=27, initial=GPIO.HIGH, onstate=GPIO.LOW, offstate=GPIO.HIGH, wattage=12*0.4), 'humidifier': PIN(pin=17, initial=GPIO.HIGH, onstate=GPIO.LOW, offstate=GPIO.HIGH, wattage=25), 'heater2': PIN(pin=17, initial=GPIO.HIGH, onstate=GPIO.LOW, offstate=GPIO.HIGH, wattage=2000), }