Beispiel #1
0
	def _sensorAlertHandler(self, incomingMessage):

		logging.info("[%s]: Received sensor alert." % self.fileName)

		# extract sensor alert values
		sensorAlert = SensorAlert()
		sensorAlert.timeReceived = int(time.time())
		try:
			if not self._checkMsgServerTime(
				incomingMessage["serverTime"],
				incomingMessage["message"]):

				logging.error("[%s]: Received serverTime invalid."
					% self.fileName)
				return False
			if not self._checkMsgAlertLevels(
				incomingMessage["payload"]["alertLevels"],
				incomingMessage["message"]):

				logging.error("[%s]: Received alertLevels invalid."
					% self.fileName)
				return False
			if not self._checkMsgDescription(
				incomingMessage["payload"]["description"],
				incomingMessage["message"]):

				logging.error("[%s]: Received description invalid."
					% self.fileName)
				return False
			if not self._checkMsgRulesActivated(
				incomingMessage["payload"]["rulesActivated"],
				incomingMessage["message"]):

				logging.error("[%s]: Received rulesActivated invalid."
					% self.fileName)
				return False
			if not self._checkMsgSensorId(
				incomingMessage["payload"]["sensorId"],
				incomingMessage["message"]):

				logging.error("[%s]: Received sensorId invalid."
					% self.fileName)
				return False
			if not self._checkMsgState(
				incomingMessage["payload"]["state"],
				incomingMessage["message"]):

				logging.error("[%s]: Received state invalid."
					% self.fileName)
				return False
			if not self._checkMsgHasOptionalData(
				incomingMessage["payload"]["hasOptionalData"],
				incomingMessage["message"]):

				logging.error("[%s]: Received hasOptionalData invalid."
					% self.fileName)
				return False
			if incomingMessage["payload"]["hasOptionalData"]:
				if not self._checkMsgOptionalData(
					incomingMessage["payload"]["optionalData"],
					incomingMessage["message"]):

					logging.error("[%s]: Received optionalData invalid."
						% self.fileName)
					return False
			if not self._checkMsgSensorDataType(
				incomingMessage["payload"]["dataType"],
				incomingMessage["message"]):

				logging.error("[%s]: Received dataType invalid."
					% self.fileName)
				return False
			if incomingMessage["payload"]["dataType"] != SensorDataType.NONE:
				if not self._checkMsgSensorData(
					incomingMessage["payload"]["data"],
					incomingMessage["payload"]["dataType"],
					incomingMessage["message"]):

					logging.error("[%s]: Received data invalid."
						% self.fileName)
					return False
			if not self._checkMsgHasLatestData(
				incomingMessage["payload"]["hasLatestData"],
				incomingMessage["message"]):

				logging.error("[%s]: Received hasLatestData invalid."
					% self.fileName)
				return False
			if not self._checkMsgChangeState(
				incomingMessage["payload"]["changeState"],
				incomingMessage["message"]):

				logging.error("[%s]: Received changeState invalid."
					% self.fileName)
				return False

			sensorAlert.sensorId = incomingMessage["payload"]["sensorId"]
			sensorAlert.alertLevels = incomingMessage["payload"]["alertLevels"]
			sensorAlert.state = incomingMessage["payload"]["state"]
			sensorAlert.description = incomingMessage["payload"]["description"]
			sensorAlert.changeState = incomingMessage["payload"]["changeState"]
			sensorAlert.rulesActivated = \
				incomingMessage["payload"]["rulesActivated"]

			# parse received data (if data transfer is activated)
			sensorAlert.optionalData = None
			sensorAlert.hasOptionalData = \
				incomingMessage["payload"]["hasOptionalData"]
			if sensorAlert.hasOptionalData:
				sensorAlert.optionalData = incomingMessage[
					"payload"]["optionalData"]

			sensorAlert.changeState = incomingMessage["payload"]["changeState"]
			sensorAlert.hasLatestData = \
				incomingMessage["payload"]["hasLatestData"]

			sensorAlert.dataType = incomingMessage["payload"]["dataType"]
			sensorAlert.sensorData = None
			if sensorAlert.dataType != SensorDataType.NONE:
				sensorAlert.sensorData = incomingMessage["payload"]["data"]

		except Exception as e:
			logging.exception("[%s]: Received sensor alert " % self.fileName
				+ "invalid.")

			# send error message back
			try:
				utcTimestamp = int(time.time())
				message = {"clientTime": utcTimestamp,
					"message": incomingMessage["message"],
					"error": "received sensor alert invalid"}
				self.client.send(json.dumps(message))
			except Exception as e:
				pass

			return False

		# sending sensor alert response
		logging.debug("[%s]: Sending sensor alert " % self.fileName
			+ "response message.")
		try:
			payload = {"type": "response", "result": "ok"}
			utcTimestamp = int(time.time())
			message = {"clientTime": utcTimestamp,
				"message": "sensoralert", "payload": payload}
			self.client.send(json.dumps(message))

		except Exception as e:
			logging.exception("[%s]: Sending sensor alert " % self.fileName
				+ "response failed.")

			return False

		# trigger all alerts that have the same alert level
		atLeastOnceTriggered = False
		for alert in self.alerts:
			for alertLevel in sensorAlert.alertLevels:
				if alertLevel in alert.alertLevels:
					atLeastOnceTriggered = True
					# trigger alert in an own thread to not block this one
					alertTriggerProcess = AsynchronousAlertExecuter(alert)
					alertTriggerProcess.sensorAlert = sensorAlert
					# set thread to daemon
					# => threads terminates when main thread terminates
					alertTriggerProcess.daemon = True
					alertTriggerProcess.triggerAlert = True
					alertTriggerProcess.start()
					break

		# Write to log file if no alert was triggered for received sensorAlert.
		if not atLeastOnceTriggered:
			alertLevelsStr = ", ".join(map(str, sensorAlert.alertLevels))
			logging.info("[%s]: No alert triggered for alertLevels: %s."
				% (self.fileName, alertLevelsStr))

		return True
Beispiel #2
0
    def execute(self):

        # time on which the last full sensor states were sent
        # to the server
        lastFullStateSent = 0

        # Get reference to server communication object.
        while self.connection is None:
            time.sleep(0.5)
            self.connection = self.globalData.serverComm

        self._isInitialized = True

        while True:

            # check if the client is connected to the server
            # => wait and continue loop until client is connected
            if not self.connection.isConnected():
                time.sleep(0.5)
                continue

            # poll all sensors and check their states
            for sensor in self.sensors:

                oldState = sensor.getState()
                sensor.updateState()
                currentState = sensor.getState()

                # Check if a sensor alert is forced to send to the server.
                # => update already known state and continue
                sensorAlert = sensor.forceSendAlert()
                if sensorAlert:
                    oldState = currentState

                    asyncSenderProcess = AsynchronousSender(
                        self.connection, self.globalData)
                    # set thread to daemon
                    # => threads terminates when main thread terminates
                    asyncSenderProcess.daemon = True
                    asyncSenderProcess.sendSensorAlert = True
                    asyncSenderProcess.sendSensorAlertSensorAlert = sensorAlert
                    asyncSenderProcess.start()

                    continue

                # check if the current state is the same
                # than the already known state => continue
                elif oldState == currentState:
                    continue

                # check if the current state is an alert triggering state
                elif currentState == sensor.triggerState:

                    # check if the sensor triggers a sensor alert
                    # => send sensor alert to server
                    if sensor.triggerAlert:

                        logging.info("[%s]: Sensor alert " % self.fileName +
                                     "triggered by '%s'." % sensor.description)

                        # Create sensor alert object to send to the server.
                        sensorAlert = SensorAlert()
                        sensorAlert.clientSensorId = sensor.id
                        sensorAlert.state = 1
                        sensorAlert.hasOptionalData = sensor.hasOptionalData
                        sensorAlert.optionalData = sensor.optionalData
                        sensorAlert.changeState = sensor.changeState
                        sensorAlert.hasLatestData = sensor.hasLatestData
                        sensorAlert.dataType = sensor.sensorDataType
                        sensorAlert.sensorData = sensor.sensorData

                        asyncSenderProcess = AsynchronousSender(
                            self.connection, self.globalData)
                        # set thread to daemon
                        # => threads terminates when main thread terminates
                        asyncSenderProcess.daemon = True
                        asyncSenderProcess.sendSensorAlert = True
                        asyncSenderProcess.sendSensorAlertSensorAlert = \
                         sensorAlert
                        asyncSenderProcess.start()

                    # if sensor does not trigger sensor alert
                    # => just send changed state to server
                    else:

                        logging.debug("[%s]: State " % self.fileName +
                                      "changed by '%s'." % sensor.description)

                        # Create state change object to send to the server.
                        stateChange = StateChange()
                        stateChange.clientSensorId = sensor.id
                        stateChange.state = 1
                        stateChange.dataType = sensor.sensorDataType
                        stateChange.sensorData = sensor.sensorData

                        asyncSenderProcess = AsynchronousSender(
                            self.connection, self.globalData)
                        # set thread to daemon
                        # => threads terminates when main thread terminates
                        asyncSenderProcess.daemon = True
                        asyncSenderProcess.sendStateChange = True
                        asyncSenderProcess.sendStateChangeStateChange = \
                         stateChange
                        asyncSenderProcess.start()

                # only possible situation left => sensor changed
                # back from triggering state to a normal state
                else:

                    # check if the sensor triggers a sensor alert when
                    # state is back to normal
                    # => send sensor alert to server
                    if sensor.triggerAlertNormal:

                        logging.info("[%s]: Sensor alert " % self.fileName +
                                     "for back to normal state " +
                                     "triggered by '%s'." % sensor.description)

                        # Create sensor alert object to send to the server.
                        sensorAlert = SensorAlert()
                        sensorAlert.clientSensorId = sensor.id
                        sensorAlert.state = 0
                        sensorAlert.hasOptionalData = sensor.hasOptionalData
                        sensorAlert.optionalData = sensor.optionalData
                        sensorAlert.changeState = sensor.changeState
                        sensorAlert.hasLatestData = sensor.hasLatestData
                        sensorAlert.dataType = sensor.sensorDataType
                        sensorAlert.sensorData = sensor.sensorData

                        asyncSenderProcess = AsynchronousSender(
                            self.connection, self.globalData)
                        # set thread to daemon
                        # => threads terminates when main thread terminates
                        asyncSenderProcess.daemon = True
                        asyncSenderProcess.sendSensorAlert = True
                        asyncSenderProcess.sendSensorAlertSensorAlert = \
                         sensorAlert
                        asyncSenderProcess.start()

                    # if sensor does not trigger sensor alert when
                    # state is back to normal
                    # => just send changed state to server
                    else:

                        logging.debug("[%s]: State " % self.fileName +
                                      "changed by '%s'." % sensor.description)

                        # Create state change object to send to the server.
                        stateChange = StateChange()
                        stateChange.clientSensorId = sensor.id
                        stateChange.state = 0
                        stateChange.dataType = sensor.sensorDataType
                        stateChange.sensorData = sensor.sensorData

                        asyncSenderProcess = AsynchronousSender(
                            self.connection, self.globalData)
                        # set thread to daemon
                        # => threads terminates when main thread terminates
                        asyncSenderProcess.daemon = True
                        asyncSenderProcess.sendStateChange = True
                        asyncSenderProcess.sendStateChangeStateChange = \
                         stateChange
                        asyncSenderProcess.start()

            # Poll all sensors if they want to force an update that should
            # be send to the server.
            for sensor in self.sensors:

                stateChange = sensor.forceSendState()
                if stateChange:
                    asyncSenderProcess = AsynchronousSender(
                        self.connection, self.globalData)
                    # set thread to daemon
                    # => threads terminates when main thread terminates
                    asyncSenderProcess.daemon = True
                    asyncSenderProcess.sendStateChange = True
                    asyncSenderProcess.sendStateChangeStateChange = stateChange
                    asyncSenderProcess.start()

            # check if the last state that was sent to the server
            # is older than 60 seconds => send state update
            utcTimestamp = int(time.time())
            if (utcTimestamp - lastFullStateSent) > 60:

                logging.debug("[%s]: Last state " % self.fileName +
                              "timed out.")

                asyncSenderProcess = AsynchronousSender(
                    self.connection, self.globalData)
                # set thread to daemon
                # => threads terminates when main thread terminates
                asyncSenderProcess.daemon = True
                asyncSenderProcess.sendSensorsState = True
                asyncSenderProcess.start()

                # update time on which the full state update was sent
                lastFullStateSent = utcTimestamp

            time.sleep(0.5)
Beispiel #3
0
	def execute(self):

		# time on which the last full sensor states were sent
		# to the server
		lastFullStateSent = 0

		# Get reference to server communication object.
		while self.connection is None:
			time.sleep(0.5)
			self.connection = self.globalData.serverComm

		self._isInitialized = True

		while True:

			# check if the client is connected to the server
			# => wait and continue loop until client is connected
			if not self.connection.isConnected():
				time.sleep(0.5)
				continue

			# poll all sensors and check their states
			for sensor in self.sensors:

				oldState = sensor.getState()
				sensor.updateState()
				currentState = sensor.getState()

				# Check if a sensor alert is forced to send to the server.
				# => update already known state and continue
				sensorAlert = sensor.forceSendAlert()
				if sensorAlert:
					oldState = currentState

					asyncSenderProcess = AsynchronousSender(
						self.connection, self.globalData)
					# set thread to daemon
					# => threads terminates when main thread terminates	
					asyncSenderProcess.daemon = True
					asyncSenderProcess.sendSensorAlert = True
					asyncSenderProcess.sendSensorAlertSensorAlert = sensorAlert
					asyncSenderProcess.start()

					continue

				# check if the current state is the same
				# than the already known state => continue
				elif oldState == currentState:
					continue

				# check if the current state is an alert triggering state
				elif currentState == sensor.triggerState:

					# check if the sensor triggers a sensor alert
					# => send sensor alert to server
					if sensor.triggerAlert:

						logging.info("[%s]: Sensor alert " % self.fileName
							+ "triggered by '%s'." % sensor.description)

						# Create sensor alert object to send to the server.
						sensorAlert = SensorAlert()
						sensorAlert.clientSensorId = sensor.id
						sensorAlert.state = 1
						sensorAlert.hasOptionalData = sensor.hasOptionalData
						sensorAlert.optionalData = sensor.optionalData
						sensorAlert.changeState = sensor.changeState
						sensorAlert.hasLatestData = sensor.hasLatestData
						sensorAlert.dataType = sensor.sensorDataType
						sensorAlert.sensorData = sensor.sensorData

						asyncSenderProcess = AsynchronousSender(
							self.connection, self.globalData)
						# set thread to daemon
						# => threads terminates when main thread terminates	
						asyncSenderProcess.daemon = True
						asyncSenderProcess.sendSensorAlert = True
						asyncSenderProcess.sendSensorAlertSensorAlert = \
							sensorAlert
						asyncSenderProcess.start()

					# if sensor does not trigger sensor alert
					# => just send changed state to server
					else:

						logging.debug("[%s]: State " % self.fileName
							+ "changed by '%s'." % sensor.description)

						# Create state change object to send to the server.
						stateChange = StateChange()
						stateChange.clientSensorId = sensor.id
						stateChange.state = 1
						stateChange.dataType = sensor.sensorDataType
						stateChange.sensorData = sensor.sensorData

						asyncSenderProcess = AsynchronousSender(
							self.connection, self.globalData)
						# set thread to daemon
						# => threads terminates when main thread terminates	
						asyncSenderProcess.daemon = True
						asyncSenderProcess.sendStateChange = True
						asyncSenderProcess.sendStateChangeStateChange = \
							stateChange
						asyncSenderProcess.start()

				# only possible situation left => sensor changed
				# back from triggering state to a normal state
				else:

					# check if the sensor triggers a sensor alert when
					# state is back to normal
					# => send sensor alert to server
					if sensor.triggerAlertNormal:

						logging.info("[%s]: Sensor alert " % self.fileName
							+ "for back to normal state "
							+ "triggered by '%s'." % sensor.description)

						# Create sensor alert object to send to the server.
						sensorAlert = SensorAlert()
						sensorAlert.clientSensorId = sensor.id
						sensorAlert.state = 0
						sensorAlert.hasOptionalData = sensor.hasOptionalData
						sensorAlert.optionalData = sensor.optionalData
						sensorAlert.changeState = sensor.changeState
						sensorAlert.hasLatestData = sensor.hasLatestData
						sensorAlert.dataType = sensor.sensorDataType
						sensorAlert.sensorData = sensor.sensorData

						asyncSenderProcess = AsynchronousSender(
							self.connection, self.globalData)
						# set thread to daemon
						# => threads terminates when main thread terminates	
						asyncSenderProcess.daemon = True
						asyncSenderProcess.sendSensorAlert = True
						asyncSenderProcess.sendSensorAlertSensorAlert = \
							sensorAlert
						asyncSenderProcess.start()

					# if sensor does not trigger sensor alert when
					# state is back to normal
					# => just send changed state to server
					else:

						logging.debug("[%s]: State " % self.fileName
							+ "changed by '%s'." % sensor.description)

						# Create state change object to send to the server.
						stateChange = StateChange()
						stateChange.clientSensorId = sensor.id
						stateChange.state = 0
						stateChange.dataType = sensor.sensorDataType
						stateChange.sensorData = sensor.sensorData

						asyncSenderProcess = AsynchronousSender(
							self.connection, self.globalData)
						# set thread to daemon
						# => threads terminates when main thread terminates	
						asyncSenderProcess.daemon = True
						asyncSenderProcess.sendStateChange = True
						asyncSenderProcess.sendStateChangeStateChange = \
							stateChange
						asyncSenderProcess.start()

			# Poll all sensors if they want to force an update that should
			# be send to the server.
			for sensor in self.sensors:

				stateChange = sensor.forceSendState()
				if stateChange:
					asyncSenderProcess = AsynchronousSender(
						self.connection, self.globalData)
					# set thread to daemon
					# => threads terminates when main thread terminates	
					asyncSenderProcess.daemon = True
					asyncSenderProcess.sendStateChange = True
					asyncSenderProcess.sendStateChangeStateChange = stateChange
					asyncSenderProcess.start()

			# check if the last state that was sent to the server
			# is older than 60 seconds => send state update
			if (time.time() - lastFullStateSent) > 60:

				logging.debug("[%s]: Last state " % self.fileName
					+ "timed out.")

				asyncSenderProcess = AsynchronousSender(
					self.connection, self.globalData)
				# set thread to daemon
				# => threads terminates when main thread terminates	
				asyncSenderProcess.daemon = True
				asyncSenderProcess.sendSensorsState = True
				asyncSenderProcess.start()

				# update time on which the full state update was sent
				lastFullStateSent = time.time()
				
			time.sleep(0.5)
Beispiel #4
0
    def forceSendAlert(self):

        # Check if we have exceeded the threshold of failed calendar
        # retrieval attempts and create a sensor alert if we have.
        sensorAlert = None
        if (not self.inFailedState
            and self.failedCounter > self.maxFailedAttempts):

            logging.warning("[%s] Triggering sensor alert for "
                % self.fileName
                + "'%d' failed calendar fetching attempts."
                % self.failedCounter)

            sensorAlert = SensorAlert()
            sensorAlert.clientSensorId = self.id
            sensorAlert.state = 1
            sensorAlert.hasOptionalData = True
            msg = "Failed more than %d times for '%s' " \
                % (self.maxFailedAttempts, self.name) \
                + "to retrieve calendar data."
            sensorAlert.optionalData = {"message": msg,
                                        "calendar": self.name,
                                        "type": "timeout"}
            sensorAlert.changeState = True
            sensorAlert.hasLatestData = False
            sensorAlert.dataType = SensorDataType.NONE

            self.state = self.triggerState
            self.inFailedState = True

        # If we are in a failed retrieval state and we could retrieve
        # calendar data again trigger a sensor alert for "normal".
        elif (self.inFailedState
            and self.failedCounter <= self.maxFailedAttempts):

            logging.warning("[%s] Fetching calendar succeeded after "
                % self.fileName
                + "multiple failed attempts. Triggering sensor alert.")

            sensorAlert = SensorAlert()
            sensorAlert.clientSensorId = self.id
            sensorAlert.state = 0
            sensorAlert.hasOptionalData = True
            msg = "Calendar data for '%s' retrievable again." \
                % self.name
            sensorAlert.optionalData = {"message": msg,
                                        "calendar": self.name,
                                        "type": "timeout"}
            sensorAlert.changeState = True
            sensorAlert.hasLatestData = False
            sensorAlert.dataType = SensorDataType.NONE

            self.state = 1 - self.triggerState
            self.inFailedState = False

        # If we have sensor alerts of reminder waiting
        # return the oldest of them.
        elif not self.reminderAlertQueue.empty():
            try:
                sensorAlert = self.reminderAlertQueue.get(True, 2)
            except:
                pass

        return sensorAlert
Beispiel #5
0
    def _processEventAlarms(self, event, eventDatetime):

        # Create current datetime object.
        currentUTCTime = time.time()
        currentDatetime = datetime.datetime.utcfromtimestamp(currentUTCTime)
        currentDatetime = currentDatetime.replace(tzinfo=pytz.UTC)

        for alarm in event.walk("VALARM"):

            if alarm.has_key("TRIGGER"):

                # Get time delta when reminder is triggered.
                trigger = alarm.get("TRIGGER")

                # Get time when reminder is triggered.
                # When trigger time is a delta, then calculate the actual time.
                if type(trigger.dt) == datetime.timedelta:
                    triggerDatetime = eventDatetime + trigger.dt

                # When trigger time is an actual time, use this.
                elif type(trigger.dt) == datetime.datetime:
                    triggerDatetime = trigger.dt

                    # Use the same timezone as the event when
                    # no is given.
                    if triggerDatetime.tzinfo is None:
                        triggerDatetime = triggerDatetime.replace(
                                                tzinfo=eventDatetime.tzinfo)

                # When trigger time is only a date, start at midnight,
                # however, use the same timezone as the event.
                elif type(trigger.dt) == datetime.date:
                    triggerUTCTime = calendar.timegm(trigger.dt.timetuple())
                    triggerDatetime = datetime.datetime.utcfromtimestamp(
                                                                triggerUTCTime)
                    # Since we just overwrite the timezone here, we do not
                    # care about conversion from UTC since the new datetime
                    # object starts at midnight in the given timezone.
                    triggerDatetime = triggerDatetime.replace(
                                                tzinfo=eventDatetime.tzinfo)

                else:
                    logging.error("[%s] Error: Do not know how to handle "
                        % self.fileName
                        + "trigger type '%s'."
                        % trigger.dt.__class__)
                    continue

                # Uid of event is needed.
                uid = event.get("UID")

                # Get time when event starts.
                dtstart = event.get("DTSTART")

                # Check if we already triggered an alarm for the event
                # with this uid and the given alarm trigger time.
                if (uid, triggerDatetime) in self.alreadyTriggered:
                    break

                # Check if the alarm trigger time lies in the past but not
                # more than 1 day.
                if((currentDatetime - self.timedelta1day)
                    <= triggerDatetime
                    <= currentDatetime):

                    title = event.get("SUMMARY")

                    # Get description if event has one.
                    evDescription = ""
                    if event.has_key("DESCRIPTION"):
                        evDescription = event.get("DESCRIPTION")

                    # Get location if event has one.
                    location = ""
                    if event.has_key("LOCATION"):
                        location = event.get("LOCATION")

                    # Create the utc unix timestamp for the start of the event.
                    unixStart = datetime.datetime.utcfromtimestamp(0)
                    unixStart = unixStart.replace(tzinfo=pytz.UTC)

                    utcDtstart = int(
                                (eventDatetime - unixStart).total_seconds())

                    # Create the utc unix timestamp for the reminder trigger.
                    utcTrigger = int(
                                (triggerDatetime - unixStart).total_seconds())

                    eventDateStr = time.strftime("%D %H:%M:%S",
                                                 time.localtime(utcDtstart))
                    msg = "Reminder for event '%s' at %s" \
                        % (title, eventDateStr)

                    # Create sensor alert.
                    sensorAlert = SensorAlert()
                    sensorAlert.clientSensorId = self.id
                    sensorAlert.state = 1
                    sensorAlert.hasOptionalData = True
                    sensorAlert.optionalData = {"message": msg,
                                                "calendar": self.name,
                                                "type": "reminder",
                                                "title": title,
                                                "description": evDescription,
                                                "location": location,
                                                "trigger": utcTrigger,
                                                "start": utcDtstart}
                    sensorAlert.changeState = False
                    sensorAlert.hasLatestData = False
                    sensorAlert.dataType = SensorDataType.NONE

                    self.reminderAlertQueue.put(sensorAlert)

                    # Store the event uid and the alarm trigger time
                    # as already triggered.
                    self.alreadyTriggered.add( (uid, triggerDatetime) )
Beispiel #6
0
    def forceSendAlert(self):

        # Check if we have exceeded the threshold of failed calendar
        # retrieval attempts and create a sensor alert if we have.
        sensorAlert = None
        if (not self.inFailedState
                and self.failedCounter > self.maxFailedAttempts):

            logging.warning(
                "[%s] Triggering sensor alert for " % self.fileName +
                "'%d' failed calendar fetching attempts." % self.failedCounter)

            sensorAlert = SensorAlert()
            sensorAlert.clientSensorId = self.id
            sensorAlert.state = 1
            sensorAlert.hasOptionalData = True
            msg = "Failed more than %d times for '%s' " \
             % (self.maxFailedAttempts, self.name) \
             + "to retrieve calendar data."
            sensorAlert.optionalData = {
                "message": msg,
                "calendar": self.name,
                "type": "timeout"
            }
            sensorAlert.changeState = True
            sensorAlert.hasLatestData = False
            sensorAlert.dataType = SensorDataType.NONE

            self.state = self.triggerState
            self.inFailedState = True

        # If we are in a failed retrieval state and we could retrieve
        # calendar data again trigger a sensor alert for "normal".
        elif (self.inFailedState
              and self.failedCounter <= self.maxFailedAttempts):

            logging.warning(
                "[%s] Fetching calendar succeeded after " % self.fileName +
                "multiple failed attempts. Triggering sensor alert.")

            sensorAlert = SensorAlert()
            sensorAlert.clientSensorId = self.id
            sensorAlert.state = 0
            sensorAlert.hasOptionalData = True
            msg = "Calendar data for '%s' retrievable again." \
             % self.name
            sensorAlert.optionalData = {
                "message": msg,
                "calendar": self.name,
                "type": "timeout"
            }
            sensorAlert.changeState = True
            sensorAlert.hasLatestData = False
            sensorAlert.dataType = SensorDataType.NONE

            self.state = 1 - self.triggerState
            self.inFailedState = False

        # If we have sensor alerts of reminder waiting
        # return the oldest of them.
        elif not self.reminderAlertQueue.empty():
            try:
                sensorAlert = self.reminderAlertQueue.get(True, 2)
            except:
                pass

        return sensorAlert
Beispiel #7
0
    def _processEventAlarms(self, event, eventDatetime):

        # Create current datetime object.
        currentUTCTime = time.time()
        currentDatetime = datetime.datetime.utcfromtimestamp(currentUTCTime)
        currentDatetime = currentDatetime.replace(tzinfo=pytz.UTC)

        for alarm in event.walk("VALARM"):

            if alarm.has_key("TRIGGER"):

                # Get time delta when reminder is triggered.
                trigger = alarm.get("TRIGGER")

                # Get time when reminder is triggered.
                # When trigger time is a delta, then calculate the actual time.
                if type(trigger.dt) == datetime.timedelta:
                    triggerDatetime = eventDatetime + trigger.dt

                # When trigger time is an actual time, use this.
                elif type(trigger.dt) == datetime.datetime:
                    triggerDatetime = trigger.dt

                    # Thunderbird uses the same timezone as the event when
                    # no is given.
                    if triggerDatetime.tzinfo is None:
                        triggerDatetime = triggerDatetime.replace(
                            tzinfo=eventDatetime.tzinfo)

                # When trigger time is only a date, start at midnight.
                elif type(trigger.dt) == datetime.date:
                    triggerUTCTime = calendar.timegm(trigger.dt.timetuple())
                    triggerDatetime = datetime.datetime.utcfromtimestamp(
                        triggerUTCTime)
                    triggerDatetime = triggerDatetime.replace(tzinfo=pytz.UTC)

                else:
                    logging.error("[%s] Error: Do not know how to handle " %
                                  self.fileName +
                                  "trigger type '%s'." % trigger.dt.__class__)
                    continue

                # Uid of event is needed.
                uid = event.get("UID")

                # Get time when event starts.
                dtstart = event.get("DTSTART")

                # Check if we already triggered an alarm for the event
                # with this uid and the given alarm trigger time.
                if (uid, triggerDatetime) in self.alreadyTriggered:
                    break

                # Check if the alarm trigger time lies in the past but not
                # more than 1 day.
                if ((currentDatetime - self.timedelta1day) <= triggerDatetime
                        <= currentDatetime):

                    title = event.get("SUMMARY")

                    # Get description if event has one.
                    evDescription = ""
                    if event.has_key("DESCRIPTION"):
                        evDescription = event.get("DESCRIPTION")

                    # Get location if event has one.
                    location = ""
                    if event.has_key("LOCATION"):
                        location = event.get("LOCATION")

                    # Create the utc unix timestamp for the start of the event.
                    unixStart = datetime.datetime.utcfromtimestamp(0)
                    unixStart = unixStart.replace(tzinfo=pytz.UTC)

                    utcDtstart = int(
                        (eventDatetime - unixStart).total_seconds())

                    # Create the utc unix timestamp for the reminder trigger.
                    utcTrigger = int(
                        (triggerDatetime - unixStart).total_seconds())

                    eventDateStr = time.strftime("%D %H:%M:%S",
                                                 time.localtime(utcDtstart))
                    msg = "Reminder for event '%s' at %s" \
                     % (title, eventDateStr)

                    # Create sensor alert.
                    sensorAlert = SensorAlert()
                    sensorAlert.clientSensorId = self.id
                    sensorAlert.state = 1
                    sensorAlert.hasOptionalData = True
                    sensorAlert.optionalData = {
                        "message": msg,
                        "calendar": self.name,
                        "type": "reminder",
                        "title": title,
                        "description": evDescription,
                        "location": location,
                        "trigger": utcTrigger,
                        "start": utcDtstart
                    }
                    sensorAlert.changeState = False
                    sensorAlert.hasLatestData = False
                    sensorAlert.dataType = SensorDataType.NONE

                    self.reminderAlertQueue.put(sensorAlert)

                    # Store the event uid and the alarm trigger time
                    # as already triggered.
                    self.alreadyTriggered.add((uid, triggerDatetime))