def after_handle(self): cost = datetime.datetime.now().timestamp() - self.start_handle_time app_log.info("{} {} {} ({}) {}ms".format(self.request.method.upper(), self.status_code, self.request.path, self.request.client_ip, round(cost * 1000, 1)))
def restartNotifyServer(): # disconnectAllPVs() # clearGlobalDicts() # getListOfPVNames() # initAlarmDict() print("Notify server restarted...") app_log.info("Notify server restarted...")
def notifyWhatsApp(timestamp, mobile, userNotifyDict): # This function must return True as an acknowledgedment to the notification # server that the notification method executed successfully app_log.info(mobile) # app_log.info(str(userNotifyDict)) return False
def start_server(self, host, port, router): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind((host, port)) sock.listen() sock.setblocking(False) sel.register(sock, selectors.EVENT_READ, self._on_new_connect) self.router = router app_log.info("Start listen on {}:{}".format(host, port))
def startNotifyServer(): # initPreSuffix() # getListOfPVNames() # initAlarmDict() # debug prints # print(alarmDict) print("Notify server running...") app_log.info("Notify server running...")
def notifyEmail(timestamp, email, userNotifyDict): # This function must return True as an acknowledgedment to the notification # server that the notification method executed successfully timestamp = datetime.fromisoformat(timestamp) app_log.info("###-EMAIL NOTIFY-###") app_log.info(timestamp.strftime('%a, %d %b %Y at %H:%M:%S UTC')) app_log.info(email) # app_log.info(str(userNotifyDict)) try: msg = MIMEMultipart() msg['From'] = SMTP_SENDER msg['To'] = email # Time zone localisation if (localtz): str_time = timestamp.astimezone(localtz).strftime( '%a, %d %b %Y at %H:%M:%S') else: str_time = timestamp.strftime( '%a, %d %b %Y at %H:%M:%S') + " (UTC)" # Time zone localisation msg['Subject'] = "Alarm Notification: " + str_time email_body = composeEmailBody(userNotifyDict) msg.attach(MIMEText(email_body, 'html', 'utf-8')) try: with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: if (AH_DEBUG): server.set_debuglevel(2) # identify ourselves, prompting server for supported features server.ehlo() # If we can encrypt this session, do it if server.has_extn('STARTTLS'): server.starttls() server.ehlo() # re-identify ourselves over TLS connection if (smtpAuth): server.login(SMTP_USER, SMTP_PASS) server.sendmail(msg['From'], msg['To'], msg.as_string()) server.quit() print("Successfully sent email to", email) app_log.info("Successfully sent email to " + email) return True except Exception as e: app_log.error("Exception raised: " + str(e)) app_log.error("Exception type: " + str(type(e))) app_log.error("Exception args: " + str(e.args)) print("Failed to send email to", email, ". Verify SMTP settings.") app_log.error("Failed to send email to " + email + ". Verify SMTP settings.") return False except Exception as e: app_log.error("Exception raised: " + str(e)) app_log.error("Exception type: " + str(type(e))) app_log.error("Exception args: " + str(e.args)) print("Failed to send email to", email, ". Verify SMTP settings.") app_log.error("Failed to send email to " + email + ". Verify SMTP settings.") return False
def _on_response(self, request, sock, mask): sel.unregister(sock) try: data = sock.recv(1024) except Exception as e: request["fut"].throw(type(e), e.args[1], e.__traceback__) else: request["fut"].send(data) finally: sock.close() cost = time.time() - request["start_time"] app_log.info("HTTP {} http://{}:{}{} {}ms".format( request["method"], request["host"], request["port"], request["path"], round(cost * 1000, 1), ))
def initAlarmDatabase(): ALARM_DATABASE = os.getenv('ALARM_DATABASE', 'localhost') ALARM_DATABASE_REPLICA_SET_NAME = os.getenv( 'ALARM_DATABASE_REPLICA_SET_NAME', 'devrs') MONGO_INITDB_ALARM_DATABASE = os.getenv('MONGO_INITDB_ALARM_DATABASE', 'demoAlarmDatabase') try: MONGO_ROOT_USERNAME = os.environ['MONGO_ROOT_USERNAME'] MONGO_ROOT_PASSWORD = os.environ['MONGO_ROOT_PASSWORD'] MONGO_ROOT_USERNAME = urllib.parse.quote_plus(MONGO_ROOT_USERNAME) MONGO_ROOT_PASSWORD = urllib.parse.quote_plus(MONGO_ROOT_PASSWORD) mongoAuth = True except: mongoAuth = False if (mongoAuth): client = MongoClient( 'mongodb://%s:%s@%s' % (MONGO_ROOT_USERNAME, MONGO_ROOT_PASSWORD, ALARM_DATABASE), replicaSet=ALARM_DATABASE_REPLICA_SET_NAME, readPreference='secondaryPreferred') else: client = MongoClient('mongodb://%s' % (ALARM_DATABASE), replicaSet=ALARM_DATABASE_REPLICA_SET_NAME, readPreference='secondaryPreferred') global alarmDB alarmDB = client[MONGO_INITDB_ALARM_DATABASE] while (len(alarmDB.list_collection_names()) != 5): app_log.info( 'Waiting for Pymongo to connect to all collections in alarm database' ) sleep(1.0) app_log.info('Pymongo connected to all collections in alarm database') app_log.info(str(alarmDB.list_collection_names())) while (len(list(alarmDB['glob'].find({}))) == 0): app_log.info('Alarm database ' + MONGO_INITDB_ALARM_DATABASE + ' still being instantiated') sleep(1.0) app_log.info('Alarm database ' + MONGO_INITDB_ALARM_DATABASE + ' instantiated')
def notifyValid(notifySetup): now = datetime.now(utc) if (notifySetup["notify"]): app_log.info("Must notify") if (notifySetup["allDay"]): app_log.info("All day") else: app_log.info("Time restricted") formatTime = "%H:%M" fromTime = datetime.fromisoformat( notifySetup["fromTime"]).astimezone(utc).strftime(formatTime) toTime = datetime.fromisoformat( notifySetup["toTime"]).astimezone(utc).strftime(formatTime) nowTime = now.strftime(formatTime) app_log.info('fromTime UTC ' + str(fromTime)) app_log.info('toTime UTC ' + str(toTime)) app_log.info('nowTime UTC ' + str(nowTime)) if (time_is_between(nowTime, fromTime, toTime)): app_log.info("Current time between fromTime and toTime") else: app_log.info("Current time NOT between fromTime and toTime") app_log.info("!!Don't notify!!") return False if (notifySetup["weekly"]): formatTime = "%A" dayToday = now.strftime(formatTime) app_log.info("Notify weekly") daysToNotify = [] for key, value in notifySetup["days"].items(): if (value): daysToNotify.append(key) app_log.info("Notify on " + " ".join(daysToNotify)) app_log.info("Today is " + dayToday) if (dayToday in daysToNotify): app_log.info("Notify today") else: app_log.info("Don't notify today") app_log.info("!!Don't notify!!") return False else: formatTime = "%d %B %Y" fromDate = datetime.fromisoformat( notifySetup["fromDate"]).astimezone(utc) toDate = datetime.fromisoformat( notifySetup["toDate"]).astimezone(utc) app_log.info("Notify date range") app_log.info('fromDate ' + fromDate.strftime(formatTime)) app_log.info('toDate ' + toDate.strftime(formatTime)) app_log.info("Today" + now.strftime(formatTime)) if (date_is_between(now, fromDate, toDate)): app_log.info("Notify today") else: app_log.info("Don't notify today") app_log.info("!!Don't notify!!") return False return True else: app_log.info("!!Don't notify!!") return False
def notify(notifyBuffer): for user in dbGetCollection("users").find(): if (user["adminDB_en"] and user["isAHUser"]): app_log.info("User " + user["name"] + " is a valid alarm user") notifyEmailDict = {} notifySMSDict = {} notifyWhatsAppDict = {} notifySignalDict = {} name = user["name"] email = user["email"] mobile = user["mobile"] for notifyPV in user["notifyPVs"]: for area in notifyBuffer: for pvname in notifyBuffer[area]: app_log.info('##-START NOTIFY DEBUG-##') app_log.info(name) app_log.info(area) app_log.info(pvname) message = notifyBuffer[area][pvname] minorAlarm = False majorAlarm = False invalidAlarm = False disconnAlarm = False for entry in message: minorAlarm = minorAlarm or ("MINOR_ALARM" in entry["entry"]) majorAlarm = majorAlarm or ("MAJOR_ALARM" in entry["entry"]) invalidAlarm = invalidAlarm or ("INVALID_ALARM" in entry["entry"]) disconnAlarm = disconnAlarm or ("DISCONNECTED" in entry["entry"]) app_log.info("minorAlarm " + str(minorAlarm)) app_log.info("majorAlarm " + str(majorAlarm)) app_log.info("invalidAlarm " + str(invalidAlarm)) app_log.info("disconnAlarm " + str(disconnAlarm)) if (js_regex.compile( notifyPV["regEx"]).search(pvname)): # Passes regEx check app_log.info("Pass regEx " + notifyPV["regEx"]) notify = False notifyAlarmType = False notifyOnEmail = False notifyOnSMS = False notifyOnWhatsApp = False notifyOnSignal = False if (user["global"]): app_log.info("Using global profile") notify = notifyValid(user["globalSetup"]) notifyOnEmail = user["globalSetup"]["email"] notifyOnSMS = user["globalSetup"]["sms"] notifyOnWhatsApp = user["globalSetup"][ "whatsapp"] # Backwards compatible notifyOnSignal = user["globalSetup"][ "signal"] if ( "signal" in user["globalSetup"]) else False notifyMinorAlarm = user["globalSetup"][ "alarmMinor"] if ( "alarmMinor" in user["globalSetup"]) else True notifyMajorAlarm = user["globalSetup"][ "alarmMajor"] if ( "alarmMajor" in user["globalSetup"]) else True notifyInvalidAlarm = user["globalSetup"][ "alarmInvalid"] if ( "alarmInvalid" in user["globalSetup"]) else True notifyDisconnAlarm = user["globalSetup"][ "alarmDisconn"] if ( "alarmDisconn" in user["globalSetup"]) else True # else: app_log.info("Using unique profile") notify = notifyValid(notifyPV["notifySetup"]) notifyOnEmail = notifyPV["notifySetup"][ "email"] notifyOnSMS = notifyPV["notifySetup"]["sms"] notifyOnWhatsApp = notifyPV["notifySetup"][ "whatsapp"] # Backwards compatible notifyOnSignal = notifyPV["notifySetup"][ "signal"] if ( "signal" in notifyPV["notifySetup"]) else False notifyMinorAlarm = notifyPV["notifySetup"][ "alarmMinor"] if ( "alarmMinor" in notifyPV["notifySetup"]) else True notifyMajorAlarm = notifyPV["notifySetup"][ "alarmMajor"] if ( "alarmMajor" in notifyPV["notifySetup"]) else True notifyInvalidAlarm = notifyPV["notifySetup"][ "alarmInvalid"] if ( "alarmInvalid" in notifyPV["notifySetup"]) else True notifyDisconnAlarm = notifyPV["notifySetup"][ "alarmDisconn"] if ( "alarmDisconn" in notifyPV["notifySetup"]) else True # app_log.info("notifyMinorAlarm " + str(notifyMinorAlarm)) app_log.info("notifyMajorAlarm " + str(notifyMajorAlarm)) app_log.info("notifyInvalidAlarm " + str(notifyInvalidAlarm)) app_log.info("notifyDisconnAlarm " + str(notifyDisconnAlarm)) if (minorAlarm and notifyMinorAlarm): notifyAlarmType = True elif (majorAlarm and notifyMajorAlarm): notifyAlarmType = True elif (invalidAlarm and notifyInvalidAlarm): notifyAlarmType = True elif (disconnAlarm and notifyDisconnAlarm): notifyAlarmType = True if (notify and notifyAlarmType): # Passes notifyValid check app_log.info( "Pass notifyValid and alarm type checks") if (notifyOnEmail): # Notify via email app_log.info("Notify via email") if (area not in notifyEmailDict): notifyEmailDict[area] = {} notifyEmailDict[area][pvname] = message if (notifyOnSMS): # Notify via sms app_log.info("Notify via sms") if (area not in notifySMSDict): notifySMSDict[area] = {} notifySMSDict[area][pvname] = message if (notifyOnWhatsApp): # Notify via whatsapp app_log.info("Notify via whatsapp") if (area not in notifyWhatsAppDict): notifyWhatsAppDict[area] = {} notifyWhatsAppDict[area][pvname] = message if (notifyOnSignal): # Notify via signal app_log.info("Notify via Signal") if (area not in notifySignalDict): notifySignalDict[area] = {} notifySignalDict[area][pvname] = message else: app_log.info( "Fail notifyValid or alarm type check") else: app_log.info("Fail regEx " + notifyPV["regEx"]) app_log.info('###-END NOTIFY DEBUG-###') timestamp = datetime.now(utc).isoformat() if (notifyEmailDict): if (notifyEmail(timestamp, email, notifyEmailDict)): timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join([name, "notified on email"]) } else: timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join(["FAILED to notify", name, "on email!"]) } for area in notifyEmailDict: for pvname in notifyEmailDict[area]: dbUpdateHistory(area, entry, pvname) if (notifySMSDict): if (notifySMS(timestamp, mobile, notifySMSDict)): timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join([name, "notified on SMS"]) } else: timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join(["FAILED to notify", name, "on SMS!"]) } for area in notifySMSDict: for pvname in notifySMSDict[area]: dbUpdateHistory(area, entry, pvname) if (notifyWhatsAppDict): if (notifyWhatsApp(timestamp, mobile, notifyWhatsAppDict)): timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join([name, "notified on WhatsApp"]) } else: timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join(["FAILED to notify", name, "on WhatsApp!"]) } for area in notifyWhatsAppDict: for pvname in notifyWhatsAppDict[area]: dbUpdateHistory(area, entry, pvname) if (notifySignalDict): notifySignal(timestamp, mobile, name, notifySignalDict) else: app_log.info("User " + user["name"] + " is NOT a valid alarm user")
from notificationMethods.notifyEmail import notifyEmail from notificationMethods.notifySMS import notifySMS from notificationMethods.notifyWhatsApp import notifyWhatsApp from notificationMethods.notifySignal import notifySignal from log import app_log try: AH_DEBUG = bool(os.environ['AH_DEBUG']) except: AH_DEBUG = False try: timezone(os.environ['AH_TZ']) print('Local timezone for alarm handler set to', os.environ['AH_TZ']) app_log.info('Local timezone for alarm handler set to ' + os.environ['AH_TZ']) except: print('[Warning]', 'Local timezone for alarm handler not set!') app_log.warning('Local timezone for alarm handler not set!') pvNameList = [] alarmDict = {} def initPreSuffix(): # Prefix and suffix for alarmIOC pvs global alarmIOCPVPrefix global alarmIOCPVSuffix doc = dbFindOne("config") alarmIOCPVPrefix = doc["alarmIOCPVPrefix"] alarmIOCPVSuffix = doc["alarmIOCPVSuffix"]
def worker(): while True: item = q.get() timestamp = item['timestamp'] mobile = item['mobile'] name = item['name'] userNotifyDict = item['userNotifyDict'] timestamp = datetime.fromisoformat(timestamp) app_log.info("###-SIGNAL NOTIFY-###") app_log.info(timestamp.strftime('%a, %d %b %Y at %H:%M:%S UTC')) app_log.info(mobile) # app_log.info(str(userNotifyDict)) if (SIGNAL_CLI_REST_ENDPOINT != ''): try: # Time zone localisation if (localtz): str_time = timestamp.astimezone(localtz).strftime( '%a, %d %b %Y at %H:%M:%S') else: str_time = timestamp.strftime( '%a, %d %b %Y at %H:%M:%S') + " (UTC)" # Time zone localisation message = "You have new alarm notifications" message = message.replace(" ", "\ ") message.encode('unicode_escape') html = composeEmailBody(userNotifyDict, str_time) imgkit.from_string(html, 'alarms.jpg') with open("alarms.jpg", "rb") as image_file: encoded_image = base64.b64encode(image_file.read()) data = { "text": message, "receivers": [mobile], "group": False, "groupId": "", "attachments": [{ "url": "", "filename": "alarms.jpg", "content": encoded_image.decode() }] } try: r = requests.post(SIGNAL_CLI_REST_ENDPOINT, json=data) app_log.info("Signal rest API response: [" + str(r.status_code) + "] " + r.reason) if (r.ok): timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join([name, "notified on Signal"]) } except Exception as e: app_log.error("Exception raised: " + str(e)) app_log.error("Exception type: " + str(type(e))) app_log.error("Exception args: " + str(e.args)) print("Failed to send Signal message to", mobile, ". Verify Signal settings.") app_log.error("Failed to send Signal message to " + mobile + ". Verify Signal settings.") timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join(["FAILED to notify", name, "on Signal!"]) } except Exception as e: app_log.error("Exception raised: " + str(e)) app_log.error("Exception type: " + str(type(e))) app_log.error("Exception args: " + str(e.args)) print("Failed to send Signal message to", mobile, ". Verify Signal settings.") app_log.error("Failed to send Signal message to " + mobile + ". Verify Signal settings.") timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join(["FAILED to notify", name, "on Signal!"]) } else: print("Failed to send Signal message to", mobile, ". Verify Signal settings.") app_log.error("Failed to send Signal message to " + mobile + ". Verify Signal settings.") timestamp = datetime.now(utc).isoformat() entry = { "timestamp": timestamp, "entry": " ".join(["FAILED to notify", name, "on Signal!"]) } for area in userNotifyDict: for pvname in userNotifyDict[area]: dbUpdateHistory(area, entry, pvname) q.task_done()
try: SIGNAL_CLI_REST_API_PORT = os.environ['SIGNAL_CLI_REST_API_PORT'] except: print("SIGNAL_CLI_REST_API_PORT not defined, defaulting to port 8000") app_log.warning( "SIGNAL_CLI_REST_API_PORT not defined, defaulting to port 8000") SIGNAL_CLI_REST_API_PORT = str(8000) try: SIGNAL_ACC_NUMBER = os.environ['SIGNAL_ACC_NUMBER'] SIGNAL_ACC_NUMBER = SIGNAL_ACC_NUMBER.replace('+', '%2B') SIGNAL_CLI_REST_ENDPOINT = 'http://127.0.0.1:' + \ SIGNAL_CLI_REST_API_PORT+'/messages/'+SIGNAL_ACC_NUMBER print(SIGNAL_CLI_REST_ENDPOINT) app_log.info(SIGNAL_CLI_REST_ENDPOINT) except: print("Signal account number not configured!") print("Signal notifications will not be sent") app_log.warning("Signal account number not configured!") app_log.warning("Signal notifications will not be sent") SIGNAL_CLI_REST_ENDPOINT = '' q = queue.Queue() def composeEmailBody(userNotifyDict, sent_time): body = "" for area in userNotifyDict: if ("=" in area): displayArea = area.replace("=", " > ")
AH_DEBUG = bool(os.environ['AH_DEBUG']) except: AH_DEBUG = False try: AH_TZ = os.environ['AH_TZ'] localtz = timezone(AH_TZ) except: localtz = None try: SMTP_HOST = os.environ['SMTP_HOST'] SMTP_PORT = os.environ['SMTP_PORT'] SMTP_SENDER = os.environ['SMTP_SENDER'] print("Email SMTP settings configured") app_log.info("Email SMTP settings configured") except: SMTP_HOST = '' SMTP_PORT = '' SMTP_SENDER = '' print("Email SMTP settings not configured!") print("Email notifications will not be sent") app_log.warning("Email SMTP settings not configured!") app_log.warning("Email notifications will not be sent") try: SMTP_USER = os.environ['SMTP_USER'] SMTP_PASS = os.environ['SMTP_PASS'] smtpAuth = True print("SMTP user/password set, login required") app_log.info("SMTP user/password set, login required")