# Feature Specification: Modbus Relay Control System
**Feature Branch**: `001-modbus-relay-control`
**Created**: 2025-12-28
**Status**: Draft
**Input**: User description: "Modbus relay control system: backend reads relay and writes states via Modbus, exposes REST API, frontend displays relay states and allows toggling."
## Executive Summary
### Problem Statement
Users currently require specialized Modbus software (Modbus Poll, SSCOM) to interact with an 8-channel relay device, creating barriers to adoption and limiting remote access capabilities. The lack of a web-based interface prevents non-technical users from controlling relays and limits integration possibilities.
### Proposed Solution
A web application consisting of:
- **Rust Backend**: Modbus RTU over TCP integration + RESTful HTTP API (deployed on Raspberry Pi)
- **Vue.js Frontend**: Real-time relay status display and control interface (deployed on Cloudflare Pages)
- **Reverse Proxy**: Traefik with Authelia middleware for authentication and HTTPS termination
- **Local Network**: Raspberry Pi on same network as Modbus relay device
### Value Proposition
- **Accessibility**: Control relays from any browser without specialized software
- **Usability**: Intuitive UI eliminates need for Modbus protocol knowledge
- **Foundation**: Enables future automation, scheduling, and integration capabilities
- **Deployment**: Self-contained system with no external dependencies
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Monitor Relay Status (Priority: P1)
As a user, I want to see the current state (on/off) of all 8 relays in real-time so I can verify the physical system state without being physically present.
**Why this priority**: Foundation capability - all other features depend on accurate state visibility. Delivers immediate value by eliminating need for physical inspection or specialized software.
**Independent Test**: Can be fully tested by loading the web interface and verifying displayed states match physical relay states (verified with multimeter or visual indicators). Delivers value even without control capabilities.
**Acceptance Scenarios**:
1.**Given** all relays are OFF, **When** I load the web interface, **Then** I see 8 relays each displaying "OFF" state
2.**Given** relay #3 is ON and others are OFF, **When** I load the interface, **Then** I see relay #3 showing "ON" and others showing "OFF"
3.**Given** the interface is loaded, **When** relay state changes externally (via Modbus Poll), **Then** the interface updates within 2 seconds to reflect the new state
4.**Given** the Modbus device is unreachable, **When** I load the interface, **Then** I see an error message indicating the device is unavailable
---
### User Story 2 - Toggle Individual Relay (Priority: P1)
As a user, I want to toggle any relay on or off with a single click so I can control connected devices remotely.
**Why this priority**: Core use case - enables remote control capability. Combined with Story 1, creates a complete minimal viable product.
**Independent Test**: Can be tested by clicking any relay toggle button and observing both UI update and physical relay click/LED change. Delivers standalone value for remote control.
**Acceptance Scenarios**:
1.**Given** relay #5 is OFF, **When** I click the toggle button for relay #5, **Then** relay #5 turns ON and the UI reflects this within 1 second
2.**Given** relay #2 is ON, **When** I click the toggle button for relay #2, **Then** relay #2 turns OFF and the UI reflects this within 1 second
3.**Given** the Modbus device is unreachable, **When** I attempt to toggle a relay, **Then** I see an error message and the UI does not change
4.**Given** I toggle relay #1, **When** the Modbus command times out, **Then** I see a timeout error and can retry
---
### User Story 3 - Bulk Relay Control (Priority: P2)
As a user, I want to turn all relays ON or OFF simultaneously so I can quickly reset the entire system or enable/disable all connected devices at once.
**Why this priority**: Efficiency improvement for common scenarios (system shutdown, initialization). Not critical for MVP but significantly improves user experience.
**Independent Test**: Can be tested by clicking "All ON" or "All OFF" buttons and verifying all 8 physical relays respond. Delivers value for batch operations without requiring individual story implementations.
**Acceptance Scenarios**:
1.**Given** relays have mixed states (some ON, some OFF), **When** I click "All ON", **Then** all 8 relays turn ON within 2 seconds
2.**Given** all relays are ON, **When** I click "All OFF", **Then** all 8 relays turn OFF within 2 seconds
3.**Given** I click "All ON" and relay #4 fails to respond, **Then** I see an error for relay #4 but other relays still turn ON
4.**Given** the Modbus device is unreachable, **When** I click "All ON", **Then** I see an error message and no state changes occur
---
### User Story 4 - System Health Monitoring (Priority: P2)
As a user, I want to see device connectivity status and firmware version so I can diagnose issues and verify device compatibility.
**Why this priority**: Operational value for troubleshooting. Not required for basic control but critical for production reliability and maintenance.
**Independent Test**: Can be tested by viewing the health status section, disconnecting the Modbus device, and observing status change. Delivers standalone diagnostic value.
**Acceptance Scenarios**:
1.**Given** the Modbus device is connected and responsive, **When** I view the health status, **Then** I see "Healthy" status with firmware version displayed
2.**Given** the Modbus device is unreachable, **When** the backend starts, **Then** the backend starts successfully and the frontend displays "Unhealthy - Device Unreachable" status
3.**Given** the Modbus device becomes unreachable during operation, **When** I view the health status, **Then** I see "Unhealthy - Connection Lost" with timestamp of last successful communication
4.**Given** the Modbus device responds but with CRC errors, **When** I view health status, **Then** I see "Degraded - Communication Errors" with error count
---
### User Story 5 - Relay Labeling (Priority: P3)
As a user, I want to assign custom labels to each relay (e.g., "Garage Light", "Water Pump") so I can identify relays by purpose instead of numbers.
**Why this priority**: Usability enhancement - makes system more intuitive for production use. Not required for MVP but improves long-term user experience.
**Independent Test**: Can be tested by assigning a label to relay #1, refreshing the page, and verifying the label persists. Delivers value for multi-relay installations without requiring other stories.
**Acceptance Scenarios**:
1.**Given** I am viewing relay #3, **When** I click "Edit Label" and enter "Office Fan", **Then** relay #3 displays "Office Fan (Relay 3)"
2.**Given** relay #7 has label "Water Pump", **When** I refresh the page, **Then** relay #7 still shows "Water Pump (Relay 7)"
3.**Given** I have labeled multiple relays, **When** I toggle a relay by label, **Then** the correct physical relay responds
4.**Given** two relays have similar labels, **When** I search for a label, **Then** both matching relays are highlighted
---
### Edge Cases
- **Network Partition**: What happens when the Raspberry Pi loses connectivity to the Modbus device mid-operation?
- Backend marks device unhealthy, frontend displays error state, pending operations fail gracefully with clear error messages
- **Concurrent Control**: How does system handle multiple users toggling the same relay simultaneously?
- Last-write-wins semantics, each client receives updated state via polling within 2 seconds
- **Modbus Timeout**: What happens when a relay command times out?
- Backend retries once automatically, if retry fails, returns error to frontend with clear timeout message
- **Partial Bulk Failure**: What happens when "All ON" command succeeds for 7 relays but relay #4 fails?
- Frontend displays partial success with list of failed relays, successful relays remain ON, user can retry failed relays individually
- **Rapid Toggle Requests**: How does system handle user clicking toggle button repeatedly in quick succession?
| Modbus device firmware incompatibility | High | Low | Test with actual hardware early, document compatible firmware versions |
| Network latency exceeds timeout thresholds | Medium | Medium | Make timeouts configurable, implement adaptive retry logic |
| Concurrent control causes state conflicts | Low | Medium | Implement last-write-wins with clear state refresh in UI |
| Frontend polling overwhelms backend | Low | Low | Rate limit API endpoints, make poll interval configurable |
| Raspberry Pi resource exhaustion | Medium | Low | Benchmark with 10 concurrent users, optimize Modbus connection pooling |
## Revision History
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0 | 2025-12-28 | Business Analyst Agent | Initial specification based on user input |
| 1.1 | 2025-12-28 | User Clarification | FR-023 clarified: Backend starts successfully even when device unhealthy, frontend displays error (part of Health story) |
| 1.2 | 2025-12-29 | User Clarification | Architecture updated: Frontend on Cloudflare Pages, backend on RPi behind Traefik with Authelia. Updated NFR-009 to NFR-013-SEC to reflect HTTPS via reverse proxy, authentication via Traefik middleware |