2015-07-11 11:11:13 +02:00
|
|
|
import Queue
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
from time import gmtime, strftime, sleep
|
|
|
|
import threading
|
2015-07-10 21:51:33 +02:00
|
|
|
import datetime
|
2015-07-11 11:11:13 +02:00
|
|
|
import pymongo
|
2015-07-23 15:03:48 +02:00
|
|
|
import smtplib
|
|
|
|
from email.mime.text import MIMEText
|
|
|
|
|
2015-07-11 11:11:13 +02:00
|
|
|
|
|
|
|
|
2016-07-09 22:48:06 +02:00
|
|
|
DEBUG = False
|
|
|
|
BACKGROUND = True
|
|
|
|
PID_FILE = "/opt/logs/FridgeAlarm.pid"
|
|
|
|
LOG_FILE = "/opt/logs/FridgeAlarm.log"
|
|
|
|
MONGO_HOST = "127.0.0.1"
|
2015-07-11 11:11:13 +02:00
|
|
|
MONGO_DATABASE = "iot"
|
|
|
|
MONGO_COLLECTION = "iot"
|
|
|
|
INTERVAL = 30 * 60
|
2015-07-23 15:08:54 +02:00
|
|
|
PERIOD = 120
|
2015-07-11 11:11:13 +02:00
|
|
|
THRESHOLD = 0.0
|
2015-07-23 15:08:54 +02:00
|
|
|
EMAIL_SENDER = 'freezer@hottis.de'
|
|
|
|
EMAIL_RECP = 'familie@hottis.de'
|
2015-07-11 11:11:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Logger(object):
|
|
|
|
debugFlag = False
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def log(cls, data):
|
|
|
|
t = strftime("%d %b %Y %H:%M:%S", gmtime())
|
|
|
|
with open(cls.logfile, 'a') as f:
|
|
|
|
f.write("%s %s\n" % (t, data))
|
|
|
|
if cls.debugFlag:
|
|
|
|
print data
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def debug(cls, data):
|
|
|
|
if cls.debugFlag:
|
|
|
|
cls.log(data)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def debugEnable(cls):
|
|
|
|
cls.debugFlag = True
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def debugDisable(cls):
|
|
|
|
cls.debugFlag = False
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def openlog(cls, logfile):
|
|
|
|
cls.logfile = logfile
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TemperatureChecker(threading.Thread):
|
|
|
|
def __init__(self, queue, dbhost, database, collection, period, interval, threshold):
|
|
|
|
threading.Thread.__init__(self)
|
|
|
|
self.queue = queue
|
|
|
|
self.dbhost = dbhost
|
|
|
|
self.database = database
|
|
|
|
self.collection = collection
|
|
|
|
self.mongoClient = pymongo.MongoClient(self.dbhost)
|
|
|
|
self.db = self.mongoClient[self.database]
|
|
|
|
self.coll = self.db[self.collection]
|
|
|
|
self.period = period
|
|
|
|
self.interval = interval
|
|
|
|
self.threshold = threshold
|
|
|
|
self.setDaemon(True)
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
while True:
|
|
|
|
try:
|
|
|
|
now1 = datetime.datetime.now()
|
|
|
|
now = now1.replace(now1.year, now1.month, now1.day, now1.hour, now1.minute, now1.second, 0)
|
|
|
|
midnight = now.replace(now.year, now.month, now.day, 0,0,0,0)
|
|
|
|
seconds = (now - midnight).seconds
|
|
|
|
intervalBegin = seconds - self.interval
|
|
|
|
|
|
|
|
if intervalBegin > 0:
|
|
|
|
pipeline = [
|
|
|
|
{'$match': {'metadata.device': 'ModbusHub',
|
|
|
|
'metadata.day': midnight,
|
|
|
|
'metadata.seconds': {'$gt': intervalBegin, '$lt': seconds}
|
|
|
|
}},
|
|
|
|
{'$sort': {'seconds': 1}},
|
|
|
|
# {'$project': {'_id': 0, 'ts': '$metadata.timestamp', 't': '$data.t2'}}
|
|
|
|
{'$group': {'_id': 0,
|
|
|
|
'avgTemp': {'$avg': '$data.t2'}}}
|
|
|
|
]
|
|
|
|
cursor = self.coll.aggregate(pipeline)
|
|
|
|
result = cursor.next()
|
|
|
|
result2 = {'temperature': result['avgTemp'], 'timestamp': now1}
|
|
|
|
Logger.log(result2)
|
|
|
|
|
|
|
|
if result2['temperature'] > self.threshold:
|
|
|
|
Logger.log("Queueing an alarm")
|
|
|
|
self.queue.put_nowait(result2)
|
|
|
|
|
|
|
|
except pymongo.errors.ServerSelectionTimeoutError, e:
|
|
|
|
Logger.log("Exception %s in TemperatureChecker, run" % str(e))
|
|
|
|
except TypeError, e:
|
|
|
|
Logger.log("Exception %s in TemperatureChecker, run" % str(e))
|
|
|
|
except Exception, e:
|
|
|
|
Logger.log("Unexcepted exception %s in TemperatureChecker: %s" % (e.__class__.__name__, str(e)))
|
|
|
|
finally:
|
|
|
|
sleep(self.period)
|
|
|
|
|
|
|
|
|
|
|
|
class AlarmSender(threading.Thread):
|
|
|
|
def __init__(self, queue):
|
|
|
|
threading.Thread.__init__(self)
|
|
|
|
self.queue = queue
|
|
|
|
self.setDaemon(True)
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
while True:
|
|
|
|
try:
|
|
|
|
msg = self.queue.get()
|
2015-07-23 15:03:48 +02:00
|
|
|
emailMsg = MIMEText("Temperature in freezer to high: %s %s" % (msg['timestamp'], msg['temperature']))
|
|
|
|
emailMsg['Subject'] = 'Freezer Alarm'
|
2015-07-23 15:08:54 +02:00
|
|
|
emailMsg['From'] = EMAIL_SENDER
|
|
|
|
emailMsg['To'] = EMAIL_RECP
|
2015-07-23 15:03:48 +02:00
|
|
|
s = smtplib.SMTP('localhost')
|
2015-07-23 15:08:54 +02:00
|
|
|
s.sendmail(EMAIL_SENDER, [EMAIL_RECP], emailMsg.as_string())
|
2015-07-23 15:03:48 +02:00
|
|
|
s.quit()
|
|
|
|
|
2015-07-11 11:11:13 +02:00
|
|
|
Logger.debug("AlarmSender sends message for: %s" % msg)
|
|
|
|
except TypeError, e:
|
|
|
|
Logger.log("Exception %s in AlarmSender, run" % str(e))
|
|
|
|
except Exception, e:
|
|
|
|
Logger.log("Unexcepted exception %s in AlarmSender: %s" % (e.__class__.__name__, str(e)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if BACKGROUND:
|
|
|
|
pid = os.fork()
|
|
|
|
else:
|
|
|
|
pid = 0
|
|
|
|
|
|
|
|
if pid:
|
|
|
|
pidFile = file(PID_FILE , mode='w')
|
|
|
|
pidFile.write("%i\n" % pid)
|
|
|
|
pidFile.close()
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
Logger.openlog(LOG_FILE)
|
|
|
|
|
|
|
|
if DEBUG:
|
|
|
|
Logger.debugEnable()
|
|
|
|
|
|
|
|
Logger.log("FridgeAlarm starting")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
alarmQueue = Queue.Queue()
|
|
|
|
Logger.log("alarm queue created ...")
|
|
|
|
|
|
|
|
temperatureChecker = TemperatureChecker(alarmQueue, MONGO_HOST, MONGO_DATABASE, MONGO_COLLECTION,
|
|
|
|
PERIOD, INTERVAL, THRESHOLD)
|
|
|
|
temperatureChecker.start()
|
|
|
|
Logger.log("TemperatureChecker started ...")
|
|
|
|
|
|
|
|
alarmSender = AlarmSender(alarmQueue)
|
|
|
|
alarmSender.start()
|
|
|
|
Logger.log("AlarmSender started ...")
|
|
|
|
|
|
|
|
|
|
|
|
Logger.log("FridgeAlarm running")
|
|
|
|
|
|
|
|
while (True):
|
|
|
|
sleep(10)
|
|
|
|
except Exception, e:
|
|
|
|
Logger.log("FridgeAlarm dying from %s, %s" % (str(e), e.msg))
|
|
|
|
finally:
|
|
|
|
Logger.log("FridgeAlarm terminating ...")
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-07-10 21:51:33 +02:00
|
|
|
|
|
|
|
|
|
|
|
|