Skip to content

Commit

Permalink
Merge pull request #21 from joergschultzelutter/new_taf_keyword
Browse files Browse the repository at this point in the history
Support for new "TAF" keyword
  • Loading branch information
joergschultzelutter committed Mar 23, 2024
2 parents 8d387d0 + 8c0eb26 commit ec7683b
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 101 deletions.
22 changes: 13 additions & 9 deletions docs/COMMANDS/ACTION_KEYWORDS.md
Expand Up @@ -113,11 +113,11 @@ You have three options:

- specify a specific ICAO code
- specify a specific IATA code
- specify the METAR keyword, which instructs the program to look for the airport that is close to your position. That 'nearest' airport position can either be based on the user's own call sign or alternatively on a different user's call sign.
- specify the ```metar``` or the ```taf``` keyword, which instructs the program to look for the airport that is close to your position. That 'nearest' airport position can either be based on the user's own call sign or alternatively on a different user's call sign.

If the given airport or the nearest one has been found but does __not__ support METAR data, the program will try to provide you with a standard WX report for the airport's coordinates instead. If the airport is capable of providing METAR data but the METAR report cannot be retrieved, an error message is returned to the user.

Action Keyword can be combined with [date](DATE_KEYWORDS.md) / [daytime](DAYTIME_KEYWORDS.md) keyword parameters: __NO__. If WX data is returned, 'today'/'full' settings will be applied.
Action Keyword can be combined with [date](DATE_KEYWORDS.md) / [daytime](DAYTIME_KEYWORDS.md) keyword parameters: __YES__. If the user specifies the ```metar``` or the ```taf``` keyword in combination with the ```full``` keyword, the returned message will contain both METAR and TAF information. Otherwise, only the data related to the given keyword is returned (e.g. METAR data for ```metar```, TAF data for ```taf```). If WX data is returned, 'today'/'full' settings will be applied.

### ICAO METAR / wx inquiries

Expand All @@ -140,7 +140,7 @@ Get a METAR/TAF report for a specific ICAO code. If the ICAO code is valid but t

```EDDF 171150Z 02008KT 340V050 5000 -SHSNRA FEW004 SCT011CB BKN019```

```03/01 Q1023 NOSIG ### TAF EDDF 171100Z 1712/1818 02008KT 9999```
```03/01 Q1023 NOSIG ## TAF EDDF 171100Z 1712/1818 02008KT 9999```

```BKN030 TEMPO 1712/1716 SHRAGS BKN020TCU BECMG 1717/1720 FEW030```

Expand All @@ -167,24 +167,28 @@ Get a METAR/TAF report for a specific IATA code by retrieving its associated ICA

Specifying an IATA code without keyword may or may not be successful as as there is a log of ambiguity.

### METAR keyword
### METAR / TAF keywords

Get a METAR/TAF report for the nearest airport in relation to the user's own call sign or a different call sign
Get a METAR / TAF report for the nearest airport in relation to the user's own call sign or a different call sign

#### Formats

- ```metar <callsign>[-ssid]``` - metar report that is closest to the call sign's position
- ```metar``` - metar/taf report that is closest to the user's own position
- ```metar <callsign>[-ssid]``` - METAR report that is closest to the call sign's position
- ```taf <callsign>[-ssid]``` - TAF report that is closest to the call sign's position
- ```metar <callsign>[-ssid] full``` or ```taf <callsign>[-ssid] full``` - METAR & TAF report that is closest to the call sign's position
- ```metar``` - METAR report that is closest to the user's own position
- ```taf``` - TAF report that is closest to the user's own position
- ```metar full``` or ```taf full``` - METAR & TAF report that is closest to the user's own position

If no call sign is specified, then the user's own call sign (the one that he has send us the message with) is used

#### Example requests

```metar ko4jvr-9```

```metar lb7ji```
```taf lb7ji```

```metar ```
```metar full```

Based on the user's lat/lon, the program will then try to find the nearest airport for you. If that airport supports METAR data, the program is going to return METAR data to the user. Otherwise, it will try to pull a standard wx report for the airport's coordinates. If the airport is capable of providing METAR data but the METAR report cannot be retrieved, an error message is returned to the user.

Expand Down
73 changes: 39 additions & 34 deletions docs/EXAMPLES.md
Expand Up @@ -10,32 +10,32 @@ External service dependencies:
- [Openstreetmap](www.openstreetmap.org) for coordinate transformation (e.g. City/country or zipcode to lat/lon)
- [aprs.fi](www.aprs.fi) for APRS call sign coordinates

| What do we want | Command string User > MPAD | Response example MPAD > User |
| --------------- | -------------------------- | ---------------------------- |
| What do we want | Command string User > MPAD | Response example MPAD > User |
| --------------- | -------------------------- |------------------------------------------------------------------------|
| localised Wx report for the city of Holzminden, Germany | ```Holzminden;de tomorrow lang de``` | ```16-Jan-21 Holzminden;DE Bedeckt morn:-3c day:-1c eve:-2c nite:-2c``` |
| | | ```sunrise/set 08:21/16:42UTC clouds:89% uvi:0.5 hPa:1026 hum:92%``` |
| | | ```dewpt:-5c wndspd:2m/s wnddeg:252``` |
| | | ```sunrise/set 08:21/16:42UTC clouds:89% uvi:0.5 hPa:1026 hum:92%``` |
| | | ```dewpt:-5c wndspd:2m/s wnddeg:252``` |
| WX report for monday for the user's own current position | ```monday``` | ```18-Jan-21 Hoexter;DE rain and snow morn:-1c day:1c eve:2c nite:0c``` |
| | | ```sunrise/set 08:25/16:48UTC rain:1mm snow:2mm clouds:100% uvi:0.3``` |
| | | ```hPa:1017 hum:98% dewpt:1c wndspd:2m/s wnddeg:223``` |
| WX report for monday for another user's position | ```wa1gov-10 monday``` | ```20-Jan-21 Taunton,MA,02718;US overcast clouds morn:-1c day:1c``` |
| | | ```eve:0c nite:-4c sunrise/set 13:06/22:43UTC clouds:100% uvi:0.9```|
| | |```hPa:1010 hum:84% dewpt:-4c wndspd:1m/s wnddeg:280```|
| Wx report for zipcode 94043 |```94043``` | ```17-Jan-21 Mountain View,94043;US clear sky morn:13c day:22c eve:16c```|
| U.S. country code is added implicitly for a 5-digit zip|```zip 94043``` returns same results| ```nite:14c sunrise/set 16:20/02:16UTC clouds:1% uvi:2.6 hPa:1019```|
| (see keyword specification) | |```hum:27% dewpt:2c wndspd:2m/s wnddeg:353```|
| WX report for zipcode 37603 in Germany |```zip 37603;de``` | ```19-Jan-21 Holzminden,37603;DE moderate rain morn:3c day:4c eve:8c```|
| | same as ```37603;de``` |```nite:5c sunrise/set 08:18/16:46UTC rain:13mm clouds:100% uvi:0.3```|
| | |```hPa:1006 hum:90% dewpt:3c wndspd:7m/s wnddeg:217```|
| WX report for Grid JO41du |```grid jo41du``` | ```17-Jan-21 jo41du rain and snow morn:-1c day:0c eve:1c nite:2c```|
| |```mh jo41du``` or ```jo41du``` returns same results | ```sunrise/set 08:25/16:48UTC rain:1mm snow:2mm clouds:100% uvi:0.3```|
| | |```hPa:1018 hum:97% dewpt:-1c wndspd:2m/s wnddeg:153```|
| Wx report for numeric latitude and longitude|```50.1211/8.7938``` | ```19-Jan-21 Offenbach am Main,63075;DE moderate rain morn:2c day:3c```|
| | |```eve:5c nite:3c sunrise/set 08:14/16:56UTC rain:5mm clouds:100%```|
| | |```uvi:0.1 hPa:1014 hum:79% dewpt:0c wndspd:8m/s wnddeg:217```|
| WX report in 47h for zipcode 37627 in Germany |```zip 37603;de 47h``` | ```15-Feb-21 in 47h Stadtoldendorf,37627;DE overcast clouds temp:-2c```|
| | |```clouds:100% uvi:0.5 hPa:1032 hum:87% dewpt:-8c wndspd:5m/s```|
| | |```wnddeg:166 vis:10000m```|
| | | ```hPa:1017 hum:98% dewpt:1c wndspd:2m/s wnddeg:223``` |
| WX report for monday for another user's position | ```wa1gov-10 monday``` | ```20-Jan-21 Taunton,MA,02718;US overcast clouds morn:-1c day:1c``` |
| | | ```eve:0c nite:-4c sunrise/set 13:06/22:43UTC clouds:100% uvi:0.9``` |
| | | ```hPa:1010 hum:84% dewpt:-4c wndspd:1m/s wnddeg:280``` |
| Wx report for zipcode 94043 |```94043``` | ```17-Jan-21 Mountain View,94043;US clear sky morn:13c day:22c eve:16c``` |
| U.S. country code is added implicitly for a 5-digit zip|```zip 94043``` returns same results| ```nite:14c sunrise/set 16:20/02:16UTC clouds:1% uvi:2.6 hPa:1019``` |
| (see keyword specification) | | ```hum:27% dewpt:2c wndspd:2m/s wnddeg:353``` |
| WX report for zipcode 37603 in Germany |```zip 37603;de``` | ```19-Jan-21 Holzminden,37603;DE moderate rain morn:3c day:4c eve:8c``` |
| | same as ```37603;de``` | ```nite:5c sunrise/set 08:18/16:46UTC rain:13mm clouds:100% uvi:0.3``` |
| | | ```hPa:1006 hum:90% dewpt:3c wndspd:7m/s wnddeg:217``` |
| WX report for Grid JO41du |```grid jo41du``` | ```17-Jan-21 jo41du rain and snow morn:-1c day:0c eve:1c nite:2c``` |
| |```mh jo41du``` or ```jo41du``` returns same results | ```sunrise/set 08:25/16:48UTC rain:1mm snow:2mm clouds:100% uvi:0.3``` |
| | | ```hPa:1018 hum:97% dewpt:-1c wndspd:2m/s wnddeg:153``` |
| Wx report for numeric latitude and longitude|```50.1211/8.7938``` | ```19-Jan-21 Offenbach am Main,63075;DE moderate rain morn:2c day:3c``` |
| | | ```eve:5c nite:3c sunrise/set 08:14/16:56UTC rain:5mm clouds:100%``` |
| | | ```uvi:0.1 hPa:1014 hum:79% dewpt:0c wndspd:8m/s wnddeg:217``` |
| WX report in 47h for zipcode 37627 in Germany |```zip 37603;de 47h``` | ```15-Feb-21 in 47h Stadtoldendorf,37627;DE overcast clouds temp:-2c``` |
| | | ```clouds:100% uvi:0.5 hPa:1032 hum:87% dewpt:-8c wndspd:5m/s``` |
| | | ```wnddeg:166 vis:10000m``` |

## Repeater

Expand Down Expand Up @@ -82,20 +82,25 @@ External service dependencies:
- [Aviation Weather](www.aviationweather.gov) for coordinate transformation (airport code to lat/lon) and METAR/TAF data
- [aprs.fi](www.aprs.fi) for APRS call sign coordinates

| What do we want | Command string User > MPAD | Response example MPAD > User |
| --------------- | -------------------------- | ---------------------------- |
| METAR / TAF data of a METAR-enabled airport, related to the user's position | ```metar``` | ```EDDF 171150Z 02008KT 340V050 5000 -SHSNRA FEW004 SCT011CB BKN019``` |
| | | ```03/01 Q1023 NOSIG ### TAF EDDF 171100Z 1712/1818 02008KT 9999``` |
| | | ```BKN030 TEMPO 1712/1716 SHRAGS BKN020TCU BECMG 1717/1720 FEW030``` |
| | | ```BECMG 1800/1802 02002KT BECMG 1806/1809 30005KT TEMPO 1811/1818``` |
| | | ```SHRAGS BKN020TCU SCT030``` |
| METAR data of a METAR-enabled airport, related to another user's position | ```metar wa1gov-10``` | similar output to 1st example |
| METAR data for ICAO code EDDF | ```icao eddf``` or ```eddf``` | similar output to 1st example |
| METAR data for IATA code FRA | ```iata fra``` or ```fra``` | similar output to 1st example |
| What do we want | Command string User > MPAD | Response example MPAD > User |
|---------------------------------------------------------------------------------|----------------------------------------|----------------------------------------------------------------------------|
| METAR data of a METAR-enabled airport, related to the user's position | ```metar``` | ```EDDF 171150Z 02008KT 340V050 5000 -SHSNRA FEW004 SCT011CB BKN019``` |
| | | ```03/01 Q1023 NOSIG``` |
| TAF data of a METAR-enabled airport, related to the user's position | ```taf``` | ```TAF EDDF 171100Z 1712/1818 02008KT 9999 BKN030 TEMPO 1712/1716``` |
| | | ```SHRAGS BKN020TCU BECMG 1717/1720 FEW030 BECMG 1800/1802 02002KT ``` |
| | | ```BECMG 1806/1809 30005KT TEMPO 1811/1818 SHRAGS BKN020TCU SCT030``` |
| METAR _and_ TAF data of a METAR-enabled airport, related to the user's position | ```metar full``` __or__ ```taf full``` | ```EDDF 171150Z 02008KT 340V050 5000 -SHSNRA FEW004 SCT011CB BKN019``` |
| | | ```03/01 Q1023 NOSIG ## TAF EDDF 171100Z 1712/1818 02008KT 9999``` |
| | | ```BKN030 TEMPO 1712/1716 SHRAGS BKN020TCU BECMG 1717/1720 FEW030``` |
| | | ```BECMG 1800/1802 02002KT BECMG 1806/1809 30005KT TEMPO 1811/1818``` |
| | | ```SHRAGS BKN020TCU SCT030``` |
| METAR data of a METAR-enabled airport, related to another user's position | ```metar wa1gov-10``` | similar output to 1st example; add ```full``` keyword for METAR & TAF data |
| METAR data for ICAO code EDDF | ```icao eddf``` or ```eddf``` | similar output to 1st example; add ```full``` keyword for METAR & TAF data |
| METAR data for IATA code FRA | ```iata fra``` or ```fra``` | similar output to 1st example; add ```full``` keyword for METAR & TAF data |

IATA codes are taken from [https://www.aviationweather.gov/docs/metar/stations.txt](https://www.aviationweather.gov/docs/metar/stations.txt). This file does not contain several international IATA codes. If your IATA code does not work, use an ICAO code.

For better legibility, METAR and TAF data are separated by a ### sequence - see example.
In case you use either the ```metar``` or the ```taf``` keyword in combination with the ```full``` keyword, `For better legibility,```mpad``` will separate METAR and TAF data by a ## sequence - see example.

## CWOP data

Expand Down
2 changes: 2 additions & 0 deletions docs/USAGE.md
Expand Up @@ -4,6 +4,8 @@

- The program's default ```action``` is to retrieve a wx report for the given address/coordinates. This assumption is valid as long as the user has not specified a keyword that tells the program to do something different. This means that you can a single datetime-related keyword like e.g. 'tomorrow' and the program will try to return the wx report for you.

- By default, the ```metar``` and ```taf``` commands will only return the data requested by the user, read: if ```metar``` data was requested, the user will only receive METAR data. You can request both METAR and TAF data at the same time by adding the ```full``` keyword to your inquiry, e.g. ```metar full``` or ```taf full``` will return both METAR and TAF information to the user.

- Default ```date``` is always ```today```. If you omit any date-related information, ```today``` will be the default value.

- Default ```daytime``` is always ```full```, meaning that you will get e.g. the wx report for the whole day. See the next paragraph on limitations wrt keywords and time zones. Note that ```full``` can be time- or content-specific.
Expand Down
50 changes: 40 additions & 10 deletions src/airport_data_modules.py
Expand Up @@ -75,7 +75,7 @@ def read_local_airport_data_file(
except:
lines = None
else:
logger.info(msg=f"Airport data file '{absolute_path_filename}' does not exist")
logger.error(msg=f"Airport data file '{absolute_path_filename}' does not exist")

# If the file did contain content, then parse it
if lines:
Expand Down Expand Up @@ -134,7 +134,7 @@ def read_local_airport_data_file(
return iata_dict, icao_dict


def get_metar_data(icao_code: str):
def get_metar_data(icao_code: str, keyword: str = None, full_msg: bool = False):
"""
Get METAR and TAF data for a given ICAO code.
May need to be switched to https://api.met.no/weatherapi/ at
Expand All @@ -145,6 +145,13 @@ def get_metar_data(icao_code: str):
icao_code : 'str'
4-character ICAO code of the airport whose
METAR data is to be downloaded.
keyword: 'str'
mode that we intend to run; value is either
"metar" or "taf"
full_msg: 'bool'
True = always forces the selected keyword to
return both METAR and TAF data
False = only returns METAR or TAF data
Returns
=======
Expand All @@ -155,12 +162,21 @@ def get_metar_data(icao_code: str):
(or "NOTFOUND" if no data was found)
"""

assert keyword in ("metar", "taf")

# prepare the request parameters
# false = request METAR data but no TAF data

request_mode = "false"
if keyword == "taf" or full_msg == True:
request_mode = "true"

try:
resp = requests.get(
f"https://www.aviationweather.gov/"
f"cgi-bin/data/metar.php/?ids={icao_code}"
f"&hours=0&order=id%2C-obs&sep=true"
f"&taf=true"
f"&hours=0&order=id%2C-obs&sep=false"
f"&taf={request_mode}"
)
except requests.exceptions.RequestException as e:
logger.error(msg="{e}")
Expand All @@ -186,13 +202,27 @@ def get_metar_data(icao_code: str):
metar_result_array = remainder.splitlines()
# start with an empty response
response = ""
metar = ""
taf = ""
# Iterate through the list. We stop at that line which starts with TAF (TAF report)
# Everything else before that line is our METAR report which may consist of 1..n lines
for metar_result_item in metar_result_array:
if metar_result_item.startswith("TAF"):
response = response + " ### "
response = response + metar_result_item
for index, metar_result_item in enumerate(metar_result_array):
if index == 0:
# METAR content is ALWAYS received and consists of a single line
metar = metar_result_item
else:
# TAF content may be optional, starts at index 1 and may consist of 1..n lines
taf = taf + metar_result_item.lstrip()
# end of parser; construct the outgoing message
success = True

# if the user requested both METAR and TAF data,
# concatenate both messages with a separator
if full_msg:
response = f"{metar} ## {taf}"
else:
# assign either the METAR or TAF content as response
response = metar if keyword == "metar" else taf
response = response.strip()
return success, response

Expand Down Expand Up @@ -316,7 +346,7 @@ def update_local_airport_stations_file(
try:
r = requests.get(file_url)
except:
logger.info(msg=f"Cannot download airport data from '{file_url}'")
logger.debug(msg=f"Cannot download airport data from '{file_url}'")
r = None
if r:
if r.status_code == 200:
Expand All @@ -326,7 +356,7 @@ def update_local_airport_stations_file(
f.close()
success = True
except:
logger.info(
logger.debug(
msg=f"Cannot update airport data to local file '{absolute_path_filename}'"
)
return success
Expand Down

0 comments on commit ec7683b

Please sign in to comment.