Skip to content

Commit

Permalink
Merge pull request #3 from self-host/thing-parameters
Browse files Browse the repository at this point in the history
Thing parameters
  • Loading branch information
ganehag authored May 14, 2024
2 parents 831e16e + 50ccafd commit 15edc10
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 60 deletions.
16 changes: 8 additions & 8 deletions requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --resolver=backtracking requirements.in
# pip-compile --strip-extras requirements.in
#
beartype==0.14.0
beartype==0.18.5
# via -r requirements.in
certifi==2023.5.7
certifi==2024.2.2
# via requests
charset-normalizer==3.1.0
charset-normalizer==3.3.2
# via requests
idna==3.4
idna==3.7
# via requests
pyrfc3339==1.1
# via -r requirements.in
pytz==2023.3
pytz==2024.1
# via pyrfc3339
requests==2.31.0
# via -r requirements.in
typing-extensions==4.6.2
typing-extensions==4.11.0
# via -r requirements.in
urllib3==2.0.2
urllib3==2.2.1
# via requests
6 changes: 5 additions & 1 deletion selfhost_client/base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ def _process_response(self, response: Response) -> Optional[Any]:
except json.decoder.JSONDecodeError:
return response.content or None
elif 400 <= response.status_code < 500:
raise responses[response.status_code]
if response.json():
raise responses[response.status_code](
message=response.json().get("error")
)
raise responses[response.status_code](message=response.text)
else:
raise SelfHostInternalServerException
153 changes: 106 additions & 47 deletions selfhost_client/things_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .base_client import BaseClient
from .types.dataset_types import DatasetType
from .types.thing_types import ThingType
from .types.thing_types import ThingType, ThingParameterType
from .types.timeseries_types import TimeseriesType
from .utils import filter_none_values_from_dict

Expand All @@ -21,20 +21,22 @@ class ThingsClient(BaseClient):
"""

@beartype
def __init__(self,
base_url: Optional[str] = None,
username: Optional[str] = None,
password: Optional[str] = None
) -> None:
def __init__(
self,
base_url: Optional[str] = None,
username: Optional[str] = None,
password: Optional[str] = None,
) -> None:
super().__init__(base_url, username, password)
self._things_api_path = 'things'
self._things_api_path = "things"

@beartype
def get_things(self,
limit: Optional[int] = None,
offset: Optional[int] = None,
tags: Optional[List[str]] = None
) -> List[ThingType]:
def get_things(
self,
limit: Optional[int] = None,
offset: Optional[int] = None,
tags: Optional[List[str]] = None,
) -> List[ThingType]:
"""Fetches things from NODA Self-host API
Args:
Expand All @@ -54,21 +56,20 @@ def get_things(self,
from fulfilling the request.
"""
response: Response = self._session.get(
url=f'{self._base_url}/{self._api_version}/{self._things_api_path}',
params=filter_none_values_from_dict({
'limit': limit,
'offset': offset,
'tags': tags
})
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}",
params=filter_none_values_from_dict(
{"limit": limit, "offset": offset, "tags": tags}
),
)
return self._process_response(response)

@beartype
def create_thing(self,
name: str,
thing_type: Optional[str] = None,
tags: Optional[List[str]] = None
) -> ThingType:
def create_thing(
self,
name: str,
thing_type: Optional[str] = None,
tags: Optional[List[str]] = None,
) -> ThingType:
"""Add a new thing to the NODA Self-host API
Args:
Expand All @@ -88,12 +89,10 @@ def create_thing(self,
from fulfilling the request.
"""
response: Response = self._session.post(
url=f'{self._base_url}/{self._api_version}/{self._things_api_path}',
json=filter_none_values_from_dict({
'name': name,
'type': thing_type,
'tags': tags
})
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}",
json=filter_none_values_from_dict(
{"name": name, "type": thing_type, "tags": tags}
),
)
return self._process_response(response)

Expand All @@ -117,18 +116,19 @@ def get_thing(self, thing_uuid: str) -> ThingType:
from fulfilling the request.
"""
response: Response = self._session.get(
url=f'{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}'
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}"
)
return self._process_response(response)

@beartype
def update_thing(self,
thing_uuid: str,
name: Optional[str] = None,
state: Optional[str] = None,
thing_type: Optional[str] = None,
tags: Optional[List[str]] = None
) -> None:
def update_thing(
self,
thing_uuid: str,
name: Optional[str] = None,
state: Optional[str] = None,
thing_type: Optional[str] = None,
tags: Optional[List[str]] = None,
) -> None:
"""Updates a thing from NODA Self-host API
Args:
Expand Down Expand Up @@ -157,13 +157,10 @@ def update_thing(self,
from fulfilling the request.
"""
response: Response = self._session.put(
url=f'{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}',
json=filter_none_values_from_dict({
'name': name,
'state': state,
'type': thing_type,
'tags': tags
})
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}",
json=filter_none_values_from_dict(
{"name": name, "state": state, "type": thing_type, "tags": tags}
),
)
return self._process_response(response)

Expand All @@ -184,7 +181,7 @@ def delete_thing(self, thing_uuid: str) -> None:
from fulfilling the request.
"""
response: Response = self._session.delete(
url=f'{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}'
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}"
)
return self._process_response(response)

Expand All @@ -208,7 +205,7 @@ def get_thing_datasets(self, thing_uuid: str) -> List[DatasetType]:
from fulfilling the request.
"""
response: Response = self._session.get(
url=f'{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}/datasets'
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}/datasets"
)
return self._process_response(response)

Expand All @@ -232,6 +229,68 @@ def get_thing_timeseries(self, thing_uuid: str) -> List[TimeseriesType]:
from fulfilling the request.
"""
response: Response = self._session.get(
url=f'{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}/timeseries'
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}/timeseries"
)
return self._process_response(response)

@beartype
def get_thing_parameters(
self,
thing_uuid: str,
startsWith: Optional[str] = None,
endsWith: Optional[str] = None,
) -> List[ThingParameterType]:
"""Returns a list of parameters associated with the specified thing from NODA Self-host API
Args:
thing_uuid (str): UUID of the target user.
startsWith (Optional[str], optional): Parameter name prefix. Defaults to None.
endsWith (Optional[str], optional): Parameter name suffix. Defaults to None.
Returns:
List[:class:`.ParameterType`]
Raises:
:class:`.SelfHostBadRequestException`: Sent request had insufficient data or invalid options.
:class:`.SelfHostUnauthorizedException`: Request was refused due to lacking authentication credentials.
:class:`.SelfHostForbiddenException`: Server understands the request but refuses to authorize it.
:class:`.SelfHostNotFoundException`: The requested resource was not found.
:class:`.SelfHostTooManyRequestsException`: Sent too many requests in a given amount of time.
:class:`.SelfHostInternalServerException`: Server encountered an unexpected condition that prevented it
from fulfilling the request.
"""
response: Response = self._session.get(
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}/params",
params=filter_none_values_from_dict(
{"startsWith": startsWith, "endsWith": endsWith}
),
)
return self._process_response(response)

@beartype
def set_thing_parameters(
self,
thing_uuid: str,
parameters: List[ThingParameterType],
) -> None:
"""Sets a list of parameters associated with the specified thing from NODA Self-host API
Args:
thing_uuid (str): UUID of the target user.
parameters (List[:class:`.ParameterType`]): List of parameters to set.
Raises:
:class:`.SelfHostBadRequestException`: Sent request had insufficient data or invalid options.
:class:`.SelfHostUnauthorizedException`: Request was refused due to lacking authentication credentials.
:class:`.SelfHostForbiddenException`: Server understands the request but refuses to authorize it.
:class:`.SelfHostNotFoundException`: The requested resource was not found.
:class:`.SelfHostTooManyRequestsException`: Sent too many requests in a given amount of time.
:class:`.SelfHostInternalServerException`: Server encountered an unexpected condition that prevented it
from fulfilling the request.
"""

response: Response = self._session.put(
url=f"{self._base_url}/{self._api_version}/{self._things_api_path}/{thing_uuid}/params",
json=parameters,
)
return self._process_response(response)
6 changes: 3 additions & 3 deletions selfhost_client/timeseries_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

from .base_client import BaseClient
from .types.timeseries_types import (
TimeseriesType,
TimeseriesDataPointType,
TimeseriesDataType,
TimeseriesDataPointResponse,
TimeseriesDataPointType,
TimeseriesDataResponse,
TimeseriesDataType,
TimeseriesType,
)
from .utils import filter_none_values_from_dict

Expand Down
8 changes: 7 additions & 1 deletion selfhost_client/types/thing_types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Union

try:
from typing import TypedDict
Expand Down Expand Up @@ -40,9 +40,15 @@ class ThingType(TypedDict):
}
"""

uuid: str
name: str
state: str
type: str
created_by: str
tags: List[str]


class ThingParameterType(TypedDict):
key: str
value: Union[str, int, float, bool]

0 comments on commit 15edc10

Please sign in to comment.