Exemple #1
0
class Radio(object):
    def connect(self, port):
        self.serial = SerialPort(RadioReceiverProtocol(self), port, reactor, baudrate=57600)
        self.serial.flushInput()

    def __init__(self):
        self.listeners = []
        self.serial = None

    def send(self, packet):
        data = array.array('B', packet.encode()).tostring()
        print 'tx:', packet
        if self.serial is not None:
            self.serial.write(data)

    def gotPacket(self, packet):
        print 'rx:', packet
        for l in self.listeners:
            l(packet)
Exemple #2
0
class IridiumSimulator(Thread):
	def __init__(self, comPort, moIP, moPort, mtPort, delay):
		Thread.__init__(self)
		self.udpMavlink = mavlink.MAVLink(0)
		self.serialMavlink = mavlink.MAVLink(0)
		self.udpRx = []
		self.serialRx = None
		self.ipLock = Lock()
		self.serialLock = Lock()
		self.ipTransport = None
		self.status = SatcomStatus.idle
		self.serialTime = 0
		self.delay = delay
		self.terminate = False
		# serial interface to PX4
		self.serialInterface = SerialPort(PX4UartInterface(self.receivedPX4), comPort, reactor, baudrate = 115200)
		self.serialInterface.flushInput()
		self.serialInterface.flushOutput()
		# enpoint for sending MO messages from PX to the relay
		self.relayMoEndpoint = TCP4ClientEndpoint(reactor, moIP, moPort)
		# enpoint receiving MT messages coming from the relay
		self.relayMtEndpoint = TCP4ServerEndpoint(reactor, mtPort)
		self.relayMtEndpoint.listen(relay.IridiumMtReceiverFactory(self.receivedRelay))


	def run(self):
		while not self.terminate:
			self.serialLock.acquire()

			if self.serialTime + self.delay <= time():
				if self.status == SatcomStatus.sending:
					self.sendMsgToPX4(0x01, chr(0x00))
					self.ipLock.acquire()
					# prepare and send an iridium message
					try:
						m = self.udpMavlink.decode(self.serialRx[8:])
						if m is not None:
							msgId = m.get_msgId()
							print '<-- PX4 {0} ({1})'.format(mavlink.mavlink_map[msgId].name, msgId)
					except Exception as e:
						print '<-- PX4 ' + str(e)
					moMsgData = self.prepareMoMessage(self.serialRx)
					prot = relay.IridiumMoSender(moMsgData)
					connectProtocol(self.relayMoEndpoint, prot)
					self.ipLock.release()
					#print 'SEND RQ: complete'
					self.status = SatcomStatus.idle

				elif self.status == SatcomStatus.receiving:
					if len(self.udpRx) != 0:
						self.ipLock.acquire()
						msg = self.udpRx.pop(0)

						try:
							m = self.udpMavlink.decode(msg)
						except Exception as e:
							print e
							m = None

						if m is not None:
							msgId = m.get_msgId()
							print 'QGC --> {0} ({1})'.format(mavlink.mavlink_map[msgId].name, msgId)
							self.sendMsgToPX4(0x02, chr(0x00) + msg)
						else:
							self.sendMsgToPX4(0x02, chr(0x2F))  # no msg

						self.ipLock.release()
						#print 'RCV RQ: complete'
					else:
						self.sendMsgToPX4(0x02, chr(0x2F))  # no msg
						#print 'RCV RQ: no msg'

					self.status = SatcomStatus.idle

			self.serialLock.release()

			sleep(0.1)


	def receivedPX4(self, msg):
		# send msg
		if msg.id == 0x01:
			self.satcomSendRequest(msg.data)

		# retrieve msg
		if msg.id == 0x02:
			self.satcomReceiveRequest()

		# check network status
		if msg.id == 0x05:
			self.satcomGetNetworkStatus()

		# check signal strength
		if msg.id == 0x06:
			self.satcomGetSignalStrength()


	def receivedRelay(self, msg):
		# print 'MT MSG CALLBACK'
		for ie in msg.ieList:
			# print 'IE: {0}: {1}'.format(ie.id, ie.name)
			if ie.name == 'MT Payload IE':
				# print ie.payload
				try:
					#m = self.udpMavlink.decode(ie.payload)
					#if m is not None:
						# print 'MT mavlink msg ID {0}'.format(m.get_msgId())
						self.ipLock.acquire()
						self.udpRx.append(ie.payload)
						self.ipLock.release()
				except:
					pass



	def prepareMoMessage(self, mavlinkMsg):
		msg = iridium.IridiumMessage()

		header = iridium.MoHeaderIe()
		header.autoId = 123
		header.imei = bytearray([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE])
		header.sessionStatus = iridium.MoHeaderIe.SessionStatus.SUCCESSFUL
		header.momsn = 1
		header.mtmsn = 2
		header.timeOfSession = 100000
		header.prepareRaw()
		msg.ieList.append(header)

		payload = iridium.MoPayloadIe()
		payload.payload = mavlinkMsg
		payload.prepareRaw()
		msg.ieList.append(payload)

		msg.prepareRaw()

		return msg.rawData



	def satcomSendRequest(self, msgData):
		self.serialLock.acquire()

		if self.status == SatcomStatus.idle:
			#print 'SEND RQ: pending'
			self.status = SatcomStatus.sending
			self.serialTime = time()

			scsHeader = bytearray()
			packetLen = len(msgData) + 8
			scsHeader.append(packetLen / 256)
			scsHeader.append(packetLen % 256)
			scsHeader.append(2) # PX4 packet
			scsHeader += bytearray(5) # 5 empty bytes - only used when sending images

			self.serialRx = scsHeader + msgData

		else:
			print 'SEND RQ: busy <<<<<<<<<<<<<<<<<<<<<<<'   # THIS SHOULD NOT HAPPEN - PX4 SATCOM DRIVER SHOULD WAIT FOR PREVIOUS COMMAND REPLY
			self.sendMsgToPX4(0x01, chr(0x01))

		self.serialLock.release()


	def satcomReceiveRequest(self):
		self.serialLock.acquire()

		if self.status == SatcomStatus.idle:
			#print 'RCV RQ: pending'
			self.status = SatcomStatus.receiving
			self.serialTime = time()

		else:
			print 'RCV RQ: busy <<<<<<<<<<<<<<<<<<<<<<<'    # THIS SHOULD NOT HAPPEN - PX4 SATCOM DRIVER SHOULD WAIT FOR PREVIOUS COMMAND REPLY
			self.sendMsgToPX4(0x02, chr(0x01))

		self.serialLock.release()


	def satcomGetNetworkStatus(self):
		self.serialLock.acquire()

		self.sendMsgToPX4(0x05, chr(0x00) + chr(0x01))

		self.serialLock.release()


	def satcomGetSignalStrength(self):
		self.serialLock.acquire()

		self.sendMsgToPX4(0x06, chr(0x00) + chr(0x05))

		self.serialLock.release()


	def sendMsgToPX4(self, id, data):
		msg = [0x5B, 0, 0, 0]
		msg[1] = (id)
		msg[2] = (len(data)/256)
		msg[3] = (len(data)%256)
		msg += data
		data = bytes(bytearray(msg))
		self.serialInterface.write(data)
Exemple #3
0
class AqiMonitor(service.Service):
    '''
    AQI monitor service.

    '''
    name = 'aqi_monitor'

    sensor_reconnect_timeout = 5

    def __init__(self,
                 aqi_storage,
                 sensor_device,
                 sensor_baudrate,
                 poll_period,
                 debug=False):
        self.debug = debug
        self.sensor = None
        self.sensor_device = sensor_device
        self.sensor_baudrate = sensor_baudrate
        self.poll_period = poll_period
        self.pm_timestamp = None
        self.pm_25 = None
        self.pm_10 = None
        self.aqi_storage = aqi_storage
        self.listeners = []

    def startService(self):
        self._bot = self.parent.getServiceNamed(TelegramBot.name)
        reactor.callLater(0, self.connect_sensor)  # @UndefinedVariable

    def add_listener(self, listener):
        if listener not in self.listeners:
            self.listeners.append(listener)

    def connect_sensor(self):
        self.sensor = Sds011(self, debug=self.debug)
        try:
            self.serial_port = SerialPort(self.sensor,
                                          self.sensor_device,
                                          reactor,
                                          baudrate=self.sensor_baudrate)
            self.serial_port.flushInput()
        except SerialException as se:
            log.error("Can't connect to sensor: %s" % se)
            reactor.callLater(
                self.sensor_reconnect_timeout,  # @UndefinedVariable
                self.connect_sensor)

    @defer.inlineCallbacks
    def init_sensor(self):
        yield self.sensor.query_data()
        period = yield self.sensor.set_working_period(self.poll_period)
        if self.debug:
            log.debug("Sensor initialized, poll period set to %d minute(s)" %
                      period)

    def sensor_connected(self):
        log.info("Connected to sensor")
        reactor.callLater(1, self.init_sensor)  # @UndefinedVariable

    def sensor_disconnected(self, reason):
        log.warn("Disconnected from sensor, reason: %r" % reason)
        reactor.callLater(self.sensor_reconnect_timeout,
                          self.connect_sensor)  # @UndefinedVariable

    def sensor_data(self, pm_25, pm_10):
        if pm_25 <= 0 or pm_10 <= 0:  # could be at sensor startup
            log.warn("Ignore invalid sensor data: PM2.5: %.1f, PM10: %.1f" %
                     (pm_25, pm_10))
            return
        log.info("Sensor data received, PM2.5: %.1f, PM10: %.1f" %
                 (pm_25, pm_10))
        self.pm_25 = pm_25
        self.pm_10 = pm_10
        self.pm_timestamp = time.time()
        self.aqi_storage.add_pm_data(int(self.pm_timestamp), pm_25, pm_10)
        for listener in self.listeners:
            try:
                listener.pm_data_updated(pm_25, pm_10, self.aqi)
            except Exception:
                log.failure("Can't notify PM data listener {listener}",
                            listener=listener)

    @property
    def sensor_firmware_version(self):
        if self.sensor is None or not self.sensor.connected:
            raise SensorDisconnected(
                "Can't get sensor firmware version: sensor not connected")
        return self.sensor.get_firmware_version()

    @staticmethod
    def to_aqi_level(aqi):
        if aqi <= 50:
            return 0  # Good
        elif aqi <= 100:
            return 1  # Moderate
        elif aqi <= 150:
            return 2  # Unhealthy for Sensitive Groups
        elif aqi <= 200:
            return 3  # Unhealthy
        elif aqi <= 300:
            return 4  # Very Unhealthy
        return 5  # Hazardous

    @property
    def aqi_level(self):
        if self.pm_timestamp is None:
            return None
        return self.to_aqi_level(self.aqi)

    @property
    def aqi(self):
        if self.pm_timestamp is None:
            return None
        return aqi_calc.to_aqi([(aqi_calc.POLLUTANT_PM25, self.pm_25),
                                (aqi_calc.POLLUTANT_PM10, self.pm_10)])

    @property
    def pm(self):
        return self.pm_25, self.pm_10