diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml
new file mode 100644
index 0000000..076ccda
--- /dev/null
+++ b/.github/workflows/publish.yaml
@@ -0,0 +1,21 @@
+name: Upload Python Package to PyPI when a Release is Created
+
+on:
+ release:
+ types: [created]
+
+jobs:
+ pypi-publish:
+ name: Publish release to PyPI
+ runs-on: ubuntu-latest
+ environment:
+ name: pypi
+ url: https://pypi.org/p/derapi
+ permissions:
+ id-token: write
+ contents: read
+ steps:
+ - uses: actions/checkout@v4
+ - uses: pypa/hatch@install
+ - run: hatch build
+ - uses: pypa/gh-action-pypi-publish@release/v1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..849ddff
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+dist/
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..9313eed
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+# changelog
+
+## [0.1.0] - 2024-11-08
+
+### Added
+
+- Initialized the API client code
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..0ac9ac0
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2024-present Derapi (https://derapi.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..31bd835
--- /dev/null
+++ b/README.md
@@ -0,0 +1,63 @@
+# derapi
+
+The `derapi` Python SDK provides access to the Derapi API for Python
+applications -- fully typed with async support.
+
+[](https://pypi.org/project/derapi)
+[](https://pypi.org/project/derapi)
+
+-----
+
+## Table of Contents
+
+- [Installation](#installation)
+- [Usage](#usage)
+- [License](#license)
+
+## Installation
+
+```shell
+pip install derapi
+```
+
+## Usage
+
+Client initialization:
+
+```python
+import os
+
+import httpx
+from derapi import AuthenticatedClient
+
+def init_client() -> AuthenticatedClient:
+ token_resp = httpx.post(
+ "https://auth.derapi.com/oauth2/token",
+ auth=(os.environ["DERAPI_CLIENT_ID"], os.environ["DERAPI_CLIENT_SECRET"]),
+ data={"grant_type": "client_credentials"},
+ )
+ token_resp.raise_for_status()
+ token = token_resp.json()["access_token"]
+ return AuthenticatedClient(
+ base_url="https//api.derapi.com",
+ raise_on_unexpected_status=True,
+ token=token,
+ )
+```
+
+Usage:
+
+```python
+...
+
+from derapi.api import list_sites
+
+client = init_client()
+
+for site in list_sites.sync_depaginated(client=client):
+ print(site.id)
+```
+
+## License
+
+`derapi` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
diff --git a/derapi/__init__.py b/derapi/__init__.py
new file mode 100644
index 0000000..c7d157e
--- /dev/null
+++ b/derapi/__init__.py
@@ -0,0 +1,8 @@
+"""A client library for accessing Derapi API Reference"""
+
+from .client import AuthenticatedClient, Client
+
+__all__ = (
+ "AuthenticatedClient",
+ "Client",
+)
diff --git a/derapi/api/__init__.py b/derapi/api/__init__.py
new file mode 100644
index 0000000..81f9fa2
--- /dev/null
+++ b/derapi/api/__init__.py
@@ -0,0 +1 @@
+"""Contains methods for accessing the API"""
diff --git a/derapi/api/batteries/__init__.py b/derapi/api/batteries/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/derapi/api/batteries/get_battery.py b/derapi/api/batteries/get_battery.py
new file mode 100644
index 0000000..d641a3d
--- /dev/null
+++ b/derapi/api/batteries/get_battery.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_battery_response import GetBatteryResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/batteries/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetBatteryResponse]:
+ if response.status_code == 200:
+ response_200 = GetBatteryResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetBatteryResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetBatteryResponse]:
+ """Returns Battery details
+
+ Returns details for a single Battery
+
+ Args:
+ id (str): Battery id
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetBatteryResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetBatteryResponse]:
+ """Returns Battery details
+
+ Returns details for a single Battery
+
+ Args:
+ id (str): Battery id
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetBatteryResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetBatteryResponse]:
+ """Returns Battery details
+
+ Returns details for a single Battery
+
+ Args:
+ id (str): Battery id
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetBatteryResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetBatteryResponse]:
+ """Returns Battery details
+
+ Returns details for a single Battery
+
+ Args:
+ id (str): Battery id
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetBatteryResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ )
+ ).parsed
diff --git a/derapi/api/batteries/get_battery_intervals.py b/derapi/api/batteries/get_battery_intervals.py
new file mode 100644
index 0000000..389cd06
--- /dev/null
+++ b/derapi/api/batteries/get_battery_intervals.py
@@ -0,0 +1,393 @@
+import datetime
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.battery_interval import BatteryInterval
+from ...models.get_battery_intervals_response import GetBatteryIntervalsResponse
+from ...models.summary_level import SummaryLevel
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ id: str,
+ *,
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ json_summary_level: Union[Unset, str] = UNSET
+ if not isinstance(summary_level, Unset):
+ json_summary_level = summary_level.value
+
+ params["summaryLevel"] = json_summary_level
+
+ json_start = start.isoformat()
+ params["start"] = json_start
+
+ json_end = end.isoformat()
+ params["end"] = json_end
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/batteries/{id}/intervals",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetBatteryIntervalsResponse]:
+ if response.status_code == 200:
+ response_200 = GetBatteryIntervalsResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetBatteryIntervalsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[GetBatteryIntervalsResponse]:
+ """Returns Battery interval data
+
+ Returns individual Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): Battery id
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetBatteryIntervalsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[GetBatteryIntervalsResponse]:
+ """Returns Battery interval data
+
+ Returns individual Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): Battery id
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetBatteryIntervalsResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[GetBatteryIntervalsResponse]:
+ """Returns Battery interval data
+
+ Returns individual Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): Battery id
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetBatteryIntervalsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[GetBatteryIntervalsResponse]:
+ """Returns Battery interval data
+
+ Returns individual Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): Battery id
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetBatteryIntervalsResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[BatteryInterval]:
+ """Returns Battery interval data
+
+ Returns individual Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): Battery id
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[BatteryInterval]
+ """
+
+ response = sync(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.intervals
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[BatteryInterval]:
+ """Returns Battery interval data
+
+ Returns individual Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): Battery id
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[BatteryInterval]
+ """
+
+ response = await asyncio(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.intervals:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/api/batteries/list_batteries.py b/derapi/api/batteries/list_batteries.py
new file mode 100644
index 0000000..0b4f2bb
--- /dev/null
+++ b/derapi/api/batteries/list_batteries.py
@@ -0,0 +1,345 @@
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.battery_summary import BatterySummary
+from ...models.list_batteries_response import ListBatteriesResponse
+from ...models.vendor import Vendor
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ *,
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ json_vendor: Union[Unset, str] = UNSET
+ if not isinstance(vendor, Unset):
+ json_vendor = vendor.value
+
+ params["vendor"] = json_vendor
+
+ params["vendorID"] = vendor_id
+
+ params["vendorSiteID"] = vendor_site_id
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": "/batteries",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[ListBatteriesResponse]:
+ if response.status_code == 200:
+ response_200 = ListBatteriesResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[ListBatteriesResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListBatteriesResponse]:
+ """Returns a list of Batteries
+
+ Returns a list of Batteries. In the case a vendor API request encounters an error details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ vendor_site_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListBatteriesResponse]
+ """
+
+ kwargs = _get_kwargs(
+ vendor=vendor,
+ vendor_id=vendor_id,
+ vendor_site_id=vendor_site_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListBatteriesResponse]:
+ """Returns a list of Batteries
+
+ Returns a list of Batteries. In the case a vendor API request encounters an error details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ vendor_site_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListBatteriesResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ vendor_site_id=vendor_site_id,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListBatteriesResponse]:
+ """Returns a list of Batteries
+
+ Returns a list of Batteries. In the case a vendor API request encounters an error details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ vendor_site_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListBatteriesResponse]
+ """
+
+ kwargs = _get_kwargs(
+ vendor=vendor,
+ vendor_id=vendor_id,
+ vendor_site_id=vendor_site_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListBatteriesResponse]:
+ """Returns a list of Batteries
+
+ Returns a list of Batteries. In the case a vendor API request encounters an error details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ vendor_site_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListBatteriesResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ vendor_site_id=vendor_site_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[BatterySummary]:
+ """Returns a list of Batteries
+
+ Returns a list of Batteries. In the case a vendor API request encounters an error details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ vendor_site_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[BatterySummary]
+ """
+
+ response = sync(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ vendor_site_id=vendor_site_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.batteries
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ vendor_site_id=vendor_site_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[BatterySummary]:
+ """Returns a list of Batteries
+
+ Returns a list of Batteries. In the case a vendor API request encounters an error details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ vendor_site_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[BatterySummary]
+ """
+
+ response = await asyncio(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ vendor_site_id=vendor_site_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.batteries:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ vendor_site_id=vendor_site_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/api/join/__init__.py b/derapi/api/join/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/derapi/api/join/create_join_session.py b/derapi/api/join/create_join_session.py
new file mode 100644
index 0000000..5311b9f
--- /dev/null
+++ b/derapi/api/join/create_join_session.py
@@ -0,0 +1,176 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.create_join_session_request import CreateJoinSessionRequest
+from ...models.create_join_session_response import CreateJoinSessionResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ *,
+ body: CreateJoinSessionRequest,
+) -> Dict[str, Any]:
+ headers: Dict[str, Any] = {}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "post",
+ "url": "/join/session/start",
+ }
+
+ _body = body.to_dict()
+
+ _kwargs["json"] = _body
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[CreateJoinSessionResponse]:
+ if response.status_code == 200:
+ response_200 = CreateJoinSessionResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[CreateJoinSessionResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateJoinSessionRequest,
+) -> Response[CreateJoinSessionResponse]:
+ """Create a Join session
+
+ Create a Join session and retrieve a session token. Pass this token to the Join JS component
+ function createJoin(). Add a vendor credential object for each vendor that should appear in the Join
+ UI.
+
+ Args:
+ body (CreateJoinSessionRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateJoinSessionResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateJoinSessionRequest,
+) -> Optional[CreateJoinSessionResponse]:
+ """Create a Join session
+
+ Create a Join session and retrieve a session token. Pass this token to the Join JS component
+ function createJoin(). Add a vendor credential object for each vendor that should appear in the Join
+ UI.
+
+ Args:
+ body (CreateJoinSessionRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateJoinSessionResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ body=body,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateJoinSessionRequest,
+) -> Response[CreateJoinSessionResponse]:
+ """Create a Join session
+
+ Create a Join session and retrieve a session token. Pass this token to the Join JS component
+ function createJoin(). Add a vendor credential object for each vendor that should appear in the Join
+ UI.
+
+ Args:
+ body (CreateJoinSessionRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateJoinSessionResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateJoinSessionRequest,
+) -> Optional[CreateJoinSessionResponse]:
+ """Create a Join session
+
+ Create a Join session and retrieve a session token. Pass this token to the Join JS component
+ function createJoin(). Add a vendor credential object for each vendor that should appear in the Join
+ UI.
+
+ Args:
+ body (CreateJoinSessionRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateJoinSessionResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ body=body,
+ )
+ ).parsed
diff --git a/derapi/api/join/get_join_session_token.py b/derapi/api/join/get_join_session_token.py
new file mode 100644
index 0000000..0d75806
--- /dev/null
+++ b/derapi/api/join/get_join_session_token.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_join_session_token_response import GetJoinSessionTokenResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ session_id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/join/session/{session_id}/fetch-token",
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetJoinSessionTokenResponse]:
+ if response.status_code == 200:
+ response_200 = GetJoinSessionTokenResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetJoinSessionTokenResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ session_id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetJoinSessionTokenResponse]:
+ """Retrieve token(s) from a Join session
+
+ Use this endpoint to retrieve the token generated by an end-customer Join authorization
+
+ Args:
+ session_id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetJoinSessionTokenResponse]
+ """
+
+ kwargs = _get_kwargs(
+ session_id=session_id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ session_id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetJoinSessionTokenResponse]:
+ """Retrieve token(s) from a Join session
+
+ Use this endpoint to retrieve the token generated by an end-customer Join authorization
+
+ Args:
+ session_id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetJoinSessionTokenResponse
+ """
+
+ return sync_detailed(
+ session_id=session_id,
+ client=client,
+ ).parsed
+
+
+async def asyncio_detailed(
+ session_id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetJoinSessionTokenResponse]:
+ """Retrieve token(s) from a Join session
+
+ Use this endpoint to retrieve the token generated by an end-customer Join authorization
+
+ Args:
+ session_id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetJoinSessionTokenResponse]
+ """
+
+ kwargs = _get_kwargs(
+ session_id=session_id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ session_id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetJoinSessionTokenResponse]:
+ """Retrieve token(s) from a Join session
+
+ Use this endpoint to retrieve the token generated by an end-customer Join authorization
+
+ Args:
+ session_id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetJoinSessionTokenResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ session_id=session_id,
+ client=client,
+ )
+ ).parsed
diff --git a/derapi/api/sites/__init__.py b/derapi/api/sites/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/derapi/api/sites/get_site.py b/derapi/api/sites/get_site.py
new file mode 100644
index 0000000..01ae8f3
--- /dev/null
+++ b/derapi/api/sites/get_site.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_site_response import GetSiteResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/sites/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetSiteResponse]:
+ if response.status_code == 200:
+ response_200 = GetSiteResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetSiteResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetSiteResponse]:
+ """Return Site details
+
+ Returns details for a single Site including the list of devices associated with the Site.
+
+ Args:
+ id (str): the ID for the Site
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSiteResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetSiteResponse]:
+ """Return Site details
+
+ Returns details for a single Site including the list of devices associated with the Site.
+
+ Args:
+ id (str): the ID for the Site
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSiteResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetSiteResponse]:
+ """Return Site details
+
+ Returns details for a single Site including the list of devices associated with the Site.
+
+ Args:
+ id (str): the ID for the Site
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSiteResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetSiteResponse]:
+ """Return Site details
+
+ Returns details for a single Site including the list of devices associated with the Site.
+
+ Args:
+ id (str): the ID for the Site
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSiteResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ )
+ ).parsed
diff --git a/derapi/api/sites/get_site_battery_control.py b/derapi/api/sites/get_site_battery_control.py
new file mode 100644
index 0000000..aeb35bf
--- /dev/null
+++ b/derapi/api/sites/get_site_battery_control.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_site_battery_control_response import GetSiteBatteryControlResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/sites/{id}/battery-control",
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetSiteBatteryControlResponse]:
+ if response.status_code == 200:
+ response_200 = GetSiteBatteryControlResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetSiteBatteryControlResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetSiteBatteryControlResponse]:
+ """Returns Battery control state
+
+ Returns Battery control state
+
+ Args:
+ id (str): the ID for the Site
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSiteBatteryControlResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetSiteBatteryControlResponse]:
+ """Returns Battery control state
+
+ Returns Battery control state
+
+ Args:
+ id (str): the ID for the Site
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSiteBatteryControlResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetSiteBatteryControlResponse]:
+ """Returns Battery control state
+
+ Returns Battery control state
+
+ Args:
+ id (str): the ID for the Site
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSiteBatteryControlResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetSiteBatteryControlResponse]:
+ """Returns Battery control state
+
+ Returns Battery control state
+
+ Args:
+ id (str): the ID for the Site
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSiteBatteryControlResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ )
+ ).parsed
diff --git a/derapi/api/sites/get_site_battery_intervals.py b/derapi/api/sites/get_site_battery_intervals.py
new file mode 100644
index 0000000..0682e2f
--- /dev/null
+++ b/derapi/api/sites/get_site_battery_intervals.py
@@ -0,0 +1,393 @@
+import datetime
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_site_battery_intervals_response import GetSiteBatteryIntervalsResponse
+from ...models.site_battery_interval import SiteBatteryInterval
+from ...models.summary_level import SummaryLevel
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ id: str,
+ *,
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ json_summary_level: Union[Unset, str] = UNSET
+ if not isinstance(summary_level, Unset):
+ json_summary_level = summary_level.value
+
+ params["summaryLevel"] = json_summary_level
+
+ json_start = start.isoformat()
+ params["start"] = json_start
+
+ json_end = end.isoformat()
+ params["end"] = json_end
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/sites/{id}/battery-intervals",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetSiteBatteryIntervalsResponse]:
+ if response.status_code == 200:
+ response_200 = GetSiteBatteryIntervalsResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetSiteBatteryIntervalsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[GetSiteBatteryIntervalsResponse]:
+ """Returns Battery system interval data
+
+ Returns Site-level Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSiteBatteryIntervalsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[GetSiteBatteryIntervalsResponse]:
+ """Returns Battery system interval data
+
+ Returns Site-level Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSiteBatteryIntervalsResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[GetSiteBatteryIntervalsResponse]:
+ """Returns Battery system interval data
+
+ Returns Site-level Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSiteBatteryIntervalsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[GetSiteBatteryIntervalsResponse]:
+ """Returns Battery system interval data
+
+ Returns Site-level Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSiteBatteryIntervalsResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[SiteBatteryInterval]:
+ """Returns Battery system interval data
+
+ Returns Site-level Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[SiteBatteryInterval]
+ """
+
+ response = sync(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.intervals
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[SiteBatteryInterval]:
+ """Returns Battery system interval data
+
+ Returns Site-level Battery charge and discharge data aggregated to the specific granularity
+ requested for a specified start and end date. The energy data intervals are represented in kWh.
+ Intervals are always aligned with the start of a month, day, or hour. Partial period requests are
+ expanded to cover the full interval for the requested summary level. For example, a summary-level
+ request of month with a start date of 12/3 and end date of 1/1 will return data covering the entire
+ month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[SiteBatteryInterval]
+ """
+
+ response = await asyncio(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.intervals:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/api/sites/get_site_solar_inverter_intervals.py b/derapi/api/sites/get_site_solar_inverter_intervals.py
new file mode 100644
index 0000000..3c6a965
--- /dev/null
+++ b/derapi/api/sites/get_site_solar_inverter_intervals.py
@@ -0,0 +1,263 @@
+import datetime
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_site_solar_inverter_intervals_response import GetSiteSolarInverterIntervalsResponse
+from ...models.summary_level import SummaryLevel
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ id: str,
+ *,
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ json_summary_level: Union[Unset, str] = UNSET
+ if not isinstance(summary_level, Unset):
+ json_summary_level = summary_level.value
+
+ params["summaryLevel"] = json_summary_level
+
+ json_start = start.isoformat()
+ params["start"] = json_start
+
+ json_end = end.isoformat()
+ params["end"] = json_end
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/sites/{id}/solar-intervals",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetSiteSolarInverterIntervalsResponse]:
+ if response.status_code == 200:
+ response_200 = GetSiteSolarInverterIntervalsResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetSiteSolarInverterIntervalsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[GetSiteSolarInverterIntervalsResponse]:
+ """Returns Site-level solar production interval data
+
+ Returns Site-level solar production data aggregated to the specific granularity requested for a
+ specified start and end date. The energy data intervals are represented in kWh. Intervals are always
+ aligned with the start of a month, day, or hour. Partial period requests are expanded to cover the
+ full interval for the requested summary level. For example, a summary-level request of month with a
+ start date of 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSiteSolarInverterIntervalsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[GetSiteSolarInverterIntervalsResponse]:
+ """Returns Site-level solar production interval data
+
+ Returns Site-level solar production data aggregated to the specific granularity requested for a
+ specified start and end date. The energy data intervals are represented in kWh. Intervals are always
+ aligned with the start of a month, day, or hour. Partial period requests are expanded to cover the
+ full interval for the requested summary level. For example, a summary-level request of month with a
+ start date of 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSiteSolarInverterIntervalsResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[GetSiteSolarInverterIntervalsResponse]:
+ """Returns Site-level solar production interval data
+
+ Returns Site-level solar production data aggregated to the specific granularity requested for a
+ specified start and end date. The energy data intervals are represented in kWh. Intervals are always
+ aligned with the start of a month, day, or hour. Partial period requests are expanded to cover the
+ full interval for the requested summary level. For example, a summary-level request of month with a
+ start date of 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSiteSolarInverterIntervalsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[GetSiteSolarInverterIntervalsResponse]:
+ """Returns Site-level solar production interval data
+
+ Returns Site-level solar production data aggregated to the specific granularity requested for a
+ specified start and end date. The energy data intervals are represented in kWh. Intervals are always
+ aligned with the start of a month, day, or hour. Partial period requests are expanded to cover the
+ full interval for the requested summary level. For example, a summary-level request of month with a
+ start date of 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): the ID for the Site
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSiteSolarInverterIntervalsResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
diff --git a/derapi/api/sites/list_sites.py b/derapi/api/sites/list_sites.py
new file mode 100644
index 0000000..1f0f481
--- /dev/null
+++ b/derapi/api/sites/list_sites.py
@@ -0,0 +1,316 @@
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.list_sites_response import ListSitesResponse
+from ...models.site_summary import SiteSummary
+from ...models.vendor import Vendor
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ *,
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ json_vendor: Union[Unset, str] = UNSET
+ if not isinstance(vendor, Unset):
+ json_vendor = vendor.value
+
+ params["vendor"] = json_vendor
+
+ params["vendorID"] = vendor_id
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": "/sites",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[ListSitesResponse]:
+ if response.status_code == 200:
+ response_200 = ListSitesResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[ListSitesResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListSitesResponse]:
+ """Returns a list of Sites
+
+ Returns a list of Sites. In the case a vendor API request encounters an error details are provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListSitesResponse]
+ """
+
+ kwargs = _get_kwargs(
+ vendor=vendor,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListSitesResponse]:
+ """Returns a list of Sites
+
+ Returns a list of Sites. In the case a vendor API request encounters an error details are provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListSitesResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListSitesResponse]:
+ """Returns a list of Sites
+
+ Returns a list of Sites. In the case a vendor API request encounters an error details are provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListSitesResponse]
+ """
+
+ kwargs = _get_kwargs(
+ vendor=vendor,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListSitesResponse]:
+ """Returns a list of Sites
+
+ Returns a list of Sites. In the case a vendor API request encounters an error details are provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListSitesResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[SiteSummary]:
+ """Returns a list of Sites
+
+ Returns a list of Sites. In the case a vendor API request encounters an error details are provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[SiteSummary]
+ """
+
+ response = sync(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.sites
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[SiteSummary]:
+ """Returns a list of Sites
+
+ Returns a list of Sites. In the case a vendor API request encounters an error details are provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[SiteSummary]
+ """
+
+ response = await asyncio(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.sites:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ client=client,
+ vendor=vendor,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/api/sites/put_site_battery_control.py b/derapi/api/sites/put_site_battery_control.py
new file mode 100644
index 0000000..f220b25
--- /dev/null
+++ b/derapi/api/sites/put_site_battery_control.py
@@ -0,0 +1,205 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.put_site_battery_control_request import PutSiteBatteryControlRequest
+from ...models.put_site_battery_control_response import PutSiteBatteryControlResponse
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ id: str,
+ *,
+ body: PutSiteBatteryControlRequest,
+ program_id: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ headers: Dict[str, Any] = {}
+
+ params: Dict[str, Any] = {}
+
+ params["programID"] = program_id
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "put",
+ "url": f"/sites/{id}/battery-control",
+ "params": params,
+ }
+
+ _body = body.to_dict()
+
+ _kwargs["json"] = _body
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[PutSiteBatteryControlResponse]:
+ if response.status_code == 200:
+ response_200 = PutSiteBatteryControlResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[PutSiteBatteryControlResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: PutSiteBatteryControlRequest,
+ program_id: Union[Unset, str] = UNSET,
+) -> Response[PutSiteBatteryControlResponse]:
+ """Accepts Battery control signals for an individual Site
+
+ Accepts Battery control signals for individual Sites and translates those to vendor control
+ commands.
+
+ Args:
+ id (str): the ID for the Site
+ program_id (Union[Unset, str]):
+ body (PutSiteBatteryControlRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[PutSiteBatteryControlResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ body=body,
+ program_id=program_id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: PutSiteBatteryControlRequest,
+ program_id: Union[Unset, str] = UNSET,
+) -> Optional[PutSiteBatteryControlResponse]:
+ """Accepts Battery control signals for an individual Site
+
+ Accepts Battery control signals for individual Sites and translates those to vendor control
+ commands.
+
+ Args:
+ id (str): the ID for the Site
+ program_id (Union[Unset, str]):
+ body (PutSiteBatteryControlRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ PutSiteBatteryControlResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ body=body,
+ program_id=program_id,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: PutSiteBatteryControlRequest,
+ program_id: Union[Unset, str] = UNSET,
+) -> Response[PutSiteBatteryControlResponse]:
+ """Accepts Battery control signals for an individual Site
+
+ Accepts Battery control signals for individual Sites and translates those to vendor control
+ commands.
+
+ Args:
+ id (str): the ID for the Site
+ program_id (Union[Unset, str]):
+ body (PutSiteBatteryControlRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[PutSiteBatteryControlResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ body=body,
+ program_id=program_id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: PutSiteBatteryControlRequest,
+ program_id: Union[Unset, str] = UNSET,
+) -> Optional[PutSiteBatteryControlResponse]:
+ """Accepts Battery control signals for an individual Site
+
+ Accepts Battery control signals for individual Sites and translates those to vendor control
+ commands.
+
+ Args:
+ id (str): the ID for the Site
+ program_id (Union[Unset, str]):
+ body (PutSiteBatteryControlRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ PutSiteBatteryControlResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ body=body,
+ program_id=program_id,
+ )
+ ).parsed
diff --git a/derapi/api/solar_inverters/__init__.py b/derapi/api/solar_inverters/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/derapi/api/solar_inverters/get_solar_inverter.py b/derapi/api/solar_inverters/get_solar_inverter.py
new file mode 100644
index 0000000..27697f3
--- /dev/null
+++ b/derapi/api/solar_inverters/get_solar_inverter.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_solar_inverter_response import GetSolarInverterResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/solar-inverters/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetSolarInverterResponse]:
+ if response.status_code == 200:
+ response_200 = GetSolarInverterResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetSolarInverterResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetSolarInverterResponse]:
+ """Returns Solar Inverter details
+
+ Returns details for a single Solar Inverter
+
+ Args:
+ id (str): ID of the solar inverter
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSolarInverterResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetSolarInverterResponse]:
+ """Returns Solar Inverter details
+
+ Returns details for a single Solar Inverter
+
+ Args:
+ id (str): ID of the solar inverter
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSolarInverterResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetSolarInverterResponse]:
+ """Returns Solar Inverter details
+
+ Returns details for a single Solar Inverter
+
+ Args:
+ id (str): ID of the solar inverter
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSolarInverterResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetSolarInverterResponse]:
+ """Returns Solar Inverter details
+
+ Returns details for a single Solar Inverter
+
+ Args:
+ id (str): ID of the solar inverter
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSolarInverterResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ )
+ ).parsed
diff --git a/derapi/api/solar_inverters/get_solar_inverter_intervals.py b/derapi/api/solar_inverters/get_solar_inverter_intervals.py
new file mode 100644
index 0000000..dd19434
--- /dev/null
+++ b/derapi/api/solar_inverters/get_solar_inverter_intervals.py
@@ -0,0 +1,387 @@
+import datetime
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_solar_inverter_intervals_response import GetSolarInverterIntervalsResponse
+from ...models.solar_inverter_interval import SolarInverterInterval
+from ...models.summary_level import SummaryLevel
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ id: str,
+ *,
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ json_summary_level: Union[Unset, str] = UNSET
+ if not isinstance(summary_level, Unset):
+ json_summary_level = summary_level.value
+
+ params["summaryLevel"] = json_summary_level
+
+ json_start = start.isoformat()
+ params["start"] = json_start
+
+ json_end = end.isoformat()
+ params["end"] = json_end
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/solar-inverters/{id}/intervals",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetSolarInverterIntervalsResponse]:
+ if response.status_code == 200:
+ response_200 = GetSolarInverterIntervalsResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetSolarInverterIntervalsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[GetSolarInverterIntervalsResponse]:
+ """Returns solar production data
+
+ Returns solar production data aggregated to the specific granularity requested for a specified start
+ and end date. The energy data intervals are represented in kWh. Intervals are always aligned with
+ the start of a month, day, or hour. Partial period requests are expanded to cover the full interval
+ for the requested summary level. For example, a summary-level request of month with a start date of
+ 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): ID of the solar inverter
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSolarInverterIntervalsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[GetSolarInverterIntervalsResponse]:
+ """Returns solar production data
+
+ Returns solar production data aggregated to the specific granularity requested for a specified start
+ and end date. The energy data intervals are represented in kWh. Intervals are always aligned with
+ the start of a month, day, or hour. Partial period requests are expanded to cover the full interval
+ for the requested summary level. For example, a summary-level request of month with a start date of
+ 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): ID of the solar inverter
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSolarInverterIntervalsResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[GetSolarInverterIntervalsResponse]:
+ """Returns solar production data
+
+ Returns solar production data aggregated to the specific granularity requested for a specified start
+ and end date. The energy data intervals are represented in kWh. Intervals are always aligned with
+ the start of a month, day, or hour. Partial period requests are expanded to cover the full interval
+ for the requested summary level. For example, a summary-level request of month with a start date of
+ 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): ID of the solar inverter
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetSolarInverterIntervalsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[GetSolarInverterIntervalsResponse]:
+ """Returns solar production data
+
+ Returns solar production data aggregated to the specific granularity requested for a specified start
+ and end date. The energy data intervals are represented in kWh. Intervals are always aligned with
+ the start of a month, day, or hour. Partial period requests are expanded to cover the full interval
+ for the requested summary level. For example, a summary-level request of month with a start date of
+ 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): ID of the solar inverter
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetSolarInverterIntervalsResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[SolarInverterInterval]:
+ """Returns solar production data
+
+ Returns solar production data aggregated to the specific granularity requested for a specified start
+ and end date. The energy data intervals are represented in kWh. Intervals are always aligned with
+ the start of a month, day, or hour. Partial period requests are expanded to cover the full interval
+ for the requested summary level. For example, a summary-level request of month with a start date of
+ 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): ID of the solar inverter
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[SolarInverterInterval]
+ """
+
+ response = sync(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.intervals
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ summary_level: Union[Unset, SummaryLevel] = UNSET,
+ start: datetime.datetime,
+ end: datetime.datetime,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[SolarInverterInterval]:
+ """Returns solar production data
+
+ Returns solar production data aggregated to the specific granularity requested for a specified start
+ and end date. The energy data intervals are represented in kWh. Intervals are always aligned with
+ the start of a month, day, or hour. Partial period requests are expanded to cover the full interval
+ for the requested summary level. For example, a summary-level request of month with a start date of
+ 12/3 and end date of 1/1 will return data covering the entire month of December.
+
+ Args:
+ id (str): ID of the solar inverter
+ summary_level (Union[Unset, SummaryLevel]):
+ start (datetime.datetime):
+ end (datetime.datetime):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[SolarInverterInterval]
+ """
+
+ response = await asyncio(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.intervals:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ id=id,
+ client=client,
+ summary_level=summary_level,
+ start=start,
+ end=end,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/api/solar_inverters/list_solar_inverters.py b/derapi/api/solar_inverters/list_solar_inverters.py
new file mode 100644
index 0000000..ba1e26f
--- /dev/null
+++ b/derapi/api/solar_inverters/list_solar_inverters.py
@@ -0,0 +1,345 @@
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.list_solar_inverters_response import ListSolarInvertersResponse
+from ...models.solar_inverter_summary import SolarInverterSummary
+from ...models.vendor import Vendor
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ *,
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ json_vendor: Union[Unset, str] = UNSET
+ if not isinstance(vendor, Unset):
+ json_vendor = vendor.value
+
+ params["vendor"] = json_vendor
+
+ params["vendorSiteID"] = vendor_site_id
+
+ params["vendorID"] = vendor_id
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": "/solar-inverters",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[ListSolarInvertersResponse]:
+ if response.status_code == 200:
+ response_200 = ListSolarInvertersResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[ListSolarInvertersResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListSolarInvertersResponse]:
+ """Returns a list of Solar Inverters
+
+ Returns a list of Solar Inverters. In the case a vendor API request encounters an erorr details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_site_id (Union[Unset, str]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListSolarInvertersResponse]
+ """
+
+ kwargs = _get_kwargs(
+ vendor=vendor,
+ vendor_site_id=vendor_site_id,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListSolarInvertersResponse]:
+ """Returns a list of Solar Inverters
+
+ Returns a list of Solar Inverters. In the case a vendor API request encounters an erorr details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_site_id (Union[Unset, str]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListSolarInvertersResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ vendor=vendor,
+ vendor_site_id=vendor_site_id,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListSolarInvertersResponse]:
+ """Returns a list of Solar Inverters
+
+ Returns a list of Solar Inverters. In the case a vendor API request encounters an erorr details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_site_id (Union[Unset, str]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListSolarInvertersResponse]
+ """
+
+ kwargs = _get_kwargs(
+ vendor=vendor,
+ vendor_site_id=vendor_site_id,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListSolarInvertersResponse]:
+ """Returns a list of Solar Inverters
+
+ Returns a list of Solar Inverters. In the case a vendor API request encounters an erorr details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_site_id (Union[Unset, str]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListSolarInvertersResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ vendor=vendor,
+ vendor_site_id=vendor_site_id,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[SolarInverterSummary]:
+ """Returns a list of Solar Inverters
+
+ Returns a list of Solar Inverters. In the case a vendor API request encounters an erorr details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_site_id (Union[Unset, str]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[SolarInverterSummary]
+ """
+
+ response = sync(
+ client=client,
+ vendor=vendor,
+ vendor_site_id=vendor_site_id,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.solar_inverters
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ client=client,
+ vendor=vendor,
+ vendor_site_id=vendor_site_id,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ vendor: Union[Unset, Vendor] = UNSET,
+ vendor_site_id: Union[Unset, str] = UNSET,
+ vendor_id: Union[Unset, str] = UNSET,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[SolarInverterSummary]:
+ """Returns a list of Solar Inverters
+
+ Returns a list of Solar Inverters. In the case a vendor API request encounters an erorr details are
+ provided.
+
+ Args:
+ vendor (Union[Unset, Vendor]):
+ vendor_site_id (Union[Unset, str]):
+ vendor_id (Union[Unset, str]):
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[SolarInverterSummary]
+ """
+
+ response = await asyncio(
+ client=client,
+ vendor=vendor,
+ vendor_site_id=vendor_site_id,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.solar_inverters:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ client=client,
+ vendor=vendor,
+ vendor_site_id=vendor_site_id,
+ vendor_id=vendor_id,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/api/vendor_credentials/__init__.py b/derapi/api/vendor_credentials/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/derapi/api/vendor_credentials/create_vendor_credentials.py b/derapi/api/vendor_credentials/create_vendor_credentials.py
new file mode 100644
index 0000000..a9fb378
--- /dev/null
+++ b/derapi/api/vendor_credentials/create_vendor_credentials.py
@@ -0,0 +1,188 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.create_vendor_credentials_request import CreateVendorCredentialsRequest
+from ...models.create_vendor_credentials_response import CreateVendorCredentialsResponse
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ *,
+ body: CreateVendorCredentialsRequest,
+ include_secrets: Union[Unset, bool] = False,
+) -> Dict[str, Any]:
+ headers: Dict[str, Any] = {}
+
+ params: Dict[str, Any] = {}
+
+ params["includeSecrets"] = include_secrets
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "post",
+ "url": "/vendor-credentials",
+ "params": params,
+ }
+
+ _body = body.to_dict()
+
+ _kwargs["json"] = _body
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[CreateVendorCredentialsResponse]:
+ if response.status_code == 201:
+ response_201 = CreateVendorCredentialsResponse.from_dict(response.json())
+
+ return response_201
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[CreateVendorCredentialsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVendorCredentialsRequest,
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[CreateVendorCredentialsResponse]:
+ """Stores vendor credentials
+
+ Stores vendor credentials as specified.
+
+ Args:
+ include_secrets (Union[Unset, bool]): Default: False.
+ body (CreateVendorCredentialsRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateVendorCredentialsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ include_secrets=include_secrets,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVendorCredentialsRequest,
+ include_secrets: Union[Unset, bool] = False,
+) -> Optional[CreateVendorCredentialsResponse]:
+ """Stores vendor credentials
+
+ Stores vendor credentials as specified.
+
+ Args:
+ include_secrets (Union[Unset, bool]): Default: False.
+ body (CreateVendorCredentialsRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateVendorCredentialsResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ body=body,
+ include_secrets=include_secrets,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVendorCredentialsRequest,
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[CreateVendorCredentialsResponse]:
+ """Stores vendor credentials
+
+ Stores vendor credentials as specified.
+
+ Args:
+ include_secrets (Union[Unset, bool]): Default: False.
+ body (CreateVendorCredentialsRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateVendorCredentialsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ include_secrets=include_secrets,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVendorCredentialsRequest,
+ include_secrets: Union[Unset, bool] = False,
+) -> Optional[CreateVendorCredentialsResponse]:
+ """Stores vendor credentials
+
+ Stores vendor credentials as specified.
+
+ Args:
+ include_secrets (Union[Unset, bool]): Default: False.
+ body (CreateVendorCredentialsRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateVendorCredentialsResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ body=body,
+ include_secrets=include_secrets,
+ )
+ ).parsed
diff --git a/derapi/api/vendor_credentials/delete_vendor_credentials.py b/derapi/api/vendor_credentials/delete_vendor_credentials.py
new file mode 100644
index 0000000..5a7327b
--- /dev/null
+++ b/derapi/api/vendor_credentials/delete_vendor_credentials.py
@@ -0,0 +1,112 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ id: str,
+ *,
+ include_secrets: Union[Unset, bool] = False,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ params["includeSecrets"] = include_secrets
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "delete",
+ "url": f"/vendor-credentials/{id}",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
+ if response.status_code == 204:
+ return None
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[Any]:
+ """Delete stored vendor credentials
+
+ Deletes the stored vendor credentials with this ID
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ include_secrets=include_secrets,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[Any]:
+ """Delete stored vendor credentials
+
+ Deletes the stored vendor credentials with this ID
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ include_secrets=include_secrets,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
diff --git a/derapi/api/vendor_credentials/get_vendor_credentials.py b/derapi/api/vendor_credentials/get_vendor_credentials.py
new file mode 100644
index 0000000..b8fd246
--- /dev/null
+++ b/derapi/api/vendor_credentials/get_vendor_credentials.py
@@ -0,0 +1,179 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_vendor_credentials_response import GetVendorCredentialsResponse
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ id: str,
+ *,
+ include_secrets: Union[Unset, bool] = False,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ params["includeSecrets"] = include_secrets
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/vendor-credentials/{id}",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetVendorCredentialsResponse]:
+ if response.status_code == 200:
+ response_200 = GetVendorCredentialsResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetVendorCredentialsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[GetVendorCredentialsResponse]:
+ """Fetches specified credentials
+
+ Fetches the Derapi managed credentials for the specified vendor and name
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetVendorCredentialsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ include_secrets=include_secrets,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ include_secrets: Union[Unset, bool] = False,
+) -> Optional[GetVendorCredentialsResponse]:
+ """Fetches specified credentials
+
+ Fetches the Derapi managed credentials for the specified vendor and name
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetVendorCredentialsResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ include_secrets=include_secrets,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[GetVendorCredentialsResponse]:
+ """Fetches specified credentials
+
+ Fetches the Derapi managed credentials for the specified vendor and name
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetVendorCredentialsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ include_secrets=include_secrets,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ include_secrets: Union[Unset, bool] = False,
+) -> Optional[GetVendorCredentialsResponse]:
+ """Fetches specified credentials
+
+ Fetches the Derapi managed credentials for the specified vendor and name
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetVendorCredentialsResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ include_secrets=include_secrets,
+ )
+ ).parsed
diff --git a/derapi/api/vendor_credentials/list_vendor_credentials.py b/derapi/api/vendor_credentials/list_vendor_credentials.py
new file mode 100644
index 0000000..2c197a2
--- /dev/null
+++ b/derapi/api/vendor_credentials/list_vendor_credentials.py
@@ -0,0 +1,339 @@
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.list_vendor_credentials_response import ListVendorCredentialsResponse
+from ...models.vendor import Vendor
+from ...models.vendor_credentials import VendorCredentials
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ *,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+ vendor: Union[Unset, Vendor] = UNSET,
+ name: Union[Unset, str] = UNSET,
+ include_secrets: Union[Unset, bool] = False,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ json_vendor: Union[Unset, str] = UNSET
+ if not isinstance(vendor, Unset):
+ json_vendor = vendor.value
+
+ params["vendor"] = json_vendor
+
+ params["name"] = name
+
+ params["includeSecrets"] = include_secrets
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": "/vendor-credentials",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[ListVendorCredentialsResponse]:
+ if response.status_code == 200:
+ response_200 = ListVendorCredentialsResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[ListVendorCredentialsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+ vendor: Union[Unset, Vendor] = UNSET,
+ name: Union[Unset, str] = UNSET,
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[ListVendorCredentialsResponse]:
+ """Lists stored vendor credentials
+
+ Lists stored vendor credentials, paginated and optionally filtered.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+ vendor (Union[Unset, Vendor]):
+ name (Union[Unset, str]):
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListVendorCredentialsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ page_size=page_size,
+ page_token=page_token,
+ vendor=vendor,
+ name=name,
+ include_secrets=include_secrets,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+ vendor: Union[Unset, Vendor] = UNSET,
+ name: Union[Unset, str] = UNSET,
+ include_secrets: Union[Unset, bool] = False,
+) -> Optional[ListVendorCredentialsResponse]:
+ """Lists stored vendor credentials
+
+ Lists stored vendor credentials, paginated and optionally filtered.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+ vendor (Union[Unset, Vendor]):
+ name (Union[Unset, str]):
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListVendorCredentialsResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ vendor=vendor,
+ name=name,
+ include_secrets=include_secrets,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+ vendor: Union[Unset, Vendor] = UNSET,
+ name: Union[Unset, str] = UNSET,
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[ListVendorCredentialsResponse]:
+ """Lists stored vendor credentials
+
+ Lists stored vendor credentials, paginated and optionally filtered.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+ vendor (Union[Unset, Vendor]):
+ name (Union[Unset, str]):
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListVendorCredentialsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ page_size=page_size,
+ page_token=page_token,
+ vendor=vendor,
+ name=name,
+ include_secrets=include_secrets,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+ vendor: Union[Unset, Vendor] = UNSET,
+ name: Union[Unset, str] = UNSET,
+ include_secrets: Union[Unset, bool] = False,
+) -> Optional[ListVendorCredentialsResponse]:
+ """Lists stored vendor credentials
+
+ Lists stored vendor credentials, paginated and optionally filtered.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+ vendor (Union[Unset, Vendor]):
+ name (Union[Unset, str]):
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListVendorCredentialsResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ vendor=vendor,
+ name=name,
+ include_secrets=include_secrets,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+ vendor: Union[Unset, Vendor] = UNSET,
+ name: Union[Unset, str] = UNSET,
+ include_secrets: Union[Unset, bool] = False,
+) -> Iterator[VendorCredentials]:
+ """Lists stored vendor credentials
+
+ Lists stored vendor credentials, paginated and optionally filtered.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+ vendor (Union[Unset, Vendor]):
+ name (Union[Unset, str]):
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[VendorCredentials]
+ """
+
+ response = sync(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ vendor=vendor,
+ name=name,
+ include_secrets=include_secrets,
+ )
+ while response is not None:
+ yield from response.vendor_credentials
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ vendor=vendor,
+ name=name,
+ include_secrets=include_secrets,
+ )
+
+
+async def async_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+ vendor: Union[Unset, Vendor] = UNSET,
+ name: Union[Unset, str] = UNSET,
+ include_secrets: Union[Unset, bool] = False,
+) -> AsyncIterator[VendorCredentials]:
+ """Lists stored vendor credentials
+
+ Lists stored vendor credentials, paginated and optionally filtered.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+ vendor (Union[Unset, Vendor]):
+ name (Union[Unset, str]):
+ include_secrets (Union[Unset, bool]): Default: False.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[VendorCredentials]
+ """
+
+ response = await asyncio(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ vendor=vendor,
+ name=name,
+ include_secrets=include_secrets,
+ )
+ while response is not None:
+ for item in response.vendor_credentials:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ vendor=vendor,
+ name=name,
+ include_secrets=include_secrets,
+ )
diff --git a/derapi/api/vendor_credentials/update_vendor_credentials.py b/derapi/api/vendor_credentials/update_vendor_credentials.py
new file mode 100644
index 0000000..b2842d5
--- /dev/null
+++ b/derapi/api/vendor_credentials/update_vendor_credentials.py
@@ -0,0 +1,234 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.update_vendor_credentials_request import UpdateVendorCredentialsRequest
+from ...models.update_vendor_credentials_response import UpdateVendorCredentialsResponse
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ id: str,
+ *,
+ body: Union[
+ UpdateVendorCredentialsRequest,
+ UpdateVendorCredentialsRequest,
+ ],
+ include_secrets: Union[Unset, bool] = False,
+) -> Dict[str, Any]:
+ headers: Dict[str, Any] = {}
+
+ params: Dict[str, Any] = {}
+
+ params["includeSecrets"] = include_secrets
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "patch",
+ "url": f"/vendor-credentials/{id}",
+ "params": params,
+ }
+
+ if isinstance(body, UpdateVendorCredentialsRequest):
+ _json_body = body.to_dict()
+
+ _kwargs["json"] = _json_body
+ headers["Content-Type"] = "application/merge-patch+json"
+ if isinstance(body, UpdateVendorCredentialsRequest):
+ _json_body = body.to_dict()
+
+ _kwargs["json"] = _json_body
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[UpdateVendorCredentialsResponse]:
+ if response.status_code == 200:
+ response_200 = UpdateVendorCredentialsResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[UpdateVendorCredentialsResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: Union[
+ UpdateVendorCredentialsRequest,
+ UpdateVendorCredentialsRequest,
+ ],
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[UpdateVendorCredentialsResponse]:
+ """Updates the stored credentials
+
+ Updates the stored credentials with the given ID. The request body will be interpreted as a [JSON
+ Merge Patch](https://datatracker.ietf.org/doc/html/rfc7396) against the stored credentials. Note
+ that updating the 'vendor' or 'type' fields is not supported.
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+ body (UpdateVendorCredentialsRequest):
+ body (UpdateVendorCredentialsRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[UpdateVendorCredentialsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ body=body,
+ include_secrets=include_secrets,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: Union[
+ UpdateVendorCredentialsRequest,
+ UpdateVendorCredentialsRequest,
+ ],
+ include_secrets: Union[Unset, bool] = False,
+) -> Optional[UpdateVendorCredentialsResponse]:
+ """Updates the stored credentials
+
+ Updates the stored credentials with the given ID. The request body will be interpreted as a [JSON
+ Merge Patch](https://datatracker.ietf.org/doc/html/rfc7396) against the stored credentials. Note
+ that updating the 'vendor' or 'type' fields is not supported.
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+ body (UpdateVendorCredentialsRequest):
+ body (UpdateVendorCredentialsRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ UpdateVendorCredentialsResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ body=body,
+ include_secrets=include_secrets,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: Union[
+ UpdateVendorCredentialsRequest,
+ UpdateVendorCredentialsRequest,
+ ],
+ include_secrets: Union[Unset, bool] = False,
+) -> Response[UpdateVendorCredentialsResponse]:
+ """Updates the stored credentials
+
+ Updates the stored credentials with the given ID. The request body will be interpreted as a [JSON
+ Merge Patch](https://datatracker.ietf.org/doc/html/rfc7396) against the stored credentials. Note
+ that updating the 'vendor' or 'type' fields is not supported.
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+ body (UpdateVendorCredentialsRequest):
+ body (UpdateVendorCredentialsRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[UpdateVendorCredentialsResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ body=body,
+ include_secrets=include_secrets,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: Union[
+ UpdateVendorCredentialsRequest,
+ UpdateVendorCredentialsRequest,
+ ],
+ include_secrets: Union[Unset, bool] = False,
+) -> Optional[UpdateVendorCredentialsResponse]:
+ """Updates the stored credentials
+
+ Updates the stored credentials with the given ID. The request body will be interpreted as a [JSON
+ Merge Patch](https://datatracker.ietf.org/doc/html/rfc7396) against the stored credentials. Note
+ that updating the 'vendor' or 'type' fields is not supported.
+
+ Args:
+ id (str): ID for the vendor credentials
+ include_secrets (Union[Unset, bool]): Default: False.
+ body (UpdateVendorCredentialsRequest):
+ body (UpdateVendorCredentialsRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ UpdateVendorCredentialsResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ body=body,
+ include_secrets=include_secrets,
+ )
+ ).parsed
diff --git a/derapi/api/virtual/__init__.py b/derapi/api/virtual/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/derapi/api/virtual/create_virtual_battery.py b/derapi/api/virtual/create_virtual_battery.py
new file mode 100644
index 0000000..e2d976c
--- /dev/null
+++ b/derapi/api/virtual/create_virtual_battery.py
@@ -0,0 +1,172 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.create_virtual_battery_request import CreateVirtualBatteryRequest
+from ...models.create_virtual_battery_response import CreateVirtualBatteryResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ *,
+ body: CreateVirtualBatteryRequest,
+) -> Dict[str, Any]:
+ headers: Dict[str, Any] = {}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "post",
+ "url": "/virtual/batteries",
+ }
+
+ _body = body.to_dict()
+
+ _kwargs["json"] = _body
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[CreateVirtualBatteryResponse]:
+ if response.status_code == 201:
+ response_201 = CreateVirtualBatteryResponse.from_dict(response.json())
+
+ return response_201
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[CreateVirtualBatteryResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualBatteryRequest,
+) -> Response[CreateVirtualBatteryResponse]:
+ """Create a Virtual Battery
+
+ Create Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualBatteryRequest): Fields the user would like to provide. Omitted ones
+ will be inferred.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateVirtualBatteryResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualBatteryRequest,
+) -> Optional[CreateVirtualBatteryResponse]:
+ """Create a Virtual Battery
+
+ Create Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualBatteryRequest): Fields the user would like to provide. Omitted ones
+ will be inferred.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateVirtualBatteryResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ body=body,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualBatteryRequest,
+) -> Response[CreateVirtualBatteryResponse]:
+ """Create a Virtual Battery
+
+ Create Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualBatteryRequest): Fields the user would like to provide. Omitted ones
+ will be inferred.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateVirtualBatteryResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualBatteryRequest,
+) -> Optional[CreateVirtualBatteryResponse]:
+ """Create a Virtual Battery
+
+ Create Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualBatteryRequest): Fields the user would like to provide. Omitted ones
+ will be inferred.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateVirtualBatteryResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ body=body,
+ )
+ ).parsed
diff --git a/derapi/api/virtual/create_virtual_site.py b/derapi/api/virtual/create_virtual_site.py
new file mode 100644
index 0000000..adcfbef
--- /dev/null
+++ b/derapi/api/virtual/create_virtual_site.py
@@ -0,0 +1,172 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.create_virtual_site_request import CreateVirtualSiteRequest
+from ...models.create_virtual_site_response import CreateVirtualSiteResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ *,
+ body: CreateVirtualSiteRequest,
+) -> Dict[str, Any]:
+ headers: Dict[str, Any] = {}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "post",
+ "url": "/virtual/sites",
+ }
+
+ _body = body.to_dict()
+
+ _kwargs["json"] = _body
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[CreateVirtualSiteResponse]:
+ if response.status_code == 201:
+ response_201 = CreateVirtualSiteResponse.from_dict(response.json())
+
+ return response_201
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[CreateVirtualSiteResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualSiteRequest,
+) -> Response[CreateVirtualSiteResponse]:
+ """Create a Virtual Site
+
+ Create a Virtual Site test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualSiteRequest): Fields the user would like to provide. Omitted ones will
+ be inferred.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateVirtualSiteResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualSiteRequest,
+) -> Optional[CreateVirtualSiteResponse]:
+ """Create a Virtual Site
+
+ Create a Virtual Site test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualSiteRequest): Fields the user would like to provide. Omitted ones will
+ be inferred.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateVirtualSiteResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ body=body,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualSiteRequest,
+) -> Response[CreateVirtualSiteResponse]:
+ """Create a Virtual Site
+
+ Create a Virtual Site test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualSiteRequest): Fields the user would like to provide. Omitted ones will
+ be inferred.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateVirtualSiteResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualSiteRequest,
+) -> Optional[CreateVirtualSiteResponse]:
+ """Create a Virtual Site
+
+ Create a Virtual Site test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualSiteRequest): Fields the user would like to provide. Omitted ones will
+ be inferred.
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateVirtualSiteResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ body=body,
+ )
+ ).parsed
diff --git a/derapi/api/virtual/create_virtual_solar_inverter.py b/derapi/api/virtual/create_virtual_solar_inverter.py
new file mode 100644
index 0000000..6ff99af
--- /dev/null
+++ b/derapi/api/virtual/create_virtual_solar_inverter.py
@@ -0,0 +1,168 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.create_virtual_solar_inverter_request import CreateVirtualSolarInverterRequest
+from ...models.create_virtual_solar_inverter_response import CreateVirtualSolarInverterResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ *,
+ body: CreateVirtualSolarInverterRequest,
+) -> Dict[str, Any]:
+ headers: Dict[str, Any] = {}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "post",
+ "url": "/virtual/solar-inverters",
+ }
+
+ _body = body.to_dict()
+
+ _kwargs["json"] = _body
+ headers["Content-Type"] = "application/json"
+
+ _kwargs["headers"] = headers
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[CreateVirtualSolarInverterResponse]:
+ if response.status_code == 201:
+ response_201 = CreateVirtualSolarInverterResponse.from_dict(response.json())
+
+ return response_201
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[CreateVirtualSolarInverterResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualSolarInverterRequest,
+) -> Response[CreateVirtualSolarInverterResponse]:
+ """Create a virtual solar inverter
+
+ Create virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualSolarInverterRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateVirtualSolarInverterResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualSolarInverterRequest,
+) -> Optional[CreateVirtualSolarInverterResponse]:
+ """Create a virtual solar inverter
+
+ Create virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualSolarInverterRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateVirtualSolarInverterResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ body=body,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualSolarInverterRequest,
+) -> Response[CreateVirtualSolarInverterResponse]:
+ """Create a virtual solar inverter
+
+ Create virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualSolarInverterRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[CreateVirtualSolarInverterResponse]
+ """
+
+ kwargs = _get_kwargs(
+ body=body,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ body: CreateVirtualSolarInverterRequest,
+) -> Optional[CreateVirtualSolarInverterResponse]:
+ """Create a virtual solar inverter
+
+ Create virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ body (CreateVirtualSolarInverterRequest):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ CreateVirtualSolarInverterResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ body=body,
+ )
+ ).parsed
diff --git a/derapi/api/virtual/delete_virtual_battery.py b/derapi/api/virtual/delete_virtual_battery.py
new file mode 100644
index 0000000..f18aab0
--- /dev/null
+++ b/derapi/api/virtual/delete_virtual_battery.py
@@ -0,0 +1,97 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "delete",
+ "url": f"/virtual/batteries/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
+ if response.status_code == 204:
+ return None
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[Any]:
+ """Delete Virtual Battery
+
+ Delete Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[Any]:
+ """Delete Virtual Battery
+
+ Delete Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
diff --git a/derapi/api/virtual/delete_virtual_site.py b/derapi/api/virtual/delete_virtual_site.py
new file mode 100644
index 0000000..b41736b
--- /dev/null
+++ b/derapi/api/virtual/delete_virtual_site.py
@@ -0,0 +1,97 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "delete",
+ "url": f"/virtual/sites/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
+ if response.status_code == 204:
+ return None
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[Any]:
+ """Delete Virtual Site
+
+ Delete Virtual Site test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[Any]:
+ """Delete Virtual Site
+
+ Delete Virtual Site test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
diff --git a/derapi/api/virtual/delete_virtual_solar_inverter.py b/derapi/api/virtual/delete_virtual_solar_inverter.py
new file mode 100644
index 0000000..ba164cf
--- /dev/null
+++ b/derapi/api/virtual/delete_virtual_solar_inverter.py
@@ -0,0 +1,97 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "delete",
+ "url": f"/virtual/solar-inverters/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
+ if response.status_code == 204:
+ return None
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[Any]:
+ """Delete virtual solar inverter
+
+ Delete virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[Any]:
+ """Delete virtual solar inverter
+
+ Delete virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[Any]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
diff --git a/derapi/api/virtual/get_virtual_battery.py b/derapi/api/virtual/get_virtual_battery.py
new file mode 100644
index 0000000..5139307
--- /dev/null
+++ b/derapi/api/virtual/get_virtual_battery.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_virtual_battery_response import GetVirtualBatteryResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/virtual/batteries/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetVirtualBatteryResponse]:
+ if response.status_code == 200:
+ response_200 = GetVirtualBatteryResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetVirtualBatteryResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetVirtualBatteryResponse]:
+ """Get Virtual Battery
+
+ Get Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetVirtualBatteryResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetVirtualBatteryResponse]:
+ """Get Virtual Battery
+
+ Get Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetVirtualBatteryResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetVirtualBatteryResponse]:
+ """Get Virtual Battery
+
+ Get Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetVirtualBatteryResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetVirtualBatteryResponse]:
+ """Get Virtual Battery
+
+ Get Virtual Battery test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetVirtualBatteryResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ )
+ ).parsed
diff --git a/derapi/api/virtual/get_virtual_site.py b/derapi/api/virtual/get_virtual_site.py
new file mode 100644
index 0000000..ec3ec01
--- /dev/null
+++ b/derapi/api/virtual/get_virtual_site.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_virtual_site_response import GetVirtualSiteResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/virtual/sites/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetVirtualSiteResponse]:
+ if response.status_code == 200:
+ response_200 = GetVirtualSiteResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetVirtualSiteResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetVirtualSiteResponse]:
+ """Get Virtual Site
+
+ Get Virtual Site test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetVirtualSiteResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetVirtualSiteResponse]:
+ """Get Virtual Site
+
+ Get Virtual Site test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetVirtualSiteResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetVirtualSiteResponse]:
+ """Get Virtual Site
+
+ Get Virtual Site test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetVirtualSiteResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetVirtualSiteResponse]:
+ """Get Virtual Site
+
+ Get Virtual Site test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetVirtualSiteResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ )
+ ).parsed
diff --git a/derapi/api/virtual/get_virtual_solar_inverter.py b/derapi/api/virtual/get_virtual_solar_inverter.py
new file mode 100644
index 0000000..19bb08e
--- /dev/null
+++ b/derapi/api/virtual/get_virtual_solar_inverter.py
@@ -0,0 +1,158 @@
+from http import HTTPStatus
+from typing import Any, Dict, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.get_virtual_solar_inverter_response import GetVirtualSolarInverterResponse
+from ...types import Response
+
+
+def _get_kwargs(
+ id: str,
+) -> Dict[str, Any]:
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": f"/virtual/solar-inverters/{id}",
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[GetVirtualSolarInverterResponse]:
+ if response.status_code == 200:
+ response_200 = GetVirtualSolarInverterResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[GetVirtualSolarInverterResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetVirtualSolarInverterResponse]:
+ """Get virtual solar inverter
+
+ Get virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetVirtualSolarInverterResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetVirtualSolarInverterResponse]:
+ """Get virtual solar inverter
+
+ Get virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetVirtualSolarInverterResponse
+ """
+
+ return sync_detailed(
+ id=id,
+ client=client,
+ ).parsed
+
+
+async def asyncio_detailed(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Response[GetVirtualSolarInverterResponse]:
+ """Get virtual solar inverter
+
+ Get virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[GetVirtualSolarInverterResponse]
+ """
+
+ kwargs = _get_kwargs(
+ id=id,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ id: str,
+ *,
+ client: Union[AuthenticatedClient, Client],
+) -> Optional[GetVirtualSolarInverterResponse]:
+ """Get virtual solar inverter
+
+ Get virtual solar inverter test configuration in the current sandbox.
+
+ Args:
+ id (str):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ GetVirtualSolarInverterResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ id=id,
+ client=client,
+ )
+ ).parsed
diff --git a/derapi/api/virtual/list_virtual_batteries.py b/derapi/api/virtual/list_virtual_batteries.py
new file mode 100644
index 0000000..9c55bb1
--- /dev/null
+++ b/derapi/api/virtual/list_virtual_batteries.py
@@ -0,0 +1,265 @@
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.list_virtual_batteries_response import ListVirtualBatteriesResponse
+from ...models.virtual_battery import VirtualBattery
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ *,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": "/virtual/batteries",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[ListVirtualBatteriesResponse]:
+ if response.status_code == 200:
+ response_200 = ListVirtualBatteriesResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[ListVirtualBatteriesResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListVirtualBatteriesResponse]:
+ """List Virtual Batteries
+
+ List Virtual Battery test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListVirtualBatteriesResponse]
+ """
+
+ kwargs = _get_kwargs(
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListVirtualBatteriesResponse]:
+ """List Virtual Batteries
+
+ List Virtual Battery test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListVirtualBatteriesResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListVirtualBatteriesResponse]:
+ """List Virtual Batteries
+
+ List Virtual Battery test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListVirtualBatteriesResponse]
+ """
+
+ kwargs = _get_kwargs(
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListVirtualBatteriesResponse]:
+ """List Virtual Batteries
+
+ List Virtual Battery test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListVirtualBatteriesResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[VirtualBattery]:
+ """List Virtual Batteries
+
+ List Virtual Battery test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[VirtualBattery]
+ """
+
+ response = sync(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.virtual_batteries
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[VirtualBattery]:
+ """List Virtual Batteries
+
+ List Virtual Battery test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[VirtualBattery]
+ """
+
+ response = await asyncio(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.virtual_batteries:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/api/virtual/list_virtual_sites.py b/derapi/api/virtual/list_virtual_sites.py
new file mode 100644
index 0000000..531f985
--- /dev/null
+++ b/derapi/api/virtual/list_virtual_sites.py
@@ -0,0 +1,265 @@
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.list_virtual_sites_response import ListVirtualSitesResponse
+from ...models.virtual_site import VirtualSite
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ *,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": "/virtual/sites",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[ListVirtualSitesResponse]:
+ if response.status_code == 200:
+ response_200 = ListVirtualSitesResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[ListVirtualSitesResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListVirtualSitesResponse]:
+ """List Virtual Sites
+
+ List Virtual Site test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListVirtualSitesResponse]
+ """
+
+ kwargs = _get_kwargs(
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListVirtualSitesResponse]:
+ """List Virtual Sites
+
+ List Virtual Site test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListVirtualSitesResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListVirtualSitesResponse]:
+ """List Virtual Sites
+
+ List Virtual Site test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListVirtualSitesResponse]
+ """
+
+ kwargs = _get_kwargs(
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListVirtualSitesResponse]:
+ """List Virtual Sites
+
+ List Virtual Site test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListVirtualSitesResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[VirtualSite]:
+ """List Virtual Sites
+
+ List Virtual Site test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[VirtualSite]
+ """
+
+ response = sync(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.virtual_sites
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[VirtualSite]:
+ """List Virtual Sites
+
+ List Virtual Site test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[VirtualSite]
+ """
+
+ response = await asyncio(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.virtual_sites:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/api/virtual/list_virtual_solar_inverters.py b/derapi/api/virtual/list_virtual_solar_inverters.py
new file mode 100644
index 0000000..8909322
--- /dev/null
+++ b/derapi/api/virtual/list_virtual_solar_inverters.py
@@ -0,0 +1,265 @@
+from http import HTTPStatus
+from typing import Any, AsyncIterator, Dict, Iterator, Optional, Union
+
+import httpx
+
+from ... import errors
+from ...client import AuthenticatedClient, Client
+from ...models.list_virtual_solar_inverters_response import ListVirtualSolarInvertersResponse
+from ...models.virtual_solar_inverter import VirtualSolarInverter
+from ...types import UNSET, Response, Unset
+
+
+def _get_kwargs(
+ *,
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Dict[str, Any]:
+ params: Dict[str, Any] = {}
+
+ params["pageSize"] = page_size
+
+ params["pageToken"] = page_token
+
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
+
+ _kwargs: Dict[str, Any] = {
+ "method": "get",
+ "url": "/virtual/solar-inverters",
+ "params": params,
+ }
+
+ return _kwargs
+
+
+def _parse_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Optional[ListVirtualSolarInvertersResponse]:
+ if response.status_code == 200:
+ response_200 = ListVirtualSolarInvertersResponse.from_dict(response.json())
+
+ return response_200
+ if client.raise_on_unexpected_status:
+ raise errors.UnexpectedStatus(response.status_code, response.content)
+ else:
+ return None
+
+
+def _build_response(
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
+) -> Response[ListVirtualSolarInvertersResponse]:
+ return Response(
+ status_code=HTTPStatus(response.status_code),
+ content=response.content,
+ headers=response.headers,
+ parsed=_parse_response(client=client, response=response),
+ )
+
+
+def sync_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListVirtualSolarInvertersResponse]:
+ """List virtual solar inverters
+
+ List virtual solar inverter test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListVirtualSolarInvertersResponse]
+ """
+
+ kwargs = _get_kwargs(
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = client.get_httpx_client().request(
+ **kwargs,
+ )
+
+ return _build_response(client=client, response=response)
+
+
+def sync(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListVirtualSolarInvertersResponse]:
+ """List virtual solar inverters
+
+ List virtual solar inverter test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListVirtualSolarInvertersResponse
+ """
+
+ return sync_detailed(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ ).parsed
+
+
+async def asyncio_detailed(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Response[ListVirtualSolarInvertersResponse]:
+ """List virtual solar inverters
+
+ List virtual solar inverter test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Response[ListVirtualSolarInvertersResponse]
+ """
+
+ kwargs = _get_kwargs(
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+ response = await client.get_async_httpx_client().request(**kwargs)
+
+ return _build_response(client=client, response=response)
+
+
+async def asyncio(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Optional[ListVirtualSolarInvertersResponse]:
+ """List virtual solar inverters
+
+ List virtual solar inverter test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ ListVirtualSolarInvertersResponse
+ """
+
+ return (
+ await asyncio_detailed(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ ).parsed
+
+
+def sync_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> Iterator[VirtualSolarInverter]:
+ """List virtual solar inverters
+
+ List virtual solar inverter test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[VirtualSolarInverter]
+ """
+
+ response = sync(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ yield from response.virtual_solar_inverters
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = sync(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+
+
+async def async_depaginated(
+ *,
+ client: Union[AuthenticatedClient, Client],
+ page_size: Union[Unset, int] = 50,
+ page_token: Union[Unset, str] = UNSET,
+) -> AsyncIterator[VirtualSolarInverter]:
+ """List virtual solar inverters
+
+ List virtual solar inverter test configurations in the current sandbox.
+
+ Args:
+ page_size (Union[Unset, int]): Default: 50.
+ page_token (Union[Unset, str]):
+
+ Raises:
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
+
+ Returns:
+ Iterator[VirtualSolarInverter]
+ """
+
+ response = await asyncio(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
+ while response is not None:
+ for item in response.virtual_solar_inverters:
+ yield item
+
+ page_token = response.next_page_token
+ if page_token == UNSET:
+ response = None
+ else:
+ response = await asyncio(
+ client=client,
+ page_size=page_size,
+ page_token=page_token,
+ )
diff --git a/derapi/client.py b/derapi/client.py
new file mode 100644
index 0000000..0f6d15e
--- /dev/null
+++ b/derapi/client.py
@@ -0,0 +1,268 @@
+import ssl
+from typing import Any, Dict, Optional, Union
+
+import httpx
+from attrs import define, evolve, field
+
+
+@define
+class Client:
+ """A class for keeping track of data related to the API
+
+ The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
+
+ ``base_url``: The base URL for the API, all requests are made to a relative path to this URL
+
+ ``cookies``: A dictionary of cookies to be sent with every request
+
+ ``headers``: A dictionary of headers to be sent with every request
+
+ ``timeout``: The maximum amount of a time a request can take. API functions will raise
+ httpx.TimeoutException if this is exceeded.
+
+ ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
+ but can be set to False for testing purposes.
+
+ ``follow_redirects``: Whether or not to follow redirects. Default value is False.
+
+ ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
+
+
+ Attributes:
+ raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
+ status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
+ argument to the constructor.
+ """
+
+ raise_on_unexpected_status: bool = field(default=False, kw_only=True)
+ _base_url: str = field(alias="base_url")
+ _cookies: Dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
+ _headers: Dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
+ _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True, alias="timeout")
+ _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True, alias="verify_ssl")
+ _follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
+ _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
+ _client: Optional[httpx.Client] = field(default=None, init=False)
+ _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False)
+
+ def with_headers(self, headers: Dict[str, str]) -> "Client":
+ """Get a new client matching this one with additional headers"""
+ if self._client is not None:
+ self._client.headers.update(headers)
+ if self._async_client is not None:
+ self._async_client.headers.update(headers)
+ return evolve(self, headers={**self._headers, **headers})
+
+ def with_cookies(self, cookies: Dict[str, str]) -> "Client":
+ """Get a new client matching this one with additional cookies"""
+ if self._client is not None:
+ self._client.cookies.update(cookies)
+ if self._async_client is not None:
+ self._async_client.cookies.update(cookies)
+ return evolve(self, cookies={**self._cookies, **cookies})
+
+ def with_timeout(self, timeout: httpx.Timeout) -> "Client":
+ """Get a new client matching this one with a new timeout (in seconds)"""
+ if self._client is not None:
+ self._client.timeout = timeout
+ if self._async_client is not None:
+ self._async_client.timeout = timeout
+ return evolve(self, timeout=timeout)
+
+ def set_httpx_client(self, client: httpx.Client) -> "Client":
+ """Manually set the underlying httpx.Client
+
+ **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
+ """
+ self._client = client
+ return self
+
+ def get_httpx_client(self) -> httpx.Client:
+ """Get the underlying httpx.Client, constructing a new one if not previously set"""
+ if self._client is None:
+ self._client = httpx.Client(
+ base_url=self._base_url,
+ cookies=self._cookies,
+ headers=self._headers,
+ timeout=self._timeout,
+ verify=self._verify_ssl,
+ follow_redirects=self._follow_redirects,
+ **self._httpx_args,
+ )
+ return self._client
+
+ def __enter__(self) -> "Client":
+ """Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
+ self.get_httpx_client().__enter__()
+ return self
+
+ def __exit__(self, *args: Any, **kwargs: Any) -> None:
+ """Exit a context manager for internal httpx.Client (see httpx docs)"""
+ self.get_httpx_client().__exit__(*args, **kwargs)
+
+ def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client":
+ """Manually the underlying httpx.AsyncClient
+
+ **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
+ """
+ self._async_client = async_client
+ return self
+
+ def get_async_httpx_client(self) -> httpx.AsyncClient:
+ """Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
+ if self._async_client is None:
+ self._async_client = httpx.AsyncClient(
+ base_url=self._base_url,
+ cookies=self._cookies,
+ headers=self._headers,
+ timeout=self._timeout,
+ verify=self._verify_ssl,
+ follow_redirects=self._follow_redirects,
+ **self._httpx_args,
+ )
+ return self._async_client
+
+ async def __aenter__(self) -> "Client":
+ """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
+ await self.get_async_httpx_client().__aenter__()
+ return self
+
+ async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
+ """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
+ await self.get_async_httpx_client().__aexit__(*args, **kwargs)
+
+
+@define
+class AuthenticatedClient:
+ """A Client which has been authenticated for use on secured endpoints
+
+ The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
+
+ ``base_url``: The base URL for the API, all requests are made to a relative path to this URL
+
+ ``cookies``: A dictionary of cookies to be sent with every request
+
+ ``headers``: A dictionary of headers to be sent with every request
+
+ ``timeout``: The maximum amount of a time a request can take. API functions will raise
+ httpx.TimeoutException if this is exceeded.
+
+ ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
+ but can be set to False for testing purposes.
+
+ ``follow_redirects``: Whether or not to follow redirects. Default value is False.
+
+ ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
+
+
+ Attributes:
+ raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
+ status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
+ argument to the constructor.
+ token: The token to use for authentication
+ prefix: The prefix to use for the Authorization header
+ auth_header_name: The name of the Authorization header
+ """
+
+ raise_on_unexpected_status: bool = field(default=False, kw_only=True)
+ _base_url: str = field(alias="base_url")
+ _cookies: Dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
+ _headers: Dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
+ _timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True, alias="timeout")
+ _verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True, alias="verify_ssl")
+ _follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
+ _httpx_args: Dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
+ _client: Optional[httpx.Client] = field(default=None, init=False)
+ _async_client: Optional[httpx.AsyncClient] = field(default=None, init=False)
+
+ token: str
+ prefix: str = "Bearer"
+ auth_header_name: str = "Authorization"
+
+ def with_headers(self, headers: Dict[str, str]) -> "AuthenticatedClient":
+ """Get a new client matching this one with additional headers"""
+ if self._client is not None:
+ self._client.headers.update(headers)
+ if self._async_client is not None:
+ self._async_client.headers.update(headers)
+ return evolve(self, headers={**self._headers, **headers})
+
+ def with_cookies(self, cookies: Dict[str, str]) -> "AuthenticatedClient":
+ """Get a new client matching this one with additional cookies"""
+ if self._client is not None:
+ self._client.cookies.update(cookies)
+ if self._async_client is not None:
+ self._async_client.cookies.update(cookies)
+ return evolve(self, cookies={**self._cookies, **cookies})
+
+ def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient":
+ """Get a new client matching this one with a new timeout (in seconds)"""
+ if self._client is not None:
+ self._client.timeout = timeout
+ if self._async_client is not None:
+ self._async_client.timeout = timeout
+ return evolve(self, timeout=timeout)
+
+ def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient":
+ """Manually set the underlying httpx.Client
+
+ **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
+ """
+ self._client = client
+ return self
+
+ def get_httpx_client(self) -> httpx.Client:
+ """Get the underlying httpx.Client, constructing a new one if not previously set"""
+ if self._client is None:
+ self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token
+ self._client = httpx.Client(
+ base_url=self._base_url,
+ cookies=self._cookies,
+ headers=self._headers,
+ timeout=self._timeout,
+ verify=self._verify_ssl,
+ follow_redirects=self._follow_redirects,
+ **self._httpx_args,
+ )
+ return self._client
+
+ def __enter__(self) -> "AuthenticatedClient":
+ """Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
+ self.get_httpx_client().__enter__()
+ return self
+
+ def __exit__(self, *args: Any, **kwargs: Any) -> None:
+ """Exit a context manager for internal httpx.Client (see httpx docs)"""
+ self.get_httpx_client().__exit__(*args, **kwargs)
+
+ def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient":
+ """Manually the underlying httpx.AsyncClient
+
+ **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
+ """
+ self._async_client = async_client
+ return self
+
+ def get_async_httpx_client(self) -> httpx.AsyncClient:
+ """Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
+ if self._async_client is None:
+ self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token
+ self._async_client = httpx.AsyncClient(
+ base_url=self._base_url,
+ cookies=self._cookies,
+ headers=self._headers,
+ timeout=self._timeout,
+ verify=self._verify_ssl,
+ follow_redirects=self._follow_redirects,
+ **self._httpx_args,
+ )
+ return self._async_client
+
+ async def __aenter__(self) -> "AuthenticatedClient":
+ """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
+ await self.get_async_httpx_client().__aenter__()
+ return self
+
+ async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
+ """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
+ await self.get_async_httpx_client().__aexit__(*args, **kwargs)
diff --git a/derapi/errors.py b/derapi/errors.py
new file mode 100644
index 0000000..5f92e76
--- /dev/null
+++ b/derapi/errors.py
@@ -0,0 +1,16 @@
+"""Contains shared errors types that can be raised from API functions"""
+
+
+class UnexpectedStatus(Exception):
+ """Raised by api functions when the response status an undocumented status and Client.raise_on_unexpected_status is True"""
+
+ def __init__(self, status_code: int, content: bytes):
+ self.status_code = status_code
+ self.content = content
+
+ super().__init__(
+ f"Unexpected status code: {status_code}\n\nResponse content:\n{content.decode(errors='ignore')}"
+ )
+
+
+__all__ = ["UnexpectedStatus"]
diff --git a/derapi/models/__init__.py b/derapi/models/__init__.py
new file mode 100644
index 0000000..25b5efb
--- /dev/null
+++ b/derapi/models/__init__.py
@@ -0,0 +1,221 @@
+"""Contains all the data models used in inputs/outputs"""
+
+from .battery import Battery
+from .battery_interval import BatteryInterval
+from .battery_mode import BatteryMode
+from .battery_recent_errors_error import BatteryRecentErrorsError
+from .battery_recent_errors_info import BatteryRecentErrorsInfo
+from .battery_recent_errors_start import BatteryRecentErrorsStart
+from .battery_recent_errors_warning import BatteryRecentErrorsWarning
+from .battery_summary import BatterySummary
+from .create_join_session_request import CreateJoinSessionRequest
+from .create_join_session_response import CreateJoinSessionResponse
+from .create_vendor_credentials_request import CreateVendorCredentialsRequest
+from .create_vendor_credentials_response import CreateVendorCredentialsResponse
+from .create_virtual_battery_request import CreateVirtualBatteryRequest
+from .create_virtual_battery_response import CreateVirtualBatteryResponse
+from .create_virtual_site_request import CreateVirtualSiteRequest
+from .create_virtual_site_response import CreateVirtualSiteResponse
+from .create_virtual_solar_inverter_request import CreateVirtualSolarInverterRequest
+from .create_virtual_solar_inverter_response import CreateVirtualSolarInverterResponse
+from .enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+from .enphase_join_config import EnphaseJoinConfig
+from .enphase_join_config_inline_credentials import EnphaseJoinConfigInlineCredentials
+from .enphase_partner_app_credentials import EnphasePartnerAppCredentials
+from .enphase_vpp_credentials import EnphaseVPPCredentials
+from .enphase_vpp_join_config import EnphaseVPPJoinConfig
+from .enphase_vpp_join_config_inline_credentials import EnphaseVPPJoinConfigInlineCredentials
+from .franklin_wh_credentials import FranklinWHCredentials
+from .get_battery_intervals_response import GetBatteryIntervalsResponse
+from .get_battery_response import GetBatteryResponse
+from .get_join_session_token_response import GetJoinSessionTokenResponse
+from .get_site_battery_control_response import GetSiteBatteryControlResponse
+from .get_site_battery_intervals_response import GetSiteBatteryIntervalsResponse
+from .get_site_response import GetSiteResponse
+from .get_site_solar_inverter_intervals_response import GetSiteSolarInverterIntervalsResponse
+from .get_solar_inverter_intervals_response import GetSolarInverterIntervalsResponse
+from .get_solar_inverter_response import GetSolarInverterResponse
+from .get_vendor_credentials_response import GetVendorCredentialsResponse
+from .get_virtual_battery_response import GetVirtualBatteryResponse
+from .get_virtual_site_response import GetVirtualSiteResponse
+from .get_virtual_solar_inverter_response import GetVirtualSolarInverterResponse
+from .hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+from .hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+from .hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+from .hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+from .hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+from .hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+from .hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+from .hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+from .hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+from .hidden_solis_credentials import HiddenSolisCredentials
+from .hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+from .list_batteries_response import ListBatteriesResponse
+from .list_batteries_response_errors import ListBatteriesResponseErrors
+from .list_site_response_errors import ListSiteResponseErrors
+from .list_sites_response import ListSitesResponse
+from .list_solar_inverters_response import ListSolarInvertersResponse
+from .list_solar_inverters_response_errors import ListSolarInvertersResponseErrors
+from .list_vendor_credentials_response import ListVendorCredentialsResponse
+from .list_virtual_batteries_response import ListVirtualBatteriesResponse
+from .list_virtual_sites_response import ListVirtualSitesResponse
+from .list_virtual_solar_inverters_response import ListVirtualSolarInvertersResponse
+from .put_site_battery_control_request import PutSiteBatteryControlRequest
+from .put_site_battery_control_request_interval import PutSiteBatteryControlRequestInterval
+from .put_site_battery_control_response import PutSiteBatteryControlResponse
+from .site import Site
+from .site_battery_control_command import SiteBatteryControlCommand
+from .site_battery_control_priority import SiteBatteryControlPriority
+from .site_battery_control_status import SiteBatteryControlStatus
+from .site_battery_control_status_interval import SiteBatteryControlStatusInterval
+from .site_battery_control_status_interval_site_battery_control_status_interval_command import (
+ SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand,
+)
+from .site_battery_interval import SiteBatteryInterval
+from .site_bess import SiteBESS
+from .site_location import SiteLocation
+from .site_solar_inverter_interval import SiteSolarInverterInterval
+from .site_summary import SiteSummary
+from .sma_custom_grant_credentials import SMACustomGrantCredentials
+from .sma_join_config import SMAJoinConfig
+from .sma_join_config_inline_credentials import SMAJoinConfigInlineCredentials
+from .sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+from .sma_sandbox_join_config import SMASandboxJoinConfig
+from .sma_sandbox_join_config_inline_credentials import SMASandboxJoinConfigInlineCredentials
+from .sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+from .smao_auth_credentials import SMAOAuthCredentials
+from .solar_edge_credentials import SolarEdgeCredentials
+from .solar_inverter import SolarInverter
+from .solar_inverter_interval import SolarInverterInterval
+from .solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+from .solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+from .solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+from .solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+from .solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+from .solar_inverter_recent_production import SolarInverterRecentProduction
+from .solar_inverter_summary import SolarInverterSummary
+from .solaredge_join_config import SolaredgeJoinConfig
+from .solis_credentials import SolisCredentials
+from .solis_join_config import SolisJoinConfig
+from .stored_credentials_reference import StoredCredentialsReference
+from .summary_level import SummaryLevel
+from .telsa_join_config_inline_credentials import TelsaJoinConfigInlineCredentials
+from .tesla_app_credentials import TeslaAppCredentials
+from .tesla_join_config import TeslaJoinConfig
+from .update_vendor_credentials_request import UpdateVendorCredentialsRequest
+from .update_vendor_credentials_response import UpdateVendorCredentialsResponse
+from .vendor import Vendor
+from .vendor_credentials import VendorCredentials
+from .virtual_battery import VirtualBattery
+from .virtual_site import VirtualSite
+from .virtual_solar_inverter import VirtualSolarInverter
+
+__all__ = (
+ "Battery",
+ "BatteryInterval",
+ "BatteryMode",
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ "BatterySummary",
+ "CreateJoinSessionRequest",
+ "CreateJoinSessionResponse",
+ "CreateVendorCredentialsRequest",
+ "CreateVendorCredentialsResponse",
+ "CreateVirtualBatteryRequest",
+ "CreateVirtualBatteryResponse",
+ "CreateVirtualSiteRequest",
+ "CreateVirtualSiteResponse",
+ "CreateVirtualSolarInverterRequest",
+ "CreateVirtualSolarInverterResponse",
+ "EnphaseDeveloperAppCredentials",
+ "EnphaseJoinConfig",
+ "EnphaseJoinConfigInlineCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "EnphaseVPPJoinConfig",
+ "EnphaseVPPJoinConfigInlineCredentials",
+ "FranklinWHCredentials",
+ "GetBatteryIntervalsResponse",
+ "GetBatteryResponse",
+ "GetJoinSessionTokenResponse",
+ "GetSiteBatteryControlResponse",
+ "GetSiteBatteryIntervalsResponse",
+ "GetSiteResponse",
+ "GetSiteSolarInverterIntervalsResponse",
+ "GetSolarInverterIntervalsResponse",
+ "GetSolarInverterResponse",
+ "GetVendorCredentialsResponse",
+ "GetVirtualBatteryResponse",
+ "GetVirtualSiteResponse",
+ "GetVirtualSolarInverterResponse",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "ListBatteriesResponse",
+ "ListBatteriesResponseErrors",
+ "ListSiteResponseErrors",
+ "ListSitesResponse",
+ "ListSolarInvertersResponse",
+ "ListSolarInvertersResponseErrors",
+ "ListVendorCredentialsResponse",
+ "ListVirtualBatteriesResponse",
+ "ListVirtualSitesResponse",
+ "ListVirtualSolarInvertersResponse",
+ "PutSiteBatteryControlRequest",
+ "PutSiteBatteryControlRequestInterval",
+ "PutSiteBatteryControlResponse",
+ "Site",
+ "SiteBatteryControlCommand",
+ "SiteBatteryControlPriority",
+ "SiteBatteryControlStatus",
+ "SiteBatteryControlStatusInterval",
+ "SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand",
+ "SiteBatteryInterval",
+ "SiteBESS",
+ "SiteLocation",
+ "SiteSolarInverterInterval",
+ "SiteSummary",
+ "SMACustomGrantCredentials",
+ "SMAJoinConfig",
+ "SMAJoinConfigInlineCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxJoinConfig",
+ "SMASandboxJoinConfigInlineCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolaredgeJoinConfig",
+ "SolarInverter",
+ "SolarInverterInterval",
+ "SolarInverterLifetimeProduction",
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ "SolarInverterRecentProduction",
+ "SolarInverterSummary",
+ "SolisCredentials",
+ "SolisJoinConfig",
+ "StoredCredentialsReference",
+ "SummaryLevel",
+ "TelsaJoinConfigInlineCredentials",
+ "TeslaAppCredentials",
+ "TeslaJoinConfig",
+ "UpdateVendorCredentialsRequest",
+ "UpdateVendorCredentialsResponse",
+ "Vendor",
+ "VendorCredentials",
+ "VirtualBattery",
+ "VirtualSite",
+ "VirtualSolarInverter",
+)
diff --git a/derapi/models/battery.py b/derapi/models/battery.py
new file mode 100644
index 0000000..6c6120e
--- /dev/null
+++ b/derapi/models/battery.py
@@ -0,0 +1,236 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.battery_mode import BatteryMode
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+
+T = TypeVar("T", bound="Battery")
+
+
+@_attrs_define
+class Battery:
+ """
+ Attributes:
+ id (str): Battery id
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format (timezone is always +00:00
+ and is always present)
+ model (str): Model number of Battery
+ serial_number (str): Manufacturer serial number of the Battery
+ site_id (str): The Derapi Site ID this Battery is associated with
+ name (Union[Unset, str]): Customer defined name of the Battery
+ nameplate_kwh (Union[Unset, float]): The rated storage capacity of the unit
+ mode (Union[Unset, BatteryMode]): Battery management system mode. Values are Self Consumption - minimize grid
+ import, Savings - optimizing Battery to save money; usually based on a rate plan, Backup - only use Battery for
+ grid backup
+ state_of_charge_percent (Union[Unset, float]): Battery state of charge as a percent of capacity
+ recent_errors (Union[Unset, List[Union['BatteryRecentErrorsError', 'BatteryRecentErrorsInfo',
+ 'BatteryRecentErrorsStart', 'BatteryRecentErrorsWarning']]]): Most recent errors, warnings, or info reported by
+ the manufacturer for this Battery. The key represents the severity level (info/warning/error); the value is a
+ string description. start is always present and is the last element to be returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ nameplate_kwh: Union[Unset, float] = UNSET
+ mode: Union[Unset, BatteryMode] = UNSET
+ state_of_charge_percent: Union[Unset, float] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ nameplate_kwh = self.nameplate_kwh
+
+ mode: Union[Unset, str] = UNSET
+ if not isinstance(self.mode, Unset):
+ mode = self.mode.value
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_battery_recent_errors_item_data in self.recent_errors:
+ componentsschemas_battery_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsError):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsWarning):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsInfo):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if nameplate_kwh is not UNSET:
+ field_dict["nameplateKwh"] = nameplate_kwh
+ if mode is not UNSET:
+ field_dict["mode"] = mode
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ nameplate_kwh = d.pop("nameplateKwh", UNSET)
+
+ _mode = d.pop("mode", UNSET)
+ mode: Union[Unset, BatteryMode]
+ if isinstance(_mode, Unset):
+ mode = UNSET
+ else:
+ mode = BatteryMode(_mode)
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_battery_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_battery_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_0 = BatteryRecentErrorsError.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_1 = BatteryRecentErrorsWarning.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_2 = BatteryRecentErrorsInfo.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_3 = BatteryRecentErrorsStart.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_3
+
+ componentsschemas_battery_recent_errors_item = _parse_componentsschemas_battery_recent_errors_item(
+ componentsschemas_battery_recent_errors_item_data
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ battery = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ nameplate_kwh=nameplate_kwh,
+ mode=mode,
+ state_of_charge_percent=state_of_charge_percent,
+ recent_errors=recent_errors,
+ )
+
+ return battery
diff --git a/derapi/models/battery_interval.py b/derapi/models/battery_interval.py
new file mode 100644
index 0000000..b7718db
--- /dev/null
+++ b/derapi/models/battery_interval.py
@@ -0,0 +1,75 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..types import UNSET, Unset
+
+T = TypeVar("T", bound="BatteryInterval")
+
+
+@_attrs_define
+class BatteryInterval:
+ """
+ Attributes:
+ charge_kwh (float): kWh into the Battery during the interval
+ discharge_kwh (float): kWh out of the Battery during the interval
+ start (datetime.datetime): Interval start in ISO-8601 format
+ end (datetime.datetime): Interval end in ISO-8601 format
+ state_of_charge_percent (Union[Unset, float]): average % charge over the interval
+ """
+
+ charge_kwh: float
+ discharge_kwh: float
+ start: datetime.datetime
+ end: datetime.datetime
+ state_of_charge_percent: Union[Unset, float] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ charge_kwh = self.charge_kwh
+
+ discharge_kwh = self.discharge_kwh
+
+ start = self.start.isoformat()
+
+ end = self.end.isoformat()
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "chargeKwh": charge_kwh,
+ "dischargeKwh": discharge_kwh,
+ "start": start,
+ "end": end,
+ }
+ )
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ charge_kwh = d.pop("chargeKwh")
+
+ discharge_kwh = d.pop("dischargeKwh")
+
+ start = isoparse(d.pop("start"))
+
+ end = isoparse(d.pop("end"))
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ battery_interval = cls(
+ charge_kwh=charge_kwh,
+ discharge_kwh=discharge_kwh,
+ start=start,
+ end=end,
+ state_of_charge_percent=state_of_charge_percent,
+ )
+
+ return battery_interval
diff --git a/derapi/models/battery_mode.py b/derapi/models/battery_mode.py
new file mode 100644
index 0000000..08c5f89
--- /dev/null
+++ b/derapi/models/battery_mode.py
@@ -0,0 +1,10 @@
+from enum import Enum
+
+
+class BatteryMode(str, Enum):
+ BACKUP = "Backup"
+ SAVINGS = "Savings"
+ SELF_CONSUMPTION = "Self Consumption"
+
+ def __str__(self) -> str:
+ return str(self.value)
diff --git a/derapi/models/battery_recent_errors_error.py b/derapi/models/battery_recent_errors_error.py
new file mode 100644
index 0000000..28a40fd
--- /dev/null
+++ b/derapi/models/battery_recent_errors_error.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="BatteryRecentErrorsError")
+
+
+@_attrs_define
+class BatteryRecentErrorsError:
+ """
+ Attributes:
+ error (str):
+ """
+
+ error: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ error = self.error
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "error": error,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ error = d.pop("error")
+
+ battery_recent_errors_error = cls(
+ error=error,
+ )
+
+ return battery_recent_errors_error
diff --git a/derapi/models/battery_recent_errors_info.py b/derapi/models/battery_recent_errors_info.py
new file mode 100644
index 0000000..1b9ff4f
--- /dev/null
+++ b/derapi/models/battery_recent_errors_info.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="BatteryRecentErrorsInfo")
+
+
+@_attrs_define
+class BatteryRecentErrorsInfo:
+ """
+ Attributes:
+ info (str):
+ """
+
+ info: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ info = self.info
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "info": info,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ info = d.pop("info")
+
+ battery_recent_errors_info = cls(
+ info=info,
+ )
+
+ return battery_recent_errors_info
diff --git a/derapi/models/battery_recent_errors_start.py b/derapi/models/battery_recent_errors_start.py
new file mode 100644
index 0000000..f4a9d45
--- /dev/null
+++ b/derapi/models/battery_recent_errors_start.py
@@ -0,0 +1,40 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+T = TypeVar("T", bound="BatteryRecentErrorsStart")
+
+
+@_attrs_define
+class BatteryRecentErrorsStart:
+ """
+ Attributes:
+ start (datetime.datetime): The start date of the recent errors log in ISO-8601 format
+ """
+
+ start: datetime.datetime
+
+ def to_dict(self) -> Dict[str, Any]:
+ start = self.start.isoformat()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "start": start,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ start = isoparse(d.pop("start"))
+
+ battery_recent_errors_start = cls(
+ start=start,
+ )
+
+ return battery_recent_errors_start
diff --git a/derapi/models/battery_recent_errors_warning.py b/derapi/models/battery_recent_errors_warning.py
new file mode 100644
index 0000000..2c2e485
--- /dev/null
+++ b/derapi/models/battery_recent_errors_warning.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="BatteryRecentErrorsWarning")
+
+
+@_attrs_define
+class BatteryRecentErrorsWarning:
+ """
+ Attributes:
+ warning (str):
+ """
+
+ warning: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ warning = self.warning
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "warning": warning,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ warning = d.pop("warning")
+
+ battery_recent_errors_warning = cls(
+ warning=warning,
+ )
+
+ return battery_recent_errors_warning
diff --git a/derapi/models/battery_summary.py b/derapi/models/battery_summary.py
new file mode 100644
index 0000000..b092e8a
--- /dev/null
+++ b/derapi/models/battery_summary.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="BatterySummary")
+
+
+@_attrs_define
+class BatterySummary:
+ """
+ Attributes:
+ id (str): Battery id
+ """
+
+ id: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ battery_summary = cls(
+ id=id,
+ )
+
+ return battery_summary
diff --git a/derapi/models/create_join_session_request.py b/derapi/models/create_join_session_request.py
new file mode 100644
index 0000000..908dec4
--- /dev/null
+++ b/derapi/models/create_join_session_request.py
@@ -0,0 +1,173 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.enphase_join_config import EnphaseJoinConfig
+ from ..models.enphase_vpp_join_config import EnphaseVPPJoinConfig
+ from ..models.sma_join_config import SMAJoinConfig
+ from ..models.sma_sandbox_join_config import SMASandboxJoinConfig
+ from ..models.solaredge_join_config import SolaredgeJoinConfig
+ from ..models.solis_join_config import SolisJoinConfig
+ from ..models.tesla_join_config import TeslaJoinConfig
+
+
+T = TypeVar("T", bound="CreateJoinSessionRequest")
+
+
+@_attrs_define
+class CreateJoinSessionRequest:
+ """
+ Attributes:
+ store_credentials (bool): Whether Derapi should store the credentials received from Join. If enabled, requires
+ VCM.
+ vendors (List[Union['EnphaseJoinConfig', 'EnphaseVPPJoinConfig', 'SMAJoinConfig', 'SMASandboxJoinConfig',
+ 'SolaredgeJoinConfig', 'SolisJoinConfig', 'TeslaJoinConfig']]): Add an object for each vendor that should appear
+ in the UI
+ """
+
+ store_credentials: bool
+ vendors: List[
+ Union[
+ "EnphaseJoinConfig",
+ "EnphaseVPPJoinConfig",
+ "SMAJoinConfig",
+ "SMASandboxJoinConfig",
+ "SolaredgeJoinConfig",
+ "SolisJoinConfig",
+ "TeslaJoinConfig",
+ ]
+ ]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_join_config import EnphaseJoinConfig
+ from ..models.enphase_vpp_join_config import EnphaseVPPJoinConfig
+ from ..models.sma_join_config import SMAJoinConfig
+ from ..models.sma_sandbox_join_config import SMASandboxJoinConfig
+ from ..models.solaredge_join_config import SolaredgeJoinConfig
+ from ..models.solis_join_config import SolisJoinConfig
+
+ store_credentials = self.store_credentials
+
+ vendors = []
+ for vendors_item_data in self.vendors:
+ vendors_item: Dict[str, Any]
+ if isinstance(vendors_item_data, EnphaseJoinConfig):
+ vendors_item = vendors_item_data.to_dict()
+ elif isinstance(vendors_item_data, EnphaseVPPJoinConfig):
+ vendors_item = vendors_item_data.to_dict()
+ elif isinstance(vendors_item_data, SMAJoinConfig):
+ vendors_item = vendors_item_data.to_dict()
+ elif isinstance(vendors_item_data, SMASandboxJoinConfig):
+ vendors_item = vendors_item_data.to_dict()
+ elif isinstance(vendors_item_data, SolaredgeJoinConfig):
+ vendors_item = vendors_item_data.to_dict()
+ elif isinstance(vendors_item_data, SolisJoinConfig):
+ vendors_item = vendors_item_data.to_dict()
+ else:
+ vendors_item = vendors_item_data.to_dict()
+
+ vendors.append(vendors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "storeCredentials": store_credentials,
+ "vendors": vendors,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_join_config import EnphaseJoinConfig
+ from ..models.enphase_vpp_join_config import EnphaseVPPJoinConfig
+ from ..models.sma_join_config import SMAJoinConfig
+ from ..models.sma_sandbox_join_config import SMASandboxJoinConfig
+ from ..models.solaredge_join_config import SolaredgeJoinConfig
+ from ..models.solis_join_config import SolisJoinConfig
+ from ..models.tesla_join_config import TeslaJoinConfig
+
+ d = src_dict.copy()
+ store_credentials = d.pop("storeCredentials")
+
+ vendors = []
+ _vendors = d.pop("vendors")
+ for vendors_item_data in _vendors:
+
+ def _parse_vendors_item(
+ data: object,
+ ) -> Union[
+ "EnphaseJoinConfig",
+ "EnphaseVPPJoinConfig",
+ "SMAJoinConfig",
+ "SMASandboxJoinConfig",
+ "SolaredgeJoinConfig",
+ "SolisJoinConfig",
+ "TeslaJoinConfig",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ vendors_item_type_0 = EnphaseJoinConfig.from_dict(data)
+
+ return vendors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ vendors_item_type_1 = EnphaseVPPJoinConfig.from_dict(data)
+
+ return vendors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ vendors_item_type_2 = SMAJoinConfig.from_dict(data)
+
+ return vendors_item_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ vendors_item_type_3 = SMASandboxJoinConfig.from_dict(data)
+
+ return vendors_item_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ vendors_item_type_4 = SolaredgeJoinConfig.from_dict(data)
+
+ return vendors_item_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ vendors_item_type_5 = SolisJoinConfig.from_dict(data)
+
+ return vendors_item_type_5
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ vendors_item_type_6 = TeslaJoinConfig.from_dict(data)
+
+ return vendors_item_type_6
+
+ vendors_item = _parse_vendors_item(vendors_item_data)
+
+ vendors.append(vendors_item)
+
+ create_join_session_request = cls(
+ store_credentials=store_credentials,
+ vendors=vendors,
+ )
+
+ return create_join_session_request
diff --git a/derapi/models/create_join_session_response.py b/derapi/models/create_join_session_response.py
new file mode 100644
index 0000000..889ac03
--- /dev/null
+++ b/derapi/models/create_join_session_response.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="CreateJoinSessionResponse")
+
+
+@_attrs_define
+class CreateJoinSessionResponse:
+ """
+ Attributes:
+ session_id (str): session token to pass to Join JS component function createJoin()
+ """
+
+ session_id: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ session_id = self.session_id
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "sessionID": session_id,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ session_id = d.pop("sessionID")
+
+ create_join_session_response = cls(
+ session_id=session_id,
+ )
+
+ return create_join_session_response
diff --git a/derapi/models/create_vendor_credentials_request.py b/derapi/models/create_vendor_credentials_request.py
new file mode 100644
index 0000000..aa435a7
--- /dev/null
+++ b/derapi/models/create_vendor_credentials_request.py
@@ -0,0 +1,227 @@
+from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+
+T = TypeVar("T", bound="CreateVendorCredentialsRequest")
+
+
+@_attrs_define
+class CreateVendorCredentialsRequest:
+ """
+ Attributes:
+ credentials (Union['EnphaseDeveloperAppCredentials', 'EnphasePartnerAppCredentials', 'EnphaseVPPCredentials',
+ 'FranklinWHCredentials', 'SMACustomGrantCredentials', 'SMAOAuthCredentials', 'SMASandboxCustomGrantCredentials',
+ 'SMASandboxOAuthCredentials', 'SolarEdgeCredentials', 'SolisCredentials', 'TeslaAppCredentials']): Credentials
+ for a given vendor.
+ name (Union[Unset, str]): The name of the vendor credentials; inferred if not provided.
+ """
+
+ credentials: Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]
+ name: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, EnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, FranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolisCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ name = self.name
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "credentials": credentials,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+ d = src_dict.copy()
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_0 = EnphasePartnerAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_1 = EnphaseDeveloperAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_2 = EnphaseVPPCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_3 = FranklinWHCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_4 = SMACustomGrantCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_5 = SMAOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_6 = SMASandboxCustomGrantCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_7 = SMASandboxOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_8 = SolarEdgeCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_9 = SolisCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_10 = TeslaAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_10
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ name = d.pop("name", UNSET)
+
+ create_vendor_credentials_request = cls(
+ credentials=credentials,
+ name=name,
+ )
+
+ return create_vendor_credentials_request
diff --git a/derapi/models/create_vendor_credentials_response.py b/derapi/models/create_vendor_credentials_response.py
new file mode 100644
index 0000000..752dd15
--- /dev/null
+++ b/derapi/models/create_vendor_credentials_response.py
@@ -0,0 +1,420 @@
+from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+
+T = TypeVar("T", bound="CreateVendorCredentialsResponse")
+
+
+@_attrs_define
+class CreateVendorCredentialsResponse:
+ """Vendor credentials which may or may not be hidden.
+
+ Attributes:
+ id (str): ID for the vendor credentials
+ name (str): The name of the vendor credentials; inferred if not provided.
+ credentials (Union['EnphaseDeveloperAppCredentials', 'EnphasePartnerAppCredentials', 'EnphaseVPPCredentials',
+ 'FranklinWHCredentials', 'HiddenEnphaseDeveloperAppCredentials', 'HiddenEnphasePartnerAppCredentials',
+ 'HiddenEnphaseVPPCredentials', 'HiddenFranklinWHCredentials', 'HiddenSMACustomGrantCredentials',
+ 'HiddenSMAOAuthCredentials', 'HiddenSMASandboxCustomGrantCredentials', 'HiddenSMASandboxOAuthCredentials',
+ 'HiddenSolarEdgeCredentials', 'HiddenSolisCredentials', 'HiddenTeslaAppCredentials',
+ 'SMACustomGrantCredentials', 'SMAOAuthCredentials', 'SMASandboxCustomGrantCredentials',
+ 'SMASandboxOAuthCredentials', 'SolarEdgeCredentials', 'SolisCredentials', 'TeslaAppCredentials']):
+ """
+
+ id: str
+ name: str
+ credentials: Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+
+ id = self.id
+
+ name = self.name
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, HiddenEnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenEnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenEnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenFranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSolisCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenTeslaAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, FranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolisCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "name": name,
+ "credentials": credentials,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ name = d.pop("name")
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_0 = (
+ HiddenEnphaseDeveloperAppCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_1 = (
+ HiddenEnphasePartnerAppCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_2 = HiddenEnphaseVPPCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_3 = HiddenFranklinWHCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_4 = (
+ HiddenSMACustomGrantCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_5 = HiddenSMAOAuthCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_6 = (
+ HiddenSMASandboxCustomGrantCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_7 = (
+ HiddenSMASandboxOAuthCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_8 = HiddenSolarEdgeCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_9 = HiddenSolisCredentials.from_dict(data)
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_10 = HiddenTeslaAppCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_10
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_0 = EnphasePartnerAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_1 = EnphaseDeveloperAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_2 = EnphaseVPPCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_3 = FranklinWHCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_4 = SMACustomGrantCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_5 = SMAOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_6 = SMASandboxCustomGrantCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_7 = SMASandboxOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_8 = SolarEdgeCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_9 = SolisCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_10 = TeslaAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_10
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ create_vendor_credentials_response = cls(
+ id=id,
+ name=name,
+ credentials=credentials,
+ )
+
+ return create_vendor_credentials_response
diff --git a/derapi/models/create_virtual_battery_request.py b/derapi/models/create_virtual_battery_request.py
new file mode 100644
index 0000000..841395b
--- /dev/null
+++ b/derapi/models/create_virtual_battery_request.py
@@ -0,0 +1,122 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.battery_mode import BatteryMode
+from ..types import UNSET, Unset
+
+T = TypeVar("T", bound="CreateVirtualBatteryRequest")
+
+
+@_attrs_define
+class CreateVirtualBatteryRequest:
+ """Fields the user would like to provide. Omitted ones will be inferred.
+
+ Attributes:
+ name (Union[Unset, str]): Customer defined name of the Battery
+ site_id (Union[Unset, str]): The Derapi Site ID this Battery is associated with
+ reported_at (Union[Unset, datetime.datetime]): Date the request was generated in ISO-8601 format (timezone is
+ always +00:00 and is always present)
+ model (Union[Unset, str]): Model number of Battery
+ serial_number (Union[Unset, str]): Manufacturer serial number of the Battery
+ nameplate_kwh (Union[Unset, float]): The rated storage capacity of the unit
+ mode (Union[Unset, BatteryMode]): Battery management system mode. Values are Self Consumption - minimize grid
+ import, Savings - optimizing Battery to save money; usually based on a rate plan, Backup - only use Battery for
+ grid backup
+ state_of_charge_percent (Union[Unset, float]): Battery state of charge as a percent of capacity
+ """
+
+ name: Union[Unset, str] = UNSET
+ site_id: Union[Unset, str] = UNSET
+ reported_at: Union[Unset, datetime.datetime] = UNSET
+ model: Union[Unset, str] = UNSET
+ serial_number: Union[Unset, str] = UNSET
+ nameplate_kwh: Union[Unset, float] = UNSET
+ mode: Union[Unset, BatteryMode] = UNSET
+ state_of_charge_percent: Union[Unset, float] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ name = self.name
+
+ site_id = self.site_id
+
+ reported_at: Union[Unset, str] = UNSET
+ if not isinstance(self.reported_at, Unset):
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ nameplate_kwh = self.nameplate_kwh
+
+ mode: Union[Unset, str] = UNSET
+ if not isinstance(self.mode, Unset):
+ mode = self.mode.value
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update({})
+ if name is not UNSET:
+ field_dict["name"] = name
+ if site_id is not UNSET:
+ field_dict["siteID"] = site_id
+ if reported_at is not UNSET:
+ field_dict["reportedAt"] = reported_at
+ if model is not UNSET:
+ field_dict["model"] = model
+ if serial_number is not UNSET:
+ field_dict["serialNumber"] = serial_number
+ if nameplate_kwh is not UNSET:
+ field_dict["nameplateKwh"] = nameplate_kwh
+ if mode is not UNSET:
+ field_dict["mode"] = mode
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ name = d.pop("name", UNSET)
+
+ site_id = d.pop("siteID", UNSET)
+
+ _reported_at = d.pop("reportedAt", UNSET)
+ reported_at: Union[Unset, datetime.datetime]
+ if isinstance(_reported_at, Unset):
+ reported_at = UNSET
+ else:
+ reported_at = isoparse(_reported_at)
+
+ model = d.pop("model", UNSET)
+
+ serial_number = d.pop("serialNumber", UNSET)
+
+ nameplate_kwh = d.pop("nameplateKwh", UNSET)
+
+ _mode = d.pop("mode", UNSET)
+ mode: Union[Unset, BatteryMode]
+ if isinstance(_mode, Unset):
+ mode = UNSET
+ else:
+ mode = BatteryMode(_mode)
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ create_virtual_battery_request = cls(
+ name=name,
+ site_id=site_id,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ nameplate_kwh=nameplate_kwh,
+ mode=mode,
+ state_of_charge_percent=state_of_charge_percent,
+ )
+
+ return create_virtual_battery_request
diff --git a/derapi/models/create_virtual_battery_response.py b/derapi/models/create_virtual_battery_response.py
new file mode 100644
index 0000000..acc95be
--- /dev/null
+++ b/derapi/models/create_virtual_battery_response.py
@@ -0,0 +1,236 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.battery_mode import BatteryMode
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+
+T = TypeVar("T", bound="CreateVirtualBatteryResponse")
+
+
+@_attrs_define
+class CreateVirtualBatteryResponse:
+ """
+ Attributes:
+ id (str): Battery id
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format (timezone is always +00:00
+ and is always present)
+ model (str): Model number of Battery
+ serial_number (str): Manufacturer serial number of the Battery
+ site_id (str): The Derapi Site ID this Battery is associated with
+ name (Union[Unset, str]): Customer defined name of the Battery
+ nameplate_kwh (Union[Unset, float]): The rated storage capacity of the unit
+ mode (Union[Unset, BatteryMode]): Battery management system mode. Values are Self Consumption - minimize grid
+ import, Savings - optimizing Battery to save money; usually based on a rate plan, Backup - only use Battery for
+ grid backup
+ state_of_charge_percent (Union[Unset, float]): Battery state of charge as a percent of capacity
+ recent_errors (Union[Unset, List[Union['BatteryRecentErrorsError', 'BatteryRecentErrorsInfo',
+ 'BatteryRecentErrorsStart', 'BatteryRecentErrorsWarning']]]): Most recent errors, warnings, or info reported by
+ the manufacturer for this Battery. The key represents the severity level (info/warning/error); the value is a
+ string description. start is always present and is the last element to be returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ nameplate_kwh: Union[Unset, float] = UNSET
+ mode: Union[Unset, BatteryMode] = UNSET
+ state_of_charge_percent: Union[Unset, float] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ nameplate_kwh = self.nameplate_kwh
+
+ mode: Union[Unset, str] = UNSET
+ if not isinstance(self.mode, Unset):
+ mode = self.mode.value
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_battery_recent_errors_item_data in self.recent_errors:
+ componentsschemas_battery_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsError):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsWarning):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsInfo):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if nameplate_kwh is not UNSET:
+ field_dict["nameplateKwh"] = nameplate_kwh
+ if mode is not UNSET:
+ field_dict["mode"] = mode
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ nameplate_kwh = d.pop("nameplateKwh", UNSET)
+
+ _mode = d.pop("mode", UNSET)
+ mode: Union[Unset, BatteryMode]
+ if isinstance(_mode, Unset):
+ mode = UNSET
+ else:
+ mode = BatteryMode(_mode)
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_battery_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_battery_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_0 = BatteryRecentErrorsError.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_1 = BatteryRecentErrorsWarning.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_2 = BatteryRecentErrorsInfo.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_3 = BatteryRecentErrorsStart.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_3
+
+ componentsschemas_battery_recent_errors_item = _parse_componentsschemas_battery_recent_errors_item(
+ componentsschemas_battery_recent_errors_item_data
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ create_virtual_battery_response = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ nameplate_kwh=nameplate_kwh,
+ mode=mode,
+ state_of_charge_percent=state_of_charge_percent,
+ recent_errors=recent_errors,
+ )
+
+ return create_virtual_battery_response
diff --git a/derapi/models/create_virtual_site_request.py b/derapi/models/create_virtual_site_request.py
new file mode 100644
index 0000000..9f74509
--- /dev/null
+++ b/derapi/models/create_virtual_site_request.py
@@ -0,0 +1,90 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.site_location import SiteLocation
+
+
+T = TypeVar("T", bound="CreateVirtualSiteRequest")
+
+
+@_attrs_define
+class CreateVirtualSiteRequest:
+ """Fields the user would like to provide. Omitted ones will be inferred.
+
+ Attributes:
+ name (Union[Unset, str]): Customer defined name of the Site
+ location (Union[Unset, SiteLocation]): The location of this Solar Inverter in lat/lon coordinates
+ location_utc_offset (Union[Unset, float]): UTC Offset in hours; positive values represent locations East of UTC.
+ Please note this field will soon be deprecated, please use `timezone` instead.
+ operational_since (Union[Unset, datetime.datetime]): The date the Site became operational or received permission
+ to operate. Sometimes absent for Solaredge.
+ """
+
+ name: Union[Unset, str] = UNSET
+ location: Union[Unset, "SiteLocation"] = UNSET
+ location_utc_offset: Union[Unset, float] = UNSET
+ operational_since: Union[Unset, datetime.datetime] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ name = self.name
+
+ location: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.location, Unset):
+ location = self.location.to_dict()
+
+ location_utc_offset = self.location_utc_offset
+
+ operational_since: Union[Unset, str] = UNSET
+ if not isinstance(self.operational_since, Unset):
+ operational_since = self.operational_since.isoformat()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update({})
+ if name is not UNSET:
+ field_dict["name"] = name
+ if location is not UNSET:
+ field_dict["location"] = location
+ if location_utc_offset is not UNSET:
+ field_dict["locationUTCOffset"] = location_utc_offset
+ if operational_since is not UNSET:
+ field_dict["operationalSince"] = operational_since
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.site_location import SiteLocation
+
+ d = src_dict.copy()
+ name = d.pop("name", UNSET)
+
+ _location = d.pop("location", UNSET)
+ location: Union[Unset, SiteLocation]
+ if isinstance(_location, Unset):
+ location = UNSET
+ else:
+ location = SiteLocation.from_dict(_location)
+
+ location_utc_offset = d.pop("locationUTCOffset", UNSET)
+
+ _operational_since = d.pop("operationalSince", UNSET)
+ operational_since: Union[Unset, datetime.datetime]
+ if isinstance(_operational_since, Unset):
+ operational_since = UNSET
+ else:
+ operational_since = isoparse(_operational_since)
+
+ create_virtual_site_request = cls(
+ name=name,
+ location=location,
+ location_utc_offset=location_utc_offset,
+ operational_since=operational_since,
+ )
+
+ return create_virtual_site_request
diff --git a/derapi/models/create_virtual_site_response.py b/derapi/models/create_virtual_site_response.py
new file mode 100644
index 0000000..992d819
--- /dev/null
+++ b/derapi/models/create_virtual_site_response.py
@@ -0,0 +1,163 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+
+T = TypeVar("T", bound="CreateVirtualSiteResponse")
+
+
+@_attrs_define
+class CreateVirtualSiteResponse:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ vendor (Vendor):
+ name (str): Customer defined name of the Site
+ location_utc_offset (float): UTC Offset in hours; positive values represent locations East of UTC. Please note
+ this field will soon be deprecated, please use `timezone` instead.
+ batteries (List['BatterySummary']): List of Battery IDs associated with this Site
+ solar_inverters (List['SolarInverterSummary']): List of Solar Inverter IDs associated with this Site
+ location (Union[Unset, SiteLocation]): The location of this Solar Inverter in lat/lon coordinates
+ operational_since (Union[Unset, datetime.datetime]): The date the Site became operational or received permission
+ to operate. Sometimes absent for Solaredge.
+ bess (Union[Unset, SiteBESS]): For Sites with Batteries this key is present
+ """
+
+ id: str
+ vendor: Vendor
+ name: str
+ location_utc_offset: float
+ batteries: List["BatterySummary"]
+ solar_inverters: List["SolarInverterSummary"]
+ location: Union[Unset, "SiteLocation"] = UNSET
+ operational_since: Union[Unset, datetime.datetime] = UNSET
+ bess: Union[Unset, "SiteBESS"] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ vendor = self.vendor.value
+
+ name = self.name
+
+ location_utc_offset = self.location_utc_offset
+
+ batteries = []
+ for componentsschemas_site_batteries_item_data in self.batteries:
+ componentsschemas_site_batteries_item = componentsschemas_site_batteries_item_data.to_dict()
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ for componentsschemas_site_solar_inverters_item_data in self.solar_inverters:
+ componentsschemas_site_solar_inverters_item = componentsschemas_site_solar_inverters_item_data.to_dict()
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ location: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.location, Unset):
+ location = self.location.to_dict()
+
+ operational_since: Union[Unset, str] = UNSET
+ if not isinstance(self.operational_since, Unset):
+ operational_since = self.operational_since.isoformat()
+
+ bess: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.bess, Unset):
+ bess = self.bess.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "name": name,
+ "locationUTCOffset": location_utc_offset,
+ "batteries": batteries,
+ "solarInverters": solar_inverters,
+ }
+ )
+ if location is not UNSET:
+ field_dict["location"] = location
+ if operational_since is not UNSET:
+ field_dict["operationalSince"] = operational_since
+ if bess is not UNSET:
+ field_dict["bess"] = bess
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ name = d.pop("name")
+
+ location_utc_offset = d.pop("locationUTCOffset")
+
+ batteries = []
+ _batteries = d.pop("batteries")
+ for componentsschemas_site_batteries_item_data in _batteries:
+ componentsschemas_site_batteries_item = BatterySummary.from_dict(componentsschemas_site_batteries_item_data)
+
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ _solar_inverters = d.pop("solarInverters")
+ for componentsschemas_site_solar_inverters_item_data in _solar_inverters:
+ componentsschemas_site_solar_inverters_item = SolarInverterSummary.from_dict(
+ componentsschemas_site_solar_inverters_item_data
+ )
+
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ _location = d.pop("location", UNSET)
+ location: Union[Unset, SiteLocation]
+ if isinstance(_location, Unset):
+ location = UNSET
+ else:
+ location = SiteLocation.from_dict(_location)
+
+ _operational_since = d.pop("operationalSince", UNSET)
+ operational_since: Union[Unset, datetime.datetime]
+ if isinstance(_operational_since, Unset):
+ operational_since = UNSET
+ else:
+ operational_since = isoparse(_operational_since)
+
+ _bess = d.pop("bess", UNSET)
+ bess: Union[Unset, SiteBESS]
+ if isinstance(_bess, Unset):
+ bess = UNSET
+ else:
+ bess = SiteBESS.from_dict(_bess)
+
+ create_virtual_site_response = cls(
+ id=id,
+ vendor=vendor,
+ name=name,
+ location_utc_offset=location_utc_offset,
+ batteries=batteries,
+ solar_inverters=solar_inverters,
+ location=location,
+ operational_since=operational_since,
+ bess=bess,
+ )
+
+ return create_virtual_site_response
diff --git a/derapi/models/create_virtual_solar_inverter_request.py b/derapi/models/create_virtual_solar_inverter_request.py
new file mode 100644
index 0000000..d9fe456
--- /dev/null
+++ b/derapi/models/create_virtual_solar_inverter_request.py
@@ -0,0 +1,123 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+
+T = TypeVar("T", bound="CreateVirtualSolarInverterRequest")
+
+
+@_attrs_define
+class CreateVirtualSolarInverterRequest:
+ """
+ Attributes:
+ site_id (Union[Unset, str]): The Derapi Site ID this Solar Inverter is associated with
+ reported_at (Union[Unset, datetime.datetime]): Date the request was generated in ISO-8601 format
+ model (Union[Unset, str]): Model number of this Solar Inverter
+ serial_number (Union[Unset, str]): Manufacturer serial number of this Solar Inverter
+ name (Union[Unset, str]): Customer defined name of this Solar Inverter
+ recent_production (Union[Unset, SolarInverterRecentProduction]):
+ lifetime_production (Union[Unset, SolarInverterLifetimeProduction]):
+ """
+
+ site_id: Union[Unset, str] = UNSET
+ reported_at: Union[Unset, datetime.datetime] = UNSET
+ model: Union[Unset, str] = UNSET
+ serial_number: Union[Unset, str] = UNSET
+ name: Union[Unset, str] = UNSET
+ recent_production: Union[Unset, "SolarInverterRecentProduction"] = UNSET
+ lifetime_production: Union[Unset, "SolarInverterLifetimeProduction"] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ site_id = self.site_id
+
+ reported_at: Union[Unset, str] = UNSET
+ if not isinstance(self.reported_at, Unset):
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ name = self.name
+
+ recent_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.recent_production, Unset):
+ recent_production = self.recent_production.to_dict()
+
+ lifetime_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.lifetime_production, Unset):
+ lifetime_production = self.lifetime_production.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update({})
+ if site_id is not UNSET:
+ field_dict["siteID"] = site_id
+ if reported_at is not UNSET:
+ field_dict["reportedAt"] = reported_at
+ if model is not UNSET:
+ field_dict["model"] = model
+ if serial_number is not UNSET:
+ field_dict["serialNumber"] = serial_number
+ if name is not UNSET:
+ field_dict["name"] = name
+ if recent_production is not UNSET:
+ field_dict["recentProduction"] = recent_production
+ if lifetime_production is not UNSET:
+ field_dict["lifetimeProduction"] = lifetime_production
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+ d = src_dict.copy()
+ site_id = d.pop("siteID", UNSET)
+
+ _reported_at = d.pop("reportedAt", UNSET)
+ reported_at: Union[Unset, datetime.datetime]
+ if isinstance(_reported_at, Unset):
+ reported_at = UNSET
+ else:
+ reported_at = isoparse(_reported_at)
+
+ model = d.pop("model", UNSET)
+
+ serial_number = d.pop("serialNumber", UNSET)
+
+ name = d.pop("name", UNSET)
+
+ _recent_production = d.pop("recentProduction", UNSET)
+ recent_production: Union[Unset, SolarInverterRecentProduction]
+ if isinstance(_recent_production, Unset):
+ recent_production = UNSET
+ else:
+ recent_production = SolarInverterRecentProduction.from_dict(_recent_production)
+
+ _lifetime_production = d.pop("lifetimeProduction", UNSET)
+ lifetime_production: Union[Unset, SolarInverterLifetimeProduction]
+ if isinstance(_lifetime_production, Unset):
+ lifetime_production = UNSET
+ else:
+ lifetime_production = SolarInverterLifetimeProduction.from_dict(_lifetime_production)
+
+ create_virtual_solar_inverter_request = cls(
+ site_id=site_id,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ name=name,
+ recent_production=recent_production,
+ lifetime_production=lifetime_production,
+ )
+
+ return create_virtual_solar_inverter_request
diff --git a/derapi/models/create_virtual_solar_inverter_response.py b/derapi/models/create_virtual_solar_inverter_response.py
new file mode 100644
index 0000000..ab9256b
--- /dev/null
+++ b/derapi/models/create_virtual_solar_inverter_response.py
@@ -0,0 +1,249 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+
+T = TypeVar("T", bound="CreateVirtualSolarInverterResponse")
+
+
+@_attrs_define
+class CreateVirtualSolarInverterResponse:
+ """
+ Attributes:
+ id (str): ID of the solar inverter
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format
+ model (str): Model number of this Solar Inverter
+ serial_number (str): Manufacturer serial number of this Solar Inverter
+ site_id (str): The Derapi Site ID this Solar Inverter is associated with
+ name (Union[Unset, str]): Customer defined name of this Solar Inverter
+ recent_production (Union[Unset, SolarInverterRecentProduction]):
+ lifetime_production (Union[Unset, SolarInverterLifetimeProduction]):
+ recent_errors (Union[Unset, List[Union['SolarInverterRecentErrorsError', 'SolarInverterRecentErrorsInfo',
+ 'SolarInverterRecentErrorsStart', 'SolarInverterRecentErrorsWarning']]]): Most recent errors, warnings, or info
+ reported by the manufacturer for this Solar Inverter. The key represents the severity level
+ (info/warning/error); the value is a string description. start is always present and is the last element to be
+ returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ recent_production: Union[Unset, "SolarInverterRecentProduction"] = UNSET
+ lifetime_production: Union[Unset, "SolarInverterLifetimeProduction"] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ recent_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.recent_production, Unset):
+ recent_production = self.recent_production.to_dict()
+
+ lifetime_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.lifetime_production, Unset):
+ lifetime_production = self.lifetime_production.to_dict()
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_solar_inverter_recent_errors_item_data in self.recent_errors:
+ componentsschemas_solar_inverter_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsError):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsWarning
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsInfo
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if recent_production is not UNSET:
+ field_dict["recentProduction"] = recent_production
+ if lifetime_production is not UNSET:
+ field_dict["lifetimeProduction"] = lifetime_production
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ _recent_production = d.pop("recentProduction", UNSET)
+ recent_production: Union[Unset, SolarInverterRecentProduction]
+ if isinstance(_recent_production, Unset):
+ recent_production = UNSET
+ else:
+ recent_production = SolarInverterRecentProduction.from_dict(_recent_production)
+
+ _lifetime_production = d.pop("lifetimeProduction", UNSET)
+ lifetime_production: Union[Unset, SolarInverterLifetimeProduction]
+ if isinstance(_lifetime_production, Unset):
+ lifetime_production = UNSET
+ else:
+ lifetime_production = SolarInverterLifetimeProduction.from_dict(_lifetime_production)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_solar_inverter_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_solar_inverter_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_0 = (
+ SolarInverterRecentErrorsError.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_1 = (
+ SolarInverterRecentErrorsWarning.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_2 = (
+ SolarInverterRecentErrorsInfo.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_3 = SolarInverterRecentErrorsStart.from_dict(
+ data
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_3
+
+ componentsschemas_solar_inverter_recent_errors_item = (
+ _parse_componentsschemas_solar_inverter_recent_errors_item(
+ componentsschemas_solar_inverter_recent_errors_item_data
+ )
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ create_virtual_solar_inverter_response = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ recent_production=recent_production,
+ lifetime_production=lifetime_production,
+ recent_errors=recent_errors,
+ )
+
+ return create_virtual_solar_inverter_response
diff --git a/derapi/models/enphase_developer_app_credentials.py b/derapi/models/enphase_developer_app_credentials.py
new file mode 100644
index 0000000..a7253ae
--- /dev/null
+++ b/derapi/models/enphase_developer_app_credentials.py
@@ -0,0 +1,75 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="EnphaseDeveloperAppCredentials")
+
+
+@_attrs_define
+class EnphaseDeveloperAppCredentials:
+ """Credentials for an Enphase developer app
+
+ Attributes:
+ vendor (Literal['enphase']): Default: 'enphase'.
+ type (Literal['developerapp']): Default: 'developerapp'.
+ client_id (str): Enphase Client ID
+ client_secret (str): Enphase Client Secret
+ api_key (str): Enphase API key of the application
+ """
+
+ client_id: str
+ client_secret: str
+ api_key: str
+ vendor: Literal["enphase"] = "enphase"
+ type: Literal["developerapp"] = "developerapp"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ api_key = self.api_key
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ "apiKey": api_key,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["enphase"], d.pop("vendor"))
+ if vendor != "enphase":
+ raise ValueError(f"vendor must match const 'enphase', got '{vendor}'")
+
+ type = cast(Literal["developerapp"], d.pop("type"))
+ if type != "developerapp":
+ raise ValueError(f"type must match const 'developerapp', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ api_key = d.pop("apiKey")
+
+ enphase_developer_app_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ api_key=api_key,
+ )
+
+ return enphase_developer_app_credentials
diff --git a/derapi/models/enphase_join_config.py b/derapi/models/enphase_join_config.py
new file mode 100644
index 0000000..a7f44bf
--- /dev/null
+++ b/derapi/models/enphase_join_config.py
@@ -0,0 +1,81 @@
+from typing import TYPE_CHECKING, Any, Dict, Literal, Type, TypeVar, Union, cast
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.enphase_join_config_inline_credentials import EnphaseJoinConfigInlineCredentials
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+
+
+T = TypeVar("T", bound="EnphaseJoinConfig")
+
+
+@_attrs_define
+class EnphaseJoinConfig:
+ """
+ Attributes:
+ vendor (Literal['enphase']):
+ credentials (Union['EnphaseJoinConfigInlineCredentials', 'StoredCredentialsReference']):
+ """
+
+ vendor: Literal["enphase"]
+ credentials: Union["EnphaseJoinConfigInlineCredentials", "StoredCredentialsReference"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_join_config_inline_credentials import EnphaseJoinConfigInlineCredentials
+
+ vendor = self.vendor
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, EnphaseJoinConfigInlineCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "credentials": credentials,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_join_config_inline_credentials import EnphaseJoinConfigInlineCredentials
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+
+ d = src_dict.copy()
+ vendor = cast(Literal["enphase"], d.pop("vendor"))
+ if vendor != "enphase":
+ raise ValueError(f"vendor must match const 'enphase', got '{vendor}'")
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union["EnphaseJoinConfigInlineCredentials", "StoredCredentialsReference"]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_enphase_join_config_credentials_type_0 = EnphaseJoinConfigInlineCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_enphase_join_config_credentials_type_0
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_enphase_join_config_credentials_type_1 = StoredCredentialsReference.from_dict(data)
+
+ return componentsschemas_enphase_join_config_credentials_type_1
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ enphase_join_config = cls(
+ vendor=vendor,
+ credentials=credentials,
+ )
+
+ return enphase_join_config
diff --git a/derapi/models/enphase_join_config_inline_credentials.py b/derapi/models/enphase_join_config_inline_credentials.py
new file mode 100644
index 0000000..005141b
--- /dev/null
+++ b/derapi/models/enphase_join_config_inline_credentials.py
@@ -0,0 +1,54 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="EnphaseJoinConfigInlineCredentials")
+
+
+@_attrs_define
+class EnphaseJoinConfigInlineCredentials:
+ """
+ Attributes:
+ client_id (str): Enphase Client ID
+ client_secret (str): Enphase Client Secret
+ api_key (str): Enphase API key of the application
+ """
+
+ client_id: str
+ client_secret: str
+ api_key: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ api_key = self.api_key
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ "apiKey": api_key,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ api_key = d.pop("apiKey")
+
+ enphase_join_config_inline_credentials = cls(
+ client_id=client_id,
+ client_secret=client_secret,
+ api_key=api_key,
+ )
+
+ return enphase_join_config_inline_credentials
diff --git a/derapi/models/enphase_partner_app_credentials.py b/derapi/models/enphase_partner_app_credentials.py
new file mode 100644
index 0000000..5f08f0a
--- /dev/null
+++ b/derapi/models/enphase_partner_app_credentials.py
@@ -0,0 +1,75 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="EnphasePartnerAppCredentials")
+
+
+@_attrs_define
+class EnphasePartnerAppCredentials:
+ """Credentials for an Enphase partner app
+
+ Attributes:
+ vendor (Literal['enphase']): Default: 'enphase'.
+ type (Literal['partnerapp']): Default: 'partnerapp'.
+ client_id (str): Enphase Client ID
+ client_secret (str): Enphase Client Secret
+ api_key (str): Enphase API key of the application
+ """
+
+ client_id: str
+ client_secret: str
+ api_key: str
+ vendor: Literal["enphase"] = "enphase"
+ type: Literal["partnerapp"] = "partnerapp"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ api_key = self.api_key
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ "apiKey": api_key,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["enphase"], d.pop("vendor"))
+ if vendor != "enphase":
+ raise ValueError(f"vendor must match const 'enphase', got '{vendor}'")
+
+ type = cast(Literal["partnerapp"], d.pop("type"))
+ if type != "partnerapp":
+ raise ValueError(f"type must match const 'partnerapp', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ api_key = d.pop("apiKey")
+
+ enphase_partner_app_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ api_key=api_key,
+ )
+
+ return enphase_partner_app_credentials
diff --git a/derapi/models/enphase_vpp_credentials.py b/derapi/models/enphase_vpp_credentials.py
new file mode 100644
index 0000000..44f04bf
--- /dev/null
+++ b/derapi/models/enphase_vpp_credentials.py
@@ -0,0 +1,74 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="EnphaseVPPCredentials")
+
+
+@_attrs_define
+class EnphaseVPPCredentials:
+ """
+ Attributes:
+ vendor (Literal['enphasevpp']): Default: 'enphasevpp'.
+ type (Literal['vpp']): Default: 'vpp'.
+ client_id (str): Enphase VPP Client ID
+ client_secret (str): Enphase VPP Client Secret
+ api_key (str): Enphase VPP API Key
+ """
+
+ client_id: str
+ client_secret: str
+ api_key: str
+ vendor: Literal["enphasevpp"] = "enphasevpp"
+ type: Literal["vpp"] = "vpp"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ api_key = self.api_key
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ "apiKey": api_key,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["enphasevpp"], d.pop("vendor"))
+ if vendor != "enphasevpp":
+ raise ValueError(f"vendor must match const 'enphasevpp', got '{vendor}'")
+
+ type = cast(Literal["vpp"], d.pop("type"))
+ if type != "vpp":
+ raise ValueError(f"type must match const 'vpp', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ api_key = d.pop("apiKey")
+
+ enphase_vpp_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ api_key=api_key,
+ )
+
+ return enphase_vpp_credentials
diff --git a/derapi/models/enphase_vpp_join_config.py b/derapi/models/enphase_vpp_join_config.py
new file mode 100644
index 0000000..f798830
--- /dev/null
+++ b/derapi/models/enphase_vpp_join_config.py
@@ -0,0 +1,121 @@
+from typing import TYPE_CHECKING, Any, Dict, Literal, Type, TypeVar, Union, cast
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.enphase_join_config_inline_credentials import EnphaseJoinConfigInlineCredentials
+ from ..models.enphase_vpp_join_config_inline_credentials import EnphaseVPPJoinConfigInlineCredentials
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+
+
+T = TypeVar("T", bound="EnphaseVPPJoinConfig")
+
+
+@_attrs_define
+class EnphaseVPPJoinConfig:
+ """
+ Attributes:
+ vendor (Literal['enphasevpp']):
+ credentials (Union['EnphaseVPPJoinConfigInlineCredentials', 'StoredCredentialsReference']):
+ partner_app_credentials (Union['EnphaseJoinConfigInlineCredentials', 'StoredCredentialsReference']):
+ program_id (str):
+ """
+
+ vendor: Literal["enphasevpp"]
+ credentials: Union["EnphaseVPPJoinConfigInlineCredentials", "StoredCredentialsReference"]
+ partner_app_credentials: Union["EnphaseJoinConfigInlineCredentials", "StoredCredentialsReference"]
+ program_id: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_join_config_inline_credentials import EnphaseJoinConfigInlineCredentials
+ from ..models.enphase_vpp_join_config_inline_credentials import EnphaseVPPJoinConfigInlineCredentials
+
+ vendor = self.vendor
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, EnphaseVPPJoinConfigInlineCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ partner_app_credentials: Dict[str, Any]
+ if isinstance(self.partner_app_credentials, EnphaseJoinConfigInlineCredentials):
+ partner_app_credentials = self.partner_app_credentials.to_dict()
+ else:
+ partner_app_credentials = self.partner_app_credentials.to_dict()
+
+ program_id = self.program_id
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "credentials": credentials,
+ "partnerAppCredentials": partner_app_credentials,
+ "programID": program_id,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_join_config_inline_credentials import EnphaseJoinConfigInlineCredentials
+ from ..models.enphase_vpp_join_config_inline_credentials import EnphaseVPPJoinConfigInlineCredentials
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+
+ d = src_dict.copy()
+ vendor = cast(Literal["enphasevpp"], d.pop("vendor"))
+ if vendor != "enphasevpp":
+ raise ValueError(f"vendor must match const 'enphasevpp', got '{vendor}'")
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union["EnphaseVPPJoinConfigInlineCredentials", "StoredCredentialsReference"]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ credentials_type_0 = EnphaseVPPJoinConfigInlineCredentials.from_dict(data)
+
+ return credentials_type_0
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ credentials_type_1 = StoredCredentialsReference.from_dict(data)
+
+ return credentials_type_1
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ def _parse_partner_app_credentials(
+ data: object,
+ ) -> Union["EnphaseJoinConfigInlineCredentials", "StoredCredentialsReference"]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_enphase_join_config_credentials_type_0 = EnphaseJoinConfigInlineCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_enphase_join_config_credentials_type_0
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_enphase_join_config_credentials_type_1 = StoredCredentialsReference.from_dict(data)
+
+ return componentsschemas_enphase_join_config_credentials_type_1
+
+ partner_app_credentials = _parse_partner_app_credentials(d.pop("partnerAppCredentials"))
+
+ program_id = d.pop("programID")
+
+ enphase_vpp_join_config = cls(
+ vendor=vendor,
+ credentials=credentials,
+ partner_app_credentials=partner_app_credentials,
+ program_id=program_id,
+ )
+
+ return enphase_vpp_join_config
diff --git a/derapi/models/enphase_vpp_join_config_inline_credentials.py b/derapi/models/enphase_vpp_join_config_inline_credentials.py
new file mode 100644
index 0000000..2de98ea
--- /dev/null
+++ b/derapi/models/enphase_vpp_join_config_inline_credentials.py
@@ -0,0 +1,54 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="EnphaseVPPJoinConfigInlineCredentials")
+
+
+@_attrs_define
+class EnphaseVPPJoinConfigInlineCredentials:
+ """
+ Attributes:
+ client_id (str): Enphase VPP Client ID
+ client_secret (str): Enphase VPP Client Secret
+ api_key (str): Enphase VPP API Key
+ """
+
+ client_id: str
+ client_secret: str
+ api_key: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ api_key = self.api_key
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ "apiKey": api_key,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ api_key = d.pop("apiKey")
+
+ enphase_vpp_join_config_inline_credentials = cls(
+ client_id=client_id,
+ client_secret=client_secret,
+ api_key=api_key,
+ )
+
+ return enphase_vpp_join_config_inline_credentials
diff --git a/derapi/models/franklin_wh_credentials.py b/derapi/models/franklin_wh_credentials.py
new file mode 100644
index 0000000..e78db5c
--- /dev/null
+++ b/derapi/models/franklin_wh_credentials.py
@@ -0,0 +1,66 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="FranklinWHCredentials")
+
+
+@_attrs_define
+class FranklinWHCredentials:
+ """
+ Attributes:
+ vendor (Literal['franklinwh']): Default: 'franklinwh'.
+ type (Literal['partner']): Default: 'partner'.
+ client_id (str): FranklinWH Client ID
+ client_secret (str): FranklinWH Client Secret
+ """
+
+ client_id: str
+ client_secret: str
+ vendor: Literal["franklinwh"] = "franklinwh"
+ type: Literal["partner"] = "partner"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["franklinwh"], d.pop("vendor"))
+ if vendor != "franklinwh":
+ raise ValueError(f"vendor must match const 'franklinwh', got '{vendor}'")
+
+ type = cast(Literal["partner"], d.pop("type"))
+ if type != "partner":
+ raise ValueError(f"type must match const 'partner', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ franklin_wh_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return franklin_wh_credentials
diff --git a/derapi/models/get_battery_intervals_response.py b/derapi/models/get_battery_intervals_response.py
new file mode 100644
index 0000000..240c366
--- /dev/null
+++ b/derapi/models/get_battery_intervals_response.py
@@ -0,0 +1,81 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..models.summary_level import SummaryLevel
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_interval import BatteryInterval
+
+
+T = TypeVar("T", bound="GetBatteryIntervalsResponse")
+
+
+@_attrs_define
+class GetBatteryIntervalsResponse:
+ """
+ Attributes:
+ id (str): Battery id
+ summary_level (SummaryLevel):
+ intervals (List['BatteryInterval']):
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ id: str
+ summary_level: SummaryLevel
+ intervals: List["BatteryInterval"]
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ summary_level = self.summary_level.value
+
+ intervals = []
+ for intervals_item_data in self.intervals:
+ intervals_item = intervals_item_data.to_dict()
+ intervals.append(intervals_item)
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "summaryLevel": summary_level,
+ "intervals": intervals,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_interval import BatteryInterval
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ summary_level = SummaryLevel(d.pop("summaryLevel"))
+
+ intervals = []
+ _intervals = d.pop("intervals")
+ for intervals_item_data in _intervals:
+ intervals_item = BatteryInterval.from_dict(intervals_item_data)
+
+ intervals.append(intervals_item)
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ get_battery_intervals_response = cls(
+ id=id,
+ summary_level=summary_level,
+ intervals=intervals,
+ next_page_token=next_page_token,
+ )
+
+ return get_battery_intervals_response
diff --git a/derapi/models/get_battery_response.py b/derapi/models/get_battery_response.py
new file mode 100644
index 0000000..bd8d5bf
--- /dev/null
+++ b/derapi/models/get_battery_response.py
@@ -0,0 +1,236 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.battery_mode import BatteryMode
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+
+T = TypeVar("T", bound="GetBatteryResponse")
+
+
+@_attrs_define
+class GetBatteryResponse:
+ """
+ Attributes:
+ id (str): Battery id
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format (timezone is always +00:00
+ and is always present)
+ model (str): Model number of Battery
+ serial_number (str): Manufacturer serial number of the Battery
+ site_id (str): The Derapi Site ID this Battery is associated with
+ name (Union[Unset, str]): Customer defined name of the Battery
+ nameplate_kwh (Union[Unset, float]): The rated storage capacity of the unit
+ mode (Union[Unset, BatteryMode]): Battery management system mode. Values are Self Consumption - minimize grid
+ import, Savings - optimizing Battery to save money; usually based on a rate plan, Backup - only use Battery for
+ grid backup
+ state_of_charge_percent (Union[Unset, float]): Battery state of charge as a percent of capacity
+ recent_errors (Union[Unset, List[Union['BatteryRecentErrorsError', 'BatteryRecentErrorsInfo',
+ 'BatteryRecentErrorsStart', 'BatteryRecentErrorsWarning']]]): Most recent errors, warnings, or info reported by
+ the manufacturer for this Battery. The key represents the severity level (info/warning/error); the value is a
+ string description. start is always present and is the last element to be returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ nameplate_kwh: Union[Unset, float] = UNSET
+ mode: Union[Unset, BatteryMode] = UNSET
+ state_of_charge_percent: Union[Unset, float] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ nameplate_kwh = self.nameplate_kwh
+
+ mode: Union[Unset, str] = UNSET
+ if not isinstance(self.mode, Unset):
+ mode = self.mode.value
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_battery_recent_errors_item_data in self.recent_errors:
+ componentsschemas_battery_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsError):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsWarning):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsInfo):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if nameplate_kwh is not UNSET:
+ field_dict["nameplateKwh"] = nameplate_kwh
+ if mode is not UNSET:
+ field_dict["mode"] = mode
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ nameplate_kwh = d.pop("nameplateKwh", UNSET)
+
+ _mode = d.pop("mode", UNSET)
+ mode: Union[Unset, BatteryMode]
+ if isinstance(_mode, Unset):
+ mode = UNSET
+ else:
+ mode = BatteryMode(_mode)
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_battery_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_battery_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_0 = BatteryRecentErrorsError.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_1 = BatteryRecentErrorsWarning.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_2 = BatteryRecentErrorsInfo.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_3 = BatteryRecentErrorsStart.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_3
+
+ componentsschemas_battery_recent_errors_item = _parse_componentsschemas_battery_recent_errors_item(
+ componentsschemas_battery_recent_errors_item_data
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ get_battery_response = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ nameplate_kwh=nameplate_kwh,
+ mode=mode,
+ state_of_charge_percent=state_of_charge_percent,
+ recent_errors=recent_errors,
+ )
+
+ return get_battery_response
diff --git a/derapi/models/get_join_session_token_response.py b/derapi/models/get_join_session_token_response.py
new file mode 100644
index 0000000..347029a
--- /dev/null
+++ b/derapi/models/get_join_session_token_response.py
@@ -0,0 +1,73 @@
+from typing import Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+T = TypeVar("T", bound="GetJoinSessionTokenResponse")
+
+
+@_attrs_define
+class GetJoinSessionTokenResponse:
+ """
+ Attributes:
+ vendor (str): The vendor that the client authorized (sma, enphase, solis, solaredge, enphasevpp, tesla)
+ access_token (str): The public access token to use when requesting data for clients system
+ refresh_token (str): The refresh token to use when requesting a new token for clients system
+ expires_in (str): Amount of time the accessToken is valid (in seconds)
+ site_id (Union[Unset, str]): Only for enphasevpp, the siteID for the clients system
+ """
+
+ vendor: str
+ access_token: str
+ refresh_token: str
+ expires_in: str
+ site_id: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ access_token = self.access_token
+
+ refresh_token = self.refresh_token
+
+ expires_in = self.expires_in
+
+ site_id = self.site_id
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "accessToken": access_token,
+ "refreshToken": refresh_token,
+ "expiresIn": expires_in,
+ }
+ )
+ if site_id is not UNSET:
+ field_dict["siteID"] = site_id
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = d.pop("vendor")
+
+ access_token = d.pop("accessToken")
+
+ refresh_token = d.pop("refreshToken")
+
+ expires_in = d.pop("expiresIn")
+
+ site_id = d.pop("siteID", UNSET)
+
+ get_join_session_token_response = cls(
+ vendor=vendor,
+ access_token=access_token,
+ refresh_token=refresh_token,
+ expires_in=expires_in,
+ site_id=site_id,
+ )
+
+ return get_join_session_token_response
diff --git a/derapi/models/get_site_battery_control_response.py b/derapi/models/get_site_battery_control_response.py
new file mode 100644
index 0000000..3c471de
--- /dev/null
+++ b/derapi/models/get_site_battery_control_response.py
@@ -0,0 +1,60 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.site_battery_control_status_interval import SiteBatteryControlStatusInterval
+
+
+T = TypeVar("T", bound="GetSiteBatteryControlResponse")
+
+
+@_attrs_define
+class GetSiteBatteryControlResponse:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ intervals (List['SiteBatteryControlStatusInterval']):
+ """
+
+ id: str
+ intervals: List["SiteBatteryControlStatusInterval"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ intervals = []
+ for intervals_item_data in self.intervals:
+ intervals_item = intervals_item_data.to_dict()
+ intervals.append(intervals_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "intervals": intervals,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.site_battery_control_status_interval import SiteBatteryControlStatusInterval
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ intervals = []
+ _intervals = d.pop("intervals")
+ for intervals_item_data in _intervals:
+ intervals_item = SiteBatteryControlStatusInterval.from_dict(intervals_item_data)
+
+ intervals.append(intervals_item)
+
+ get_site_battery_control_response = cls(
+ id=id,
+ intervals=intervals,
+ )
+
+ return get_site_battery_control_response
diff --git a/derapi/models/get_site_battery_intervals_response.py b/derapi/models/get_site_battery_intervals_response.py
new file mode 100644
index 0000000..07d55fd
--- /dev/null
+++ b/derapi/models/get_site_battery_intervals_response.py
@@ -0,0 +1,81 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..models.summary_level import SummaryLevel
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.site_battery_interval import SiteBatteryInterval
+
+
+T = TypeVar("T", bound="GetSiteBatteryIntervalsResponse")
+
+
+@_attrs_define
+class GetSiteBatteryIntervalsResponse:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ summary_level (SummaryLevel):
+ intervals (List['SiteBatteryInterval']):
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ id: str
+ summary_level: SummaryLevel
+ intervals: List["SiteBatteryInterval"]
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ summary_level = self.summary_level.value
+
+ intervals = []
+ for intervals_item_data in self.intervals:
+ intervals_item = intervals_item_data.to_dict()
+ intervals.append(intervals_item)
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "summaryLevel": summary_level,
+ "intervals": intervals,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.site_battery_interval import SiteBatteryInterval
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ summary_level = SummaryLevel(d.pop("summaryLevel"))
+
+ intervals = []
+ _intervals = d.pop("intervals")
+ for intervals_item_data in _intervals:
+ intervals_item = SiteBatteryInterval.from_dict(intervals_item_data)
+
+ intervals.append(intervals_item)
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ get_site_battery_intervals_response = cls(
+ id=id,
+ summary_level=summary_level,
+ intervals=intervals,
+ next_page_token=next_page_token,
+ )
+
+ return get_site_battery_intervals_response
diff --git a/derapi/models/get_site_response.py b/derapi/models/get_site_response.py
new file mode 100644
index 0000000..8ee6139
--- /dev/null
+++ b/derapi/models/get_site_response.py
@@ -0,0 +1,163 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+
+T = TypeVar("T", bound="GetSiteResponse")
+
+
+@_attrs_define
+class GetSiteResponse:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ vendor (Vendor):
+ name (str): Customer defined name of the Site
+ location_utc_offset (float): UTC Offset in hours; positive values represent locations East of UTC. Please note
+ this field will soon be deprecated, please use `timezone` instead.
+ batteries (List['BatterySummary']): List of Battery IDs associated with this Site
+ solar_inverters (List['SolarInverterSummary']): List of Solar Inverter IDs associated with this Site
+ location (Union[Unset, SiteLocation]): The location of this Solar Inverter in lat/lon coordinates
+ operational_since (Union[Unset, datetime.datetime]): The date the Site became operational or received permission
+ to operate. Sometimes absent for Solaredge.
+ bess (Union[Unset, SiteBESS]): For Sites with Batteries this key is present
+ """
+
+ id: str
+ vendor: Vendor
+ name: str
+ location_utc_offset: float
+ batteries: List["BatterySummary"]
+ solar_inverters: List["SolarInverterSummary"]
+ location: Union[Unset, "SiteLocation"] = UNSET
+ operational_since: Union[Unset, datetime.datetime] = UNSET
+ bess: Union[Unset, "SiteBESS"] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ vendor = self.vendor.value
+
+ name = self.name
+
+ location_utc_offset = self.location_utc_offset
+
+ batteries = []
+ for componentsschemas_site_batteries_item_data in self.batteries:
+ componentsschemas_site_batteries_item = componentsschemas_site_batteries_item_data.to_dict()
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ for componentsschemas_site_solar_inverters_item_data in self.solar_inverters:
+ componentsschemas_site_solar_inverters_item = componentsschemas_site_solar_inverters_item_data.to_dict()
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ location: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.location, Unset):
+ location = self.location.to_dict()
+
+ operational_since: Union[Unset, str] = UNSET
+ if not isinstance(self.operational_since, Unset):
+ operational_since = self.operational_since.isoformat()
+
+ bess: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.bess, Unset):
+ bess = self.bess.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "name": name,
+ "locationUTCOffset": location_utc_offset,
+ "batteries": batteries,
+ "solarInverters": solar_inverters,
+ }
+ )
+ if location is not UNSET:
+ field_dict["location"] = location
+ if operational_since is not UNSET:
+ field_dict["operationalSince"] = operational_since
+ if bess is not UNSET:
+ field_dict["bess"] = bess
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ name = d.pop("name")
+
+ location_utc_offset = d.pop("locationUTCOffset")
+
+ batteries = []
+ _batteries = d.pop("batteries")
+ for componentsschemas_site_batteries_item_data in _batteries:
+ componentsschemas_site_batteries_item = BatterySummary.from_dict(componentsschemas_site_batteries_item_data)
+
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ _solar_inverters = d.pop("solarInverters")
+ for componentsschemas_site_solar_inverters_item_data in _solar_inverters:
+ componentsschemas_site_solar_inverters_item = SolarInverterSummary.from_dict(
+ componentsschemas_site_solar_inverters_item_data
+ )
+
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ _location = d.pop("location", UNSET)
+ location: Union[Unset, SiteLocation]
+ if isinstance(_location, Unset):
+ location = UNSET
+ else:
+ location = SiteLocation.from_dict(_location)
+
+ _operational_since = d.pop("operationalSince", UNSET)
+ operational_since: Union[Unset, datetime.datetime]
+ if isinstance(_operational_since, Unset):
+ operational_since = UNSET
+ else:
+ operational_since = isoparse(_operational_since)
+
+ _bess = d.pop("bess", UNSET)
+ bess: Union[Unset, SiteBESS]
+ if isinstance(_bess, Unset):
+ bess = UNSET
+ else:
+ bess = SiteBESS.from_dict(_bess)
+
+ get_site_response = cls(
+ id=id,
+ vendor=vendor,
+ name=name,
+ location_utc_offset=location_utc_offset,
+ batteries=batteries,
+ solar_inverters=solar_inverters,
+ location=location,
+ operational_since=operational_since,
+ bess=bess,
+ )
+
+ return get_site_response
diff --git a/derapi/models/get_site_solar_inverter_intervals_response.py b/derapi/models/get_site_solar_inverter_intervals_response.py
new file mode 100644
index 0000000..156b362
--- /dev/null
+++ b/derapi/models/get_site_solar_inverter_intervals_response.py
@@ -0,0 +1,81 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..models.summary_level import SummaryLevel
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.site_solar_inverter_interval import SiteSolarInverterInterval
+
+
+T = TypeVar("T", bound="GetSiteSolarInverterIntervalsResponse")
+
+
+@_attrs_define
+class GetSiteSolarInverterIntervalsResponse:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ summary_level (SummaryLevel):
+ intervals (List['SiteSolarInverterInterval']):
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ id: str
+ summary_level: SummaryLevel
+ intervals: List["SiteSolarInverterInterval"]
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ summary_level = self.summary_level.value
+
+ intervals = []
+ for intervals_item_data in self.intervals:
+ intervals_item = intervals_item_data.to_dict()
+ intervals.append(intervals_item)
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "summaryLevel": summary_level,
+ "intervals": intervals,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.site_solar_inverter_interval import SiteSolarInverterInterval
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ summary_level = SummaryLevel(d.pop("summaryLevel"))
+
+ intervals = []
+ _intervals = d.pop("intervals")
+ for intervals_item_data in _intervals:
+ intervals_item = SiteSolarInverterInterval.from_dict(intervals_item_data)
+
+ intervals.append(intervals_item)
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ get_site_solar_inverter_intervals_response = cls(
+ id=id,
+ summary_level=summary_level,
+ intervals=intervals,
+ next_page_token=next_page_token,
+ )
+
+ return get_site_solar_inverter_intervals_response
diff --git a/derapi/models/get_solar_inverter_intervals_response.py b/derapi/models/get_solar_inverter_intervals_response.py
new file mode 100644
index 0000000..a3108a2
--- /dev/null
+++ b/derapi/models/get_solar_inverter_intervals_response.py
@@ -0,0 +1,81 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..models.summary_level import SummaryLevel
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.solar_inverter_interval import SolarInverterInterval
+
+
+T = TypeVar("T", bound="GetSolarInverterIntervalsResponse")
+
+
+@_attrs_define
+class GetSolarInverterIntervalsResponse:
+ """
+ Attributes:
+ id (str): ID of the solar inverter
+ summary_level (SummaryLevel):
+ intervals (List['SolarInverterInterval']):
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ id: str
+ summary_level: SummaryLevel
+ intervals: List["SolarInverterInterval"]
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ summary_level = self.summary_level.value
+
+ intervals = []
+ for intervals_item_data in self.intervals:
+ intervals_item = intervals_item_data.to_dict()
+ intervals.append(intervals_item)
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "summaryLevel": summary_level,
+ "intervals": intervals,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.solar_inverter_interval import SolarInverterInterval
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ summary_level = SummaryLevel(d.pop("summaryLevel"))
+
+ intervals = []
+ _intervals = d.pop("intervals")
+ for intervals_item_data in _intervals:
+ intervals_item = SolarInverterInterval.from_dict(intervals_item_data)
+
+ intervals.append(intervals_item)
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ get_solar_inverter_intervals_response = cls(
+ id=id,
+ summary_level=summary_level,
+ intervals=intervals,
+ next_page_token=next_page_token,
+ )
+
+ return get_solar_inverter_intervals_response
diff --git a/derapi/models/get_solar_inverter_response.py b/derapi/models/get_solar_inverter_response.py
new file mode 100644
index 0000000..e413686
--- /dev/null
+++ b/derapi/models/get_solar_inverter_response.py
@@ -0,0 +1,249 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+
+T = TypeVar("T", bound="GetSolarInverterResponse")
+
+
+@_attrs_define
+class GetSolarInverterResponse:
+ """
+ Attributes:
+ id (str): ID of the solar inverter
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format
+ model (str): Model number of this Solar Inverter
+ serial_number (str): Manufacturer serial number of this Solar Inverter
+ site_id (str): The Derapi Site ID this Solar Inverter is associated with
+ name (Union[Unset, str]): Customer defined name of this Solar Inverter
+ recent_production (Union[Unset, SolarInverterRecentProduction]):
+ lifetime_production (Union[Unset, SolarInverterLifetimeProduction]):
+ recent_errors (Union[Unset, List[Union['SolarInverterRecentErrorsError', 'SolarInverterRecentErrorsInfo',
+ 'SolarInverterRecentErrorsStart', 'SolarInverterRecentErrorsWarning']]]): Most recent errors, warnings, or info
+ reported by the manufacturer for this Solar Inverter. The key represents the severity level
+ (info/warning/error); the value is a string description. start is always present and is the last element to be
+ returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ recent_production: Union[Unset, "SolarInverterRecentProduction"] = UNSET
+ lifetime_production: Union[Unset, "SolarInverterLifetimeProduction"] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ recent_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.recent_production, Unset):
+ recent_production = self.recent_production.to_dict()
+
+ lifetime_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.lifetime_production, Unset):
+ lifetime_production = self.lifetime_production.to_dict()
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_solar_inverter_recent_errors_item_data in self.recent_errors:
+ componentsschemas_solar_inverter_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsError):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsWarning
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsInfo
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if recent_production is not UNSET:
+ field_dict["recentProduction"] = recent_production
+ if lifetime_production is not UNSET:
+ field_dict["lifetimeProduction"] = lifetime_production
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ _recent_production = d.pop("recentProduction", UNSET)
+ recent_production: Union[Unset, SolarInverterRecentProduction]
+ if isinstance(_recent_production, Unset):
+ recent_production = UNSET
+ else:
+ recent_production = SolarInverterRecentProduction.from_dict(_recent_production)
+
+ _lifetime_production = d.pop("lifetimeProduction", UNSET)
+ lifetime_production: Union[Unset, SolarInverterLifetimeProduction]
+ if isinstance(_lifetime_production, Unset):
+ lifetime_production = UNSET
+ else:
+ lifetime_production = SolarInverterLifetimeProduction.from_dict(_lifetime_production)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_solar_inverter_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_solar_inverter_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_0 = (
+ SolarInverterRecentErrorsError.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_1 = (
+ SolarInverterRecentErrorsWarning.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_2 = (
+ SolarInverterRecentErrorsInfo.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_3 = SolarInverterRecentErrorsStart.from_dict(
+ data
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_3
+
+ componentsschemas_solar_inverter_recent_errors_item = (
+ _parse_componentsschemas_solar_inverter_recent_errors_item(
+ componentsschemas_solar_inverter_recent_errors_item_data
+ )
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ get_solar_inverter_response = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ recent_production=recent_production,
+ lifetime_production=lifetime_production,
+ recent_errors=recent_errors,
+ )
+
+ return get_solar_inverter_response
diff --git a/derapi/models/get_vendor_credentials_response.py b/derapi/models/get_vendor_credentials_response.py
new file mode 100644
index 0000000..905dedf
--- /dev/null
+++ b/derapi/models/get_vendor_credentials_response.py
@@ -0,0 +1,420 @@
+from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+
+T = TypeVar("T", bound="GetVendorCredentialsResponse")
+
+
+@_attrs_define
+class GetVendorCredentialsResponse:
+ """Vendor credentials which may or may not be hidden.
+
+ Attributes:
+ id (str): ID for the vendor credentials
+ name (str): The name of the vendor credentials; inferred if not provided.
+ credentials (Union['EnphaseDeveloperAppCredentials', 'EnphasePartnerAppCredentials', 'EnphaseVPPCredentials',
+ 'FranklinWHCredentials', 'HiddenEnphaseDeveloperAppCredentials', 'HiddenEnphasePartnerAppCredentials',
+ 'HiddenEnphaseVPPCredentials', 'HiddenFranklinWHCredentials', 'HiddenSMACustomGrantCredentials',
+ 'HiddenSMAOAuthCredentials', 'HiddenSMASandboxCustomGrantCredentials', 'HiddenSMASandboxOAuthCredentials',
+ 'HiddenSolarEdgeCredentials', 'HiddenSolisCredentials', 'HiddenTeslaAppCredentials',
+ 'SMACustomGrantCredentials', 'SMAOAuthCredentials', 'SMASandboxCustomGrantCredentials',
+ 'SMASandboxOAuthCredentials', 'SolarEdgeCredentials', 'SolisCredentials', 'TeslaAppCredentials']):
+ """
+
+ id: str
+ name: str
+ credentials: Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+
+ id = self.id
+
+ name = self.name
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, HiddenEnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenEnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenEnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenFranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSolisCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenTeslaAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, FranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolisCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "name": name,
+ "credentials": credentials,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ name = d.pop("name")
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_0 = (
+ HiddenEnphaseDeveloperAppCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_1 = (
+ HiddenEnphasePartnerAppCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_2 = HiddenEnphaseVPPCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_3 = HiddenFranklinWHCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_4 = (
+ HiddenSMACustomGrantCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_5 = HiddenSMAOAuthCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_6 = (
+ HiddenSMASandboxCustomGrantCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_7 = (
+ HiddenSMASandboxOAuthCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_8 = HiddenSolarEdgeCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_9 = HiddenSolisCredentials.from_dict(data)
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_10 = HiddenTeslaAppCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_10
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_0 = EnphasePartnerAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_1 = EnphaseDeveloperAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_2 = EnphaseVPPCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_3 = FranklinWHCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_4 = SMACustomGrantCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_5 = SMAOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_6 = SMASandboxCustomGrantCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_7 = SMASandboxOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_8 = SolarEdgeCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_9 = SolisCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_10 = TeslaAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_10
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ get_vendor_credentials_response = cls(
+ id=id,
+ name=name,
+ credentials=credentials,
+ )
+
+ return get_vendor_credentials_response
diff --git a/derapi/models/get_virtual_battery_response.py b/derapi/models/get_virtual_battery_response.py
new file mode 100644
index 0000000..559076d
--- /dev/null
+++ b/derapi/models/get_virtual_battery_response.py
@@ -0,0 +1,236 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.battery_mode import BatteryMode
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+
+T = TypeVar("T", bound="GetVirtualBatteryResponse")
+
+
+@_attrs_define
+class GetVirtualBatteryResponse:
+ """
+ Attributes:
+ id (str): Battery id
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format (timezone is always +00:00
+ and is always present)
+ model (str): Model number of Battery
+ serial_number (str): Manufacturer serial number of the Battery
+ site_id (str): The Derapi Site ID this Battery is associated with
+ name (Union[Unset, str]): Customer defined name of the Battery
+ nameplate_kwh (Union[Unset, float]): The rated storage capacity of the unit
+ mode (Union[Unset, BatteryMode]): Battery management system mode. Values are Self Consumption - minimize grid
+ import, Savings - optimizing Battery to save money; usually based on a rate plan, Backup - only use Battery for
+ grid backup
+ state_of_charge_percent (Union[Unset, float]): Battery state of charge as a percent of capacity
+ recent_errors (Union[Unset, List[Union['BatteryRecentErrorsError', 'BatteryRecentErrorsInfo',
+ 'BatteryRecentErrorsStart', 'BatteryRecentErrorsWarning']]]): Most recent errors, warnings, or info reported by
+ the manufacturer for this Battery. The key represents the severity level (info/warning/error); the value is a
+ string description. start is always present and is the last element to be returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ nameplate_kwh: Union[Unset, float] = UNSET
+ mode: Union[Unset, BatteryMode] = UNSET
+ state_of_charge_percent: Union[Unset, float] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ nameplate_kwh = self.nameplate_kwh
+
+ mode: Union[Unset, str] = UNSET
+ if not isinstance(self.mode, Unset):
+ mode = self.mode.value
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_battery_recent_errors_item_data in self.recent_errors:
+ componentsschemas_battery_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsError):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsWarning):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsInfo):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if nameplate_kwh is not UNSET:
+ field_dict["nameplateKwh"] = nameplate_kwh
+ if mode is not UNSET:
+ field_dict["mode"] = mode
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ nameplate_kwh = d.pop("nameplateKwh", UNSET)
+
+ _mode = d.pop("mode", UNSET)
+ mode: Union[Unset, BatteryMode]
+ if isinstance(_mode, Unset):
+ mode = UNSET
+ else:
+ mode = BatteryMode(_mode)
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_battery_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_battery_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_0 = BatteryRecentErrorsError.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_1 = BatteryRecentErrorsWarning.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_2 = BatteryRecentErrorsInfo.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_3 = BatteryRecentErrorsStart.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_3
+
+ componentsschemas_battery_recent_errors_item = _parse_componentsschemas_battery_recent_errors_item(
+ componentsschemas_battery_recent_errors_item_data
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ get_virtual_battery_response = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ nameplate_kwh=nameplate_kwh,
+ mode=mode,
+ state_of_charge_percent=state_of_charge_percent,
+ recent_errors=recent_errors,
+ )
+
+ return get_virtual_battery_response
diff --git a/derapi/models/get_virtual_site_response.py b/derapi/models/get_virtual_site_response.py
new file mode 100644
index 0000000..9b058f3
--- /dev/null
+++ b/derapi/models/get_virtual_site_response.py
@@ -0,0 +1,163 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+
+T = TypeVar("T", bound="GetVirtualSiteResponse")
+
+
+@_attrs_define
+class GetVirtualSiteResponse:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ vendor (Vendor):
+ name (str): Customer defined name of the Site
+ location_utc_offset (float): UTC Offset in hours; positive values represent locations East of UTC. Please note
+ this field will soon be deprecated, please use `timezone` instead.
+ batteries (List['BatterySummary']): List of Battery IDs associated with this Site
+ solar_inverters (List['SolarInverterSummary']): List of Solar Inverter IDs associated with this Site
+ location (Union[Unset, SiteLocation]): The location of this Solar Inverter in lat/lon coordinates
+ operational_since (Union[Unset, datetime.datetime]): The date the Site became operational or received permission
+ to operate. Sometimes absent for Solaredge.
+ bess (Union[Unset, SiteBESS]): For Sites with Batteries this key is present
+ """
+
+ id: str
+ vendor: Vendor
+ name: str
+ location_utc_offset: float
+ batteries: List["BatterySummary"]
+ solar_inverters: List["SolarInverterSummary"]
+ location: Union[Unset, "SiteLocation"] = UNSET
+ operational_since: Union[Unset, datetime.datetime] = UNSET
+ bess: Union[Unset, "SiteBESS"] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ vendor = self.vendor.value
+
+ name = self.name
+
+ location_utc_offset = self.location_utc_offset
+
+ batteries = []
+ for componentsschemas_site_batteries_item_data in self.batteries:
+ componentsschemas_site_batteries_item = componentsschemas_site_batteries_item_data.to_dict()
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ for componentsschemas_site_solar_inverters_item_data in self.solar_inverters:
+ componentsschemas_site_solar_inverters_item = componentsschemas_site_solar_inverters_item_data.to_dict()
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ location: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.location, Unset):
+ location = self.location.to_dict()
+
+ operational_since: Union[Unset, str] = UNSET
+ if not isinstance(self.operational_since, Unset):
+ operational_since = self.operational_since.isoformat()
+
+ bess: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.bess, Unset):
+ bess = self.bess.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "name": name,
+ "locationUTCOffset": location_utc_offset,
+ "batteries": batteries,
+ "solarInverters": solar_inverters,
+ }
+ )
+ if location is not UNSET:
+ field_dict["location"] = location
+ if operational_since is not UNSET:
+ field_dict["operationalSince"] = operational_since
+ if bess is not UNSET:
+ field_dict["bess"] = bess
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ name = d.pop("name")
+
+ location_utc_offset = d.pop("locationUTCOffset")
+
+ batteries = []
+ _batteries = d.pop("batteries")
+ for componentsschemas_site_batteries_item_data in _batteries:
+ componentsschemas_site_batteries_item = BatterySummary.from_dict(componentsschemas_site_batteries_item_data)
+
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ _solar_inverters = d.pop("solarInverters")
+ for componentsschemas_site_solar_inverters_item_data in _solar_inverters:
+ componentsschemas_site_solar_inverters_item = SolarInverterSummary.from_dict(
+ componentsschemas_site_solar_inverters_item_data
+ )
+
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ _location = d.pop("location", UNSET)
+ location: Union[Unset, SiteLocation]
+ if isinstance(_location, Unset):
+ location = UNSET
+ else:
+ location = SiteLocation.from_dict(_location)
+
+ _operational_since = d.pop("operationalSince", UNSET)
+ operational_since: Union[Unset, datetime.datetime]
+ if isinstance(_operational_since, Unset):
+ operational_since = UNSET
+ else:
+ operational_since = isoparse(_operational_since)
+
+ _bess = d.pop("bess", UNSET)
+ bess: Union[Unset, SiteBESS]
+ if isinstance(_bess, Unset):
+ bess = UNSET
+ else:
+ bess = SiteBESS.from_dict(_bess)
+
+ get_virtual_site_response = cls(
+ id=id,
+ vendor=vendor,
+ name=name,
+ location_utc_offset=location_utc_offset,
+ batteries=batteries,
+ solar_inverters=solar_inverters,
+ location=location,
+ operational_since=operational_since,
+ bess=bess,
+ )
+
+ return get_virtual_site_response
diff --git a/derapi/models/get_virtual_solar_inverter_response.py b/derapi/models/get_virtual_solar_inverter_response.py
new file mode 100644
index 0000000..f9f5465
--- /dev/null
+++ b/derapi/models/get_virtual_solar_inverter_response.py
@@ -0,0 +1,249 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+
+T = TypeVar("T", bound="GetVirtualSolarInverterResponse")
+
+
+@_attrs_define
+class GetVirtualSolarInverterResponse:
+ """
+ Attributes:
+ id (str): ID of the solar inverter
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format
+ model (str): Model number of this Solar Inverter
+ serial_number (str): Manufacturer serial number of this Solar Inverter
+ site_id (str): The Derapi Site ID this Solar Inverter is associated with
+ name (Union[Unset, str]): Customer defined name of this Solar Inverter
+ recent_production (Union[Unset, SolarInverterRecentProduction]):
+ lifetime_production (Union[Unset, SolarInverterLifetimeProduction]):
+ recent_errors (Union[Unset, List[Union['SolarInverterRecentErrorsError', 'SolarInverterRecentErrorsInfo',
+ 'SolarInverterRecentErrorsStart', 'SolarInverterRecentErrorsWarning']]]): Most recent errors, warnings, or info
+ reported by the manufacturer for this Solar Inverter. The key represents the severity level
+ (info/warning/error); the value is a string description. start is always present and is the last element to be
+ returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ recent_production: Union[Unset, "SolarInverterRecentProduction"] = UNSET
+ lifetime_production: Union[Unset, "SolarInverterLifetimeProduction"] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ recent_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.recent_production, Unset):
+ recent_production = self.recent_production.to_dict()
+
+ lifetime_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.lifetime_production, Unset):
+ lifetime_production = self.lifetime_production.to_dict()
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_solar_inverter_recent_errors_item_data in self.recent_errors:
+ componentsschemas_solar_inverter_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsError):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsWarning
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsInfo
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if recent_production is not UNSET:
+ field_dict["recentProduction"] = recent_production
+ if lifetime_production is not UNSET:
+ field_dict["lifetimeProduction"] = lifetime_production
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ _recent_production = d.pop("recentProduction", UNSET)
+ recent_production: Union[Unset, SolarInverterRecentProduction]
+ if isinstance(_recent_production, Unset):
+ recent_production = UNSET
+ else:
+ recent_production = SolarInverterRecentProduction.from_dict(_recent_production)
+
+ _lifetime_production = d.pop("lifetimeProduction", UNSET)
+ lifetime_production: Union[Unset, SolarInverterLifetimeProduction]
+ if isinstance(_lifetime_production, Unset):
+ lifetime_production = UNSET
+ else:
+ lifetime_production = SolarInverterLifetimeProduction.from_dict(_lifetime_production)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_solar_inverter_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_solar_inverter_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_0 = (
+ SolarInverterRecentErrorsError.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_1 = (
+ SolarInverterRecentErrorsWarning.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_2 = (
+ SolarInverterRecentErrorsInfo.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_3 = SolarInverterRecentErrorsStart.from_dict(
+ data
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_3
+
+ componentsschemas_solar_inverter_recent_errors_item = (
+ _parse_componentsschemas_solar_inverter_recent_errors_item(
+ componentsschemas_solar_inverter_recent_errors_item_data
+ )
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ get_virtual_solar_inverter_response = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ recent_production=recent_production,
+ lifetime_production=lifetime_production,
+ recent_errors=recent_errors,
+ )
+
+ return get_virtual_solar_inverter_response
diff --git a/derapi/models/hidden_enphase_developer_app_credentials.py b/derapi/models/hidden_enphase_developer_app_credentials.py
new file mode 100644
index 0000000..ed966eb
--- /dev/null
+++ b/derapi/models/hidden_enphase_developer_app_credentials.py
@@ -0,0 +1,50 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenEnphaseDeveloperAppCredentials")
+
+
+@_attrs_define
+class HiddenEnphaseDeveloperAppCredentials:
+ """
+ Attributes:
+ type (Literal['developerapp']): Default: 'developerapp'.
+ vendor (Literal['enphase']): Default: 'enphase'.
+ """
+
+ type: Literal["developerapp"] = "developerapp"
+ vendor: Literal["enphase"] = "enphase"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["developerapp"], d.pop("type"))
+ if type != "developerapp":
+ raise ValueError(f"type must match const 'developerapp', got '{type}'")
+
+ vendor = cast(Literal["enphase"], d.pop("vendor"))
+ if vendor != "enphase":
+ raise ValueError(f"vendor must match const 'enphase', got '{vendor}'")
+
+ hidden_enphase_developer_app_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_enphase_developer_app_credentials
diff --git a/derapi/models/hidden_enphase_partner_app_credentials.py b/derapi/models/hidden_enphase_partner_app_credentials.py
new file mode 100644
index 0000000..4fec65d
--- /dev/null
+++ b/derapi/models/hidden_enphase_partner_app_credentials.py
@@ -0,0 +1,51 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenEnphasePartnerAppCredentials")
+
+
+@_attrs_define
+class HiddenEnphasePartnerAppCredentials:
+ """Credentials for an Enphase partner app
+
+ Attributes:
+ type (Literal['partnerapp']): Default: 'partnerapp'.
+ vendor (Literal['enphase']): Default: 'enphase'.
+ """
+
+ type: Literal["partnerapp"] = "partnerapp"
+ vendor: Literal["enphase"] = "enphase"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["partnerapp"], d.pop("type"))
+ if type != "partnerapp":
+ raise ValueError(f"type must match const 'partnerapp', got '{type}'")
+
+ vendor = cast(Literal["enphase"], d.pop("vendor"))
+ if vendor != "enphase":
+ raise ValueError(f"vendor must match const 'enphase', got '{vendor}'")
+
+ hidden_enphase_partner_app_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_enphase_partner_app_credentials
diff --git a/derapi/models/hidden_enphase_vpp_credentials.py b/derapi/models/hidden_enphase_vpp_credentials.py
new file mode 100644
index 0000000..c932830
--- /dev/null
+++ b/derapi/models/hidden_enphase_vpp_credentials.py
@@ -0,0 +1,50 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenEnphaseVPPCredentials")
+
+
+@_attrs_define
+class HiddenEnphaseVPPCredentials:
+ """
+ Attributes:
+ type (Literal['vpp']): Default: 'vpp'.
+ vendor (Literal['enphasevpp']): Default: 'enphasevpp'.
+ """
+
+ type: Literal["vpp"] = "vpp"
+ vendor: Literal["enphasevpp"] = "enphasevpp"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["vpp"], d.pop("type"))
+ if type != "vpp":
+ raise ValueError(f"type must match const 'vpp', got '{type}'")
+
+ vendor = cast(Literal["enphasevpp"], d.pop("vendor"))
+ if vendor != "enphasevpp":
+ raise ValueError(f"vendor must match const 'enphasevpp', got '{vendor}'")
+
+ hidden_enphase_vpp_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_enphase_vpp_credentials
diff --git a/derapi/models/hidden_franklin_wh_credentials.py b/derapi/models/hidden_franklin_wh_credentials.py
new file mode 100644
index 0000000..289bcf6
--- /dev/null
+++ b/derapi/models/hidden_franklin_wh_credentials.py
@@ -0,0 +1,50 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenFranklinWHCredentials")
+
+
+@_attrs_define
+class HiddenFranklinWHCredentials:
+ """
+ Attributes:
+ type (Literal['partner']): Default: 'partner'.
+ vendor (Literal['franklinwh']): Default: 'franklinwh'.
+ """
+
+ type: Literal["partner"] = "partner"
+ vendor: Literal["franklinwh"] = "franklinwh"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["partner"], d.pop("type"))
+ if type != "partner":
+ raise ValueError(f"type must match const 'partner', got '{type}'")
+
+ vendor = cast(Literal["franklinwh"], d.pop("vendor"))
+ if vendor != "franklinwh":
+ raise ValueError(f"vendor must match const 'franklinwh', got '{vendor}'")
+
+ hidden_franklin_wh_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_franklin_wh_credentials
diff --git a/derapi/models/hidden_sma_custom_grant_credentials.py b/derapi/models/hidden_sma_custom_grant_credentials.py
new file mode 100644
index 0000000..f7cefd5
--- /dev/null
+++ b/derapi/models/hidden_sma_custom_grant_credentials.py
@@ -0,0 +1,51 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenSMACustomGrantCredentials")
+
+
+@_attrs_define
+class HiddenSMACustomGrantCredentials:
+ """Credentials from the SMA custom grant oauth flow
+
+ Attributes:
+ type (Literal['customgrant']): Default: 'customgrant'.
+ vendor (Literal['sma']): Default: 'sma'.
+ """
+
+ type: Literal["customgrant"] = "customgrant"
+ vendor: Literal["sma"] = "sma"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["customgrant"], d.pop("type"))
+ if type != "customgrant":
+ raise ValueError(f"type must match const 'customgrant', got '{type}'")
+
+ vendor = cast(Literal["sma"], d.pop("vendor"))
+ if vendor != "sma":
+ raise ValueError(f"vendor must match const 'sma', got '{vendor}'")
+
+ hidden_sma_custom_grant_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_sma_custom_grant_credentials
diff --git a/derapi/models/hidden_sma_sandbox_custom_grant_credentials.py b/derapi/models/hidden_sma_sandbox_custom_grant_credentials.py
new file mode 100644
index 0000000..fc3070c
--- /dev/null
+++ b/derapi/models/hidden_sma_sandbox_custom_grant_credentials.py
@@ -0,0 +1,51 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenSMASandboxCustomGrantCredentials")
+
+
+@_attrs_define
+class HiddenSMASandboxCustomGrantCredentials:
+ """Credentials from the SMA Sandbox custom grant oauth flow
+
+ Attributes:
+ type (Literal['customgrant']): Default: 'customgrant'.
+ vendor (Literal['smasbox']): Default: 'smasbox'.
+ """
+
+ type: Literal["customgrant"] = "customgrant"
+ vendor: Literal["smasbox"] = "smasbox"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["customgrant"], d.pop("type"))
+ if type != "customgrant":
+ raise ValueError(f"type must match const 'customgrant', got '{type}'")
+
+ vendor = cast(Literal["smasbox"], d.pop("vendor"))
+ if vendor != "smasbox":
+ raise ValueError(f"vendor must match const 'smasbox', got '{vendor}'")
+
+ hidden_sma_sandbox_custom_grant_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_sma_sandbox_custom_grant_credentials
diff --git a/derapi/models/hidden_sma_sandbox_o_auth_credentials.py b/derapi/models/hidden_sma_sandbox_o_auth_credentials.py
new file mode 100644
index 0000000..04b807a
--- /dev/null
+++ b/derapi/models/hidden_sma_sandbox_o_auth_credentials.py
@@ -0,0 +1,51 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenSMASandboxOAuthCredentials")
+
+
+@_attrs_define
+class HiddenSMASandboxOAuthCredentials:
+ """Credentials from the SMA Sandbox OAuth code grant flow
+
+ Attributes:
+ type (Literal['oauthclient']): Default: 'oauthclient'.
+ vendor (Literal['smasbox']): Default: 'smasbox'.
+ """
+
+ type: Literal["oauthclient"] = "oauthclient"
+ vendor: Literal["smasbox"] = "smasbox"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["oauthclient"], d.pop("type"))
+ if type != "oauthclient":
+ raise ValueError(f"type must match const 'oauthclient', got '{type}'")
+
+ vendor = cast(Literal["smasbox"], d.pop("vendor"))
+ if vendor != "smasbox":
+ raise ValueError(f"vendor must match const 'smasbox', got '{vendor}'")
+
+ hidden_sma_sandbox_o_auth_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_sma_sandbox_o_auth_credentials
diff --git a/derapi/models/hidden_smao_auth_credentials.py b/derapi/models/hidden_smao_auth_credentials.py
new file mode 100644
index 0000000..15a4d08
--- /dev/null
+++ b/derapi/models/hidden_smao_auth_credentials.py
@@ -0,0 +1,51 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenSMAOAuthCredentials")
+
+
+@_attrs_define
+class HiddenSMAOAuthCredentials:
+ """Credentials from the SMA OAuth code grant flow
+
+ Attributes:
+ type (Literal['oauthclient']): Default: 'oauthclient'.
+ vendor (Literal['sma']): Default: 'sma'.
+ """
+
+ type: Literal["oauthclient"] = "oauthclient"
+ vendor: Literal["sma"] = "sma"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["oauthclient"], d.pop("type"))
+ if type != "oauthclient":
+ raise ValueError(f"type must match const 'oauthclient', got '{type}'")
+
+ vendor = cast(Literal["sma"], d.pop("vendor"))
+ if vendor != "sma":
+ raise ValueError(f"vendor must match const 'sma', got '{vendor}'")
+
+ hidden_smao_auth_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_smao_auth_credentials
diff --git a/derapi/models/hidden_solar_edge_credentials.py b/derapi/models/hidden_solar_edge_credentials.py
new file mode 100644
index 0000000..2baf87a
--- /dev/null
+++ b/derapi/models/hidden_solar_edge_credentials.py
@@ -0,0 +1,50 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenSolarEdgeCredentials")
+
+
+@_attrs_define
+class HiddenSolarEdgeCredentials:
+ """
+ Attributes:
+ type (Literal['apikey']): Default: 'apikey'.
+ vendor (Literal['solaredge']): Default: 'solaredge'.
+ """
+
+ type: Literal["apikey"] = "apikey"
+ vendor: Literal["solaredge"] = "solaredge"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["apikey"], d.pop("type"))
+ if type != "apikey":
+ raise ValueError(f"type must match const 'apikey', got '{type}'")
+
+ vendor = cast(Literal["solaredge"], d.pop("vendor"))
+ if vendor != "solaredge":
+ raise ValueError(f"vendor must match const 'solaredge', got '{vendor}'")
+
+ hidden_solar_edge_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_solar_edge_credentials
diff --git a/derapi/models/hidden_solis_credentials.py b/derapi/models/hidden_solis_credentials.py
new file mode 100644
index 0000000..6735407
--- /dev/null
+++ b/derapi/models/hidden_solis_credentials.py
@@ -0,0 +1,50 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenSolisCredentials")
+
+
+@_attrs_define
+class HiddenSolisCredentials:
+ """
+ Attributes:
+ type (Literal['apikeysecret']): Default: 'apikeysecret'.
+ vendor (Literal['solis']): Default: 'solis'.
+ """
+
+ type: Literal["apikeysecret"] = "apikeysecret"
+ vendor: Literal["solis"] = "solis"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["apikeysecret"], d.pop("type"))
+ if type != "apikeysecret":
+ raise ValueError(f"type must match const 'apikeysecret', got '{type}'")
+
+ vendor = cast(Literal["solis"], d.pop("vendor"))
+ if vendor != "solis":
+ raise ValueError(f"vendor must match const 'solis', got '{vendor}'")
+
+ hidden_solis_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_solis_credentials
diff --git a/derapi/models/hidden_tesla_app_credentials.py b/derapi/models/hidden_tesla_app_credentials.py
new file mode 100644
index 0000000..3d28cc5
--- /dev/null
+++ b/derapi/models/hidden_tesla_app_credentials.py
@@ -0,0 +1,50 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="HiddenTeslaAppCredentials")
+
+
+@_attrs_define
+class HiddenTeslaAppCredentials:
+ """
+ Attributes:
+ type (Literal['app']): Default: 'app'.
+ vendor (Literal['tesla']): Default: 'tesla'.
+ """
+
+ type: Literal["app"] = "app"
+ vendor: Literal["tesla"] = "tesla"
+
+ def to_dict(self) -> Dict[str, Any]:
+ type = self.type
+
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "type": type,
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ type = cast(Literal["app"], d.pop("type"))
+ if type != "app":
+ raise ValueError(f"type must match const 'app', got '{type}'")
+
+ vendor = cast(Literal["tesla"], d.pop("vendor"))
+ if vendor != "tesla":
+ raise ValueError(f"vendor must match const 'tesla', got '{vendor}'")
+
+ hidden_tesla_app_credentials = cls(
+ type=type,
+ vendor=vendor,
+ )
+
+ return hidden_tesla_app_credentials
diff --git a/derapi/models/list_batteries_response.py b/derapi/models/list_batteries_response.py
new file mode 100644
index 0000000..2bc1521
--- /dev/null
+++ b/derapi/models/list_batteries_response.py
@@ -0,0 +1,75 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_summary import BatterySummary
+ from ..models.list_batteries_response_errors import ListBatteriesResponseErrors
+
+
+T = TypeVar("T", bound="ListBatteriesResponse")
+
+
+@_attrs_define
+class ListBatteriesResponse:
+ """
+ Attributes:
+ batteries (List['BatterySummary']): List of Batteries
+ errors (ListBatteriesResponseErrors): If there is an error accessing a vendor API then error details are
+ provided
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ batteries: List["BatterySummary"]
+ errors: "ListBatteriesResponseErrors"
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ batteries = []
+ for batteries_item_data in self.batteries:
+ batteries_item = batteries_item_data.to_dict()
+ batteries.append(batteries_item)
+
+ errors = self.errors.to_dict()
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "batteries": batteries,
+ "errors": errors,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_summary import BatterySummary
+ from ..models.list_batteries_response_errors import ListBatteriesResponseErrors
+
+ d = src_dict.copy()
+ batteries = []
+ _batteries = d.pop("batteries")
+ for batteries_item_data in _batteries:
+ batteries_item = BatterySummary.from_dict(batteries_item_data)
+
+ batteries.append(batteries_item)
+
+ errors = ListBatteriesResponseErrors.from_dict(d.pop("errors"))
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ list_batteries_response = cls(
+ batteries=batteries,
+ errors=errors,
+ next_page_token=next_page_token,
+ )
+
+ return list_batteries_response
diff --git a/derapi/models/list_batteries_response_errors.py b/derapi/models/list_batteries_response_errors.py
new file mode 100644
index 0000000..a4c23de
--- /dev/null
+++ b/derapi/models/list_batteries_response_errors.py
@@ -0,0 +1,43 @@
+from typing import Any, Dict, List, Type, TypeVar
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+T = TypeVar("T", bound="ListBatteriesResponseErrors")
+
+
+@_attrs_define
+class ListBatteriesResponseErrors:
+ """If there is an error accessing a vendor API then error details are provided"""
+
+ additional_properties: Dict[str, str] = _attrs_field(init=False, factory=dict)
+
+ def to_dict(self) -> Dict[str, Any]:
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ list_batteries_response_errors = cls()
+
+ list_batteries_response_errors.additional_properties = d
+ return list_batteries_response_errors
+
+ @property
+ def additional_keys(self) -> List[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> str:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: str) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/derapi/models/list_site_response_errors.py b/derapi/models/list_site_response_errors.py
new file mode 100644
index 0000000..6a93948
--- /dev/null
+++ b/derapi/models/list_site_response_errors.py
@@ -0,0 +1,43 @@
+from typing import Any, Dict, List, Type, TypeVar
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+T = TypeVar("T", bound="ListSiteResponseErrors")
+
+
+@_attrs_define
+class ListSiteResponseErrors:
+ """If there is an error accessing a vendor API then error details are provided"""
+
+ additional_properties: Dict[str, str] = _attrs_field(init=False, factory=dict)
+
+ def to_dict(self) -> Dict[str, Any]:
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ list_site_response_errors = cls()
+
+ list_site_response_errors.additional_properties = d
+ return list_site_response_errors
+
+ @property
+ def additional_keys(self) -> List[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> str:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: str) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/derapi/models/list_sites_response.py b/derapi/models/list_sites_response.py
new file mode 100644
index 0000000..c5a2dc4
--- /dev/null
+++ b/derapi/models/list_sites_response.py
@@ -0,0 +1,74 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.list_site_response_errors import ListSiteResponseErrors
+ from ..models.site_summary import SiteSummary
+
+
+T = TypeVar("T", bound="ListSitesResponse")
+
+
+@_attrs_define
+class ListSitesResponse:
+ """
+ Attributes:
+ sites (List['SiteSummary']): List of Sites
+ errors (ListSiteResponseErrors): If there is an error accessing a vendor API then error details are provided
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ sites: List["SiteSummary"]
+ errors: "ListSiteResponseErrors"
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ sites = []
+ for sites_item_data in self.sites:
+ sites_item = sites_item_data.to_dict()
+ sites.append(sites_item)
+
+ errors = self.errors.to_dict()
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "sites": sites,
+ "errors": errors,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.list_site_response_errors import ListSiteResponseErrors
+ from ..models.site_summary import SiteSummary
+
+ d = src_dict.copy()
+ sites = []
+ _sites = d.pop("sites")
+ for sites_item_data in _sites:
+ sites_item = SiteSummary.from_dict(sites_item_data)
+
+ sites.append(sites_item)
+
+ errors = ListSiteResponseErrors.from_dict(d.pop("errors"))
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ list_sites_response = cls(
+ sites=sites,
+ errors=errors,
+ next_page_token=next_page_token,
+ )
+
+ return list_sites_response
diff --git a/derapi/models/list_solar_inverters_response.py b/derapi/models/list_solar_inverters_response.py
new file mode 100644
index 0000000..cf99569
--- /dev/null
+++ b/derapi/models/list_solar_inverters_response.py
@@ -0,0 +1,75 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.list_solar_inverters_response_errors import ListSolarInvertersResponseErrors
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+
+T = TypeVar("T", bound="ListSolarInvertersResponse")
+
+
+@_attrs_define
+class ListSolarInvertersResponse:
+ """
+ Attributes:
+ solar_inverters (List['SolarInverterSummary']): List of Solar Inverters
+ errors (ListSolarInvertersResponseErrors): If there is an error accessing a vendor API then error details are
+ provided
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ solar_inverters: List["SolarInverterSummary"]
+ errors: "ListSolarInvertersResponseErrors"
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ solar_inverters = []
+ for solar_inverters_item_data in self.solar_inverters:
+ solar_inverters_item = solar_inverters_item_data.to_dict()
+ solar_inverters.append(solar_inverters_item)
+
+ errors = self.errors.to_dict()
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "solarInverters": solar_inverters,
+ "errors": errors,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.list_solar_inverters_response_errors import ListSolarInvertersResponseErrors
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+ d = src_dict.copy()
+ solar_inverters = []
+ _solar_inverters = d.pop("solarInverters")
+ for solar_inverters_item_data in _solar_inverters:
+ solar_inverters_item = SolarInverterSummary.from_dict(solar_inverters_item_data)
+
+ solar_inverters.append(solar_inverters_item)
+
+ errors = ListSolarInvertersResponseErrors.from_dict(d.pop("errors"))
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ list_solar_inverters_response = cls(
+ solar_inverters=solar_inverters,
+ errors=errors,
+ next_page_token=next_page_token,
+ )
+
+ return list_solar_inverters_response
diff --git a/derapi/models/list_solar_inverters_response_errors.py b/derapi/models/list_solar_inverters_response_errors.py
new file mode 100644
index 0000000..c88a31f
--- /dev/null
+++ b/derapi/models/list_solar_inverters_response_errors.py
@@ -0,0 +1,43 @@
+from typing import Any, Dict, List, Type, TypeVar
+
+from attrs import define as _attrs_define
+from attrs import field as _attrs_field
+
+T = TypeVar("T", bound="ListSolarInvertersResponseErrors")
+
+
+@_attrs_define
+class ListSolarInvertersResponseErrors:
+ """If there is an error accessing a vendor API then error details are provided"""
+
+ additional_properties: Dict[str, str] = _attrs_field(init=False, factory=dict)
+
+ def to_dict(self) -> Dict[str, Any]:
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(self.additional_properties)
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ list_solar_inverters_response_errors = cls()
+
+ list_solar_inverters_response_errors.additional_properties = d
+ return list_solar_inverters_response_errors
+
+ @property
+ def additional_keys(self) -> List[str]:
+ return list(self.additional_properties.keys())
+
+ def __getitem__(self, key: str) -> str:
+ return self.additional_properties[key]
+
+ def __setitem__(self, key: str, value: str) -> None:
+ self.additional_properties[key] = value
+
+ def __delitem__(self, key: str) -> None:
+ del self.additional_properties[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self.additional_properties
diff --git a/derapi/models/list_vendor_credentials_response.py b/derapi/models/list_vendor_credentials_response.py
new file mode 100644
index 0000000..d4e95ae
--- /dev/null
+++ b/derapi/models/list_vendor_credentials_response.py
@@ -0,0 +1,64 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.vendor_credentials import VendorCredentials
+
+
+T = TypeVar("T", bound="ListVendorCredentialsResponse")
+
+
+@_attrs_define
+class ListVendorCredentialsResponse:
+ """
+ Attributes:
+ vendor_credentials (List['VendorCredentials']):
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ vendor_credentials: List["VendorCredentials"]
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor_credentials = []
+ for vendor_credentials_item_data in self.vendor_credentials:
+ vendor_credentials_item = vendor_credentials_item_data.to_dict()
+ vendor_credentials.append(vendor_credentials_item)
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendorCredentials": vendor_credentials,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.vendor_credentials import VendorCredentials
+
+ d = src_dict.copy()
+ vendor_credentials = []
+ _vendor_credentials = d.pop("vendorCredentials")
+ for vendor_credentials_item_data in _vendor_credentials:
+ vendor_credentials_item = VendorCredentials.from_dict(vendor_credentials_item_data)
+
+ vendor_credentials.append(vendor_credentials_item)
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ list_vendor_credentials_response = cls(
+ vendor_credentials=vendor_credentials,
+ next_page_token=next_page_token,
+ )
+
+ return list_vendor_credentials_response
diff --git a/derapi/models/list_virtual_batteries_response.py b/derapi/models/list_virtual_batteries_response.py
new file mode 100644
index 0000000..ab8275c
--- /dev/null
+++ b/derapi/models/list_virtual_batteries_response.py
@@ -0,0 +1,64 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.virtual_battery import VirtualBattery
+
+
+T = TypeVar("T", bound="ListVirtualBatteriesResponse")
+
+
+@_attrs_define
+class ListVirtualBatteriesResponse:
+ """
+ Attributes:
+ virtual_batteries (List['VirtualBattery']):
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ virtual_batteries: List["VirtualBattery"]
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ virtual_batteries = []
+ for virtual_batteries_item_data in self.virtual_batteries:
+ virtual_batteries_item = virtual_batteries_item_data.to_dict()
+ virtual_batteries.append(virtual_batteries_item)
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "virtualBatteries": virtual_batteries,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.virtual_battery import VirtualBattery
+
+ d = src_dict.copy()
+ virtual_batteries = []
+ _virtual_batteries = d.pop("virtualBatteries")
+ for virtual_batteries_item_data in _virtual_batteries:
+ virtual_batteries_item = VirtualBattery.from_dict(virtual_batteries_item_data)
+
+ virtual_batteries.append(virtual_batteries_item)
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ list_virtual_batteries_response = cls(
+ virtual_batteries=virtual_batteries,
+ next_page_token=next_page_token,
+ )
+
+ return list_virtual_batteries_response
diff --git a/derapi/models/list_virtual_sites_response.py b/derapi/models/list_virtual_sites_response.py
new file mode 100644
index 0000000..39dd1d8
--- /dev/null
+++ b/derapi/models/list_virtual_sites_response.py
@@ -0,0 +1,64 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.virtual_site import VirtualSite
+
+
+T = TypeVar("T", bound="ListVirtualSitesResponse")
+
+
+@_attrs_define
+class ListVirtualSitesResponse:
+ """
+ Attributes:
+ virtual_sites (List['VirtualSite']):
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ virtual_sites: List["VirtualSite"]
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ virtual_sites = []
+ for virtual_sites_item_data in self.virtual_sites:
+ virtual_sites_item = virtual_sites_item_data.to_dict()
+ virtual_sites.append(virtual_sites_item)
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "virtualSites": virtual_sites,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.virtual_site import VirtualSite
+
+ d = src_dict.copy()
+ virtual_sites = []
+ _virtual_sites = d.pop("virtualSites")
+ for virtual_sites_item_data in _virtual_sites:
+ virtual_sites_item = VirtualSite.from_dict(virtual_sites_item_data)
+
+ virtual_sites.append(virtual_sites_item)
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ list_virtual_sites_response = cls(
+ virtual_sites=virtual_sites,
+ next_page_token=next_page_token,
+ )
+
+ return list_virtual_sites_response
diff --git a/derapi/models/list_virtual_solar_inverters_response.py b/derapi/models/list_virtual_solar_inverters_response.py
new file mode 100644
index 0000000..4c1ad5b
--- /dev/null
+++ b/derapi/models/list_virtual_solar_inverters_response.py
@@ -0,0 +1,64 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.virtual_solar_inverter import VirtualSolarInverter
+
+
+T = TypeVar("T", bound="ListVirtualSolarInvertersResponse")
+
+
+@_attrs_define
+class ListVirtualSolarInvertersResponse:
+ """
+ Attributes:
+ virtual_solar_inverters (List['VirtualSolarInverter']):
+ next_page_token (Union[Unset, str]): A token to request the next page, if any. If absent, there are no more
+ pages.
+ """
+
+ virtual_solar_inverters: List["VirtualSolarInverter"]
+ next_page_token: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ virtual_solar_inverters = []
+ for virtual_solar_inverters_item_data in self.virtual_solar_inverters:
+ virtual_solar_inverters_item = virtual_solar_inverters_item_data.to_dict()
+ virtual_solar_inverters.append(virtual_solar_inverters_item)
+
+ next_page_token = self.next_page_token
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "virtualSolarInverters": virtual_solar_inverters,
+ }
+ )
+ if next_page_token is not UNSET:
+ field_dict["nextPageToken"] = next_page_token
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.virtual_solar_inverter import VirtualSolarInverter
+
+ d = src_dict.copy()
+ virtual_solar_inverters = []
+ _virtual_solar_inverters = d.pop("virtualSolarInverters")
+ for virtual_solar_inverters_item_data in _virtual_solar_inverters:
+ virtual_solar_inverters_item = VirtualSolarInverter.from_dict(virtual_solar_inverters_item_data)
+
+ virtual_solar_inverters.append(virtual_solar_inverters_item)
+
+ next_page_token = d.pop("nextPageToken", UNSET)
+
+ list_virtual_solar_inverters_response = cls(
+ virtual_solar_inverters=virtual_solar_inverters,
+ next_page_token=next_page_token,
+ )
+
+ return list_virtual_solar_inverters_response
diff --git a/derapi/models/put_site_battery_control_request.py b/derapi/models/put_site_battery_control_request.py
new file mode 100644
index 0000000..efceb71
--- /dev/null
+++ b/derapi/models/put_site_battery_control_request.py
@@ -0,0 +1,52 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.put_site_battery_control_request_interval import PutSiteBatteryControlRequestInterval
+
+
+T = TypeVar("T", bound="PutSiteBatteryControlRequest")
+
+
+@_attrs_define
+class PutSiteBatteryControlRequest:
+ """
+ Attributes:
+ intervals (List['PutSiteBatteryControlRequestInterval']):
+ """
+
+ intervals: List["PutSiteBatteryControlRequestInterval"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ intervals = []
+ for intervals_item_data in self.intervals:
+ intervals_item = intervals_item_data.to_dict()
+ intervals.append(intervals_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "intervals": intervals,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.put_site_battery_control_request_interval import PutSiteBatteryControlRequestInterval
+
+ d = src_dict.copy()
+ intervals = []
+ _intervals = d.pop("intervals")
+ for intervals_item_data in _intervals:
+ intervals_item = PutSiteBatteryControlRequestInterval.from_dict(intervals_item_data)
+
+ intervals.append(intervals_item)
+
+ put_site_battery_control_request = cls(
+ intervals=intervals,
+ )
+
+ return put_site_battery_control_request
diff --git a/derapi/models/put_site_battery_control_request_interval.py b/derapi/models/put_site_battery_control_request_interval.py
new file mode 100644
index 0000000..b175973
--- /dev/null
+++ b/derapi/models/put_site_battery_control_request_interval.py
@@ -0,0 +1,107 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.site_battery_control_command import SiteBatteryControlCommand
+from ..models.site_battery_control_priority import SiteBatteryControlPriority
+from ..types import UNSET, Unset
+
+T = TypeVar("T", bound="PutSiteBatteryControlRequestInterval")
+
+
+@_attrs_define
+class PutSiteBatteryControlRequestInterval:
+ """
+ Attributes:
+ command (SiteBatteryControlCommand): discharge, charge, or idle
+ start (datetime.datetime): Interval start in ISO-8601 format
+ end (datetime.datetime): Interval end in ISO-8601 format
+ kw (Union[Unset, float]): discharge rate in kilowatts
+ state_of_charge_limit_percent (Union[Unset, float]): the minimum/maximum state of charge, expressed as a
+ percent, the Battery can be charged/discharged to
+ priority (Union[Unset, SiteBatteryControlPriority]): PV = Prioritize charging the Battery with PV production or,
+ for discharge, prioritize using PV production to meet Site loads first first
B = Prioritize using Battery
+ discharge to meet Site loads first
Load = Prioritize using PV production for Sites loads first, then use
+ excess to charge the Battery
Grid = Prioritize charing with Battery with grid import first
+ allow_export (Union[Unset, bool]): True or False
+ """
+
+ command: SiteBatteryControlCommand
+ start: datetime.datetime
+ end: datetime.datetime
+ kw: Union[Unset, float] = UNSET
+ state_of_charge_limit_percent: Union[Unset, float] = UNSET
+ priority: Union[Unset, SiteBatteryControlPriority] = UNSET
+ allow_export: Union[Unset, bool] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ command = self.command.value
+
+ start = self.start.isoformat()
+
+ end = self.end.isoformat()
+
+ kw = self.kw
+
+ state_of_charge_limit_percent = self.state_of_charge_limit_percent
+
+ priority: Union[Unset, str] = UNSET
+ if not isinstance(self.priority, Unset):
+ priority = self.priority.value
+
+ allow_export = self.allow_export
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "command": command,
+ "start": start,
+ "end": end,
+ }
+ )
+ if kw is not UNSET:
+ field_dict["kw"] = kw
+ if state_of_charge_limit_percent is not UNSET:
+ field_dict["stateOfChargeLimitPercent"] = state_of_charge_limit_percent
+ if priority is not UNSET:
+ field_dict["priority"] = priority
+ if allow_export is not UNSET:
+ field_dict["allowExport"] = allow_export
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ command = SiteBatteryControlCommand(d.pop("command"))
+
+ start = isoparse(d.pop("start"))
+
+ end = isoparse(d.pop("end"))
+
+ kw = d.pop("kw", UNSET)
+
+ state_of_charge_limit_percent = d.pop("stateOfChargeLimitPercent", UNSET)
+
+ _priority = d.pop("priority", UNSET)
+ priority: Union[Unset, SiteBatteryControlPriority]
+ if isinstance(_priority, Unset):
+ priority = UNSET
+ else:
+ priority = SiteBatteryControlPriority(_priority)
+
+ allow_export = d.pop("allowExport", UNSET)
+
+ put_site_battery_control_request_interval = cls(
+ command=command,
+ start=start,
+ end=end,
+ kw=kw,
+ state_of_charge_limit_percent=state_of_charge_limit_percent,
+ priority=priority,
+ allow_export=allow_export,
+ )
+
+ return put_site_battery_control_request_interval
diff --git a/derapi/models/put_site_battery_control_response.py b/derapi/models/put_site_battery_control_response.py
new file mode 100644
index 0000000..01e8cf1
--- /dev/null
+++ b/derapi/models/put_site_battery_control_response.py
@@ -0,0 +1,60 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.site_battery_control_status_interval import SiteBatteryControlStatusInterval
+
+
+T = TypeVar("T", bound="PutSiteBatteryControlResponse")
+
+
+@_attrs_define
+class PutSiteBatteryControlResponse:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ intervals (List['SiteBatteryControlStatusInterval']):
+ """
+
+ id: str
+ intervals: List["SiteBatteryControlStatusInterval"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ intervals = []
+ for intervals_item_data in self.intervals:
+ intervals_item = intervals_item_data.to_dict()
+ intervals.append(intervals_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "intervals": intervals,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.site_battery_control_status_interval import SiteBatteryControlStatusInterval
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ intervals = []
+ _intervals = d.pop("intervals")
+ for intervals_item_data in _intervals:
+ intervals_item = SiteBatteryControlStatusInterval.from_dict(intervals_item_data)
+
+ intervals.append(intervals_item)
+
+ put_site_battery_control_response = cls(
+ id=id,
+ intervals=intervals,
+ )
+
+ return put_site_battery_control_response
diff --git a/derapi/models/site.py b/derapi/models/site.py
new file mode 100644
index 0000000..85736c5
--- /dev/null
+++ b/derapi/models/site.py
@@ -0,0 +1,163 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+
+T = TypeVar("T", bound="Site")
+
+
+@_attrs_define
+class Site:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ vendor (Vendor):
+ name (str): Customer defined name of the Site
+ location_utc_offset (float): UTC Offset in hours; positive values represent locations East of UTC. Please note
+ this field will soon be deprecated, please use `timezone` instead.
+ batteries (List['BatterySummary']): List of Battery IDs associated with this Site
+ solar_inverters (List['SolarInverterSummary']): List of Solar Inverter IDs associated with this Site
+ location (Union[Unset, SiteLocation]): The location of this Solar Inverter in lat/lon coordinates
+ operational_since (Union[Unset, datetime.datetime]): The date the Site became operational or received permission
+ to operate. Sometimes absent for Solaredge.
+ bess (Union[Unset, SiteBESS]): For Sites with Batteries this key is present
+ """
+
+ id: str
+ vendor: Vendor
+ name: str
+ location_utc_offset: float
+ batteries: List["BatterySummary"]
+ solar_inverters: List["SolarInverterSummary"]
+ location: Union[Unset, "SiteLocation"] = UNSET
+ operational_since: Union[Unset, datetime.datetime] = UNSET
+ bess: Union[Unset, "SiteBESS"] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ vendor = self.vendor.value
+
+ name = self.name
+
+ location_utc_offset = self.location_utc_offset
+
+ batteries = []
+ for componentsschemas_site_batteries_item_data in self.batteries:
+ componentsschemas_site_batteries_item = componentsschemas_site_batteries_item_data.to_dict()
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ for componentsschemas_site_solar_inverters_item_data in self.solar_inverters:
+ componentsschemas_site_solar_inverters_item = componentsschemas_site_solar_inverters_item_data.to_dict()
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ location: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.location, Unset):
+ location = self.location.to_dict()
+
+ operational_since: Union[Unset, str] = UNSET
+ if not isinstance(self.operational_since, Unset):
+ operational_since = self.operational_since.isoformat()
+
+ bess: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.bess, Unset):
+ bess = self.bess.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "name": name,
+ "locationUTCOffset": location_utc_offset,
+ "batteries": batteries,
+ "solarInverters": solar_inverters,
+ }
+ )
+ if location is not UNSET:
+ field_dict["location"] = location
+ if operational_since is not UNSET:
+ field_dict["operationalSince"] = operational_since
+ if bess is not UNSET:
+ field_dict["bess"] = bess
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ name = d.pop("name")
+
+ location_utc_offset = d.pop("locationUTCOffset")
+
+ batteries = []
+ _batteries = d.pop("batteries")
+ for componentsschemas_site_batteries_item_data in _batteries:
+ componentsschemas_site_batteries_item = BatterySummary.from_dict(componentsschemas_site_batteries_item_data)
+
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ _solar_inverters = d.pop("solarInverters")
+ for componentsschemas_site_solar_inverters_item_data in _solar_inverters:
+ componentsschemas_site_solar_inverters_item = SolarInverterSummary.from_dict(
+ componentsschemas_site_solar_inverters_item_data
+ )
+
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ _location = d.pop("location", UNSET)
+ location: Union[Unset, SiteLocation]
+ if isinstance(_location, Unset):
+ location = UNSET
+ else:
+ location = SiteLocation.from_dict(_location)
+
+ _operational_since = d.pop("operationalSince", UNSET)
+ operational_since: Union[Unset, datetime.datetime]
+ if isinstance(_operational_since, Unset):
+ operational_since = UNSET
+ else:
+ operational_since = isoparse(_operational_since)
+
+ _bess = d.pop("bess", UNSET)
+ bess: Union[Unset, SiteBESS]
+ if isinstance(_bess, Unset):
+ bess = UNSET
+ else:
+ bess = SiteBESS.from_dict(_bess)
+
+ site = cls(
+ id=id,
+ vendor=vendor,
+ name=name,
+ location_utc_offset=location_utc_offset,
+ batteries=batteries,
+ solar_inverters=solar_inverters,
+ location=location,
+ operational_since=operational_since,
+ bess=bess,
+ )
+
+ return site
diff --git a/derapi/models/site_battery_control_command.py b/derapi/models/site_battery_control_command.py
new file mode 100644
index 0000000..f67de5c
--- /dev/null
+++ b/derapi/models/site_battery_control_command.py
@@ -0,0 +1,10 @@
+from enum import Enum
+
+
+class SiteBatteryControlCommand(str, Enum):
+ CHARGE = "charge"
+ DISCHARGE = "discharge"
+ IDLE = "idle"
+
+ def __str__(self) -> str:
+ return str(self.value)
diff --git a/derapi/models/site_battery_control_priority.py b/derapi/models/site_battery_control_priority.py
new file mode 100644
index 0000000..e7efc7c
--- /dev/null
+++ b/derapi/models/site_battery_control_priority.py
@@ -0,0 +1,11 @@
+from enum import Enum
+
+
+class SiteBatteryControlPriority(str, Enum):
+ B = "B"
+ GRID = "Grid"
+ LOAD = "Load"
+ PV = "PV"
+
+ def __str__(self) -> str:
+ return str(self.value)
diff --git a/derapi/models/site_battery_control_status.py b/derapi/models/site_battery_control_status.py
new file mode 100644
index 0000000..a5b1dff
--- /dev/null
+++ b/derapi/models/site_battery_control_status.py
@@ -0,0 +1,60 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.site_battery_control_status_interval import SiteBatteryControlStatusInterval
+
+
+T = TypeVar("T", bound="SiteBatteryControlStatus")
+
+
+@_attrs_define
+class SiteBatteryControlStatus:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ intervals (List['SiteBatteryControlStatusInterval']):
+ """
+
+ id: str
+ intervals: List["SiteBatteryControlStatusInterval"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ intervals = []
+ for intervals_item_data in self.intervals:
+ intervals_item = intervals_item_data.to_dict()
+ intervals.append(intervals_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "intervals": intervals,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.site_battery_control_status_interval import SiteBatteryControlStatusInterval
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ intervals = []
+ _intervals = d.pop("intervals")
+ for intervals_item_data in _intervals:
+ intervals_item = SiteBatteryControlStatusInterval.from_dict(intervals_item_data)
+
+ intervals.append(intervals_item)
+
+ site_battery_control_status = cls(
+ id=id,
+ intervals=intervals,
+ )
+
+ return site_battery_control_status
diff --git a/derapi/models/site_battery_control_status_interval.py b/derapi/models/site_battery_control_status_interval.py
new file mode 100644
index 0000000..55fa08d
--- /dev/null
+++ b/derapi/models/site_battery_control_status_interval.py
@@ -0,0 +1,128 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.site_battery_control_priority import SiteBatteryControlPriority
+from ..models.site_battery_control_status_interval_site_battery_control_status_interval_command import (
+ SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand,
+)
+from ..types import UNSET, Unset
+
+T = TypeVar("T", bound="SiteBatteryControlStatusInterval")
+
+
+@_attrs_define
+class SiteBatteryControlStatusInterval:
+ """
+ Attributes:
+ command (SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand): discharge, charge, or idle
+ Default: SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand.DISCHARGE.
+ start (datetime.datetime): Interval start in ISO-8601 format
+ end (datetime.datetime): Interval end in ISO-8601 format
+ status (str): Vendor provided command status
+ reported_at (datetime.datetime): The date this control status update is provided
+ kw (Union[Unset, float]): discharge rate in kilowatts
+ state_of_charge_limit_percent (Union[Unset, float]): the minimum/maximum state of charge, expressed as a
+ percent, the Battery can be charged/discharged to
+ priority (Union[Unset, SiteBatteryControlPriority]): PV = Prioritize charging the Battery with PV production or,
+ for discharge, prioritize using PV production to meet Site loads first first
B = Prioritize using Battery
+ discharge to meet Site loads first
Load = Prioritize using PV production for Sites loads first, then use
+ excess to charge the Battery
Grid = Prioritize charing with Battery with grid import first
+ allow_export (Union[Unset, bool]): True or False
+ """
+
+ start: datetime.datetime
+ end: datetime.datetime
+ status: str
+ reported_at: datetime.datetime
+ command: SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand = (
+ SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand.DISCHARGE
+ )
+ kw: Union[Unset, float] = UNSET
+ state_of_charge_limit_percent: Union[Unset, float] = UNSET
+ priority: Union[Unset, SiteBatteryControlPriority] = UNSET
+ allow_export: Union[Unset, bool] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ command = self.command.value
+
+ start = self.start.isoformat()
+
+ end = self.end.isoformat()
+
+ status = self.status
+
+ reported_at = self.reported_at.isoformat()
+
+ kw = self.kw
+
+ state_of_charge_limit_percent = self.state_of_charge_limit_percent
+
+ priority: Union[Unset, str] = UNSET
+ if not isinstance(self.priority, Unset):
+ priority = self.priority.value
+
+ allow_export = self.allow_export
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "command": command,
+ "start": start,
+ "end": end,
+ "status": status,
+ "reportedAt": reported_at,
+ }
+ )
+ if kw is not UNSET:
+ field_dict["kw"] = kw
+ if state_of_charge_limit_percent is not UNSET:
+ field_dict["stateOfChargeLimitPercent"] = state_of_charge_limit_percent
+ if priority is not UNSET:
+ field_dict["priority"] = priority
+ if allow_export is not UNSET:
+ field_dict["allowExport"] = allow_export
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ command = SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand(d.pop("command"))
+
+ start = isoparse(d.pop("start"))
+
+ end = isoparse(d.pop("end"))
+
+ status = d.pop("status")
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ kw = d.pop("kw", UNSET)
+
+ state_of_charge_limit_percent = d.pop("stateOfChargeLimitPercent", UNSET)
+
+ _priority = d.pop("priority", UNSET)
+ priority: Union[Unset, SiteBatteryControlPriority]
+ if isinstance(_priority, Unset):
+ priority = UNSET
+ else:
+ priority = SiteBatteryControlPriority(_priority)
+
+ allow_export = d.pop("allowExport", UNSET)
+
+ site_battery_control_status_interval = cls(
+ command=command,
+ start=start,
+ end=end,
+ status=status,
+ reported_at=reported_at,
+ kw=kw,
+ state_of_charge_limit_percent=state_of_charge_limit_percent,
+ priority=priority,
+ allow_export=allow_export,
+ )
+
+ return site_battery_control_status_interval
diff --git a/derapi/models/site_battery_control_status_interval_site_battery_control_status_interval_command.py b/derapi/models/site_battery_control_status_interval_site_battery_control_status_interval_command.py
new file mode 100644
index 0000000..5c000dd
--- /dev/null
+++ b/derapi/models/site_battery_control_status_interval_site_battery_control_status_interval_command.py
@@ -0,0 +1,10 @@
+from enum import Enum
+
+
+class SiteBatteryControlStatusIntervalSiteBatteryControlStatusIntervalCommand(str, Enum):
+ CHARGE = "charge"
+ DISCHARGE = "discharge"
+ IDLE = "idle"
+
+ def __str__(self) -> str:
+ return str(self.value)
diff --git a/derapi/models/site_battery_interval.py b/derapi/models/site_battery_interval.py
new file mode 100644
index 0000000..dea6fab
--- /dev/null
+++ b/derapi/models/site_battery_interval.py
@@ -0,0 +1,78 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..types import UNSET, Unset
+
+T = TypeVar("T", bound="SiteBatteryInterval")
+
+
+@_attrs_define
+class SiteBatteryInterval:
+ """
+ Attributes:
+ charge_kwh (float): kWh into the Battery system (i.e. energy into all the Batteries in the system) during the
+ interval
+ discharge_kwh (float): kWh out of the Battery system (i.e. energy discharged from all the Batteries in the
+ system) during the interval
+ start (datetime.datetime): Interval start in ISO-8601 format
+ end (datetime.datetime): Interval end in ISO-8601 format
+ state_of_charge_percent (Union[Unset, float]): average % charge over the interval for all Batteries in the
+ system
+ """
+
+ charge_kwh: float
+ discharge_kwh: float
+ start: datetime.datetime
+ end: datetime.datetime
+ state_of_charge_percent: Union[Unset, float] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ charge_kwh = self.charge_kwh
+
+ discharge_kwh = self.discharge_kwh
+
+ start = self.start.isoformat()
+
+ end = self.end.isoformat()
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "chargeKwh": charge_kwh,
+ "dischargeKwh": discharge_kwh,
+ "start": start,
+ "end": end,
+ }
+ )
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ charge_kwh = d.pop("chargeKwh")
+
+ discharge_kwh = d.pop("dischargeKwh")
+
+ start = isoparse(d.pop("start"))
+
+ end = isoparse(d.pop("end"))
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ site_battery_interval = cls(
+ charge_kwh=charge_kwh,
+ discharge_kwh=discharge_kwh,
+ start=start,
+ end=end,
+ state_of_charge_percent=state_of_charge_percent,
+ )
+
+ return site_battery_interval
diff --git a/derapi/models/site_bess.py b/derapi/models/site_bess.py
new file mode 100644
index 0000000..924d966
--- /dev/null
+++ b/derapi/models/site_bess.py
@@ -0,0 +1,57 @@
+from typing import Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+T = TypeVar("T", bound="SiteBESS")
+
+
+@_attrs_define
+class SiteBESS:
+ """For Sites with Batteries this key is present
+
+ Attributes:
+ nameplate_kwh (Union[Unset, float]): The rated storage capacity of the system in kWh
+ mode (Union[Unset, str]): Battery management system mode
+ state_of_charge_percent (Union[Unset, float]): Battery system state of charge as a percent of capacity
+ """
+
+ nameplate_kwh: Union[Unset, float] = UNSET
+ mode: Union[Unset, str] = UNSET
+ state_of_charge_percent: Union[Unset, float] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ nameplate_kwh = self.nameplate_kwh
+
+ mode = self.mode
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update({})
+ if nameplate_kwh is not UNSET:
+ field_dict["nameplateKwh"] = nameplate_kwh
+ if mode is not UNSET:
+ field_dict["mode"] = mode
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ nameplate_kwh = d.pop("nameplateKwh", UNSET)
+
+ mode = d.pop("mode", UNSET)
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ site_bess = cls(
+ nameplate_kwh=nameplate_kwh,
+ mode=mode,
+ state_of_charge_percent=state_of_charge_percent,
+ )
+
+ return site_bess
diff --git a/derapi/models/site_location.py b/derapi/models/site_location.py
new file mode 100644
index 0000000..88d72a9
--- /dev/null
+++ b/derapi/models/site_location.py
@@ -0,0 +1,69 @@
+from typing import Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+T = TypeVar("T", bound="SiteLocation")
+
+
+@_attrs_define
+class SiteLocation:
+ """The location of this Solar Inverter in lat/lon coordinates
+
+ Attributes:
+ current_utc_offset (float): UTC Offset in (possibly fractional) hours; positive values represent locations East
+ of UTC
+ lat (Union[Unset, float]): Latitude coordinate of the inverter
+ lon (Union[Unset, float]): Longitude coordinate of the inverter
+ timezone (Union[Unset, str]): IANA timezone string
+ """
+
+ current_utc_offset: float
+ lat: Union[Unset, float] = UNSET
+ lon: Union[Unset, float] = UNSET
+ timezone: Union[Unset, str] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ current_utc_offset = self.current_utc_offset
+
+ lat = self.lat
+
+ lon = self.lon
+
+ timezone = self.timezone
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "currentUTCOffset": current_utc_offset,
+ }
+ )
+ if lat is not UNSET:
+ field_dict["lat"] = lat
+ if lon is not UNSET:
+ field_dict["lon"] = lon
+ if timezone is not UNSET:
+ field_dict["timezone"] = timezone
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ current_utc_offset = d.pop("currentUTCOffset")
+
+ lat = d.pop("lat", UNSET)
+
+ lon = d.pop("lon", UNSET)
+
+ timezone = d.pop("timezone", UNSET)
+
+ site_location = cls(
+ current_utc_offset=current_utc_offset,
+ lat=lat,
+ lon=lon,
+ timezone=timezone,
+ )
+
+ return site_location
diff --git a/derapi/models/site_solar_inverter_interval.py b/derapi/models/site_solar_inverter_interval.py
new file mode 100644
index 0000000..39b7caf
--- /dev/null
+++ b/derapi/models/site_solar_inverter_interval.py
@@ -0,0 +1,56 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+T = TypeVar("T", bound="SiteSolarInverterInterval")
+
+
+@_attrs_define
+class SiteSolarInverterInterval:
+ """
+ Attributes:
+ kwh (float): Solar energy production in kWh
+ start (datetime.datetime): Interval start in ISO-8601 format
+ end (datetime.datetime): Interval end in ISO-8601 format
+ """
+
+ kwh: float
+ start: datetime.datetime
+ end: datetime.datetime
+
+ def to_dict(self) -> Dict[str, Any]:
+ kwh = self.kwh
+
+ start = self.start.isoformat()
+
+ end = self.end.isoformat()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "kwh": kwh,
+ "start": start,
+ "end": end,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ kwh = d.pop("kwh")
+
+ start = isoparse(d.pop("start"))
+
+ end = isoparse(d.pop("end"))
+
+ site_solar_inverter_interval = cls(
+ kwh=kwh,
+ start=start,
+ end=end,
+ )
+
+ return site_solar_inverter_interval
diff --git a/derapi/models/site_summary.py b/derapi/models/site_summary.py
new file mode 100644
index 0000000..3012a28
--- /dev/null
+++ b/derapi/models/site_summary.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SiteSummary")
+
+
+@_attrs_define
+class SiteSummary:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ """
+
+ id: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ site_summary = cls(
+ id=id,
+ )
+
+ return site_summary
diff --git a/derapi/models/sma_custom_grant_credentials.py b/derapi/models/sma_custom_grant_credentials.py
new file mode 100644
index 0000000..17d637e
--- /dev/null
+++ b/derapi/models/sma_custom_grant_credentials.py
@@ -0,0 +1,67 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SMACustomGrantCredentials")
+
+
+@_attrs_define
+class SMACustomGrantCredentials:
+ """Credentials from the SMA custom grant oauth flow
+
+ Attributes:
+ vendor (Literal['sma']): Default: 'sma'.
+ type (Literal['customgrant']): Default: 'customgrant'.
+ client_id (str): SMA Client ID
+ client_secret (str): SMA Client Secret
+ """
+
+ client_id: str
+ client_secret: str
+ vendor: Literal["sma"] = "sma"
+ type: Literal["customgrant"] = "customgrant"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["sma"], d.pop("vendor"))
+ if vendor != "sma":
+ raise ValueError(f"vendor must match const 'sma', got '{vendor}'")
+
+ type = cast(Literal["customgrant"], d.pop("type"))
+ if type != "customgrant":
+ raise ValueError(f"type must match const 'customgrant', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ sma_custom_grant_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return sma_custom_grant_credentials
diff --git a/derapi/models/sma_join_config.py b/derapi/models/sma_join_config.py
new file mode 100644
index 0000000..d57c63f
--- /dev/null
+++ b/derapi/models/sma_join_config.py
@@ -0,0 +1,77 @@
+from typing import TYPE_CHECKING, Any, Dict, Literal, Type, TypeVar, Union, cast
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.sma_join_config_inline_credentials import SMAJoinConfigInlineCredentials
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+
+
+T = TypeVar("T", bound="SMAJoinConfig")
+
+
+@_attrs_define
+class SMAJoinConfig:
+ """
+ Attributes:
+ vendor (Literal['sma']):
+ credentials (Union['SMAJoinConfigInlineCredentials', 'StoredCredentialsReference']):
+ """
+
+ vendor: Literal["sma"]
+ credentials: Union["SMAJoinConfigInlineCredentials", "StoredCredentialsReference"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.sma_join_config_inline_credentials import SMAJoinConfigInlineCredentials
+
+ vendor = self.vendor
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, SMAJoinConfigInlineCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "credentials": credentials,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.sma_join_config_inline_credentials import SMAJoinConfigInlineCredentials
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+
+ d = src_dict.copy()
+ vendor = cast(Literal["sma"], d.pop("vendor"))
+ if vendor != "sma":
+ raise ValueError(f"vendor must match const 'sma', got '{vendor}'")
+
+ def _parse_credentials(data: object) -> Union["SMAJoinConfigInlineCredentials", "StoredCredentialsReference"]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ credentials_type_0 = SMAJoinConfigInlineCredentials.from_dict(data)
+
+ return credentials_type_0
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ credentials_type_1 = StoredCredentialsReference.from_dict(data)
+
+ return credentials_type_1
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ sma_join_config = cls(
+ vendor=vendor,
+ credentials=credentials,
+ )
+
+ return sma_join_config
diff --git a/derapi/models/sma_join_config_inline_credentials.py b/derapi/models/sma_join_config_inline_credentials.py
new file mode 100644
index 0000000..837db9c
--- /dev/null
+++ b/derapi/models/sma_join_config_inline_credentials.py
@@ -0,0 +1,46 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SMAJoinConfigInlineCredentials")
+
+
+@_attrs_define
+class SMAJoinConfigInlineCredentials:
+ """
+ Attributes:
+ client_id (str): SMA Client ID
+ client_secret (str): SMA Client Secret
+ """
+
+ client_id: str
+ client_secret: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ sma_join_config_inline_credentials = cls(
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return sma_join_config_inline_credentials
diff --git a/derapi/models/sma_sandbox_custom_grant_credentials.py b/derapi/models/sma_sandbox_custom_grant_credentials.py
new file mode 100644
index 0000000..0c6d5cf
--- /dev/null
+++ b/derapi/models/sma_sandbox_custom_grant_credentials.py
@@ -0,0 +1,67 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SMASandboxCustomGrantCredentials")
+
+
+@_attrs_define
+class SMASandboxCustomGrantCredentials:
+ """Credentials from the SMA Sandbox custom grant oauth flow
+
+ Attributes:
+ vendor (Literal['smasbox']): Default: 'smasbox'.
+ type (Literal['customgrant']): Default: 'customgrant'.
+ client_id (str): SMA Sandbox Client ID
+ client_secret (str): SMA Sandbox Client Secret
+ """
+
+ client_id: str
+ client_secret: str
+ vendor: Literal["smasbox"] = "smasbox"
+ type: Literal["customgrant"] = "customgrant"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["smasbox"], d.pop("vendor"))
+ if vendor != "smasbox":
+ raise ValueError(f"vendor must match const 'smasbox', got '{vendor}'")
+
+ type = cast(Literal["customgrant"], d.pop("type"))
+ if type != "customgrant":
+ raise ValueError(f"type must match const 'customgrant', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ sma_sandbox_custom_grant_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return sma_sandbox_custom_grant_credentials
diff --git a/derapi/models/sma_sandbox_join_config.py b/derapi/models/sma_sandbox_join_config.py
new file mode 100644
index 0000000..ad0e7a1
--- /dev/null
+++ b/derapi/models/sma_sandbox_join_config.py
@@ -0,0 +1,79 @@
+from typing import TYPE_CHECKING, Any, Dict, Literal, Type, TypeVar, Union, cast
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.sma_sandbox_join_config_inline_credentials import SMASandboxJoinConfigInlineCredentials
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+
+
+T = TypeVar("T", bound="SMASandboxJoinConfig")
+
+
+@_attrs_define
+class SMASandboxJoinConfig:
+ """
+ Attributes:
+ vendor (Literal['smasbox']):
+ credentials (Union['SMASandboxJoinConfigInlineCredentials', 'StoredCredentialsReference']):
+ """
+
+ vendor: Literal["smasbox"]
+ credentials: Union["SMASandboxJoinConfigInlineCredentials", "StoredCredentialsReference"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.sma_sandbox_join_config_inline_credentials import SMASandboxJoinConfigInlineCredentials
+
+ vendor = self.vendor
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, SMASandboxJoinConfigInlineCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "credentials": credentials,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.sma_sandbox_join_config_inline_credentials import SMASandboxJoinConfigInlineCredentials
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+
+ d = src_dict.copy()
+ vendor = cast(Literal["smasbox"], d.pop("vendor"))
+ if vendor != "smasbox":
+ raise ValueError(f"vendor must match const 'smasbox', got '{vendor}'")
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union["SMASandboxJoinConfigInlineCredentials", "StoredCredentialsReference"]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ credentials_type_0 = SMASandboxJoinConfigInlineCredentials.from_dict(data)
+
+ return credentials_type_0
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ credentials_type_1 = StoredCredentialsReference.from_dict(data)
+
+ return credentials_type_1
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ sma_sandbox_join_config = cls(
+ vendor=vendor,
+ credentials=credentials,
+ )
+
+ return sma_sandbox_join_config
diff --git a/derapi/models/sma_sandbox_join_config_inline_credentials.py b/derapi/models/sma_sandbox_join_config_inline_credentials.py
new file mode 100644
index 0000000..06a8556
--- /dev/null
+++ b/derapi/models/sma_sandbox_join_config_inline_credentials.py
@@ -0,0 +1,46 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SMASandboxJoinConfigInlineCredentials")
+
+
+@_attrs_define
+class SMASandboxJoinConfigInlineCredentials:
+ """
+ Attributes:
+ client_id (str): SMA Sandbox Client ID
+ client_secret (str): SMA Sandbox Client Secret
+ """
+
+ client_id: str
+ client_secret: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ sma_sandbox_join_config_inline_credentials = cls(
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return sma_sandbox_join_config_inline_credentials
diff --git a/derapi/models/sma_sandbox_o_auth_credentials.py b/derapi/models/sma_sandbox_o_auth_credentials.py
new file mode 100644
index 0000000..e3eff68
--- /dev/null
+++ b/derapi/models/sma_sandbox_o_auth_credentials.py
@@ -0,0 +1,67 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SMASandboxOAuthCredentials")
+
+
+@_attrs_define
+class SMASandboxOAuthCredentials:
+ """Credentials from the SMA Sandbox OAuth code grant flow
+
+ Attributes:
+ vendor (Literal['smasbox']): Default: 'smasbox'.
+ type (Literal['oauthclient']): Default: 'oauthclient'.
+ client_id (str): SMA Sandbox Client ID
+ client_secret (str): SMA Sandbox Client Secret
+ """
+
+ client_id: str
+ client_secret: str
+ vendor: Literal["smasbox"] = "smasbox"
+ type: Literal["oauthclient"] = "oauthclient"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["smasbox"], d.pop("vendor"))
+ if vendor != "smasbox":
+ raise ValueError(f"vendor must match const 'smasbox', got '{vendor}'")
+
+ type = cast(Literal["oauthclient"], d.pop("type"))
+ if type != "oauthclient":
+ raise ValueError(f"type must match const 'oauthclient', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ sma_sandbox_o_auth_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return sma_sandbox_o_auth_credentials
diff --git a/derapi/models/smao_auth_credentials.py b/derapi/models/smao_auth_credentials.py
new file mode 100644
index 0000000..febf861
--- /dev/null
+++ b/derapi/models/smao_auth_credentials.py
@@ -0,0 +1,67 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SMAOAuthCredentials")
+
+
+@_attrs_define
+class SMAOAuthCredentials:
+ """Credentials from the SMA OAuth code grant flow
+
+ Attributes:
+ vendor (Literal['sma']): Default: 'sma'.
+ type (Literal['oauthclient']): Default: 'oauthclient'.
+ client_id (str): SMA Client ID
+ client_secret (str): SMA Client Secret
+ """
+
+ client_id: str
+ client_secret: str
+ vendor: Literal["sma"] = "sma"
+ type: Literal["oauthclient"] = "oauthclient"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["sma"], d.pop("vendor"))
+ if vendor != "sma":
+ raise ValueError(f"vendor must match const 'sma', got '{vendor}'")
+
+ type = cast(Literal["oauthclient"], d.pop("type"))
+ if type != "oauthclient":
+ raise ValueError(f"type must match const 'oauthclient', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ smao_auth_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return smao_auth_credentials
diff --git a/derapi/models/solar_edge_credentials.py b/derapi/models/solar_edge_credentials.py
new file mode 100644
index 0000000..d06d9c8
--- /dev/null
+++ b/derapi/models/solar_edge_credentials.py
@@ -0,0 +1,58 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SolarEdgeCredentials")
+
+
+@_attrs_define
+class SolarEdgeCredentials:
+ """
+ Attributes:
+ vendor (Literal['solaredge']): Default: 'solaredge'.
+ type (Literal['apikey']): Default: 'apikey'.
+ api_key (str): SolarEdge API Key
+ """
+
+ api_key: str
+ vendor: Literal["solaredge"] = "solaredge"
+ type: Literal["apikey"] = "apikey"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ api_key = self.api_key
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "apiKey": api_key,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["solaredge"], d.pop("vendor"))
+ if vendor != "solaredge":
+ raise ValueError(f"vendor must match const 'solaredge', got '{vendor}'")
+
+ type = cast(Literal["apikey"], d.pop("type"))
+ if type != "apikey":
+ raise ValueError(f"type must match const 'apikey', got '{type}'")
+
+ api_key = d.pop("apiKey")
+
+ solar_edge_credentials = cls(
+ vendor=vendor,
+ type=type,
+ api_key=api_key,
+ )
+
+ return solar_edge_credentials
diff --git a/derapi/models/solar_inverter.py b/derapi/models/solar_inverter.py
new file mode 100644
index 0000000..7296aab
--- /dev/null
+++ b/derapi/models/solar_inverter.py
@@ -0,0 +1,249 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+
+T = TypeVar("T", bound="SolarInverter")
+
+
+@_attrs_define
+class SolarInverter:
+ """
+ Attributes:
+ id (str): ID of the solar inverter
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format
+ model (str): Model number of this Solar Inverter
+ serial_number (str): Manufacturer serial number of this Solar Inverter
+ site_id (str): The Derapi Site ID this Solar Inverter is associated with
+ name (Union[Unset, str]): Customer defined name of this Solar Inverter
+ recent_production (Union[Unset, SolarInverterRecentProduction]):
+ lifetime_production (Union[Unset, SolarInverterLifetimeProduction]):
+ recent_errors (Union[Unset, List[Union['SolarInverterRecentErrorsError', 'SolarInverterRecentErrorsInfo',
+ 'SolarInverterRecentErrorsStart', 'SolarInverterRecentErrorsWarning']]]): Most recent errors, warnings, or info
+ reported by the manufacturer for this Solar Inverter. The key represents the severity level
+ (info/warning/error); the value is a string description. start is always present and is the last element to be
+ returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ recent_production: Union[Unset, "SolarInverterRecentProduction"] = UNSET
+ lifetime_production: Union[Unset, "SolarInverterLifetimeProduction"] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ recent_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.recent_production, Unset):
+ recent_production = self.recent_production.to_dict()
+
+ lifetime_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.lifetime_production, Unset):
+ lifetime_production = self.lifetime_production.to_dict()
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_solar_inverter_recent_errors_item_data in self.recent_errors:
+ componentsschemas_solar_inverter_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsError):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsWarning
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsInfo
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if recent_production is not UNSET:
+ field_dict["recentProduction"] = recent_production
+ if lifetime_production is not UNSET:
+ field_dict["lifetimeProduction"] = lifetime_production
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ _recent_production = d.pop("recentProduction", UNSET)
+ recent_production: Union[Unset, SolarInverterRecentProduction]
+ if isinstance(_recent_production, Unset):
+ recent_production = UNSET
+ else:
+ recent_production = SolarInverterRecentProduction.from_dict(_recent_production)
+
+ _lifetime_production = d.pop("lifetimeProduction", UNSET)
+ lifetime_production: Union[Unset, SolarInverterLifetimeProduction]
+ if isinstance(_lifetime_production, Unset):
+ lifetime_production = UNSET
+ else:
+ lifetime_production = SolarInverterLifetimeProduction.from_dict(_lifetime_production)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_solar_inverter_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_solar_inverter_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_0 = (
+ SolarInverterRecentErrorsError.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_1 = (
+ SolarInverterRecentErrorsWarning.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_2 = (
+ SolarInverterRecentErrorsInfo.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_3 = SolarInverterRecentErrorsStart.from_dict(
+ data
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_3
+
+ componentsschemas_solar_inverter_recent_errors_item = (
+ _parse_componentsschemas_solar_inverter_recent_errors_item(
+ componentsschemas_solar_inverter_recent_errors_item_data
+ )
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ solar_inverter = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ recent_production=recent_production,
+ lifetime_production=lifetime_production,
+ recent_errors=recent_errors,
+ )
+
+ return solar_inverter
diff --git a/derapi/models/solar_inverter_interval.py b/derapi/models/solar_inverter_interval.py
new file mode 100644
index 0000000..45994a6
--- /dev/null
+++ b/derapi/models/solar_inverter_interval.py
@@ -0,0 +1,56 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+T = TypeVar("T", bound="SolarInverterInterval")
+
+
+@_attrs_define
+class SolarInverterInterval:
+ """
+ Attributes:
+ kwh (float): Solar energy production in kWh
+ start (datetime.datetime): Interval start in ISO-8601 format
+ end (datetime.datetime): Interval end in ISO-8601 format
+ """
+
+ kwh: float
+ start: datetime.datetime
+ end: datetime.datetime
+
+ def to_dict(self) -> Dict[str, Any]:
+ kwh = self.kwh
+
+ start = self.start.isoformat()
+
+ end = self.end.isoformat()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "kwh": kwh,
+ "start": start,
+ "end": end,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ kwh = d.pop("kwh")
+
+ start = isoparse(d.pop("start"))
+
+ end = isoparse(d.pop("end"))
+
+ solar_inverter_interval = cls(
+ kwh=kwh,
+ start=start,
+ end=end,
+ )
+
+ return solar_inverter_interval
diff --git a/derapi/models/solar_inverter_lifetime_production.py b/derapi/models/solar_inverter_lifetime_production.py
new file mode 100644
index 0000000..31033c0
--- /dev/null
+++ b/derapi/models/solar_inverter_lifetime_production.py
@@ -0,0 +1,65 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar, Union, cast
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+T = TypeVar("T", bound="SolarInverterLifetimeProduction")
+
+
+@_attrs_define
+class SolarInverterLifetimeProduction:
+ """
+ Attributes:
+ kwh (float): Lifetime production value in kWh
+ start (Union[None, datetime.datetime]): The start date of the lifetime production period in ISO-8601 format
+ """
+
+ kwh: float
+ start: Union[None, datetime.datetime]
+
+ def to_dict(self) -> Dict[str, Any]:
+ kwh = self.kwh
+
+ start: Union[None, str]
+ if isinstance(self.start, datetime.datetime):
+ start = self.start.isoformat()
+ else:
+ start = self.start
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "kwh": kwh,
+ "start": start,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ kwh = d.pop("kwh")
+
+ def _parse_start(data: object) -> Union[None, datetime.datetime]:
+ if data is None:
+ return data
+ try:
+ if not isinstance(data, str):
+ raise TypeError()
+ start_type_0 = isoparse(data)
+
+ return start_type_0
+ except: # noqa: E722
+ pass
+ return cast(Union[None, datetime.datetime], data)
+
+ start = _parse_start(d.pop("start"))
+
+ solar_inverter_lifetime_production = cls(
+ kwh=kwh,
+ start=start,
+ )
+
+ return solar_inverter_lifetime_production
diff --git a/derapi/models/solar_inverter_recent_errors_error.py b/derapi/models/solar_inverter_recent_errors_error.py
new file mode 100644
index 0000000..b7e7255
--- /dev/null
+++ b/derapi/models/solar_inverter_recent_errors_error.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SolarInverterRecentErrorsError")
+
+
+@_attrs_define
+class SolarInverterRecentErrorsError:
+ """
+ Attributes:
+ error (str):
+ """
+
+ error: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ error = self.error
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "error": error,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ error = d.pop("error")
+
+ solar_inverter_recent_errors_error = cls(
+ error=error,
+ )
+
+ return solar_inverter_recent_errors_error
diff --git a/derapi/models/solar_inverter_recent_errors_info.py b/derapi/models/solar_inverter_recent_errors_info.py
new file mode 100644
index 0000000..3be40d3
--- /dev/null
+++ b/derapi/models/solar_inverter_recent_errors_info.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SolarInverterRecentErrorsInfo")
+
+
+@_attrs_define
+class SolarInverterRecentErrorsInfo:
+ """
+ Attributes:
+ info (str):
+ """
+
+ info: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ info = self.info
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "info": info,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ info = d.pop("info")
+
+ solar_inverter_recent_errors_info = cls(
+ info=info,
+ )
+
+ return solar_inverter_recent_errors_info
diff --git a/derapi/models/solar_inverter_recent_errors_start.py b/derapi/models/solar_inverter_recent_errors_start.py
new file mode 100644
index 0000000..8897b9c
--- /dev/null
+++ b/derapi/models/solar_inverter_recent_errors_start.py
@@ -0,0 +1,40 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+T = TypeVar("T", bound="SolarInverterRecentErrorsStart")
+
+
+@_attrs_define
+class SolarInverterRecentErrorsStart:
+ """
+ Attributes:
+ start (datetime.datetime): The start date of the recent errors log in ISO-8601 format
+ """
+
+ start: datetime.datetime
+
+ def to_dict(self) -> Dict[str, Any]:
+ start = self.start.isoformat()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "start": start,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ start = isoparse(d.pop("start"))
+
+ solar_inverter_recent_errors_start = cls(
+ start=start,
+ )
+
+ return solar_inverter_recent_errors_start
diff --git a/derapi/models/solar_inverter_recent_errors_warning.py b/derapi/models/solar_inverter_recent_errors_warning.py
new file mode 100644
index 0000000..303cbda
--- /dev/null
+++ b/derapi/models/solar_inverter_recent_errors_warning.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SolarInverterRecentErrorsWarning")
+
+
+@_attrs_define
+class SolarInverterRecentErrorsWarning:
+ """
+ Attributes:
+ warning (str):
+ """
+
+ warning: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ warning = self.warning
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "warning": warning,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ warning = d.pop("warning")
+
+ solar_inverter_recent_errors_warning = cls(
+ warning=warning,
+ )
+
+ return solar_inverter_recent_errors_warning
diff --git a/derapi/models/solar_inverter_recent_production.py b/derapi/models/solar_inverter_recent_production.py
new file mode 100644
index 0000000..bfa2029
--- /dev/null
+++ b/derapi/models/solar_inverter_recent_production.py
@@ -0,0 +1,48 @@
+import datetime
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+T = TypeVar("T", bound="SolarInverterRecentProduction")
+
+
+@_attrs_define
+class SolarInverterRecentProduction:
+ """
+ Attributes:
+ kwh (float): Recent production value in kWh
+ start (datetime.datetime): The start date of the recent production period in ISO-8601 format
+ """
+
+ kwh: float
+ start: datetime.datetime
+
+ def to_dict(self) -> Dict[str, Any]:
+ kwh = self.kwh
+
+ start = self.start.isoformat()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "kwh": kwh,
+ "start": start,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ kwh = d.pop("kwh")
+
+ start = isoparse(d.pop("start"))
+
+ solar_inverter_recent_production = cls(
+ kwh=kwh,
+ start=start,
+ )
+
+ return solar_inverter_recent_production
diff --git a/derapi/models/solar_inverter_summary.py b/derapi/models/solar_inverter_summary.py
new file mode 100644
index 0000000..ce3986f
--- /dev/null
+++ b/derapi/models/solar_inverter_summary.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SolarInverterSummary")
+
+
+@_attrs_define
+class SolarInverterSummary:
+ """
+ Attributes:
+ id (str): ID of the solar inverter
+ """
+
+ id: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ solar_inverter_summary = cls(
+ id=id,
+ )
+
+ return solar_inverter_summary
diff --git a/derapi/models/solaredge_join_config.py b/derapi/models/solaredge_join_config.py
new file mode 100644
index 0000000..ff84c5a
--- /dev/null
+++ b/derapi/models/solaredge_join_config.py
@@ -0,0 +1,40 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SolaredgeJoinConfig")
+
+
+@_attrs_define
+class SolaredgeJoinConfig:
+ """
+ Attributes:
+ vendor (Literal['solaredge']):
+ """
+
+ vendor: Literal["solaredge"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["solaredge"], d.pop("vendor"))
+ if vendor != "solaredge":
+ raise ValueError(f"vendor must match const 'solaredge', got '{vendor}'")
+
+ solaredge_join_config = cls(
+ vendor=vendor,
+ )
+
+ return solaredge_join_config
diff --git a/derapi/models/solis_credentials.py b/derapi/models/solis_credentials.py
new file mode 100644
index 0000000..1a12ac0
--- /dev/null
+++ b/derapi/models/solis_credentials.py
@@ -0,0 +1,66 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SolisCredentials")
+
+
+@_attrs_define
+class SolisCredentials:
+ """
+ Attributes:
+ vendor (Literal['solis']): Default: 'solis'.
+ type (Literal['apikeysecret']): Default: 'apikeysecret'.
+ key_id (str): Solis Key ID
+ key_secret (str): Solis Secret
+ """
+
+ key_id: str
+ key_secret: str
+ vendor: Literal["solis"] = "solis"
+ type: Literal["apikeysecret"] = "apikeysecret"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ key_id = self.key_id
+
+ key_secret = self.key_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "keyID": key_id,
+ "keySecret": key_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["solis"], d.pop("vendor"))
+ if vendor != "solis":
+ raise ValueError(f"vendor must match const 'solis', got '{vendor}'")
+
+ type = cast(Literal["apikeysecret"], d.pop("type"))
+ if type != "apikeysecret":
+ raise ValueError(f"type must match const 'apikeysecret', got '{type}'")
+
+ key_id = d.pop("keyID")
+
+ key_secret = d.pop("keySecret")
+
+ solis_credentials = cls(
+ vendor=vendor,
+ type=type,
+ key_id=key_id,
+ key_secret=key_secret,
+ )
+
+ return solis_credentials
diff --git a/derapi/models/solis_join_config.py b/derapi/models/solis_join_config.py
new file mode 100644
index 0000000..9212f0e
--- /dev/null
+++ b/derapi/models/solis_join_config.py
@@ -0,0 +1,40 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="SolisJoinConfig")
+
+
+@_attrs_define
+class SolisJoinConfig:
+ """
+ Attributes:
+ vendor (Literal['solis']):
+ """
+
+ vendor: Literal["solis"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["solis"], d.pop("vendor"))
+ if vendor != "solis":
+ raise ValueError(f"vendor must match const 'solis', got '{vendor}'")
+
+ solis_join_config = cls(
+ vendor=vendor,
+ )
+
+ return solis_join_config
diff --git a/derapi/models/stored_credentials_reference.py b/derapi/models/stored_credentials_reference.py
new file mode 100644
index 0000000..05aa753
--- /dev/null
+++ b/derapi/models/stored_credentials_reference.py
@@ -0,0 +1,38 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="StoredCredentialsReference")
+
+
+@_attrs_define
+class StoredCredentialsReference:
+ """
+ Attributes:
+ credentials_id (str): ID for the vendor credentials
+ """
+
+ credentials_id: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ credentials_id = self.credentials_id
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "credentialsID": credentials_id,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ credentials_id = d.pop("credentialsID")
+
+ stored_credentials_reference = cls(
+ credentials_id=credentials_id,
+ )
+
+ return stored_credentials_reference
diff --git a/derapi/models/summary_level.py b/derapi/models/summary_level.py
new file mode 100644
index 0000000..1dcffaa
--- /dev/null
+++ b/derapi/models/summary_level.py
@@ -0,0 +1,11 @@
+from enum import Enum
+
+
+class SummaryLevel(str, Enum):
+ DAY = "day"
+ HOUR = "hour"
+ MONTH = "month"
+ VALUE_3 = "15mins"
+
+ def __str__(self) -> str:
+ return str(self.value)
diff --git a/derapi/models/telsa_join_config_inline_credentials.py b/derapi/models/telsa_join_config_inline_credentials.py
new file mode 100644
index 0000000..77efd80
--- /dev/null
+++ b/derapi/models/telsa_join_config_inline_credentials.py
@@ -0,0 +1,46 @@
+from typing import Any, Dict, Type, TypeVar
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="TelsaJoinConfigInlineCredentials")
+
+
+@_attrs_define
+class TelsaJoinConfigInlineCredentials:
+ """
+ Attributes:
+ client_id (str): Client ID for a Tesla App
+ client_secret (str): Client secret for a Tesla App
+ """
+
+ client_id: str
+ client_secret: str
+
+ def to_dict(self) -> Dict[str, Any]:
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ telsa_join_config_inline_credentials = cls(
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return telsa_join_config_inline_credentials
diff --git a/derapi/models/tesla_app_credentials.py b/derapi/models/tesla_app_credentials.py
new file mode 100644
index 0000000..69b883a
--- /dev/null
+++ b/derapi/models/tesla_app_credentials.py
@@ -0,0 +1,66 @@
+from typing import Any, Dict, Literal, Type, TypeVar, cast
+
+from attrs import define as _attrs_define
+
+T = TypeVar("T", bound="TeslaAppCredentials")
+
+
+@_attrs_define
+class TeslaAppCredentials:
+ """
+ Attributes:
+ vendor (Literal['tesla']): Default: 'tesla'.
+ type (Literal['app']): Default: 'app'.
+ client_id (str): Client ID for a Tesla App
+ client_secret (str): Client secret for a Tesla App
+ """
+
+ client_id: str
+ client_secret: str
+ vendor: Literal["tesla"] = "tesla"
+ type: Literal["app"] = "app"
+
+ def to_dict(self) -> Dict[str, Any]:
+ vendor = self.vendor
+
+ type = self.type
+
+ client_id = self.client_id
+
+ client_secret = self.client_secret
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "type": type,
+ "clientID": client_id,
+ "clientSecret": client_secret,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ d = src_dict.copy()
+ vendor = cast(Literal["tesla"], d.pop("vendor"))
+ if vendor != "tesla":
+ raise ValueError(f"vendor must match const 'tesla', got '{vendor}'")
+
+ type = cast(Literal["app"], d.pop("type"))
+ if type != "app":
+ raise ValueError(f"type must match const 'app', got '{type}'")
+
+ client_id = d.pop("clientID")
+
+ client_secret = d.pop("clientSecret")
+
+ tesla_app_credentials = cls(
+ vendor=vendor,
+ type=type,
+ client_id=client_id,
+ client_secret=client_secret,
+ )
+
+ return tesla_app_credentials
diff --git a/derapi/models/tesla_join_config.py b/derapi/models/tesla_join_config.py
new file mode 100644
index 0000000..011b7c6
--- /dev/null
+++ b/derapi/models/tesla_join_config.py
@@ -0,0 +1,77 @@
+from typing import TYPE_CHECKING, Any, Dict, Literal, Type, TypeVar, Union, cast
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+ from ..models.telsa_join_config_inline_credentials import TelsaJoinConfigInlineCredentials
+
+
+T = TypeVar("T", bound="TeslaJoinConfig")
+
+
+@_attrs_define
+class TeslaJoinConfig:
+ """
+ Attributes:
+ vendor (Literal['tesla']):
+ credentials (Union['StoredCredentialsReference', 'TelsaJoinConfigInlineCredentials']):
+ """
+
+ vendor: Literal["tesla"]
+ credentials: Union["StoredCredentialsReference", "TelsaJoinConfigInlineCredentials"]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.telsa_join_config_inline_credentials import TelsaJoinConfigInlineCredentials
+
+ vendor = self.vendor
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, TelsaJoinConfigInlineCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "vendor": vendor,
+ "credentials": credentials,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.stored_credentials_reference import StoredCredentialsReference
+ from ..models.telsa_join_config_inline_credentials import TelsaJoinConfigInlineCredentials
+
+ d = src_dict.copy()
+ vendor = cast(Literal["tesla"], d.pop("vendor"))
+ if vendor != "tesla":
+ raise ValueError(f"vendor must match const 'tesla', got '{vendor}'")
+
+ def _parse_credentials(data: object) -> Union["StoredCredentialsReference", "TelsaJoinConfigInlineCredentials"]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ credentials_type_0 = TelsaJoinConfigInlineCredentials.from_dict(data)
+
+ return credentials_type_0
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ credentials_type_1 = StoredCredentialsReference.from_dict(data)
+
+ return credentials_type_1
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ tesla_join_config = cls(
+ vendor=vendor,
+ credentials=credentials,
+ )
+
+ return tesla_join_config
diff --git a/derapi/models/update_vendor_credentials_request.py b/derapi/models/update_vendor_credentials_request.py
new file mode 100644
index 0000000..0438bc4
--- /dev/null
+++ b/derapi/models/update_vendor_credentials_request.py
@@ -0,0 +1,242 @@
+from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union, cast
+
+from attrs import define as _attrs_define
+
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+
+T = TypeVar("T", bound="UpdateVendorCredentialsRequest")
+
+
+@_attrs_define
+class UpdateVendorCredentialsRequest:
+ """
+ Attributes:
+ name (Union[None, Unset, str]): The name of the vendor credentials; if null, the value will be unset.
+ credentials (Union['EnphaseDeveloperAppCredentials', 'EnphasePartnerAppCredentials', 'EnphaseVPPCredentials',
+ 'FranklinWHCredentials', 'SMACustomGrantCredentials', 'SMAOAuthCredentials', 'SMASandboxCustomGrantCredentials',
+ 'SMASandboxOAuthCredentials', 'SolarEdgeCredentials', 'SolisCredentials', 'TeslaAppCredentials', Unset]):
+ Credentials for a given vendor.
+ """
+
+ name: Union[None, Unset, str] = UNSET
+ credentials: Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ Unset,
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+
+ name: Union[None, Unset, str]
+ if isinstance(self.name, Unset):
+ name = UNSET
+ else:
+ name = self.name
+
+ credentials: Union[Dict[str, Any], Unset]
+ if isinstance(self.credentials, Unset):
+ credentials = UNSET
+ elif isinstance(self.credentials, EnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, FranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolisCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update({})
+ if name is not UNSET:
+ field_dict["name"] = name
+ if credentials is not UNSET:
+ field_dict["credentials"] = credentials
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+ d = src_dict.copy()
+
+ def _parse_name(data: object) -> Union[None, Unset, str]:
+ if data is None:
+ return data
+ if isinstance(data, Unset):
+ return data
+ return cast(Union[None, Unset, str], data)
+
+ name = _parse_name(d.pop("name", UNSET))
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ Unset,
+ ]:
+ if isinstance(data, Unset):
+ return data
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_0 = EnphasePartnerAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_1 = EnphaseDeveloperAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_2 = EnphaseVPPCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_3 = FranklinWHCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_4 = SMACustomGrantCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_5 = SMAOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_6 = SMASandboxCustomGrantCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_7 = SMASandboxOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_8 = SolarEdgeCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_9 = SolisCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_10 = TeslaAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_10
+
+ credentials = _parse_credentials(d.pop("credentials", UNSET))
+
+ update_vendor_credentials_request = cls(
+ name=name,
+ credentials=credentials,
+ )
+
+ return update_vendor_credentials_request
diff --git a/derapi/models/update_vendor_credentials_response.py b/derapi/models/update_vendor_credentials_response.py
new file mode 100644
index 0000000..841d794
--- /dev/null
+++ b/derapi/models/update_vendor_credentials_response.py
@@ -0,0 +1,420 @@
+from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+
+T = TypeVar("T", bound="UpdateVendorCredentialsResponse")
+
+
+@_attrs_define
+class UpdateVendorCredentialsResponse:
+ """Vendor credentials which may or may not be hidden.
+
+ Attributes:
+ id (str): ID for the vendor credentials
+ name (str): The name of the vendor credentials; inferred if not provided.
+ credentials (Union['EnphaseDeveloperAppCredentials', 'EnphasePartnerAppCredentials', 'EnphaseVPPCredentials',
+ 'FranklinWHCredentials', 'HiddenEnphaseDeveloperAppCredentials', 'HiddenEnphasePartnerAppCredentials',
+ 'HiddenEnphaseVPPCredentials', 'HiddenFranklinWHCredentials', 'HiddenSMACustomGrantCredentials',
+ 'HiddenSMAOAuthCredentials', 'HiddenSMASandboxCustomGrantCredentials', 'HiddenSMASandboxOAuthCredentials',
+ 'HiddenSolarEdgeCredentials', 'HiddenSolisCredentials', 'HiddenTeslaAppCredentials',
+ 'SMACustomGrantCredentials', 'SMAOAuthCredentials', 'SMASandboxCustomGrantCredentials',
+ 'SMASandboxOAuthCredentials', 'SolarEdgeCredentials', 'SolisCredentials', 'TeslaAppCredentials']):
+ """
+
+ id: str
+ name: str
+ credentials: Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+
+ id = self.id
+
+ name = self.name
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, HiddenEnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenEnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenEnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenFranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSolisCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenTeslaAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, FranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolisCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "name": name,
+ "credentials": credentials,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ name = d.pop("name")
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_0 = (
+ HiddenEnphaseDeveloperAppCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_1 = (
+ HiddenEnphasePartnerAppCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_2 = HiddenEnphaseVPPCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_3 = HiddenFranklinWHCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_4 = (
+ HiddenSMACustomGrantCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_5 = HiddenSMAOAuthCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_6 = (
+ HiddenSMASandboxCustomGrantCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_7 = (
+ HiddenSMASandboxOAuthCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_8 = HiddenSolarEdgeCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_9 = HiddenSolisCredentials.from_dict(data)
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_10 = HiddenTeslaAppCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_10
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_0 = EnphasePartnerAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_1 = EnphaseDeveloperAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_2 = EnphaseVPPCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_3 = FranklinWHCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_4 = SMACustomGrantCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_5 = SMAOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_6 = SMASandboxCustomGrantCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_7 = SMASandboxOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_8 = SolarEdgeCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_9 = SolisCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_10 = TeslaAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_10
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ update_vendor_credentials_response = cls(
+ id=id,
+ name=name,
+ credentials=credentials,
+ )
+
+ return update_vendor_credentials_response
diff --git a/derapi/models/vendor.py b/derapi/models/vendor.py
new file mode 100644
index 0000000..dce9b97
--- /dev/null
+++ b/derapi/models/vendor.py
@@ -0,0 +1,15 @@
+from enum import Enum
+
+
+class Vendor(str, Enum):
+ ENPHASE = "enphase"
+ ENPHASEVPP = "enphasevpp"
+ SMA = "sma"
+ SMASBOX = "smasbox"
+ SOLAREDGE = "solaredge"
+ SOLIS = "solis"
+ TESLA = "tesla"
+ VIRTUAL = "virtual"
+
+ def __str__(self) -> str:
+ return str(self.value)
diff --git a/derapi/models/vendor_credentials.py b/derapi/models/vendor_credentials.py
new file mode 100644
index 0000000..eca052b
--- /dev/null
+++ b/derapi/models/vendor_credentials.py
@@ -0,0 +1,420 @@
+from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+
+if TYPE_CHECKING:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+
+T = TypeVar("T", bound="VendorCredentials")
+
+
+@_attrs_define
+class VendorCredentials:
+ """Vendor credentials which may or may not be hidden.
+
+ Attributes:
+ id (str): ID for the vendor credentials
+ name (str): The name of the vendor credentials; inferred if not provided.
+ credentials (Union['EnphaseDeveloperAppCredentials', 'EnphasePartnerAppCredentials', 'EnphaseVPPCredentials',
+ 'FranklinWHCredentials', 'HiddenEnphaseDeveloperAppCredentials', 'HiddenEnphasePartnerAppCredentials',
+ 'HiddenEnphaseVPPCredentials', 'HiddenFranklinWHCredentials', 'HiddenSMACustomGrantCredentials',
+ 'HiddenSMAOAuthCredentials', 'HiddenSMASandboxCustomGrantCredentials', 'HiddenSMASandboxOAuthCredentials',
+ 'HiddenSolarEdgeCredentials', 'HiddenSolisCredentials', 'HiddenTeslaAppCredentials',
+ 'SMACustomGrantCredentials', 'SMAOAuthCredentials', 'SMASandboxCustomGrantCredentials',
+ 'SMASandboxOAuthCredentials', 'SolarEdgeCredentials', 'SolisCredentials', 'TeslaAppCredentials']):
+ """
+
+ id: str
+ name: str
+ credentials: Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+
+ id = self.id
+
+ name = self.name
+
+ credentials: Dict[str, Any]
+ if isinstance(self.credentials, HiddenEnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenEnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenEnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenFranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenSolisCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, HiddenTeslaAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphasePartnerAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseDeveloperAppCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, EnphaseVPPCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, FranklinWHCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMACustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMAOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxCustomGrantCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SMASandboxOAuthCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolarEdgeCredentials):
+ credentials = self.credentials.to_dict()
+ elif isinstance(self.credentials, SolisCredentials):
+ credentials = self.credentials.to_dict()
+ else:
+ credentials = self.credentials.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "name": name,
+ "credentials": credentials,
+ }
+ )
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.enphase_developer_app_credentials import EnphaseDeveloperAppCredentials
+ from ..models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+ from ..models.enphase_vpp_credentials import EnphaseVPPCredentials
+ from ..models.franklin_wh_credentials import FranklinWHCredentials
+ from ..models.hidden_enphase_developer_app_credentials import HiddenEnphaseDeveloperAppCredentials
+ from ..models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+ from ..models.hidden_enphase_vpp_credentials import HiddenEnphaseVPPCredentials
+ from ..models.hidden_franklin_wh_credentials import HiddenFranklinWHCredentials
+ from ..models.hidden_sma_custom_grant_credentials import HiddenSMACustomGrantCredentials
+ from ..models.hidden_sma_sandbox_custom_grant_credentials import HiddenSMASandboxCustomGrantCredentials
+ from ..models.hidden_sma_sandbox_o_auth_credentials import HiddenSMASandboxOAuthCredentials
+ from ..models.hidden_smao_auth_credentials import HiddenSMAOAuthCredentials
+ from ..models.hidden_solar_edge_credentials import HiddenSolarEdgeCredentials
+ from ..models.hidden_solis_credentials import HiddenSolisCredentials
+ from ..models.hidden_tesla_app_credentials import HiddenTeslaAppCredentials
+ from ..models.sma_custom_grant_credentials import SMACustomGrantCredentials
+ from ..models.sma_sandbox_custom_grant_credentials import SMASandboxCustomGrantCredentials
+ from ..models.sma_sandbox_o_auth_credentials import SMASandboxOAuthCredentials
+ from ..models.smao_auth_credentials import SMAOAuthCredentials
+ from ..models.solar_edge_credentials import SolarEdgeCredentials
+ from ..models.solis_credentials import SolisCredentials
+ from ..models.tesla_app_credentials import TeslaAppCredentials
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ name = d.pop("name")
+
+ def _parse_credentials(
+ data: object,
+ ) -> Union[
+ "EnphaseDeveloperAppCredentials",
+ "EnphasePartnerAppCredentials",
+ "EnphaseVPPCredentials",
+ "FranklinWHCredentials",
+ "HiddenEnphaseDeveloperAppCredentials",
+ "HiddenEnphasePartnerAppCredentials",
+ "HiddenEnphaseVPPCredentials",
+ "HiddenFranklinWHCredentials",
+ "HiddenSMACustomGrantCredentials",
+ "HiddenSMAOAuthCredentials",
+ "HiddenSMASandboxCustomGrantCredentials",
+ "HiddenSMASandboxOAuthCredentials",
+ "HiddenSolarEdgeCredentials",
+ "HiddenSolisCredentials",
+ "HiddenTeslaAppCredentials",
+ "SMACustomGrantCredentials",
+ "SMAOAuthCredentials",
+ "SMASandboxCustomGrantCredentials",
+ "SMASandboxOAuthCredentials",
+ "SolarEdgeCredentials",
+ "SolisCredentials",
+ "TeslaAppCredentials",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_0 = (
+ HiddenEnphaseDeveloperAppCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_1 = (
+ HiddenEnphasePartnerAppCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_2 = HiddenEnphaseVPPCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_3 = HiddenFranklinWHCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_4 = (
+ HiddenSMACustomGrantCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_5 = HiddenSMAOAuthCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_6 = (
+ HiddenSMASandboxCustomGrantCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_7 = (
+ HiddenSMASandboxOAuthCredentials.from_dict(data)
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_8 = HiddenSolarEdgeCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_9 = HiddenSolisCredentials.from_dict(data)
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_hidden_vendor_credentials_credentials_type_10 = HiddenTeslaAppCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_hidden_vendor_credentials_credentials_type_10
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_0 = EnphasePartnerAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_1 = EnphaseDeveloperAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_2 = EnphaseVPPCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_2
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_3 = FranklinWHCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_3
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_4 = SMACustomGrantCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_4
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_5 = SMAOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_5
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_6 = SMASandboxCustomGrantCredentials.from_dict(
+ data
+ )
+
+ return componentsschemas_vendor_credentials_credentials_type_6
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_7 = SMASandboxOAuthCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_7
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_8 = SolarEdgeCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_8
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_9 = SolisCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_9
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_vendor_credentials_credentials_type_10 = TeslaAppCredentials.from_dict(data)
+
+ return componentsschemas_vendor_credentials_credentials_type_10
+
+ credentials = _parse_credentials(d.pop("credentials"))
+
+ vendor_credentials = cls(
+ id=id,
+ name=name,
+ credentials=credentials,
+ )
+
+ return vendor_credentials
diff --git a/derapi/models/virtual_battery.py b/derapi/models/virtual_battery.py
new file mode 100644
index 0000000..0a452bf
--- /dev/null
+++ b/derapi/models/virtual_battery.py
@@ -0,0 +1,236 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.battery_mode import BatteryMode
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+
+T = TypeVar("T", bound="VirtualBattery")
+
+
+@_attrs_define
+class VirtualBattery:
+ """
+ Attributes:
+ id (str): Battery id
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format (timezone is always +00:00
+ and is always present)
+ model (str): Model number of Battery
+ serial_number (str): Manufacturer serial number of the Battery
+ site_id (str): The Derapi Site ID this Battery is associated with
+ name (Union[Unset, str]): Customer defined name of the Battery
+ nameplate_kwh (Union[Unset, float]): The rated storage capacity of the unit
+ mode (Union[Unset, BatteryMode]): Battery management system mode. Values are Self Consumption - minimize grid
+ import, Savings - optimizing Battery to save money; usually based on a rate plan, Backup - only use Battery for
+ grid backup
+ state_of_charge_percent (Union[Unset, float]): Battery state of charge as a percent of capacity
+ recent_errors (Union[Unset, List[Union['BatteryRecentErrorsError', 'BatteryRecentErrorsInfo',
+ 'BatteryRecentErrorsStart', 'BatteryRecentErrorsWarning']]]): Most recent errors, warnings, or info reported by
+ the manufacturer for this Battery. The key represents the severity level (info/warning/error); the value is a
+ string description. start is always present and is the last element to be returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ nameplate_kwh: Union[Unset, float] = UNSET
+ mode: Union[Unset, BatteryMode] = UNSET
+ state_of_charge_percent: Union[Unset, float] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ nameplate_kwh = self.nameplate_kwh
+
+ mode: Union[Unset, str] = UNSET
+ if not isinstance(self.mode, Unset):
+ mode = self.mode.value
+
+ state_of_charge_percent = self.state_of_charge_percent
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_battery_recent_errors_item_data in self.recent_errors:
+ componentsschemas_battery_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsError):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsWarning):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(componentsschemas_battery_recent_errors_item_data, BatteryRecentErrorsInfo):
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_battery_recent_errors_item = (
+ componentsschemas_battery_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if nameplate_kwh is not UNSET:
+ field_dict["nameplateKwh"] = nameplate_kwh
+ if mode is not UNSET:
+ field_dict["mode"] = mode
+ if state_of_charge_percent is not UNSET:
+ field_dict["stateOfChargePercent"] = state_of_charge_percent
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_recent_errors_error import BatteryRecentErrorsError
+ from ..models.battery_recent_errors_info import BatteryRecentErrorsInfo
+ from ..models.battery_recent_errors_start import BatteryRecentErrorsStart
+ from ..models.battery_recent_errors_warning import BatteryRecentErrorsWarning
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ nameplate_kwh = d.pop("nameplateKwh", UNSET)
+
+ _mode = d.pop("mode", UNSET)
+ mode: Union[Unset, BatteryMode]
+ if isinstance(_mode, Unset):
+ mode = UNSET
+ else:
+ mode = BatteryMode(_mode)
+
+ state_of_charge_percent = d.pop("stateOfChargePercent", UNSET)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_battery_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_battery_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "BatteryRecentErrorsError",
+ "BatteryRecentErrorsInfo",
+ "BatteryRecentErrorsStart",
+ "BatteryRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_0 = BatteryRecentErrorsError.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_1 = BatteryRecentErrorsWarning.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_2 = BatteryRecentErrorsInfo.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_battery_recent_errors_item_type_3 = BatteryRecentErrorsStart.from_dict(data)
+
+ return componentsschemas_battery_recent_errors_item_type_3
+
+ componentsschemas_battery_recent_errors_item = _parse_componentsschemas_battery_recent_errors_item(
+ componentsschemas_battery_recent_errors_item_data
+ )
+
+ recent_errors.append(componentsschemas_battery_recent_errors_item)
+
+ virtual_battery = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ nameplate_kwh=nameplate_kwh,
+ mode=mode,
+ state_of_charge_percent=state_of_charge_percent,
+ recent_errors=recent_errors,
+ )
+
+ return virtual_battery
diff --git a/derapi/models/virtual_site.py b/derapi/models/virtual_site.py
new file mode 100644
index 0000000..673e7ea
--- /dev/null
+++ b/derapi/models/virtual_site.py
@@ -0,0 +1,163 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+
+T = TypeVar("T", bound="VirtualSite")
+
+
+@_attrs_define
+class VirtualSite:
+ """
+ Attributes:
+ id (str): the ID for the Site
+ vendor (Vendor):
+ name (str): Customer defined name of the Site
+ location_utc_offset (float): UTC Offset in hours; positive values represent locations East of UTC. Please note
+ this field will soon be deprecated, please use `timezone` instead.
+ batteries (List['BatterySummary']): List of Battery IDs associated with this Site
+ solar_inverters (List['SolarInverterSummary']): List of Solar Inverter IDs associated with this Site
+ location (Union[Unset, SiteLocation]): The location of this Solar Inverter in lat/lon coordinates
+ operational_since (Union[Unset, datetime.datetime]): The date the Site became operational or received permission
+ to operate. Sometimes absent for Solaredge.
+ bess (Union[Unset, SiteBESS]): For Sites with Batteries this key is present
+ """
+
+ id: str
+ vendor: Vendor
+ name: str
+ location_utc_offset: float
+ batteries: List["BatterySummary"]
+ solar_inverters: List["SolarInverterSummary"]
+ location: Union[Unset, "SiteLocation"] = UNSET
+ operational_since: Union[Unset, datetime.datetime] = UNSET
+ bess: Union[Unset, "SiteBESS"] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ id = self.id
+
+ vendor = self.vendor.value
+
+ name = self.name
+
+ location_utc_offset = self.location_utc_offset
+
+ batteries = []
+ for componentsschemas_site_batteries_item_data in self.batteries:
+ componentsschemas_site_batteries_item = componentsschemas_site_batteries_item_data.to_dict()
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ for componentsschemas_site_solar_inverters_item_data in self.solar_inverters:
+ componentsschemas_site_solar_inverters_item = componentsschemas_site_solar_inverters_item_data.to_dict()
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ location: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.location, Unset):
+ location = self.location.to_dict()
+
+ operational_since: Union[Unset, str] = UNSET
+ if not isinstance(self.operational_since, Unset):
+ operational_since = self.operational_since.isoformat()
+
+ bess: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.bess, Unset):
+ bess = self.bess.to_dict()
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "name": name,
+ "locationUTCOffset": location_utc_offset,
+ "batteries": batteries,
+ "solarInverters": solar_inverters,
+ }
+ )
+ if location is not UNSET:
+ field_dict["location"] = location
+ if operational_since is not UNSET:
+ field_dict["operationalSince"] = operational_since
+ if bess is not UNSET:
+ field_dict["bess"] = bess
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.battery_summary import BatterySummary
+ from ..models.site_bess import SiteBESS
+ from ..models.site_location import SiteLocation
+ from ..models.solar_inverter_summary import SolarInverterSummary
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ name = d.pop("name")
+
+ location_utc_offset = d.pop("locationUTCOffset")
+
+ batteries = []
+ _batteries = d.pop("batteries")
+ for componentsschemas_site_batteries_item_data in _batteries:
+ componentsschemas_site_batteries_item = BatterySummary.from_dict(componentsschemas_site_batteries_item_data)
+
+ batteries.append(componentsschemas_site_batteries_item)
+
+ solar_inverters = []
+ _solar_inverters = d.pop("solarInverters")
+ for componentsschemas_site_solar_inverters_item_data in _solar_inverters:
+ componentsschemas_site_solar_inverters_item = SolarInverterSummary.from_dict(
+ componentsschemas_site_solar_inverters_item_data
+ )
+
+ solar_inverters.append(componentsschemas_site_solar_inverters_item)
+
+ _location = d.pop("location", UNSET)
+ location: Union[Unset, SiteLocation]
+ if isinstance(_location, Unset):
+ location = UNSET
+ else:
+ location = SiteLocation.from_dict(_location)
+
+ _operational_since = d.pop("operationalSince", UNSET)
+ operational_since: Union[Unset, datetime.datetime]
+ if isinstance(_operational_since, Unset):
+ operational_since = UNSET
+ else:
+ operational_since = isoparse(_operational_since)
+
+ _bess = d.pop("bess", UNSET)
+ bess: Union[Unset, SiteBESS]
+ if isinstance(_bess, Unset):
+ bess = UNSET
+ else:
+ bess = SiteBESS.from_dict(_bess)
+
+ virtual_site = cls(
+ id=id,
+ vendor=vendor,
+ name=name,
+ location_utc_offset=location_utc_offset,
+ batteries=batteries,
+ solar_inverters=solar_inverters,
+ location=location,
+ operational_since=operational_since,
+ bess=bess,
+ )
+
+ return virtual_site
diff --git a/derapi/models/virtual_solar_inverter.py b/derapi/models/virtual_solar_inverter.py
new file mode 100644
index 0000000..5649d61
--- /dev/null
+++ b/derapi/models/virtual_solar_inverter.py
@@ -0,0 +1,249 @@
+import datetime
+from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union
+
+from attrs import define as _attrs_define
+from dateutil.parser import isoparse
+
+from ..models.vendor import Vendor
+from ..types import UNSET, Unset
+
+if TYPE_CHECKING:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+
+T = TypeVar("T", bound="VirtualSolarInverter")
+
+
+@_attrs_define
+class VirtualSolarInverter:
+ """
+ Attributes:
+ id (str): ID of the solar inverter
+ vendor (Vendor):
+ reported_at (datetime.datetime): Date the request was generated in ISO-8601 format
+ model (str): Model number of this Solar Inverter
+ serial_number (str): Manufacturer serial number of this Solar Inverter
+ site_id (str): The Derapi Site ID this Solar Inverter is associated with
+ name (Union[Unset, str]): Customer defined name of this Solar Inverter
+ recent_production (Union[Unset, SolarInverterRecentProduction]):
+ lifetime_production (Union[Unset, SolarInverterLifetimeProduction]):
+ recent_errors (Union[Unset, List[Union['SolarInverterRecentErrorsError', 'SolarInverterRecentErrorsInfo',
+ 'SolarInverterRecentErrorsStart', 'SolarInverterRecentErrorsWarning']]]): Most recent errors, warnings, or info
+ reported by the manufacturer for this Solar Inverter. The key represents the severity level
+ (info/warning/error); the value is a string description. start is always present and is the last element to be
+ returned.
+ """
+
+ id: str
+ vendor: Vendor
+ reported_at: datetime.datetime
+ model: str
+ serial_number: str
+ site_id: str
+ name: Union[Unset, str] = UNSET
+ recent_production: Union[Unset, "SolarInverterRecentProduction"] = UNSET
+ lifetime_production: Union[Unset, "SolarInverterLifetimeProduction"] = UNSET
+ recent_errors: Union[
+ Unset,
+ List[
+ Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]
+ ],
+ ] = UNSET
+
+ def to_dict(self) -> Dict[str, Any]:
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+
+ id = self.id
+
+ vendor = self.vendor.value
+
+ reported_at = self.reported_at.isoformat()
+
+ model = self.model
+
+ serial_number = self.serial_number
+
+ site_id = self.site_id
+
+ name = self.name
+
+ recent_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.recent_production, Unset):
+ recent_production = self.recent_production.to_dict()
+
+ lifetime_production: Union[Unset, Dict[str, Any]] = UNSET
+ if not isinstance(self.lifetime_production, Unset):
+ lifetime_production = self.lifetime_production.to_dict()
+
+ recent_errors: Union[Unset, List[Dict[str, Any]]] = UNSET
+ if not isinstance(self.recent_errors, Unset):
+ recent_errors = []
+ for componentsschemas_solar_inverter_recent_errors_item_data in self.recent_errors:
+ componentsschemas_solar_inverter_recent_errors_item: Dict[str, Any]
+ if isinstance(componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsError):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsWarning
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ elif isinstance(
+ componentsschemas_solar_inverter_recent_errors_item_data, SolarInverterRecentErrorsInfo
+ ):
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+ else:
+ componentsschemas_solar_inverter_recent_errors_item = (
+ componentsschemas_solar_inverter_recent_errors_item_data.to_dict()
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ field_dict: Dict[str, Any] = {}
+ field_dict.update(
+ {
+ "id": id,
+ "vendor": vendor,
+ "reportedAt": reported_at,
+ "model": model,
+ "serialNumber": serial_number,
+ "siteID": site_id,
+ }
+ )
+ if name is not UNSET:
+ field_dict["name"] = name
+ if recent_production is not UNSET:
+ field_dict["recentProduction"] = recent_production
+ if lifetime_production is not UNSET:
+ field_dict["lifetimeProduction"] = lifetime_production
+ if recent_errors is not UNSET:
+ field_dict["recentErrors"] = recent_errors
+
+ return field_dict
+
+ @classmethod
+ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
+ from ..models.solar_inverter_lifetime_production import SolarInverterLifetimeProduction
+ from ..models.solar_inverter_recent_errors_error import SolarInverterRecentErrorsError
+ from ..models.solar_inverter_recent_errors_info import SolarInverterRecentErrorsInfo
+ from ..models.solar_inverter_recent_errors_start import SolarInverterRecentErrorsStart
+ from ..models.solar_inverter_recent_errors_warning import SolarInverterRecentErrorsWarning
+ from ..models.solar_inverter_recent_production import SolarInverterRecentProduction
+
+ d = src_dict.copy()
+ id = d.pop("id")
+
+ vendor = Vendor(d.pop("vendor"))
+
+ reported_at = isoparse(d.pop("reportedAt"))
+
+ model = d.pop("model")
+
+ serial_number = d.pop("serialNumber")
+
+ site_id = d.pop("siteID")
+
+ name = d.pop("name", UNSET)
+
+ _recent_production = d.pop("recentProduction", UNSET)
+ recent_production: Union[Unset, SolarInverterRecentProduction]
+ if isinstance(_recent_production, Unset):
+ recent_production = UNSET
+ else:
+ recent_production = SolarInverterRecentProduction.from_dict(_recent_production)
+
+ _lifetime_production = d.pop("lifetimeProduction", UNSET)
+ lifetime_production: Union[Unset, SolarInverterLifetimeProduction]
+ if isinstance(_lifetime_production, Unset):
+ lifetime_production = UNSET
+ else:
+ lifetime_production = SolarInverterLifetimeProduction.from_dict(_lifetime_production)
+
+ recent_errors = []
+ _recent_errors = d.pop("recentErrors", UNSET)
+ for componentsschemas_solar_inverter_recent_errors_item_data in _recent_errors or []:
+
+ def _parse_componentsschemas_solar_inverter_recent_errors_item(
+ data: object,
+ ) -> Union[
+ "SolarInverterRecentErrorsError",
+ "SolarInverterRecentErrorsInfo",
+ "SolarInverterRecentErrorsStart",
+ "SolarInverterRecentErrorsWarning",
+ ]:
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_0 = (
+ SolarInverterRecentErrorsError.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_0
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_1 = (
+ SolarInverterRecentErrorsWarning.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_1
+ except: # noqa: E722
+ pass
+ try:
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_2 = (
+ SolarInverterRecentErrorsInfo.from_dict(data)
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_2
+ except: # noqa: E722
+ pass
+ if not isinstance(data, dict):
+ raise TypeError()
+ componentsschemas_solar_inverter_recent_errors_item_type_3 = SolarInverterRecentErrorsStart.from_dict(
+ data
+ )
+
+ return componentsschemas_solar_inverter_recent_errors_item_type_3
+
+ componentsschemas_solar_inverter_recent_errors_item = (
+ _parse_componentsschemas_solar_inverter_recent_errors_item(
+ componentsschemas_solar_inverter_recent_errors_item_data
+ )
+ )
+
+ recent_errors.append(componentsschemas_solar_inverter_recent_errors_item)
+
+ virtual_solar_inverter = cls(
+ id=id,
+ vendor=vendor,
+ reported_at=reported_at,
+ model=model,
+ serial_number=serial_number,
+ site_id=site_id,
+ name=name,
+ recent_production=recent_production,
+ lifetime_production=lifetime_production,
+ recent_errors=recent_errors,
+ )
+
+ return virtual_solar_inverter
diff --git a/derapi/types.py b/derapi/types.py
new file mode 100644
index 0000000..21fac10
--- /dev/null
+++ b/derapi/types.py
@@ -0,0 +1,45 @@
+"""Contains some shared types for properties"""
+
+from http import HTTPStatus
+from typing import BinaryIO, Generic, Literal, MutableMapping, Optional, Tuple, TypeVar
+
+from attrs import define
+
+
+class Unset:
+ def __bool__(self) -> Literal[False]:
+ return False
+
+
+UNSET: Unset = Unset()
+
+FileJsonType = Tuple[Optional[str], BinaryIO, Optional[str]]
+
+
+@define
+class File:
+ """Contains information for file uploads"""
+
+ payload: BinaryIO
+ file_name: Optional[str] = None
+ mime_type: Optional[str] = None
+
+ def to_tuple(self) -> FileJsonType:
+ """Return a tuple representation that httpx will accept for multipart/form-data"""
+ return self.file_name, self.payload, self.mime_type
+
+
+T = TypeVar("T")
+
+
+@define
+class Response(Generic[T]):
+ """A response from an endpoint"""
+
+ status_code: HTTPStatus
+ content: bytes
+ headers: MutableMapping[str, str]
+ parsed: Optional[T]
+
+
+__all__ = ["File", "Response", "FileJsonType", "Unset", "UNSET"]
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..462c01d
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,61 @@
+[build-system]
+requires = ["hatchling", "hatch-vcs"]
+build-backend = "hatchling.build"
+
+[project]
+name = "derapi"
+dynamic = ["version"]
+requires-python = ">=3.8"
+classifiers = [
+ "Development Status :: 4 - Beta",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: Implementation :: CPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+]
+dependencies = [
+ "httpx>=0.20.0,<0.28.0",
+ "attrs>=21.3.0",
+ "python-dateutil==2.8.0"
+]
+readme = "README.md"
+
+[project.optional-dependencies]
+dev = [
+ "pyright==v1.1.388",
+]
+
+[tool.hatch.envs.hatch-test]
+features = ["dev"]
+
+[tool.hatch.build.targets.sdist]
+packages = ["derapi"]
+
+[tool.hatch.build.targets.wheel]
+packages = ["derapi"]
+
+[tool.hatch.version]
+source = "vcs"
+fallback-version = "0.0.0"
+
+[tool.pytest.ini_options]
+pythonpath = "."
+
+[tool.ruff]
+line-length = 120
+
+[tool.ruff.lint]
+select = ["F", "I", "UP"]
+
+[tool.hatch.envs.typing]
+template = "hatch-test"
+
+scripts.check = "pyright {args}"
+
+[tool.pyright]
+typeCheckingMode = "strict"
+include = ["tests/"]
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..2176a54
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,52 @@
+import os
+
+import httpx
+import pytest
+
+from derapi import AuthenticatedClient
+
+
+@pytest.fixture(scope="session")
+def client():
+ token = _request_token(
+ os.environ["DERAPI_TOKEN_URL"],
+ os.environ["DERAPI_CLIENT_ID"],
+ os.environ["DERAPI_CLIENT_SECRET"],
+ )
+ return AuthenticatedClient(
+ os.environ["DERAPI_URL"],
+ headers={"api-version": "v2024-09-01"},
+ raise_on_unexpected_status=True,
+ token=token,
+ )
+
+
+@pytest.fixture(scope="session")
+def virtual_client():
+ token = _request_token(
+ os.environ["DERAPI_TOKEN_URL"],
+ os.environ["DERAPI_VIRTUAL_CLIENT_ID"],
+ os.environ["DERAPI_VIRTUAL_CLIENT_SECRET"],
+ )
+ client = AuthenticatedClient(
+ os.environ["DERAPI_URL"],
+ headers={"api-version": "v2024-09-01"},
+ raise_on_unexpected_status=True,
+ token=token,
+ )
+
+ def log_request(r: httpx.Request):
+ print(f"Request: {r.method} {r.url} {r.headers}")
+
+ client.get_httpx_client().event_hooks["request"].append(log_request)
+ return client
+
+
+def _request_token(token_url: str, client_id: str, client_secret: str) -> str:
+ resp = httpx.post(
+ token_url,
+ auth=(client_id, client_secret),
+ data={"grant_type": "client_credentials"},
+ )
+ resp.raise_for_status()
+ return resp.json()["access_token"]
diff --git a/tests/test_batteries.py b/tests/test_batteries.py
new file mode 100644
index 0000000..553a861
--- /dev/null
+++ b/tests/test_batteries.py
@@ -0,0 +1,58 @@
+from datetime import datetime, timedelta, timezone
+from typing import Iterator
+
+import pytest
+
+from derapi.api.batteries import get_battery, get_battery_intervals, list_batteries
+from derapi.api.virtual import create_virtual_battery, delete_virtual_battery
+from derapi.client import Client
+from derapi.models.create_virtual_battery_request import (
+ CreateVirtualBatteryRequest,
+)
+from derapi.models.create_virtual_battery_response import (
+ CreateVirtualBatteryResponse,
+)
+from derapi.models.vendor import Vendor
+from derapi.models.virtual_battery import VirtualBattery
+
+
+@pytest.fixture(scope="module")
+def virtual_battery(virtual_client: Client) -> Iterator[CreateVirtualBatteryResponse]:
+ virtual_battery = create_virtual_battery.sync(
+ client=virtual_client,
+ body=CreateVirtualBatteryRequest(name="My test battery"),
+ )
+ assert virtual_battery is not None
+
+ yield virtual_battery
+
+ delete_virtual_battery.sync_detailed(virtual_battery.id, client=virtual_client)
+
+
+def test_get_battery(virtual_client: Client, virtual_battery: VirtualBattery) -> None:
+ battery = get_battery.sync(virtual_battery.id, client=virtual_client)
+ assert battery is not None
+
+ assert battery.name == "My test battery"
+ assert battery.vendor == Vendor.VIRTUAL
+
+
+def test_list_batteries(virtual_client: Client, virtual_battery: VirtualBattery) -> None:
+ batteries = list_batteries.sync_depaginated(client=virtual_client)
+ assert any(battery.id == virtual_battery.id for battery in batteries)
+
+
+def test_list_battery_intervals(
+ virtual_client: Client,
+ virtual_battery: VirtualBattery,
+) -> None:
+ intervals = get_battery_intervals.sync(
+ virtual_battery.id,
+ start=datetime.now(timezone.utc) - timedelta(hours=25),
+ end=datetime.now(timezone.utc) - timedelta(hours=1),
+ client=virtual_client,
+ )
+ assert intervals is not None
+
+ assert len(intervals.intervals) > 0
+ assert intervals.intervals[0].start.tzinfo is not None
diff --git a/tests/test_credentials.py b/tests/test_credentials.py
new file mode 100644
index 0000000..b67b8ed
--- /dev/null
+++ b/tests/test_credentials.py
@@ -0,0 +1,25 @@
+import random
+
+from derapi.api.vendor_credentials import create_vendor_credentials, delete_vendor_credentials
+from derapi.client import Client
+from derapi.models.create_vendor_credentials_request import CreateVendorCredentialsRequest
+from derapi.models.enphase_partner_app_credentials import EnphasePartnerAppCredentials
+from derapi.models.hidden_enphase_partner_app_credentials import HiddenEnphasePartnerAppCredentials
+
+
+def test_create_credentials(client: Client):
+ credentials = create_vendor_credentials.sync(
+ client=client,
+ body=CreateVendorCredentialsRequest(
+ name="hi",
+ credentials=EnphasePartnerAppCredentials(
+ client_id="client_id",
+ client_secret="".join(random.sample("abcdefghijklmnopqrstuvwxyz", 10)),
+ api_key="api_key",
+ ),
+ ),
+ )
+ assert credentials is not None
+ assert isinstance(credentials.credentials, HiddenEnphasePartnerAppCredentials)
+
+ delete_vendor_credentials.sync_detailed(credentials.id, client=client)
diff --git a/tests/test_sites.py b/tests/test_sites.py
new file mode 100644
index 0000000..65bffeb
--- /dev/null
+++ b/tests/test_sites.py
@@ -0,0 +1,36 @@
+from typing import Any, Generator
+
+import pytest
+
+from derapi import Client
+from derapi.api.sites import get_site, list_sites
+from derapi.api.virtual import create_virtual_site, delete_virtual_site
+from derapi.models.create_virtual_site_request import CreateVirtualSiteRequest
+from derapi.models.create_virtual_site_response import CreateVirtualSiteResponse
+from derapi.models.vendor import Vendor
+
+
+@pytest.fixture(scope="module")
+def virtual_site(virtual_client: Client) -> Generator[CreateVirtualSiteResponse, Any, Any]:
+ virtual_site = create_virtual_site.sync(
+ client=virtual_client,
+ body=CreateVirtualSiteRequest(name="My test site"),
+ )
+ assert virtual_site is not None
+
+ yield virtual_site
+
+ delete_virtual_site.sync_detailed(virtual_site.id, client=virtual_client)
+
+
+def test_get_site(virtual_client: Client, virtual_site: CreateVirtualSiteResponse) -> None:
+ site = get_site.sync(virtual_site.id, client=virtual_client)
+ assert site is not None
+
+ assert site.name == "My test site"
+ assert site.vendor == Vendor.VIRTUAL
+
+
+def test_list_sites(virtual_client: Client, virtual_site: CreateVirtualSiteResponse) -> None:
+ sites = list_sites.sync_depaginated(client=virtual_client)
+ assert any(site.id == virtual_site.id for site in sites)
diff --git a/tests/test_solar_inverters.py b/tests/test_solar_inverters.py
new file mode 100644
index 0000000..5913831
--- /dev/null
+++ b/tests/test_solar_inverters.py
@@ -0,0 +1,73 @@
+from datetime import datetime, timedelta, timezone
+from typing import Iterator
+
+import pytest
+
+from derapi.api.solar_inverters import (
+ get_solar_inverter,
+ get_solar_inverter_intervals,
+ list_solar_inverters,
+)
+from derapi.api.virtual import (
+ create_virtual_solar_inverter,
+ delete_virtual_solar_inverter,
+)
+from derapi.client import Client
+from derapi.models.create_virtual_solar_inverter_request import (
+ CreateVirtualSolarInverterRequest,
+)
+from derapi.models.create_virtual_solar_inverter_response import (
+ CreateVirtualSolarInverterResponse,
+)
+from derapi.models.vendor import Vendor
+from derapi.models.virtual_solar_inverter import VirtualSolarInverter
+
+
+@pytest.fixture(scope="module")
+def virtual_inverter(virtual_client: Client) -> Iterator[CreateVirtualSolarInverterResponse]:
+ virtual_inverter = create_virtual_solar_inverter.sync(
+ client=virtual_client,
+ body=CreateVirtualSolarInverterRequest(name="My test inverter"),
+ )
+ assert virtual_inverter is not None
+
+ yield virtual_inverter
+
+ delete_virtual_solar_inverter.sync_detailed(virtual_inverter.id, client=virtual_client)
+
+
+def test_get_solar_inverter(
+ virtual_client: Client,
+ virtual_inverter: VirtualSolarInverter,
+) -> None:
+ inverter = get_solar_inverter.sync(virtual_inverter.id, client=virtual_client)
+ assert inverter is not None
+
+ assert inverter.name == "My test inverter"
+ assert inverter.vendor == Vendor.VIRTUAL
+
+
+def test_list_solar_inverters(
+ virtual_client: Client,
+ virtual_inverter: CreateVirtualSolarInverterResponse,
+) -> None:
+ inverters = list_solar_inverters.sync_depaginated(client=virtual_client)
+ assert inverters is not None
+
+ assert any(inverter.id == virtual_inverter.id for inverter in inverters)
+
+
+def test_list_solar_inverter_intervals(
+ virtual_client: Client,
+ virtual_inverter: CreateVirtualSolarInverterResponse,
+) -> None:
+ intervals = get_solar_inverter_intervals.sync(
+ virtual_inverter.id,
+ start=datetime.now(timezone.utc) - timedelta(hours=25),
+ end=datetime.now(timezone.utc) - timedelta(hours=1),
+ client=virtual_client,
+ )
+ assert intervals is not None
+
+ assert len(intervals.intervals) > 0
+ assert intervals.intervals[0].start.tzinfo is not None