Skip to content

BrightDevelopers/gopurple

Repository files navigation

Gopurple - BSN.cloud SDK for Go

Gopurple Logo

Status: EXTERNAL BETA RELEASE

Why Go Instead of Python?

Python is incredibly popular and would be an easy starting point for many developers. Its vast ecosystem, readable syntax, and extensive libraries make it a natural first choice. However, after careful consideration, we chose Go for this SDK. Here's why:

Cross-Platform Deployment: Single Binary Simplicity

One of Python's biggest challenges is deployment complexity. Running Python reliably across Windows, macOS, Linux, and cloud environments requires managing:

  • Python interpreter installation - Ensuring the correct Python version is available on each target system
  • Virtual environments - Isolating dependencies per project to avoid conflicts
  • Dependency resolution - Managing pip, requirements.txt, and potential version conflicts between packages
  • Platform-specific issues - Some packages require different installation procedures or have OS-specific dependencies

As noted in the Python community, dependency management can be challenging, and many teams resort to containerization just to achieve consistent deployments.

Go takes a different approach: compile once, run anywhere. The Go compiler produces a single, self-contained binary with no external dependencies. Deploy to Windows, Mac, Linux, or any cloud platform by simply copying one file. No runtime installation, no virtual environments, no dependency management on target systems.

Easy to Learn

Go was designed with simplicity in mind. Its small, consistent syntax means developers can become productive quickly. The language has:

  • 25 keywords (compared to Python's 35+)
  • One way to do things - Go's philosophy reduces decision fatigue
  • Excellent documentation - The standard library is well-documented with runnable examples
  • Built-in formatting - go fmt eliminates style debates

Excellent Concurrency Model

Go's concurrency primitives—goroutines and channels—provide an intuitive model for parallel operations. This is essential for an SDK that needs to:

  • Handle multiple device connections simultaneously
  • Process large batches of API requests efficiently
  • Manage concurrent uploads and downloads

Python's Global Interpreter Lock (GIL) limits true parallelism, making concurrent I/O-bound operations more complex to implement correctly.

AI and LLMs Write Excellent Go Code

Modern AI assistants and LLMs are remarkably proficient at generating Go code. This is increasingly important as developers leverage AI tools for productivity. Go's characteristics make it particularly well-suited for AI-assisted development:

  • Strong typing catches errors at compile time, providing immediate feedback on generated code
  • Simple, consistent syntax means AI models produce more reliable output
  • Comprehensive standard library reduces the need for third-party dependencies
  • Clear error handling patterns result in more predictable generated code

As the Go team notes, Go is excellent for building LLM-powered applications, and the same qualities that make it good for using AI make it good for AI to write.

Performance Where It Matters

Go compiles to native machine code, delivering significantly better performance than interpreted Python for CPU-bound operations. For an SDK making hundreds of API calls, parsing large responses, and processing device data, this translates to faster execution and lower resource usage.

A comprehensive Go SDK providing type-safe access to BrightSign Network (BSN.cloud) APIs. Includes both the main REST API and Remote Diagnostic Web Server (RDWS) functionality with 64 working example programs.

What It Does

This SDK abstracts the complexity of BSN.cloud integration:

  • OAuth2 Authentication - Automatic token management and refresh
  • Device Management - List, monitor, control, and provision BrightSign players
  • Remote Operations - Screenshots, reboots, file management, diagnostics via RDWS
  • B-Deploy Provisioning - Create and manage player setup configurations
  • Network Management - Handle multiple networks, groups, permissions

Key Features:

  • Full type safety - All nested types exported for compile-time checking and IDE autocomplete
  • Device status monitoring - Type-safe access to firmware, network, storage, and sync information
  • Screenshot capture - Request and response types for device snapshots with region support
  • Structured error types with context
  • Pagination support for large datasets
  • Network context management with BS_NETWORK environment variable support
  • Concurrent-safe token handling
  • 64 example CLI tools demonstrating all features
  • Flexible output modes (JSON, stdout, file) for automation and scripting

Quick Start

Installation

Recommended: Pin to a specific version

go get github.com/brightdevelopers/gopurple@v1.2.0

Or use latest (development)

go get github.com/brightdevelopers/gopurple

In your go.mod:

require github.com/brightdevelopers/gopurple v1.2.0

See versioning docs for version management details.

Basic Usage

package main

import (
    "context"
    "log"
    "github.com/brightdevelopers/gopurple"
)

func main() {
    // Create client (uses BS_CLIENT_ID and BS_SECRET env vars)
    client, err := gopurple.New()
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Authenticate and set network
    if err := client.Authenticate(ctx); err != nil {
        log.Fatal(err)
    }

    // List devices
    devices, err := client.Devices.List(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Found %d devices", len(devices.Items))
}

Working with Device Status

The SDK provides full type safety for device status information, including firmware, network, storage, and synchronization details:

// Get device with full status information
device, err := client.Devices.Get(ctx, "ABC123")
if err != nil {
    log.Fatal(err)
}

// Access device status with full type safety
if device.Status != nil {
    // Check firmware version
    if device.Status.Firmware != nil {
        log.Printf("Firmware: %s", device.Status.Firmware.Version)
    }

    // Check network connectivity
    if device.Status.Network != nil {
        log.Printf("IP: %s", device.Status.Network.ExternalIP)
        for _, iface := range device.Status.Network.Interfaces {
            log.Printf("  %s: %s", iface.Name, iface.Type)
        }
    }

    // Monitor storage usage
    for _, storage := range device.Status.Storage {
        pct := float64(storage.Used) / float64(storage.Total) * 100
        log.Printf("Storage: %.1f%% used", pct)
    }
}

Taking Screenshots

Capture device screenshots with specific regions and quality settings:

// Take a full-screen screenshot
req := &gopurple.SnapshotRequest{
    Format:  "png",
    Quality: 90,
}

resp, err := client.RDWS.Snapshot(ctx, "ABC123", req)
if err != nil {
    log.Fatal(err)
}
log.Printf("Screenshot: %s (%dx%d)", resp.Filename, resp.Width, resp.Height)

// Capture specific region
regionReq := &gopurple.SnapshotRequest{
    Format:  "jpeg",
    Quality: 85,
    Region: &gopurple.Region{
        X:      100,
        Y:      100,
        Width:  1920,
        Height: 1080,
    },
}

Type-Safe B-Deploy Configuration

Build device setup records with full compile-time type checking:

setup := &gopurple.BDeploySetupRecord{
    Version: "1.0",
    BDeploy: &gopurple.BDeployInfo{
        // ... your B-Deploy configuration
    },
    IdleScreenColor: &gopurple.IdleScreenColor{
        R: 0, G: 0, B: 0, A: 1,  // Black idle screen
    },
}

Version Management

Using Versioned Releases (Recommended)

Always pin to specific versions in production to ensure reproducible builds:

# Install specific version
go get github.com/brightdevelopers/gopurple@v1.2.0

In your go.mod:

require github.com/brightdevelopers/gopurple v1.2.0

Checking Available Versions

# List all available versions
go list -m -versions github.com/brightdevelopers/gopurple

# View current installed version
go list -m github.com/brightdevelopers/gopurple

# View release notes
gh release list --repo brightdevelopers/gopurple

Updating to Newer Versions

# Update to specific version
go get github.com/brightdevelopers/gopurple@v1.3.0

# Update to latest version
go get -u github.com/brightdevelopers/gopurple

# Update to latest patch only (safer)
go get -u=patch github.com/brightdevelopers/gopurple

Semantic Versioning

The SDK follows Semantic Versioning 2.0.0:

  • v1.x.x → v1.x.x - Backward compatible (safe to update)
  • v1.x.x → v2.0.0 - Breaking changes (review migration guide)
  • v1.x.x-beta.x - Pre-release versions (test before production)

Version compatibility:

# All v1 releases are compatible with each other
v1.0.0, v1.1.0, v1.2.0  ✅ Compatible

# Major version changes may require code updates
v1.x.x → v2.0.0  ⚠️ Review breaking changes

CI/CD Integration

GitHub Actions:

- name: Install gopurple
  run: go get github.com/brightdevelopers/gopurple@v1.2.0

Dockerfile:

FROM golang:1.24-alpine
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
# gopurple version pinned in go.mod
COPY . .
RUN go build -o app

For Maintainers: Creating Releases

# Create a new release
./scripts/release.sh v1.2.0 "Release Description"

# Create a pre-release
./scripts/release.sh v1.3.0-beta.1 "Beta: New Features"

See RELEASING.md for the complete release process and docs/versioning.md for detailed version management documentation.

Authentication

Get API Credentials

  1. Log into BSN.cloud
  2. Navigate to AdminAPI Access
  3. Create new OAuth2 credentials
  4. Note your Client ID and Secret

Configure SDK

export BS_CLIENT_ID=your_client_id
export BS_SECRET=your_client_secret
export BS_NETWORK=your_network_name  # optional

Or configure programmatically:

client, err := gopurple.New(
    gopurple.WithCredentials("client-id", "client-secret"),
    gopurple.WithNetwork("Production"),
    gopurple.WithTimeout(60*time.Second),
)

Examples

The SDK includes 64 working example programs demonstrating all functionality. Each example is a standalone CLI tool you can use immediately.

See examples/README.md for complete documentation of all examples with usage instructions.

Example Categories

Category Count Examples
Authentication 2 Token management, credential testing
B-Deploy Provisioning 13 Setup records, device association, template rendering, token generation
Device Management 9 List, status, errors, operations, group management
Group Management 3 Group info, updates, deletion
Subscription Management 3 Device subscriptions, counts, operations
Remote DWS (RDWS) 34 Remote control, diagnostics, file operations, screenshots

Quick Example

# Build all examples
make build-examples

# List devices
./bin/main--devices-list --network Production

# Get device info via RDWS
./bin/rdws-info --serial BS123456789

# Capture screenshot
./bin/rdws-snapshot --serial BS123456789 --output screenshot.png

# Get device logs (flexible output modes)
./bin/rdws-logs-get --serial BS123456789 --logfile device.log  # to file
./bin/rdws-logs-get --serial BS123456789 --stdout | grep ERROR # to stdout
./bin/rdws-logs-get --serial BS123456789 --json                # as JSON

Configuration Files

Example configuration files are provided in multiple locations:

B-Deploy Setup Configurations (examples/bdeploy-add-setup/)

  • config.json - Basic B-Deploy setup configuration
  • config-comprehensive.json - Full setup with all debugging/logging enabled
  • config-wifi-example.json - Wireless network configuration example
  • config-annotated.json - Annotated configuration showing all available options

The comprehensive configuration includes:

  • Local DWS enabled with password protection
  • Remote DWS enabled
  • All logging types enabled (playback, event, diagnostic, state, variable)
  • Serial and system log debugging enabled
  • Remote screenshots enabled
  • Network diagnostics enabled

Global Configuration Examples (configs/)

  • bsn-control.json - BSN.cloud network control setup example
  • lfn-control.json - Local File Network (LFN) control setup example

Update Configurations (examples/bdeploy-update-setup/)

  • example-config.json - Partial setup update example
  • example-full-update.json - Complete setup reconfiguration example

These show the JSON structure expected by various SDK methods and can be used as templates for your own configurations.

Note: SSH and Telnet must be enabled via RDWS after device provisioning.

API Coverage

Implementation Status: 43 of ~294 endpoints

See docs/all-apis.md for a comprehensive list of all BSN.cloud API endpoints with implementation status ([DONE] or [NOT-DONE]).

What's Implemented

Device Management (Complete)

  • List devices with pagination, filtering, sorting
  • Get device details, status, errors, operations
  • Update device properties, change groups
  • Delete devices

Remote Diagnostic Web Server (RDWS) (Complete)

  • Device info, health, time management
  • Remote reboot (normal, crash, factory reset)
  • Screenshots and diagnostics
  • File operations (list, upload, download, delete, rename)
  • Network diagnostics (ping, traceroute, DNS lookup)
  • Registry operations (read, write)
  • Log and crashdump retrieval
  • Firmware downloads
  • SSH/Telnet management
  • Local DWS control
  • Storage reformatting

B-Deploy Provisioning (Complete)

  • Create, update, delete setup records (struct-based and raw JSON)
  • Associate devices with setups
  • List and query provisioning configurations
  • Template-based setup generation with dynamic token injection
  • Raw JSON round-trip preserving all fields (firmware entries, network config)

Group Management (Core Features)

  • Get group information
  • Update group properties
  • Delete groups

Subscription Management (Read Operations)

  • List device subscriptions
  • Get subscription counts
  • Query permissions

What's Not Yet Implemented

See docs/all-apis.md for the complete list of unimplemented endpoints, including:

  • Autorun/Plugin management
  • Dynamic playlists
  • Live text feeds
  • Data feeds
  • Device web pages
  • Live media feeds
  • Scheduled downloads
  • Tag management
  • User management
  • Web folder management
  • And more...

The SDK focuses on the most commonly used operations first. Additional endpoints can be added as needed.

Architecture

graph TB
    App[Your Application] --> Client[gopurple.Client]
    Client --> Auth[Auth Manager]
    Client --> HTTP[HTTP Client]
    Client --> Services[Service Layers]

    Auth --> Token[Token Management]
    Auth --> Network[Network Context]

    HTTP --> Retry[Retry Logic]
    HTTP --> Error[Error Handling]

    Services --> Devices[Device Service]
    Services --> RDWS[RDWS Service]
    Services --> BDeploy[B-Deploy Service]

    HTTP --> BSN[BSN Main API<br/>api.bsn.cloud]
    HTTP --> RDWS_API[Remote DWS API<br/>ws.bsn.cloud]
Loading

Authentication Flow

sequenceDiagram
    participant App
    participant Client
    participant Auth
    participant BSN as BSN.cloud

    App->>Client: New()
    Client->>Auth: NewAuthManager()

    App->>Client: Authenticate(ctx)
    Client->>Auth: Authenticate()
    Auth->>BSN: POST /token (client_credentials)
    BSN-->>Auth: access_token + expires_in
    Auth-->>Client: success

    App->>Client: SetNetwork(ctx, "MyNetwork")
    Client->>Auth: SetNetwork()
    Auth->>BSN: PUT /Self/Session/Network
    BSN-->>Auth: 204 No Content
    Auth-->>Client: network set

    App->>Client: API Operation
    Client->>Auth: GetToken()
    Auth->>Auth: Check expiry
    Auth-->>Client: valid token
    Client->>BSN: API request with token
    BSN-->>Client: response
    Client-->>App: result
Loading

Usage Examples

Device Operations

// List devices with filtering
params := &gopurple.DeviceListParams{
    Filter:   "model=XD1033",
    Sort:     "lastModifiedDate desc",
    PageSize: 50,
}
devices, err := client.Devices.List(ctx, params)

// Get specific device
device, err := client.Devices.GetBySerial(ctx, "BS123456789")

// Change device group
err = client.Devices.Update(ctx, deviceID, &gopurple.DeviceUpdate{
    GroupID: newGroupID,
})

// Delete device
err = client.Devices.Delete(ctx, deviceID)

Remote Operations (RDWS)

// Get device info
info, err := client.RDWS.GetInfo(ctx, serial)

// Capture screenshot
screenshot, err := client.RDWS.Snapshot(ctx, serial)
os.WriteFile("screenshot.png", screenshot, 0644)

// Reboot device
success, err := client.RDWS.Reboot(ctx, serial, "normal")

// List files on device
files, err := client.RDWS.ListFiles(ctx, serial, "/storage/sd/")

// Upload file to device
err = client.RDWS.UploadFile(ctx, serial, localPath, remotePath)

B-Deploy Provisioning

// Create setup record from config
config := &types.BDeploySetupConfig{
    NetworkName: "Production",
    Username:    "admin@example.com",
    PackageName: "retail-display",
    SetupType:   "bsn",
    Network: types.NetworkConfig{
        TimeServers: []string{"time.bsn.cloud"},
        Interfaces: []types.NetworkInterface{
            {
                ID:                      "eth0",
                Type:                    "Ethernet",
                Proto:                   "DHCPv4",
                ContentDownloadEnabled:  true,
                HealthReportingEnabled:  true,
            },
        },
    },
}

setupID, err := client.BDeploy.CreateSetup(ctx, config)

// Associate device with setup
err = client.BDeploy.AssociateDevice(ctx, serial, setupID)

Error Handling

devices, err := client.Devices.List(ctx, nil)
if err != nil {
    if gopurple.IsAuthenticationError(err) {
        log.Println("Auth failed - check credentials")
    } else if gopurple.IsNetworkError(err) {
        log.Println("Network issue - check connectivity")
    } else if gopurple.IsRateLimitError(err) {
        log.Println("Rate limited - retry later")
    } else if gopurple.IsRetryableError(err) {
        log.Println("Temporary error - will retry")
    } else {
        log.Printf("API error: %v", err)
    }
    return
}

Development

Build and Test

# Run all tests
make test

# Build all example programs
make build-examples

# Build specific example
make build-main--devices-list

# Clean build artifacts
make clean

# Run all (test + build)
make all

Project Structure

gopurple/
├── gopurple.go                      # Main SDK client interface
├── internal/
│   ├── auth/                       # OAuth2 authentication
│   ├── config/                     # Configuration management
│   ├── errors/                     # Error types
│   ├── http/                       # HTTP client wrapper
│   ├── services/                   # API service implementations
│   └── types/                      # Data structures
├── templates/                       # Setup template files
│   └── DefaultSetupPackageTemplateMaster.json  # Master Go-template for B-Deploy setups
├── setups/                          # Rendered setup templates
│   └── setup-template.json         # Reference setup template
├── examples/                        # 64 example CLI programs
│   ├── render-setup-template/      # Render template + generate token -> stdout
│   ├── generate-token-json/        # Generate registration token JSON
│   ├── bdeploy-add-setup-raw/      # Create setup from raw JSON (preserves all fields)
│   ├── bdeploy-add-setup/          # Create setup via Go struct
│   │   ├── config.json             # Basic setup example
│   │   ├── config-comprehensive.json
│   │   └── config-wifi-example.json
│   ├── bdeploy-update-setup/
│   │   ├── example-config.json
│   │   └── example-full-update.json
│   ├── README.md                   # Complete examples documentation
│   └── ... (55+ more examples)
├── configs/                         # Global configuration examples
│   ├── bsn-control.json
│   └── lfn-control.json
├── docs/
│   ├── all-apis.md                 # Complete API endpoint reference
│   ├── bdeploy-config-reference.md # B-Deploy configuration guide
│   ├── bdeploy-association.md      # Device association documentation
│   └── need-json-out.md            # Programs needing JSON output
├── images/
│   └── logo.png                    # Project logo
└── Makefile                         # Build targets

Requirements

  • Go 1.21+
  • BSN.cloud API credentials (OAuth2 Client ID and Secret)
  • Network access to:
    • auth.bsn.cloud (authentication)
    • api.bsn.cloud (main API)
    • ws.bsn.cloud (RDWS API)

Contributing

This SDK prioritizes the most commonly used BSN.cloud operations. If you need additional endpoints:

  1. Check docs/all-apis.md to see if it's documented
  2. Look at existing service implementations in internal/services/
  3. Follow the established patterns for consistency
  4. Add tests and example programs
  5. Update documentation

For Maintainers

Creating releases:

./scripts/release.sh v1.2.0 "Release Description"

See RELEASING.md for the complete release workflow and docs/versioning.md for version management guidelines.

License

This is an unofficial SDK for BSN.cloud integration.

Resources

Documentation

Links

Disclaimer

EXPERIMENTAL ONLY - This SDK is provided as-is for integration with BrightSign Network. While actively used in production, it is not officially supported by BrightSign LLC. Use at your own discretion.

About

Gopurple - BSN.cloud SDK for Go

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages