Skip to content

Commit dd9907f

Browse files
aravindhan-niAravindhan PalanisamyAmmar Husain Mian Fazulul
authored
feat: Add Client for Asset Management (Asset) create, delete and query API (#134)
Co-authored-by: Aravindhan Palanisamy <[email protected]> Co-authored-by: Ammar Husain Mian Fazulul <[email protected]>
1 parent 4622ba7 commit dd9907f

18 files changed

+1078
-0
lines changed

docs/api_reference.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ API Reference
1616
api_reference/file
1717
api_reference/notebook
1818
api_reference/feeds
19+
api_reference/assetmanagement
1920

2021
Indices and tables
2122
------------------
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.. _api_tag_page:
2+
3+
nisystemlink.clients.assetmanagement
4+
======================
5+
6+
.. autoclass:: nisystemlink.clients.assetmanagement.AssetManagementClient
7+
:exclude-members: __init__
8+
9+
.. automethod:: __init__
10+
.. automethod:: create_assets
11+
.. automethod:: query_assets
12+
.. automethod:: delete_assets
13+
14+
.. automodule:: nisystemlink.clients.assetmanagement.models
15+
:members:
16+
:imported-members:

docs/getting_started.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,5 +318,32 @@ Create, query, update, and delete some notebooks.
318318
Create, query, retry, and cancel notebook executions.
319319

320320
.. literalinclude:: ../examples/notebook/notebook_execution.py
321+
:language: python
322+
:linenos:
323+
324+
325+
Asset Management API
326+
-------
327+
328+
Overview
329+
~~~~~~~~
330+
331+
The :class:`.AssetManagementClient` class is the primary entry point of the Asset Management API.
332+
333+
When constructing a :class:`.AssetManagementClient`, you can pass an
334+
:class:`.HttpConfiguration` (like one retrieved from the
335+
:class:`.HttpConfigurationManager`), or let :class:`.AssetManagementClient` use the
336+
default connection. The default connection depends on your environment.
337+
338+
With a :class:`.AssetManagementClient` object, you can:
339+
340+
* Create, delete and get the list of assets.
341+
342+
Examples
343+
~~~~~~~~
344+
345+
create, delete and query asset
346+
347+
.. literalinclude:: ../examples/assetmanagement/assets.py
321348
:language: python
322349
:linenos:

examples/assetmanagement/assets.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from nisystemlink.clients.assetmanagement import AssetManagementClient
2+
from nisystemlink.clients.assetmanagement.models import (
3+
AssetBusType,
4+
AssetDiscoveryType,
5+
AssetLocationForCreate,
6+
AssetPresence,
7+
AssetPresenceStatus,
8+
AssetType,
9+
CreateAssetRequest,
10+
ExternalCalibration,
11+
QueryAssetsRequest,
12+
SelfCalibration,
13+
TemperatureSensor,
14+
)
15+
from nisystemlink.clients.core._http_configuration import HttpConfiguration
16+
17+
18+
server_configuration = HttpConfiguration(
19+
server_uri="https://yourserver.yourcompany.com",
20+
api_key="YourAPIKeyGeneratedFromSystemLink",
21+
)
22+
client = AssetManagementClient(configuration=server_configuration)
23+
24+
create_assets_request = [
25+
CreateAssetRequest(
26+
model_number=4000,
27+
model_name="NI PXIe-6368",
28+
serial_number="01BB877A",
29+
vendor_name="NI",
30+
vendor_number="4244",
31+
bus_type=AssetBusType.ACCESSORY,
32+
name="PCISlot2",
33+
asset_type=AssetType.DEVICE_UNDER_TEST,
34+
firmware_version="A1",
35+
hardware_version="12A",
36+
visa_resource_name="vs-3144",
37+
temperature_sensors=[TemperatureSensor(name="Sensor0", reading=25.8)],
38+
supports_self_calibration=True,
39+
supports_external_calibration=True,
40+
custom_calibration_interval=24,
41+
self_calibration=SelfCalibration(
42+
temperature_sensors=[TemperatureSensor(name="Sensor0", reading=25.8)],
43+
is_limited=False,
44+
date="2022-06-07T18:58:05.000Z",
45+
),
46+
is_NI_asset=True,
47+
workspace="846e294a-a007-47ac-9fc2-fac07eab240e",
48+
location=AssetLocationForCreate(
49+
state=AssetPresence(asset_presence=AssetPresenceStatus.PRESENT)
50+
),
51+
external_calibration=ExternalCalibration(
52+
temperature_sensors=[TemperatureSensor(name="Sensor0", reading=25.8)],
53+
date="2022-06-07T18:58:05.000Z",
54+
recommended_interval=10,
55+
next_recommended_date="2023-11-14T20:42:11.583Z",
56+
next_custom_due_date="2024-11-14T20:42:11.583Z",
57+
resolved_due_date="2022-06-07T18:58:05.000Z",
58+
),
59+
properties={"Key1": "Value1"},
60+
keywords=["Keyword1"],
61+
discovery_type=AssetDiscoveryType.MANUAL,
62+
file_ids=["608a5684800e325b48837c2a"],
63+
supports_self_test=True,
64+
supports_reset=True,
65+
partNumber="A1234 B5",
66+
)
67+
]
68+
69+
# Create an asset.
70+
create_assets_response = client.create_assets(assets=create_assets_request)
71+
72+
created_asset_id = None
73+
if create_assets_response.assets and len(create_assets_response.assets) > 0:
74+
created_asset_id = str(create_assets_response.assets[0].id)
75+
76+
# Query assets using id.
77+
query_asset_request = QueryAssetsRequest(
78+
ids=[created_asset_id],
79+
skip=0,
80+
take=1,
81+
descending=False,
82+
calibratable_only=False,
83+
returnCount=False,
84+
)
85+
client.query_assets(query=query_asset_request)
86+
87+
# Delete the created asset.
88+
if created_asset_id is not None:
89+
client.delete_assets(ids=[created_asset_id])
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from nisystemlink.clients.assetmanagement._asset_management_client import (
2+
AssetManagementClient,
3+
)
4+
5+
# flake8: noqa
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""Implementation of AssetManagementClient."""
2+
3+
from typing import List, Optional
4+
5+
from nisystemlink.clients import core
6+
from nisystemlink.clients.core._http_configuration import HttpConfiguration
7+
from nisystemlink.clients.core._uplink._base_client import BaseClient
8+
from nisystemlink.clients.core._uplink._methods import post
9+
from uplink import Field, retry
10+
11+
from . import models
12+
13+
14+
@retry(
15+
when=retry.when.status(408, 429, 502, 503, 504),
16+
stop=retry.stop.after_attempt(5),
17+
on_exception=retry.CONNECTION_ERROR,
18+
)
19+
class AssetManagementClient(BaseClient):
20+
def __init__(self, configuration: Optional[HttpConfiguration] = None):
21+
"""Initialize an instance.
22+
23+
Args:
24+
configuration: Defines the web server to connect to and information about
25+
how to connect. If not provided, the
26+
:class:`HttpConfigurationManager <nisystemlink.clients.core.HttpConfigurationManager>`
27+
is used to obtain the configuration.
28+
29+
Raises:
30+
ApiException: If unable to communicate with the asset management Service.
31+
"""
32+
if configuration is None:
33+
configuration = core.HttpConfigurationManager.get_configuration()
34+
35+
super().__init__(configuration, base_path="/niapm/v1/")
36+
37+
@post("assets", args=[Field("assets")])
38+
def create_assets(
39+
self, assets: List[models.CreateAssetRequest]
40+
) -> models.CreateAssetsPartialSuccessResponse:
41+
"""Create Assets.
42+
43+
Args:
44+
assets: Array of assets that should be created.
45+
46+
Returns:
47+
CreateAssetsPartialSuccessResponse: Array of created assets and array of failed.
48+
49+
Raises:
50+
ApiException: If unable to communicate with the asset management service or if there are invalid
51+
arguments.
52+
"""
53+
...
54+
55+
@post("query-assets")
56+
def __query_assets(
57+
self, query: models._QueryAssetsRequest
58+
) -> models.QueryAssetsResponse:
59+
"""Query Assets.
60+
61+
Args:
62+
query: Object containing filters to apply when retrieving assets.
63+
64+
Returns:
65+
QueryAssetsResponse: Assets Response containing the assets satisfying the query and
66+
the total count of matching assets.
67+
68+
Raises:
69+
ApiException: If unable to communicate with the asset management service or if there are invalid
70+
arguments.
71+
"""
72+
...
73+
74+
def query_assets(
75+
self, query: models.QueryAssetsRequest
76+
) -> models.QueryAssetsResponse:
77+
"""Query Assets.
78+
79+
Args:
80+
query: Object containing filters to apply when retrieving assets.
81+
82+
Returns:
83+
QueryAssetsResponse: Assets Response containing the assets satisfying the query and
84+
the total count of matching assets.
85+
86+
Raises:
87+
ApiException: If unable to communicate with the asset management service or if there are invalid
88+
arguments.
89+
"""
90+
projection_str = (
91+
f"new({', '.join(projection.name for projection in query.projection)})"
92+
if query.projection
93+
else None
94+
)
95+
query_params = {
96+
"filter": query.filter,
97+
"take": query.take,
98+
"skip": query.skip,
99+
"return_count": query.return_count,
100+
"order_by": query.order_by,
101+
"descending": query.descending,
102+
"projection": projection_str,
103+
}
104+
105+
query_params = {k: v for k, v in query_params.items() if v is not None}
106+
107+
query_request = models._QueryAssetsRequest(**query_params)
108+
109+
return self.__query_assets(query=query_request)
110+
111+
@post("delete-assets", args=[Field("ids")])
112+
def delete_assets(self, ids: List[str]) -> models.DeleteAssetsResponse:
113+
"""Delete Assets.
114+
115+
Args:
116+
ids: List of IDs of the assets to delete.
117+
118+
Returns:
119+
DeleteAssetsResponse: Response containing the IDs of the assets that were deleted.
120+
121+
Raises:
122+
ApiException: If unable to communicate with the asset management service or if there are invalid arguments.
123+
"""
124+
...
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from ._query_assets_response import QueryAssetsResponse
2+
from ._asset import Asset
3+
from ._create_asset_request import CreateAssetRequest
4+
from ._create_assets_partial_success_response import CreateAssetsPartialSuccessResponse
5+
from ._delete_assets_response import DeleteAssetsResponse
6+
from ._query_assets_request import AssetField, QueryAssetsRequest, _QueryAssetsRequest
7+
from ._query_assets_response import QueryAssetsResponse
8+
from ._asset_location import (
9+
AssetLocation,
10+
AssetLocationForCreate,
11+
AssetPresence,
12+
AssetPresenceWithSystemConnection,
13+
AssetPresenceStatus,
14+
)
15+
from ._asset_calibration import (
16+
CalibrationMode,
17+
CalibrationStatus,
18+
SelfCalibration,
19+
TemperatureSensor,
20+
ExternalCalibration,
21+
)
22+
from ._asset_types import AssetBusType, AssetDiscoveryType, AssetType
23+
24+
# flake8: noqa

0 commit comments

Comments
 (0)