koios-client 1.0.0rc1__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.
- koios_client-1.0.0rc1/PKG-INFO +537 -0
- koios_client-1.0.0rc1/README.md +508 -0
- koios_client-1.0.0rc1/pyproject.toml +117 -0
- koios_client-1.0.0rc1/setup.cfg +4 -0
- koios_client-1.0.0rc1/src/koios_client/__init__.py +80 -0
- koios_client-1.0.0rc1/src/koios_client/_auth.py +214 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/__init__.py +1424 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/acknowledge_all_events.py +40 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/acknowledge_event.py +40 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/acknowledge_events.py +40 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/base_client.py +199 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/base_model.py +30 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/client.py +4245 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_component_environment.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_component_instance.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_device.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_device_set.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_endpoint_client.py +41 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_local_value.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_model.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_scan_group.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_tag.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_trend.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_trend_item.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/create_wire.py +37 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_component_environment.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_component_instance.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_component_library.py +43 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_device.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_device_set.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_device_sets.py +17 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_devices.py +17 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_endpoint_client.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_events.py +17 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_local_value.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_local_values.py +19 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_model.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_models.py +17 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_scan_group.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_scan_groups.py +17 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_tag.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_tags.py +17 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_trend.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_trend_item.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/delete_wire.py +37 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/duplicate_device.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/duplicate_model.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/duplicate_tag.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/duplicate_trend.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/enums.py +527 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/exceptions.py +85 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_bindings.py +97 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_definition.py +44 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_definitions.py +42 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_environment.py +69 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_environment_live.py +30 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_environments.py +40 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_environments_live.py +35 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_instance.py +56 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_instances.py +50 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_libraries.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_library.py +73 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_component_library_groups.py +36 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_device.py +111 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_device_live.py +32 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_device_set.py +37 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_device_sets.py +43 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_devices.py +53 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_devices_live.py +37 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_endpoint_client.py +48 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_endpoint_clients.py +49 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_event_count_summary.py +18 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_events.py +61 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_failed_counts.py +19 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_license_detail.py +26 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_local_values.py +45 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_model.py +121 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_model_files.py +46 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_model_live.py +57 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_models.py +70 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_models_live.py +62 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_platform_version.py +29 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_protocol.py +32 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_protocols.py +32 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_scan_group.py +54 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_scan_group_live.py +31 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_scan_groups.py +40 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_scan_groups_live.py +36 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_services.py +33 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_system_health.py +17 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_system_info.py +35 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_tag.py +127 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_tag_history.py +29 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_tag_live.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_tags.py +76 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_tags_history.py +32 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_tags_live.py +44 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_trend.py +72 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_trend_items.py +58 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_trends.py +32 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/get_wires.py +74 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/input_types.py +1748 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/mark_all_events_seen.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/mark_event_seen.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/obtain_client_token.py +40 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/refresh_token.py +40 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/regenerate_client_secret.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/set_endpoint_client_permissions.py +50 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/set_protocol_visible.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_binding.py +44 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_component_environment.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_component_instance.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_device.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_device_set.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_device_sets.py +19 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_devices.py +20 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_endpoint_client.py +40 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_local_value.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_local_values.py +21 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_model.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_models.py +20 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_scan_group.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_scan_groups.py +20 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_tag.py +39 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_tags.py +20 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_trend.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_trend_item.py +38 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/update_wire.py +37 -0
- koios_client-1.0.0rc1/src/koios_client/_generated/verify_token.py +10 -0
- koios_client-1.0.0rc1/src/koios_client/client.py +1105 -0
- koios_client-1.0.0rc1/src/koios_client/exceptions.py +82 -0
- koios_client-1.0.0rc1/src/koios_client/py.typed +0 -0
- koios_client-1.0.0rc1/src/koios_client/resources/__init__.py +33 -0
- koios_client-1.0.0rc1/src/koios_client/resources/_base.py +96 -0
- koios_client-1.0.0rc1/src/koios_client/resources/_helpers.py +80 -0
- koios_client-1.0.0rc1/src/koios_client/resources/bindings.py +44 -0
- koios_client-1.0.0rc1/src/koios_client/resources/device_sets.py +87 -0
- koios_client-1.0.0rc1/src/koios_client/resources/devices.py +167 -0
- koios_client-1.0.0rc1/src/koios_client/resources/models.py +191 -0
- koios_client-1.0.0rc1/src/koios_client/resources/protocols.py +54 -0
- koios_client-1.0.0rc1/src/koios_client/resources/scan_groups.py +112 -0
- koios_client-1.0.0rc1/src/koios_client/resources/tags.py +134 -0
- koios_client-1.0.0rc1/src/koios_client/types.py +138 -0
- koios_client-1.0.0rc1/src/koios_client.egg-info/PKG-INFO +537 -0
- koios_client-1.0.0rc1/src/koios_client.egg-info/SOURCES.txt +149 -0
- koios_client-1.0.0rc1/src/koios_client.egg-info/dependency_links.txt +1 -0
- koios_client-1.0.0rc1/src/koios_client.egg-info/requires.txt +9 -0
- koios_client-1.0.0rc1/src/koios_client.egg-info/top_level.txt +1 -0
- koios_client-1.0.0rc1/tests/test_auth.py +205 -0
- koios_client-1.0.0rc1/tests/test_client.py +473 -0
- koios_client-1.0.0rc1/tests/test_resources.py +850 -0
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: koios-client
|
|
3
|
+
Version: 1.0.0rc1
|
|
4
|
+
Summary: Python client library for the Koios IoT platform — typed GraphQL & REST wrapper
|
|
5
|
+
Author: Ai-OPs, Inc.
|
|
6
|
+
License: Proprietary
|
|
7
|
+
Project-URL: Homepage, https://www.ai-op.com
|
|
8
|
+
Project-URL: Documentation, https://docs.ai-op.com
|
|
9
|
+
Project-URL: Repository, https://github.com/Ai-Ops-Inc/koios-client
|
|
10
|
+
Keywords: koios,api,graphql,client,iot,industrial
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: httpx>=0.27.0
|
|
22
|
+
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
23
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: ariadne-codegen>=0.14.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-httpx>=0.30.0; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
29
|
+
|
|
30
|
+
# Koios Client
|
|
31
|
+
|
|
32
|
+
Typed Python SDK for the [Koios IoT platform](https://ai-op.com). Provides two API layers:
|
|
33
|
+
|
|
34
|
+
- **High-level resource API** — `Device`, `Tag`, `Model` objects with intuitive methods like `.enable()`, `.update()`, `.delete()`
|
|
35
|
+
- **Low-level GraphQL client** — fully-typed generated client via `client.gql` with IDE autocomplete
|
|
36
|
+
|
|
37
|
+
Plus REST helpers for file operations, import/export, backups, and trend data.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install koios-client
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or install from source:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install -e ".[dev]"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from koios_client import KoiosClient
|
|
55
|
+
|
|
56
|
+
client = KoiosClient(
|
|
57
|
+
hostname="koios.example.com",
|
|
58
|
+
client_id="your-client-uuid",
|
|
59
|
+
client_secret="your-client-secret",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# High-level resource API — fetch by ID (default) or slug
|
|
63
|
+
device = client.device(1)
|
|
64
|
+
device.enable()
|
|
65
|
+
for tag in device.tags():
|
|
66
|
+
print(tag.name, tag.value)
|
|
67
|
+
|
|
68
|
+
# Low-level GraphQL (fully typed — IDE autocomplete works)
|
|
69
|
+
result = client.gql.get_devices()
|
|
70
|
+
for device in result.devices.results:
|
|
71
|
+
print(device.name, device.status)
|
|
72
|
+
|
|
73
|
+
client.close()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Use as a context manager for automatic cleanup:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
with KoiosClient("koios.example.com", "client-id", "secret") as client:
|
|
80
|
+
device = client.device(1)
|
|
81
|
+
print(device.name, device.enabled)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## High-Level Resource API
|
|
85
|
+
|
|
86
|
+
The resource layer wraps the generated GraphQL client with intuitive Python objects. All resource classes are importable from the top-level package:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from koios_client import Device, Tag, Model, PaginatedList
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Fetching Resources
|
|
93
|
+
|
|
94
|
+
Every resource can be fetched by **ID** (default positional arg) or **slug** (UUID).
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
# By ID (default — integer database primary key)
|
|
98
|
+
device = client.device(1)
|
|
99
|
+
tag = client.tag(42)
|
|
100
|
+
model = client.model(5)
|
|
101
|
+
|
|
102
|
+
# By slug (UUID — useful when you already have the identifier)
|
|
103
|
+
device = client.device(slug="550e8400-e29b-41d4-a716-446655440000")
|
|
104
|
+
|
|
105
|
+
# By name — use the list query with filters
|
|
106
|
+
from koios_client.types import DeviceFilter, StrFilterLookup
|
|
107
|
+
devices = client.devices(filters=DeviceFilter(name=StrFilterLookup(exact="My Device")))
|
|
108
|
+
device = devices[0]
|
|
109
|
+
|
|
110
|
+
# List with filtering, ordering, and pagination
|
|
111
|
+
from koios_client.types import OffsetPaginationInput
|
|
112
|
+
|
|
113
|
+
devices = client.devices(
|
|
114
|
+
filters=DeviceFilter(enabled=True),
|
|
115
|
+
pagination=OffsetPaginationInput(limit=50),
|
|
116
|
+
)
|
|
117
|
+
print(f"{devices.total_count} total devices")
|
|
118
|
+
for device in devices:
|
|
119
|
+
print(device.name, device.slug, device.enabled)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`PaginatedList` supports iteration, indexing, `len()`, and `bool()`:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
tags = client.tags()
|
|
126
|
+
print(len(tags)) # Number of items on this page
|
|
127
|
+
print(tags.total_count) # Total matching items on server
|
|
128
|
+
first = tags[0] # Index access
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### CRUD Operations
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from koios_client.types import DeviceInput
|
|
135
|
+
|
|
136
|
+
# Create
|
|
137
|
+
device = client.create_device(DeviceInput(
|
|
138
|
+
name="New Device",
|
|
139
|
+
protocol_id="1",
|
|
140
|
+
enabled=True,
|
|
141
|
+
))
|
|
142
|
+
|
|
143
|
+
# Update (returns a fresh object with all fields refreshed)
|
|
144
|
+
device = device.update(name="Renamed Device", scan_rate=5.0)
|
|
145
|
+
|
|
146
|
+
# Enable / Disable (convenience wrappers around update)
|
|
147
|
+
device = device.enable()
|
|
148
|
+
device = device.disable()
|
|
149
|
+
|
|
150
|
+
# Duplicate
|
|
151
|
+
copy = device.duplicate("Device Copy", description="Cloned from original")
|
|
152
|
+
|
|
153
|
+
# Delete
|
|
154
|
+
device.delete()
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Parent-Child Accessors
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
# Device → Tags
|
|
161
|
+
device = client.device(1)
|
|
162
|
+
tags = device.tags(
|
|
163
|
+
filters=TagFilter(enabled=True),
|
|
164
|
+
pagination=OffsetPaginationInput(limit=100),
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Model → Bindings
|
|
168
|
+
model = client.model(5)
|
|
169
|
+
for binding in model.bindings():
|
|
170
|
+
print(binding.name, binding.usage, binding.normalization_type)
|
|
171
|
+
binding.update(normalization_type="MIN_MAX")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Bulk Operations
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
# Bulk enable / disable
|
|
178
|
+
client.enable_devices(["1", "2", "3"])
|
|
179
|
+
client.disable_tags(["10", "11", "12"])
|
|
180
|
+
|
|
181
|
+
# Bulk delete
|
|
182
|
+
client.delete_devices(["1", "2", "3"])
|
|
183
|
+
client.delete_tags(["10", "11", "12"])
|
|
184
|
+
client.delete_models(["20", "21"])
|
|
185
|
+
client.delete_scan_groups(["30", "31"])
|
|
186
|
+
client.delete_device_sets(["40", "41"])
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Live Data
|
|
190
|
+
|
|
191
|
+
Fetch real-time values from the Redis cache:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
device = client.device(1)
|
|
195
|
+
live = device.live()
|
|
196
|
+
print(live.get("status"), live.get("error_message"))
|
|
197
|
+
|
|
198
|
+
tag = client.tag(42)
|
|
199
|
+
live = tag.live()
|
|
200
|
+
print(live.get("value"), live.get("timestamp"), live.get("quality"))
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Import / Export with Resources
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
# Import with dry_run (default) — returns preview without applying
|
|
207
|
+
preview = client.import_devices("devices.csv")
|
|
208
|
+
print(preview)
|
|
209
|
+
|
|
210
|
+
# Import for real
|
|
211
|
+
result = client.import_devices("devices.csv", dry_run=False)
|
|
212
|
+
|
|
213
|
+
# Export a single device/model
|
|
214
|
+
csv_bytes = device.export_csv()
|
|
215
|
+
zip_bytes = model.export()
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### All Resource Types
|
|
219
|
+
|
|
220
|
+
All singular methods accept `id` (positional, integer) or `slug=` (UUID). Exactly one must be provided.
|
|
221
|
+
|
|
222
|
+
| Method | Returns | Notes |
|
|
223
|
+
|--------|---------|-------|
|
|
224
|
+
| `client.device(id, slug=)` | `Device` | |
|
|
225
|
+
| `client.devices(...)` | `PaginatedList[Device]` | filters, order, pagination |
|
|
226
|
+
| `client.create_device(data)` | `Device` | |
|
|
227
|
+
| `client.enable_devices(ids)` | `list[Device]` | |
|
|
228
|
+
| `client.disable_devices(ids)` | `list[Device]` | |
|
|
229
|
+
| `client.delete_devices(ids)` | `None` | |
|
|
230
|
+
| `client.import_devices(file)` | `dict` | dry_run=True by default |
|
|
231
|
+
| `client.tag(id, slug=)` | `Tag` | |
|
|
232
|
+
| `client.tags(...)` | `PaginatedList[Tag]` | |
|
|
233
|
+
| `client.create_tag(data)` | `Tag` | |
|
|
234
|
+
| `client.enable_tags(ids)` | `list[Tag]` | |
|
|
235
|
+
| `client.disable_tags(ids)` | `list[Tag]` | |
|
|
236
|
+
| `client.delete_tags(ids)` | `None` | |
|
|
237
|
+
| `client.import_tags(file)` | `dict` | dry_run=True by default |
|
|
238
|
+
| `client.model(id, slug=)` | `Model` | |
|
|
239
|
+
| `client.models(...)` | `PaginatedList[Model]` | |
|
|
240
|
+
| `client.create_model(data)` | `Model` | |
|
|
241
|
+
| `client.enable_models(ids)` | `list[Model]` | |
|
|
242
|
+
| `client.disable_models(ids)` | `list[Model]` | |
|
|
243
|
+
| `client.delete_models(ids)` | `None` | |
|
|
244
|
+
| `client.import_models(file)` | `dict` | dry_run=True by default |
|
|
245
|
+
| `client.scan_group(id, slug=)` | `ScanGroup` | |
|
|
246
|
+
| `client.scan_groups(...)` | `PaginatedList[ScanGroup]` | |
|
|
247
|
+
| `client.create_scan_group(data)` | `ScanGroup` | |
|
|
248
|
+
| `client.enable_scan_groups(ids)` | `list[ScanGroup]` | |
|
|
249
|
+
| `client.disable_scan_groups(ids)` | `list[ScanGroup]` | |
|
|
250
|
+
| `client.delete_scan_groups(ids)` | `None` | |
|
|
251
|
+
| `client.device_set(id, slug=)` | `DeviceSet` | |
|
|
252
|
+
| `client.device_sets(...)` | `PaginatedList[DeviceSet]` | |
|
|
253
|
+
| `client.create_device_set(data)` | `DeviceSet` | |
|
|
254
|
+
| `client.delete_device_sets(ids)` | `None` | |
|
|
255
|
+
| `client.protocol(id, slug=)` | `Protocol` | read-only |
|
|
256
|
+
| `client.protocols()` | `list[Protocol]` | not paginated |
|
|
257
|
+
|
|
258
|
+
### Endpoint Clients
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
# List endpoint clients
|
|
262
|
+
clients = client.endpoint_clients()
|
|
263
|
+
|
|
264
|
+
# Get a single endpoint client by ID
|
|
265
|
+
ec = client.endpoint_client("123")
|
|
266
|
+
|
|
267
|
+
# Create a new endpoint client (returns one-time secret)
|
|
268
|
+
result = client.create_endpoint_client("My Integration", description="Data pipeline")
|
|
269
|
+
|
|
270
|
+
# Set permissions
|
|
271
|
+
client.set_endpoint_client_permissions(
|
|
272
|
+
client_id="123",
|
|
273
|
+
permission_ids=["1", "2", "3"],
|
|
274
|
+
)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Low-Level GraphQL Client
|
|
278
|
+
|
|
279
|
+
All GraphQL queries and mutations are available via `client.gql` with fully typed parameters and return values.
|
|
280
|
+
|
|
281
|
+
### Querying Data
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
from koios_client.types import (
|
|
285
|
+
DeviceFilter,
|
|
286
|
+
OffsetPaginationInput,
|
|
287
|
+
StatusChoices,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# Paginated queries
|
|
291
|
+
devices = client.gql.get_devices(
|
|
292
|
+
pagination=OffsetPaginationInput(limit=50),
|
|
293
|
+
)
|
|
294
|
+
print(f"Total: {devices.devices.total_count}")
|
|
295
|
+
for device in devices.devices.results:
|
|
296
|
+
print(device.name, device.status, device.protocol.name)
|
|
297
|
+
|
|
298
|
+
# Filtered queries
|
|
299
|
+
tags = client.gql.get_tags(
|
|
300
|
+
filters=TagFilter(enabled=True),
|
|
301
|
+
pagination=OffsetPaginationInput(limit=100),
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
# Single item by slug
|
|
305
|
+
device = client.gql.get_device(slug="my-device")
|
|
306
|
+
tag = client.gql.get_tag(slug="my-tag")
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Mutations
|
|
310
|
+
|
|
311
|
+
Single-item mutations return a union of the entity type or `OperationInfo`. Use `check_operation` to unwrap:
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
from koios_client.types import DeviceInput
|
|
315
|
+
|
|
316
|
+
raw = client.gql.create_device(data=DeviceInput(
|
|
317
|
+
name="New Device",
|
|
318
|
+
protocol_id="1",
|
|
319
|
+
enabled=True,
|
|
320
|
+
))
|
|
321
|
+
|
|
322
|
+
# Raises OperationError if the server returned validation/permission errors
|
|
323
|
+
device = KoiosClient.check_operation(raw.create_device)
|
|
324
|
+
print(f"Created: {device.name} ({device.slug})")
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Available Enums
|
|
328
|
+
|
|
329
|
+
All GraphQL enums are available as typed Python enums:
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
from koios_client.types import (
|
|
333
|
+
StatusChoices, # RUNNING, STOPPED, FAILED
|
|
334
|
+
UsageChoices, # INPUT, OUTPUT, VIRTUAL
|
|
335
|
+
AggregateFunction, # MEAN, SUM, MIN, MAX, FIRST, LAST, COUNT
|
|
336
|
+
DeviceErrorCodeChoices,
|
|
337
|
+
TagErrorCodeChoices,
|
|
338
|
+
ProtocolReferenceCodeChoices, # OPCUA, MODBUS_TCP, ETHERNET_IP, ...
|
|
339
|
+
)
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## REST API
|
|
343
|
+
|
|
344
|
+
Operations that involve file uploads, background tasks, or binary responses use REST endpoints exposed directly on the client.
|
|
345
|
+
|
|
346
|
+
### Export / Import
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
# Export devices as CSV
|
|
350
|
+
csv_bytes = client.export_devices_csv()
|
|
351
|
+
with open("devices.csv", "wb") as f:
|
|
352
|
+
f.write(csv_bytes)
|
|
353
|
+
|
|
354
|
+
# Export specific tags
|
|
355
|
+
csv_bytes = client.export_tags_csv(ids=[1, 2, 3])
|
|
356
|
+
|
|
357
|
+
# Export models as ZIP (includes bindings)
|
|
358
|
+
zip_bytes = client.export_models()
|
|
359
|
+
|
|
360
|
+
# Two-step import: preview then confirm
|
|
361
|
+
preview = client.import_tags_preview("tags.csv")
|
|
362
|
+
print(f"Will import {preview['result']['total_rows']} rows")
|
|
363
|
+
if preview["can_import"]:
|
|
364
|
+
result = client.import_tags_confirm(
|
|
365
|
+
preview["tmp_storage_name"],
|
|
366
|
+
preview["file_name"],
|
|
367
|
+
)
|
|
368
|
+
print(f"Imported {result['imported_count']} tags")
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Model Files
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
# Upload a model file
|
|
375
|
+
result = client.upload_model_file(
|
|
376
|
+
"model.onnx",
|
|
377
|
+
model_slug="my-model",
|
|
378
|
+
version="1.0",
|
|
379
|
+
set_active=True,
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
# Download a model file
|
|
383
|
+
model_bytes = client.download_model_file("model-file-slug")
|
|
384
|
+
|
|
385
|
+
# Get model structure (weights stripped for ONNX)
|
|
386
|
+
structure = client.get_model_file_structure("model-file-slug")
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Backups
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
# Create a backup
|
|
393
|
+
task = client.create_backup(tier="full")
|
|
394
|
+
|
|
395
|
+
# Poll for completion
|
|
396
|
+
import time
|
|
397
|
+
while True:
|
|
398
|
+
status = client.get_backup_status(task["task_id"])
|
|
399
|
+
if status["status"] == "completed":
|
|
400
|
+
break
|
|
401
|
+
time.sleep(2)
|
|
402
|
+
|
|
403
|
+
# List and download
|
|
404
|
+
backups = client.list_backups()
|
|
405
|
+
for backup in backups["backups"]:
|
|
406
|
+
print(backup["filename"], backup["size_bytes"])
|
|
407
|
+
|
|
408
|
+
data = client.download_backup(backups["backups"][0]["filename"])
|
|
409
|
+
|
|
410
|
+
# Restore from backup
|
|
411
|
+
upload = client.upload_restore_file("backup.tar.gz")
|
|
412
|
+
task = client.start_restore(upload["restore_file_path"])
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Trend Data Export
|
|
416
|
+
|
|
417
|
+
```python
|
|
418
|
+
# Start an export task
|
|
419
|
+
task = client.create_trend_export(
|
|
420
|
+
tag_ids=[1, 2, 3],
|
|
421
|
+
start="2026-01-01T00:00:00Z",
|
|
422
|
+
stop="2026-02-01T00:00:00Z",
|
|
423
|
+
mode="resampled",
|
|
424
|
+
resample_interval="5m",
|
|
425
|
+
aggregate_fn="mean",
|
|
426
|
+
output_format="csv",
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
# Poll and download
|
|
430
|
+
status = client.get_trend_export_status(task["task_id"])
|
|
431
|
+
if status["status"] == "completed":
|
|
432
|
+
data = client.download_trend_export(status["filename"])
|
|
433
|
+
|
|
434
|
+
# Estimate before exporting
|
|
435
|
+
estimate = client.estimate_trend_export(
|
|
436
|
+
tag_ids=[1, 2, 3],
|
|
437
|
+
export_all=True,
|
|
438
|
+
)
|
|
439
|
+
print(f"~{estimate['estimated_size_bytes'] / 1e6:.1f} MB")
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Component Libraries
|
|
443
|
+
|
|
444
|
+
```python
|
|
445
|
+
result = client.upload_component_library("my-component.kcl")
|
|
446
|
+
print(f"Uploaded: {result['name']} v{result['version']}")
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### OPC-UA Certificates
|
|
450
|
+
|
|
451
|
+
```python
|
|
452
|
+
# Upload a certificate + key pair
|
|
453
|
+
result = client.upload_opcua_certificate(
|
|
454
|
+
"cert.der", "key.pem", name="My Certificate"
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
# Download cert or key
|
|
458
|
+
cert_bytes = client.download_opcua_certificate("cert-slug")
|
|
459
|
+
key_bytes = client.download_opcua_key("cert-slug")
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### EDS Files
|
|
463
|
+
|
|
464
|
+
```python
|
|
465
|
+
# Upload an EDS file for a device
|
|
466
|
+
result = client.upload_eds_file("device.eds")
|
|
467
|
+
|
|
468
|
+
# Delete the EDS file from a device
|
|
469
|
+
client.delete_eds_file(device_id=1)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Log Downloads
|
|
473
|
+
|
|
474
|
+
```python
|
|
475
|
+
log = client.download_device_log("my-device")
|
|
476
|
+
log = client.download_model_log("my-model")
|
|
477
|
+
log = client.download_scan_group_log("scan-group-1")
|
|
478
|
+
log = client.download_component_log("instance-1")
|
|
479
|
+
log = client.download_service_log("datacollector")
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Connection Options
|
|
483
|
+
|
|
484
|
+
```python
|
|
485
|
+
client = KoiosClient(
|
|
486
|
+
hostname="koios.example.com",
|
|
487
|
+
client_id="your-uuid",
|
|
488
|
+
client_secret="your-secret",
|
|
489
|
+
port=443, # Default: 443 (HTTPS) or 80 (HTTP)
|
|
490
|
+
ssl=True, # Default: True
|
|
491
|
+
verify_ssl=True, # Default: True (set False for self-signed certs)
|
|
492
|
+
timeout=30.0, # Default: 30 seconds
|
|
493
|
+
)
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
## Error Handling
|
|
497
|
+
|
|
498
|
+
```python
|
|
499
|
+
from koios_client import (
|
|
500
|
+
KoiosError, # Base exception
|
|
501
|
+
AuthenticationError, # Bad credentials or expired token
|
|
502
|
+
NotFoundError, # Resource not found (e.g. client.device(999))
|
|
503
|
+
OperationError, # Mutation returned OperationInfo
|
|
504
|
+
GraphQLError, # GraphQL response errors
|
|
505
|
+
KoiosConnectionError, # Network connectivity issues
|
|
506
|
+
KoiosPermissionError, # Insufficient permissions
|
|
507
|
+
ValidationError, # Input validation failures
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
try:
|
|
511
|
+
device = client.device(1)
|
|
512
|
+
device.update(name="New Name")
|
|
513
|
+
except NotFoundError:
|
|
514
|
+
print("Device not found")
|
|
515
|
+
except OperationError as e:
|
|
516
|
+
for msg in e.messages:
|
|
517
|
+
print(f"{msg.kind}: {msg.field}: {msg.message}")
|
|
518
|
+
except AuthenticationError:
|
|
519
|
+
print("Check your client credentials")
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
## Development
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
# Install with dev dependencies
|
|
526
|
+
pip install -e ".[dev]"
|
|
527
|
+
|
|
528
|
+
# Run tests
|
|
529
|
+
python3 -m pytest tests/ -v
|
|
530
|
+
|
|
531
|
+
# Regenerate GraphQL client (requires running Koios server)
|
|
532
|
+
make codegen
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
## License
|
|
536
|
+
|
|
537
|
+
Copyright 2024-2026 Ai-OPs, Inc. All rights reserved.
|