HouseStats.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from datetime import datetime
  4. from abc import ABC, abstractmethod
  5. class _airStats(object):
  6. oxigenLevel = 0
  7. nitrogenLevel = 0
  8. methaneLevel = 0
  9. sulfurDioxidLevel = 0
  10. carbonMonoxidLevel = 0
  11. carbonDioxidLevel = 0
  12. particles_pm1 = 0
  13. particles_pm5 = 0
  14. particles_pm10 = 0
  15. def getJSON(self):
  16. return {
  17. "Oxigen": self.oxigenLevel,
  18. "Nitrogen": self.nitrogenLevel,
  19. "Methane": self.methaneLevel,
  20. "Sulfurdioxid": self.sulfurDioxidLevel,
  21. "Carbonmonoxid": self.carbonMonoxidLevel,
  22. "Carbondioxid": self.carbonDioxidLevel,
  23. "Particles_PM1": self.particles_pm1,
  24. "Particles_PM5": self.particles_pm5,
  25. "Particles_PM10":self.particles_pm10
  26. }
  27. class _temperatureProperty:
  28. _temperature = dict()
  29. __temperature_count = 0
  30. __temperature_coldest = 22
  31. __temperature_hottest = 22
  32. __temperature_avg = 22
  33. @property
  34. def count(self) -> int:
  35. return self.__temperature_count
  36. @property
  37. def coldest(self) -> float:
  38. return self.__temperature_coldest
  39. @property
  40. def hottest(self) -> float:
  41. return self.__temperature_hottest
  42. @property
  43. def avg(self) -> float:
  44. if self.__temperature_count==0:
  45. return 20.0
  46. else:
  47. return self.__temperature_avg
  48. def set(self, id:str, value:float):
  49. if id in self._temperature:
  50. if self._temperature[id] == value:
  51. # Value exists and didn't change
  52. return
  53. # Key doesn't exists or value has changed
  54. self._temperature[id] = value
  55. count = 0
  56. tempMin = 99.9
  57. tempMax = 0.0
  58. tempTotal = 0.0
  59. for k,v in self._temperature.items():
  60. count+=1
  61. tempTotal+=v
  62. if tempMin > v:
  63. tempMin = v
  64. if tempMax < v:
  65. tempMax = v
  66. self.__temperature_count = int(count)
  67. self.__temperature_coldest = float(tempMin)
  68. self.__temperature_hottest = float(tempMax)
  69. if count==0:
  70. return 20.0
  71. else:
  72. self.__temperature_avg = float(tempTotal / count)
  73. def getJSON(self):
  74. return {
  75. "count": self.count,
  76. "avg": self.avg,
  77. "coldest": self.coldest,
  78. "hottest": self.hottest
  79. }
  80. class _toggleProperty(ABC):
  81. _objects = dict()
  82. _count = 0
  83. _active = 0
  84. _inactive = 0
  85. _time_active = datetime.now()
  86. _time_inactive = datetime.now()
  87. _time_all_active = datetime.now()
  88. _time_all_inactive = datetime.now()
  89. @property
  90. def count(self) -> int:
  91. return self._count
  92. def set(self, id:str, state:bool):
  93. if id in self._objects:
  94. if self._objects[id] == state:
  95. # Value exists and didn't change
  96. return
  97. # Key doesn't exists or value has changed
  98. if self._count == self._off:
  99. self._time_all_inactive = datetime.now()
  100. if self._off>0:
  101. self._time_inactive = datetime.now()
  102. if self._count == self._open:
  103. self._time_all_active = datetime.now()
  104. if self._on>0:
  105. self._time_active = datetime.now()
  106. self._objects[id] = state
  107. count = 0
  108. countOn = 0
  109. countOff = 0
  110. for k,v in self._objects.items():
  111. count+=1
  112. if v==True:
  113. countOn+=1
  114. else:
  115. countOff+=1
  116. self._count = count
  117. self._active = countOn
  118. self._inactive = countOff
  119. @abstractmethod
  120. def getJSON(self):
  121. pass
  122. def _readableTime(self, time:datetime):
  123. return time
  124. class _onOffProperty(_toggleProperty):
  125. @property
  126. def bAllOn(self) -> bool:
  127. return self._count <= self._active
  128. @property
  129. def bAllOff(self) -> bool:
  130. return self._count <= self._inactive
  131. @property
  132. def on(self) -> int:
  133. return self._active
  134. @property
  135. def off(self) -> int:
  136. return self._inactive
  137. @property
  138. def lastTimeOn(self) -> datetime:
  139. if self._active>0:
  140. return datetime.now()
  141. else:
  142. self._time_active
  143. @property
  144. def lastTimeAllOn(self) -> datetime:
  145. if self._count == self._active:
  146. return datetime.now()
  147. else:
  148. self._time_all_active
  149. @property
  150. def laseTimeOff(self) -> datetime:
  151. if self._inactive>0:
  152. return datetime.now()
  153. else:
  154. return self._time_inactive
  155. @property
  156. def lastTimeAllOff(self) -> datetime:
  157. if self._count == self._inactive:
  158. return datetime.now()
  159. else:
  160. return self._time_all_inactive
  161. def getJSON(self):
  162. return {
  163. "All_Off": self.bAllOn,
  164. "All_On": self.bAllOff,
  165. "LastTimeOpen": self._readableTime(self.lastTimeOn),
  166. "LaseTimeClose": self._readableTime(self.laseTimeOff),
  167. "LastTimeAllOpen": self._readableTime(self.lastTimeAllOn),
  168. "LastTimeAllClosed": self._readableTime(self.lastTimeAllOff),
  169. "Count": self.count,
  170. "OnCount": self.on,
  171. "OffCount": self.off
  172. }
  173. class _openCloseProperty(_toggleProperty):
  174. @property
  175. def bAllOpen(self) -> bool:
  176. return self._count <= self._active
  177. @property
  178. def bAllClose(self) -> bool:
  179. return self._count <= self._inactive
  180. @property
  181. def open(self) -> int:
  182. return self._active
  183. @property
  184. def close(self) -> int:
  185. return self._inactive
  186. @property
  187. def lastTimeOpen(self) -> datetime:
  188. if self._active>0:
  189. return datetime.now()
  190. else:
  191. self._time_active
  192. @property
  193. def lastTimeAllOpen(self) -> datetime:
  194. if self._count == self._active:
  195. return datetime.now()
  196. else:
  197. self._time_all_active
  198. @property
  199. def laseTimeClose(self) -> datetime:
  200. if self._inactive>0:
  201. return datetime.now()
  202. else:
  203. return self._time_inactive
  204. @property
  205. def lastTimeAllClose(self) -> datetime:
  206. if self._count == self._inactive:
  207. return datetime.now()
  208. else:
  209. return self._time_all_inactive
  210. def getJSON(self):
  211. return {
  212. "All_Closed": self.bAllOpen,
  213. "All_Opened": self.bAllClose,
  214. "LastTimeOpen": self._readableTime(self.lastTimeOpen),
  215. "LaseTimeClose": self._readableTime(self.laseTimeClose),
  216. "LastTimeAllOpen": self._readableTime(self.lastTimeAllOpen),
  217. "LastTimeAllClosed": self._readableTime(self.lastTimeAllClose),
  218. "Count": self.count,
  219. "OpenCount": self.open,
  220. "CloseCount": self.close
  221. }
  222. class HouseStats(object):
  223. def __init__(self):
  224. self._movements = dict()
  225. self._rooms = dict()
  226. self._air = _airStats()
  227. self.__lightsProp = _onOffProperty()
  228. self.__switchesProp = _onOffProperty()
  229. self.__windowsProp = _openCloseProperty()
  230. self.__doorsProp = _openCloseProperty()
  231. self.__temperature = _temperatureProperty()
  232. @property
  233. def Lights(self) -> _onOffProperty:
  234. return self.__lightsProp
  235. @property
  236. def Switches(self) -> _onOffProperty:
  237. return self.__switchesProp
  238. @property
  239. def Windows(self) -> _onOffProperty:
  240. return self.__windowsProp
  241. @property
  242. def Doors(self) -> _onOffProperty:
  243. return self.__doorsProp
  244. @property
  245. def Temperature(self) -> _temperatureProperty:
  246. return self.__temperature
  247. @property
  248. def Air(self) -> _airStats:
  249. return self._air
  250. #TODO Rooms
  251. #TODO Movement Stats
  252. def getJson(self):
  253. return {
  254. "Temperature": self.Temperature.getJSON(),
  255. "Windows": self.Windows.getJSON(),
  256. "Doors": self.Doors.getJSON(),
  257. "Lights": self.Lights.getJSON(),
  258. "Switches": self.Lights.getJSON(),
  259. "Air": self.Air.getJSON(),
  260. "Rooms": {
  261. # TODO
  262. },
  263. "Movements": {
  264. # TODO
  265. }
  266. }