diff --git a/.gitignore b/.gitignore index 592ab39..e993544 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ dist/ build/ -__pycache__ +__pycache__/ greenhouse.egg-info/ diff --git a/greenhouse/__main__.py b/greenhouse/__main__.py index e3497ba..5486c91 100644 --- a/greenhouse/__main__.py +++ b/greenhouse/__main__.py @@ -7,85 +7,44 @@ import threading import time import RPi.GPIO as gpio -import paho.mqtt.client as mqtt -import Adafruit_DHT +from w1thermsensor import W1ThermSensor -SWITCH_ON_TEMP = 8.0 -SWITCH_OFF_TEMP = 10.0 +SWITCH_ON_TEMP = 3.0 +SWITCH_OFF_TEMP = 5.0 log_level = logging.INFO LOG_FILE = "/var/log/greenhouse.log" LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s" -#logging.basicConfig(format=LOG_FORMAT, level=log_level, filename=LOG_FILE) -logging.basicConfig(format=LOG_FORMAT, level=log_level) +logging.basicConfig(format=LOG_FORMAT, level=log_level, filename=LOG_FILE) +#logging.basicConfig(format=LOG_FORMAT, level=log_level) log = logging.getLogger('greenhouse') -class EnvData(object): - def __init__(self): - self.stamp = datetime.datetime.fromtimestamp(0) - self.temperature = -273.15 - self.humidity = -1.0 - self.is_valid = False - class EnvDataCollector(threading.Thread): - def __init__(self, name, dht_pin, update_interval=60): + def __init__(self, name, update_interval=60): super(EnvDataCollector, self).__init__() self.name = name - self.sensor = 22 - self.dht_pin = dht_pin + self.sensor = W1ThermSensor() self.update_interval = update_interval self.run_condition = True - self.data = EnvData() + self.temperature = self.sensor.get_temperature() + self.stamp=datetime.datetime.now() def run(self): next_update = datetime.datetime.now() while self.run_condition: now = datetime.datetime.now() if now >= next_update: - humidity, temperature = Adafruit_DHT.read(self.sensor, self.dht_pin) - if humidity is None or temperature is None: -# log.info("%s: No data read - setting re-read intterval to 1s.", self.name) - next_update = now + datetime.timedelta(seconds=10) - else: - if humidity >= 0.0 and humidity <= 100.0 and temperature >= -273.15: - self.data.temperature = temperature - self.data.humidity = humidity - self.data.stamp = now - self.data.is_valid = True - next_update = now + datetime.timedelta(seconds=self.update_interval) -# log.info("%s: Data read - setting re-read intterval to %ss.", -# self.name, self.update_interval) - else: -# log.info("%s: Invalid data read - setting re-read intterval to 1s.", -# self.name) - next_update = now + datetime.timedelta(seconds=10) + self.temperature = self.sensor.get_temperature() + self.stamp = now + next_update = now + datetime.timedelta(seconds=self.update_interval) time.sleep(1) def stop(self): self.run_condition = False self.join() - -class MqttHandler(object): - def __init__(self, url, port, certificate): - self.url = url - self.port = port - self.certificate = certificate - self.client = mqtt.Client() - self.client.tls_set(certificate) - self.client.connect(url, port, 60) - self.client.loop_start() - - def stop(self): - self.client.loop_stop() - self.client.disconnect() - - def transmit(self, topic, message): - self.client.publish(topic, message, qos=2, retain=True) - - class Heat(object): def __init__(self, pin): self.pin = pin @@ -99,106 +58,38 @@ class Heat(object): def off(self): gpio.output(self.pin, 1) -class Water(object): - def __init__(self, water_switch): - self.filename = "/var/log/relay_{}.state".format(water_switch) - - def state(self): - res = [0, 0, 0] - with open(self.filename, "r") as f: - ctx = f.read().strip().split(" ") - return ctx[0], ctx[1], ctx[2] - def main(): - old_green = EnvDataCollector("Greenhouse one", 17) - old_heat = Heat(6) - old_heat.off() - old_heat_state = "off" - old_water = Water(1) - last_old_water_state = "off" - new_green = EnvDataCollector("Greenhouse two", 21) - new_water = Water(2) - last_new_water_state = "off" - old_green.start() - new_green.start() + green = EnvDataCollector("Greenhouse one") + heat = Heat(26) + heat.off() + heat_state = "off" + green.start() - mqtt_handler = MqttHandler("mqtt.blackfinn.de", 8883, "/etc/ssl/certs/DST_Root_CA_X3.pem") try: - # let first temperature/humidity collection happen. - time.sleep(5) next_update = datetime.datetime.now() while True: now = datetime.datetime.now() - - # Water state - current_old_water_state = old_water.state() - if current_old_water_state[2] != last_old_water_state: - last_old_water_state = current_old_water_state[2] - msg = "{} {} {}".format(current_old_water_state[0], current_old_water_state[1], current_old_water_state[2]) - mqtt_handler.transmit("outdoor/greenhouse/water", msg) - - current_new_water_state = new_water.state() - if current_new_water_state[2] != last_new_water_state: - last_new_water_state = current_new_water_state[2] - msg = "{} {} {}".format(current_new_water_state[0], current_new_water_state[1], current_new_water_state[2]) - mqtt_handler.transmit("outdoor/greenhouse-2/water", msg) - if now >= next_update: - - # 1) Check timestamp of last data collection. If data are older - # than 5 minutes the sensor isn't working anymore. - if old_green.data.is_valid and old_green.data.stamp + datetime.timedelta(minutes=5) >= now: - msg = "{} {}".format(datetime.datetime.timestamp(old_green.data.stamp), old_green.data.temperature) - mqtt_handler.transmit("outdoor/greenhouse/temperature", msg) - log.info("%s: Temperature: %s", old_green.data.stamp.time(), old_green.data.temperature) - msg = "{} {}".format(datetime.datetime.timestamp(old_green.data.stamp), old_green.data.humidity) - mqtt_handler.transmit("outdoor/greenhouse/humidity", msg) - log.info("%s: Humidity: %s", old_green.data.stamp.time(), old_green.data.humidity) - if old_green.data.temperature < SWITCH_ON_TEMP and old_heat_state == "off": - old_heat.on() - old_heat_state = "on" - msg = "{} {}".format(time.time(), old_heat_state) - mqtt_handler.transmit("outdoor/greenhouse/heat", msg) - log.info("%s: Heat: switch %s", time.time(), old_heat_state) - elif old_green.data.temperature > SWITCH_OFF_TEMP and old_heat_state == "on": - old_heat.off() - old_heat_state = "off" - msg = "{} {}".format(time.time(), old_heat_state) - mqtt_handler.transmit("outdoor/greenhouse/heat", msg) - log.info("%s: Heat: switch %s", time.time(), old_heat_state) - elif old_heat_state == "on": - # Do a power cycle to prevent auto-poweroff - log.info("%s: Heat init power cycle.", time.time()) - old_heat.off() - time.sleep(5) - old_heat.on() - log.info("%s: Heat power cycle done.", time.time()) - next_update = now + datetime.timedelta(minutes=5) - else: - msg = "{} Error! Last valid DHT sensor data is from {}.".format(time.time(), old_green.data.stamp) - mqtt_handler.transmit("outdoor/greenhouse/status", msg) - log.error("%s: Error! Last valid DHT sensor data is from %s", time.time(), old_green.data.stamp) - next_update = now + datetime.timedelta(seconds=5) - - if new_green.data.is_valid and new_green.data.stamp + datetime.timedelta(minutes=5) >= now: - msg = "{} {}".format(datetime.datetime.timestamp(new_green.data.stamp), new_green.data.temperature) - mqtt_handler.transmit("outdoor/greenhouse-2/temperature", msg) - log.info("%s: Temperature: %s", new_green.data.stamp.time(), new_green.data.temperature) - msg = "{} {}".format(datetime.datetime.timestamp(new_green.data.stamp), new_green.data.humidity) - mqtt_handler.transmit("outdoor/greenhouse-2/humidity", msg) - log.info("%s: Humidity: %s", new_green.data.stamp.time(), new_green.data.humidity) - else: - msg = "{} Error! Last valid DHT sensor data is from {}.".format(time.time(), new_green.data.stamp) - mqtt_handler.transmit("outdoor/greenhouse-2/status", msg) - log.error("%s: Error! Last valid DHT sensor data is from %s", time.time(), new_green.data.stamp) - + log.info("Temperature: %.1f", float(green.temperature)) + if float(green.temperature) < SWITCH_ON_TEMP and heat_state == "off": + heat.on() + heat_state = "on" + log.info("Heat: switch %s", heat_state) + elif float(green.temperature) > SWITCH_OFF_TEMP and heat_state == "on": + heat.off() + heat_state = "off" + log.info("Heat: switch %s", heat_state) + elif heat_state == "on": + # Do a power cycle to prevent auto-poweroff + heat.off() + time.sleep(5) + heat.on() + next_update = now + datetime.timedelta(minutes=5) time.sleep(1) except KeyboardInterrupt: log.info("Shutting down...") - old_green.stop() - new_green.stop() - mqtt_handler.stop() - log.info("Exiting...") + green.stop() + log.info("Done") if __name__ == "__main__": sys.exit(main())