Skip to main content

User-friendly Python SDK for the PREKIT edge computing platform

Project description

prekit-sdk

CI Tests Python 3.12+ License: MIT

User-friendly Python SDK for the PREKIT edge computing platform. Django-inspired API, self-documenting objects, pandas-native data access.

Architecture

SDK Architecture
How prekit-sdk wraps the auto-generated API client. The __getattr__ proxy in models.py is the critical boundary — new fields from client regeneration appear automatically.

Installation

# Install the API client wheel first (from GitHub Releases or local build)
pip install prekit_edge_node_api-1.10.0-py3-none-any.whl

# Install the SDK
pip install prekit-sdk

# Or from git
pip install git+https://github.com/alpamayo-solutions/prekit-sdk.git

# Or for local development
pip install -e "./prekit-sdk[dev]"

CA Certificate

PREKIT deployments use a private PKI. The SDK can auto-download and cache the Alpamayo root CA certificate using ca_cert="alpamayo":

pk = Prekit.connect(url="https://edge.local", api_key="my-key", ca_cert="alpamayo")

The certificate is cached at ~/.prekit/alpamayo-root-ca.crt. You can also pass an explicit path to any CA cert file:

pk = Prekit.connect(url="https://edge.local", api_key="my-key", ca_cert="/path/to/ca.crt")

The root CA certificate is also available in this repo at certs/alpamayo-root-ca.crt.

SHA-256 Fingerprint: 62:96:51:A7:63:CC:14:B3:74:2A:BB:4B:A3:7A:17:20:5E:6D:58:9F:46:E9:CC:D8:E6:38:94:FE:3B:3C:7C:5C
Valid: 2025-04-30 to 2035-04-28

Quick Start

from prekit_sdk import Prekit

# Connect with API key (auto-downloads CA cert)
pk = Prekit.connect(url="https://edge.local", api_key="my-key", ca_cert="alpamayo")
print(pk)
# PREKIT SDK
#   URL:     https://edge.local
#   Health:  healthy
#   User:    operator@company.com
#   Roles:   reader

# Browse the asset tree
tree = pk.tree()
print(tree)
# Factory
# ├── LineA
# │   ├── CNC-Mill [3 signals]
# │   └── Lathe [2 signals]
# └── LineB
#     └── Press [1 signal]

# Find a machine
machine = pk.elements.get(name="CNC-Mill")
machine.help()

# Get its signals
sigs = machine.signals()

# Fetch historian data
df = machine.data(last="1h")

Connection & Authentication

Keycloak Client Credentials

For scripts and service accounts:

pk = Prekit.connect(
    url="https://edge.local",
    client_id="prekit-test",
    client_secret="your-secret",
    verify_ssl=False,
)

Azure / Entra ID

Interactive browser login with Microsoft account:

pk = Prekit.connect(
    url="https://edge.local",
    auth="azure",
    tenant_id="your-tenant-id",
    client_id="your-app-id",
)

API Key

pk = Prekit.connect(url="https://edge.local", api_key="my-key")

From Environment Variables

pk = Prekit.connect_from_env()

Reads: PREKIT_URL, PREKIT_AUTH_METHOD (api_key/oauth/azure), API_KEY, KEYCLOAK_URL, KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET, AZURE_TENANT_ID, AZURE_CLIENT_ID, PREKIT_VERIFY_SSL, CA_CERT_FILE.

Escape Hatch

Direct access to the raw AutoRefreshApiClient:

pk.api  # for any API call not covered by the SDK

Browsing the Asset Tree

# Full tree (compact, with signal counts)
pk.tree().print()

# Full tree (expanded, showing individual signals)
pk.tree().print(signals=True)

# Subtree from a specific element
pk.tree(root=machine).print()
pk.tree(root="01JABCDE...").print()  # by ID

Compact output

Factory
├── LineA
│   ├── CNC-Mill [3 signals]
│   └── Lathe [2 signals]
└── LineB
    └── Press [1 signal]

Expanded output (signals=True)

Factory
├── LineA
│   ├── CNC-Mill
│   │   ├─ Temperature (float, C)
│   │   ├─ Vibration (float, mm/s)
│   │   └─ SpindleSpeed (int, rpm)
│   └── Lathe
│       └─ Temperature (float, C)
└── LineB
    └── Press
        └─ Pressure (float, bar)

Finding Things (Django-style)

The SDK provides managers with .get(), .filter(), .all(), and .create(), inspired by Django's ORM.

.get() -- single object

# By name
machine = pk.elements.get(name="CNC-Mill")

# By ID (direct API call, fast)
sig = pk.signals.get(id="01JABCDE...")

# By hierarchy path
line = pk.elements.get(path="Factory/LineA")

.filter() -- multiple objects

# Substring match
machines = pk.elements.filter(name__contains="CNC")

# Multiple criteria
sigs = pk.signals.filter(data_type="float", unit="C")

# By parent element (accepts object or ID)
sigs = pk.signals.filter(system_element=machine)

Available lookups

Lookup Example Behavior
name name="CNC" Exact match
name__contains name__contains="Mill" Substring
name__startswith name__startswith="CNC" Prefix
name__icontains name__icontains="mill" Case-insensitive substring
system_element system_element=machine FK (object or ID)
id id="01JAB..." Direct ID lookup
path path="Factory/LineA" Hierarchy path (elements only)

Handling non-unique signal names

Signal names are not unique. "Temperature" may exist on multiple machines:

pk.signals.get(name="Temperature")
# -> MultipleObjectsReturned: 3 signals match name="Temperature"

# Disambiguate by scoping to an element:
sig = pk.signals.get(name="Temperature", system_element=machine)

# Or get all matches:
temps = pk.signals.filter(name="Temperature")

.create()

elem = pk.elements.create(name="NewMachine", parent=line_a)
sig = pk.signals.create(name="Temp", element=elem, data_type="float", unit="C")

Data Access

All data access uses signal IDs internally (always unambiguous). Returns pandas DataFrames.

Single signal

sig = pk.signals.get(name="Temperature", system_element=machine)

df = sig.data(last="1h")                                    # relative time
df = sig.data(start="2026-03-17", end="2026-03-18")         # absolute range
latest = sig.latest()                                        # {"value": 23.5, "timestamp": ...}

All signals on an element

df = machine.data(last="1h")
# Pivoted DataFrame: timestamp | Temperature | Vibration | SpindleSpeed

Multiple specific signals

df = pk.data(signals=[sig1, sig2], last="1h")

Rich Models & .help()

Every object returned by the SDK is a thin proxy over the generated Pydantic model. Generated fields are accessible directly; the SDK adds navigation methods.

machine = pk.elements.get(name="CNC-Mill")

# Generated fields (from prekit_edge_node_api)
machine.name           # "CNC-Mill"
machine.id             # "01JABCDE..."
machine.created_at     # datetime

# SDK navigation methods
machine.signals()      # -> [<Signal: Temperature>, ...]
machine.children()     # -> []
machine.parent()       # -> <Element: LineA>
machine.path()         # -> "Factory/LineA/CNC-Mill"

# Escape hatch
machine._raw           # the generated SystemElement Pydantic model

.help() -- self-documenting objects

machine.help()

Output:

SystemElement: CNC-Mill (01JABCDE...)
Path: Factory/LineA/CNC-Mill

Fields (from generated model):
  name, id, created_at, updated_at, parent, level, ...

Relationships:
  .signals()              child signals (3 items)
  .children()             child elements (0 items)
  .parent()               parent element -> LineA

Actions:
  .data(last="1h")        DataFrame (all child signals)
  .tree()                 subtree from here
  .update(name=...)       patch this element
  ._raw                   generated SystemElement model

Health check

pk.is_healthy()   # -> True/False
pk.health()       # -> {"status": "healthy", ...}

API Client Updates

The SDK is designed to be resilient to API client regeneration:

  • __getattr__ proxy: element.name delegates to _raw.name. New fields on the generated model appear automatically.
  • .help() introspects dynamically: reads model_fields from the Pydantic model at runtime. New fields show up in help output without SDK changes.
  • Managers resolve API classes by name: getattr(prekit, "SystemElementApi") at init time, not hardcoded imports.

Update workflow: regenerate the API client -> pip install the new wheel -> the SDK picks up new models and fields automatically. No SDK code changes needed unless adding new navigation methods.

Development

# Setup
pip install tests/edge-node/api-client-whl/*.whl
pip install -e "./prekit-sdk[dev]"

# Run tests
pytest prekit-sdk/tests/ -v

# Lint
ruff check prekit-sdk/src/

# Demo notebook
jupyter notebook prekit-sdk/notebooks/demo.ipynb

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

prekit_sdk-0.1.0.tar.gz (56.1 kB view details)

Uploaded Source

Built Distribution

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

prekit_sdk-0.1.0-py3-none-any.whl (26.9 kB view details)

Uploaded Python 3

File details

Details for the file prekit_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: prekit_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 56.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for prekit_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 221c9665892e7be809a49f57e4fae714427c13ec20b9dfaec9339b7fd6f31818
MD5 ceb7162394650d2b09bb15a3b344aff8
BLAKE2b-256 db92a4081695062e5e039c501320b2eb68554f806dc5392119bc822dc3dd984c

See more details on using hashes here.

Provenance

The following attestation bundles were made for prekit_sdk-0.1.0.tar.gz:

Publisher: ci.yml on alpamayo-solutions/prekit-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file prekit_sdk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: prekit_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 26.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for prekit_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7009c2313af6aa9226ec1a670480eae69bbf0ad72119904c4f5f5af3e11bda81
MD5 c9602a450ec6f63dd9e8509d9b06de75
BLAKE2b-256 1471f09786b71264985dd77a60b7e3ac1af0fb32cf28d8ae58b0fea7b8a537f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for prekit_sdk-0.1.0-py3-none-any.whl:

Publisher: ci.yml on alpamayo-solutions/prekit-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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