示例#1
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)
示例#2
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
示例#3
0
    def run(self):

        while True:

            # check if FIFO file exists
            # => remove it if it does
            if os.path.exists(self.fifoFile):
                try:
                    os.remove(self.fifoFile)
                except Exception as e:
                    logging.exception(
                        "[%s]: Could not delete " % self.fileName +
                        "FIFO file of sensor with id '%d'." % self.id)
                    time.sleep(10)
                    continue

            # create a new FIFO file
            try:
                os.umask(self.umask)
                os.mkfifo(self.fifoFile)
            except Exception as e:
                logging.exception("[%s]: Could not create " % self.fileName +
                                  "FIFO file of sensor with id '%d'." %
                                  self.id)
                time.sleep(10)
                continue

            # read FIFO for data
            data = ""
            try:
                fifo = open(self.fifoFile, "r")
                data = fifo.read()
                fifo.close()
            except Exception as e:
                logging.exception(
                    "[%s]: Could not read data from " % self.fileName +
                    "FIFO file of sensor with id '%d'." % self.id)
                time.sleep(10)
                continue

            logging.debug("[%s]: Received data '%s' from " %
                          (self.fileName, data) +
                          "FIFO file of sensor with id '%d'." % self.id)

            # parse received data
            try:

                message = json.loads(data)

                # Parse message depending on type.
                # Type: statechange
                if str(message["message"]).upper() == "STATECHANGE":

                    # Check if state is valid.
                    tempInputState = message["payload"]["state"]
                    if not self._checkState(tempInputState):
                        logging.error(
                            "[%s]: Received state " % self.fileName +
                            "from FIFO file of sensor with id '%d' " %
                            self.id + "invalid. Ignoring message.")
                        continue

                    # Check if data type is valid.
                    tempDataType = message["payload"]["dataType"]
                    if not self._checkDataType(tempDataType):
                        logging.error(
                            "[%s]: Received data type " % self.fileName +
                            "from FIFO file of sensor with id '%d' " %
                            self.id + "invalid. Ignoring message.")
                        continue

                    # Set new data.
                    if self.sensorDataType == SensorDataType.NONE:
                        self.sensorData = None
                    elif self.sensorDataType == SensorDataType.INT:
                        self.sensorData = int(message["payload"]["data"])
                    elif self.sensorDataType == SensorDataType.FLOAT:
                        self.sensorData = float(message["payload"]["data"])

                    # Set state.
                    self.temporaryState = tempInputState

                    # Force state change sending if the data could be changed.
                    if self.sensorDataType != SensorDataType.NONE:

                        # Create state change object that is
                        # send to the server.
                        self.forceSendStateLock.acquire()
                        self.stateChange = StateChange()
                        self.stateChange.clientSensorId = self.id
                        if tempInputState == self.triggerState:
                            self.stateChange.state = 1
                        else:
                            self.stateChange.state = 0
                        self.stateChange.dataType = tempDataType
                        self.stateChange.sensorData = self.sensorData
                        self.shouldForceSendState = True
                        self.forceSendStateLock.release()

                # Type: sensoralert
                elif str(message["message"]).upper() == "SENSORALERT":

                    # Check if state is valid.
                    tempInputState = message["payload"]["state"]
                    if not self._checkState(tempInputState):
                        logging.error(
                            "[%s]: Received state " % self.fileName +
                            "from FIFO file of sensor with id '%d' " %
                            self.id + "invalid. Ignoring message.")
                        continue

                    # Check if hasOptionalData field is valid.
                    tempHasOptionalData = message["payload"]["hasOptionalData"]
                    if not self._checkHasOptionalData(tempHasOptionalData):
                        logging.error(
                            "[%s]: Received hasOptionalData field " %
                            self.fileName +
                            "from FIFO file of sensor with id '%d' " %
                            self.id + "invalid. Ignoring message.")
                        continue

                    # Check if data type is valid.
                    tempDataType = message["payload"]["dataType"]
                    if not self._checkDataType(tempDataType):
                        logging.error(
                            "[%s]: Received data type " % self.fileName +
                            "from FIFO file of sensor with id '%d' " %
                            self.id + "invalid. Ignoring message.")
                        continue

                    if self.sensorDataType == SensorDataType.NONE:
                        tempSensorData = None
                    elif self.sensorDataType == SensorDataType.INT:
                        tempSensorData = int(message["payload"]["data"])
                    elif self.sensorDataType == SensorDataType.FLOAT:
                        tempSensorData = float(message["payload"]["data"])

                    # Check if hasLatestData field is valid.
                    tempHasLatestData = message["payload"]["hasLatestData"]
                    if not self._checkHasLatestData(tempHasLatestData):
                        logging.error(
                            "[%s]: Received hasLatestData field " %
                            self.fileName +
                            "from FIFO file of sensor with id '%d' " %
                            self.id + "invalid. Ignoring message.")
                        continue

                    # Check if changeState field is valid.
                    tempChangeState = message["payload"]["changeState"]
                    if not self._checkChangeState(tempChangeState):
                        logging.error(
                            "[%s]: Received changeState field " %
                            self.fileName +
                            "from FIFO file of sensor with id '%d' " %
                            self.id + "invalid. Ignoring message.")
                        continue

                    # Check if data should be transfered with the sensor alert
                    # => if it should parse it
                    tempOptionalData = None
                    if tempHasOptionalData:

                        tempOptionalData = message["payload"]["optionalData"]

                        # check if data is of type dict
                        if not isinstance(tempOptionalData, dict):
                            logging.warning(
                                "[%s]: Received optional data " %
                                self.fileName +
                                "from FIFO file of sensor with id '%d' " %
                                self.id + "invalid. Ignoring message.")
                            continue

                    # Set optional data.
                    self.hasOptionalData = tempHasOptionalData
                    self.optionalData = tempOptionalData

                    # Set new data.
                    if tempHasLatestData:
                        self.sensorData = tempSensorData

                    # Set state.
                    if tempChangeState:
                        self.temporaryState = tempInputState

                    # Create sensor alert object that is send to the server.
                    self.forceSendAlertLock.acquire()
                    self.sensorAlert = SensorAlert()
                    self.sensorAlert.clientSensorId = self.id
                    if tempInputState == self.triggerState:
                        self.sensorAlert.state = 1
                    else:
                        self.sensorAlert.state = 0
                    self.sensorAlert.hasOptionalData = tempHasOptionalData
                    self.sensorAlert.optionalData = tempOptionalData
                    self.sensorAlert.changeState = tempChangeState
                    self.sensorAlert.hasLatestData = tempHasLatestData
                    self.sensorAlert.dataType = tempDataType
                    self.sensorAlert.sensorData = tempSensorData
                    self.shouldForceSendAlert = True
                    self.forceSendAlertLock.release()

                # Type: invalid
                else:
                    raise ValueError("Received invalid message type.")

            except Exception as e:
                logging.exception("[%s]: Could not parse received data from " %
                                  self.fileName +
                                  "FIFO file of sensor with id '%d'." %
                                  self.id)
                continue
示例#4
0
文件: sensor.py 项目: sqall01/alertR
    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
示例#5
0
文件: sensor.py 项目: catding/alertR
	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)
示例#6
0
文件: sensor.py 项目: sqall01/alertR
    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) )
示例#7
0
文件: sensor.py 项目: shr1k4nt/alertR
    def updateState(self):

        self.hasOptionalData = False
        self.optionalData = None

        # check if a process is executed
        # => if none no process is executed
        if self.process is None:

            # check if the interval in which the service should be checked
            # is exceeded
            utcTimestamp = int(time.time())
            if (utcTimestamp - self.timeExecute) > self.intervalToCheck:

                logging.debug("[%s]: Executing process " % self.fileName +
                              "'%s'." % self.description)

                self.process = subprocess.Popen(self.execute,
                                                stdout=subprocess.PIPE,
                                                stderr=subprocess.PIPE)

                self.timeExecute = utcTimestamp

        # => process is still running
        else:

            # check if process is not finished yet
            if self.process.poll() is None:

                # check if process has timed out
                utcTimestamp = int(time.time())
                if (utcTimestamp - self.timeExecute) > self.timeout:

                    self.state = self.triggerState
                    self.hasOptionalData = True
                    self.optionalData = {"message": "Timeout"}

                    logging.error("[%s]: Process " % self.fileName +
                                  "'%s' has timed out." % self.description)

                    # terminate process
                    self.process.terminate()

                    # give the process one second to terminate
                    time.sleep(1)

                    # check if the process has terminated
                    # => if not kill it
                    exitCode = self.process.poll()
                    if exitCode != -15:
                        try:
                            logging.error("[%s]: Could not " % self.fileName +
                                          "terminate '%s'. Killing it." %
                                          self.description)

                            self.process.kill()
                        except:
                            pass
                    self.optionalData["exitCode"] = exitCode

                    # set process to none so it can be newly started
                    # in the next state update
                    self.process = None

            # process has finished
            else:

                # Distinguish if we should parse the output or not.
                if self.parseOutput:

                    # Parse output.
                    output, err = self.process.communicate()
                    if not self._parseOutput(output):

                        logging.error("[%s] Not able to parse output " %
                                      self.fileName +
                                      "of sensor with id '%d'." % self.id)
                        logging.error("[%s] Sensor with id '%d' stdout: %s" %
                                      (self.fileName, self.id, output))
                        logging.error("[%s] Sensor with id '%d' stderr: %s" %
                                      (self.fileName, self.id, err))

                        self.state = self.triggerState

                        # Generate sensor alert object.
                        self.sensorAlert = SensorAlert()
                        self.sensorAlert.clientSensorId = self.id
                        self.sensorAlert.state = 1
                        self.sensorAlert.hasOptionalData = True
                        self.sensorAlert.optionalData = \
                         {"message": "Illegal output"}
                        self.sensorAlert.changeState = True
                        self.sensorAlert.hasLatestData = False
                        self.sensorAlert.dataType = self.sensorDataType
                        if self.sensorDataType == SensorDataType.NONE:
                            self.sensorAlert.sensorData = None
                        elif self.sensorDataType == SensorDataType.INT:
                            self.sensorAlert.sensorData = 0
                        elif self.sensorDataType == SensorDataType.FLOAT:
                            self.sensorAlert.sensorData = 0.0
                        self.shouldForceSendAlert = True

                else:
                    self.hasOptionalData = True
                    self.optionalData = dict()

                    # check if the process has exited with code 0
                    # => everything works fine
                    exitCode = self.process.poll()
                    if exitCode == 0:
                        self.state = 1 - self.triggerState
                    # process did not exited correctly
                    # => something is wrong with the service
                    else:
                        output, err = self.process.communicate()
                        logging.error("[%s] Sensor with id '%d' stdout: %s" %
                                      (self.fileName, self.id, output))
                        logging.error("[%s] Sensor with id '%d' stderr: %s" %
                                      (self.fileName, self.id, err))

                        self.state = self.triggerState
                    self.optionalData["exitCode"] = exitCode

                # set process to none so it can be newly started
                # in the next state update
                self.process = None
示例#8
0
文件: sensor.py 项目: shr1k4nt/alertR
    def _parseOutput(self, data):

        # Parse output data
        try:

            logging.debug("[%s] Received output from sensor with id '%d': %s" %
                          (self.fileName, self.id, data))

            message = json.loads(data)

            # Parse message depending on type.
            # Type: statechange
            if str(message["message"]).upper() == "STATECHANGE":

                # Check if state is valid.
                tempInputState = message["payload"]["state"]
                if not self._checkState(tempInputState):
                    logging.error("[%s]: Received state " % self.fileName +
                                  "from output of sensor with id '%d' " %
                                  self.id + "invalid. Ignoring output.")
                    return False

                # Check if data type is valid.
                tempDataType = message["payload"]["dataType"]
                if not self._checkDataType(tempDataType):
                    logging.error("[%s]: Received data type " % self.fileName +
                                  "from output of sensor with id '%d' " %
                                  self.id + "invalid. Ignoring output.")
                    return False

                # Set new data.
                if self.sensorDataType == SensorDataType.NONE:
                    self.sensorData = None
                elif self.sensorDataType == SensorDataType.INT:
                    self.sensorData = int(message["payload"]["data"])
                elif self.sensorDataType == SensorDataType.FLOAT:
                    self.sensorData = float(message["payload"]["data"])

                # Force state change sending if the data could be changed
                # or the state has changed.
                if (self.sensorDataType != SensorDataType.NONE
                        or self.state != tempInputState):

                    # Create state change object that is
                    # send to the server.
                    self.stateChange = StateChange()
                    self.stateChange.clientSensorId = self.id
                    if tempInputState == self.triggerState:
                        self.stateChange.state = 1
                    else:
                        self.stateChange.state = 0
                    self.stateChange.dataType = tempDataType
                    self.stateChange.sensorData = self.sensorData
                    self.shouldForceSendState = True

                # Set state.
                self.state = tempInputState

            # Type: sensoralert
            elif str(message["message"]).upper() == "SENSORALERT":

                # Check if state is valid.
                tempInputState = message["payload"]["state"]
                if not self._checkState(tempInputState):
                    logging.error("[%s]: Received state " % self.fileName +
                                  "from output of sensor with id '%d' " %
                                  self.id + "invalid. Ignoring output.")
                    return False

                # Check if hasOptionalData field is valid.
                tempHasOptionalData = message["payload"]["hasOptionalData"]
                if not self._checkHasOptionalData(tempHasOptionalData):
                    logging.error("[%s]: Received hasOptionalData field " %
                                  self.fileName +
                                  "from output of sensor with id '%d' " %
                                  self.id + "invalid. Ignoring output.")
                    return False

                # Check if data type is valid.
                tempDataType = message["payload"]["dataType"]
                if not self._checkDataType(tempDataType):
                    logging.error("[%s]: Received data type " % self.fileName +
                                  "from output of sensor with id '%d' " %
                                  self.id + "invalid. Ignoring output.")
                    return False

                if self.sensorDataType == SensorDataType.NONE:
                    tempSensorData = None
                elif self.sensorDataType == SensorDataType.INT:
                    tempSensorData = int(message["payload"]["data"])
                elif self.sensorDataType == SensorDataType.FLOAT:
                    tempSensorData = float(message["payload"]["data"])

                # Check if hasLatestData field is valid.
                tempHasLatestData = message["payload"]["hasLatestData"]
                if not self._checkHasLatestData(tempHasLatestData):
                    logging.error(
                        "[%s]: Received hasLatestData field " % self.fileName +
                        "from output of sensor with id '%d' " % self.id +
                        "invalid. Ignoring output.")
                    return False

                # Check if changeState field is valid.
                tempChangeState = message["payload"]["changeState"]
                if not self._checkChangeState(tempChangeState):
                    logging.error(
                        "[%s]: Received changeState field " % self.fileName +
                        "from output of sensor with id '%d' " % self.id +
                        "invalid. Ignoring output.")
                    return False

                # Check if data should be transfered with the sensor alert
                # => if it should parse it
                tempOptionalData = None
                if tempHasOptionalData:

                    tempOptionalData = message["payload"]["optionalData"]

                    # check if data is of type dict
                    if not isinstance(tempOptionalData, dict):
                        logging.warning(
                            "[%s]: Received optional data " % self.fileName +
                            "from output of sensor with id '%d' " % self.id +
                            "invalid. Ignoring output.")
                        return False

                # Set optional data.
                self.hasOptionalData = tempHasOptionalData
                self.optionalData = tempOptionalData

                # Set new data.
                if tempHasLatestData:
                    self.sensorData = tempSensorData

                # Set state.
                if tempChangeState:
                    self.state = tempInputState

                # Create sensor alert object that is send to the server.
                self.sensorAlert = SensorAlert()
                self.sensorAlert.clientSensorId = self.id
                if tempInputState == self.triggerState:
                    self.sensorAlert.state = 1
                else:
                    self.sensorAlert.state = 0
                self.sensorAlert.hasOptionalData = tempHasOptionalData
                self.sensorAlert.optionalData = tempOptionalData
                self.sensorAlert.changeState = tempChangeState
                self.sensorAlert.hasLatestData = tempHasLatestData
                self.sensorAlert.dataType = tempDataType
                self.sensorAlert.sensorData = tempSensorData
                self.shouldForceSendAlert = True

            # Type: invalid
            else:
                raise ValueError("Received invalid message type.")

        except Exception as e:
            logging.exception("[%s]: Could not parse received data from " %
                              self.fileName +
                              "output of sensor with id '%d'." % self.id)
            return False

        return True
示例#9
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
示例#10
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))