Skip to main content

Official Python SDK for the Scadable IoT platform.

Project description

Scadable Python SDK

PyPi Downloads Supported Versions GitHub issues GitHub actions status

Scadable is the first fully container-native SCADA platform—built on Kubernetes & NATS and delivered with Python + React SDKs. Forget rigid vendor UIs: craft your own dashboards, deploy in any cloud, and scale to millions of tags in minutes.

Table of Contents

Overview

The Scadable Python SDK provides a simple, pythonic interface to interact with the Scadable SCADA platform. Key features include:

  • Live Telemetry Streaming: Subscribe to real-time device data via WebSocket connections
  • Device Management: Create and manage multiple devices within a facility
  • Flexible Connection Handling: Built-in WebSocket support with extensible connection factory pattern
  • Async-First Design: Fully asynchronous API using Python's asyncio
  • Type-Safe: Full type hints for better IDE support and code quality

Access & Deployment

Installation

Requirements

  • Python 3.10 or higher
  • pip package manager

Install from PyPI

pip install scadable

Install for Development

For contributing to the project, see the CONTRIBUTING.md guide.

Quick Start

Here's a minimal example to get started with Scadable:

import asyncio
from scadable import Facility
from scadable.connection import WebsocketConnectionFactory

# Initialize a facility with your API key
facility = Facility(
    api_key="your-api-key-here",
    connection_factory=WebsocketConnectionFactory(dest_uri="your-scadable-host.com")
)

# Create devices with live connections
devices = facility.create_many_devices(
    device_ids=["device-1", "device-2"],
    create_connection=True
)

# Subscribe to live telemetry for specific devices
@facility.live_telemetry(["device-1", "device-2"])
async def handle_telemetry(data: str):
    print(f"Received data: {data}")
    # Process your telemetry data here

# Start listening for telemetry
async def main():
    await asyncio.gather(*[device.start_live_telemetry() for device in devices])

if __name__ == "__main__":
    asyncio.run(main())

Core Concepts

Facility

The Facility class is your main entry point. It represents a physical or logical facility containing multiple devices.

from scadable import Facility

facility = Facility(api_key="your-api-key")

Devices

Devices represent individual data sources (PLCs, sensors, controllers, etc.) within your facility.

# Create a single device
device = facility.create_device("device-id-123")

# Create multiple devices
devices = facility.create_many_devices(["device-1", "device-2", "device-3"])

Connections

Connections manage the communication channel between your application and the Scadable platform. The SDK provides WebSocket connections out of the box:

from scadable.connection import WebsocketConnectionFactory

# Create a connection factory
factory = WebsocketConnectionFactory(
    dest_uri="scadable.example.com",
    connection_type="wss"  # or "ws" for non-secure
)

facility = Facility(api_key="your-key", connection_factory=factory)

Live Telemetry

Subscribe to real-time data streams using decorators:

# Subscribe to a single device
@facility.live_telemetry("device-1")
async def handler(data: str):
    print(data)

# Subscribe to multiple devices
@facility.live_telemetry(["device-1", "device-2"])
async def multi_handler(data: str):
    # This handler will receive data from both devices
    process_data(data)

Usage Examples

Example 1: Basic Telemetry Monitoring

import asyncio
from scadable import Facility
from scadable.connection import WebsocketConnectionFactory

async def monitor_devices():
    # Setup
    facility = Facility(
        api_key="your-api-key",
        connection_factory=WebsocketConnectionFactory("your-host.com")
    )

    # Create devices with connections
    device = facility.create_device("sensor-001", create_connection=True)

    # Subscribe to telemetry
    @facility.live_telemetry("sensor-001")
    async def log_data(data: str):
        print(f"Sensor reading: {data}")

    # Start monitoring
    await device.start_live_telemetry()

asyncio.run(monitor_devices())

Example 2: Multiple Device Management

import asyncio
from scadable import Facility
from scadable.connection import WebsocketConnectionFactory

async def monitor_facility():
    facility = Facility(
        api_key="your-api-key",
        connection_factory=WebsocketConnectionFactory("your-host.com")
    )

    # Create multiple devices
    device_ids = ["plc-1", "plc-2", "sensor-1", "sensor-2"]
    devices = facility.create_many_devices(device_ids, create_connection=True)

    # Different handlers for different device groups
    @facility.live_telemetry(["plc-1", "plc-2"])
    async def handle_plc_data(data: str):
        print(f"PLC Data: {data}")

    @facility.live_telemetry(["sensor-1", "sensor-2"])
    async def handle_sensor_data(data: str):
        print(f"Sensor Data: {data}")

    # Start all connections
    await asyncio.gather(*[dev.start_live_telemetry() for dev in devices])

asyncio.run(monitor_facility())

Example 3: Raw Data Processing

For advanced use cases where you need access to raw, unparsed data:

device = facility.create_device("device-1", create_connection=True)

@device.raw_live_telemetry
async def handle_raw(raw_data: str):
    # Process raw data before parsing
    print(f"Raw: {raw_data}")

await device.start_live_telemetry()

Architecture

Component Overview

┌─────────────────────────────────────────────────────────┐
│                        Facility                         │
│  - Manages API authentication                           │
│  - Coordinates devices and connections                  │
└────────────────┬───────────────────┬────────────────────┘
                 │                   │
        ┌────────▼────────┐  ┌───────▼──────────┐
        │ DeviceManager   │  │ ConnectionFactory │
        │ - Device CRUD   │  │ - Creates conns   │
        └────────┬────────┘  └───────┬───────────┘
                 │                   │
        ┌────────▼────────┐  ┌───────▼───────────┐
        │     Device      │  │   Connection      │
        │ - Telemetry bus │◄─┤ - WebSocket       │
        │ - Event routing │  │ - Send/Receive    │
        └─────────────────┘  └───────────────────┘

Key Design Patterns

  1. Factory Pattern: ConnectionFactory allows for different connection types (WebSocket, HTTP, custom)
  2. Observer Pattern: Devices use a pub-sub bus for telemetry data distribution
  3. Async/Await: Fully asynchronous for efficient I/O operations
  4. Decorator Pattern: Clean syntax for subscribing to telemetry streams

Tech Stack

  • Language: Python 3.10+
  • Async Framework: asyncio (standard library)
  • WebSocket Library: websockets 13.0+
  • Type System: Full type hints with Python's typing module

Package Structure

scadable/
├── __init__.py           # Public API exports
├── facility.py           # Facility class
├── device.py             # Device and DeviceManager classes
└── connection.py         # Connection abstractions and WebSocket implementation

Contributing

We welcome contributions! Please see CONTRIBUTING.md for:

  • Development environment setup
  • Code style guidelines
  • Testing requirements
  • Pull request process

Support

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

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

scadable-2.0.0.tar.gz (20.5 kB view details)

Uploaded Source

Built Distribution

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

scadable-2.0.0-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file scadable-2.0.0.tar.gz.

File metadata

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

File hashes

Hashes for scadable-2.0.0.tar.gz
Algorithm Hash digest
SHA256 84e673e27a8df02705e8309530e30952fc8128f9ec8e1f9ac5eca4d96da1c5e7
MD5 173de28805e06151d037485a11d2f8b6
BLAKE2b-256 7bea110e53367f26e69b844137905f5eeae724f92df4c267a6ee6121f1a9ba31

See more details on using hashes here.

Provenance

The following attestation bundles were made for scadable-2.0.0.tar.gz:

Publisher: python-publish.yml on scadable/library-python

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

File details

Details for the file scadable-2.0.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for scadable-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec2a52e06ca6d62184f3ebcbcf9248c4fc35fdab8614b86eec6f3b421a2fe1aa
MD5 183ece8920a6aae175a9bafb785dbd12
BLAKE2b-256 386c01ec2b766f9728f2cfe21a5d9916496e47a76c9a4aeb884eb08366069ffb

See more details on using hashes here.

Provenance

The following attestation bundles were made for scadable-2.0.0-py3-none-any.whl:

Publisher: python-publish.yml on scadable/library-python

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