kopia lustrzana https://github.com/glidernet/python-ogn-client
AprsClient now be used asynchronously/concurrently/with asyncio.
rodzic
b0f3333fd0
commit
94dbe5302c
73
README.md
73
README.md
|
@ -30,12 +30,16 @@ beacon = parse("FLRDDDEAD>APRS,qAS,EDER:/114500h5029.86N/00956.98E'342/049/A=005
|
||||||
reference_timestamp=datetime(2015, 7, 31, 12, 34, 56))
|
reference_timestamp=datetime(2015, 7, 31, 12, 34, 56))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Connect to OGN and display all incoming beacons.
|
### Simple Example:
|
||||||
|
Connect to OGN and display all incoming beacons.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from ogn.client import AprsClient
|
from ogn.client import AprsClient
|
||||||
from ogn.parser import parse, ParseError
|
from ogn.parser import parse, ParseError
|
||||||
|
|
||||||
|
|
||||||
def process_beacon(raw_message):
|
def process_beacon(raw_message):
|
||||||
try:
|
try:
|
||||||
beacon = parse(raw_message)
|
beacon = parse(raw_message)
|
||||||
|
@ -45,16 +49,69 @@ def process_beacon(raw_message):
|
||||||
except NotImplementedError as e:
|
except NotImplementedError as e:
|
||||||
print('{}: {}'.format(e, raw_message))
|
print('{}: {}'.format(e, raw_message))
|
||||||
|
|
||||||
client = AprsClient(aprs_user='N0CALL')
|
|
||||||
client.connect()
|
|
||||||
|
|
||||||
try:
|
async def run_aprs():
|
||||||
client.run(callback=process_beacon, autoreconnect=True)
|
client = AprsClient(aprs_user='N0CALL')
|
||||||
except KeyboardInterrupt:
|
await client.connect()
|
||||||
print('\nStop ogn gateway')
|
await client.run(callback=process_beacon, autoreconnect=True)
|
||||||
client.disconnect()
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
asyncio.run(run_aprs())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print('\nStop ogn gateway')
|
||||||
|
# await client.disconnect()
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Concurrent Example:
|
||||||
|
Same as above, but run concurrently run your custom long running function:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from ogn.client import AprsClient
|
||||||
|
from ogn.parser import parse, ParseError
|
||||||
|
|
||||||
|
|
||||||
|
def process_beacon(raw_message):
|
||||||
|
try:
|
||||||
|
beacon = parse(raw_message)
|
||||||
|
print('Received {aprs_type}: {raw_message}'.format(**beacon))
|
||||||
|
except ParseError as e:
|
||||||
|
print('Error, {}'.format(e.message))
|
||||||
|
except NotImplementedError as e:
|
||||||
|
print('{}: {}'.format(e, raw_message))
|
||||||
|
|
||||||
|
|
||||||
|
async def run_aprs():
|
||||||
|
client = AprsClient(aprs_user='N0CALL')
|
||||||
|
await client.connect()
|
||||||
|
await client.run(callback=process_beacon, autoreconnect=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_another_long_running_function():
|
||||||
|
import datetime
|
||||||
|
while True:
|
||||||
|
print(f'The time is {datetime.datetime.now()}')
|
||||||
|
await asyncio.sleep(10)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
await asyncio.gather(run_aprs(), run_another_long_running_function())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
asyncio.run(main())
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Connect to telnet console and display all decoded beacons.
|
### Connect to telnet console and display all decoded beacons.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import asyncio
|
||||||
import socket
|
import socket
|
||||||
import logging
|
import logging
|
||||||
from time import time, sleep
|
from time import time, sleep
|
||||||
|
@ -24,26 +25,34 @@ class AprsClient:
|
||||||
self._sock_peer_ip = None
|
self._sock_peer_ip = None
|
||||||
self._kill = False
|
self._kill = False
|
||||||
|
|
||||||
def connect(self, retries=1, wait_period=15):
|
self.reader = None
|
||||||
|
self.writer = None
|
||||||
|
|
||||||
|
async def connect(self, retries=1, wait_period=15):
|
||||||
# create socket, connect to server, login and make a file object associated with the socket
|
# create socket, connect to server, login and make a file object associated with the socket
|
||||||
while retries > 0:
|
while retries > 0:
|
||||||
retries -= 1
|
retries -= 1
|
||||||
try:
|
try:
|
||||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
#self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
#self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
||||||
self.sock.settimeout(5)
|
#self.sock.settimeout(5)
|
||||||
|
|
||||||
if self.aprs_filter:
|
if self.aprs_filter:
|
||||||
port = self.settings.APRS_SERVER_PORT_CLIENT_DEFINED_FILTERS
|
port = self.settings.APRS_SERVER_PORT_CLIENT_DEFINED_FILTERS
|
||||||
else:
|
else:
|
||||||
port = self.settings.APRS_SERVER_PORT_FULL_FEED
|
port = self.settings.APRS_SERVER_PORT_FULL_FEED
|
||||||
|
|
||||||
self.sock.connect((self.settings.APRS_SERVER_HOST, port))
|
# self.sock.connect((self.settings.APRS_SERVER_HOST, port))
|
||||||
self._sock_peer_ip = self.sock.getpeername()[0]
|
self.reader, self.writer = await asyncio.open_connection(self.settings.APRS_SERVER_HOST, port)
|
||||||
|
# self._sock_peer_ip = self.sock.getpeername()[0]
|
||||||
|
if (sock := self.writer.get_extra_info('socket')):
|
||||||
|
self._sock_peer_ip = sock.getpeername()[0]
|
||||||
|
|
||||||
login = create_aprs_login(self.aprs_user, -1, self.settings.APRS_APP_NAME, self.settings.APRS_APP_VER, self.aprs_filter)
|
login = create_aprs_login(self.aprs_user, -1, self.settings.APRS_APP_NAME, self.settings.APRS_APP_VER, self.aprs_filter)
|
||||||
self.sock.send(login.encode())
|
#self.sock.send(login.encode())
|
||||||
self.sock_file = self.sock.makefile('rb')
|
self.writer.write(login.encode())
|
||||||
|
await self.writer.drain()
|
||||||
|
#self.sock_file = self.sock.makefile('rb')
|
||||||
|
|
||||||
self._kill = False
|
self._kill = False
|
||||||
self.logger.info("Connect to OGN ({}/{}:{}) as {} with filter: {}".
|
self.logger.info("Connect to OGN ({}/{}:{}) as {} with filter: {}".
|
||||||
|
@ -59,18 +68,20 @@ class AprsClient:
|
||||||
self._kill = True
|
self._kill = True
|
||||||
self.logger.critical('Could not connect to OGN.')
|
self.logger.critical('Could not connect to OGN.')
|
||||||
|
|
||||||
def disconnect(self):
|
async def disconnect(self):
|
||||||
self.logger.info('Disconnect from {}'.format(self._sock_peer_ip))
|
self.logger.info('Disconnect from {}'.format(self._sock_peer_ip))
|
||||||
try:
|
try:
|
||||||
# close everything
|
# close everything
|
||||||
self.sock.shutdown(0)
|
# self.sock.shutdown(0)
|
||||||
self.sock.close()
|
# self.sock.close()
|
||||||
|
self.writer.close()
|
||||||
|
await self.writer.wait_closed()
|
||||||
except OSError:
|
except OSError:
|
||||||
self.logger.error('Socket close error')
|
self.logger.error('Socket close error')
|
||||||
|
|
||||||
self._kill = True
|
self._kill = True
|
||||||
|
|
||||||
def run(self, callback, timed_callback=lambda client: None, autoreconnect=False, ignore_decoding_error=True,
|
async def run(self, callback, timed_callback=lambda client: None, autoreconnect=False, ignore_decoding_error=True,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
while not self._kill:
|
while not self._kill:
|
||||||
try:
|
try:
|
||||||
|
@ -78,13 +89,16 @@ class AprsClient:
|
||||||
while not self._kill:
|
while not self._kill:
|
||||||
if time() - keepalive_time > self.settings.APRS_KEEPALIVE_TIME:
|
if time() - keepalive_time > self.settings.APRS_KEEPALIVE_TIME:
|
||||||
self.logger.info('Send keepalive to {}'.format(self._sock_peer_ip))
|
self.logger.info('Send keepalive to {}'.format(self._sock_peer_ip))
|
||||||
self.sock.send('#keepalive\n'.encode())
|
#self.sock.send('#keepalive\n'.encode())
|
||||||
|
self.writer.write('#keepalive\n'.encode())
|
||||||
|
await self.writer.drain()
|
||||||
timed_callback(self)
|
timed_callback(self)
|
||||||
keepalive_time = time()
|
keepalive_time = time()
|
||||||
|
|
||||||
# Read packet string from socket
|
# Read packet string from socket
|
||||||
packet_b = self.sock_file.readline().strip()
|
#packet_b = self.sock_file.readline().strip()
|
||||||
packet_str = packet_b.decode(errors="replace") if ignore_decoding_error else packet_b.decode()
|
packet_b = await self.reader.readline()
|
||||||
|
packet_str = packet_b.strip().decode(errors="replace") if ignore_decoding_error else packet_b.decode()
|
||||||
|
|
||||||
# A zero length line should not be return if keepalives are being sent
|
# A zero length line should not be return if keepalives are being sent
|
||||||
# A zero length line will only be returned after ~30m if keepalives are not sent
|
# A zero length line will only be returned after ~30m if keepalives are not sent
|
||||||
|
@ -103,7 +117,7 @@ class AprsClient:
|
||||||
self.logger.debug(packet_b)
|
self.logger.debug(packet_b)
|
||||||
|
|
||||||
if autoreconnect and not self._kill:
|
if autoreconnect and not self._kill:
|
||||||
self.connect(retries=100)
|
await self.connect(retries=100)
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue