Skip to content

scadable/library-python

Repository files navigation

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.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages