PyHolfuy 0.2__tar.gz → 0.3__tar.gz
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.
- {pyholfuy-0.2/pyholfuy.egg-info → pyholfuy-0.3}/PKG-INFO +17 -5
- pyholfuy-0.3/README.md +38 -0
- {pyholfuy-0.2 → pyholfuy-0.3}/holfuy/__init__.py +65 -28
- {pyholfuy-0.2 → pyholfuy-0.3}/holfuy/const.py +4 -4
- pyholfuy-0.3/holfuy/exceptions.py +13 -0
- {pyholfuy-0.2 → pyholfuy-0.3}/holfuy/test_holfuy.py +44 -22
- {pyholfuy-0.2 → pyholfuy-0.3/pyholfuy.egg-info}/PKG-INFO +17 -5
- {pyholfuy-0.2 → pyholfuy-0.3}/pyholfuy.egg-info/SOURCES.txt +1 -0
- {pyholfuy-0.2 → pyholfuy-0.3}/pyproject.toml +1 -1
- pyholfuy-0.2/README.md +0 -26
- {pyholfuy-0.2 → pyholfuy-0.3}/LICENSE +0 -0
- {pyholfuy-0.2 → pyholfuy-0.3}/MANIFEST.in +0 -0
- {pyholfuy-0.2 → pyholfuy-0.3}/pyholfuy.egg-info/dependency_links.txt +0 -0
- {pyholfuy-0.2 → pyholfuy-0.3}/pyholfuy.egg-info/requires.txt +0 -0
- {pyholfuy-0.2 → pyholfuy-0.3}/pyholfuy.egg-info/top_level.txt +0 -0
- {pyholfuy-0.2 → pyholfuy-0.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyholfuy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3
|
|
4
4
|
Summary: A Python library for interacting with Holfuy weather stations.
|
|
5
5
|
Author-email: Håvard Dagenborg <haavardj@dagenborg.net>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,7 +26,7 @@ A Python library for talking to [Holfuy Weather Stations](https://holfuy.com/).
|
|
|
26
26
|
|
|
27
27
|
You need an API key to access the service. To obtain one, please visit the [Holfuy API](https://api.holfuy.com/live/) pages.
|
|
28
28
|
|
|
29
|
-
The
|
|
29
|
+
The library can only access live data.
|
|
30
30
|
|
|
31
31
|
## Example Code
|
|
32
32
|
Here is an example of how to use the library.
|
|
@@ -38,10 +38,22 @@ from holfuy import HolfuyService
|
|
|
38
38
|
|
|
39
39
|
async def main():
|
|
40
40
|
async with aiohttp.ClientSession() as session:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
s = HolfuyService("", session)
|
|
42
|
+
data = await s.fetch_data(["101"])
|
|
43
|
+
print(data)
|
|
44
44
|
|
|
45
45
|
if __name__ == "__main__":
|
|
46
46
|
asyncio.run(main())
|
|
47
47
|
```
|
|
48
|
+
|
|
49
|
+
## Return value and errors
|
|
50
|
+
|
|
51
|
+
`fetch_data()` returns `{"measurements": [...]}` with one entry per station, also when
|
|
52
|
+
a single station is requested. A station the key cannot read is still listed, with
|
|
53
|
+
`error` and `errorCode` instead of data.
|
|
54
|
+
|
|
55
|
+
It raises, all subclasses of `holfuy.HolfuyError`:
|
|
56
|
+
|
|
57
|
+
- `HolfuyAuthError`: the API key is rejected, or it has no access to any requested station.
|
|
58
|
+
- `HolfuyConnectionError`: network error, timeout, or an HTTP error status.
|
|
59
|
+
- `HolfuyError`: any other unexpected reply.
|
pyholfuy-0.3/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# PyHolfuy
|
|
4
|
+
A Python library for talking to [Holfuy Weather Stations](https://holfuy.com/).
|
|
5
|
+
|
|
6
|
+
You need an API key to access the service. To obtain one, please visit the [Holfuy API](https://api.holfuy.com/live/) pages.
|
|
7
|
+
|
|
8
|
+
The library can only access live data.
|
|
9
|
+
|
|
10
|
+
## Example Code
|
|
11
|
+
Here is an example of how to use the library.
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import aiohttp
|
|
15
|
+
import asyncio
|
|
16
|
+
from holfuy import HolfuyService
|
|
17
|
+
|
|
18
|
+
async def main():
|
|
19
|
+
async with aiohttp.ClientSession() as session:
|
|
20
|
+
s = HolfuyService("", session)
|
|
21
|
+
data = await s.fetch_data(["101"])
|
|
22
|
+
print(data)
|
|
23
|
+
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
asyncio.run(main())
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Return value and errors
|
|
29
|
+
|
|
30
|
+
`fetch_data()` returns `{"measurements": [...]}` with one entry per station, also when
|
|
31
|
+
a single station is requested. A station the key cannot read is still listed, with
|
|
32
|
+
`error` and `errorCode` instead of data.
|
|
33
|
+
|
|
34
|
+
It raises, all subclasses of `holfuy.HolfuyError`:
|
|
35
|
+
|
|
36
|
+
- `HolfuyAuthError`: the API key is rejected, or it has no access to any requested station.
|
|
37
|
+
- `HolfuyConnectionError`: network error, timeout, or an HTTP error status.
|
|
38
|
+
- `HolfuyError`: any other unexpected reply.
|
|
@@ -15,15 +15,23 @@ from .const import (
|
|
|
15
15
|
CONF_MODE_JSON,
|
|
16
16
|
STATIONS_ALL,
|
|
17
17
|
)
|
|
18
|
+
from .exceptions import HolfuyAuthError, HolfuyConnectionError, HolfuyError
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"HolfuyAuthError",
|
|
22
|
+
"HolfuyConnectionError",
|
|
23
|
+
"HolfuyError",
|
|
24
|
+
"HolfuyService",
|
|
25
|
+
]
|
|
18
26
|
|
|
19
27
|
TIMEOUT = 30
|
|
20
28
|
_LOGGER = logging.getLogger(__name__)
|
|
21
29
|
|
|
22
|
-
API_URL = "
|
|
30
|
+
API_URL = "https://api.holfuy.com/live/"
|
|
23
31
|
|
|
24
32
|
# noqa: E501
|
|
25
33
|
#### API Description
|
|
26
|
-
# URL Format:
|
|
34
|
+
# URL Format: https://api.holfuy.com/live/?s=101&pw=pass&m=JSON&tu=C&su=m/s
|
|
27
35
|
#
|
|
28
36
|
# s: station(s) ID e.g. s=101 or you can get the data from more stations by one query as well (coma separated list) e.g. s=101,102,103 . If you would get all stations' data (to which you have access) by one single API call please use the "all" string -> s=all .
|
|
29
37
|
# pw: password for the API access (it could be sent by a POST "pw" parameter also)
|
|
@@ -68,8 +76,16 @@ class HolfuyService:
|
|
|
68
76
|
include_battery=False,
|
|
69
77
|
include_daily=False,
|
|
70
78
|
include_location=False,
|
|
71
|
-
) -> dict[str, Any]
|
|
72
|
-
"""Get the latest data from Holfuy.
|
|
79
|
+
) -> dict[str, Any]:
|
|
80
|
+
"""Get the latest data from Holfuy.
|
|
81
|
+
|
|
82
|
+
Returns {"measurements": [...]}, one entry per station. A station the key
|
|
83
|
+
cannot read is still listed, with "error" and "errorCode" instead of data.
|
|
84
|
+
|
|
85
|
+
Raises HolfuyAuthError if the key is rejected or can read none of the
|
|
86
|
+
requested stations, HolfuyConnectionError on network errors, timeouts and
|
|
87
|
+
HTTP errors, and HolfuyError on any other unexpected reply.
|
|
88
|
+
"""
|
|
73
89
|
|
|
74
90
|
params = {
|
|
75
91
|
"pw": self._api_key,
|
|
@@ -97,29 +113,50 @@ class HolfuyService:
|
|
|
97
113
|
params["s"] = STATIONS_ALL
|
|
98
114
|
|
|
99
115
|
try:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
# The timeout covers the whole exchange, body included, and the
|
|
117
|
+
# context manager releases the connection back to the pool.
|
|
118
|
+
async with (
|
|
119
|
+
asyncio.timeout(TIMEOUT),
|
|
120
|
+
self._session.get(self._api_url, params=params) as resp,
|
|
121
|
+
):
|
|
122
|
+
if resp.status >= 400:
|
|
123
|
+
raise HolfuyConnectionError(
|
|
124
|
+
f"Holfuy API returned HTTP {resp.status}"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# A rejected key gets HTTP 200 with the plain text "No access".
|
|
128
|
+
if resp.content_type != "application/json":
|
|
129
|
+
text = (await resp.text()).strip()
|
|
130
|
+
if text.lower().startswith("no access"):
|
|
131
|
+
raise HolfuyAuthError("Holfuy API rejected the API key")
|
|
132
|
+
raise HolfuyError(
|
|
133
|
+
f"Unexpected response from Holfuy API: {text[:100]!r}"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
result = await resp.json()
|
|
117
137
|
|
|
118
138
|
except (TimeoutError, aiohttp.ClientError) as err:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
139
|
+
# Only the type name: aiohttp messages can contain the URL, and
|
|
140
|
+
# with it the API key.
|
|
141
|
+
raise HolfuyConnectionError(
|
|
142
|
+
f"Cannot reach Holfuy API: {type(err).__name__}"
|
|
143
|
+
) from err
|
|
144
|
+
except ValueError as err:
|
|
145
|
+
raise HolfuyError("Unable to parse JSON response from Holfuy API") from err
|
|
146
|
+
|
|
147
|
+
# Request for a single station is not enveloped in a list of
|
|
148
|
+
# measurements objects. Make data consistent for all request types before it
|
|
149
|
+
# is returned.
|
|
150
|
+
if stations and len(stations) == 1:
|
|
151
|
+
result = {"measurements": [result]}
|
|
152
|
+
|
|
153
|
+
measurements = result.get("measurements") if isinstance(result, dict) else None
|
|
154
|
+
if not isinstance(measurements, list):
|
|
155
|
+
raise HolfuyError("Unexpected response from Holfuy API: no measurements")
|
|
156
|
+
|
|
157
|
+
if measurements and all(
|
|
158
|
+
m.get("errorCode") == "no_access" for m in measurements
|
|
159
|
+
):
|
|
160
|
+
raise HolfuyAuthError("API key has no access to the requested stations")
|
|
161
|
+
|
|
162
|
+
return result
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
CONF_MODE_JSON = "JSON" # We only handle JSON from the api
|
|
2
|
-
CONF_MODE_XML = "
|
|
3
|
-
CONF_MODE_CSV = "
|
|
2
|
+
CONF_MODE_XML = "XML"
|
|
3
|
+
CONF_MODE_CSV = "CSV"
|
|
4
4
|
|
|
5
5
|
CONF_AVERAGING_NEWEST = 0
|
|
6
6
|
CONF_AVERAGING_QUARTERLY = 1
|
|
@@ -11,8 +11,8 @@ CONF_WIND_SPEED_UNIT_KMH = "km/h"
|
|
|
11
11
|
CONF_WIND_SPEED_UNIT_MS = "m/s"
|
|
12
12
|
CONF_WIND_SPEED_UNIT_MPH = "mph"
|
|
13
13
|
|
|
14
|
-
CONF_TEMPERATURE_UNIT_CELSIUS = "
|
|
15
|
-
CONF_TEMPERATURE_UNIT_FAHRENHEIT = "
|
|
14
|
+
CONF_TEMPERATURE_UNIT_CELSIUS = "C"
|
|
15
|
+
CONF_TEMPERATURE_UNIT_FAHRENHEIT = "F"
|
|
16
16
|
|
|
17
17
|
CONF_OPTION_BATT = "batt"
|
|
18
18
|
CONF_OPTION_DAILY = "daily"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Exceptions raised by the Holfuy library."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class HolfuyError(Exception):
|
|
5
|
+
"""Base class for all Holfuy errors, raised as is for unexpected replies."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HolfuyConnectionError(HolfuyError):
|
|
9
|
+
"""The API could not be reached, timed out or returned an HTTP error."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class HolfuyAuthError(HolfuyError):
|
|
13
|
+
"""The API key was rejected, or it has no access to any requested station."""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from unittest import IsolatedAsyncioTestCase, mock
|
|
3
|
-
from unittest.mock import AsyncMock, patch
|
|
3
|
+
from unittest.mock import AsyncMock, MagicMock, patch
|
|
4
4
|
import json
|
|
5
5
|
|
|
6
6
|
import aiohttp
|
|
@@ -24,7 +24,19 @@ RESP_AUTHERROR=json.loads("""
|
|
|
24
24
|
{"measurements":[{"stationId":105,"error":"Sorry, you don't have access for this station.","errorCode":"no_access"},
|
|
25
25
|
{"stationId":106,"error":"Sorry, you don't have access for this station.","errorCode":"no_access"}]}""")
|
|
26
26
|
|
|
27
|
-
from holfuy import
|
|
27
|
+
from holfuy import (
|
|
28
|
+
HolfuyAuthError,
|
|
29
|
+
HolfuyConnectionError,
|
|
30
|
+
HolfuyService,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _get_returning(resp):
|
|
35
|
+
"""Mock session.get() as an async context manager yielding resp."""
|
|
36
|
+
ctx = MagicMock()
|
|
37
|
+
ctx.__aenter__ = AsyncMock(return_value=resp)
|
|
38
|
+
ctx.__aexit__ = AsyncMock(return_value=False)
|
|
39
|
+
return MagicMock(return_value=ctx)
|
|
28
40
|
|
|
29
41
|
from holfuy.const import (
|
|
30
42
|
CONF_TEMPERATURE_UNIT_CELSIUS,
|
|
@@ -51,9 +63,10 @@ class TestHolfuyService(IsolatedAsyncioTestCase):
|
|
|
51
63
|
|
|
52
64
|
mock_resp = AsyncMock()
|
|
53
65
|
mock_resp.status = 200
|
|
66
|
+
mock_resp.content_type = "application/json"
|
|
54
67
|
mock_resp.json = AsyncMock(return_value=mock_response)
|
|
55
68
|
|
|
56
|
-
self.session.get =
|
|
69
|
+
self.session.get = _get_returning(mock_resp)
|
|
57
70
|
|
|
58
71
|
result = await self.api.fetch_data(["142"])
|
|
59
72
|
|
|
@@ -67,7 +80,7 @@ class TestHolfuyService(IsolatedAsyncioTestCase):
|
|
|
67
80
|
}
|
|
68
81
|
|
|
69
82
|
self.session.get.assert_called_once_with(
|
|
70
|
-
"
|
|
83
|
+
"https://api.holfuy.com/live/",
|
|
71
84
|
params=expected_params
|
|
72
85
|
)
|
|
73
86
|
|
|
@@ -79,8 +92,9 @@ class TestHolfuyService(IsolatedAsyncioTestCase):
|
|
|
79
92
|
|
|
80
93
|
mock_resp = AsyncMock()
|
|
81
94
|
mock_resp.status = 200
|
|
95
|
+
mock_resp.content_type = "application/json"
|
|
82
96
|
mock_resp.json = AsyncMock(return_value=mock_response)
|
|
83
|
-
self.session.get =
|
|
97
|
+
self.session.get = _get_returning(mock_resp)
|
|
84
98
|
|
|
85
99
|
result = await self.api.fetch_data(None)
|
|
86
100
|
|
|
@@ -94,7 +108,7 @@ class TestHolfuyService(IsolatedAsyncioTestCase):
|
|
|
94
108
|
}
|
|
95
109
|
|
|
96
110
|
self.session.get.assert_called_once_with(
|
|
97
|
-
"
|
|
111
|
+
"https://api.holfuy.com/live/",
|
|
98
112
|
params=expected_params
|
|
99
113
|
)
|
|
100
114
|
|
|
@@ -105,23 +119,24 @@ class TestHolfuyService(IsolatedAsyncioTestCase):
|
|
|
105
119
|
mock_resp = AsyncMock()
|
|
106
120
|
mock_resp.status = 404
|
|
107
121
|
|
|
108
|
-
self.session.get =
|
|
122
|
+
self.session.get = _get_returning(mock_resp)
|
|
109
123
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
self.assertIsNone(result)
|
|
124
|
+
with self.assertRaises(HolfuyConnectionError):
|
|
125
|
+
await self.api.fetch_data(None)
|
|
113
126
|
|
|
114
127
|
async def test_fetch_data_invalid_access_token(self):
|
|
115
128
|
"""Test handling of error responses."""
|
|
116
129
|
mock_resp = AsyncMock()
|
|
117
130
|
mock_resp.status = 200
|
|
131
|
+
mock_resp.content_type = "application/json"
|
|
118
132
|
mock_response = RESP_AUTHERROR
|
|
119
133
|
|
|
120
134
|
mock_resp.json = AsyncMock(return_value=mock_response)
|
|
121
135
|
|
|
122
|
-
self.session.get =
|
|
136
|
+
self.session.get = _get_returning(mock_resp)
|
|
123
137
|
|
|
124
|
-
|
|
138
|
+
with self.assertRaises(HolfuyAuthError):
|
|
139
|
+
await self.api.fetch_data(["105","106"])
|
|
125
140
|
|
|
126
141
|
expected_params = {
|
|
127
142
|
"pw": "test_api_key",
|
|
@@ -133,24 +148,31 @@ class TestHolfuyService(IsolatedAsyncioTestCase):
|
|
|
133
148
|
}
|
|
134
149
|
|
|
135
150
|
self.session.get.assert_called_once_with(
|
|
136
|
-
"
|
|
151
|
+
"https://api.holfuy.com/live/",
|
|
137
152
|
params=expected_params
|
|
138
153
|
)
|
|
139
154
|
|
|
140
|
-
self.assertEqual(result["measurements"][0]["stationId"], 105)
|
|
141
|
-
|
|
142
155
|
async def test_fetch_data_timeout(self):
|
|
143
156
|
"""Test handling of timeout errors."""
|
|
144
|
-
self.session.get =
|
|
157
|
+
self.session.get = MagicMock(side_effect=asyncio.TimeoutError)
|
|
145
158
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
self.assertIsNone(result)
|
|
159
|
+
with self.assertRaises(HolfuyConnectionError):
|
|
160
|
+
await self.api.fetch_data(None)
|
|
149
161
|
|
|
150
162
|
async def test_fetch_data_client_error(self):
|
|
151
163
|
"""Test handling of client errors."""
|
|
152
|
-
self.session.get =
|
|
164
|
+
self.session.get = MagicMock(side_effect=aiohttp.ClientError)
|
|
153
165
|
|
|
154
|
-
|
|
166
|
+
with self.assertRaises(HolfuyConnectionError):
|
|
167
|
+
await self.api.fetch_data(None)
|
|
168
|
+
|
|
169
|
+
async def test_fetch_data_rejected_key(self):
|
|
170
|
+
"""A rejected key gets HTTP 200 with a plain-text "No access" body."""
|
|
171
|
+
mock_resp = AsyncMock()
|
|
172
|
+
mock_resp.status = 200
|
|
173
|
+
mock_resp.content_type = "text/html"
|
|
174
|
+
mock_resp.text = AsyncMock(return_value="No access")
|
|
175
|
+
self.session.get = _get_returning(mock_resp)
|
|
155
176
|
|
|
156
|
-
self.
|
|
177
|
+
with self.assertRaises(HolfuyAuthError):
|
|
178
|
+
await self.api.fetch_data(None)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyholfuy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3
|
|
4
4
|
Summary: A Python library for interacting with Holfuy weather stations.
|
|
5
5
|
Author-email: Håvard Dagenborg <haavardj@dagenborg.net>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,7 +26,7 @@ A Python library for talking to [Holfuy Weather Stations](https://holfuy.com/).
|
|
|
26
26
|
|
|
27
27
|
You need an API key to access the service. To obtain one, please visit the [Holfuy API](https://api.holfuy.com/live/) pages.
|
|
28
28
|
|
|
29
|
-
The
|
|
29
|
+
The library can only access live data.
|
|
30
30
|
|
|
31
31
|
## Example Code
|
|
32
32
|
Here is an example of how to use the library.
|
|
@@ -38,10 +38,22 @@ from holfuy import HolfuyService
|
|
|
38
38
|
|
|
39
39
|
async def main():
|
|
40
40
|
async with aiohttp.ClientSession() as session:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
s = HolfuyService("", session)
|
|
42
|
+
data = await s.fetch_data(["101"])
|
|
43
|
+
print(data)
|
|
44
44
|
|
|
45
45
|
if __name__ == "__main__":
|
|
46
46
|
asyncio.run(main())
|
|
47
47
|
```
|
|
48
|
+
|
|
49
|
+
## Return value and errors
|
|
50
|
+
|
|
51
|
+
`fetch_data()` returns `{"measurements": [...]}` with one entry per station, also when
|
|
52
|
+
a single station is requested. A station the key cannot read is still listed, with
|
|
53
|
+
`error` and `errorCode` instead of data.
|
|
54
|
+
|
|
55
|
+
It raises, all subclasses of `holfuy.HolfuyError`:
|
|
56
|
+
|
|
57
|
+
- `HolfuyAuthError`: the API key is rejected, or it has no access to any requested station.
|
|
58
|
+
- `HolfuyConnectionError`: network error, timeout, or an HTTP error status.
|
|
59
|
+
- `HolfuyError`: any other unexpected reply.
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "pyholfuy"
|
|
9
|
-
version = "0.
|
|
9
|
+
version = "0.3"
|
|
10
10
|
description = "A Python library for interacting with Holfuy weather stations."
|
|
11
11
|
authors = [{name="Håvard Dagenborg", email="haavardj@dagenborg.net"}]
|
|
12
12
|
license = "MIT"
|
pyholfuy-0.2/README.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
|
-
# PyHolfuy
|
|
4
|
-
A Python library for talking to [Holfuy Weather Stations](https://holfuy.com/).
|
|
5
|
-
|
|
6
|
-
You need an API key to access the service. To obtain one, please visit the [Holfuy API](https://api.holfuy.com/live/) pages.
|
|
7
|
-
|
|
8
|
-
The Library only access live data.
|
|
9
|
-
|
|
10
|
-
## Example Code
|
|
11
|
-
Here is an example of how to use the library.
|
|
12
|
-
|
|
13
|
-
```python
|
|
14
|
-
import aiohttp
|
|
15
|
-
import asyncio
|
|
16
|
-
from holfuy import HolfuyService
|
|
17
|
-
|
|
18
|
-
async def main():
|
|
19
|
-
async with aiohttp.ClientSession() as session:
|
|
20
|
-
s = HolfuyService("", session)
|
|
21
|
-
data = await s.fetch_data(["101"])
|
|
22
|
-
print(data)
|
|
23
|
-
|
|
24
|
-
if __name__ == "__main__":
|
|
25
|
-
asyncio.run(main())
|
|
26
|
-
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|