hkopenai.hk-climate-mcp-server 0.2.0__py3-none-any.whl → 0.4.0__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.
- hkopenai/hk_climate_mcp_server/__init__.py +3 -18
- hkopenai/hk_climate_mcp_server/__main__.py +1 -1
- hkopenai/hk_climate_mcp_server/server.py +247 -0
- hkopenai/hk_climate_mcp_server/tools/astronomical.py +109 -0
- hkopenai/hk_climate_mcp_server/tools/current_weather.py +106 -0
- hkopenai/hk_climate_mcp_server/tools/forecast.py +82 -0
- hkopenai/hk_climate_mcp_server/tools/lightning.py +20 -0
- hkopenai/hk_climate_mcp_server/tools/radiation.py +206 -0
- hkopenai/hk_climate_mcp_server/tools/temperature.py +119 -0
- hkopenai/hk_climate_mcp_server/tools/tides.py +165 -0
- hkopenai/hk_climate_mcp_server/tools/visibility.py +20 -0
- hkopenai/hk_climate_mcp_server/tools/warnings.py +77 -0
- {hkopenai_hk_climate_mcp_server-0.2.0.dist-info → hkopenai_hk_climate_mcp_server-0.4.0.dist-info}/METADATA +78 -6
- hkopenai_hk_climate_mcp_server-0.4.0.dist-info/RECORD +18 -0
- hkopenai/hk_climate_mcp_server/app.py +0 -65
- hkopenai/hk_climate_mcp_server/tool_weather.py +0 -241
- hkopenai_hk_climate_mcp_server-0.2.0.dist-info/RECORD +0 -10
- {hkopenai_hk_climate_mcp_server-0.2.0.dist-info → hkopenai_hk_climate_mcp_server-0.4.0.dist-info}/WHEEL +0 -0
- {hkopenai_hk_climate_mcp_server-0.2.0.dist-info → hkopenai_hk_climate_mcp_server-0.4.0.dist-info}/entry_points.txt +0 -0
- {hkopenai_hk_climate_mcp_server-0.2.0.dist-info → hkopenai_hk_climate_mcp_server-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {hkopenai_hk_climate_mcp_server-0.2.0.dist-info → hkopenai_hk_climate_mcp_server-0.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,206 @@
|
|
1
|
+
import requests
|
2
|
+
from datetime import datetime, timedelta
|
3
|
+
from typing import Dict, Any, Optional
|
4
|
+
|
5
|
+
# Station names in different languages: en (English), tc (Traditional Chinese), sc (Simplified Chinese)
|
6
|
+
VALID_STATIONS = {
|
7
|
+
'en': {
|
8
|
+
'CCH': 'Cheung Chau',
|
9
|
+
'CLK': 'Chek Lap Kok',
|
10
|
+
'EPC': 'Ping Chau',
|
11
|
+
'HKO': 'Hong Kong Observatory',
|
12
|
+
'HKP': 'Hong Kong Park',
|
13
|
+
'HKS': 'Wong Chuk Hang',
|
14
|
+
'HPV': 'Happy Valley',
|
15
|
+
'JKB': 'Tseung Kwan O',
|
16
|
+
'KAT': 'Kat O',
|
17
|
+
'KLT': 'Kowloon City',
|
18
|
+
'KP': 'Kings Park',
|
19
|
+
'KTG': 'Kwun Tong',
|
20
|
+
'LFS': 'Lau Fau Shan',
|
21
|
+
'PLC': 'Tai Mei Tuk',
|
22
|
+
'SE1': 'Kai Tak Runway Park',
|
23
|
+
'SEK': 'Shek Kong',
|
24
|
+
'SHA': 'Sha Tin',
|
25
|
+
'SKG': 'Sai Kung',
|
26
|
+
'SKW': 'Shau Kei Wan',
|
27
|
+
'SSP': 'Sham Shui Po',
|
28
|
+
'STK': 'Sha Tau Kok',
|
29
|
+
'STY': 'Stanley',
|
30
|
+
'SWH': 'Sai Wan Ho',
|
31
|
+
'TAP': 'Tap Mun',
|
32
|
+
'TBT': 'Tsim Bei Tsui',
|
33
|
+
'TKL': 'Ta Kwu Ling',
|
34
|
+
'TUN': 'Tuen Mun',
|
35
|
+
'TW': 'Tsuen Wan Shing Mun Valley',
|
36
|
+
'TWN': 'Tsuen Wan Ho Koon',
|
37
|
+
'TY1': 'Tsing Yi',
|
38
|
+
'WTS': 'Wong Tai Sin',
|
39
|
+
'YCT': 'Tai Po',
|
40
|
+
'YLP': 'Yuen Long Park',
|
41
|
+
'YNF': 'Yuen Ng Fan'
|
42
|
+
},
|
43
|
+
'tc': {
|
44
|
+
'CCH': '長洲',
|
45
|
+
'CLK': '赤鱲角',
|
46
|
+
'EPC': '平洲',
|
47
|
+
'HKO': '香港天文台',
|
48
|
+
'HKP': '香港公園',
|
49
|
+
'HKS': '黃竹坑',
|
50
|
+
'HPV': '跑馬地',
|
51
|
+
'JKB': '將軍澳',
|
52
|
+
'KAT': '吉澳',
|
53
|
+
'KLT': '九龍城',
|
54
|
+
'KP': '京士柏',
|
55
|
+
'KTG': '觀塘',
|
56
|
+
'LFS': '流浮山',
|
57
|
+
'PLC': '大美督',
|
58
|
+
'SE1': '啟德跑道公園',
|
59
|
+
'SEK': '石崗',
|
60
|
+
'SHA': '沙田',
|
61
|
+
'SKG': '西貢',
|
62
|
+
'SKW': '筲箕灣',
|
63
|
+
'SSP': '深水埗',
|
64
|
+
'STK': '沙頭角',
|
65
|
+
'STY': '赤柱',
|
66
|
+
'SWH': '西灣河',
|
67
|
+
'TAP': '塔門',
|
68
|
+
'TBT': '尖鼻咀',
|
69
|
+
'TKL': '打鼓嶺',
|
70
|
+
'TUN': '屯門',
|
71
|
+
'TW': '荃灣城門谷',
|
72
|
+
'TWN': '荃灣可觀',
|
73
|
+
'TY1': '青衣',
|
74
|
+
'WTS': '黃大仙',
|
75
|
+
'YCT': '大埔',
|
76
|
+
'YLP': '元朗公園',
|
77
|
+
'YNF': '元五墳'
|
78
|
+
},
|
79
|
+
'sc': {
|
80
|
+
'CCH': '长洲',
|
81
|
+
'CLK': '赤鱲角',
|
82
|
+
'EPC': '平洲',
|
83
|
+
'HKO': '香港天文台',
|
84
|
+
'HKP': '香港公园',
|
85
|
+
'HKS': '黄竹坑',
|
86
|
+
'HPV': '跑马地',
|
87
|
+
'JKB': '将军澳',
|
88
|
+
'KAT': '吉澳',
|
89
|
+
'KLT': '九龙城',
|
90
|
+
'KP': '京士柏',
|
91
|
+
'KTG': '观塘',
|
92
|
+
'LFS': '流浮山',
|
93
|
+
'PLC': '大美督',
|
94
|
+
'SE1': '启德跑道公园',
|
95
|
+
'SEK': '石岗',
|
96
|
+
'SHA': '沙田',
|
97
|
+
'SKG': '西贡',
|
98
|
+
'SKW': '筲箕湾',
|
99
|
+
'SSP': '深水埗',
|
100
|
+
'STK': '沙头角',
|
101
|
+
'STY': '赤柱',
|
102
|
+
'SWH': '西湾河',
|
103
|
+
'TAP': '塔门',
|
104
|
+
'TBT': '尖鼻咀',
|
105
|
+
'TKL': '打鼓岭',
|
106
|
+
'TUN': '屯门',
|
107
|
+
'TW': '荃湾城门谷',
|
108
|
+
'TWN': '荃湾可观',
|
109
|
+
'TY1': '青衣',
|
110
|
+
'WTS': '黄大仙',
|
111
|
+
'YCT': '大埔',
|
112
|
+
'YLP': '元朗公园',
|
113
|
+
'YNF': '元五坟'
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
def get_weather_radiation_report(
|
119
|
+
date: str = "Unknown",
|
120
|
+
station: str = "Unknown",
|
121
|
+
lang: str = "en"
|
122
|
+
) -> Dict[str, Any]:
|
123
|
+
"""
|
124
|
+
Get weather and radiation level report for Hong Kong.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
date: Mandatory date in YYYYMMDD format (e.g., 20250618)
|
128
|
+
station: Mandatory station code (e.g., 'HKO' for Hong Kong Observatory).
|
129
|
+
If not provided or invalid, returns an error message.
|
130
|
+
lang: Language code (en/tc/sc, default: en)
|
131
|
+
|
132
|
+
Returns:
|
133
|
+
Dict containing weather and radiation data or an error message if station is invalid
|
134
|
+
"""
|
135
|
+
|
136
|
+
# Select the station dictionary based on the language, default to English
|
137
|
+
stations_dict = VALID_STATIONS.get(lang, VALID_STATIONS['en'])
|
138
|
+
|
139
|
+
if not station or station not in stations_dict:
|
140
|
+
return {"error": "Invalid or missing station code. Use the 'get_radiation_station_codes' tool to retrieve the list of valid station codes."}
|
141
|
+
|
142
|
+
if not date:
|
143
|
+
return {"error": "Date parameter is mandatory in YYYYMMDD format (e.g., 20250618)"}
|
144
|
+
|
145
|
+
try:
|
146
|
+
datetime.strptime(date, '%Y%m%d')
|
147
|
+
except ValueError:
|
148
|
+
return {"error": "Invalid date format. Date must be in YYYYMMDD format (e.g., 20250618)"}
|
149
|
+
|
150
|
+
if is_date_in_future(date):
|
151
|
+
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y%m%d')
|
152
|
+
return {"error": f"Date must be yesterday or before in YYYYMMDD format. Expected {yesterday} or earlier, but got {date}"}
|
153
|
+
|
154
|
+
params = {
|
155
|
+
'dataType': 'RYES',
|
156
|
+
'lang': lang,
|
157
|
+
'rformat': 'json',
|
158
|
+
'date': date,
|
159
|
+
'station': station
|
160
|
+
}
|
161
|
+
|
162
|
+
try:
|
163
|
+
response = requests.get(
|
164
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
165
|
+
params=params
|
166
|
+
)
|
167
|
+
response.raise_for_status()
|
168
|
+
try:
|
169
|
+
return response.json()
|
170
|
+
except ValueError:
|
171
|
+
return {"error": "Failed to parse response as JSON. This could be due to invalid parameters or data not being updated. Please try again later."}
|
172
|
+
except requests.RequestException as e:
|
173
|
+
return {"error": f"Failed to fetch data: {str(e)}. Please try again later."}
|
174
|
+
|
175
|
+
|
176
|
+
def get_radiation_station_codes(lang: str = "en") -> Dict[str, str]:
|
177
|
+
"""
|
178
|
+
Get a dictionary of station codes and their corresponding names for weather and radiation reports in Hong Kong used in radiation API.
|
179
|
+
|
180
|
+
Args:
|
181
|
+
lang: Language code (en/tc/sc, default: en)
|
182
|
+
|
183
|
+
Returns:
|
184
|
+
Dict mapping station codes to station names in the specified language.
|
185
|
+
"""
|
186
|
+
# Return the dictionary for the specified language, default to English
|
187
|
+
return VALID_STATIONS.get(lang, VALID_STATIONS['en'])
|
188
|
+
|
189
|
+
|
190
|
+
def is_date_in_future(date_str: str) -> bool:
|
191
|
+
"""
|
192
|
+
Check if the provided date is in the future compared to today.
|
193
|
+
|
194
|
+
Args:
|
195
|
+
date_str: Date string in YYYYMMDD format.
|
196
|
+
|
197
|
+
Returns:
|
198
|
+
bool: True if the date is today or in the future, False otherwise.
|
199
|
+
"""
|
200
|
+
try:
|
201
|
+
input_date = datetime.strptime(date_str, '%Y%m%d')
|
202
|
+
today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
203
|
+
input_date = input_date.replace(hour=0, minute=0, second=0, microsecond=0)
|
204
|
+
return input_date >= today
|
205
|
+
except ValueError:
|
206
|
+
return False
|
@@ -0,0 +1,119 @@
|
|
1
|
+
import requests
|
2
|
+
from typing import Dict, Any, Optional
|
3
|
+
|
4
|
+
def get_daily_mean_temperature(
|
5
|
+
station: str,
|
6
|
+
year: Optional[int] = None,
|
7
|
+
month: Optional[int] = None,
|
8
|
+
lang: str = "en"
|
9
|
+
) -> Dict[str, Any]:
|
10
|
+
"""
|
11
|
+
Get daily mean temperature data for a specific station.
|
12
|
+
|
13
|
+
Args:
|
14
|
+
station: Station code (e.g. 'HKO' for Hong Kong Observatory)
|
15
|
+
year: Optional year (varies by station)
|
16
|
+
month: Optional month (1-12)
|
17
|
+
lang: Language code (en/tc/sc, default: en)
|
18
|
+
|
19
|
+
Returns:
|
20
|
+
Dict containing temperature data with fields and data arrays
|
21
|
+
"""
|
22
|
+
params = {
|
23
|
+
'dataType': 'CLMTEMP',
|
24
|
+
'lang': lang,
|
25
|
+
'rformat': 'json',
|
26
|
+
'station': station
|
27
|
+
}
|
28
|
+
if year: params['year'] = str(year)
|
29
|
+
if month: params['month'] = str(month)
|
30
|
+
|
31
|
+
response = requests.get(
|
32
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
33
|
+
params=params
|
34
|
+
)
|
35
|
+
try:
|
36
|
+
response.raise_for_status()
|
37
|
+
return response.json()
|
38
|
+
except requests.exceptions.JSONDecodeError as e:
|
39
|
+
return {"error": f"Failed to parse API response: {str(e)}. This might indicate invalid parameters or no data for the given request."}
|
40
|
+
except requests.RequestException as e:
|
41
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
42
|
+
|
43
|
+
def get_daily_max_temperature(
|
44
|
+
station: str,
|
45
|
+
year: Optional[int] = None,
|
46
|
+
month: Optional[int] = None,
|
47
|
+
lang: str = "en"
|
48
|
+
) -> Dict[str, Any]:
|
49
|
+
"""
|
50
|
+
Get daily maximum temperature data for a specific station.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
station: Station code (e.g. 'HKO' for Hong Kong Observatory)
|
54
|
+
year: Optional year (varies by station)
|
55
|
+
month: Optional month (1-12)
|
56
|
+
lang: Language code (en/tc/sc, default: en)
|
57
|
+
|
58
|
+
Returns:
|
59
|
+
Dict containing temperature data with fields and data arrays
|
60
|
+
"""
|
61
|
+
params = {
|
62
|
+
'dataType': 'CLMMAXT',
|
63
|
+
'lang': lang,
|
64
|
+
'rformat': 'json',
|
65
|
+
'station': station
|
66
|
+
}
|
67
|
+
if year: params['year'] = str(year)
|
68
|
+
if month: params['month'] = str(month)
|
69
|
+
|
70
|
+
response = requests.get(
|
71
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
72
|
+
params=params
|
73
|
+
)
|
74
|
+
try:
|
75
|
+
response.raise_for_status()
|
76
|
+
return response.json()
|
77
|
+
except requests.exceptions.JSONDecodeError as e:
|
78
|
+
return {"error": f"Failed to parse API response: {str(e)}. This might indicate invalid parameters or no data for the given request."}
|
79
|
+
except requests.RequestException as e:
|
80
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
81
|
+
|
82
|
+
def get_daily_min_temperature(
|
83
|
+
station: str,
|
84
|
+
year: Optional[int] = None,
|
85
|
+
month: Optional[int] = None,
|
86
|
+
lang: str = "en"
|
87
|
+
) -> Dict[str, Any]:
|
88
|
+
"""
|
89
|
+
Get daily minimum temperature data for a specific station.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
station: Station code (e.g. 'HKO' for Hong Kong Observatory)
|
93
|
+
year: Optional year (varies by station)
|
94
|
+
month: Optional month (1-12)
|
95
|
+
lang: Language code (en/tc/sc, default: en)
|
96
|
+
|
97
|
+
Returns:
|
98
|
+
Dict containing temperature data with fields and data arrays
|
99
|
+
"""
|
100
|
+
params = {
|
101
|
+
'dataType': 'CLMMINT',
|
102
|
+
'lang': lang,
|
103
|
+
'rformat': 'json',
|
104
|
+
'station': station
|
105
|
+
}
|
106
|
+
if year: params['year'] = str(year)
|
107
|
+
if month: params['month'] = str(month)
|
108
|
+
|
109
|
+
response = requests.get(
|
110
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
111
|
+
params=params
|
112
|
+
)
|
113
|
+
try:
|
114
|
+
response.raise_for_status()
|
115
|
+
return response.json()
|
116
|
+
except requests.exceptions.JSONDecodeError as e:
|
117
|
+
return {"error": f"Failed to parse API response: {str(e)}. This might indicate invalid parameters or no data for the given request."}
|
118
|
+
except requests.RequestException as e:
|
119
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
@@ -0,0 +1,165 @@
|
|
1
|
+
import requests
|
2
|
+
from typing import Dict, Any, Optional
|
3
|
+
|
4
|
+
# Station names for tide data in different languages: en (English), tc (Traditional Chinese), sc (Simplified Chinese)
|
5
|
+
VALID_TIDE_STATIONS = {
|
6
|
+
'en': {
|
7
|
+
'CCH': 'Cheung Chau',
|
8
|
+
'CLK': 'Chek Lap Kok',
|
9
|
+
'CMW': 'Chi Ma Wan',
|
10
|
+
'KCT': 'Kwai Chung',
|
11
|
+
'KLW': 'Ko Lau Wan',
|
12
|
+
'LOP': 'Lok On Pai',
|
13
|
+
'MWC': 'Ma Wan',
|
14
|
+
'QUB': 'Quarry Bay',
|
15
|
+
'SPW': 'Shek Pik',
|
16
|
+
'TAO': 'Tai O',
|
17
|
+
'TBT': 'Tsim Bei Tsui',
|
18
|
+
'TMW': 'Tai Miu Wan',
|
19
|
+
'TPK': 'Tai Po Kau',
|
20
|
+
'WAG': 'Waglan Island'
|
21
|
+
},
|
22
|
+
'tc': {
|
23
|
+
'CCH': '長洲',
|
24
|
+
'CLK': '赤鱲角',
|
25
|
+
'CMW': '芝麻灣',
|
26
|
+
'KCT': '葵涌',
|
27
|
+
'KLW': '高流灣',
|
28
|
+
'LOP': '樂安排',
|
29
|
+
'MWC': '馬灣',
|
30
|
+
'QUB': '鰂魚涌',
|
31
|
+
'SPW': '石壁',
|
32
|
+
'TAO': '大澳',
|
33
|
+
'TBT': '尖鼻咀',
|
34
|
+
'TMW': '大廟灣',
|
35
|
+
'TPK': '大埔滘',
|
36
|
+
'WAG': '橫瀾島'
|
37
|
+
},
|
38
|
+
'sc': {
|
39
|
+
'CCH': '长洲',
|
40
|
+
'CLK': '赤鱲角',
|
41
|
+
'CMW': '芝麻湾',
|
42
|
+
'KCT': '葵涌',
|
43
|
+
'KLW': '高流湾',
|
44
|
+
'LOP': '乐安排',
|
45
|
+
'MWC': '马湾',
|
46
|
+
'QUB': '鲗鱼涌',
|
47
|
+
'SPW': '石壁',
|
48
|
+
'TAO': '大澳',
|
49
|
+
'TBT': '尖鼻咀',
|
50
|
+
'TMW': '大庙湾',
|
51
|
+
'TPK': '大埔滘',
|
52
|
+
'WAG': '横澜岛'
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
def get_hourly_tides(
|
57
|
+
station: str,
|
58
|
+
year: int,
|
59
|
+
month: Optional[int] = None,
|
60
|
+
day: Optional[int] = None,
|
61
|
+
hour: Optional[int] = None,
|
62
|
+
lang: str = "en"
|
63
|
+
) -> Dict[str, Any]:
|
64
|
+
"""
|
65
|
+
Get hourly heights of astronomical tides for a specific station in Hong Kong.
|
66
|
+
|
67
|
+
Args:
|
68
|
+
station: Station code (e.g. 'CCH' for Cheung Chau)
|
69
|
+
year: Year (2022-2024)
|
70
|
+
month: Optional month (1-12)
|
71
|
+
day: Optional day (1-31)
|
72
|
+
hour: Optional hour (1-24)
|
73
|
+
lang: Language code (en/tc/sc, default: en)
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
Dict containing tide data with fields and data arrays
|
77
|
+
"""
|
78
|
+
params = {
|
79
|
+
'dataType': 'HHOT',
|
80
|
+
'lang': lang,
|
81
|
+
'rformat': 'json',
|
82
|
+
'station': station,
|
83
|
+
'year': year
|
84
|
+
}
|
85
|
+
if month: params['month'] = str(month)
|
86
|
+
if day: params['day'] = str(day)
|
87
|
+
if hour: params['hour'] = str(hour)
|
88
|
+
|
89
|
+
response = requests.get(
|
90
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
91
|
+
params=params
|
92
|
+
)
|
93
|
+
try:
|
94
|
+
response.raise_for_status()
|
95
|
+
# Decode response content with utf-8-sig to handle potential BOM
|
96
|
+
content = response.content.decode('utf-8-sig')
|
97
|
+
import json
|
98
|
+
return json.loads(content)
|
99
|
+
except (requests.RequestException, UnicodeDecodeError, ValueError) as e:
|
100
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
101
|
+
|
102
|
+
def get_tide_station_codes(lang: str = "en") -> Dict[str, str]:
|
103
|
+
"""
|
104
|
+
Get a dictionary of station codes and their corresponding names for tide reports in Hong Kong.
|
105
|
+
|
106
|
+
Args:
|
107
|
+
lang: Language code (en/tc/sc, default: en)
|
108
|
+
|
109
|
+
Returns:
|
110
|
+
Dict mapping station codes to station names in the specified language.
|
111
|
+
"""
|
112
|
+
# Return the dictionary for the specified language, default to English
|
113
|
+
return VALID_TIDE_STATIONS.get(lang, VALID_TIDE_STATIONS['en'])
|
114
|
+
|
115
|
+
def get_high_low_tides(
|
116
|
+
station: str,
|
117
|
+
year: int,
|
118
|
+
month: Optional[int] = None,
|
119
|
+
day: Optional[int] = None,
|
120
|
+
hour: Optional[int] = None,
|
121
|
+
lang: str = "en",
|
122
|
+
) -> Dict[str, Any]:
|
123
|
+
"""
|
124
|
+
Get times and heights of astronomical high and low tides for a specific station.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
station: Station code (e.g. 'CCH' for Cheung Chau)
|
128
|
+
year: Year (2022-2024)
|
129
|
+
month: Optional month (1-12)
|
130
|
+
day: Optional day (1-31)
|
131
|
+
hour: Optional hour (1-24)
|
132
|
+
lang: Language code (en/tc/sc, default: en)
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
Dict containing tide data with fields and data arrays or an error message if station is invalid
|
136
|
+
"""
|
137
|
+
# Select the station dictionary based on the language, default to English
|
138
|
+
stations_dict = VALID_TIDE_STATIONS.get(lang, VALID_TIDE_STATIONS['en'])
|
139
|
+
|
140
|
+
if not station or station not in stations_dict:
|
141
|
+
return {"error": "Invalid or missing station code. Use the 'get_tide_station_codes' tool to retrieve the list of valid station codes."}
|
142
|
+
|
143
|
+
params = {
|
144
|
+
'dataType': 'HLT',
|
145
|
+
'lang': lang,
|
146
|
+
'rformat': 'json',
|
147
|
+
'station': station,
|
148
|
+
'year': year
|
149
|
+
}
|
150
|
+
if month: params['month'] = str(month)
|
151
|
+
if day: params['day'] = str(day)
|
152
|
+
if hour: params['hour'] = str(hour)
|
153
|
+
|
154
|
+
response = requests.get(
|
155
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
156
|
+
params=params
|
157
|
+
)
|
158
|
+
try:
|
159
|
+
response.raise_for_status()
|
160
|
+
# Decode response content with utf-8-sig to handle potential BOM
|
161
|
+
content = response.content.decode('utf-8-sig')
|
162
|
+
import json
|
163
|
+
return json.loads(content)
|
164
|
+
except (requests.RequestException, UnicodeDecodeError, ValueError) as e:
|
165
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import requests
|
2
|
+
from typing import Dict, Any
|
3
|
+
|
4
|
+
def get_visibility_data(lang: str = "en") -> Dict[str, Any]:
|
5
|
+
"""
|
6
|
+
Get latest 10-minute mean visibility data for Hong Kong.
|
7
|
+
|
8
|
+
Args:
|
9
|
+
lang: Language code (en/tc/sc, default: en)
|
10
|
+
|
11
|
+
Returns:
|
12
|
+
Dict containing visibility data with fields and data arrays
|
13
|
+
"""
|
14
|
+
url = f"https://data.weather.gov.hk/weatherAPI/opendata/opendata.php?dataType=LTMV&lang={lang}&rformat=json"
|
15
|
+
response = requests.get(url)
|
16
|
+
try:
|
17
|
+
response.raise_for_status()
|
18
|
+
return response.json()
|
19
|
+
except (requests.RequestException, ValueError) as e:
|
20
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import requests
|
2
|
+
from typing import Dict, Any
|
3
|
+
|
4
|
+
def get_weather_warning_summary(lang: str = "en") -> Dict[str, Any]:
|
5
|
+
"""
|
6
|
+
Get weather warning summary for Hong Kong.
|
7
|
+
|
8
|
+
Args:
|
9
|
+
lang: Language code (en/tc/sc, default: en)
|
10
|
+
|
11
|
+
Returns:
|
12
|
+
Dict containing:
|
13
|
+
- warningMessage: List of warning messages
|
14
|
+
- updateTime: Last update time
|
15
|
+
"""
|
16
|
+
url = f"https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=warnsum&lang={lang}"
|
17
|
+
response = requests.get(url)
|
18
|
+
try:
|
19
|
+
response.raise_for_status()
|
20
|
+
data = response.json()
|
21
|
+
except (requests.RequestException, ValueError) as e:
|
22
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
23
|
+
|
24
|
+
return {
|
25
|
+
"warningMessage": data.get("warningMessage", []),
|
26
|
+
"updateTime": data.get("updateTime", ""),
|
27
|
+
}
|
28
|
+
|
29
|
+
def get_weather_warning_info(lang: str = "en") -> Dict[str, Any]:
|
30
|
+
"""
|
31
|
+
Get detailed weather warning information for Hong Kong.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
lang: Language code (en/tc/sc, default: en)
|
35
|
+
|
36
|
+
Returns:
|
37
|
+
Dict containing:
|
38
|
+
- warningStatement: Warning statement
|
39
|
+
- updateTime: Last update time
|
40
|
+
"""
|
41
|
+
url = f"https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=warningInfo&lang={lang}"
|
42
|
+
response = requests.get(url)
|
43
|
+
try:
|
44
|
+
response.raise_for_status()
|
45
|
+
data = response.json()
|
46
|
+
except (requests.RequestException, ValueError) as e:
|
47
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
48
|
+
|
49
|
+
return {
|
50
|
+
"warningStatement": data.get("warningStatement", ""),
|
51
|
+
"updateTime": data.get("updateTime", ""),
|
52
|
+
}
|
53
|
+
|
54
|
+
def get_special_weather_tips(lang: str = "en") -> Dict[str, Any]:
|
55
|
+
"""
|
56
|
+
Get special weather tips for Hong Kong.
|
57
|
+
|
58
|
+
Args:
|
59
|
+
lang: Language code (en/tc/sc, default: en)
|
60
|
+
|
61
|
+
Returns:
|
62
|
+
Dict containing:
|
63
|
+
- specialWeatherTips: List of special weather tips
|
64
|
+
- updateTime: Last update time
|
65
|
+
"""
|
66
|
+
url = f"https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=swt&lang={lang}"
|
67
|
+
response = requests.get(url)
|
68
|
+
try:
|
69
|
+
response.raise_for_status()
|
70
|
+
data = response.json()
|
71
|
+
except (requests.RequestException, ValueError) as e:
|
72
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
73
|
+
|
74
|
+
return {
|
75
|
+
"specialWeatherTips": data.get("specialWeatherTips", []),
|
76
|
+
"updateTime": data.get("updateTime", ""),
|
77
|
+
}
|