climify_api 1.0.26__tar.gz → 1.0.28__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.
- {climify_api-1.0.26 → climify_api-1.0.28}/PKG-INFO +1 -1
- {climify_api-1.0.26 → climify_api-1.0.28}/pyproject.toml +2 -2
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/__init__.py +2 -2
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/ApiController.py +4 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/__init__.py +3 -0
- climify_api-1.0.28/src/climify_api/apis/v1/paths/buildings_id_metering_points/__init__.py +1 -0
- climify_api-1.0.28/src/climify_api/apis/v1/paths/buildings_id_metering_points/get.py +92 -0
- climify_api-1.0.28/src/climify_api/apis/v1/paths/metering_points_id/__init__.py +1 -0
- climify_api-1.0.28/src/climify_api/apis/v1/paths/metering_points_id/get.py +192 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/models/__init__.py +9 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api.egg-info/PKG-INFO +1 -1
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api.egg-info/SOURCES.txt +4 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/LICENSE +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/MANIFEST.in +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/README.md +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/setup.cfg +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/ApiController.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/REST.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/api_client.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/PathBase.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/buildings_id/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/buildings_id/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/buildings_id_devices/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/buildings_id_devices/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/devices_id/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/devices_id/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/feedback_forms_id_locations_id_responses/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/feedback_forms_id_locations_id_responses/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id_change_temperature/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id_change_temperature/post.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id_devices/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id_devices/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id_sensor_values/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id_sensor_values/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/maps_id/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/maps_id/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/maps_id_devices/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/maps_id_devices/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/organisations_id/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/organisations_id/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/organisations_id_devices/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/organisations_id_devices/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/resources/__init__.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/resources/get.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/auth.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/configuration.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/exceptions.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/schemas.py +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api.egg-info/dependency_links.txt +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api.egg-info/requires.txt +0 -0
- {climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api.egg-info/top_level.txt +0 -0
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "climify_api"
|
|
9
|
-
version = "1.0.
|
|
9
|
+
version = "1.0.28"
|
|
10
10
|
keywords=['Climify','Environmental engineering']
|
|
11
11
|
authors = [
|
|
12
12
|
{ name="Climify Aps", email="info@climify.com" },
|
|
@@ -50,7 +50,7 @@ Homepage = "https://gitlab.climify.com/climify/python-api-lib"
|
|
|
50
50
|
Issues = "https://gitlab.climify.com/climify/python-api-lib/-/issues"
|
|
51
51
|
|
|
52
52
|
[tool.bumpver]
|
|
53
|
-
current_version = "1.0.
|
|
53
|
+
current_version = "1.0.28"
|
|
54
54
|
version_pattern = "MAJOR.MINOR.PATCH"
|
|
55
55
|
commit_message = "Bump version {old_version} -> {new_version}"
|
|
56
56
|
commit = true
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
Provides a REST endpoints for Climify applications and 3rd party solutions. # noqa: E501
|
|
10
10
|
|
|
11
|
-
The version of the OpenAPI document: 1.0.
|
|
11
|
+
The version of the OpenAPI document: 1.0.28
|
|
12
12
|
Generated by: https://openapi-generator.tech
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
__name__ = 'climify_api'
|
|
16
|
-
__version__ = "1.0.
|
|
16
|
+
__version__ = "1.0.28"
|
|
17
17
|
|
|
18
18
|
# import ApiClient
|
|
19
19
|
from climify_api.api_client import ApiClient
|
|
@@ -7,6 +7,7 @@ from climify_api.apis.v1.paths import (
|
|
|
7
7
|
GetOrganisationDevicesById,
|
|
8
8
|
GetBuildingById,
|
|
9
9
|
GetBuildingDevicesById,
|
|
10
|
+
GetBuildingMeteringPointsById,
|
|
10
11
|
GetMapById,
|
|
11
12
|
GetMapDevicesById,
|
|
12
13
|
GetLocationById,
|
|
@@ -14,6 +15,7 @@ from climify_api.apis.v1.paths import (
|
|
|
14
15
|
GetLocationSensorValuesById,
|
|
15
16
|
GetFormResponsesFromLocationById,
|
|
16
17
|
GetDeviceById,
|
|
18
|
+
GetMeteringPointValuesById,
|
|
17
19
|
|
|
18
20
|
# POST
|
|
19
21
|
SetLocationTemperatureById
|
|
@@ -26,6 +28,7 @@ class ApiController(
|
|
|
26
28
|
GetOrganisationDevicesById,
|
|
27
29
|
GetBuildingById,
|
|
28
30
|
GetBuildingDevicesById,
|
|
31
|
+
GetBuildingMeteringPointsById,
|
|
29
32
|
GetMapById,
|
|
30
33
|
GetMapDevicesById,
|
|
31
34
|
GetLocationById,
|
|
@@ -33,6 +36,7 @@ class ApiController(
|
|
|
33
36
|
GetLocationSensorValuesById,
|
|
34
37
|
GetFormResponsesFromLocationById,
|
|
35
38
|
GetDeviceById,
|
|
39
|
+
GetMeteringPointValuesById,
|
|
36
40
|
|
|
37
41
|
# POST
|
|
38
42
|
SetLocationTemperatureById
|
|
@@ -5,6 +5,7 @@ from climify_api.apis.v1.paths.organisations_id_devices import GetOrganisationDe
|
|
|
5
5
|
|
|
6
6
|
from climify_api.apis.v1.paths.buildings_id import GetBuildingById
|
|
7
7
|
from climify_api.apis.v1.paths.buildings_id_devices import GetBuildingDevicesById
|
|
8
|
+
from climify_api.apis.v1.paths.buildings_id_metering_points import GetBuildingMeteringPointsById
|
|
8
9
|
|
|
9
10
|
from climify_api.apis.v1.paths.maps_id import GetMapById
|
|
10
11
|
from climify_api.apis.v1.paths.maps_id_devices import GetMapDevicesById
|
|
@@ -17,4 +18,6 @@ from climify_api.apis.v1.paths.feedback_forms_id_locations_id_responses import G
|
|
|
17
18
|
|
|
18
19
|
from climify_api.apis.v1.paths.devices_id import GetDeviceById
|
|
19
20
|
|
|
21
|
+
from climify_api.apis.v1.paths.metering_points_id import GetMeteringPointValuesById
|
|
22
|
+
|
|
20
23
|
from climify_api.apis.v1.paths.locations_id_change_temperature import SetLocationTemperatureById
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from climify_api.apis.v1.paths.buildings_id_metering_points.get import GetBuildingMeteringPointsById
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
import typing_extensions
|
|
3
|
+
import urllib3
|
|
4
|
+
from urllib3._collections import HTTPHeaderDict
|
|
5
|
+
|
|
6
|
+
from climify_api import api_client, exceptions
|
|
7
|
+
from datetime import date, datetime # noqa: F401
|
|
8
|
+
import decimal # noqa: F401
|
|
9
|
+
import functools # noqa: F401
|
|
10
|
+
import io # noqa: F401
|
|
11
|
+
import re # noqa: F401
|
|
12
|
+
import typing # noqa: F401
|
|
13
|
+
import typing_extensions # noqa: F401
|
|
14
|
+
import uuid # noqa: F401
|
|
15
|
+
from typing import List
|
|
16
|
+
from pydantic import parse_raw_as
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
from climify_api.apis.PathBase import PathBase # noqa: F401
|
|
20
|
+
|
|
21
|
+
from climify_api.exceptions import ApiValueError, ClimifyApiException
|
|
22
|
+
from climify_api.api_client import ClimifyApiResponse, ClimifyApiResponseWithoutDeserialization
|
|
23
|
+
from climify_api.models import MeteringPointDto
|
|
24
|
+
|
|
25
|
+
PATH = 'buildings/{id}/metering-points'
|
|
26
|
+
|
|
27
|
+
class GetBuildingMeteringPointsById(PathBase):
|
|
28
|
+
# this class is used by api classes that refer to endpoints with operationId fn names
|
|
29
|
+
|
|
30
|
+
def get_building_metering_points_by_id(
|
|
31
|
+
self,
|
|
32
|
+
building_id: int,
|
|
33
|
+
access_token: str = None,
|
|
34
|
+
stream: bool = False,
|
|
35
|
+
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
|
|
36
|
+
skip_deserialization: bool = False,
|
|
37
|
+
) -> ClimifyApiResponse[List[MeteringPointDto]]:
|
|
38
|
+
"""Returns the metering points associated with the provided building.
|
|
39
|
+
|
|
40
|
+
:param building_id: Building identifier
|
|
41
|
+
:type building_id: int
|
|
42
|
+
:param access_token: Access token to use for the request
|
|
43
|
+
:type access_token: str, optional
|
|
44
|
+
:param stream: Toggles streaming. Defaults to False.
|
|
45
|
+
:type stream: bool, optional
|
|
46
|
+
:param timeout: How long to wait for a request in seconds. Defaults to None.
|
|
47
|
+
:type timeout: typing.Optional[typing.Union[int, typing.Tuple]], optional
|
|
48
|
+
:param skip_deserialization: Toggles whether or not to skip deserialize of the byte response. Defaults to False.
|
|
49
|
+
:type skip_deserialization: bool, optional
|
|
50
|
+
|
|
51
|
+
:raises ApiValueError: Will be raised if invalid inputs are provided
|
|
52
|
+
:raises ClimifyApiException: Will be raised if an error occurred while calling the API
|
|
53
|
+
|
|
54
|
+
:return: A response with a body containing the list of metering points
|
|
55
|
+
:rtype: ClimifyApiResponse[List[MeteringPointDto]]
|
|
56
|
+
"""
|
|
57
|
+
# Validate input
|
|
58
|
+
if building_id is None:
|
|
59
|
+
raise ApiValueError("Building id was given as None. A valid building id must be provided.")
|
|
60
|
+
|
|
61
|
+
# Make rest request
|
|
62
|
+
used_path = PATH.replace('{id}',str(building_id))
|
|
63
|
+
|
|
64
|
+
response = self.api_client.call_api(
|
|
65
|
+
resource_path=used_path,
|
|
66
|
+
method='GET',
|
|
67
|
+
access_token=access_token,
|
|
68
|
+
stream=stream,
|
|
69
|
+
timeout=timeout,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
if not 200 <= response.status <= 299:
|
|
73
|
+
raise ClimifyApiException(
|
|
74
|
+
status=response.status,
|
|
75
|
+
reason=response.reason,
|
|
76
|
+
api_response=response
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if skip_deserialization:
|
|
80
|
+
api_response = ClimifyApiResponseWithoutDeserialization(response=response)
|
|
81
|
+
else:
|
|
82
|
+
# Deserialize response
|
|
83
|
+
deserialized_body = parse_raw_as(List[MeteringPointDto], response.data)
|
|
84
|
+
api_response = ClimifyApiResponse[List[MeteringPointDto]](
|
|
85
|
+
response=response,
|
|
86
|
+
status=response.status,
|
|
87
|
+
body=deserialized_body,
|
|
88
|
+
headers=response.headers
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
return api_response
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from climify_api.apis.v1.paths.metering_points_id.get import GetMeteringPointValuesById
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
import typing_extensions
|
|
4
|
+
import urllib3
|
|
5
|
+
from urllib3._collections import HTTPHeaderDict
|
|
6
|
+
|
|
7
|
+
from datetime import date, datetime, timedelta # noqa: F401
|
|
8
|
+
from dateutil.relativedelta import relativedelta
|
|
9
|
+
import decimal # noqa: F401
|
|
10
|
+
import functools # noqa: F401
|
|
11
|
+
import io # noqa: F401
|
|
12
|
+
import re # noqa: F401
|
|
13
|
+
import typing # noqa: F401
|
|
14
|
+
import typing_extensions # noqa: F401
|
|
15
|
+
import uuid # noqa: F401
|
|
16
|
+
from pandas import DataFrame, concat
|
|
17
|
+
from typing import List
|
|
18
|
+
from pydantic import parse_raw_as
|
|
19
|
+
from varname import nameof
|
|
20
|
+
import pytz
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
from climify_api.apis.PathBase import PathBase # noqa: F401
|
|
24
|
+
|
|
25
|
+
from climify_api.exceptions import ApiValueError, ClimifyApiException
|
|
26
|
+
from climify_api.api_client import ClimifyApiResponse, ClimifyApiResponseWithoutDeserialization
|
|
27
|
+
from climify_api.models import SensorDataExtDto
|
|
28
|
+
|
|
29
|
+
PATH = 'metering-points/{id}'
|
|
30
|
+
|
|
31
|
+
def convert_values_to_dataFrame(data: List[SensorDataExtDto]) -> DataFrame:
|
|
32
|
+
"""Converts the sensor values to pandas DataFrames inplace.
|
|
33
|
+
|
|
34
|
+
:param data: List of sensor data DTOs with sensor data as list of Data models
|
|
35
|
+
:type data: List[SensorDataExtDto]
|
|
36
|
+
:return: The list of sensor data with the updated data values
|
|
37
|
+
:rtype: DataFrame
|
|
38
|
+
"""
|
|
39
|
+
if len(data) == 0:
|
|
40
|
+
return data
|
|
41
|
+
|
|
42
|
+
for sensor in data:
|
|
43
|
+
variables = list(sensor.data[0].values.keys())
|
|
44
|
+
columns = [nameof(sensor.data[0].time)] + variables
|
|
45
|
+
values = [[row.time] + [row.values[col] for col in variables] for row in sensor.data]
|
|
46
|
+
sensor.data = DataFrame(values, columns = columns)
|
|
47
|
+
|
|
48
|
+
return data
|
|
49
|
+
|
|
50
|
+
class GetMeteringPointValuesById(PathBase):
|
|
51
|
+
def get_metering_point_values_by_id(
|
|
52
|
+
self,
|
|
53
|
+
metering_point_id: int,
|
|
54
|
+
from_datetime: datetime = datetime.today() - relativedelta(month=1),
|
|
55
|
+
to_datetime: datetime = datetime.today(),
|
|
56
|
+
as_dataframe: bool = False,
|
|
57
|
+
access_token: str = None,
|
|
58
|
+
stream: bool = False,
|
|
59
|
+
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
|
|
60
|
+
skip_deserialization: bool = False,
|
|
61
|
+
) -> ClimifyApiResponse[List[SensorDataExtDto]]:
|
|
62
|
+
"""Returns metering values from devices associated with the given metering point.
|
|
63
|
+
|
|
64
|
+
from_datetime and to_datetime:
|
|
65
|
+
The default time period of the data is 3 months.
|
|
66
|
+
Thus the sensor period is always the last 3 months unless *both* time period variables are specified.
|
|
67
|
+
The storage time is 3 years for the data, from_datetime must therefore be later than this point.
|
|
68
|
+
|
|
69
|
+
:param metering_point_id: Location identifier
|
|
70
|
+
:type metering_point_id: int
|
|
71
|
+
:param from_datetime: Start time for wanted sensor data period
|
|
72
|
+
:type from_datetime: datetime
|
|
73
|
+
:param to_datetime: End time for wanted sensor data period
|
|
74
|
+
:type to_datetime: datetime
|
|
75
|
+
:param as_dataframe: If True, will convert the data of the devices to pandas DataFrames, defaults to False.
|
|
76
|
+
:type as_dataframe: bool, optional
|
|
77
|
+
:param access_token: Access token to use for the request
|
|
78
|
+
:type access_token: str, optional
|
|
79
|
+
:param stream: Toggles streaming, defaults to False
|
|
80
|
+
:type stream: bool, optional
|
|
81
|
+
:param timeout: How long to wait for a request in seconds, defaults to None
|
|
82
|
+
:type timeout: typing.Optional[typing.Union[int, typing.Tuple]], optional
|
|
83
|
+
:param skip_deserialization: Toggles whether or not to skip deserialize of the byte response, defaults to False
|
|
84
|
+
:type skip_deserialization: bool, optional
|
|
85
|
+
|
|
86
|
+
:raises ApiValueError: Will be raised if invalid inputs are provided
|
|
87
|
+
:raises ClimifyApiException: Will be raised if an error occurred while calling the API
|
|
88
|
+
|
|
89
|
+
:return: A response with a body containing the list of devices with their data
|
|
90
|
+
:rtype: ClimifyApiResponse[List[SensorDataExtDto]]
|
|
91
|
+
"""
|
|
92
|
+
# Validate input
|
|
93
|
+
if metering_point_id is None:
|
|
94
|
+
raise ApiValueError("Location id was given as None. A valid location id must be provided.")
|
|
95
|
+
|
|
96
|
+
if from_datetime > to_datetime:
|
|
97
|
+
raise ApiValueError(f'Given {nameof(from_datetime)} was later than the given {nameof(to_datetime)}. Please provide a valid time period.')
|
|
98
|
+
|
|
99
|
+
if from_datetime.tzinfo != pytz.UTC:
|
|
100
|
+
from_datetime = from_datetime.astimezone(pytz.UTC)
|
|
101
|
+
|
|
102
|
+
if to_datetime.tzinfo != pytz.UTC:
|
|
103
|
+
to_datetime = to_datetime.astimezone(pytz.UTC)
|
|
104
|
+
|
|
105
|
+
if from_datetime < datetime.now(pytz.UTC) - relativedelta(years=3):
|
|
106
|
+
raise ApiValueError(f'The given value of {nameof(from_datetime)} is longer than 3 years ago. Data storage limit is 3 years, please provide a value within this limit.')
|
|
107
|
+
|
|
108
|
+
# Make rest request
|
|
109
|
+
usedPath = PATH.replace('{id}',str(metering_point_id))
|
|
110
|
+
|
|
111
|
+
requests = []
|
|
112
|
+
subRequestToTime = to_datetime
|
|
113
|
+
subRequestFromTime = max(subRequestToTime - relativedelta(months=3), from_datetime)
|
|
114
|
+
|
|
115
|
+
while subRequestFromTime >= from_datetime:
|
|
116
|
+
query_parameters = []
|
|
117
|
+
for name, value in (
|
|
118
|
+
('dateTimeFrom', subRequestFromTime.replace(tzinfo=None).isoformat()+'Z' if subRequestFromTime else None), # Sets timezone to None, to remove +HH:MM
|
|
119
|
+
('dateTimeTo', subRequestToTime.replace(tzinfo=None).isoformat()+'Z' if subRequestToTime else None)
|
|
120
|
+
):
|
|
121
|
+
if value:
|
|
122
|
+
query_parameters.append(f"{name}={value}")
|
|
123
|
+
|
|
124
|
+
if len(query_parameters) > 0:
|
|
125
|
+
requests.append("?" + "&".join(query_parameters))
|
|
126
|
+
|
|
127
|
+
if subRequestFromTime == from_datetime:
|
|
128
|
+
break
|
|
129
|
+
|
|
130
|
+
subRequestToTime = subRequestFromTime - relativedelta(seconds=1)
|
|
131
|
+
subRequestFromTime = max(subRequestToTime - relativedelta(months=3), from_datetime)
|
|
132
|
+
|
|
133
|
+
bodies = []
|
|
134
|
+
for request in requests:
|
|
135
|
+
requestPath = usedPath+request
|
|
136
|
+
response = self.api_client.call_api(
|
|
137
|
+
resource_path=requestPath,
|
|
138
|
+
method='GET',
|
|
139
|
+
access_token=access_token,
|
|
140
|
+
stream=stream,
|
|
141
|
+
timeout=timeout
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Format response
|
|
145
|
+
if not 200 <= response.status <= 299:
|
|
146
|
+
raise ClimifyApiException(
|
|
147
|
+
status=response.status,
|
|
148
|
+
reason=response.reason,
|
|
149
|
+
api_response=response
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
if skip_deserialization:
|
|
153
|
+
bodies.append(response.data)
|
|
154
|
+
continue
|
|
155
|
+
|
|
156
|
+
deserialized_body = parse_raw_as(List[SensorDataExtDto],response.data) if response.data\
|
|
157
|
+
else []
|
|
158
|
+
|
|
159
|
+
# Sort observations on time
|
|
160
|
+
for sensor in deserialized_body:
|
|
161
|
+
sensor.data = sorted(sensor.data, key=lambda x: x.time, reverse=True)
|
|
162
|
+
|
|
163
|
+
if as_dataframe:
|
|
164
|
+
deserialized_body = convert_values_to_dataFrame(deserialized_body)
|
|
165
|
+
|
|
166
|
+
bodies.append(deserialized_body)
|
|
167
|
+
|
|
168
|
+
if skip_deserialization:
|
|
169
|
+
response.data = bodies
|
|
170
|
+
return ClimifyApiResponseWithoutDeserialization(response=response)
|
|
171
|
+
|
|
172
|
+
sensors = {}
|
|
173
|
+
for body in bodies:
|
|
174
|
+
for sensor in body:
|
|
175
|
+
if sensor.devId not in sensors:
|
|
176
|
+
sensors[sensor.devId] = sensor
|
|
177
|
+
continue
|
|
178
|
+
|
|
179
|
+
sensor_data = sensors[sensor.devId]
|
|
180
|
+
if as_dataframe:
|
|
181
|
+
sensor_data.data = concat([sensor_data.data, sensor.data], ignore_index=True)
|
|
182
|
+
else:
|
|
183
|
+
sensor_data.data += sensor.data
|
|
184
|
+
|
|
185
|
+
deserialized_body = list(sensors.values())
|
|
186
|
+
|
|
187
|
+
return ClimifyApiResponse[List[SensorDataExtDto]](
|
|
188
|
+
response=response,
|
|
189
|
+
status=response.status,
|
|
190
|
+
body=deserialized_body,
|
|
191
|
+
headers=response.headers
|
|
192
|
+
)
|
|
@@ -183,6 +183,14 @@ class DeviceDto(BaseModel):
|
|
|
183
183
|
resources: Optional[List[DeviceResourceDto]] = []
|
|
184
184
|
historySyncedAt: Optional[datetime] = None
|
|
185
185
|
|
|
186
|
+
class MeteringPointDto(BaseModel):
|
|
187
|
+
id: Optional[int] = None
|
|
188
|
+
externalId: constr(min_length=0, max_length=100)
|
|
189
|
+
deviceModel: DeviceModelDto
|
|
190
|
+
alias: Optional[constr(min_length=0, max_length=100)] = None
|
|
191
|
+
integration: Optional[IntegrationDto] = None
|
|
192
|
+
resources: Optional[List[DeviceResourceDto]] = []
|
|
193
|
+
historySyncedAt: Optional[datetime] = None
|
|
186
194
|
|
|
187
195
|
class DeviceResourceDto(BaseModel):
|
|
188
196
|
id: Optional[int] = None
|
|
@@ -207,6 +215,7 @@ LocationDto.update_forward_refs()
|
|
|
207
215
|
LocationProfileDto.update_forward_refs()
|
|
208
216
|
OrganisationDto.update_forward_refs()
|
|
209
217
|
DeviceDto.update_forward_refs()
|
|
218
|
+
MeteringPointDto.update_forward_refs()
|
|
210
219
|
|
|
211
220
|
# Feedback forms
|
|
212
221
|
class FormQuestionBase(BaseModel):
|
|
@@ -24,6 +24,8 @@ src/climify_api/apis/v1/paths/buildings_id/__init__.py
|
|
|
24
24
|
src/climify_api/apis/v1/paths/buildings_id/get.py
|
|
25
25
|
src/climify_api/apis/v1/paths/buildings_id_devices/__init__.py
|
|
26
26
|
src/climify_api/apis/v1/paths/buildings_id_devices/get.py
|
|
27
|
+
src/climify_api/apis/v1/paths/buildings_id_metering_points/__init__.py
|
|
28
|
+
src/climify_api/apis/v1/paths/buildings_id_metering_points/get.py
|
|
27
29
|
src/climify_api/apis/v1/paths/devices_id/__init__.py
|
|
28
30
|
src/climify_api/apis/v1/paths/devices_id/get.py
|
|
29
31
|
src/climify_api/apis/v1/paths/feedback_forms_id_locations_id_responses/__init__.py
|
|
@@ -40,6 +42,8 @@ src/climify_api/apis/v1/paths/maps_id/__init__.py
|
|
|
40
42
|
src/climify_api/apis/v1/paths/maps_id/get.py
|
|
41
43
|
src/climify_api/apis/v1/paths/maps_id_devices/__init__.py
|
|
42
44
|
src/climify_api/apis/v1/paths/maps_id_devices/get.py
|
|
45
|
+
src/climify_api/apis/v1/paths/metering_points_id/__init__.py
|
|
46
|
+
src/climify_api/apis/v1/paths/metering_points_id/get.py
|
|
43
47
|
src/climify_api/apis/v1/paths/organisations_id/__init__.py
|
|
44
48
|
src/climify_api/apis/v1/paths/organisations_id/get.py
|
|
45
49
|
src/climify_api/apis/v1/paths/organisations_id_devices/__init__.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/buildings_id/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/buildings_id_devices/get.py
RENAMED
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/devices_id/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/locations_id_devices/get.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/maps_id_devices/__init__.py
RENAMED
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/maps_id_devices/get.py
RENAMED
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/organisations_id/__init__.py
RENAMED
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/organisations_id/get.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climify_api-1.0.26 → climify_api-1.0.28}/src/climify_api/apis/v1/paths/resources/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|