Skip to content

Commit 8989ccd

Browse files
committed
Initial version
1 parent 27d0f40 commit 8989ccd

6 files changed

+267
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
releases/
2+
csv/
3+
4+
config-dev.ini

METAR_TAF_logger.py

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
# ##### BEGIN GPL LICENSE BLOCK #####
5+
#
6+
# This program is free software; you can redistribute it and/or
7+
# modify it under the terms of the GNU General Public License
8+
# as published by the Free Software Foundation; either version 2
9+
# of the License, or (at your option) any later version.
10+
#
11+
# This program is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with this program; if not, write to the Free Software Foundation,
18+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
#
20+
# ##### END GPL LICENSE BLOCK #####
21+
22+
# Name :
23+
# Weather Logger
24+
# Author :
25+
# ▄▄▄▄▄▄▄ ▄ ▄▄ ▄▄▄▄▄▄▄
26+
# █ ▄▄▄ █ ██ ▀▄ █ ▄▄▄ █
27+
# █ ███ █ ▄▀ ▀▄ █ ███ █
28+
# █▄▄▄▄▄█ █ ▄▀█ █▄▄▄▄▄█
29+
# ▄▄ ▄ ▄▄▀██▀▀ ▄▄▄ ▄▄
30+
# ▀█▄█▄▄▄█▀▀ ▄▄▀█ █▄▀█
31+
# █ █▀▄▄▄▀██▀▄ █▄▄█ ▀█
32+
# ▄▄▄▄▄▄▄ █▄█▀ ▄ ██ ▄█
33+
# █ ▄▄▄ █ █▀█▀ ▄▀▀ ▄▀
34+
# █ ███ █ ▀▄ ▄▀▀▄▄▀█▀█
35+
# █▄▄▄▄▄█ ███▀▄▀ ▀██ ▄
36+
37+
# DEPENDENCIES
38+
39+
import sys
40+
import os.path
41+
import argparse
42+
import datetime
43+
import configparser
44+
import urllib.request
45+
from lxml import etree
46+
47+
# CONFIGURATION
48+
49+
PROGRAM_NAME = "Weather Logger"
50+
PROGRAM_VERSION = "1.0"
51+
52+
argParser = argparse.ArgumentParser(description=PROGRAM_NAME + " " + PROGRAM_VERSION)
53+
argParser.add_argument('-c', '--config', metavar='PATH', help='"config.ini" configuration file path', required=True)
54+
args = vars(argParser.parse_args())
55+
sConfigFilePath = args['config']
56+
57+
if not os.path.isfile(sConfigFilePath):
58+
print("Invalid INI configuration file path")
59+
sys.exit(1)
60+
try:
61+
configObj = configparser.RawConfigParser()
62+
configObj.read(sConfigFilePath)
63+
except:
64+
print("Badly written INI configuration file")
65+
sys.exit(1)
66+
67+
# URL OPENING
68+
69+
sLocationCodes = configObj.get('General', 'ICAO_airport_codes').replace(" ", "").split(",")
70+
71+
sWeatherDataUrl = "http://aviation.meteo.fr/FR/aviation/serveur_donnees.jsp?ID=" + configObj.get('General', 'user_code') + "&TYPE_DONNEES=OPMET&LIEUID=" + "%7C".join(sLocationCodes) + "&METAR=oui&TAF=Deux"
72+
oFile = urllib.request.urlopen(sWeatherDataUrl)
73+
sFileContent = oFile.read()
74+
75+
# XML PARSING
76+
77+
rootXML = etree.fromstring(sFileContent)
78+
if not rootXML.find('code') is None:
79+
print("Invalid 10-digits aeronautical code")
80+
sys.exit(1)
81+
82+
for sLocationCode in sLocationCodes:
83+
84+
# DATA EXTRACTION
85+
86+
sDataMETAR = rootXML.xpath("///messages[attribute::oaci='" + sLocationCode + "']/message[attribute::type='METAR']/texte")[0].text.replace('\n', '') + '\n'
87+
sDataTAF = rootXML.xpath("///messages[attribute::oaci='" + sLocationCode + "']/message[attribute::type='TAFL']/texte")[0].text.replace('\n', '') + '\n'
88+
89+
# CSV FILES
90+
91+
sOutputPath = configObj.get('Directory', 'output_directory')
92+
if not os.path.exists(sOutputPath):
93+
os.makedirs(sOutputPath)
94+
sDateTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M ')
95+
96+
if configObj.getboolean('General', 'METAR_logging'):
97+
csvFileMETAR = open(os.path.join(sOutputPath, "METAR_" + sLocationCode + ".csv"), 'a')
98+
csvFileMETAR.write(sDateTime + sDataMETAR)
99+
csvFileMETAR.close()
100+
101+
if configObj.getboolean('General', 'TAF_logging'):
102+
csvFileTAF = open(os.path.join(sOutputPath, "TAF_" + sLocationCode + ".csv"), 'a')
103+
csvFileTAF.write(sDateTime + sDataTAF)
104+
csvFileTAF.close()

README.md

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Weather Logger
2+
3+
## About
4+
Simple Python script to log [METAR](https://en.wikipedia.org/wiki/METAR) and [TAF](https://en.wikipedia.org/wiki/Terminal_aerodrome_forecast) weather reports from [aviation.meteo.fr](https://aviation.meteo.fr) XML API to CSV files.
5+
6+
## Usage
7+
Run `METAR_TAF_logger.py` with a `config.ini` file path as `-c` command line argument, for example from a [cron](https://en.wikipedia.org/wiki/Cron) job.
8+
9+
Crontab every 10 minutes ? There you go :
10+
```
11+
*/10 * * * * cd /SCRIPT_PATH/ && /usr/bin/python3 /SCRIPT_PATH/METAR_TAF_logger.py -c /CONFIG_PATH/config.ini
12+
```
13+
:warning: The `cd /SCRIPT_PATH/` command from the example above is **MANDATORY** in a cron job if you want to use relative paths in your `config.ini` configuration file. You are welcome.
14+
15+
## Output
16+
CSV file(s) containing METAR / TAF reports in the following format : `YYYY-MM-DD HH:mm METAR_OR_TAF_REPORT`
17+
18+
For `LFPG` [ICAO](https://en.wikipedia.org/wiki/ICAO_airport_code) airport code, for example :
19+
- `METAR_LFPG.csv` :
20+
```
21+
2018-02-21 16:00 METAR LFPG 211500Z 02011KT 330V110 4500 HZ NSC 05/M02 Q1021 TEMPO6000=
22+
2018-02-22 16:00 METAR LFPG 220800Z 03014KT 010V090 3000 BR NSC M02/M04 Q1019 NOSIG=
23+
```
24+
- `TAF_LFPG.csv` :
25+
```
26+
2018-02-21 16:00 TAF AMD LFPG 211306Z 2113/2218 03012KT 4000 HZ BKN020 TEMPO 2113/2117 6000 BECMG 2202/2204 4000 BR BKN005 BECMG 2207/2209 5000 NSW SCT010BECMG 2212/2214 SCT025 TX06/2115Z TNM03/2206Z=
27+
2018-02-22 16:00 TAF AMD LFPG 220719Z 2207/2312 03010G20KT 5000 BR NSC TEMPO 2207/2210 3000 BR TEMPO 2210/2218 4500 HZ TX04/2215Z TNM03/2306Z=
28+
```
29+
30+
## Requirements
31+
- [Python 3](https://www.python.org/)
32+
- [lxml](http://lxml.de/)
33+
34+
## Configuration
35+
Edit the provided `config.ini` configuration file to set up the script. Everything is properly commented, easy peasy !
36+
37+
```ini
38+
[General]
39+
; Should I save TAR reports to CSV? If True, yes. If False, nope
40+
TAF_logging = True
41+
; Should I save METAR reports to CSV? If True, yes. If False, nope
42+
METAR_logging = True
43+
; List of ICAO airport codes, comma separated
44+
ICAO_airport_codes = LFPG,LFPO,PHTO,EGLL
45+
; Your 10 digits aeronautical code
46+
user_code = XXXXXXXXXX
47+
48+
[Directory]
49+
; CSV files will be saved to this directory path
50+
output_directory = ./csv/
51+
```
52+
53+
## XML API overview
54+
For `LFPG` and `LFPO` [ICAO](https://en.wikipedia.org/wiki/ICAO_airport_code) airport codes for example, [aviation.meteo.fr](https://aviation.meteo.fr) XML API will output the following document :
55+
56+
```xml
57+
<?xml version="1.0" encoding="ISO-8859-1"?>
58+
<groupe>
59+
<messages oaci="LFPG" nom="PARIS CHARLES DE GAULLE">
60+
<message type="METAR">
61+
<texte>
62+
<![CDATA[
63+
METAR LFPG 220800Z 03014KT 010V090 3000 BR NSC M02/M04 Q1019 NOSIG=
64+
]]>
65+
</texte>
66+
</message>
67+
<message type="TAFL">
68+
<texte>
69+
<![CDATA[
70+
TAF AMD LFPG 220719Z 2207/2312 03010G20KT 5000 BR NSC TEMPO 2207/2210 3000 BR TEMPO 2210/2218 4500 HZ TX04/2215Z TNM03/2306Z=
71+
]]>
72+
</texte>
73+
</message>
74+
<message type="SIGMET">
75+
<texte>
76+
<![CDATA[
77+
LFFF SIGMET 1 VALID 220600/220900 LFPW- LFFF PARIS FIR/UIR SEV TURB FCST WI N4815 E00515 - N4730 E00415 - N4630 E00445 - N4630 E00300 - N4700 E00215 - N4815 E00500 - N4815 E00515 FL170/250 MOV SW 25KT NC=
78+
]]>
79+
</texte>
80+
</message>
81+
</messages>
82+
<messages oaci="LFPO" nom="PARIS ORLY">
83+
<message type="METAR">
84+
<texte>
85+
<![CDATA[
86+
METAR LFPO 220800Z 03012KT 6000 NSC M01/M04 Q1019 NOSIG=
87+
]]>
88+
</texte>
89+
</message>
90+
<message type="TAFL">
91+
<texte>
92+
<![CDATA[
93+
TAF LFPO 220500Z 2206/2312 02010KT 8000 NSC PROB30 TEMPO 2206/2209 3000 BR SCT008 TEMPO 2211/2224 CAVOK=
94+
]]>
95+
</texte>
96+
</message>
97+
<message type="SIGMET">
98+
<texte>
99+
<![CDATA[
100+
LFFF SIGMET 1 VALID 220600/220900 LFPW- LFFF PARIS FIR/UIR SEV TURB FCST WI N4815 E00515 - N4730 E00415 - N4630 E00445 - N4630 E00300 - N4700 E00215 - N4815 E00500 - N4815 E00515 FL170/250 MOV SW 25KT NC=
101+
]]>
102+
</texte>
103+
</message>
104+
</messages>
105+
</groupe>
106+
```
107+
108+
## Todo
109+
- Debug logging
110+
- Error handling
111+
112+
## License
113+
Weather Logger is released under the [GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.fr.html).

config.ini

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
; ##### BEGIN GPL LICENSE BLOCK #####
2+
;
3+
; This program is free software; you can redistribute it and/or
4+
; modify it under the terms of the GNU General Public License
5+
; as published by the Free Software Foundation; either version 2
6+
; of the License, or (at your option) any later version.
7+
;
8+
; This program is distributed in the hope that it will be useful,
9+
; but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
; GNU General Public License for more details.
12+
;
13+
; You should have received a copy of the GNU General Public License
14+
; along with this program; if not, write to the Free Software Foundation,
15+
; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16+
;
17+
; ##### END GPL LICENSE BLOCK #####
18+
19+
; Name :
20+
; Weather Logger
21+
; Author :
22+
; ▄▄▄▄▄▄▄ ▄ ▄▄ ▄▄▄▄▄▄▄
23+
; █ ▄▄▄ █ ██ ▀▄ █ ▄▄▄ █
24+
; █ ███ █ ▄▀ ▀▄ █ ███ █
25+
; █▄▄▄▄▄█ █ ▄▀█ █▄▄▄▄▄█
26+
; ▄▄ ▄ ▄▄▀██▀▀ ▄▄▄ ▄▄
27+
; ▀█▄█▄▄▄█▀▀ ▄▄▀█ █▄▀█
28+
; █ █▀▄▄▄▀██▀▄ █▄▄█ ▀█
29+
; ▄▄▄▄▄▄▄ █▄█▀ ▄ ██ ▄█
30+
; █ ▄▄▄ █ █▀█▀ ▄▀▀ ▄▀
31+
; █ ███ █ ▀▄ ▄▀▀▄▄▀█▀█
32+
; █▄▄▄▄▄█ ███▀▄▀ ▀██ ▄
33+
34+
[General]
35+
; Should I save TAR reports to CSV? If True, yes. If False, nope
36+
TAF_logging = True
37+
; Should I save METAR reports to CSV? If True, yes. If False, nope
38+
METAR_logging = True
39+
; List of ICAO airport codes, comma separated
40+
ICAO_airport_codes = LFPG,LFPO,PHTO,EGLL
41+
; Your 10 digits aeronautical code
42+
user_code = XXXXXXXXXX
43+
44+
[Directory]
45+
; CSV files will be saved to this directory path
46+
output_directory = ./csv/
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)