#!/usr/bin/env python # -*- coding: utf-8 -*- from Stats.DeviceStats import DeviceStats as _DeviceStats from Stats.HouseStats import HouseStats as _HouseStats from Stats.MicLevel import MicLevel as _MicLevel from Stats.OutdoorStats import OutdoorStats as _OutdoorStats from Stats.OwnerStats import OwnerStats as _OwnerStats from Stats.TalkingStats import TalkingStats as _TalkingStats from Stats.AdminStats import AdminStats as _AdminStats import MicCapture import OpenWeatherMap #from Homematic import Homematic from threading import Timer import time import datetime import configparser from lib.RepeatTimer import RepeatTimer import lib.MoonPhase as mp import random class Stats: instance = None @staticmethod def getInstance(): if Stats.instance==None: Stats.instance = Stats() return Stats.instance #deviceStats:_DeviceStats = _DeviceStats() #houseStats:_HouseStats = _HouseStats() #micLevel:_MicLevel = _MicLevel() #outdoorStats = _OutdoorStats() #ownerStats = _OwnerStats() #talkingStats = _TalkingStats() #adminStats = _AdminStats() UPDATE_EMOTION_DELAY_MINUTE = 0.2 UPDATE_HOMEMATIC_DELAY_MINUTE = 1 UPDATE_DATETIME_DELAY_MINUTE = 10 UPDATE_OUTDOOR_DELAY_MINUTE = 2.1 UPDATE_MIC_DELAY_MINUTE = 0.5 #Thread_Homematic = None #Thread_Emotion = None #Thread_DateTime = None #Thread_OutDoor = None #Thread_Mic = None #lastUpdate = 0.0 Mic = MicCapture.MicCapture() def __init__(self): print("Init Stats") self.lastUpdate = 0.0 self.Thread_Homematic = None self.Thread_Emotion = None self.Thread_DateTime = None self.Thread_OutDoor = None self.Thread_Mic = None print("- Read Config") try: config = configparser.ConfigParser() config.read('config/stats.ini') except: print("Failed to get Config") config = dict self._weather = OpenWeatherMap.OpenWeatherMap() self._deviceStats:_DeviceStats = _DeviceStats() self._houseStats:_HouseStats = _HouseStats() self._micLevel:_MicLevel = _MicLevel() self._outdoorStats = _OutdoorStats() self._ownerStats = _OwnerStats() self._talkingStats = _TalkingStats() self._adminStats = _AdminStats() self._outdoorStats.MoonPhase = mp.phase(time=datetime.datetime.now()) self._deviceStats.lastUpdate = time.time() self.__UpdateDateTime() self.Thread_DateTime = RepeatTimer(self.UPDATE_DATETIME_DELAY_MINUTE*60, self.__UpdateDateTime) self.Thread_DateTime.start() self.__UpdateOutdoor() self.Thread_OutDoor = RepeatTimer(self.UPDATE_OUTDOOR_DELAY_MINUTE*60, self.__UpdateOutdoor) self.Thread_OutDoor.start() self.Thread_Mic = RepeatTimer(self.UPDATE_MIC_DELAY_MINUTE*60, self.__UpdateMic) self.Thread_Mic.start() print("- Init Emotion") self.Thread_Emotion = RepeatTimer(self.UPDATE_EMOTION_DELAY_MINUTE*60, self.__UpdateEmotion) print("- - Start Emotion Timer") self.Thread_Emotion.start() print("- - Init Stats done") @property def HouseStats(self) -> _HouseStats: return self._houseStats @property def DeviceStats(self) -> _DeviceStats: return self._deviceStats @property def OutdoorStats(self) -> _OutdoorStats: return self._outdoorStats @property def OwnerStats(self) -> _OwnerStats: return self._ownerStats @property def TalkingStats(self) -> _TalkingStats: return self._talkingStats @property def AdminStats(self) -> _AdminStats: return self._adminStats @property def WeatherInfo(self) -> OpenWeatherMap.OpenWeatherMap: return self._weather def __UpdateMic(self): self.Mic.Update() self._micLevel.Volume_Min = self.Mic.LastResult["min"] self._micLevel.Volume_Max = self.Mic.LastResult["max"] self._micLevel.Volume_Avg = self.Mic.LastResult["avg"] #print(self._micLevel.getJson()) def __UpdateDateTime(self): self._outdoorStats.MoonPhase = mp.phase(time=datetime.datetime.now()) def __UpdateOutdoor(self): self._weather.Update() self._outdoorStats.bRaining = self._weather.CurrentLocation.Rain.PerHour>0.1 self._outdoorStats.bSnowing = self._weather.CurrentLocation.Rain.PerHour>0.1 and self.weather.CurrentLocation.Main.TempMax<1 self._outdoorStats.bWindy = self._weather.CurrentLocation.Wind.Speed>20 self._outdoorStats.Clouds = self._weather.CurrentLocation.Clouds.All self._outdoorStats.Humidity = self._weather.CurrentLocation.Main.Humidity self._outdoorStats.Pressure = self._weather.CurrentLocation.Main.Pressure self._outdoorStats.Temperature = self._weather.CurrentLocation.Main.Temperature self._outdoorStats.WindDegree = self._weather.CurrentLocation.Wind.Deg self._outdoorStats.WindSpeed = self._weather.CurrentLocation.Wind.Speed #def __UpdateHomematic(self): # print("Update Homematic") # self.homematic.updateDevices() # # Check open/closed windows # self.houseStats.bAllWindowOpen = True # self.houseStats.bAllWindowClosed = True # for ise in self.homematic.favWindowList: # if self.homematic.windowList[ise]["value"]==False: # self.houseStats.bAllWindowOpen = False # else: # self.houseStats.bAllWindowClosed = False # # Check open/closed doors # self.houseStats.bAllDoorOpen = True # self.houseStats.bAllDoorClosed = True # for ise in self.homematic.favDoorList: # if self.homematic.doorList[ise]["value"]==False: # self.houseStats.bAllDoorOpen = False # else: # self.houseStats.bAllDoorClosed = False # # Check all Lights # self.houseStats.bAllLightOn = True # self.houseStats.bAllLightOff = True # for ise in self.homematic.favLightList: # if self.homematic.lightList[ise]["value"]==False: # self.houseStats.bAllLightOn = False # else: # self.houseStats.bAllLightOff = False # # Termo # temp_min=40.0 # temp_max=0.0 # temp_avg_add=0.0 # temp_avg_count=0 # for ise in self.homematic.favThermoList: # if self.homematic.thermoList[ise]["value"] > temp_max: # temp_max = self.homematic.thermoList[ise]["value"] # if self.homematic.thermoList[ise]["value"] < temp_min: # temp_min = self.homematic.thermoList[ise]["value"] # temp_avg_add += self.homematic.thermoList[ise]["value"] # temp_avg_count += 1 # self.houseStats.temp_avg = temp_avg_add / temp_avg_count # self.houseStats.temp_coldest = temp_min # self.houseStats.temp_hottest = temp_max def __UpdateEmotion(self): print("Update Emotion") newTime = int(time.time()) updateDur = float(self._deviceStats.MAX_VALUE * ((newTime - self._deviceStats.lastUpdate) / 3600)) # Per Thausend self._deviceStats.lastUpdate = newTime #curHour = ((newTime % 86400) / 3600) curHour = datetime.datetime.now().hour moonImpact = 1.0 # Define MoonPhase Impact if self._outdoorStats.MoonPhase["phase"]==4: if self._outdoorStats.Clouds>80: if curHour>23 or curHour<6: moonImpact += random.randint(0,9)/60 else: moonImpact += random.randint(0,5)/80 else: if curHour>23 or curHour<6: moonImpact += random.randint(0,9)/120 else: moonImpact += random.randint(0,5)/180 # Calculate impact for stats calculation impact = moonImpact if time.time() - self._deviceStats.lastTimeToLoud > 600: self._deviceStats.toLoud += float(updateDur / 8) * impact if time.time() - self._deviceStats.lastTimeToQuiet > 600: self._deviceStats.toQuiet += float(updateDur / 8) * impact # Home depended if self._houseStats.Temperature.avg > 25.0 or self._houseStats.Temperature.hottest > 28.0: self._deviceStats.hot += float(updateDur / 12) * impact else: self._deviceStats.hot -= float(updateDur / 38) * impact if self._houseStats.Temperature.avg < 17.0 or self._houseStats.Temperature.coldest < 15.0: self._deviceStats.freezy += float(updateDur / 12) * impact else: self._deviceStats.freezy -= float(updateDur / 38) * impact if self._deviceStats.hot <200 and self._deviceStats.freezy < 200: self._deviceStats.temperate -= float(updateDur / 12) * impact else: self._deviceStats.temperate += float(updateDur / 48) * impact self._deviceStats.toLoud -= (float)(updateDur / 48) if self._ownerStats.bIsAtHome == True and self._ownerStats.bSleeping == False: self._deviceStats.toQuiet -= (float)(updateDur / 48) # substractive self._deviceStats.angry -= (float)(updateDur / 48) * impact # 48std to 1000 self._deviceStats.annoyed -= (float)(updateDur / 50) self._deviceStats.aroused -= (float)(updateDur / 72) * impact if self._ownerStats.bSleeping: self._deviceStats.exhausted -= (float)(updateDur / 18) else: self._deviceStats.exhausted -= (float)(updateDur / 48) self._deviceStats.humanity -= (float)(updateDur / 48) self._deviceStats.naiv -= (float)(updateDur / 48) self._deviceStats.shy -= (float)(updateDur / 500) self._deviceStats.soziality -= (float)(updateDur / 48) * impact self._deviceStats.usefull -= (float)(updateDur / 48) # Additive self._deviceStats.bored += (float)(updateDur / 50) if self._ownerStats.bSleeping: self._deviceStats.energy += (float)(updateDur / 14) * impact else: self._deviceStats.energy += (float)(updateDur / 30) * impact self._deviceStats.useless += (float)(updateDur / 168) # 168 = 1 Woche 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: self._deviceStats.exhausted += (float)(updateDur / 18) if self._deviceStats.toQuiet > 50: if self._deviceStats.toQuiet > 150: if self._deviceStats.toQuiet > 450: if self._deviceStats.toQuiet > 600: self._deviceStats.lonely+= (float)(updateDur / 5) else: self._deviceStats.lonely+=(float)(updateDur / 8) else: self._deviceStats.lonely+=(float)(updateDur / 32) else: self._deviceStats.lonely+=(float)(updateDur / 64) # Dependend if self._deviceStats.usefull > 600: self._deviceStats.happyness += (float)(updateDur / 20) * impact elif self._deviceStats.usefull > 400: self._deviceStats.happyness += (float)(updateDur / 40) * impact elif self._deviceStats.usefull > 300 and self._deviceStats.useless < 300: self._deviceStats.happyness += (float)(updateDur / 50) * impact else: self._deviceStats.happyness -= (float)(updateDur / 20) if self._deviceStats.temperate > 300: self._deviceStats.angry += (float)(updateDur / 60) * impact if self._deviceStats.freezy > 400 or self._deviceStats.hot > 400: self._deviceStats.angry += (float)(updateDur / 50) * impact if self._deviceStats.toLoud > 300 or self._deviceStats.toQuiet > 500: self._deviceStats.angry += (float)(updateDur / 30) * impact if self._ownerStats.bSleeping: self._deviceStats.sleepy -= (float)(updateDur / 15) * impact else: if self._deviceStats.toQuiet > 300: self._deviceStats.sleepy += (float)(updateDur / 24); if curHour > 21 or curHour < 8: self._deviceStats.sleepy += (float)(updateDur / 48) if self._outdoorStats.bRaining == True: if self._outdoorStats.bWindy: self._deviceStats.depressive += (float)(updateDur / 10) else: self._deviceStats.depressive += (float)(updateDur / 20) elif self._deviceStats.angry > 650: self._deviceStats.depressive += (float)(updateDur / 40) * impact elif self._deviceStats.angry > 500: self._deviceStats.depressive += (float)(updateDur / 50) * impact elif self._deviceStats.angry > 300: self._deviceStats.depressive += (float)(updateDur / 90) * impact else: self._deviceStats.depressive -= (float)(updateDur / 50) self._deviceStats.excited += (float)(updateDur / 50) if self._deviceStats.depressive > 70: if self._deviceStats.angry < 100: self._deviceStats.happyness += (float)(updateDur / 120) if self._deviceStats.compfortable > 300: self._deviceStats.happyness += (float)(updateDur / 120) else: if self._deviceStats.angry < 120: self._deviceStats.happyness += (float)(updateDur / 120) if self._deviceStats.angry < 80: self._deviceStats.happyness += (float)(updateDur / 45) if self._deviceStats.compfortable > 300: self._deviceStats.happyness += (float)(updateDur / 90) if self._deviceStats.happyness > 150: self._deviceStats.funny += (float)(updateDur / 48) # Depends on happyness (>100) and other stats if self._deviceStats.happyness > 300: self._deviceStats.funny += (float)(updateDur / 48) # Depends on happyness (>100) and other stats else: self._deviceStats.funny -= (float)(updateDur / 90) # Depends on other stats if self._deviceStats.hot < 100 and self._deviceStats.freezy < 100: self._deviceStats.compfortable += (float)(updateDur / 90) # Depends on other stats if self._deviceStats.toLoud < 200 and self._deviceStats.toQuiet < 400: self._deviceStats.compfortable += (float)(updateDur / 120) # Depends on other stats if self._deviceStats.hot > 800 or self._deviceStats.freezy > 800: self._deviceStats.compfortable -= (float)(updateDur / 20) # Depends on other stats self._deviceStats.playful -= (float)(updateDur / 20) * impact # Depends on other stats self._deviceStats.energy -= (float)(updateDur / 15) * impact elif self._deviceStats.hot > 400 or self._deviceStats.freezy > 350: self._deviceStats.compfortable -= (float)(updateDur / 80) # Depends on other stats self._deviceStats.energy -= (float)(updateDur / 30) elif self._deviceStats.hot > 200 or self._deviceStats.freezy > 100: self._deviceStats.compfortable -= (float)(updateDur / 150) # Depends on other stats if self._deviceStats.toLoud > 800 or self._deviceStats.toQuiet > 800: self._deviceStats.compfortable -= (float)(updateDur / 20) # Depends on other stats self._deviceStats.angry += (float)(updateDur / 20) * impact self._deviceStats.sleepy += (float)(updateDur / 20) self._deviceStats.lonely -= (float)(updateDur / 100) * impact self._deviceStats.happyness -= (float)(updateDur / 100) self._deviceStats.bored -= (float)(updateDur / 100) self._deviceStats.annoyed += (float)(updateDur / 100) elif self._deviceStats.toLoud > 400 or self._deviceStats.toQuiet > 80: self._deviceStats.compfortable -= (float)(updateDur / 80) # Depends on other stats self._deviceStats.angry += (float)(updateDur / 80) self._deviceStats.sleepy += (float)(updateDur / 80) * impact self._deviceStats.annoyed += (float)(updateDur / 150) * impact elif self._deviceStats.toLoud > 200 or self._deviceStats.toQuiet > 100: self._deviceStats.compfortable -= (float)(updateDur / 150) # Depends on other stats self._deviceStats.sleepy += (float)(updateDur / 100) if self._deviceStats.happyness > 650 and self._deviceStats.funny > 500: self._deviceStats.playful += (float)(updateDur / 8) # Depends on naiv, funny and other stats elif self._deviceStats.happyness > 500 and self._deviceStats.funny > 500: self._deviceStats.playful += (float)(updateDur / 12) * impact # Depends on naiv, funny and other stats elif self._deviceStats.happyness > 300 and self._deviceStats.funny > 300: self._deviceStats.playful += (float)(updateDur / 18) # Depends on naiv, funny and other stats elif self._deviceStats.happyness > 150 and self._deviceStats.funny > 150: self._deviceStats.playful += (float)(updateDur / 48) # Depends on naiv, funny and other stats else: self._deviceStats.playful -= (float)(updateDur / 48) * impact # Depends on naiv, funny and other stats if self._deviceStats.angry > 800: self._deviceStats.sad += (float)(updateDur / 12) elif self._deviceStats.angry > 600: self._deviceStats.sad += (float)(updateDur / 18) elif self._deviceStats.angry > 450: self._deviceStats.sad += (float)(updateDur / 24) elif self._deviceStats.angry > 250: self._deviceStats.sad += (float)(updateDur / 30) else: self._deviceStats.sad -= (float)(updateDur / 48) self._deviceStats.Save() def getJson(self): return { "DeviceStats": self._deviceStats.getJson(), "HouseStats": self._houseStats.getJson(), "MicLevel": self._micLevel.getJson(), "OutdoorStats": self._outdoorStats.getJson(), "OwnerStats": self._ownerStats.getJson(), "TalkingStats": self._talkingStats.getJson() } def __del__(self): print("Del Stat-Classes") self.Thread_Emotion.cancel() self.Thread_Homematic.cancel() self.Thread_DateTime.cancel() self.Thread_OutDoor.cancel() self.Thread_Mic.cancel() del self.Thread_Emotion del self.Thread_Homematic del self.Thread_DateTime del self.Thread_OutDoor del self.Thread_Mic del self._deviceStats del self._HouseStats del self._MicLevel del self._OutdoorStats del self._OwnerStats del self._TalkingStats