Skip to content

scadable/library-react

Repository files navigation

Scadable

A production-ready React library for consuming real-time telemetry data through WebSocket connections. Built for SCADA systems, IoT dashboards, and industrial monitoring applications.

npm version License: ISC

πŸ“¦ Installation

The library is published to npm and can be installed in any React project:

npm install scadable

Requirements:

  • React 18.0.0 or higher
  • React DOM 18.0.0 or higher

πŸš€ Quick Start

Option 1: Using the LiveTelemetryLineChart Component (Recommended)

The fastest way to visualize real-time data:

import { LiveTelemetryLineChart } from 'scadable';

function App() {
  return (
    <LiveTelemetryLineChart
      apiKey="your-api-key"
      deviceId="your-device-id"
      title="Temperature Monitor"
      xAxisLabel="Time"
      yAxisLabel="Temperature (Β°C)"
      xDataPath=".timestamp"
      yDataPath=".data.temperature"
      yMin={0}
      yMax={50}
      lineColor="#8884d8"
    />
  );
}

Option 2: Using the useLiveTelemetry Hook

For custom implementations with full control:

import { Facility, Device, useLiveTelemetry } from 'scadable';

const facility = new Facility("your-api-key");
const device = new Device(facility, "your-device-id");

function App() {
  const { telemetry, isConnected, error } = useLiveTelemetry(device);

  return (
    <div>
      <h1>Status: {isConnected ? 'Connected' : 'Disconnected'}</h1>
      {error && <p>Error: {error}</p>}
      {telemetry && <pre>{JSON.stringify(telemetry, null, 2)}</pre>}
    </div>
  );
}

🎯 Key Features

  • πŸ“Š Real-Time Visualization: Live line charts with smooth scrolling data
  • πŸ”Œ WebSocket Integration: Automatic connection management and reconnection
  • βš›οΈ React Hooks: Simple useLiveTelemetry hook for custom implementations
  • πŸ›‘οΈ TypeScript Support: Full type safety with comprehensive definitions
  • 🎨 Customizable Charts: Configurable colors, scales, and dimensions
  • πŸ§ͺ Production Ready: Comprehensive tests and error handling
  • πŸ“± Framework Agnostic: Works with Next.js, Create React App, Vite, and more

πŸ“š Core API

Facility

Manages API authentication for WebSocket connections.

import { Facility } from 'scadable';

const facility = new Facility("your-api-key");

Methods:

  • connect(deviceId: string): WebSocket - Creates a WebSocket connection
  • isValid(): boolean - Validates the API key

Device

Manages device connections and message handling.

import { Facility, Device } from 'scadable';

const facility = new Facility("your-api-key");
const device = new Device(facility, "device-id");

// Connect to WebSocket
device.connect();

// Subscribe to messages
device.onMessage((data) => console.log(data));

// Handle errors
device.onError((error) => console.error(error));

// Monitor connection status
device.onStatusChange((status) => console.log(status));

// Disconnect when done
device.disconnect();

Methods:

  • connect() - Establishes WebSocket connection
  • disconnect() - Closes WebSocket connection
  • onMessage(handler) - Subscribe to telemetry messages
  • onError(handler) - Subscribe to connection errors
  • onStatusChange(handler) - Subscribe to connection status changes
  • getConnectionStatus() - Get current connection status
  • isConnected() - Check if currently connected

useLiveTelemetry Hook

React hook for consuming real-time telemetry data with automatic lifecycle management.

import { useLiveTelemetry } from 'scadable';

const { telemetry, isConnected, error } = useLiveTelemetry(device);

Returns:

  • telemetry - Latest telemetry data received
  • isConnected - Connection status (boolean)
  • error - Error message if connection fails

LiveTelemetryLineChart Component

Ready-to-use real-time line chart component.

import { LiveTelemetryLineChart } from 'scadable';

<LiveTelemetryLineChart
  apiKey="your-api-key"          // API key for authentication
  deviceId="your-device-id"      // Device ID to connect to
  title="Temperature Monitor"     // Chart title
  xAxisLabel="Time"              // X-axis label
  yAxisLabel="Temperature (Β°C)"  // Y-axis label
  xDataPath=".timestamp"         // JSON path to X value
  yDataPath=".data.temperature"  // JSON path to Y value
  yMin={0}                       // Minimum Y-axis value
  yMax={50}                      // Maximum Y-axis value
  lineColor="#8884d8"            // Optional: line color
  maxDataPoints={20}             // Optional: max data points
  width={600}                    // Optional: chart width
  height={400}                   // Optional: chart height
/>

πŸ“– Additional Documentation

🌐 Where to Access

πŸ”§ Integration Examples

Next.js Integration

'use client';

import { LiveTelemetryLineChart } from 'scadable';

export default function DashboardPage() {
  return (
    <LiveTelemetryLineChart
      apiKey={process.env.NEXT_PUBLIC_SCADABLE_API_KEY}
      deviceId="sensor-001"
      title="Temperature Monitor"
      xAxisLabel="Time"
      yAxisLabel="Temperature (Β°C)"
      xDataPath=".timestamp"
      yDataPath=".data.temperature"
      yMin={0}
      yMax={50}
    />
  );
}

Create React App Integration

import { LiveTelemetryLineChart } from 'scadable';

function App() {
  return (
    <div className="App">
      <LiveTelemetryLineChart
        apiKey={process.env.REACT_APP_SCADABLE_API_KEY}
        deviceId="sensor-001"
        title="Temperature Monitor"
        xAxisLabel="Time"
        yAxisLabel="Temperature (Β°C)"
        xDataPath=".timestamp"
        yDataPath=".data.temperature"
        yMin={0}
        yMax={50}
      />
    </div>
  );
}

Vite Integration

import { LiveTelemetryLineChart } from 'scadable';

function App() {
  return (
    <LiveTelemetryLineChart
      apiKey={import.meta.env.VITE_SCADABLE_API_KEY}
      deviceId="sensor-001"
      title="Temperature Monitor"
      xAxisLabel="Time"
      yAxisLabel="Temperature (Β°C)"
      xDataPath=".timestamp"
      yDataPath=".data.temperature"
      yMin={0}
      yMax={50}
    />
  );
}

🎨 Common Use Cases

Multiple Sensors Dashboard

function Dashboard() {
  return (
    <div>
      <LiveTelemetryLineChart
        apiKey="your-api-key"
        deviceId="temp-sensor-1"
        title="Temperature Sensor 1"
        xAxisLabel="Time"
        yAxisLabel="Β°C"
        xDataPath=".timestamp"
        yDataPath=".data.temperature"
        yMin={0}
        yMax={50}
        lineColor="#ef4444"
      />
      <LiveTelemetryLineChart
        apiKey="your-api-key"
        deviceId="pressure-sensor-1"
        title="Pressure Sensor 1"
        xAxisLabel="Time"
        yAxisLabel="PSI"
        xDataPath=".timestamp"
        yDataPath=".data.pressure"
        yMin={0}
        yMax={150}
        lineColor="#22c55e"
      />
    </div>
  );
}

Custom UI with Hook

function CustomTelemetryDisplay() {
  const facility = new Facility("your-api-key");
  const device = new Device(facility, "your-device-id");
  const { telemetry, isConnected, error } = useLiveTelemetry(device);

  return (
    <div className="custom-display">
      <div className="status-bar">
        <span className={isConnected ? 'connected' : 'disconnected'}>
          {isConnected ? '🟒 Live' : 'πŸ”΄ Offline'}
        </span>
      </div>
      {error && <div className="error">{error}</div>}
      {telemetry && (
        <div className="telemetry-data">
          <h2>Temperature: {telemetry.data?.temperature}Β°C</h2>
          <p>Last Updated: {telemetry.timestamp}</p>
        </div>
      )}
    </div>
  );
}

πŸ› οΈ Troubleshooting

Connection Issues

If you're experiencing connection problems:

  1. Verify API Key: Ensure your API key is valid
  2. Check Device ID: Confirm the device ID exists in your system
  3. Network: Verify WebSocket connections aren't blocked by firewall
  4. Browser Console: Check for error messages in the developer console

Data Not Displaying

  1. Verify JSON Paths: Ensure xDataPath and yDataPath match your data structure
  2. Check Y-axis Range: Make sure yMin and yMax encompass your data values
  3. Inspect WebSocket Messages: Use browser DevTools to inspect WebSocket traffic

TypeScript Errors

Ensure you have the latest type definitions:

npm install --save-dev @types/react @types/react-dom

Developer Documentation

πŸ› οΈ Development Setup

Prerequisites

  • Node.js: v20 or higher
  • npm: v8 or higher
  • Git: Latest version

Getting Started

  1. Clone the repository:

    git clone https://github.com/scadable/library-react.git
    cd library-react
  2. Install dependencies:

    npm install
  3. Run Storybook (interactive development environment):

    npm run storybook

    This opens at http://localhost:6006 with live component examples.

  4. Run tests:

    npm run test        # Watch mode
    npm run test:stories:ci  # CI mode
  5. Build the library:

    npm run build

πŸ—οΈ Project Architecture

High-Level Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              User's React Application                    β”‚
β”‚       (Next.js / Create React App / Vite)               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚ npm install scadable
                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           Scadable React Library                         β”‚
β”‚                                                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Components   β”‚  β”‚   Hooks    β”‚  β”‚  Core Classes  β”‚  β”‚
β”‚  β”‚              β”‚  β”‚            β”‚  β”‚                β”‚  β”‚
β”‚  β”‚ β€’ LiveChart  β”‚  β”‚ β€’ useLive  β”‚  β”‚ β€’ Facility     β”‚  β”‚
β”‚  β”‚              β”‚  β”‚   Telemetryβ”‚  β”‚ β€’ Device       β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚         β”‚                β”‚                   β”‚          β”‚
β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β”‚                          β”‚                              β”‚
β”‚                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
β”‚                 β”‚   WebSocket      β”‚                    β”‚
β”‚                 β”‚   Connection     β”‚                    β”‚
β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚ wss://
                           β–Ό
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚  Scadable Backend    β”‚
                β”‚  WebSocket Server    β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Directory Structure

library-react/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ core/                        # Core business logic
β”‚   β”‚   β”œβ”€β”€ Facility.ts             # API key & authentication
β”‚   β”‚   β”œβ”€β”€ Device.ts               # WebSocket connection management
β”‚   β”‚   └── types.ts                # TypeScript definitions
β”‚   β”‚
β”‚   β”œβ”€β”€ hooks/                       # React hooks
β”‚   β”‚   └── useLiveTelemetry.ts     # Main telemetry hook
β”‚   β”‚
β”‚   β”œβ”€β”€ components/                  # React components
β”‚   β”‚   β”œβ”€β”€ LiveTelemetryLineChart.tsx
β”‚   β”‚   β”œβ”€β”€ LiveTelemetryLineChart.stories.tsx
β”‚   β”‚   └── TelemetryDisplay.tsx
β”‚   β”‚
β”‚   β”œβ”€β”€ utils/                       # Utilities
β”‚   β”‚   β”œβ”€β”€ jsonPath.ts             # JSON path extraction
β”‚   β”‚   └── parseMessage.ts         # Message parsing
β”‚   β”‚
β”‚   └── index.ts                    # Public API exports
β”‚
β”œβ”€β”€ __tests__/                       # Test files
β”œβ”€β”€ docs/                            # Component documentation
β”œβ”€β”€ .storybook/                      # Storybook config
β”œβ”€β”€ .github/workflows/               # CI/CD pipelines
β”œβ”€β”€ dist/                            # Build output (generated)
β”œβ”€β”€ package.json
β”œβ”€β”€ vite.config.ts                  # Build configuration
└── tsconfig.json                   # TypeScript config

Component Flow

LiveTelemetryLineChart
    ↓
useLiveTelemetry Hook
    ↓
Device Class (WebSocket management)
    ↓
Facility Class (Authentication)
    ↓
WebSocket Connection
    ↓
Backend Server

Data Flow

1. User creates component with apiKey + deviceId
   ↓
2. Facility validates API key
   ↓
3. Device establishes WebSocket connection
   ↓
4. useLiveTelemetry hook:
   β€’ Connects on mount
   β€’ Subscribes to messages
   β€’ Updates React state
   β€’ Cleans up on unmount
   ↓
5. Backend sends WebSocket message
   ↓
6. parseMessage() validates JSON
   ↓
7. Hook updates state β†’ Component re-renders
   ↓
8. jsonPath extracts X/Y values β†’ Chart renders

πŸ”§ Tech Stack

Core Technologies

Technology Version Purpose
React ^19.1.1 UI framework (peer dependency)
TypeScript Latest Type safety
Vite ^6.3.6 Build tool and bundler
Vitest ^3.2.4 Testing framework
Recharts ^3.3.0 Chart visualization

Development Tools

Tool Purpose
Storybook Interactive component development
ESLint Code linting
Testing Library React testing utilities
vite-plugin-dts TypeScript declarations

Build Outputs

The library builds to three formats:

  • CommonJS: dist/index.js (older bundlers)
  • ES Modules: dist/index.mjs (modern bundlers)
  • TypeScript: dist/index.d.ts (type definitions)

πŸ§ͺ Testing

Run Tests

# Unit tests (watch mode)
npm run test

# Storybook interaction tests
npm run test:stories

# CI mode (all tests)
npm run test:stories:ci

Test Coverage

Tests cover:

  • Component rendering
  • WebSocket lifecycle (connect, disconnect, reconnect)
  • Error handling
  • Data parsing and extraction
  • Hook behavior

πŸ—οΈ Building & Publishing

Local Build

npm run build

Output in dist/ directory:

  • index.js (CommonJS)
  • index.mjs (ES Modules)
  • index.d.ts (TypeScript types)

Version Management

npm version patch   # Bug fixes (1.0.0 β†’ 1.0.1)
npm version minor   # New features (1.0.0 β†’ 1.1.0)
npm version major   # Breaking changes (1.0.0 β†’ 2.0.0)

Publishing to npm

Automated via GitHub Actions:

  1. Create a GitHub Release:

    • Tag: v1.0.11 (match package.json version)
    • Title: Same as tag
    • Description: Release notes
  2. GitHub Actions automatically:

    • Runs tests
    • Builds package
    • Publishes to npm
  3. Verify:

    npm view scadable version

πŸš€ CI/CD Pipeline

Workflows

1. CI Build (ci-build.yaml)

Runs on every push and pull request:

Steps:
1. Checkout code
2. Setup Node.js 20
3. Install dependencies (npm ci)
4. Lint code
5. Run tests
6. Build package

2. Publish (react-publish.yaml)

Runs when GitHub release is created:

Steps:
1. Checkout code
2. Setup Node.js with npm registry
3. Install dependencies
4. Build package
5. Publish to npm (with provenance)

GitHub Secrets Required

  • NPM_TOKEN: npm authentication token with publish permissions

Deployment Flow

Create GitHub Release
    ↓
Trigger GitHub Actions
    ↓
Run CI checks (lint, test, build)
    ↓
Build succeeds?
  ↙         β†˜
Yes          No
 ↓            ↓
Publish    Fail
 ↓
npm updated

🌐 Where to Access & Manage

For End Users

For Developers

Hosting & Deployment

  • Package Registry: npm (public)
  • CI/CD: GitHub Actions
  • Version Control: GitHub

🀝 Contributing

Contribution Workflow

  1. Fork the repository
  2. Clone your fork locally
  3. Create a feature branch:
    git checkout -b feature/my-feature
  4. Make changes with clear commits:
    git commit -m "feat: add new feature"
  5. Test your changes:
    npm run test
    npm run build
  6. Push and create a pull request

Commit Convention

Follow conventional commits:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation
  • test: Tests
  • chore: Maintenance
  • refactor: Code refactoring

Code Review Process

  1. Automated CI checks must pass
  2. At least one maintainer review
  3. Address feedback
  4. Merge when approved

πŸ” Troubleshooting Development

Storybook won't start

rm -rf node_modules package-lock.json
npm install
npm run storybook

Build fails

npx tsc --noEmit  # Check TypeScript errors
rm -rf dist
npm run build

Tests failing

npm run test -- --reporter=verbose

πŸ“„ License

ISC License - See LICENSE file for details


πŸ“ž Support

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 5