def main(): logging.basicConfig(level=logging.INFO) logger = logging.getLogger('grow.test') if len(sys.argv) < 4: logger.error( 'Usage: ./test.py {sensor_channel} {pump_channel} {power}') exit(1) sensor_channel = int(sys.argv[1]) pump_channel = int(sys.argv[2]) pump_power = float(sys.argv[3]) moisture = Moisture(sensor_channel) pump = Pump(pump_channel) while True: logger.info(f"Moisture: {moisture.get_reading()}") pump.dose(pump_power, 10, True) sleep(10)
class Channel: colors = [(31, 137, 251), (99, 255, 124), (254, 219, 82), (247, 0, 63)] def __init__( self, channel_number, logger, title=None, water_level=0.5, warn_level=0.5, pump_speed=0.5, pump_time=0.2, watering_delay=60, wet_point=0.7, dry_point=26.7, icon=None, auto_water=False, enabled=False, ): self._run_file = f"/var/run/grow-monitor-{channel_number}" self.channel = channel_number self.sensor = Moisture(channel_number) self.pump = Pump(channel_number) self.logger = logger self.water_level = water_level self.warn_level = warn_level self.auto_water = auto_water self.pump_speed = pump_speed self.pump_time = pump_time self.watering_delay = watering_delay self._wet_point = wet_point self._dry_point = dry_point self.icon = icon self._enabled = enabled self._alarm = False self.title = f"Channel {channel_number}" if title is None else title self.sensor.set_wet_point(wet_point) self.sensor.set_dry_point(dry_point) @classmethod def channel_from_config(cls, number, config, logger): out = Channel(number, logger) out.update_from_yml(config) return out @property def enabled(self): return self._enabled @enabled.setter def enabled(self, enabled): self._enabled = enabled @property def alarm(self): return self._alarm @alarm.setter def alarm(self, alarm): self._alarm = alarm @property def wet_point(self): return self._wet_point @property def dry_point(self): return self._dry_point @property def last_dose(self): if not exists(self._run_file): self.set_last_dose() return getmtime(self._run_file) def set_last_dose(self): Path(self._run_file).touch(exist_ok=True) @wet_point.setter def wet_point(self, wet_point): self._wet_point = wet_point self.sensor.set_wet_point(wet_point) @dry_point.setter def dry_point(self, dry_point): self._dry_point = dry_point self.sensor.set_dry_point(dry_point) def indicator_color(self, value): value = 1.0 - value if value == 1.0: return self.colors[-1] if value == 0.0: return self.colors[0] value *= len(self.colors) - 1 a = int(math.floor(value)) b = a + 1 blend = float(value - a) r, g, b = [ int(((self.colors[b][i] - self.colors[a][i]) * blend) + self.colors[a][i]) for i in range(3) ] return r, g, b def update_from_yml(self, config): if config is not None: self.pump_speed = config.get("pump_speed", self.pump_speed) self.pump_time = config.get("pump_time", self.pump_time) self.warn_level = config.get("warn_level", self.warn_level) self.water_level = config.get("water_level", self.water_level) self.watering_delay = config.get("watering_delay", self.watering_delay) self.auto_water = config.get("auto_water", self.auto_water) self.enabled = config.get("enabled", self.enabled) self.wet_point = config.get("wet_point", self.wet_point) self.dry_point = config.get("dry_point", self.dry_point) self.alarm = config.get("alarm", self.alarm) pass def __str__(self): return """Channel: {channel} Enabled: {enabled} Alarm: {alarm} Alarm level: {warn_level} Auto water: {auto_water} Water level: {water_level} Pump speed: {pump_speed} Pump time: {pump_time} Delay: {watering_delay} Wet point: {wet_point} Dry point: {dry_point} """.format( channel=self.channel, enabled=self.enabled, warn_level=self.warn_level, auto_water=self.auto_water, water_level=self.water_level, pump_speed=self.pump_speed, pump_time=self.pump_time, watering_delay=self.watering_delay, wet_point=self.wet_point, dry_point=self.dry_point, alarm=self.alarm, ) def water(self): if time.time() - self.last_dose < self.watering_delay: return False self.pump.dose(self.pump_speed, self.pump_time, blocking=True) self.set_last_dose() return True def render(self, image, font): pass def update(self): if not self.enabled: self.logger.info(f"Channel {self.channel} is disabled") return sat = self.sensor.get_reading() if sat < self.water_level: if not self.auto_water: self.logger.info( f"Channel {self.channel} is not auto water and thirsty, sat: {sat} level: {self.water_level}" ) elif self.water(): self.logger.info( "Channel {} watering at {:.2f} for {:.2f}secs".format( self.channel, self.pump_speed, self.pump_time)) else: self.logger.info( f"Channel {self.channel} waiting for next dose, sat: {sat} level: {self.water_level}" ) else: self.logger.info( f"Channel {self.channel} does not need watering, sat: {sat} level: {self.water_level}" ) if sat < self.warn_level: if not self.alarm: self.logger.warning( "Channel {} ALARM - saturation is {:.2f}% (warn level {:.2f}%)" .format(self.channel, sat * 100, self.warn_level * 100)) self.alarm = True else: self.alarm = False