diff --git a/lib/nmeaTransceiver.py b/lib/nmeaTransceiver.py new file mode 100755 index 0000000..bcfbaf6 --- /dev/null +++ b/lib/nmeaTransceiver.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 + +import asyncio, socket, sys, functools, os, signal +from nmea0183 import NMEA0183 + +class NmeaTransceiver: + "NMEA0183 transceiver. Connects to a server and sends/receives sentenses" + + __port = None + __host = None + __s = None + __loop = None + __NMEA = None + RECV_BUFFER = 4096 # Advisable to keep it as an exponent of 2 + + def __init__(self, argv): + if(len(argv) < 2): + print("Usage : " + argv[0] + " port [IP]") + sys.exit() + self.__port = int(argv[1]) + if len(argv) == 3: + self.__host = argv[2] + else: + self.__host = "0.0.0.0" + self.__connect() + self.__createLoop() + + def __connect(self): + print("Connecting to server (" + self.__host + ":" + str(self.__port) + ")") + try: + self.__s = socket.socket() + self.__s.connect((self.__host,self.__port)) + except: + print("Error while connecting.") + sys.exit() + + def __createLoop(self): + self.__loop = asyncio.get_event_loop() + + def addReader(self, rFunction): + self.__loop.add_reader(self.__s, self.__doReading, self.__s, rFunction) + + def __doReading(self, rSocket, rFunction): + data = rSocket.recv(self.RECV_BUFFER).decode() + sentences = data.splitlines() + for sentence in sentences: + rFunction(sentence) + + def addNmeaFilteringReader(self, fFunction, fTalkerIdPattern, fSentencePattern): + self.__NMEA = NMEA0183() + self.__loop.add_reader(self.__s, self.__doFiltering, self.__s, fTalkerIdPattern, fSentencePattern, fFunction) + + def __doFiltering(self, fSocket, fTalkerIdPattern, fSentencePattern, fFunction): + data = fSocket.recv(self.RECV_BUFFER).decode() + sentences = data.splitlines() + for sentence in sentences: + self.__NMEA.fromString(sentence) + if self.__NMEA.applyFilter(fTalkerIdPattern, fSentencePattern): + fFunction(sentence) + + def __removeReader(self): + self.remove_reader(self.__s) + + def startTransceiver(self): + for signame in ('SIGINT', 'SIGTERM'): + self.__loop.add_signal_handler(getattr(signal, signame), self.stopTransceiver, signame) + print("Connected. Press Ctrl-C to quit.") + self.__loop.run_forever() + + def stopTransceiver(self, signame): + print("Received signal %s: exit" % signame) + try: + self.__removeReader() + except Exception: + pass + sys.exit() + + def callLater(self, cFunction, repeatDelay = None): + self.__loop.call_later(repeatDelay, self.__doSending, self.__s, cFunction, repeatDelay) + + def callSoon(self, cFunction, repeatDelay = None): + self.__loop.call_soon(self.__doSending, self.__s, cFunction, repeatDelay) + + def __doSending(self, wSocket, wFunction, repeatDelay): + data = wFunction() + wSocket.send(data.encode()) + if repeatDelay != None: + self.callLater(wFunction, repeatDelay) + + def asyncSleep(self, duration): + yield from asyncio.sleep(duration) + +# +# Code for testing class +# + +if __name__ == '__main__': + + class TestBoat: + "Test boat that receives DPT and sends DPT..." + + __NT = None + + def __reader(self, nmeaSentence): + print("Boat received (after filtering): %s" % nmeaSentence) + + def __writer(self): + sentence = "!PODPT,HELLO*FF" + print("Boat sent: "+sentence) + return sentence + + def __init__(self): + self.__NT = NmeaTransceiver(sys.argv) + self.__NT.addNmeaFilteringReader(self.__reader, '', 'DPT') + self.__NT.callSoon(self.__writer,2) + + def startBoat(self): + self.__NT.startTransceiver() + + TB = TestBoat() + TB.startBoat() + +# EOF