orb-cloud-client 1.3.2__tar.gz → 1.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. {orb_cloud_client-1.3.2/orb_cloud_client.egg-info → orb_cloud_client-1.4.0}/PKG-INFO +1 -1
  2. orb_cloud_client-1.4.0/orb_cloud_client/client.py +216 -0
  3. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client/models/__init__.py +1 -1
  4. orb_cloud_client-1.4.0/orb_cloud_client/models/config.py +34 -0
  5. orb_cloud_client-1.4.0/orb_cloud_client/models/db.py +29 -0
  6. orb_cloud_client-1.4.0/orb_cloud_client/models/server.py +111 -0
  7. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0/orb_cloud_client.egg-info}/PKG-INFO +1 -1
  8. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/pyproject.toml +1 -1
  9. orb_cloud_client-1.3.2/orb_cloud_client/client.py +0 -119
  10. orb_cloud_client-1.3.2/orb_cloud_client/models/config.py +0 -36
  11. orb_cloud_client-1.3.2/orb_cloud_client/models/db.py +0 -26
  12. orb_cloud_client-1.3.2/orb_cloud_client/models/server.py +0 -46
  13. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/LICENSE +0 -0
  14. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/MANIFEST.in +0 -0
  15. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/README.md +0 -0
  16. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client/__init__.py +0 -0
  17. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client/example.py +0 -0
  18. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client/example_async.py +0 -0
  19. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client/models/generic.py +0 -0
  20. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client.egg-info/SOURCES.txt +0 -0
  21. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client.egg-info/dependency_links.txt +0 -0
  22. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client.egg-info/entry_points.txt +0 -0
  23. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client.egg-info/requires.txt +0 -0
  24. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/orb_cloud_client.egg-info/top_level.txt +0 -0
  25. {orb_cloud_client-1.3.2 → orb_cloud_client-1.4.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orb-cloud-client
3
- Version: 1.3.2
3
+ Version: 1.4.0
4
4
  Summary: Python client library for Orb Cloud API
5
5
  Author-email: Orb Networks <support@orb.net>
6
6
  License-Expression: MIT
@@ -0,0 +1,216 @@
1
+ """
2
+ Simple HTTP client for Orb Cloud API.
3
+ """
4
+
5
+ import httpx
6
+ from typing import Dict, Any, Optional, List
7
+
8
+ from .models.generic import Device, TempDatasetsRequest, Organization
9
+ from .models.server import OrganizationConfigurationsResponse, OrganizationDeviceConfigurationDeleteRequest
10
+
11
+ class OrbCloudClientBase(object):
12
+ def __init__(self, base_url: str = "https://panel.orb.net", token: Optional[str] = None):
13
+ self.base_url = base_url.rstrip('/')
14
+ self.headers = {"Content-Type": "application/json"}
15
+ if token:
16
+ self.headers["Authorization"] = f"Bearer {token}"
17
+
18
+ def _get_organization_devices(self, response: httpx.Response) -> List[Device]:
19
+ """Get list of devices for the organization from a response."""
20
+ response.raise_for_status()
21
+ return [Device(**device) for device in response.json()]
22
+
23
+ def _configure_temporary_datasets(self, response: httpx.Response) -> Dict[str, Any]:
24
+ """Process the response for configuring temporary datasets."""
25
+ response.raise_for_status()
26
+ return response.json()
27
+
28
+ def _trigger_speedtest(self, response: httpx.Response) -> Dict[str, Any]:
29
+ """Process the response for triggering a speedtest."""
30
+ response.raise_for_status()
31
+ return response.json()
32
+
33
+ def _get_organizations(self, response: httpx.Response) -> List[Organization]:
34
+ """Get list of organizations accessible with the provided token."""
35
+ response.raise_for_status()
36
+ return [Organization(**org) for org in response.json()]
37
+
38
+ def _get_organization_configurations(self, response: httpx.Response) -> List[OrganizationConfigurationsResponse]:
39
+ """Get list of configurations for an organization."""
40
+ response.raise_for_status()
41
+ return [OrganizationConfigurationsResponse(**config) for config in response.json()]
42
+
43
+ def _get_organization_device_configuration(self, response: httpx.Response) -> Dict[str, Any]:
44
+ """Get the current device configuration."""
45
+ response.raise_for_status()
46
+ return response.json()
47
+
48
+ def _patch_organization_device_configuration(self, response: httpx.Response) -> Dict[str, Any]:
49
+ """Process the response for patching device configuration."""
50
+ response.raise_for_status()
51
+ return response.json()
52
+
53
+ def _delete_organization_device_configuration(self, response: httpx.Response) -> Dict[str, Any]:
54
+ """Process the response for deleting device configuration override."""
55
+ response.raise_for_status()
56
+ return response.json()
57
+
58
+ def _push_organization_device_temp_datasets(self, response: httpx.Response) -> Dict[str, Any]:
59
+ """Process the response for enabling temporary datasets for a device."""
60
+ response.raise_for_status()
61
+ return response.json()
62
+
63
+ def _organization_device_trigger_speedtest(self, response: httpx.Response) -> Dict[str, Any]:
64
+ """Process the response for triggering speedtest on an organization device."""
65
+ response.raise_for_status()
66
+ return response.json()
67
+
68
+ class OrbCloudClient(OrbCloudClientBase):
69
+ """Simple HTTP client for Orb Cloud API."""
70
+
71
+ def __init__(self, base_url: str = "https://panel.orb.net", token: Optional[str] = None):
72
+ super().__init__(base_url, token)
73
+ self.client = httpx.Client(base_url=self.base_url, headers=self.headers)
74
+
75
+ def __enter__(self):
76
+ return self
77
+
78
+ def __exit__(self, exc_type, exc_val, exc_tb):
79
+ self.client.close()
80
+
81
+ def close(self):
82
+ """Close the HTTP client."""
83
+ self.client.close()
84
+
85
+ def get_organization_devices(self, organization_id: str) -> List[Device]:
86
+ """Get list of devices for the organization."""
87
+ response = self.client.get(f"/api/v2/organization/{organization_id}/devices")
88
+ return self._get_organization_devices(response)
89
+
90
+ def configure_temporary_datasets(self, device_id: str, temp_datasets_request: TempDatasetsRequest) -> Dict[str, Any]:
91
+ """Enable temporary data reporting to a custom endpoint with a given config for a specified duration."""
92
+ response = self.client.post(f"/api/v1/device/{device_id}/temp-datasets", json=temp_datasets_request.model_dump())
93
+ return self._configure_temporary_datasets(response)
94
+
95
+ def get_organizations(self) -> List[Organization]:
96
+ """Get list of organizations accessible with the provided token."""
97
+ response = self.client.get("/api/v2/organizations")
98
+ return self._get_organizations(response)
99
+
100
+ def trigger_speedtest(self, device_id: str, test_type: str) -> Dict[str, Any]:
101
+ """Trigger a content or top speedtest"""
102
+ response = self.client.post(f"/api/v2/device/{device_id}/trigger-speedtest/{test_type}")
103
+ return self._trigger_speedtest(response)
104
+
105
+ def get_organization_configurations(self, organization_id: str) -> List[OrganizationConfigurationsResponse]:
106
+ """Get list of configurations for the organization."""
107
+ response = self.client.get(f"/api/v1/organization/{organization_id}/configurations")
108
+ return self._get_organization_configurations(response)
109
+
110
+ def get_organization_device_configuration(self, organization_id: str, orb_id: str) -> Dict[str, Any]:
111
+ """Get the current device configuration."""
112
+ response = self.client.get(f"/api/v2/organization/{organization_id}/devices/{orb_id}/configuration")
113
+ return self._get_organization_device_configuration(response)
114
+
115
+ def patch_organization_device_configuration(self, organization_id: str, orb_id: str, config_patch: Dict[str, Any]) -> Dict[str, Any]:
116
+ """Patch the current device configuration and set it as an override for the device."""
117
+ response = self.client.patch(f"/api/v2/organization/{organization_id}/devices/{orb_id}/configuration", json=config_patch)
118
+ return self._patch_organization_device_configuration(response)
119
+
120
+ def delete_organization_device_configuration(self, organization_id: str, orb_id: str, configuration_id: Optional[str] = None) -> Dict[str, Any]:
121
+ """Delete device configuration override. Optionally set a specific configuration to fallback to."""
122
+ body = {}
123
+ if configuration_id:
124
+ body = OrganizationDeviceConfigurationDeleteRequest(configuration_id=configuration_id).model_dump(exclude_none=True)
125
+ response = self.client.delete(f"/api/v2/organization/{organization_id}/devices/{orb_id}/configuration", json=body if body else None)
126
+ return self._delete_organization_device_configuration(response)
127
+
128
+ def push_organization_device_temp_datasets(self, organization_id: str, orb_id: str, temp_datasets_request: TempDatasetsRequest) -> Dict[str, Any]:
129
+ """Enable temporary datasets for a specific device in the organization."""
130
+ response = self.client.post(f"/api/v2/organization/{organization_id}/devices/{orb_id}/temp-datasets", json=temp_datasets_request.model_dump())
131
+ return self._push_organization_device_temp_datasets(response)
132
+
133
+ def organization_device_trigger_speedtest(self, organization_id: str, orb_id: str, test_type: str) -> Dict[str, Any]:
134
+ """Trigger a speedtest on a specific device in the organization."""
135
+ response = self.client.post(f"/api/v2/organization/{organization_id}/devices/{orb_id}/trigger-speedtest/{test_type}")
136
+ return self._organization_device_trigger_speedtest(response)
137
+
138
+
139
+ def request(self, method: str, endpoint: str, **kwargs) -> httpx.Response:
140
+ """Make a raw HTTP request for any other endpoints."""
141
+ return self.client.request(method, endpoint, **kwargs)
142
+
143
+
144
+ class OrbCloudClientAsync(OrbCloudClientBase):
145
+ """Simple async HTTP client for Orb Cloud API."""
146
+
147
+ def __init__(self, base_url: str = "https://panel.orb.net", token: Optional[str] = None):
148
+ super().__init__(base_url, token)
149
+ self.client = httpx.AsyncClient(base_url=self.base_url, headers=self.headers)
150
+
151
+ async def __aenter__(self):
152
+ return self
153
+
154
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
155
+ await self.client.aclose()
156
+
157
+ async def close(self):
158
+ """Close the HTTP client."""
159
+ await self.client.aclose()
160
+
161
+ async def get_organization_devices(self, organization_id: str) -> List[Device]:
162
+ """Get list of devices for the organization."""
163
+ response = await self.client.get(f"/api/v2/organization/{organization_id}/devices")
164
+ return self._get_organization_devices(response)
165
+
166
+ async def configure_temporary_datasets(self, device_id: str, temp_datasets_request: TempDatasetsRequest) -> Dict[str, Any]:
167
+ """Enable temporary data reporting to a custom endpoint with a given config for a specified duration."""
168
+ response = await self.client.post(f"/api/v1/device/{device_id}/temp-datasets", json=temp_datasets_request.model_dump())
169
+ return self._configure_temporary_datasets(response)
170
+
171
+ async def get_organizations(self) -> List[Organization]:
172
+ """Get list of organizations accessible with the provided token."""
173
+ response = await self.client.get("/api/v2/organizations")
174
+ return self._get_organizations(response)
175
+
176
+ async def trigger_speedtest(self, device_id: str, test_type: str) -> Dict[str, Any]:
177
+ """Trigger a content or top speedtest"""
178
+ response = await self.client.post(f"/api/v2/device/{device_id}/trigger-speedtest/{test_type}")
179
+ return self._trigger_speedtest(response)
180
+
181
+ async def get_organization_configurations(self, organization_id: str) -> List[OrganizationConfigurationsResponse]:
182
+ """Get list of configurations for the organization."""
183
+ response = await self.client.get(f"/api/v1/organization/{organization_id}/configurations")
184
+ return self._get_organization_configurations(response)
185
+
186
+ async def get_organization_device_configuration(self, organization_id: str, orb_id: str) -> Dict[str, Any]:
187
+ """Get the current device configuration."""
188
+ response = await self.client.get(f"/api/v2/organization/{organization_id}/devices/{orb_id}/configuration")
189
+ return self._get_organization_device_configuration(response)
190
+
191
+ async def patch_organization_device_configuration(self, organization_id: str, orb_id: str, config_patch: Dict[str, Any]) -> Dict[str, Any]:
192
+ """Patch the current device configuration and set it as an override for the device."""
193
+ response = await self.client.patch(f"/api/v2/organization/{organization_id}/devices/{orb_id}/configuration", json=config_patch)
194
+ return self._patch_organization_device_configuration(response)
195
+
196
+ async def delete_organization_device_configuration(self, organization_id: str, orb_id: str, configuration_id: Optional[str] = None) -> Dict[str, Any]:
197
+ """Delete device configuration override. Optionally set a specific configuration to fallback to."""
198
+ body = {}
199
+ if configuration_id:
200
+ body = OrganizationDeviceConfigurationDeleteRequest(configuration_id=configuration_id).model_dump(exclude_none=True)
201
+ response = await self.client.delete(f"/api/v2/organization/{organization_id}/devices/{orb_id}/configuration", json=body if body else None)
202
+ return self._delete_organization_device_configuration(response)
203
+
204
+ async def push_organization_device_temp_datasets(self, organization_id: str, orb_id: str, temp_datasets_request: TempDatasetsRequest) -> Dict[str, Any]:
205
+ """Enable temporary datasets for a specific device in the organization."""
206
+ response = await self.client.post(f"/api/v2/organization/{organization_id}/devices/{orb_id}/temp-datasets", json=temp_datasets_request.model_dump())
207
+ return self._push_organization_device_temp_datasets(response)
208
+
209
+ async def organization_device_trigger_speedtest(self, organization_id: str, orb_id: str, test_type: str) -> Dict[str, Any]:
210
+ """Trigger a speedtest on a specific device in the organization."""
211
+ response = await self.client.post(f"/api/v2/organization/{organization_id}/devices/{orb_id}/trigger-speedtest/{test_type}")
212
+ return self._organization_device_trigger_speedtest(response)
213
+
214
+ async def request(self, method: str, endpoint: str, **kwargs) -> httpx.Response:
215
+ """Make a raw async HTTP request for any other endpoints."""
216
+ return await self.client.request(method, endpoint, **kwargs)
@@ -1,3 +1,3 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: openapi.yaml
3
- # timestamp: 2025-12-18T14:54:46+00:00
3
+ # timestamp: 2026-04-01T13:20:02+00:00
@@ -0,0 +1,34 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: openapi.yaml
3
+ # timestamp: 2026-04-01T13:20:02+00:00
4
+
5
+ from __future__ import annotations
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class DataAPI(BaseModel):
11
+ api_key: str | None = None
12
+ buffer: int | None = None
13
+ datasets: list[str] | None = None
14
+ enabled: bool | None = None
15
+ identifiable: bool | None = None
16
+ port: int | None = None
17
+
18
+
19
+ class DataPush(BaseModel):
20
+ buffer_kb: int | None = None
21
+ datasets: list[str] | None = None
22
+ enabled: bool | None = None
23
+ format: str | None = None
24
+ identifiable: bool | None = None
25
+ interval_ms: int | None = None
26
+ url: str | None = None
27
+
28
+
29
+ class Datasets(BaseModel):
30
+ api: DataAPI | None = None
31
+ cloud_push: DataPush | None = None
32
+ datasets: list[str] | None = None
33
+ enabled: bool | None = None
34
+ push: DataPush | None = None
@@ -0,0 +1,29 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: openapi.yaml
3
+ # timestamp: 2026-04-01T13:20:02+00:00
4
+
5
+ from __future__ import annotations
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class AccountConfigEntitlements(BaseModel):
11
+ entitlements: list[str] | None = None
12
+
13
+
14
+ class AccountPlanLimits(BaseModel):
15
+ deployment_tokens: int | None = None
16
+ devices: int | None = None
17
+ spaces: int | None = None
18
+ users: int | None = None
19
+
20
+
21
+ class OrganizationDeviceMetadata(BaseModel):
22
+ invite_id: str | None = None
23
+
24
+
25
+ class AccountPlan(BaseModel):
26
+ config: AccountConfigEntitlements | None = None
27
+ features: list[str] | None = None
28
+ limits: AccountPlanLimits | None = None
29
+ name: str | None = None
@@ -0,0 +1,111 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: openapi.yaml
3
+ # timestamp: 2026-04-01T13:20:02+00:00
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from pydantic import BaseModel, Field
10
+
11
+ from . import config as config_1
12
+ from . import db
13
+
14
+
15
+ class DeviceLinkOrganization(BaseModel):
16
+ icon_image_url: str | None = None
17
+ name: str | None = None
18
+ organization_id: str | None = None
19
+
20
+
21
+ class DeviceLinkOrganizationInvite(BaseModel):
22
+ description: str | None = None
23
+ icon_image_url: str | None = None
24
+ id: str | None = None
25
+ name: str | None = None
26
+
27
+
28
+ class OrganizationConfigurationsResponse(BaseModel):
29
+ access_code: str | None = Field(
30
+ None, description='optional, the access code for this configuration'
31
+ )
32
+ access_code_expiration_ts: str | None = Field(
33
+ None, description='optional, expiration time for the access code'
34
+ )
35
+ config: list[int] | None = None
36
+ created_at: str | None = None
37
+ devices: int | None = Field(None, description='number of devices using this token')
38
+ id: str | None = None
39
+ is_revoked: bool | None = Field(
40
+ None, description='true if the token is revoked, false otherwise'
41
+ )
42
+ last_used_at: str | None = Field(
43
+ None, description='optional, if the token has been used'
44
+ )
45
+ name: str | None = None
46
+ tags: list[int] | None = None
47
+ token: str | None = None
48
+ updated_at: str | None = None
49
+
50
+
51
+ class OrganizationDeviceConfigurationDeleteRequest(BaseModel):
52
+ configuration_id: str | None = Field(
53
+ None, description='optional ID of the configuration to delete'
54
+ )
55
+
56
+
57
+ class OrganizationDeviceLink(BaseModel):
58
+ expiration_ts: str | None = None
59
+ invite: DeviceLinkOrganizationInvite | None = None
60
+ metadata: db.OrganizationDeviceMetadata | None = None
61
+ organization: DeviceLinkOrganization | None = None
62
+ relationship: str | None = None
63
+
64
+
65
+ class OrganizationDeviceResponse(BaseModel):
66
+ can_notify: bool | None = None
67
+ config: dict[str, Any] | None = Field(
68
+ None, description='device configuration, if available'
69
+ )
70
+ configuration_id: str | None = Field(
71
+ None, description='device configuration ID, if available'
72
+ )
73
+ is_connected: int | None = None
74
+ is_connected_updated_at: str | None = None
75
+ links: list[OrganizationDeviceLink] | None = Field(
76
+ None, description='links for device'
77
+ )
78
+ name: str | None = None
79
+ orb_id: str | None = None
80
+ relationship: str | None = Field(
81
+ None, description='organization-device relationship type'
82
+ )
83
+ summary: dict[str, Any] | None = Field(
84
+ None, description='last received summary from the device'
85
+ )
86
+ tags: dict[str, Any] | None = Field(
87
+ None, description='list of tags associated with the device'
88
+ )
89
+
90
+
91
+ class OrganizationManager(BaseModel):
92
+ icon_image_url: str | None = None
93
+ name: str | None = None
94
+ organization_id: str | None = None
95
+
96
+
97
+ class DatasetsRequest(BaseModel):
98
+ datasets_config: config_1.Datasets | None = None
99
+ duration: str | None = None
100
+
101
+
102
+ class OrganizationsResponse(BaseModel):
103
+ allocations: db.AccountPlanLimits | None = None
104
+ customer_id: str | None = None
105
+ icon_image_url: str | None = None
106
+ manager: OrganizationManager | None = None
107
+ name: str | None = None
108
+ organization_id: str | None = None
109
+ plan: db.AccountPlan | None = None
110
+ subscription_id: str | None = None
111
+ usage: db.AccountPlanLimits | None = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orb-cloud-client
3
- Version: 1.3.2
3
+ Version: 1.4.0
4
4
  Summary: Python client library for Orb Cloud API
5
5
  Author-email: Orb Networks <support@orb.net>
6
6
  License-Expression: MIT
@@ -27,7 +27,7 @@ license = "MIT"
27
27
  name = "orb-cloud-client"
28
28
  readme = "README.md"
29
29
  requires-python = ">=3.8"
30
- version = "1.3.2"
30
+ version = "1.4.0"
31
31
 
32
32
  [project.optional-dependencies]
33
33
  dev = [
@@ -1,119 +0,0 @@
1
- """
2
- Simple HTTP client for Orb Cloud API.
3
- """
4
-
5
- import httpx
6
- from typing import Dict, Any, Optional, List
7
-
8
- from .models.generic import Device, TempDatasetsRequest, Organization
9
-
10
- class OrbCloudClientBase(object):
11
- def __init__(self, base_url: str = "https://panel.orb.net", token: Optional[str] = None):
12
- self.base_url = base_url.rstrip('/')
13
- self.headers = {"Content-Type": "application/json"}
14
- if token:
15
- self.headers["Authorization"] = f"Bearer {token}"
16
-
17
- def _get_organization_devices(self, response: httpx.Response) -> List[Device]:
18
- """Get list of devices for the organization from a response."""
19
- response.raise_for_status()
20
- return [Device(**device) for device in response.json()]
21
-
22
- def _configure_temporary_datasets(self, response: httpx.Response) -> Dict[str, Any]:
23
- """Process the response for configuring temporary datasets."""
24
- response.raise_for_status()
25
- return response.json()
26
-
27
- def _trigger_speedtest(self, response: httpx.Response) -> Dict[str, Any]:
28
- """Process the response for triggering a speedtest."""
29
- response.raise_for_status()
30
- return response.json()
31
-
32
- def _get_organizations(self, response: httpx.Response) -> List[Organization]:
33
- """Get list of organizations accessible with the provided token."""
34
- response.raise_for_status()
35
- return [Organization(**org) for org in response.json()]
36
-
37
- class OrbCloudClient(OrbCloudClientBase):
38
- """Simple HTTP client for Orb Cloud API."""
39
-
40
- def __init__(self, base_url: str = "https://panel.orb.net", token: Optional[str] = None):
41
- super().__init__(base_url, token)
42
- self.client = httpx.Client(base_url=self.base_url, headers=self.headers)
43
-
44
- def __enter__(self):
45
- return self
46
-
47
- def __exit__(self, exc_type, exc_val, exc_tb):
48
- self.client.close()
49
-
50
- def close(self):
51
- """Close the HTTP client."""
52
- self.client.close()
53
-
54
- def get_organization_devices(self, organization_id: str) -> List[Device]:
55
- """Get list of devices for the organization."""
56
- response = self.client.get(f"/api/v2/organization/{organization_id}/devices")
57
- return self._get_organization_devices(response)
58
-
59
- def configure_temporary_datasets(self, device_id: str, temp_datasets_request: TempDatasetsRequest) -> Dict[str, Any]:
60
- """Enable temporary data reporting to a custom endpoint with a given config for a specified duration."""
61
- response = self.client.post(f"/api/v1/device/{device_id}/temp-datasets", json=temp_datasets_request.model_dump())
62
- return self._configure_temporary_datasets(response)
63
-
64
- def get_organizations(self) -> List[Organization]:
65
- """Get list of organizations accessible with the provided token."""
66
- response = self.client.get("/api/v2/organizations")
67
- return self._get_organizations(response)
68
-
69
- def trigger_speedtest(self, device_id: str, test_type: str) -> Dict[str, Any]:
70
- """Trigger a content or top speedtest"""
71
- response = self.client.post(f"/api/v2/device/{device_id}/trigger-speedtest/{test_type}")
72
- return self._trigger_speedtest(response)
73
-
74
-
75
- def request(self, method: str, endpoint: str, **kwargs) -> httpx.Response:
76
- """Make a raw HTTP request for any other endpoints."""
77
- return self.client.request(method, endpoint, **kwargs)
78
-
79
-
80
- class OrbCloudClientAsync(OrbCloudClientBase):
81
- """Simple async HTTP client for Orb Cloud API."""
82
-
83
- def __init__(self, base_url: str = "https://panel.orb.net", token: Optional[str] = None):
84
- super().__init__(base_url, token)
85
- self.client = httpx.AsyncClient(base_url=self.base_url, headers=self.headers)
86
-
87
- async def __aenter__(self):
88
- return self
89
-
90
- async def __aexit__(self, exc_type, exc_val, exc_tb):
91
- await self.client.aclose()
92
-
93
- async def close(self):
94
- """Close the HTTP client."""
95
- await self.client.aclose()
96
-
97
- async def get_organization_devices(self, organization_id: str) -> List[Device]:
98
- """Get list of devices for the organization."""
99
- response = await self.client.get(f"/api/v2/organization/{organization_id}/devices")
100
- return self._get_organization_devices(response)
101
-
102
- async def configure_temporary_datasets(self, device_id: str, temp_datasets_request: TempDatasetsRequest) -> Dict[str, Any]:
103
- """Enable temporary data reporting to a custom endpoint with a given config for a specified duration."""
104
- response = await self.client.post(f"/api/v1/device/{device_id}/temp-datasets", json=temp_datasets_request.model_dump())
105
- return self._configure_temporary_datasets(response)
106
-
107
- async def get_organizations(self) -> List[Organization]:
108
- """Get list of organizations accessible with the provided token."""
109
- response = await self.client.get("/api/v2/organizations")
110
- return self._get_organizations(response)
111
-
112
- async def trigger_speedtest(self, device_id: str, test_type: str) -> Dict[str, Any]:
113
- """Trigger a content or top speedtest"""
114
- response = await self.client.post(f"/api/v2/device/{device_id}/trigger-speedtest/{test_type}")
115
- return self._trigger_speedtest(response)
116
-
117
- async def request(self, method: str, endpoint: str, **kwargs) -> httpx.Response:
118
- """Make a raw async HTTP request for any other endpoints."""
119
- return await self.client.request(method, endpoint, **kwargs)
@@ -1,36 +0,0 @@
1
- # generated by datamodel-codegen:
2
- # filename: openapi.yaml
3
- # timestamp: 2025-12-18T14:54:46+00:00
4
-
5
- from __future__ import annotations
6
-
7
- from typing import List, Optional
8
-
9
- from pydantic import BaseModel
10
-
11
-
12
- class DataAPI(BaseModel):
13
- api_key: Optional[str] = None
14
- buffer: Optional[int] = None
15
- datasets: Optional[List[str]] = None
16
- enabled: Optional[bool] = None
17
- identifiable: Optional[bool] = None
18
- port: Optional[int] = None
19
-
20
-
21
- class DataPush(BaseModel):
22
- buffer_kb: Optional[int] = None
23
- datasets: Optional[List[str]] = None
24
- enabled: Optional[bool] = None
25
- format: Optional[str] = None
26
- identifiable: Optional[bool] = None
27
- interval_ms: Optional[int] = None
28
- url: Optional[str] = None
29
-
30
-
31
- class Datasets(BaseModel):
32
- api: Optional[DataAPI] = None
33
- cloud_push: Optional[DataPush] = None
34
- datasets: Optional[List[str]] = None
35
- enabled: Optional[bool] = None
36
- push: Optional[DataPush] = None
@@ -1,26 +0,0 @@
1
- # generated by datamodel-codegen:
2
- # filename: openapi.yaml
3
- # timestamp: 2025-12-18T14:54:46+00:00
4
-
5
- from __future__ import annotations
6
-
7
- from typing import List, Optional
8
-
9
- from pydantic import BaseModel
10
-
11
-
12
- class AccountConfigEntitlements(BaseModel):
13
- entitlements: Optional[List[str]] = None
14
-
15
-
16
- class AccountPlanLimits(BaseModel):
17
- deployment_tokens: Optional[int] = None
18
- devices: Optional[int] = None
19
- users: Optional[int] = None
20
-
21
-
22
- class AccountPlan(BaseModel):
23
- config: Optional[AccountConfigEntitlements] = None
24
- features: Optional[List[str]] = None
25
- limits: Optional[AccountPlanLimits] = None
26
- name: Optional[str] = None
@@ -1,46 +0,0 @@
1
- # generated by datamodel-codegen:
2
- # filename: openapi.yaml
3
- # timestamp: 2025-12-18T14:54:46+00:00
4
-
5
- from __future__ import annotations
6
-
7
- from typing import Any, Dict, Optional
8
-
9
- from pydantic import BaseModel, Field
10
-
11
- from . import config as config_1
12
- from . import db
13
-
14
-
15
- class OrganizationDeviceResponse(BaseModel):
16
- can_notify: Optional[bool] = None
17
- config: Optional[Dict[str, Any]] = Field(
18
- None, description='device configuration, if available'
19
- )
20
- configuration_id: Optional[str] = Field(
21
- None, description='device configuration ID, if available'
22
- )
23
- is_connected: Optional[int] = None
24
- is_connected_updated_at: Optional[str] = None
25
- name: Optional[str] = None
26
- orb_id: Optional[str] = None
27
- summary: Optional[Dict[str, Any]] = Field(
28
- None, description='last received summary from the device'
29
- )
30
- tags: Optional[Dict[str, Any]] = Field(
31
- None, description='list of tags associated with the device'
32
- )
33
-
34
-
35
- class DatasetsRequest(BaseModel):
36
- datasets_config: Optional[config_1.Datasets] = None
37
- duration: Optional[str] = None
38
-
39
-
40
- class OrganizationsResponse(BaseModel):
41
- customer_id: Optional[str] = None
42
- name: Optional[str] = None
43
- organization_id: Optional[str] = None
44
- plan: Optional[db.AccountPlan] = None
45
- subscription_id: Optional[str] = None
46
- usage: Optional[db.AccountPlanLimits] = None