Compare commits

...

1 Commits

Author SHA1 Message Date
Thomas Klaehn
e00cb15236 Change temperature sensor from DHT22 to DS18B20 2021-03-16 08:23:11 +01:00
3 changed files with 36 additions and 145 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
dist/ dist/
build/ build/
__pycache__ __pycache__/
greenhouse.egg-info/ greenhouse.egg-info/

View File

@ -7,85 +7,44 @@ import threading
import time import time
import RPi.GPIO as gpio import RPi.GPIO as gpio
import paho.mqtt.client as mqtt from w1thermsensor import W1ThermSensor
import Adafruit_DHT
SWITCH_ON_TEMP = 8.0 SWITCH_ON_TEMP = 3.0
SWITCH_OFF_TEMP = 10.0 SWITCH_OFF_TEMP = 5.0
log_level = logging.INFO log_level = logging.INFO
LOG_FILE = "/var/log/greenhouse.log" LOG_FILE = "/var/log/greenhouse.log"
LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s" 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, filename=LOG_FILE)
logging.basicConfig(format=LOG_FORMAT, level=log_level) #logging.basicConfig(format=LOG_FORMAT, level=log_level)
log = logging.getLogger('greenhouse') 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): class EnvDataCollector(threading.Thread):
def __init__(self, name, dht_pin, update_interval=60): def __init__(self, name, update_interval=60):
super(EnvDataCollector, self).__init__() super(EnvDataCollector, self).__init__()
self.name = name self.name = name
self.sensor = 22 self.sensor = W1ThermSensor()
self.dht_pin = dht_pin
self.update_interval = update_interval self.update_interval = update_interval
self.run_condition = True self.run_condition = True
self.data = EnvData() self.temperature = self.sensor.get_temperature()
self.stamp=datetime.datetime.now()
def run(self): def run(self):
next_update = datetime.datetime.now() next_update = datetime.datetime.now()
while self.run_condition: while self.run_condition:
now = datetime.datetime.now() now = datetime.datetime.now()
if now >= next_update: if now >= next_update:
humidity, temperature = Adafruit_DHT.read(self.sensor, self.dht_pin) self.temperature = self.sensor.get_temperature()
if humidity is None or temperature is None: self.stamp = now
# 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) 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)
time.sleep(1) time.sleep(1)
def stop(self): def stop(self):
self.run_condition = False self.run_condition = False
self.join() 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): class Heat(object):
def __init__(self, pin): def __init__(self, pin):
self.pin = pin self.pin = pin
@ -99,106 +58,38 @@ class Heat(object):
def off(self): def off(self):
gpio.output(self.pin, 1) 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(): def main():
old_green = EnvDataCollector("Greenhouse one", 17) green = EnvDataCollector("Greenhouse one")
old_heat = Heat(6) heat = Heat(26)
old_heat.off() heat.off()
old_heat_state = "off" heat_state = "off"
old_water = Water(1) green.start()
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()
mqtt_handler = MqttHandler("mqtt.blackfinn.de", 8883, "/etc/ssl/certs/DST_Root_CA_X3.pem")
try: try:
# let first temperature/humidity collection happen.
time.sleep(5)
next_update = datetime.datetime.now() next_update = datetime.datetime.now()
while True: while True:
now = datetime.datetime.now() 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: if now >= next_update:
log.info("Temperature: %.1f", float(green.temperature))
# 1) Check timestamp of last data collection. If data are older if float(green.temperature) < SWITCH_ON_TEMP and heat_state == "off":
# than 5 minutes the sensor isn't working anymore. heat.on()
if old_green.data.is_valid and old_green.data.stamp + datetime.timedelta(minutes=5) >= now: heat_state = "on"
msg = "{} {}".format(datetime.datetime.timestamp(old_green.data.stamp), old_green.data.temperature) log.info("Heat: switch %s", heat_state)
mqtt_handler.transmit("outdoor/greenhouse/temperature", msg) elif float(green.temperature) > SWITCH_OFF_TEMP and heat_state == "on":
log.info("%s: Temperature: %s", old_green.data.stamp.time(), old_green.data.temperature) heat.off()
msg = "{} {}".format(datetime.datetime.timestamp(old_green.data.stamp), old_green.data.humidity) heat_state = "off"
mqtt_handler.transmit("outdoor/greenhouse/humidity", msg) log.info("Heat: switch %s", heat_state)
log.info("%s: Humidity: %s", old_green.data.stamp.time(), old_green.data.humidity) elif heat_state == "on":
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 # Do a power cycle to prevent auto-poweroff
log.info("%s: Heat init power cycle.", time.time()) heat.off()
old_heat.off()
time.sleep(5) time.sleep(5)
old_heat.on() heat.on()
log.info("%s: Heat power cycle done.", time.time())
next_update = now + datetime.timedelta(minutes=5) 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)
time.sleep(1) time.sleep(1)
except KeyboardInterrupt: except KeyboardInterrupt:
log.info("Shutting down...") log.info("Shutting down...")
old_green.stop() green.stop()
new_green.stop() log.info("Done")
mqtt_handler.stop()
log.info("Exiting...")
if __name__ == "__main__": if __name__ == "__main__":
sys.exit(main()) sys.exit(main())

View File

@ -15,7 +15,7 @@ EMAIL = 'tkl@blackfinn.de'
SYSTEMD_SCRIPTS = ['greenhouse.service'] SYSTEMD_SCRIPTS = ['greenhouse.service']
PACKAGES = ['greenhouse'] PACKAGES = ['greenhouse']
PACKAGE_DIRS = {'greenhouse':'greenhouse'} PACKAGE_DIRS = {'greenhouse':'greenhouse'}
REQUIRES = ['RPi.GPIO', 'Adafruit_DHT', 'paho-mqtt'] REQUIRES = ['RPi.GPIO', 'w1thermsensor']
SYSTEMD_PATH = '/lib/systemd/system/' SYSTEMD_PATH = '/lib/systemd/system/'