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
@@ -1,21 +1,6 @@
|
|
1
1
|
"""Hong Kong climate MCP Server package."""
|
2
|
-
from .
|
3
|
-
|
4
|
-
get_current_weather,
|
5
|
-
get_9_day_weather_forecast,
|
6
|
-
get_local_weather_forecast,
|
7
|
-
get_weather_warning_summary,
|
8
|
-
get_weather_warning_info,
|
9
|
-
get_special_weather_tips
|
10
|
-
)
|
2
|
+
from .server import main
|
3
|
+
|
11
4
|
|
12
5
|
__version__ = "0.1.0"
|
13
|
-
__all__ = [
|
14
|
-
'main',
|
15
|
-
'get_current_weather',
|
16
|
-
'get_9_day_weather_forecast',
|
17
|
-
'get_local_weather_forecast',
|
18
|
-
'get_weather_warning_summary',
|
19
|
-
'get_weather_warning_info',
|
20
|
-
'get_special_weather_tips'
|
21
|
-
]
|
6
|
+
__all__ = ['main']
|
@@ -0,0 +1,247 @@
|
|
1
|
+
import argparse
|
2
|
+
from fastmcp import FastMCP
|
3
|
+
from typing import Dict, Annotated, Optional
|
4
|
+
from pydantic import Field
|
5
|
+
from hkopenai.hk_climate_mcp_server.tools import astronomical
|
6
|
+
from hkopenai.hk_climate_mcp_server.tools import current_weather
|
7
|
+
from hkopenai.hk_climate_mcp_server.tools import forecast
|
8
|
+
from hkopenai.hk_climate_mcp_server.tools import lightning
|
9
|
+
from hkopenai.hk_climate_mcp_server.tools import radiation
|
10
|
+
from hkopenai.hk_climate_mcp_server.tools import temperature
|
11
|
+
from hkopenai.hk_climate_mcp_server.tools import tides
|
12
|
+
from hkopenai.hk_climate_mcp_server.tools import visibility
|
13
|
+
from hkopenai.hk_climate_mcp_server.tools import warnings
|
14
|
+
|
15
|
+
def create_mcp_server():
|
16
|
+
"""Create and configure the HKO MCP server"""
|
17
|
+
mcp = FastMCP(name="HKOServer")
|
18
|
+
|
19
|
+
@mcp.tool(
|
20
|
+
description="Get current weather observations, warnings, temperature, humidity and rainfall in Hong Kong from Hong Kong Observatory, with optional region or place in Hong Kong",
|
21
|
+
)
|
22
|
+
def get_current_weather(region: str = "Hong Kong Observatory") -> Dict:
|
23
|
+
return current_weather.get_current_weather(region)
|
24
|
+
|
25
|
+
@mcp.tool(
|
26
|
+
description="Get the 9-day weather forecast for Hong Kong including general situation, daily forecasts, sea and soil temperatures",
|
27
|
+
)
|
28
|
+
def get_9_day_weather_forecast(lang: str = "en") -> Dict:
|
29
|
+
return forecast.get_9_day_weather_forecast(lang)
|
30
|
+
|
31
|
+
@mcp.tool(
|
32
|
+
description="Get local weather forecast for Hong Kong including forecast description, outlook and update time",
|
33
|
+
)
|
34
|
+
def get_local_weather_forecast(lang: str = "en") -> Dict:
|
35
|
+
return forecast.get_local_weather_forecast(lang)
|
36
|
+
|
37
|
+
@mcp.tool(
|
38
|
+
description="Get weather warning summary for Hong Kong including warning messages and update time",
|
39
|
+
)
|
40
|
+
def get_weather_warning_summary(lang: str = "en") -> Dict:
|
41
|
+
return warnings.get_weather_warning_summary(lang)
|
42
|
+
|
43
|
+
@mcp.tool(
|
44
|
+
description="Get detailed weather warning information for Hong Kong including warning statement and update time",
|
45
|
+
)
|
46
|
+
def get_weather_warning_info(lang: str = "en") -> Dict:
|
47
|
+
return warnings.get_weather_warning_info(lang)
|
48
|
+
|
49
|
+
@mcp.tool(
|
50
|
+
description="Get special weather tips for Hong Kong including tips list and update time",
|
51
|
+
)
|
52
|
+
def get_special_weather_tips(lang: str = "en") -> Dict:
|
53
|
+
return warnings.get_special_weather_tips(lang)
|
54
|
+
|
55
|
+
@mcp.tool(
|
56
|
+
description="Get latest 10-minute mean visibility data for Hong Kong",
|
57
|
+
)
|
58
|
+
def get_visibility_data(lang: str = "en") -> Dict:
|
59
|
+
return visibility.get_visibility_data(lang)
|
60
|
+
|
61
|
+
@mcp.tool(
|
62
|
+
description="Get cloud-to-ground and cloud-to-cloud lightning count data",
|
63
|
+
)
|
64
|
+
def get_lightning_data(lang: str = "en") -> Dict:
|
65
|
+
return lightning.get_lightning_data(lang)
|
66
|
+
|
67
|
+
@mcp.tool(
|
68
|
+
description="Get times of moonrise, moon transit and moonset",
|
69
|
+
)
|
70
|
+
def get_moon_times(
|
71
|
+
year: int,
|
72
|
+
month: Optional[int] = None,
|
73
|
+
day: Optional[int] = None,
|
74
|
+
lang: str = "en"
|
75
|
+
) -> Dict:
|
76
|
+
return astronomical.get_moon_times(
|
77
|
+
year=year,
|
78
|
+
month=month,
|
79
|
+
day=day,
|
80
|
+
lang=lang
|
81
|
+
)
|
82
|
+
|
83
|
+
@mcp.tool(
|
84
|
+
description="Get hourly heights of astronomical tides for a specific station in Hong Kong",
|
85
|
+
)
|
86
|
+
def get_hourly_tides(
|
87
|
+
station: str,
|
88
|
+
year: int,
|
89
|
+
month: Optional[int] = None,
|
90
|
+
day: Optional[int] = None,
|
91
|
+
hour: Optional[int] = None,
|
92
|
+
lang: str = "en"
|
93
|
+
) -> Dict:
|
94
|
+
return tides.get_hourly_tides(
|
95
|
+
station=station,
|
96
|
+
year=year,
|
97
|
+
month=month,
|
98
|
+
day=day,
|
99
|
+
hour=hour,
|
100
|
+
lang=lang
|
101
|
+
)
|
102
|
+
|
103
|
+
@mcp.tool(
|
104
|
+
description="Get times and heights of astronomical high and low tides for a specific station in Hong Kong",
|
105
|
+
)
|
106
|
+
def get_high_low_tides(
|
107
|
+
station: str,
|
108
|
+
year: int,
|
109
|
+
month: Optional[int] = None,
|
110
|
+
day: Optional[int] = None,
|
111
|
+
hour: Optional[int] = None,
|
112
|
+
lang: str = "en"
|
113
|
+
) -> Dict:
|
114
|
+
return tides.get_high_low_tides(
|
115
|
+
station=station,
|
116
|
+
year=year,
|
117
|
+
month=month,
|
118
|
+
day=day,
|
119
|
+
hour=hour,
|
120
|
+
lang=lang
|
121
|
+
)
|
122
|
+
|
123
|
+
@mcp.tool(
|
124
|
+
description="Get a list of tide station codes and their corresponding names for tide reports in Hong Kong.",
|
125
|
+
)
|
126
|
+
def get_tide_station_codes(lang: str = "en") -> Dict:
|
127
|
+
return tides.get_tide_station_codes(lang)
|
128
|
+
|
129
|
+
@mcp.tool(
|
130
|
+
description="Get times of sunrise, sun transit and sunset for Hong Kong",
|
131
|
+
)
|
132
|
+
def get_sunrise_sunset_times(
|
133
|
+
year: int,
|
134
|
+
month: Optional[int] = None,
|
135
|
+
day: Optional[int] = None,
|
136
|
+
lang: str = "en"
|
137
|
+
) -> Dict:
|
138
|
+
return astronomical.get_sunrise_sunset_times(
|
139
|
+
year=year,
|
140
|
+
month=month,
|
141
|
+
day=day,
|
142
|
+
lang=lang
|
143
|
+
)
|
144
|
+
|
145
|
+
@mcp.tool(
|
146
|
+
description="Get Gregorian-Lunar calendar conversion data",
|
147
|
+
)
|
148
|
+
def get_gregorian_lunar_calendar(
|
149
|
+
year: int,
|
150
|
+
month: Optional[int] = None,
|
151
|
+
day: Optional[int] = None,
|
152
|
+
lang: str = "en"
|
153
|
+
) -> Dict:
|
154
|
+
return astronomical.get_gregorian_lunar_calendar(
|
155
|
+
year=year,
|
156
|
+
month=month,
|
157
|
+
day=day,
|
158
|
+
lang=lang
|
159
|
+
)
|
160
|
+
|
161
|
+
@mcp.tool(
|
162
|
+
description="Get daily mean temperature data for a specific station in Hong Kong",
|
163
|
+
)
|
164
|
+
def get_daily_mean_temperature(
|
165
|
+
station: str,
|
166
|
+
year: Optional[int] = None,
|
167
|
+
month: Optional[int] = None,
|
168
|
+
lang: str = "en"
|
169
|
+
) -> Dict:
|
170
|
+
return temperature.get_daily_mean_temperature(
|
171
|
+
station=station,
|
172
|
+
year=year,
|
173
|
+
month=month,
|
174
|
+
lang=lang
|
175
|
+
)
|
176
|
+
|
177
|
+
@mcp.tool(
|
178
|
+
description="Get daily maximum temperature data for a specific station in Hong Kong",
|
179
|
+
)
|
180
|
+
def get_daily_max_temperature(
|
181
|
+
station: str,
|
182
|
+
year: Optional[int] = None,
|
183
|
+
month: Optional[int] = None,
|
184
|
+
lang: str = "en"
|
185
|
+
) -> Dict:
|
186
|
+
return temperature.get_daily_max_temperature(
|
187
|
+
station=station,
|
188
|
+
year=year,
|
189
|
+
month=month,
|
190
|
+
lang=lang
|
191
|
+
)
|
192
|
+
|
193
|
+
@mcp.tool(
|
194
|
+
description="Get daily minimum temperature data for a specific station in Hong Kong",
|
195
|
+
)
|
196
|
+
def get_daily_min_temperature(
|
197
|
+
station: str,
|
198
|
+
year: Optional[int] = None,
|
199
|
+
month: Optional[int] = None,
|
200
|
+
lang: str = "en"
|
201
|
+
) -> Dict:
|
202
|
+
return temperature.get_daily_min_temperature(
|
203
|
+
station=station,
|
204
|
+
year=year,
|
205
|
+
month=month,
|
206
|
+
lang=lang
|
207
|
+
)
|
208
|
+
|
209
|
+
@mcp.tool(
|
210
|
+
description="Get weather and radiation level report for Hong Kong. Date must be in YYYYMMDD format and should be yesterday or before. Station must be a valid code like 'HKO' for Hong Kong Observatory.",
|
211
|
+
)
|
212
|
+
def get_weather_radiation_report(
|
213
|
+
date: Annotated[str, Field(description="Date in yyyyMMdd format, eg, 20250618")],
|
214
|
+
station: Annotated[str, Field(description="Station code in 3 characters in capital letters, eg, HKO")],
|
215
|
+
lang: Annotated[Optional[str], Field(description="Language (en/tc/sc)", json_schema_extra={"enum": ["en", "tc", "sc"]})] = 'en',
|
216
|
+
) -> Dict:
|
217
|
+
return radiation.get_weather_radiation_report(
|
218
|
+
date=date,
|
219
|
+
station=station,
|
220
|
+
lang=lang or 'en'
|
221
|
+
)
|
222
|
+
|
223
|
+
@mcp.tool(
|
224
|
+
description="Get a list of weather station codes and their corresponding names for radiation reports in Hong Kong.",
|
225
|
+
)
|
226
|
+
def get_radiation_station_codes(lang: str = "en") -> Dict:
|
227
|
+
return radiation.get_radiation_station_codes(lang)
|
228
|
+
|
229
|
+
return mcp
|
230
|
+
|
231
|
+
def main():
|
232
|
+
parser = argparse.ArgumentParser(description='HKO MCP Server')
|
233
|
+
parser.add_argument('-s', '--sse', action='store_true',
|
234
|
+
help='Run in SSE mode instead of stdio')
|
235
|
+
args = parser.parse_args()
|
236
|
+
|
237
|
+
server = create_mcp_server()
|
238
|
+
|
239
|
+
if args.sse:
|
240
|
+
server.run(transport="streamable-http")
|
241
|
+
print("HKO MCP Server running in SSE mode on port 8000")
|
242
|
+
else:
|
243
|
+
server.run()
|
244
|
+
print("HKO MCP Server running in stdio mode")
|
245
|
+
|
246
|
+
if __name__ == "__main__":
|
247
|
+
main()
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import requests
|
2
|
+
from typing import Dict, Any, Optional
|
3
|
+
|
4
|
+
def get_moon_times(year: int, month: Optional[int] = None,
|
5
|
+
day: Optional[int] = None, lang: str = "en") -> Dict[str, Any]:
|
6
|
+
"""
|
7
|
+
Get times of moonrise, moon transit and moonset.
|
8
|
+
|
9
|
+
Args:
|
10
|
+
year: Year (2018-2024)
|
11
|
+
month: Optional month (1-12)
|
12
|
+
day: Optional day (1-31)
|
13
|
+
lang: Language code (en/tc/sc, default: en)
|
14
|
+
|
15
|
+
Returns:
|
16
|
+
Dict containing moon times data with fields and data arrays
|
17
|
+
"""
|
18
|
+
params = {
|
19
|
+
'dataType': 'MRS',
|
20
|
+
'lang': lang,
|
21
|
+
'rformat': 'json',
|
22
|
+
'year': year
|
23
|
+
}
|
24
|
+
if month: params['month'] = str(month)
|
25
|
+
if day: params['day'] = str(day)
|
26
|
+
|
27
|
+
response = requests.get(
|
28
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
29
|
+
params=params
|
30
|
+
)
|
31
|
+
try:
|
32
|
+
response.raise_for_status()
|
33
|
+
return response.json()
|
34
|
+
except (requests.RequestException, ValueError) as e:
|
35
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
36
|
+
|
37
|
+
def get_sunrise_sunset_times(
|
38
|
+
year: int,
|
39
|
+
month: Optional[int] = None,
|
40
|
+
day: Optional[int] = None,
|
41
|
+
lang: str = "en"
|
42
|
+
) -> Dict[str, Any]:
|
43
|
+
"""
|
44
|
+
Get times of sunrise, sun transit and sunset.
|
45
|
+
|
46
|
+
Args:
|
47
|
+
year: Year (2018-2024)
|
48
|
+
month: Optional month (1-12)
|
49
|
+
day: Optional day (1-31)
|
50
|
+
lang: Language code (en/tc/sc, default: en)
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
Dict containing sun times data with fields and data arrays
|
54
|
+
"""
|
55
|
+
params = {
|
56
|
+
'dataType': 'SRS',
|
57
|
+
'lang': lang,
|
58
|
+
'rformat': 'json',
|
59
|
+
'year': year
|
60
|
+
}
|
61
|
+
if month: params['month'] = str(month)
|
62
|
+
if day: params['day'] = str(day)
|
63
|
+
|
64
|
+
response = requests.get(
|
65
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
66
|
+
params=params
|
67
|
+
)
|
68
|
+
try:
|
69
|
+
response.raise_for_status()
|
70
|
+
return response.json()
|
71
|
+
except (requests.RequestException, ValueError) as e:
|
72
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
73
|
+
|
74
|
+
def get_gregorian_lunar_calendar(
|
75
|
+
year: int,
|
76
|
+
month: Optional[int] = None,
|
77
|
+
day: Optional[int] = None,
|
78
|
+
lang: str = "en"
|
79
|
+
) -> Dict[str, Any]:
|
80
|
+
"""
|
81
|
+
Get Gregorian-Lunar calendar conversion data.
|
82
|
+
|
83
|
+
Args:
|
84
|
+
year: Year (1901-2100)
|
85
|
+
month: Optional month (1-12)
|
86
|
+
day: Optional day (1-31)
|
87
|
+
lang: Language code (en/tc/sc, default: en)
|
88
|
+
|
89
|
+
Returns:
|
90
|
+
Dict containing calendar conversion data
|
91
|
+
"""
|
92
|
+
params = {
|
93
|
+
'dataType': 'GLC',
|
94
|
+
'lang': lang,
|
95
|
+
'rformat': 'json',
|
96
|
+
'year': year
|
97
|
+
}
|
98
|
+
if month: params['month'] = str(month)
|
99
|
+
if day: params['day'] = str(day)
|
100
|
+
|
101
|
+
response = requests.get(
|
102
|
+
'https://data.weather.gov.hk/weatherAPI/opendata/opendata.php',
|
103
|
+
params=params
|
104
|
+
)
|
105
|
+
try:
|
106
|
+
response.raise_for_status()
|
107
|
+
return response.json()
|
108
|
+
except (requests.RequestException, ValueError) as e:
|
109
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import requests
|
2
|
+
from typing import Dict
|
3
|
+
|
4
|
+
def get_current_weather(region: str = "Hong Kong Observatory", lang: str = "en") -> Dict:
|
5
|
+
"""
|
6
|
+
Get current weather observations for a specific region in Hong Kong
|
7
|
+
|
8
|
+
Args:
|
9
|
+
region: The region to get weather for (default: "Hong Kong Observatory")
|
10
|
+
lang: Language code (en/tc/sc, default: en)
|
11
|
+
|
12
|
+
Returns:
|
13
|
+
Dict containing:
|
14
|
+
- warning: Current weather warnings
|
15
|
+
- temperature: Current temperature in Celsius
|
16
|
+
- humidity: Current humidity percentage
|
17
|
+
- rainfall: Current rainfall in mm
|
18
|
+
"""
|
19
|
+
response = requests.get(
|
20
|
+
f"https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=rhrread&lang={lang}"
|
21
|
+
)
|
22
|
+
data = response.json()
|
23
|
+
|
24
|
+
# Handle warnings
|
25
|
+
warning = "No warning in force"
|
26
|
+
if "warningMessage" in data:
|
27
|
+
if isinstance(data["warningMessage"], list) and data["warningMessage"]:
|
28
|
+
warning = data["warningMessage"][0]
|
29
|
+
elif data["warningMessage"]: # Handle string case
|
30
|
+
warning = data["warningMessage"]
|
31
|
+
|
32
|
+
# Get default values from HKO data
|
33
|
+
default_temp = next(
|
34
|
+
(
|
35
|
+
t
|
36
|
+
for t in data.get("temperature", {}).get("data", [])
|
37
|
+
if t.get("place") == "Hong Kong Observatory"
|
38
|
+
),
|
39
|
+
{"value": 25, "unit": "C", "recordTime": ""},
|
40
|
+
)
|
41
|
+
default_humidity = next(
|
42
|
+
(
|
43
|
+
h
|
44
|
+
for h in data.get("humidity", {}).get("data", [])
|
45
|
+
if h.get("place") == "Hong Kong Observatory"
|
46
|
+
),
|
47
|
+
{"value": 60, "unit": "percent", "recordTime": ""},
|
48
|
+
)
|
49
|
+
# Find matching region temperature
|
50
|
+
temp_data = data.get("temperature", {}).get("data", [])
|
51
|
+
matched_temp = next(
|
52
|
+
(t for t in temp_data if t["place"].lower() == region.lower()),
|
53
|
+
{
|
54
|
+
"place": "Hong Kong Observatory",
|
55
|
+
"value": default_temp["value"],
|
56
|
+
"unit": default_temp["unit"],
|
57
|
+
},
|
58
|
+
)
|
59
|
+
matched_temp["recordTime"] = data["temperature"]["recordTime"]
|
60
|
+
|
61
|
+
# Get humidity
|
62
|
+
humidity = next(
|
63
|
+
(
|
64
|
+
h
|
65
|
+
for h in data.get("humidity", {}).get("data", [])
|
66
|
+
if h.get("place") == matched_temp["place"]
|
67
|
+
),
|
68
|
+
default_humidity,
|
69
|
+
)
|
70
|
+
humidity["recordTime"] = data["humidity"]["recordTime"]
|
71
|
+
|
72
|
+
# Get rainfall (0 if no rain)
|
73
|
+
rainfall = 0
|
74
|
+
if "rainfall" in data:
|
75
|
+
rainfall = max(float(r.get("max", 0)) for r in data["rainfall"]["data"])
|
76
|
+
rainfall_start = data["rainfall"]["startTime"]
|
77
|
+
rainfall_end = data["rainfall"]["endTime"]
|
78
|
+
|
79
|
+
return {
|
80
|
+
"generalSituation": warning,
|
81
|
+
"weatherObservation": {
|
82
|
+
"temperature": {
|
83
|
+
"value": matched_temp["value"],
|
84
|
+
"unit": matched_temp["unit"],
|
85
|
+
"recordTime": matched_temp["recordTime"],
|
86
|
+
"place": matched_temp["place"]
|
87
|
+
},
|
88
|
+
"humidity": {
|
89
|
+
"value": humidity["value"],
|
90
|
+
"unit": humidity["unit"],
|
91
|
+
"recordTime": humidity["recordTime"],
|
92
|
+
"place": matched_temp["place"]
|
93
|
+
},
|
94
|
+
"rainfall": {
|
95
|
+
"value": rainfall,
|
96
|
+
"min": min(float(r.get("min", 0)) for r in data["rainfall"]["data"]),
|
97
|
+
"unit": "mm",
|
98
|
+
"startTime": rainfall_start,
|
99
|
+
"endTime": rainfall_end
|
100
|
+
},
|
101
|
+
"uvindex": data.get("uvindex", {})
|
102
|
+
},
|
103
|
+
"updateTime": data["updateTime"],
|
104
|
+
"icon": data.get("icon", []),
|
105
|
+
"iconUpdateTime": data.get("iconUpdateTime", "")
|
106
|
+
}
|
@@ -0,0 +1,82 @@
|
|
1
|
+
import requests
|
2
|
+
from typing import Dict, Any
|
3
|
+
|
4
|
+
def get_9_day_weather_forecast(lang: str = "en") -> Dict[str, Any]:
|
5
|
+
"""
|
6
|
+
Get the 9-day weather forecast for Hong Kong.
|
7
|
+
|
8
|
+
Args:
|
9
|
+
lang: Language code (en/tc/sc, default: en)
|
10
|
+
|
11
|
+
Returns:
|
12
|
+
Dict containing:
|
13
|
+
- generalSituation: General weather situation
|
14
|
+
- weatherForecast: List of daily forecast dicts (date, week, wind, weather, temp/humidity, etc.)
|
15
|
+
- updateTime: Last update time
|
16
|
+
- seaTemp: Sea temperature info
|
17
|
+
- soilTemp: List of soil temperature info
|
18
|
+
"""
|
19
|
+
url = f"https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=fnd&lang={lang}"
|
20
|
+
response = requests.get(url)
|
21
|
+
try:
|
22
|
+
response.raise_for_status()
|
23
|
+
data = response.json()
|
24
|
+
except (requests.RequestException, ValueError) as e:
|
25
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
26
|
+
|
27
|
+
# Structure the output
|
28
|
+
forecast = {
|
29
|
+
"generalSituation": data.get("generalSituation", ""),
|
30
|
+
"weatherForecast": [],
|
31
|
+
"updateTime": data.get("updateTime", ""),
|
32
|
+
"seaTemp": data.get("seaTemp", {}),
|
33
|
+
"soilTemp": data.get("soilTemp", []),
|
34
|
+
}
|
35
|
+
|
36
|
+
# Extract 9-day forecast
|
37
|
+
for day in data.get("weatherForecast", []):
|
38
|
+
forecast["weatherForecast"].append({
|
39
|
+
"forecastDate": day.get("forecastDate", ""),
|
40
|
+
"week": day.get("week", ""),
|
41
|
+
"forecastWind": day.get("forecastWind", ""),
|
42
|
+
"forecastWeather": day.get("forecastWeather", ""),
|
43
|
+
"forecastMaxtemp": day.get("forecastMaxtemp", {}),
|
44
|
+
"forecastMintemp": day.get("forecastMintemp", {}),
|
45
|
+
"forecastMaxrh": day.get("forecastMaxrh", {}),
|
46
|
+
"forecastMinrh": day.get("forecastMinrh", {}),
|
47
|
+
"ForecastIcon": day.get("ForecastIcon", ""),
|
48
|
+
"PSR": day.get("PSR", ""),
|
49
|
+
})
|
50
|
+
return forecast
|
51
|
+
|
52
|
+
def get_local_weather_forecast(lang: str = "en") -> Dict[str, Any]:
|
53
|
+
"""
|
54
|
+
Get local weather forecast for Hong Kong.
|
55
|
+
|
56
|
+
Args:
|
57
|
+
lang: Language code (en/tc/sc, default: en)
|
58
|
+
|
59
|
+
Returns:
|
60
|
+
Dict containing:
|
61
|
+
- forecastDesc: Forecast description
|
62
|
+
- outlook: Outlook forecast
|
63
|
+
- updateTime: Last update time
|
64
|
+
- forecastPeriod: Forecast period
|
65
|
+
- forecastDate: Forecast date
|
66
|
+
"""
|
67
|
+
url = f"https://data.weather.gov.hk/weatherAPI/opendata/weather.php?dataType=flw&lang={lang}"
|
68
|
+
response = requests.get(url)
|
69
|
+
try:
|
70
|
+
response.raise_for_status()
|
71
|
+
data = response.json()
|
72
|
+
except (requests.RequestException, ValueError) as e:
|
73
|
+
return {"error": f"Failed to fetch data: {str(e)}."}
|
74
|
+
|
75
|
+
return {
|
76
|
+
"generalSituation": data.get("generalSituation", ""),
|
77
|
+
"forecastDesc": data.get("forecastDesc", ""),
|
78
|
+
"outlook": data.get("outlook", ""),
|
79
|
+
"updateTime": data.get("updateTime", ""),
|
80
|
+
"forecastPeriod": data.get("forecastPeriod", ""),
|
81
|
+
"forecastDate": data.get("forecastDate", ""),
|
82
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import requests
|
2
|
+
from typing import Dict, Any
|
3
|
+
|
4
|
+
def get_lightning_data(lang: str = "en") -> Dict[str, Any]:
|
5
|
+
"""
|
6
|
+
Get cloud-to-ground and cloud-to-cloud lightning count data.
|
7
|
+
|
8
|
+
Args:
|
9
|
+
lang: Language code (en/tc/sc, default: en)
|
10
|
+
|
11
|
+
Returns:
|
12
|
+
Dict containing lightning data with fields and data arrays
|
13
|
+
"""
|
14
|
+
url = f"https://data.weather.gov.hk/weatherAPI/opendata/opendata.php?dataType=LHL&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)}."}
|