import Queue import os import sys from time import gmtime, strftime, sleep import threading import datetime import pymongo import smtplib from email.mime.text import MIMEText DEBUG = False BACKGROUND = True PID_FILE = "/opt/logs/FridgeAlarm.pid" LOG_FILE = "/opt/logs/FridgeAlarm.log" MONGO_HOST = "127.0.0.1" MONGO_DATABASE = "iot" MONGO_COLLECTION = "iot" INTERVAL = 30 * 60 PERIOD = 120 THRESHOLD = 0.0 EMAIL_SENDER = 'freezer@hottis.de' EMAIL_RECP = 'familie@hottis.de' 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() emailMsg = MIMEText("Temperature in freezer to high: %s %s" % (msg['timestamp'], msg['temperature'])) emailMsg['Subject'] = 'Freezer Alarm' emailMsg['From'] = EMAIL_SENDER emailMsg['To'] = EMAIL_RECP s = smtplib.SMTP('localhost') s.sendmail(EMAIL_SENDER, [EMAIL_RECP], emailMsg.as_string()) s.quit() 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 ...")