aprsd 4.0.2__py3-none-any.whl → 4.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aprsd/cli_helper.py +36 -35
- aprsd/client/base.py +14 -11
- aprsd/client/drivers/aprsis.py +87 -35
- aprsd/client/drivers/kiss.py +28 -5
- aprsd/client/kiss.py +1 -0
- aprsd/cmds/listen.py +84 -91
- aprsd/cmds/send_message.py +30 -28
- aprsd/cmds/server.py +29 -64
- aprsd/conf/common.py +100 -101
- aprsd/conf/log.py +32 -22
- aprsd/log/log.py +31 -18
- aprsd/main.py +22 -22
- aprsd/packets/__init__.py +6 -0
- aprsd/packets/core.py +5 -2
- aprsd/packets/filter.py +58 -0
- aprsd/packets/filters/__init__.py +0 -0
- aprsd/packets/filters/dupe_filter.py +68 -0
- aprsd/packets/filters/packet_type.py +53 -0
- aprsd/packets/packet_list.py +33 -27
- aprsd/plugin.py +52 -52
- aprsd/plugin_utils.py +20 -21
- aprsd/plugins/weather.py +110 -109
- aprsd/threads/__init__.py +1 -2
- aprsd/threads/rx.py +83 -75
- aprsd/threads/service.py +42 -0
- aprsd/threads/stats.py +4 -9
- aprsd/utils/objectstore.py +12 -13
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/METADATA +22 -20
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/RECORD +34 -29
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/WHEEL +1 -1
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/AUTHORS +0 -0
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/LICENSE +0 -0
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/entry_points.txt +0 -0
- {aprsd-4.0.2.dist-info → aprsd-4.1.1.dist-info}/top_level.txt +0 -0
aprsd/plugin_utils.py
CHANGED
@@ -4,21 +4,20 @@ import logging
|
|
4
4
|
|
5
5
|
import requests
|
6
6
|
|
7
|
-
|
8
|
-
LOG = logging.getLogger("APRSD")
|
7
|
+
LOG = logging.getLogger('APRSD')
|
9
8
|
|
10
9
|
|
11
10
|
def get_aprs_fi(api_key, callsign):
|
12
11
|
LOG.debug(f"Fetch aprs.fi location for '{callsign}'")
|
13
12
|
try:
|
14
13
|
url = (
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
'http://api.aprs.fi/api/get?&what=loc&apikey={}&format=json&name={}'.format(
|
15
|
+
api_key, callsign
|
16
|
+
)
|
18
17
|
)
|
19
18
|
response = requests.get(url)
|
20
|
-
except Exception:
|
21
|
-
raise Exception(
|
19
|
+
except Exception as e:
|
20
|
+
raise Exception('Failed to get aprs.fi location') from e
|
22
21
|
else:
|
23
22
|
response.raise_for_status()
|
24
23
|
return json.loads(response.text)
|
@@ -26,22 +25,22 @@ def get_aprs_fi(api_key, callsign):
|
|
26
25
|
|
27
26
|
def get_weather_gov_for_gps(lat, lon):
|
28
27
|
# FIXME(hemna) This is currently BROKEN
|
29
|
-
LOG.debug(f
|
28
|
+
LOG.debug(f'Fetch station at {lat}, {lon}')
|
30
29
|
headers = requests.utils.default_headers()
|
31
30
|
headers.update(
|
32
|
-
{
|
31
|
+
{'User-Agent': '(aprsd, waboring@hemna.com)'},
|
33
32
|
)
|
34
33
|
try:
|
35
34
|
url2 = (
|
36
|
-
|
37
|
-
|
35
|
+
'https://forecast.weather.gov/MapClick.php?lat=%s'
|
36
|
+
'&lon=%s&FcstType=json' % (lat, lon)
|
38
37
|
# f"https://api.weather.gov/points/{lat},{lon}"
|
39
38
|
)
|
40
39
|
LOG.debug(f"Fetching weather '{url2}'")
|
41
40
|
response = requests.get(url2, headers=headers)
|
42
41
|
except Exception as e:
|
43
42
|
LOG.error(e)
|
44
|
-
raise Exception(
|
43
|
+
raise Exception('Failed to get weather') from e
|
45
44
|
else:
|
46
45
|
response.raise_for_status()
|
47
46
|
return json.loads(response.text)
|
@@ -50,25 +49,25 @@ def get_weather_gov_for_gps(lat, lon):
|
|
50
49
|
def get_weather_gov_metar(station):
|
51
50
|
LOG.debug(f"Fetch metar for station '{station}'")
|
52
51
|
try:
|
53
|
-
url =
|
52
|
+
url = 'https://api.weather.gov/stations/{}/observations/latest'.format(
|
54
53
|
station,
|
55
54
|
)
|
56
55
|
response = requests.get(url)
|
57
|
-
except Exception:
|
58
|
-
raise Exception(
|
56
|
+
except Exception as e:
|
57
|
+
raise Exception('Failed to fetch metar') from e
|
59
58
|
else:
|
60
59
|
response.raise_for_status()
|
61
60
|
return json.loads(response)
|
62
61
|
|
63
62
|
|
64
|
-
def fetch_openweathermap(api_key, lat, lon, units=
|
65
|
-
LOG.debug(f
|
63
|
+
def fetch_openweathermap(api_key, lat, lon, units='metric', exclude=None):
|
64
|
+
LOG.debug(f'Fetch openweathermap for {lat}, {lon}')
|
66
65
|
if not exclude:
|
67
|
-
exclude =
|
66
|
+
exclude = 'minutely,hourly,daily,alerts'
|
68
67
|
try:
|
69
68
|
url = (
|
70
|
-
|
71
|
-
|
69
|
+
'https://api.openweathermap.org/data/2.5/onecall?'
|
70
|
+
'lat={}&lon={}&appid={}&units={}&exclude={}'.format(
|
72
71
|
lat,
|
73
72
|
lon,
|
74
73
|
api_key,
|
@@ -80,7 +79,7 @@ def fetch_openweathermap(api_key, lat, lon, units="metric", exclude=None):
|
|
80
79
|
response = requests.get(url)
|
81
80
|
except Exception as e:
|
82
81
|
LOG.error(e)
|
83
|
-
raise Exception(
|
82
|
+
raise Exception('Failed to get weather') from e
|
84
83
|
else:
|
85
84
|
response.raise_for_status()
|
86
85
|
return json.loads(response.text)
|
aprsd/plugins/weather.py
CHANGED
@@ -9,7 +9,7 @@ from aprsd import plugin, plugin_utils
|
|
9
9
|
from aprsd.utils import trace
|
10
10
|
|
11
11
|
CONF = cfg.CONF
|
12
|
-
LOG = logging.getLogger(
|
12
|
+
LOG = logging.getLogger('APRSD')
|
13
13
|
|
14
14
|
|
15
15
|
class USWeatherPlugin(plugin.APRSDRegexCommandPluginBase, plugin.APRSFIKEYMixin):
|
@@ -26,22 +26,22 @@ class USWeatherPlugin(plugin.APRSDRegexCommandPluginBase, plugin.APRSFIKEYMixin)
|
|
26
26
|
"""
|
27
27
|
|
28
28
|
# command_regex = r"^([w][x]|[w][x]\s|weather)"
|
29
|
-
command_regex = r
|
29
|
+
command_regex = r'^[wW]'
|
30
30
|
|
31
|
-
command_name =
|
32
|
-
short_description =
|
31
|
+
command_name = 'USWeather'
|
32
|
+
short_description = 'Provide USA only weather of GPS Beacon location'
|
33
33
|
|
34
34
|
def setup(self):
|
35
35
|
self.ensure_aprs_fi_key()
|
36
36
|
|
37
37
|
@trace.trace
|
38
38
|
def process(self, packet):
|
39
|
-
LOG.info(
|
39
|
+
LOG.info('Weather Plugin')
|
40
40
|
fromcall = packet.from_call
|
41
|
-
message = packet.get(
|
41
|
+
message = packet.get('message_text', None)
|
42
42
|
# message = packet.get("message_text", None)
|
43
43
|
# ack = packet.get("msgNo", "0")
|
44
|
-
a = re.search(r
|
44
|
+
a = re.search(r'^.*\s+(.*)', message)
|
45
45
|
if a is not None:
|
46
46
|
searchcall = a.group(1)
|
47
47
|
searchcall = searchcall.upper()
|
@@ -51,34 +51,34 @@ class USWeatherPlugin(plugin.APRSDRegexCommandPluginBase, plugin.APRSFIKEYMixin)
|
|
51
51
|
try:
|
52
52
|
aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall)
|
53
53
|
except Exception as ex:
|
54
|
-
LOG.error(f
|
55
|
-
return
|
54
|
+
LOG.error(f'Failed to fetch aprs.fi data {ex}')
|
55
|
+
return 'Failed to fetch aprs.fi location'
|
56
56
|
|
57
|
-
LOG.debug(f
|
58
|
-
if not len(aprs_data[
|
57
|
+
LOG.debug(f'LocationPlugin: aprs_data = {aprs_data}')
|
58
|
+
if not len(aprs_data['entries']):
|
59
59
|
LOG.error("Didn't get any entries from aprs.fi")
|
60
|
-
return
|
60
|
+
return 'Failed to fetch aprs.fi location'
|
61
61
|
|
62
|
-
lat = aprs_data[
|
63
|
-
lon = aprs_data[
|
62
|
+
lat = aprs_data['entries'][0]['lat']
|
63
|
+
lon = aprs_data['entries'][0]['lng']
|
64
64
|
|
65
65
|
try:
|
66
66
|
wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon)
|
67
67
|
except Exception as ex:
|
68
68
|
LOG.error(f"Couldn't fetch forecast.weather.gov '{ex}'")
|
69
|
-
return
|
69
|
+
return 'Unable to get weather'
|
70
70
|
|
71
|
-
LOG.info(f
|
71
|
+
LOG.info(f'WX data {wx_data}')
|
72
72
|
|
73
73
|
reply = (
|
74
|
-
|
74
|
+
'%sF(%sF/%sF) %s. %s, %s.'
|
75
75
|
% (
|
76
|
-
wx_data[
|
77
|
-
wx_data[
|
78
|
-
wx_data[
|
79
|
-
wx_data[
|
80
|
-
wx_data[
|
81
|
-
wx_data[
|
76
|
+
wx_data['currentobservation']['Temp'],
|
77
|
+
wx_data['data']['temperature'][0],
|
78
|
+
wx_data['data']['temperature'][1],
|
79
|
+
wx_data['data']['weather'][0],
|
80
|
+
wx_data['time']['startPeriodName'][1],
|
81
|
+
wx_data['data']['weather'][1],
|
82
82
|
)
|
83
83
|
).rstrip()
|
84
84
|
LOG.debug(f"reply: '{reply}' ")
|
@@ -100,31 +100,31 @@ class USMetarPlugin(plugin.APRSDRegexCommandPluginBase, plugin.APRSFIKEYMixin):
|
|
100
100
|
|
101
101
|
"""
|
102
102
|
|
103
|
-
command_regex = r
|
104
|
-
command_name =
|
105
|
-
short_description =
|
103
|
+
command_regex = r'^([m]|[M]|[m]\s|metar)'
|
104
|
+
command_name = 'USMetar'
|
105
|
+
short_description = 'USA only METAR of GPS Beacon location'
|
106
106
|
|
107
107
|
def setup(self):
|
108
108
|
self.ensure_aprs_fi_key()
|
109
109
|
|
110
110
|
@trace.trace
|
111
111
|
def process(self, packet):
|
112
|
-
fromcall = packet.get(
|
113
|
-
message = packet.get(
|
112
|
+
fromcall = packet.get('from')
|
113
|
+
message = packet.get('message_text', None)
|
114
114
|
# ack = packet.get("msgNo", "0")
|
115
115
|
LOG.info(f"WX Plugin '{message}'")
|
116
|
-
a = re.search(r
|
116
|
+
a = re.search(r'^.*\s+(.*)', message)
|
117
117
|
if a is not None:
|
118
118
|
searchcall = a.group(1)
|
119
119
|
station = searchcall.upper()
|
120
120
|
try:
|
121
121
|
resp = plugin_utils.get_weather_gov_metar(station)
|
122
122
|
except Exception as e:
|
123
|
-
LOG.debug(f
|
124
|
-
reply =
|
123
|
+
LOG.debug(f'Weather failed with: {str(e)}')
|
124
|
+
reply = 'Unable to find station METAR'
|
125
125
|
else:
|
126
126
|
station_data = json.loads(resp.text)
|
127
|
-
reply = station_data[
|
127
|
+
reply = station_data['properties']['rawMessage']
|
128
128
|
|
129
129
|
return reply
|
130
130
|
else:
|
@@ -136,36 +136,36 @@ class USMetarPlugin(plugin.APRSDRegexCommandPluginBase, plugin.APRSFIKEYMixin):
|
|
136
136
|
try:
|
137
137
|
aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall)
|
138
138
|
except Exception as ex:
|
139
|
-
LOG.error(f
|
140
|
-
return
|
139
|
+
LOG.error(f'Failed to fetch aprs.fi data {ex}')
|
140
|
+
return 'Failed to fetch aprs.fi location'
|
141
141
|
|
142
142
|
# LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data))
|
143
|
-
if not len(aprs_data[
|
144
|
-
LOG.error(
|
145
|
-
return
|
143
|
+
if not len(aprs_data['entries']):
|
144
|
+
LOG.error('Found no entries from aprs.fi!')
|
145
|
+
return 'Failed to fetch aprs.fi location'
|
146
146
|
|
147
|
-
lat = aprs_data[
|
148
|
-
lon = aprs_data[
|
147
|
+
lat = aprs_data['entries'][0]['lat']
|
148
|
+
lon = aprs_data['entries'][0]['lng']
|
149
149
|
|
150
150
|
try:
|
151
151
|
wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon)
|
152
152
|
except Exception as ex:
|
153
153
|
LOG.error(f"Couldn't fetch forecast.weather.gov '{ex}'")
|
154
|
-
return
|
154
|
+
return 'Unable to metar find station.'
|
155
155
|
|
156
|
-
if wx_data[
|
157
|
-
station = wx_data[
|
156
|
+
if wx_data['location']['metar']:
|
157
|
+
station = wx_data['location']['metar']
|
158
158
|
try:
|
159
159
|
resp = plugin_utils.get_weather_gov_metar(station)
|
160
160
|
except Exception as e:
|
161
|
-
LOG.debug(f
|
162
|
-
reply =
|
161
|
+
LOG.debug(f'Weather failed with: {str(e)}')
|
162
|
+
reply = 'Failed to get Metar'
|
163
163
|
else:
|
164
164
|
station_data = json.loads(resp.text)
|
165
|
-
reply = station_data[
|
165
|
+
reply = station_data['properties']['rawMessage']
|
166
166
|
else:
|
167
167
|
# Couldn't find a station
|
168
|
-
reply =
|
168
|
+
reply = 'No Metar station found'
|
169
169
|
|
170
170
|
return reply
|
171
171
|
|
@@ -190,35 +190,36 @@ class OWMWeatherPlugin(plugin.APRSDRegexCommandPluginBase):
|
|
190
190
|
"""
|
191
191
|
|
192
192
|
# command_regex = r"^([w][x]|[w][x]\s|weather)"
|
193
|
-
command_regex = r
|
193
|
+
command_regex = r'^[wW]'
|
194
194
|
|
195
|
-
command_name =
|
196
|
-
short_description =
|
195
|
+
command_name = 'OpenWeatherMap'
|
196
|
+
short_description = 'OpenWeatherMap weather of GPS Beacon location'
|
197
197
|
|
198
198
|
def setup(self):
|
199
199
|
if not CONF.owm_weather_plugin.apiKey:
|
200
|
-
LOG.error(
|
200
|
+
LOG.error('Config.owm_weather_plugin.apiKey is not set. Disabling')
|
201
201
|
self.enabled = False
|
202
202
|
else:
|
203
203
|
self.enabled = True
|
204
204
|
|
205
205
|
def help(self):
|
206
206
|
_help = [
|
207
|
-
|
207
|
+
'openweathermap: Send {} to get weather from your location'.format(
|
208
|
+
self.command_regex
|
209
|
+
),
|
210
|
+
'openweathermap: Send {} <callsign> to get weather from <callsign>'.format(
|
208
211
|
self.command_regex
|
209
212
|
),
|
210
|
-
"openweathermap: Send {} <callsign> to get "
|
211
|
-
"weather from <callsign>".format(self.command_regex),
|
212
213
|
]
|
213
214
|
return _help
|
214
215
|
|
215
216
|
@trace.trace
|
216
217
|
def process(self, packet):
|
217
|
-
fromcall = packet.get(
|
218
|
-
message = packet.get(
|
218
|
+
fromcall = packet.get('from_call')
|
219
|
+
message = packet.get('message_text', None)
|
219
220
|
# ack = packet.get("msgNo", "0")
|
220
221
|
LOG.info(f"OWMWeather Plugin '{message}'")
|
221
|
-
a = re.search(r
|
222
|
+
a = re.search(r'^.*\s+(.*)', message)
|
222
223
|
if a is not None:
|
223
224
|
searchcall = a.group(1)
|
224
225
|
searchcall = searchcall.upper()
|
@@ -230,16 +231,16 @@ class OWMWeatherPlugin(plugin.APRSDRegexCommandPluginBase):
|
|
230
231
|
try:
|
231
232
|
aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall)
|
232
233
|
except Exception as ex:
|
233
|
-
LOG.error(f
|
234
|
-
return
|
234
|
+
LOG.error(f'Failed to fetch aprs.fi data {ex}')
|
235
|
+
return 'Failed to fetch location'
|
235
236
|
|
236
237
|
# LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data))
|
237
|
-
if not len(aprs_data[
|
238
|
-
LOG.error(
|
239
|
-
return
|
238
|
+
if not len(aprs_data['entries']):
|
239
|
+
LOG.error('Found no entries from aprs.fi!')
|
240
|
+
return 'Failed to fetch location'
|
240
241
|
|
241
|
-
lat = aprs_data[
|
242
|
-
lon = aprs_data[
|
242
|
+
lat = aprs_data['entries'][0]['lat']
|
243
|
+
lon = aprs_data['entries'][0]['lng']
|
243
244
|
|
244
245
|
units = CONF.units
|
245
246
|
api_key = CONF.owm_weather_plugin.apiKey
|
@@ -249,40 +250,40 @@ class OWMWeatherPlugin(plugin.APRSDRegexCommandPluginBase):
|
|
249
250
|
lat,
|
250
251
|
lon,
|
251
252
|
units=units,
|
252
|
-
exclude=
|
253
|
+
exclude='minutely,hourly',
|
253
254
|
)
|
254
255
|
except Exception as ex:
|
255
256
|
LOG.error(f"Couldn't fetch openweathermap api '{ex}'")
|
256
257
|
# default to UTC
|
257
|
-
return
|
258
|
+
return 'Unable to get weather'
|
258
259
|
|
259
|
-
if units ==
|
260
|
-
degree =
|
260
|
+
if units == 'metric':
|
261
|
+
degree = 'C'
|
261
262
|
else:
|
262
|
-
degree =
|
263
|
+
degree = 'F'
|
263
264
|
|
264
|
-
if
|
265
|
-
wind =
|
266
|
-
wx_data[
|
267
|
-
wx_data[
|
268
|
-
wx_data[
|
265
|
+
if 'wind_gust' in wx_data['current']:
|
266
|
+
wind = '{:.0f}@{}G{:.0f}'.format(
|
267
|
+
wx_data['current']['wind_speed'],
|
268
|
+
wx_data['current']['wind_deg'],
|
269
|
+
wx_data['current']['wind_gust'],
|
269
270
|
)
|
270
271
|
else:
|
271
|
-
wind =
|
272
|
-
wx_data[
|
273
|
-
wx_data[
|
272
|
+
wind = '{:.0f}@{}'.format(
|
273
|
+
wx_data['current']['wind_speed'],
|
274
|
+
wx_data['current']['wind_deg'],
|
274
275
|
)
|
275
276
|
|
276
277
|
# LOG.debug(wx_data["current"])
|
277
278
|
# LOG.debug(wx_data["daily"])
|
278
|
-
reply =
|
279
|
-
wx_data[
|
280
|
-
wx_data[
|
279
|
+
reply = '{} {:.1f}{}/{:.1f}{} Wind {} {}%'.format(
|
280
|
+
wx_data['current']['weather'][0]['description'],
|
281
|
+
wx_data['current']['temp'],
|
281
282
|
degree,
|
282
|
-
wx_data[
|
283
|
+
wx_data['current']['dew_point'],
|
283
284
|
degree,
|
284
285
|
wind,
|
285
|
-
wx_data[
|
286
|
+
wx_data['current']['humidity'],
|
286
287
|
)
|
287
288
|
|
288
289
|
return reply
|
@@ -311,26 +312,26 @@ class AVWXWeatherPlugin(plugin.APRSDRegexCommandPluginBase):
|
|
311
312
|
docker build -f Dockerfile -t avwx-api:master .
|
312
313
|
"""
|
313
314
|
|
314
|
-
command_regex = r
|
315
|
-
command_name =
|
316
|
-
short_description =
|
315
|
+
command_regex = r'^([m]|[m]|[m]\s|metar)'
|
316
|
+
command_name = 'AVWXWeather'
|
317
|
+
short_description = 'AVWX weather of GPS Beacon location'
|
317
318
|
|
318
319
|
def setup(self):
|
319
320
|
if not CONF.avwx_plugin.base_url:
|
320
|
-
LOG.error(
|
321
|
+
LOG.error('Config avwx_plugin.base_url not specified. Disabling')
|
321
322
|
return False
|
322
323
|
elif not CONF.avwx_plugin.apiKey:
|
323
|
-
LOG.error(
|
324
|
+
LOG.error('Config avwx_plugin.apiKey not specified. Disabling')
|
324
325
|
return False
|
325
326
|
else:
|
326
327
|
return True
|
327
328
|
|
328
329
|
def help(self):
|
329
330
|
_help = [
|
330
|
-
|
331
|
+
'avwxweather: Send {} to get weather from your location'.format(
|
331
332
|
self.command_regex
|
332
333
|
),
|
333
|
-
|
334
|
+
'avwxweather: Send {} <callsign> to get weather from <callsign>'.format(
|
334
335
|
self.command_regex
|
335
336
|
),
|
336
337
|
]
|
@@ -338,11 +339,11 @@ class AVWXWeatherPlugin(plugin.APRSDRegexCommandPluginBase):
|
|
338
339
|
|
339
340
|
@trace.trace
|
340
341
|
def process(self, packet):
|
341
|
-
fromcall = packet.get(
|
342
|
-
message = packet.get(
|
342
|
+
fromcall = packet.get('from')
|
343
|
+
message = packet.get('message_text', None)
|
343
344
|
# ack = packet.get("msgNo", "0")
|
344
345
|
LOG.info(f"AVWXWeather Plugin '{message}'")
|
345
|
-
a = re.search(r
|
346
|
+
a = re.search(r'^.*\s+(.*)', message)
|
346
347
|
if a is not None:
|
347
348
|
searchcall = a.group(1)
|
348
349
|
searchcall = searchcall.upper()
|
@@ -353,43 +354,43 @@ class AVWXWeatherPlugin(plugin.APRSDRegexCommandPluginBase):
|
|
353
354
|
try:
|
354
355
|
aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall)
|
355
356
|
except Exception as ex:
|
356
|
-
LOG.error(f
|
357
|
-
return
|
357
|
+
LOG.error(f'Failed to fetch aprs.fi data {ex}')
|
358
|
+
return 'Failed to fetch location'
|
358
359
|
|
359
360
|
# LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data))
|
360
|
-
if not len(aprs_data[
|
361
|
-
LOG.error(
|
362
|
-
return
|
361
|
+
if not len(aprs_data['entries']):
|
362
|
+
LOG.error('Found no entries from aprs.fi!')
|
363
|
+
return 'Failed to fetch location'
|
363
364
|
|
364
|
-
lat = aprs_data[
|
365
|
-
lon = aprs_data[
|
365
|
+
lat = aprs_data['entries'][0]['lat']
|
366
|
+
lon = aprs_data['entries'][0]['lng']
|
366
367
|
|
367
368
|
api_key = CONF.avwx_plugin.apiKey
|
368
369
|
base_url = CONF.avwx_plugin.base_url
|
369
|
-
token = f
|
370
|
-
headers = {
|
370
|
+
token = f'TOKEN {api_key}'
|
371
|
+
headers = {'Authorization': token}
|
371
372
|
try:
|
372
|
-
coord = f
|
373
|
+
coord = f'{lat},{lon}'
|
373
374
|
url = (
|
374
|
-
|
375
|
-
|
375
|
+
'{}/api/station/near/{}?'
|
376
|
+
'n=1&airport=false&reporting=true&format=json'.format(base_url, coord)
|
376
377
|
)
|
377
378
|
|
378
379
|
LOG.debug(f"Get stations near me '{url}'")
|
379
380
|
response = requests.get(url, headers=headers)
|
380
381
|
except Exception as ex:
|
381
382
|
LOG.error(ex)
|
382
|
-
raise Exception(f"Failed to get the weather '{ex}'")
|
383
|
+
raise Exception(f"Failed to get the weather '{ex}'") from ex
|
383
384
|
else:
|
384
385
|
wx_data = json.loads(response.text)
|
385
386
|
|
386
387
|
# LOG.debug(wx_data)
|
387
|
-
station = wx_data[0][
|
388
|
+
station = wx_data[0]['station']['icao']
|
388
389
|
|
389
390
|
try:
|
390
391
|
url = (
|
391
|
-
|
392
|
-
|
392
|
+
'{}/api/metar/{}?options=info,translate,summary'
|
393
|
+
'&airport=true&reporting=true&format=json&onfail=cache'.format(
|
393
394
|
base_url,
|
394
395
|
station,
|
395
396
|
)
|
@@ -399,9 +400,9 @@ class AVWXWeatherPlugin(plugin.APRSDRegexCommandPluginBase):
|
|
399
400
|
response = requests.get(url, headers=headers)
|
400
401
|
except Exception as ex:
|
401
402
|
LOG.error(ex)
|
402
|
-
raise Exception(f
|
403
|
+
raise Exception(f'Failed to get metar {ex}') from ex
|
403
404
|
else:
|
404
405
|
metar_data = json.loads(response.text)
|
405
406
|
|
406
407
|
# LOG.debug(metar_data)
|
407
|
-
return metar_data[
|
408
|
+
return metar_data['raw']
|
aprsd/threads/__init__.py
CHANGED
@@ -4,9 +4,8 @@ import queue
|
|
4
4
|
# aprsd.threads
|
5
5
|
from .aprsd import APRSDThread, APRSDThreadList # noqa: F401
|
6
6
|
from .rx import ( # noqa: F401
|
7
|
-
APRSDDupeRXThread,
|
8
7
|
APRSDProcessPacketThread,
|
9
8
|
APRSDRXThread,
|
10
9
|
)
|
11
10
|
|
12
|
-
packet_queue = queue.Queue(maxsize=
|
11
|
+
packet_queue = queue.Queue(maxsize=500)
|