feat: externalize cluster integration and API

This commit is contained in:
2025-10-19 21:52:55 +02:00
parent 8de77e225d
commit a7018f53f3
4 changed files with 1245 additions and 1270 deletions

198
README.md
View File

@@ -1,14 +1,22 @@
# SPORE UI # SPORE UI Frontend
Zero-configuration web interface for monitoring and managing SPORE embedded systems. Frontend web interface for monitoring and managing SPORE embedded systems. Now works in conjunction with the SPORE Gateway backend service.
## Architecture
This frontend server works together with the **SPORE Gateway** (spore-gateway) backend service:
- **spore-ui**: Serves the static frontend files and provides the user interface
- **spore-gateway**: Handles UDP node discovery, API endpoints, and WebSocket connections
## Features ## Features
- **🌐 Cluster Monitoring**: Real-time view of all cluster members with auto-discovery - **🌐 Cluster Monitoring**: Real-time view of all cluster members via spore-gateway
- **📊 Node Details**: Detailed system information including running tasks and available endpoints - **📊 Node Details**: Detailed system information including running tasks and available endpoints
- **🚀 OTA**: Clusterwide over-the-air firmware updates - **🚀 OTA**: Clusterwide over-the-air firmware updates
- **📱 Responsive**: Works on all devices and screen sizes - **📱 Responsive**: Works on all devices and screen sizes
- **🖥️ Terminal**: Terminal for interacting with a node's WebSocket - **🖥️ Terminal**: Terminal for interacting with a node's WebSocket
- **🔗 Gateway Integration**: Seamlessly connects to spore-gateway for all backend functionality
## Screenshots ## Screenshots
### Cluster ### Cluster
@@ -22,161 +30,85 @@ Zero-configuration web interface for monitoring and managing SPORE embedded syst
## Getting Started ## Getting Started
### Prerequisites
1. **Install dependencies**: `npm install` 1. **Install dependencies**: `npm install`
2. **Start the server**: `npm start` 2. **Start spore-gateway**: `./spore-gateway` (in the spore-gateway directory)
3. **Open in browser**: `http://localhost:3001` 3. **Start frontend server**: `npm start`
## API Endpoints ### Access
- **Frontend UI**: `http://localhost:3000`
- **API Backend**: spore-gateway runs on port 3001
- **WebSocket**: Connects to spore-gateway on port 3001
- **`/`** - Main UI page ## API Integration
- **`/api/cluster/members`** - Get cluster member information
- **`/api/tasks/status`** - Get task status The frontend automatically connects to the spore-gateway for:
- **`/api/node/status`** - Get system status
- **`/api/node/status/:ip`** - Get status from specific node - **Cluster Discovery**: `/api/discovery/*` endpoints
- **Node Management**: `/api/node/*` endpoints
- **Task Monitoring**: `/api/tasks/*` endpoints
- **Real-time Updates**: WebSocket connections via `/ws`
## Technologies Used ## Technologies Used
- **Backend**: Express.js, Node.js - **Backend Integration**: Express.js server connecting to spore-gateway
- **Frontend**: Vanilla JavaScript, CSS3, HTML5 - **Frontend**: Vanilla JavaScript, CSS3, HTML5
- **Framework**: Custom component-based architecture - **Framework**: Custom component-based architecture
- **API**: SPORE Embedded System API - **API**: SPORE Embedded System API via spore-gateway
- **Design**: Glassmorphism, CSS Grid, Flexbox - **Design**: Glassmorphism, CSS Grid, Flexbox
## UDP Heartbeat Discovery ## Development
The backend now includes automatic UDP heartbeat-based discovery for SPORE nodes on the network. This eliminates the need for hardcoded IP addresses and provides a self-healing, scalable solution for managing SPORE clusters. ### File Structure
```
### 🚀 How It Works spore-ui/
├── public/ # Static frontend files
1. **UDP Server**: The backend listens on port 4210 for UDP messages │ ├── index.html # Main HTML page
2. **Heartbeat Message**: Nodes send `CLUSTER_HEARTBEAT` messages to broadcast address `255.255.255.255:4210` │ ├── scripts/ # JavaScript components
3. **Auto Configuration**: When a heartbeat message is received, the source IP is automatically used to configure the SporeApiClient │ └── styles/ # CSS stylesheets
4. **Dynamic Updates**: The system automatically switches to the most recently seen node as the primary connection ├── index.js # Simple static file server
5. **Health Monitoring**: Continuous monitoring of node availability with automatic failover └── package.json # Node.js dependencies
### 📡 Heartbeat Protocol
- **Port**: 4210 (configurable via `UDP_PORT` constant)
- **Message**: `CLUSTER_HEARTBEAT` (configurable via `HEARTBEAT_MESSAGE` constant)
- **Broadcast**: `255.255.255.255:4210`
- **Protocol**: UDP broadcast listening
- **Auto-binding**: Automatically binds to the specified port on startup
### 🔧 Setup Instructions
#### Backend Setup
```bash
# Start the backend server
npm start
# The server will automatically:
# - Start HTTP server on port 3001
# - Start UDP heartbeat server on port 4210
# - Wait for CLUSTER_HEARTBEAT messages
``` ```
#### Node Configuration ### Key Changes
SPORE nodes should send heartbeat messages periodically: - **Simplified Backend**: Now only serves static files
- **Gateway Integration**: All API calls go through spore-gateway
- **WebSocket Proxy**: Real-time updates via spore-gateway
- **UDP Discovery**: Handled by spore-gateway service
## Troubleshooting
### Common Issues
**Frontend not connecting to gateway**
```bash ```bash
# Recommended: Send every 30-60 seconds # Check if spore-gateway is running
# Message format: "CLUSTER_HEARTBEAT:hostname"
# Target: 255.255.255.255:4210
```
### 🌐 Cluster Endpoints
#### Cluster Management
- `GET /api/discovery/nodes` - View all cluster nodes and current status
- `POST /api/discovery/refresh` - Manually trigger cluster refresh
- `POST /api/discovery/primary/:ip` - Manually set a specific node as primary
- `POST /api/discovery/random-primary` - Randomly select a new primary node
#### Health Monitoring
- `GET /api/health` - Comprehensive health check including cluster status
### 🧪 Testing & Development
#### Test Scripts
```bash
# Send discovery messages to test the system
npm run test-discovery broadcast
# Send to specific IP
npm run test-discovery 192.168.1.100
# Send multiple messages
npm run test-discovery broadcast 5
# Test random primary node selection
npm run test-random-selection
# Monitor discovery in real-time
npm run demo-discovery
```
#### Manual Testing
```bash
# Check discovery status
curl http://localhost:3001/api/discovery/nodes
# Check health
curl http://localhost:3001/api/health curl http://localhost:3001/api/health
# Manual refresh # Verify gateway health
curl -X POST http://localhost:3001/api/discovery/refresh # Should return gateway health status
# Random primary selection
curl -X POST http://localhost:3001/api/discovery/random-primary
# Set specific primary
curl -X POST http://localhost:3001/api/discovery/primary/192.168.1.100
``` ```
### 🔍 Troubleshooting **WebSocket connection issues**
#### Common Issues
**No Nodes Discovered**
```bash ```bash
# Check if backend is running # Check WebSocket endpoint
curl http://localhost:3001/api/health curl http://localhost:3001/api/test/websocket
# Verify UDP port is open # Verify gateway WebSocket server is running
netstat -tulpn | grep 4210
# Send test discovery message
npm run test-discovery broadcast
``` ```
**UDP Port Already in Use** **No cluster data**
```bash ```bash
# Check for conflicting processes # Check gateway discovery status
netstat -tulpn | grep 4210
# Kill conflicting processes or change port in code
# Restart backend server
```
**Client Not Initialized**
```bash
# Check discovery status
curl http://localhost:3001/api/discovery/nodes curl http://localhost:3001/api/discovery/nodes
# Verify nodes are sending discovery messages # Verify SPORE nodes are sending heartbeat messages
# Check network connectivity
``` ```
#### Debug Commands ## Architecture Benefits
```bash
# Check discovery status
curl http://localhost:3001/api/discovery/nodes
# Check health 1. **Separation of Concerns**: Frontend handles UI, gateway handles backend logic
curl http://localhost:3001/api/health 2. **Scalability**: Gateway can handle multiple frontend instances
3. **Maintainability**: Clear separation between presentation and business logic
# Manual refresh 4. **Performance**: Gateway can optimize API calls and caching
curl -X POST http://localhost:3001/api/discovery/refresh 5. **Reliability**: Gateway provides failover and health monitoring
# Set primary node
curl -X POST http://localhost:3001/api/discovery/primary/192.168.1.100
```

1164
index-standalone.js Normal file

File diff suppressed because it is too large Load Diff

1141
index.js

File diff suppressed because it is too large Load Diff

View File

@@ -159,9 +159,9 @@ class WebSocketClient {
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
if (currentHost === 'localhost' || currentHost === '127.0.0.1') { if (currentHost === 'localhost' || currentHost === '127.0.0.1') {
this.wsUrl = `${wsProtocol}//localhost:3001`; this.wsUrl = `${wsProtocol}//localhost:3001/ws`;
} else { } else {
this.wsUrl = `${wsProtocol}//${currentHost}:3001`; this.wsUrl = `${wsProtocol}//${currentHost}:3001/ws`;
} }
logger.debug('WebSocket Client initialized with URL:', this.wsUrl); logger.debug('WebSocket Client initialized with URL:', this.wsUrl);