environment sensor library for raspberry dependencies to adafruit exist
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dht.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import logging
  2. import time
  3. try:
  4. from config import APP_NAME as ROOT_LOGGER_NAME
  5. except ImportError:
  6. ROOT_LOGGER_NAME = 'root'
  7. logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
  8. from . import background_task
  9. try:
  10. import adafruit_dht
  11. except ImportError:
  12. logger.warning("Could not import adafruit_dht. DEBUG set to True")
  13. DEBUG = True
  14. else:
  15. from . import DEBUG
  16. class dht_22(background_task):
  17. RUN_SLEEP_TIME = 4.0
  18. MIN_REFRESH_RATE = RUN_SLEEP_TIME
  19. KEY_TEMPERATURE = 'temperature'
  20. KEY_HUMIDITY = 'humidity'
  21. KEY_TIME = 'time'
  22. def __init__(self, gpio, data_callback=None):
  23. self.__data_callback__ = data_callback
  24. self.__temp_monitor__ = gradient_monitor(.5)
  25. self.__hum_monitor__ = gradient_monitor(5)
  26. self.__monitor__ = dht_22_monitor(300)
  27. # Initial the dht device, with data pin connected to:
  28. if not DEBUG:
  29. self.__dht_device__ = adafruit_dht.DHT22(gpio, use_pulseio=False)
  30. # Initialise background_task
  31. background_task.__init__(self)
  32. def __run__(self):
  33. data = self.__dht_data_transmission__()
  34. if data is not None:
  35. # check data
  36. if self.__temp_monitor__.process(data[self.KEY_TEMPERATURE], data[self.KEY_TIME]) and self.__hum_monitor__.process(data[self.KEY_HUMIDITY], data[self.KEY_TIME]):
  37. #
  38. logger.info('DHT-Communication successful: %s', repr(data))
  39. self.__monitor__.process(data)
  40. if self.__data_callback__ is not None:
  41. self.__data_callback__(**data)
  42. if self.__monitor__.status():
  43. logger.warning("DHT-Communication failed: Measurement stopped caused by suspicious constant values!")
  44. self.close()
  45. else:
  46. logger.debug("DHT-Communication failed: Gradient to high. Ignoring data %s!", repr(data))
  47. def __dht_data_transmission__(self):
  48. if not DEBUG:
  49. while self.__active__:
  50. try:
  51. # Store the values
  52. data = {}
  53. data[self.KEY_TEMPERATURE] = self.__dht_device__.temperature
  54. data[self.KEY_HUMIDITY] = self.__dht_device__.humidity
  55. data[self.KEY_TIME] = int(time.time())
  56. if data[self.KEY_TEMPERATURE] is not None and data[self.KEY_HUMIDITY] is not None:
  57. return data
  58. time.sleep(self.RUN_SLEEP_TIME)
  59. except RuntimeError as error:
  60. # Errors happen fairly often, DHT's are hard to read, just keep going
  61. logger.debug('DHT-Communication failed: ' + error.args[0])
  62. time.sleep(2.0)
  63. except Exception as error:
  64. self.__dht_device__.exit()
  65. raise error
  66. else:
  67. return {
  68. self.KEY_TEMPERATURE: -17.17,
  69. self.KEY_HUMIDITY: 1.7,
  70. self.KEY_TIME: int(time.time()),
  71. }
  72. class gradient_monitor(object):
  73. def __init__(self, max_gradient):
  74. self.__max_gradient__ = max_gradient
  75. #
  76. self.__last_value__ = None
  77. self.__last_time__ = None
  78. def process(self, value, time):
  79. if self.__last_value__ is not None and self.__last_time__ is not None:
  80. # Valid last value exists
  81. gradient = abs((value - self.__last_value__) / (time - self.__last_time__))
  82. if gradient > self.__max_gradient__:
  83. return False
  84. self.__last_value__ = value
  85. self.__last_time__ = time
  86. return True
  87. class dht_22_monitor(object):
  88. def __init__(self, max_const_treshold=250):
  89. self.__max_const_treshold__ = max_const_treshold
  90. self.__fail__ = False
  91. self.__max_const_measurements__ = 0
  92. self.__init_statevars__()
  93. def __init_statevars__(self):
  94. self.__current_const_measurements__ = 0
  95. self.__last_measurements__ = None
  96. def process(self, data):
  97. if self.__last_measurements__ is None:
  98. self.__last_measurements__ = data
  99. else:
  100. data_is_equal = True
  101. for key in [dht_22.KEY_HUMIDITY, dht_22.KEY_TEMPERATURE]:
  102. if data[key] != self.__last_measurements__[key]:
  103. data_is_equal = False
  104. if data_is_equal:
  105. self.__current_const_measurements__ += 1
  106. if self.__current_const_measurements__ > self.__max_const_measurements__:
  107. self.__max_const_measurements__ = self.__current_const_measurements__
  108. else:
  109. self.__init_statevars__()
  110. if self.__max_const_measurements__ > self.__max_const_treshold__:
  111. self.__fail__ = True
  112. def status(self):
  113. if self.__fail__:
  114. self.__fail__ = False
  115. self.__max_const_measurements__ = 0
  116. return True
  117. return False