Skip to main content

BioT Measurement Service

Project description

biotmed_measurement_sdk

APIs document (version: 2.15.0)

This Python SDK provides a client library for interacting with the BioT Service API. BioT is a comprehensive platform for medical device integration and healthcare data management, enabling secure communication between medical devices and cloud services.

For more information about BioT, see BioT.

Installation

pip install biotmed_measurement_sdk

Configuration

Creating and Configuring the ApiClient

The SDK requires configuration with an access token and the service endpoint. You'll need to:

  1. Configure the service path by appending the service-specific path to your BioT base URL
  2. Provide an access token (as a string or callable function)
  3. Optionally set up language management (as a string or callable function)

Service Path Configuration

The base URL for your environment can be found in the BioT Console under Technical Information → Rest API URL.

Each BioT service has its own path that must be appended to this base URL:

  • Generic Entity Service: /generic-entity
  • Organization Service: /organization
  • DMS Service: /dms
  • File Service: /file
  • Notification Service: /notification
  • UMS Service: /ums
  • Settings Service: /settings
  • Measurement Service: /measurement
  • Device Service: /device

Important: Always append the service path to your biot_base_url when configuring the SDK.

Access Token Configuration

The SDK supports both static tokens and dynamic token providers (callable pattern). You can pass either:

  • A string: A static access token (not recommended for long-running applications)
  • A callable (function or callable object): A token provider that returns a token when called, enabling automatic token refresh

Using a callable allows the SDK to refresh tokens automatically before they expire, ensuring your API calls remain authenticated.

# Option 1: Static token (simple but tokens expire)
access_token = "your-static-token-here"

# Option 2: Callable function for dynamic token refresh
def get_access_token() -> str:
    # Implement your token retrieval/refresh logic here
    # This function will be called by the SDK when authentication is needed
    # You can authenticate however you prefer (OAuth, service user, etc.)
    return "your-access-token"

# Option 3: Callable object (Token Provider pattern)
class TokenProvider:
    def __call__(self) -> str:
        # Return the token, only refresh if expired
        if self._is_token_expired():
            self._token = self._refresh_token()
        return self._token
    
    def _is_token_expired(self) -> bool:
        # Check if token needs refresh
        # Your expiration check logic here
        return True
    
    def _refresh_token(self) -> str:
        # Your token refresh implementation
        # This is only called when token is expired
        return "your-new-access-token"

token_provider = TokenProvider()

Language Configuration

The accept_language parameter controls the language used for API responses. It supports both static strings and callables for dynamic language selection. For more details on supported languages and translations, see Language and Translations.

# Option 1: Static language
accept_language = "en-us"

# Option 2: Callable for dynamic language selection
def get_accept_language() -> str:
    # Return language based on user preferences, system settings, etc.
    return "en-us"  # Examples: "en-us", "fr-fr", "de-de", etc.

Complete Configuration Example

import biotmed_measurement_sdk
from typing import Callable

# BioT configuration
biot_base_url = "https://api.example.biot-med.com"  # or your production URL

# Token provider (callable for automatic refresh)
def get_access_token() -> str:
    # Implement your token retrieval/refresh logic
    # This will be called by the SDK when authentication is needed
    # Authenticate using your preferred method (OAuth, service user credentials, etc.)
    return "your-access-token"

# Language provider (optional, callable for dynamic language)
def get_accept_language() -> str:
    return "en-us"

# Configure SDK with service path appended to base URL
configuration = biotmed_measurement_sdk.Configuration(
    host=biot_base_url + "/service-path",  # Replace with your service path (e.g., "/generic-entity", "/organization", "/dms")
    access_token=get_access_token,  # Callable token provider
    accept_language=get_accept_language  # Optional: callable language provider
)

# Create ApiClient
with biotmed_measurement_sdk.ApiClient(configuration) as api_client:
    # Create API instances
    api = biotmed_measurement_sdk.YourAPIClass(api_client)  # Replace with your actual API class name
    # Use the API...

Usage Examples

Different Approaches for Creating Resources

The SDK supports multiple approaches for creating resources, each with different trade-offs between type safety, flexibility, and developer experience. Choose the approach that best fits your use case.

Approach 1: Direct Model Construction with Inline Custom Attributes

Use direct Pydantic model construction when you want maximum type safety for standard fields and don't mind type checker warnings for custom attributes:

from uuid import UUID

create_request = biotmed_measurement_sdk.CreateResourceRequest(  # Replace with your actual request model name
    _name="My Resource",
    _ownerOrganization=biotmed_measurement_sdk.ReferenceAttributeUUIDIdRequest(
        id=UUID("your-organization-id")
    ),
    customField1="value1",  # pyright: ignore[reportCallIssue]
    customField2="value2",  # pyright: ignore[reportCallIssue]
    # ... other fields
)

response = api.create_resource(create_request, template_name="YourTemplate")  # Replace with your actual method name

Pros:

  • Full type safety and IDE autocomplete for all schema-defined fields
  • Direct, intuitive syntax
  • Compile-time validation for standard fields
  • Clear separation between standard and custom fields in code

Cons:

  • Type checker warnings for custom attributes (requires # pyright: ignore[reportCallIssue] comments)
  • Custom attributes are not statically typed
  • Can clutter constructor calls with many custom attributes

Best for: When you have a few custom attributes and want maximum type safety for standard fields.


Approach 2: Custom Attributes with **kwargs

Separate custom attributes into a dictionary and unpack them using **kwargs. This provides cleaner code organization:

from typing import Dict, Any
from uuid import UUID

# Custom attributes not defined in the schema
custom_attrs: Dict[str, Any] = {
    "customField1": "value1",
    "customField2": "value2"
}

create_request = biotmed_measurement_sdk.CreateResourceRequest(  # Replace with your actual request model name
    _name="My Resource",
    _ownerOrganization=biotmed_measurement_sdk.ReferenceAttributeUUIDIdRequest(
        id=UUID("your-organization-id")
    ),
    **custom_attrs  # Unpack custom attributes
)

response = api.create_resource(create_request, template_name="YourTemplate")  # Replace with your actual method name

Pros:

  • No type checker warnings on the model construction line
  • Full type safety for standard fields
  • Easy to build custom attributes dynamically
  • Better code organization when you have many custom attributes

Cons:

  • Separation of custom attributes from standard fields
  • Slightly more verbose than Approach 1

Best for: When you have many custom attributes or need to build them dynamically. This is the recommended approach for most use cases.


Approach 3: Using model_validate with Dictionary

Use model_validate when you're working with dictionaries, need maximum flexibility, or are building requests from external data sources:

create_request = biotmed_measurement_sdk.CreateResourceRequest.model_validate({  # Replace with your actual request model name
    "_name": "My Resource",
    "_ownerOrganization": {
        "id": "your-organization-id"
    },
    "customField1": "value1",
    "customField2": "value2",
    # ... other fields (all as dictionary keys)
})

response = api.create_resource(create_request, template_name="YourTemplate")  # Replace with your actual method name

Pros:

  • Maximum flexibility - works with any dictionary structure
  • Perfect for building requests from external data (JSON, API responses, etc.)
  • Can easily handle dynamic field names
  • Runtime validation still occurs via Pydantic

Cons:

  • No static type checking or IDE autocomplete
  • No compile-time validation
  • Field names must match JSON names (e.g., _name not name)
  • Less readable than constructor-based approaches

Best for: When working with dynamic data, parsing JSON, or when field names are determined at runtime. Also useful for global entities or cases where you need to set fields to None.


Comparison Summary

Feature Approach 1
(Direct + Inline)
Approach 2
(Direct + **kwargs)
Approach 3
(model_validate)
Type safety (standard fields) ✅ Full ✅ Full ❌ None
IDE autocomplete ✅ Yes ✅ Yes ❌ No
Custom attributes support ⚠️ With warnings ✅ Clean ✅ Clean

Accessing Response Data

When retrieving resources, you can access both standard fields and custom attributes using these recommended approaches:

Using .get() Method (Recommended)

The .get() method is the simplest and safest way to access both standard fields and custom attributes:

response = api.get_resource(template_name, resource_id)  # Replace with your actual method name

# Access standard fields
resource_name = response.get("_name")
resource_id = response.get("id")

# Access custom attributes
custom_value = response.get("customField1")

Using Dot Notation (Recommended for Standard Fields)

For standard fields, dot notation provides type safety and IDE autocomplete:

response = api.get_resource(template_name, resource_id)  # Replace with your actual method name

# Access standard fields (type-safe, IDE autocomplete)
resource_name = response._name
resource_id = response.id

# For custom attributes, use getattr with default
custom_value = getattr(response, "customField1", None)

Using additional_properties (Recommended for Custom Attributes)

For custom attributes specifically, you can access them directly through additional_properties:

response = api.get_resource(template_name, resource_id)  # Replace with your actual method name

# Access custom attributes
custom_value = response.additional_properties.get("customField1")

Note: When accessing custom attributes that aren't defined in the response model schema, type checkers may show warnings. You can safely ignore these warnings since custom attributes are stored in additional_properties and are accessible at runtime.

Search Examples

The SDK provides powerful search capabilities with various filter options.

Basic Search

from biotmed_measurement_sdk import SearchRequestV2, FilterV2, Order

search_request = SearchRequestV2(
    limit=10,
    page=0,
    sort=[Order(prop="_creationTime", order="DESC")]
)

response = api.search_resources(search_request)  # Replace with your actual method name

Search with Filters

# Search by name (like filter)
search_request = SearchRequestV2(
    filter={
        "_name": FilterV2(like="test")
    },
    limit=10,
    page=0,
    sort=[Order(prop="_creationTime", order="DESC")]
)

response = api.search_resources(search_request)  # Replace with your actual method name

Search with Multiple Filters

# Search with multiple conditions
search_request = SearchRequestV2(
    filter={
        "_name": FilterV2(like="test"),
        "_creationTime": FilterV2(
            var_from="2024-01-01T00:00:00Z",
            to="2024-12-31T23:59:59Z"
        )
    },
    limit=10,
    page=0
)

response = api.search_resources(search_request)  # Replace with your actual method name

Error Handling

Always wrap API calls in try-except blocks to handle errors gracefully:

from biotmed_measurement_sdk import ApiException

try:
    response = api.get_resource(template_name, resource_id)  # Replace with your actual method name
    print(response.model_dump_json(by_alias=True, indent=2))
except ApiException as e:
    # Handle API errors
    error_response = e.data
    if isinstance(error_response, biotmed_measurement_sdk.ErrorResponse):
        print(f"API Error: {error_response.model_dump_json(by_alias=True, indent=2)}")
    else:
        print(f"Exception: {e}")

Complete Example

Here's a complete example combining all the concepts:

import biotmed_measurement_sdk
from biotmed_measurement_sdk import ApiException
from uuid import UUID
from typing import Dict, Any

# Configuration
biot_base_url = "https://api.<>.biot-med.com"

def get_access_token() -> str:
    # Implement your token retrieval/refresh logic
    # Authenticate using your preferred method (OAuth, service user credentials, etc.)
    return "your-access-token"

configuration = biotmed_measurement_sdk.Configuration(
    host=biot_base_url + "/service-path",  # Replace with your service path
    access_token=get_access_token,  # Callable token provider
    accept_language=lambda: "en-us"  # Optional: callable language provider
)

# Use ApiClient
with biotmed_measurement_sdk.ApiClient(configuration) as api_client:
    api = biotmed_measurement_sdk.YourAPIClass(api_client)  # Replace with your actual API class name
    
    # Search example
    try:
        search_request = biotmed_measurement_sdk.SearchRequestV2(
            filter={
                "_name": biotmed_measurement_sdk.FilterV2(like="test")
            },
            limit=10,
            page=0
        )
        search_response = api.search_resources(search_request)  # Replace with your actual method name
        print(f"Found {len(search_response.data)} resources")
    except ApiException as e:
        print(f"Search error: {e}")
    
    # Create example with custom attributes
    try:
        custom_attrs: Dict[str, Any] = {
            "customField": "customValue"
        }
        create_request = biotmed_measurement_sdk.CreateResourceRequest(  # Replace with your actual request model name
            _name="My Resource",
            _ownerOrganization=biotmed_measurement_sdk.ReferenceAttributeUUIDIdRequest(
                id=UUID("your-organization-id")
            ),
            **custom_attrs
        )
        create_response = api.create_resource(  # Replace with your actual method name
            create_request, 
            template_name="YourTemplate"
        )
        print(f"Created resource: {create_response.id}")
    except ApiException as e:
        print(f"Create error: {e}")
    
    # Get example
    try:
        get_response = api.get_resource("YourTemplate", resource_id)  # Replace with your actual method name
        
        # Access data using .get() method
        name = get_response.get("_name")
        custom_value = get_response.get("customField")
        
        print(f"Resource name: {name}")
        print(f"Custom field: {custom_value}")
    except ApiException as e:
        print(f"Get error: {e}")

Additional Resources

License

This project is licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

biotmed_measurement_sdk-2.4.1.tar.gz (53.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

biotmed_measurement_sdk-2.4.1-py3-none-any.whl (118.3 kB view details)

Uploaded Python 3

File details

Details for the file biotmed_measurement_sdk-2.4.1.tar.gz.

File metadata

  • Download URL: biotmed_measurement_sdk-2.4.1.tar.gz
  • Upload date:
  • Size: 53.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0rc1

File hashes

Hashes for biotmed_measurement_sdk-2.4.1.tar.gz
Algorithm Hash digest
SHA256 f55ec52dd8e93b1a81b897835dcb459f96f64931c1b492f6b6f5267e65f9def9
MD5 3a99b98b897d818902fe0808605cb667
BLAKE2b-256 3bd916bf926ea6241244bbab555720e595407987ee9363f2429043299919267f

See more details on using hashes here.

File details

Details for the file biotmed_measurement_sdk-2.4.1-py3-none-any.whl.

File metadata

File hashes

Hashes for biotmed_measurement_sdk-2.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 63bcbe3b4e8dcab58e078709a7f30dbec259eac01542ae69cc533c2eb7fb60a0
MD5 9d6e33e968db11bd0945920a0eabb4a1
BLAKE2b-256 feaf3cd1834be901fb2785e3897747a28c22cfd2a87d2be7ce521f47373bd082

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page