pytigo 0.3.0__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.
- pytigo-0.3.0/LICENSE +21 -0
- pytigo-0.3.0/MANIFEST.in +2 -0
- pytigo-0.3.0/PKG-INFO +108 -0
- pytigo-0.3.0/README.md +81 -0
- pytigo-0.3.0/pyproject.toml +43 -0
- pytigo-0.3.0/setup.cfg +4 -0
- pytigo-0.3.0/src/pytigo/__init__.py +6 -0
- pytigo-0.3.0/src/pytigo/client.py +297 -0
- pytigo-0.3.0/src/pytigo/models.py +232 -0
- pytigo-0.3.0/src/pytigo/parsing.py +354 -0
- pytigo-0.3.0/src/pytigo.egg-info/PKG-INFO +108 -0
- pytigo-0.3.0/src/pytigo.egg-info/SOURCES.txt +16 -0
- pytigo-0.3.0/src/pytigo.egg-info/dependency_links.txt +1 -0
- pytigo-0.3.0/src/pytigo.egg-info/requires.txt +6 -0
- pytigo-0.3.0/src/pytigo.egg-info/top_level.txt +1 -0
- pytigo-0.3.0/tests/test_api_client.py +100 -0
- pytigo-0.3.0/tests/test_api_parsing.py +316 -0
- pytigo-0.3.0/tests/test_packaging.py +26 -0
pytigo-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Blind Badger Studios
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pytigo-0.3.0/MANIFEST.in
ADDED
pytigo-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytigo
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Python client for the documented Tigo REST API v3
|
|
5
|
+
Author: Blind Badger Studios
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/BlindBadgerStudios/PyTigo
|
|
8
|
+
Project-URL: Repository, https://github.com/BlindBadgerStudios/PyTigo
|
|
9
|
+
Project-URL: Issues, https://github.com/BlindBadgerStudios/PyTigo/issues
|
|
10
|
+
Keywords: tigo,solar,energy,monitoring,photovoltaic,pv,api
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Topic :: Home Automation
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: requests>=2.31.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
24
|
+
Requires-Dist: build; extra == "dev"
|
|
25
|
+
Requires-Dist: twine; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# pytigo
|
|
29
|
+
|
|
30
|
+
pytigo is a Python client for the documented Tigo REST API v3. It is focussed on near-real time monitoring (for time-series systems like Prometheus).
|
|
31
|
+
|
|
32
|
+
It is centered on the official API described in Tigo-API-V3.pdf, using:
|
|
33
|
+
- base URL: https://api2.tigoenergy.com/api/v3/
|
|
34
|
+
- token auth from `users/login`
|
|
35
|
+
- documented systems, objects, sources, and data endpoints
|
|
36
|
+
|
|
37
|
+
Supported official API areas:
|
|
38
|
+
- users/login
|
|
39
|
+
- users/logout
|
|
40
|
+
- users/get
|
|
41
|
+
- systems/list
|
|
42
|
+
- systems/view
|
|
43
|
+
- systems/layout
|
|
44
|
+
- objects/system
|
|
45
|
+
- objects/types
|
|
46
|
+
- sources/system
|
|
47
|
+
- data/summary
|
|
48
|
+
- data/aggregate
|
|
49
|
+
- data/combined
|
|
50
|
+
- alerts/system
|
|
51
|
+
- alerts/types
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install pytigo
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick start
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from pytigo import TigoClient
|
|
63
|
+
|
|
64
|
+
client = TigoClient(username="you@example.com", password="super-secret")
|
|
65
|
+
auth = client.login()
|
|
66
|
+
|
|
67
|
+
systems = client.list_systems()
|
|
68
|
+
system = systems[0]
|
|
69
|
+
|
|
70
|
+
layout = client.get_layout(system.system_id)
|
|
71
|
+
objects = client.get_objects(system.system_id)
|
|
72
|
+
sources = client.get_sources(system.system_id)
|
|
73
|
+
summary = client.get_summary(system.system_id)
|
|
74
|
+
aggregate = client.get_aggregate(
|
|
75
|
+
system.system_id,
|
|
76
|
+
start="2026-03-31T00:00:00",
|
|
77
|
+
end="2026-03-31T23:59:59",
|
|
78
|
+
level="day",
|
|
79
|
+
param="Pin",
|
|
80
|
+
)
|
|
81
|
+
combined = client.get_combined(
|
|
82
|
+
system.system_id,
|
|
83
|
+
start="2026-03-31T00:00:00",
|
|
84
|
+
end="2026-03-31T23:59:59",
|
|
85
|
+
agg="day",
|
|
86
|
+
)
|
|
87
|
+
alerts = client.get_alerts(system.system_id, limit=10)
|
|
88
|
+
alert_types = client.get_alert_types()
|
|
89
|
+
|
|
90
|
+
print(auth.user_id)
|
|
91
|
+
print(system.name)
|
|
92
|
+
print(layout.inverters[0].label if layout.inverters else None)
|
|
93
|
+
print(len(objects))
|
|
94
|
+
print(sources[0].serial if sources else None)
|
|
95
|
+
print(summary.daily_energy_dc)
|
|
96
|
+
print(aggregate.rows[0].values)
|
|
97
|
+
print(combined.rows[0].values)
|
|
98
|
+
print(alerts[0].title if alerts else None)
|
|
99
|
+
print(alert_types[0].title if alert_types else None)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Notes
|
|
103
|
+
|
|
104
|
+
The library returns typed Python models for JSON endpoints and a parsed table model for CSV-style telemetry endpoints like `data/aggregate` and `data/combined`.
|
|
105
|
+
|
|
106
|
+
`data/aggregate` and `data/combined` are especially useful for exporter/monitoring use cases because they preserve timestamped telemetry in a table-shaped format that is easy to flatten for Prometheus, Grafana, or ETL pipelines.
|
|
107
|
+
|
|
108
|
+
|
pytigo-0.3.0/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# pytigo
|
|
2
|
+
|
|
3
|
+
pytigo is a Python client for the documented Tigo REST API v3. It is focussed on near-real time monitoring (for time-series systems like Prometheus).
|
|
4
|
+
|
|
5
|
+
It is centered on the official API described in Tigo-API-V3.pdf, using:
|
|
6
|
+
- base URL: https://api2.tigoenergy.com/api/v3/
|
|
7
|
+
- token auth from `users/login`
|
|
8
|
+
- documented systems, objects, sources, and data endpoints
|
|
9
|
+
|
|
10
|
+
Supported official API areas:
|
|
11
|
+
- users/login
|
|
12
|
+
- users/logout
|
|
13
|
+
- users/get
|
|
14
|
+
- systems/list
|
|
15
|
+
- systems/view
|
|
16
|
+
- systems/layout
|
|
17
|
+
- objects/system
|
|
18
|
+
- objects/types
|
|
19
|
+
- sources/system
|
|
20
|
+
- data/summary
|
|
21
|
+
- data/aggregate
|
|
22
|
+
- data/combined
|
|
23
|
+
- alerts/system
|
|
24
|
+
- alerts/types
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install pytigo
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from pytigo import TigoClient
|
|
36
|
+
|
|
37
|
+
client = TigoClient(username="you@example.com", password="super-secret")
|
|
38
|
+
auth = client.login()
|
|
39
|
+
|
|
40
|
+
systems = client.list_systems()
|
|
41
|
+
system = systems[0]
|
|
42
|
+
|
|
43
|
+
layout = client.get_layout(system.system_id)
|
|
44
|
+
objects = client.get_objects(system.system_id)
|
|
45
|
+
sources = client.get_sources(system.system_id)
|
|
46
|
+
summary = client.get_summary(system.system_id)
|
|
47
|
+
aggregate = client.get_aggregate(
|
|
48
|
+
system.system_id,
|
|
49
|
+
start="2026-03-31T00:00:00",
|
|
50
|
+
end="2026-03-31T23:59:59",
|
|
51
|
+
level="day",
|
|
52
|
+
param="Pin",
|
|
53
|
+
)
|
|
54
|
+
combined = client.get_combined(
|
|
55
|
+
system.system_id,
|
|
56
|
+
start="2026-03-31T00:00:00",
|
|
57
|
+
end="2026-03-31T23:59:59",
|
|
58
|
+
agg="day",
|
|
59
|
+
)
|
|
60
|
+
alerts = client.get_alerts(system.system_id, limit=10)
|
|
61
|
+
alert_types = client.get_alert_types()
|
|
62
|
+
|
|
63
|
+
print(auth.user_id)
|
|
64
|
+
print(system.name)
|
|
65
|
+
print(layout.inverters[0].label if layout.inverters else None)
|
|
66
|
+
print(len(objects))
|
|
67
|
+
print(sources[0].serial if sources else None)
|
|
68
|
+
print(summary.daily_energy_dc)
|
|
69
|
+
print(aggregate.rows[0].values)
|
|
70
|
+
print(combined.rows[0].values)
|
|
71
|
+
print(alerts[0].title if alerts else None)
|
|
72
|
+
print(alert_types[0].title if alert_types else None)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Notes
|
|
76
|
+
|
|
77
|
+
The library returns typed Python models for JSON endpoints and a parsed table model for CSV-style telemetry endpoints like `data/aggregate` and `data/combined`.
|
|
78
|
+
|
|
79
|
+
`data/aggregate` and `data/combined` are especially useful for exporter/monitoring use cases because they preserve timestamped telemetry in a table-shaped format that is easy to flatten for Prometheus, Grafana, or ETL pipelines.
|
|
80
|
+
|
|
81
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pytigo"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Python client for the documented Tigo REST API v3"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Blind Badger Studios" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["tigo", "solar", "energy", "monitoring", "photovoltaic", "pv", "api"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Topic :: Home Automation",
|
|
22
|
+
"Topic :: Scientific/Engineering",
|
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"requests>=2.31.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/BlindBadgerStudios/PyTigo"
|
|
31
|
+
Repository = "https://github.com/BlindBadgerStudios/PyTigo"
|
|
32
|
+
Issues = "https://github.com/BlindBadgerStudios/PyTigo/issues"
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest>=8.0",
|
|
37
|
+
"build",
|
|
38
|
+
"twine",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[tool.pytest.ini_options]
|
|
42
|
+
pythonpath = ["src"]
|
|
43
|
+
testpaths = ["tests"]
|
pytigo-0.3.0/setup.cfg
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from requests import Session
|
|
7
|
+
|
|
8
|
+
from .models import (
|
|
9
|
+
TigoAlert,
|
|
10
|
+
TigoAlertType,
|
|
11
|
+
TigoAuth,
|
|
12
|
+
TigoCSVTable,
|
|
13
|
+
TigoObjectNode,
|
|
14
|
+
TigoObjectType,
|
|
15
|
+
TigoPage,
|
|
16
|
+
TigoSource,
|
|
17
|
+
TigoSummary,
|
|
18
|
+
TigoSystem,
|
|
19
|
+
TigoSystemLayout,
|
|
20
|
+
TigoUser,
|
|
21
|
+
)
|
|
22
|
+
from .parsing import (
|
|
23
|
+
parse_alert_types_response,
|
|
24
|
+
parse_alerts_response,
|
|
25
|
+
parse_csv_table,
|
|
26
|
+
parse_layout_response,
|
|
27
|
+
parse_login_response,
|
|
28
|
+
parse_object_types_response,
|
|
29
|
+
parse_objects_response,
|
|
30
|
+
parse_sources_response,
|
|
31
|
+
parse_summary_response,
|
|
32
|
+
parse_system_response,
|
|
33
|
+
parse_systems_response,
|
|
34
|
+
parse_user_response,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TigoClient:
|
|
41
|
+
api_root = "https://api2.tigoenergy.com/api/v3"
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
username: str,
|
|
46
|
+
password: str,
|
|
47
|
+
*,
|
|
48
|
+
session: Session | None = None,
|
|
49
|
+
timeout: int = 30,
|
|
50
|
+
) -> None:
|
|
51
|
+
self.username = username
|
|
52
|
+
self.password = password
|
|
53
|
+
self.timeout = timeout
|
|
54
|
+
self.session = session or Session()
|
|
55
|
+
self.auth: TigoAuth | None = None
|
|
56
|
+
|
|
57
|
+
def _headers(self) -> dict[str, str]:
|
|
58
|
+
if not self.auth:
|
|
59
|
+
raise ValueError("Not authenticated. Call login() first.")
|
|
60
|
+
return {"Authorization": f"Bearer {self.auth.auth_token}"}
|
|
61
|
+
|
|
62
|
+
def __enter__(self) -> TigoClient:
|
|
63
|
+
return self
|
|
64
|
+
|
|
65
|
+
def __exit__(self, *args: object) -> None:
|
|
66
|
+
self.session.close()
|
|
67
|
+
|
|
68
|
+
def login(self) -> TigoAuth:
|
|
69
|
+
logger.debug("GET /users/login user=%s", self.username)
|
|
70
|
+
response = self.session.get(
|
|
71
|
+
f"{self.api_root}/users/login",
|
|
72
|
+
auth=(self.username, self.password),
|
|
73
|
+
timeout=self.timeout,
|
|
74
|
+
)
|
|
75
|
+
response.raise_for_status()
|
|
76
|
+
self.auth = parse_login_response(response.json())
|
|
77
|
+
logger.debug("login successful user_id=%s", self.auth.user_id)
|
|
78
|
+
return self.auth
|
|
79
|
+
|
|
80
|
+
def logout(self) -> dict:
|
|
81
|
+
logger.debug("GET /users/logout")
|
|
82
|
+
response = self.session.get(
|
|
83
|
+
f"{self.api_root}/users/logout",
|
|
84
|
+
headers=self._headers(),
|
|
85
|
+
timeout=self.timeout,
|
|
86
|
+
)
|
|
87
|
+
response.raise_for_status()
|
|
88
|
+
payload = response.json()
|
|
89
|
+
self.auth = None
|
|
90
|
+
return payload
|
|
91
|
+
|
|
92
|
+
def get_current_user(self, user_id: int | None = None) -> TigoUser:
|
|
93
|
+
if user_id is None:
|
|
94
|
+
if not self.auth:
|
|
95
|
+
raise ValueError("user_id is required before login; after login it defaults to auth.user_id")
|
|
96
|
+
user_id = self.auth.user_id
|
|
97
|
+
logger.debug("GET /users/%s", user_id)
|
|
98
|
+
response = self.session.get(
|
|
99
|
+
f"{self.api_root}/users/{user_id}",
|
|
100
|
+
headers=self._headers(),
|
|
101
|
+
timeout=self.timeout,
|
|
102
|
+
)
|
|
103
|
+
response.raise_for_status()
|
|
104
|
+
return parse_user_response(response.json())
|
|
105
|
+
|
|
106
|
+
def list_systems(self, *, page: int | None = None, limit: int | None = None, sort: str | None = None) -> TigoPage[TigoSystem]:
|
|
107
|
+
params: dict[str, int | str] = {}
|
|
108
|
+
if page is not None:
|
|
109
|
+
params["page"] = page
|
|
110
|
+
if limit is not None:
|
|
111
|
+
params["limit"] = limit
|
|
112
|
+
if sort is not None:
|
|
113
|
+
params["sort"] = sort
|
|
114
|
+
logger.debug("GET /systems params=%s", params)
|
|
115
|
+
response = self.session.get(
|
|
116
|
+
f"{self.api_root}/systems",
|
|
117
|
+
headers=self._headers(),
|
|
118
|
+
params=params or None,
|
|
119
|
+
timeout=self.timeout,
|
|
120
|
+
)
|
|
121
|
+
response.raise_for_status()
|
|
122
|
+
return parse_systems_response(response.json())
|
|
123
|
+
|
|
124
|
+
def get_system(self, system_id: int, *, include: list[str] | None = None) -> TigoSystem:
|
|
125
|
+
params: dict[str, str | int] = {"id": system_id}
|
|
126
|
+
if include:
|
|
127
|
+
params["include"] = ",".join(include)
|
|
128
|
+
logger.debug("GET /systems/view system_id=%s", system_id)
|
|
129
|
+
response = self.session.get(
|
|
130
|
+
f"{self.api_root}/systems/view",
|
|
131
|
+
headers=self._headers(),
|
|
132
|
+
params=params,
|
|
133
|
+
timeout=self.timeout,
|
|
134
|
+
)
|
|
135
|
+
response.raise_for_status()
|
|
136
|
+
return parse_system_response(response.json())
|
|
137
|
+
|
|
138
|
+
def get_layout(self, system_id: int) -> TigoSystemLayout:
|
|
139
|
+
logger.debug("GET /systems/layout system_id=%s", system_id)
|
|
140
|
+
response = self.session.get(
|
|
141
|
+
f"{self.api_root}/systems/layout",
|
|
142
|
+
headers=self._headers(),
|
|
143
|
+
params={"id": system_id},
|
|
144
|
+
timeout=self.timeout,
|
|
145
|
+
)
|
|
146
|
+
response.raise_for_status()
|
|
147
|
+
return parse_layout_response(response.json())
|
|
148
|
+
|
|
149
|
+
def get_objects(self, system_id: int) -> list[TigoObjectNode]:
|
|
150
|
+
logger.debug("GET /objects/system system_id=%s", system_id)
|
|
151
|
+
response = self.session.get(
|
|
152
|
+
f"{self.api_root}/objects/system",
|
|
153
|
+
headers=self._headers(),
|
|
154
|
+
params={"system_id": system_id},
|
|
155
|
+
timeout=self.timeout,
|
|
156
|
+
)
|
|
157
|
+
response.raise_for_status()
|
|
158
|
+
return parse_objects_response(response.json())
|
|
159
|
+
|
|
160
|
+
def get_object_types(self) -> list[TigoObjectType]:
|
|
161
|
+
logger.debug("GET /objects/types")
|
|
162
|
+
response = self.session.get(
|
|
163
|
+
f"{self.api_root}/objects/types",
|
|
164
|
+
headers=self._headers(),
|
|
165
|
+
timeout=self.timeout,
|
|
166
|
+
)
|
|
167
|
+
response.raise_for_status()
|
|
168
|
+
return parse_object_types_response(response.json())
|
|
169
|
+
|
|
170
|
+
def get_sources(self, system_id: int) -> list[TigoSource]:
|
|
171
|
+
logger.debug("GET /sources/system system_id=%s", system_id)
|
|
172
|
+
response = self.session.get(
|
|
173
|
+
f"{self.api_root}/sources/system",
|
|
174
|
+
headers=self._headers(),
|
|
175
|
+
params={"system_id": system_id},
|
|
176
|
+
timeout=self.timeout,
|
|
177
|
+
)
|
|
178
|
+
response.raise_for_status()
|
|
179
|
+
return parse_sources_response(response.json())
|
|
180
|
+
|
|
181
|
+
def get_summary(self, system_id: int) -> TigoSummary:
|
|
182
|
+
logger.debug("GET /data/summary system_id=%s", system_id)
|
|
183
|
+
response = self.session.get(
|
|
184
|
+
f"{self.api_root}/data/summary",
|
|
185
|
+
headers=self._headers(),
|
|
186
|
+
params={"system_id": system_id},
|
|
187
|
+
timeout=self.timeout,
|
|
188
|
+
)
|
|
189
|
+
response.raise_for_status()
|
|
190
|
+
return parse_summary_response(response.json())
|
|
191
|
+
|
|
192
|
+
def get_aggregate(
|
|
193
|
+
self,
|
|
194
|
+
system_id: int,
|
|
195
|
+
*,
|
|
196
|
+
start: str,
|
|
197
|
+
end: str,
|
|
198
|
+
level: Literal["min", "hour", "day"] = "min",
|
|
199
|
+
param: str = "Pin",
|
|
200
|
+
object_ids: list[int] | None = None,
|
|
201
|
+
header: str | None = None,
|
|
202
|
+
sensors: bool | None = None,
|
|
203
|
+
) -> TigoCSVTable:
|
|
204
|
+
params: dict[str, str] = {
|
|
205
|
+
"system_id": str(system_id),
|
|
206
|
+
"start": start,
|
|
207
|
+
"end": end,
|
|
208
|
+
"level": level,
|
|
209
|
+
"param": param,
|
|
210
|
+
}
|
|
211
|
+
if object_ids:
|
|
212
|
+
params["object_ids"] = ",".join(str(i) for i in object_ids)
|
|
213
|
+
if header:
|
|
214
|
+
params["header"] = header
|
|
215
|
+
if sensors is not None:
|
|
216
|
+
params["sensors"] = "true" if sensors else "false"
|
|
217
|
+
logger.debug("GET /data/aggregate system_id=%s param=%s level=%s", system_id, param, level)
|
|
218
|
+
response = self.session.get(
|
|
219
|
+
f"{self.api_root}/data/aggregate",
|
|
220
|
+
headers=self._headers(),
|
|
221
|
+
params=params,
|
|
222
|
+
timeout=self.timeout,
|
|
223
|
+
)
|
|
224
|
+
response.raise_for_status()
|
|
225
|
+
return parse_csv_table(response.text)
|
|
226
|
+
|
|
227
|
+
def get_combined(
|
|
228
|
+
self,
|
|
229
|
+
system_id: int,
|
|
230
|
+
*,
|
|
231
|
+
start: str,
|
|
232
|
+
end: str,
|
|
233
|
+
agg: Literal["min", "hour", "day"],
|
|
234
|
+
object_ids: list[int] | None = None,
|
|
235
|
+
) -> TigoCSVTable:
|
|
236
|
+
params: dict[str, str] = {
|
|
237
|
+
"system_id": str(system_id),
|
|
238
|
+
"start": start,
|
|
239
|
+
"end": end,
|
|
240
|
+
"agg": agg,
|
|
241
|
+
}
|
|
242
|
+
if object_ids:
|
|
243
|
+
params["object_ids"] = ",".join(str(i) for i in object_ids)
|
|
244
|
+
logger.debug("GET /data/combined system_id=%s agg=%s", system_id, agg)
|
|
245
|
+
response = self.session.get(
|
|
246
|
+
f"{self.api_root}/data/combined",
|
|
247
|
+
headers=self._headers(),
|
|
248
|
+
params=params,
|
|
249
|
+
timeout=self.timeout,
|
|
250
|
+
)
|
|
251
|
+
response.raise_for_status()
|
|
252
|
+
return parse_csv_table(response.text)
|
|
253
|
+
|
|
254
|
+
def get_alerts(
|
|
255
|
+
self,
|
|
256
|
+
system_id: int,
|
|
257
|
+
*,
|
|
258
|
+
language: str | None = None,
|
|
259
|
+
start_added: str | None = None,
|
|
260
|
+
end_added: str | None = None,
|
|
261
|
+
page: int | None = None,
|
|
262
|
+
limit: int | None = None,
|
|
263
|
+
) -> TigoPage[TigoAlert]:
|
|
264
|
+
params: dict[str, str | int] = {"system_id": system_id}
|
|
265
|
+
if language:
|
|
266
|
+
params["language"] = language
|
|
267
|
+
if start_added:
|
|
268
|
+
params["start_added"] = start_added
|
|
269
|
+
if end_added:
|
|
270
|
+
params["end_added"] = end_added
|
|
271
|
+
if page is not None:
|
|
272
|
+
params["page"] = page
|
|
273
|
+
if limit is not None:
|
|
274
|
+
params["limit"] = limit
|
|
275
|
+
logger.debug("GET /alerts/system system_id=%s", system_id)
|
|
276
|
+
response = self.session.get(
|
|
277
|
+
f"{self.api_root}/alerts/system",
|
|
278
|
+
headers=self._headers(),
|
|
279
|
+
params=params,
|
|
280
|
+
timeout=self.timeout,
|
|
281
|
+
)
|
|
282
|
+
response.raise_for_status()
|
|
283
|
+
return parse_alerts_response(response.json())
|
|
284
|
+
|
|
285
|
+
def get_alert_types(self, *, language: str | None = None) -> list[TigoAlertType]:
|
|
286
|
+
params: dict[str, str] = {}
|
|
287
|
+
if language:
|
|
288
|
+
params["language"] = language
|
|
289
|
+
logger.debug("GET /alerts/types")
|
|
290
|
+
response = self.session.get(
|
|
291
|
+
f"{self.api_root}/alerts/types",
|
|
292
|
+
headers=self._headers(),
|
|
293
|
+
params=params or None,
|
|
294
|
+
timeout=self.timeout,
|
|
295
|
+
)
|
|
296
|
+
response.raise_for_status()
|
|
297
|
+
return parse_alert_types_response(response.json())
|