main.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from Stats.DeviceStats import DeviceStats as _DeviceStats
  4. from Stats.HouseStats import HouseStats as _HouseStats
  5. from Stats.MicLevel import MicLevel as _MicLevel
  6. from Stats.OutdoorStats import OutdoorStats as _OutdoorStats
  7. from Stats.OwnerStats import OwnerStats as _OwnerStats
  8. from Stats.TalkingStats import TalkingStats as _TalkingStats
  9. from Stats.AdminStats import AdminStats as _AdminStats
  10. import MicCapture
  11. import OpenWeatherMap
  12. #from Homematic import Homematic
  13. from threading import Timer
  14. import time
  15. import datetime
  16. import configparser
  17. from lib.RepeatTimer import RepeatTimer
  18. import lib.MoonPhase as mp
  19. import random
  20. class Stats:
  21. instance = None
  22. @staticmethod
  23. def getInstance():
  24. if Stats.instance==None:
  25. Stats.instance = Stats()
  26. return Stats.instance
  27. #deviceStats:_DeviceStats = _DeviceStats()
  28. #houseStats:_HouseStats = _HouseStats()
  29. #micLevel:_MicLevel = _MicLevel()
  30. #outdoorStats = _OutdoorStats()
  31. #ownerStats = _OwnerStats()
  32. #talkingStats = _TalkingStats()
  33. #adminStats = _AdminStats()
  34. UPDATE_EMOTION_DELAY_MINUTE = 0.2
  35. UPDATE_HOMEMATIC_DELAY_MINUTE = 1
  36. UPDATE_DATETIME_DELAY_MINUTE = 10
  37. UPDATE_OUTDOOR_DELAY_MINUTE = 2.1
  38. UPDATE_MIC_DELAY_MINUTE = 0.5
  39. Thread_Homematic = None
  40. Thread_Emotion = None
  41. Thread_DateTime = None
  42. Thread_OutDoor = None
  43. Thread_Mic = None
  44. lastUpdate = 0.0
  45. Mic = MicCapture.MicCapture()
  46. def __init__(self):
  47. print("Init Stats")
  48. print("- Read Config")
  49. try:
  50. config = configparser.ConfigParser()
  51. config.read('config/stats.ini')
  52. except:
  53. print("Failed to get Config")
  54. config = dict
  55. self._weather = OpenWeatherMap.OpenWeatherMap()
  56. self._deviceStats:_DeviceStats = _DeviceStats()
  57. self._houseStats:_HouseStats = _HouseStats()
  58. self._micLevel:_MicLevel = _MicLevel()
  59. self._outdoorStats = _OutdoorStats()
  60. self._ownerStats = _OwnerStats()
  61. self._talkingStats = _TalkingStats()
  62. self._adminStats = _AdminStats()
  63. self._outdoorStats.MoonPhase = mp.phase(time=datetime.datetime.now())
  64. self._deviceStats.lastUpdate = time.time()
  65. self.__UpdateDateTime()
  66. self.Thread_DateTime = RepeatTimer(self.UPDATE_DATETIME_DELAY_MINUTE*60, self.__UpdateDateTime)
  67. self.Thread_DateTime.start()
  68. self.__UpdateOutdoor()
  69. self.Thread_OutDoor = RepeatTimer(self.UPDATE_OUTDOOR_DELAY_MINUTE*60, self.__UpdateOutdoor)
  70. self.Thread_OutDoor.start()
  71. self.Thread_Mic = RepeatTimer(self.UPDATE_MIC_DELAY_MINUTE*60, self.__UpdateMic)
  72. self.Thread_Mic.start()
  73. print("- Init Emotion")
  74. self.Thread_Emotion = RepeatTimer(self.UPDATE_EMOTION_DELAY_MINUTE*60, self.__UpdateEmotion)
  75. print("- - Start Emotion Timer")
  76. self.Thread_Emotion.start()
  77. print("- - Init Stats done")
  78. @property
  79. def HouseStats(self) -> _HouseStats:
  80. return self._houseStats
  81. @property
  82. def DeviceStats(self) -> _DeviceStats:
  83. return self._deviceStats
  84. @property
  85. def OutdoorStats(self) -> _OutdoorStats:
  86. return self._outdoorStats
  87. @property
  88. def OwnerStats(self) -> _OwnerStats:
  89. return self._ownerStats
  90. @property
  91. def TalkingStats(self) -> _TalkingStats:
  92. return self._talkingStats
  93. @property
  94. def AdminStats(self) -> _AdminStats:
  95. return self._adminStats
  96. @property
  97. def WeatherInfo(self) -> OpenWeatherMap.OpenWeatherMap:
  98. return self._weather
  99. def __UpdateMic(self):
  100. self.Mic.Update()
  101. self._micLevel.Volume_Min = self.Mic.LastResult["min"]
  102. self._micLevel.Volume_Max = self.Mic.LastResult["max"]
  103. self._micLevel.Volume_Avg = self.Mic.LastResult["avg"]
  104. #print(self._micLevel.getJson())
  105. def __UpdateDateTime(self):
  106. self._outdoorStats.MoonPhase = mp.phase(time=datetime.datetime.now())
  107. def __UpdateOutdoor(self):
  108. self._weather.Update()
  109. self._outdoorStats.bRaining = self._weather.CurrentLocation.Rain.PerHour>0.1
  110. self._outdoorStats.bSnowing = self._weather.CurrentLocation.Rain.PerHour>0.1 and self.weather.CurrentLocation.Main.TempMax<1
  111. self._outdoorStats.bWindy = self._weather.CurrentLocation.Wind.Speed>20
  112. self._outdoorStats.Clouds = self._weather.CurrentLocation.Clouds.All
  113. self._outdoorStats.Humidity = self._weather.CurrentLocation.Main.Humidity
  114. self._outdoorStats.Pressure = self._weather.CurrentLocation.Main.Pressure
  115. self._outdoorStats.Temperature = self._weather.CurrentLocation.Main.Temperature
  116. self._outdoorStats.WindDegree = self._weather.CurrentLocation.Wind.Deg
  117. self._outdoorStats.WindSpeed = self._weather.CurrentLocation.Wind.Speed
  118. #def __UpdateHomematic(self):
  119. # print("Update Homematic")
  120. # self.homematic.updateDevices()
  121. # # Check open/closed windows
  122. # self.houseStats.bAllWindowOpen = True
  123. # self.houseStats.bAllWindowClosed = True
  124. # for ise in self.homematic.favWindowList:
  125. # if self.homematic.windowList[ise]["value"]==False:
  126. # self.houseStats.bAllWindowOpen = False
  127. # else:
  128. # self.houseStats.bAllWindowClosed = False
  129. # # Check open/closed doors
  130. # self.houseStats.bAllDoorOpen = True
  131. # self.houseStats.bAllDoorClosed = True
  132. # for ise in self.homematic.favDoorList:
  133. # if self.homematic.doorList[ise]["value"]==False:
  134. # self.houseStats.bAllDoorOpen = False
  135. # else:
  136. # self.houseStats.bAllDoorClosed = False
  137. # # Check all Lights
  138. # self.houseStats.bAllLightOn = True
  139. # self.houseStats.bAllLightOff = True
  140. # for ise in self.homematic.favLightList:
  141. # if self.homematic.lightList[ise]["value"]==False:
  142. # self.houseStats.bAllLightOn = False
  143. # else:
  144. # self.houseStats.bAllLightOff = False
  145. # # Termo
  146. # temp_min=40.0
  147. # temp_max=0.0
  148. # temp_avg_add=0.0
  149. # temp_avg_count=0
  150. # for ise in self.homematic.favThermoList:
  151. # if self.homematic.thermoList[ise]["value"] > temp_max:
  152. # temp_max = self.homematic.thermoList[ise]["value"]
  153. # if self.homematic.thermoList[ise]["value"] < temp_min:
  154. # temp_min = self.homematic.thermoList[ise]["value"]
  155. # temp_avg_add += self.homematic.thermoList[ise]["value"]
  156. # temp_avg_count += 1
  157. # self.houseStats.temp_avg = temp_avg_add / temp_avg_count
  158. # self.houseStats.temp_coldest = temp_min
  159. # self.houseStats.temp_hottest = temp_max
  160. def __UpdateEmotion(self):
  161. print("Update Emotion")
  162. newTime = int(time.time())
  163. updateDur = float(self._deviceStats.MAX_VALUE * ((newTime - self._deviceStats.lastUpdate) / 3600)) # Per Thausend
  164. self._deviceStats.lastUpdate = newTime
  165. #curHour = ((newTime % 86400) / 3600)
  166. curHour = datetime.datetime.now().hour
  167. moonImpact = 1.0
  168. # Define MoonPhase Impact
  169. if self._outdoorStats.MoonPhase["phase"]==4:
  170. if self._outdoorStats.Clouds>80:
  171. if curHour>23 or curHour<6:
  172. moonImpact += random.randint(0,9)/60
  173. else:
  174. moonImpact += random.randint(0,5)/80
  175. else:
  176. if curHour>23 or curHour<6:
  177. moonImpact += random.randint(0,9)/120
  178. else:
  179. moonImpact += random.randint(0,5)/180
  180. # Calculate impact for stats calculation
  181. impact = moonImpact
  182. if time.time() - self._deviceStats.lastTimeToLoud > 600:
  183. self._deviceStats.toLoud += float(updateDur / 8) * impact
  184. if time.time() - self._deviceStats.lastTimeToQuiet > 600:
  185. self._deviceStats.toQuiet += float(updateDur / 8) * impact
  186. # Home depended
  187. if self._houseStats.Temperature.avg > 25.0 or self._houseStats.Temperature.hottest > 28.0:
  188. self._deviceStats.hot += float(updateDur / 12) * impact
  189. else:
  190. self._deviceStats.hot -= float(updateDur / 38) * impact
  191. if self._houseStats.Temperature.avg < 17.0 or self._houseStats.Temperature.coldest < 15.0:
  192. self._deviceStats.freezy += float(updateDur / 12) * impact
  193. else:
  194. self._deviceStats.freezy -= float(updateDur / 38) * impact
  195. if self._deviceStats.hot <200 and self._deviceStats.freezy < 200:
  196. self._deviceStats.temperate -= float(updateDur / 12) * impact
  197. else:
  198. self._deviceStats.temperate += float(updateDur / 48) * impact
  199. self._deviceStats.toLoud -= (float)(updateDur / 48)
  200. if self._ownerStats.bIsAtHome == True and self._ownerStats.bSleeping == False:
  201. self._deviceStats.toQuiet -= (float)(updateDur / 48)
  202. # substractive
  203. self._deviceStats.angry -= (float)(updateDur / 48) * impact # 48std to 1000
  204. self._deviceStats.annoyed -= (float)(updateDur / 50)
  205. self._deviceStats.aroused -= (float)(updateDur / 72) * impact
  206. if self._ownerStats.bSleeping:
  207. self._deviceStats.exhausted -= (float)(updateDur / 18)
  208. else:
  209. self._deviceStats.exhausted -= (float)(updateDur / 48)
  210. self._deviceStats.humanity -= (float)(updateDur / 48)
  211. self._deviceStats.naiv -= (float)(updateDur / 48)
  212. self._deviceStats.shy -= (float)(updateDur / 500)
  213. self._deviceStats.soziality -= (float)(updateDur / 48) * impact
  214. self._deviceStats.usefull -= (float)(updateDur / 48)
  215. # Additive
  216. self._deviceStats.bored += (float)(updateDur / 50)
  217. if self._ownerStats.bSleeping:
  218. self._deviceStats.energy += (float)(updateDur / 14) * impact
  219. else:
  220. self._deviceStats.energy += (float)(updateDur / 30) * impact
  221. self._deviceStats.useless += (float)(updateDur / 168) # 168 = 1 Woche
  222. if self._deviceStats.angry>500 or self._deviceStats.annoyed>400 or self._deviceStats.depressive>300 or self._deviceStats.energy<100 or self._deviceStats.sleepy>500 or self._deviceStats.toLoud>300:
  223. self._deviceStats.exhausted += (float)(updateDur / 18)
  224. if self._deviceStats.toQuiet > 50:
  225. if self._deviceStats.toQuiet > 150:
  226. if self._deviceStats.toQuiet > 450:
  227. if self._deviceStats.toQuiet > 600:
  228. self._deviceStats.lonely+= (float)(updateDur / 5)
  229. else:
  230. self._deviceStats.lonely+=(float)(updateDur / 8)
  231. else:
  232. self._deviceStats.lonely+=(float)(updateDur / 32)
  233. else:
  234. self._deviceStats.lonely+=(float)(updateDur / 64)
  235. # Dependend
  236. if self._deviceStats.usefull > 600:
  237. self._deviceStats.happyness += (float)(updateDur / 20) * impact
  238. elif self._deviceStats.usefull > 400:
  239. self._deviceStats.happyness += (float)(updateDur / 40) * impact
  240. elif self._deviceStats.usefull > 300 and self._deviceStats.useless < 300:
  241. self._deviceStats.happyness += (float)(updateDur / 50) * impact
  242. else:
  243. self._deviceStats.happyness -= (float)(updateDur / 20)
  244. if self._deviceStats.temperate > 300:
  245. self._deviceStats.angry += (float)(updateDur / 60) * impact
  246. if self._deviceStats.freezy > 400 or self._deviceStats.hot > 400:
  247. self._deviceStats.angry += (float)(updateDur / 50) * impact
  248. if self._deviceStats.toLoud > 300 or self._deviceStats.toQuiet > 500:
  249. self._deviceStats.angry += (float)(updateDur / 30) * impact
  250. if self._ownerStats.bSleeping:
  251. self._deviceStats.sleepy -= (float)(updateDur / 15) * impact
  252. else:
  253. if self._deviceStats.toQuiet > 300:
  254. self._deviceStats.sleepy += (float)(updateDur / 24);
  255. if curHour > 21 or curHour < 8:
  256. self._deviceStats.sleepy += (float)(updateDur / 48)
  257. if self._outdoorStats.bRaining == True:
  258. if self._outdoorStats.bWindy:
  259. self._deviceStats.depressive += (float)(updateDur / 10)
  260. else:
  261. self._deviceStats.depressive += (float)(updateDur / 20)
  262. elif self._deviceStats.angry > 650:
  263. self._deviceStats.depressive += (float)(updateDur / 40) * impact
  264. elif self._deviceStats.angry > 500:
  265. self._deviceStats.depressive += (float)(updateDur / 50) * impact
  266. elif self._deviceStats.angry > 300:
  267. self._deviceStats.depressive += (float)(updateDur / 90) * impact
  268. else:
  269. self._deviceStats.depressive -= (float)(updateDur / 50)
  270. self._deviceStats.excited += (float)(updateDur / 50)
  271. if self._deviceStats.depressive > 70:
  272. if self._deviceStats.angry < 100:
  273. self._deviceStats.happyness += (float)(updateDur / 120)
  274. if self._deviceStats.compfortable > 300:
  275. self._deviceStats.happyness += (float)(updateDur / 120)
  276. else:
  277. if self._deviceStats.angry < 120:
  278. self._deviceStats.happyness += (float)(updateDur / 120)
  279. if self._deviceStats.angry < 80:
  280. self._deviceStats.happyness += (float)(updateDur / 45)
  281. if self._deviceStats.compfortable > 300:
  282. self._deviceStats.happyness += (float)(updateDur / 90)
  283. if self._deviceStats.happyness > 150:
  284. self._deviceStats.funny += (float)(updateDur / 48) # Depends on happyness (>100) and other stats
  285. if self._deviceStats.happyness > 300:
  286. self._deviceStats.funny += (float)(updateDur / 48) # Depends on happyness (>100) and other stats
  287. else:
  288. self._deviceStats.funny -= (float)(updateDur / 90) # Depends on other stats
  289. if self._deviceStats.hot < 100 and self._deviceStats.freezy < 100:
  290. self._deviceStats.compfortable += (float)(updateDur / 90) # Depends on other stats
  291. if self._deviceStats.toLoud < 200 and self._deviceStats.toQuiet < 400:
  292. self._deviceStats.compfortable += (float)(updateDur / 120) # Depends on other stats
  293. if self._deviceStats.hot > 800 or self._deviceStats.freezy > 800:
  294. self._deviceStats.compfortable -= (float)(updateDur / 20) # Depends on other stats
  295. self._deviceStats.playful -= (float)(updateDur / 20) * impact # Depends on other stats
  296. self._deviceStats.energy -= (float)(updateDur / 15) * impact
  297. elif self._deviceStats.hot > 400 or self._deviceStats.freezy > 350:
  298. self._deviceStats.compfortable -= (float)(updateDur / 80) # Depends on other stats
  299. self._deviceStats.energy -= (float)(updateDur / 30)
  300. elif self._deviceStats.hot > 200 or self._deviceStats.freezy > 100:
  301. self._deviceStats.compfortable -= (float)(updateDur / 150) # Depends on other stats
  302. if self._deviceStats.toLoud > 800 or self._deviceStats.toQuiet > 800:
  303. self._deviceStats.compfortable -= (float)(updateDur / 20) # Depends on other stats
  304. self._deviceStats.angry += (float)(updateDur / 20) * impact
  305. self._deviceStats.sleepy += (float)(updateDur / 20)
  306. self._deviceStats.lonely -= (float)(updateDur / 100) * impact
  307. self._deviceStats.happyness -= (float)(updateDur / 100)
  308. self._deviceStats.bored -= (float)(updateDur / 100)
  309. self._deviceStats.annoyed += (float)(updateDur / 100)
  310. elif self._deviceStats.toLoud > 400 or self._deviceStats.toQuiet > 80:
  311. self._deviceStats.compfortable -= (float)(updateDur / 80) # Depends on other stats
  312. self._deviceStats.angry += (float)(updateDur / 80)
  313. self._deviceStats.sleepy += (float)(updateDur / 80) * impact
  314. self._deviceStats.annoyed += (float)(updateDur / 150) * impact
  315. elif self._deviceStats.toLoud > 200 or self._deviceStats.toQuiet > 100:
  316. self._deviceStats.compfortable -= (float)(updateDur / 150) # Depends on other stats
  317. self._deviceStats.sleepy += (float)(updateDur / 100)
  318. if self._deviceStats.happyness > 650 and self._deviceStats.funny > 500:
  319. self._deviceStats.playful += (float)(updateDur / 8) # Depends on naiv, funny and other stats
  320. elif self._deviceStats.happyness > 500 and self._deviceStats.funny > 500:
  321. self._deviceStats.playful += (float)(updateDur / 12) * impact # Depends on naiv, funny and other stats
  322. elif self._deviceStats.happyness > 300 and self._deviceStats.funny > 300:
  323. self._deviceStats.playful += (float)(updateDur / 18) # Depends on naiv, funny and other stats
  324. elif self._deviceStats.happyness > 150 and self._deviceStats.funny > 150:
  325. self._deviceStats.playful += (float)(updateDur / 48) # Depends on naiv, funny and other stats
  326. else:
  327. self._deviceStats.playful -= (float)(updateDur / 48) * impact # Depends on naiv, funny and other stats
  328. if self._deviceStats.angry > 800:
  329. self._deviceStats.sad += (float)(updateDur / 12)
  330. elif self._deviceStats.angry > 600:
  331. self._deviceStats.sad += (float)(updateDur / 18)
  332. elif self._deviceStats.angry > 450:
  333. self._deviceStats.sad += (float)(updateDur / 24)
  334. elif self._deviceStats.angry > 250:
  335. self._deviceStats.sad += (float)(updateDur / 30)
  336. else:
  337. self._deviceStats.sad -= (float)(updateDur / 48)
  338. self._deviceStats.Save()
  339. def getJson(self):
  340. return {
  341. "DeviceStats": self._deviceStats.getJson(),
  342. "HouseStats": self._houseStats.getJson(),
  343. "MicLevel": self._micLevel.getJson(),
  344. "OutdoorStats": self._outdoorStats.getJson(),
  345. "OwnerStats": self._ownerStats.getJson(),
  346. "TalkingStats": self._talkingStats.getJson()
  347. }
  348. def __del__(self):
  349. print("Del Stat-Classes")
  350. self.Thread_Emotion.cancel()
  351. self.Thread_Homematic.cancel()
  352. self.Thread_DateTime.cancel()
  353. self.Thread_OutDoor.cancel()
  354. self.Thread_Mic.cancel()
  355. del self.Thread_Emotion
  356. del self.Thread_Homematic
  357. del self.Thread_DateTime
  358. del self.Thread_OutDoor
  359. del self.Thread_Mic
  360. del self._deviceStats
  361. del self._HouseStats
  362. del self._MicLevel
  363. del self._OutdoorStats
  364. del self._OwnerStats
  365. del self._TalkingStats