Initial commit: Home automation docs and CODESYS project

- Reorganized project: codesys/, docs/codesys|redesign|integration|reference/, scripts/
- CODESYS project and exports in codesys/
- Documentation index in docs/README.md
- Redesign and light naming configuration
- Water boiler control and safety design

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-07 21:52:46 +02:00
commit bf7bd56fe7
32 changed files with 73698 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
# fb_switch Analysis Summary
## Quick Assessment
**Current Approach**: ⚠️ **Needs Improvement**
**Main Issue**: Toggle-based control causes state desynchronization with Home Assistant.
## Key Problems
### 1. State Desynchronization
- **Problem**: HA sends ON/OFF commands, but CODESYS toggles
- **Result**: HA thinks light is ON, sends ON again → CODESYS toggles it OFF
- **Impact**: Lights don't match HA state
### 2. No Status Feedback
- **Problem**: Status comes from toggle button, not actual relay
- **Result**: Can't detect relay hardware failures
- **Impact**: HA may show wrong status
### 3. Mixed Control Sources
- **Problem**: HA and Zigbee both use same toggle mechanism
- **Result**: Conflicting behaviors
- **Impact**: Unpredictable control
## What You Need
**Control from Home Assistant** (ON/OFF switches)
**Control from Zigbee switches** (toggle behavior)
**Status feedback** (actual relay state)
## Recommended Solution
### Option 1: Full Redesign (Recommended)
- Separate ON/OFF commands for HA
- Edge detection for Zigbee (toggle)
- Read actual relay status from EtherCAT
- Clear priority system
**Pros**: Clean, maintainable, extensible
**Cons**: Requires more changes
### Option 2: Simplified Improvement
- Add ON/OFF commands alongside toggle
- Keep most existing structure
- Add status feedback
**Pros**: Less changes, faster to implement
**Cons**: Less clean, still some complexity
## Quick Fix (Minimal Changes)
If you need a quick fix while planning the redesign:
1. **In Node-RED**: Convert HA ON/OFF to edge pulses
```javascript
// Only send toggle on state change
if (currentState !== newState) {
sendToggle = true;
}
```
2. **Add status readback**: Read actual EtherCAT output state
```iec
lights.l_1_status := EtherCAT_Output_Channel_1;
```
3. **Update HA**: Use state topic for status feedback
## Decision Matrix
| Approach | Complexity | Time | Maintainability | Recommended For |
|----------|-----------|------|-----------------|-----------------|
| Full Redesign | High | 2-3 days | Excellent | Long-term solution |
| Simplified | Medium | 1 day | Good | Quick improvement |
| Quick Fix | Low | 2-4 hours | Fair | Temporary solution |
## My Recommendation
**Start with Quick Fix****Then implement Simplified****Plan Full Redesign**
This gives you:
1. Immediate working solution
2. Better solution in short term
3. Best solution for long term
---
**See**: [Full Redesign Recommendation](fb_switch-redesign-recommendation.md) for detailed implementation.

View File

@@ -0,0 +1,223 @@
# fb_switch Function Block Documentation
## Overview
The `fb_switch` function block is the core control logic for managing lighting in each room. It processes switch inputs from Node-RED and generates light control outputs.
## Function Block Structure
```iec
FUNCTION_BLOCK fb_switch
VAR_INPUT
switches: struct_switches; // Switch states received from Node-RED
END_VAR
VAR_OUTPUT
lights: struct_lights; // Light control outputs sent to Node-RED
END_VAR
VAR
all_off: fb_toogleButton; // Toggle button for "all off" command
all_on: fb_toogleButton; // Toggle button for "all on" command
sw_1: fb_toogleButton; // Toggle button for switch 1
sw_2: fb_toogleButton; // Toggle button for switch 2
sw_3: fb_toogleButton; // Toggle button for switch 3
sw_4: fb_toogleButton; // Toggle button for switch 4
sw_5: fb_toogleButton; // Toggle button for switch 5
sw_6: fb_toogleButton; // Toggle button for switch 6
END_VAR
```
## Data Structures
### struct_switches (Input)
```iec
TYPE struct_switches :
STRUCT
all_off: BOOL; // Command to turn all lights off
all_on: BOOL; // Command to turn all lights on
sw_1: BOOL; // Switch 1 state
sw_2: BOOL; // Switch 2 state
sw_3: BOOL; // Switch 3 state
sw_4: BOOL; // Switch 4 state
sw_5: BOOL; // Switch 5 state
sw_6: BOOL; // Switch 6 state
END_STRUCT
END_TYPE
```
### struct_lights (Output)
```iec
TYPE struct_lights:
STRUCT
l_1: BOOL; // Light 1 control output
l_2: BOOL; // Light 2 control output
l_3: BOOL; // Light 3 control output
l_4: BOOL; // Light 4 control output
l_5: BOOL; // Light 5 control output
l_6: BOOL; // Light 6 control output
END_STRUCT
END_TYPE
```
## Functionality
### Individual Switch Control
Each switch (`sw_1` through `sw_6`) is processed by a `fb_toogleButton` instance:
- **Input**: Switch state from `switches.sw_X` (received from Node-RED)
- **Output**: Light control to `lights.l_X` (sent to Node-RED)
- **Behavior**: Toggle functionality - each switch press toggles the corresponding light state
### Global Commands
1. **All Off (`switches.all_off`)**:
- When activated, turns off all lights (l_1 through l_6)
- Uses `fb_toogleButton` instance `all_off`
2. **All On (`switches.all_on`)**:
- When activated, turns on all lights (l_1 through l_6)
- Uses `fb_toogleButton` instance `all_on`
- Logic uses AND gates to combine with individual switch states
### Logic Flow
1. **Switch Input Processing**:
- Each `sw_X` input is fed to its corresponding `fb_toogleButton` instance
- The toggle button processes the input and generates an output
2. **Light Output Generation**:
- Individual switch outputs directly control their corresponding lights
- `all_off` command can override individual controls
- `all_on` command combines with individual switch states using AND logic
3. **Output Assignment**:
- `sw_1``lights.l_1`
- `sw_2``lights.l_2`
- `sw_3``lights.l_3`
- `sw_4``lights.l_4`
- `sw_5``lights.l_5`
- `sw_6``lights.l_6`
## fb_toogleButton Function Block
The `fb_toogleButton` is a toggle button implementation with debouncing and timing features.
### Structure
```iec
FUNCTION_BLOCK fb_toogleButton
VAR_INPUT
Input: BOOL; // Input signal (switch state)
END_VAR
VAR_OUTPUT
Output: BOOL; // Output signal (light control)
END_VAR
VAR
Switch: BOOL; // Internal switch state
Light: BOOL; // Internal light state
Flag1: BOOL; // Internal flag 1
Flag2: BOOL; // Internal flag 2
RT: R_TRIG; // Rising edge trigger
Pulse: TP; // Pulse timer
CTU_0: CTU; // Counter up 0
CTD_0: CTD; // Counter down 0
CTU_1: CTU; // Counter up 1
CTU_2: CTU; // Counter up 2
TOF_0: TOF; // Timer off delay 0
END_VAR
```
### Features
- **Rising Edge Detection**: Uses `R_TRIG` to detect switch press events
- **Pulse Generation**: Uses `TP` (pulse timer) for debouncing or pulse generation
- **Timing Control**: Uses `TOF` (timer off delay) for delayed turn-off
- **Counters**: Uses `CTU` and `CTD` counters for state management
- **Toggle Logic**: Implements toggle behavior - each press changes state
### Behavior
1. **Input Processing**:
- Detects rising edge of input signal
- Generates a pulse for processing
- Applies timing delays for debouncing
2. **State Management**:
- Maintains internal switch and light states
- Toggles output on each valid input pulse
- Uses flags for state tracking
3. **Output Generation**:
- Output reflects the toggled state
- May include timing delays (TOF) for smooth operation
## Usage in System
### Per-Room Instance
Each room has an instance of `fb_switch`:
- `masterBedroom: fb_switch`
- `masterBathroom: fb_switch`
- `bedroom_1: fb_switch`
- `bedroom_2: fb_switch`
- `bathroom: fb_switch`
- `guest_wc: fb_switch`
- `kitchen: fb_switch`
- `pantry: fb_switch`
- `livingRoom: fb_switch`
- `diningRoom: fb_switch`
- `veranda: fb_switch`
- `entrance: fb_switch`
- `front: fb_switch`
- `back: fb_switch`
- `side: fb_switch`
- `hallway: fb_switch`
### Network Variable Integration
- **Input**: Receives `struct_switches` from Node-RED via network variable `NVL_Receiver`
- **Output**: Sends `struct_lights` to Node-RED via network variable `NVL_Sender`
### Control Flow
```
Node-RED (Zigbee Switch)
MQTT Message
Node-RED Processing
Network Variable (struct_switches)
fb_switch (CODESYS)
fb_toogleButton Processing
Light Control Output (struct_lights)
Network Variable (NVL_Sender)
Node-RED
EtherCAT Relay Output
Physical Light
```
## Notes
- Each room can control up to 6 individual lights
- Global commands (`all_on`, `all_off`) provide room-level control
- Toggle button implementation includes debouncing to prevent rapid switching
- Timing functions ensure smooth operation and prevent electrical issues
- The system supports both individual light control and group control per room
---
**Documentation Date**: January 27, 2026
**Sources**:
- `Home_Automation.export` (CODESYS XML)
- `Home_Automation.xml` (PLCopen XML)
**Additional Details**: See [CODESYS XML Analysis](../codesys/codesys-xml-analysis.md) for timing characteristics and detailed logic flow extracted from the PLCopen XML format.

View File

@@ -0,0 +1,451 @@
# fb_switch Redesign Recommendation
## Current Implementation Issues
### Problem 1: Toggle-Based Control
**Issue**: The current `fb_toogleButton` implementation uses toggle logic, which causes state desynchronization with Home Assistant.
**Why this is a problem**:
- Home Assistant sends explicit ON/OFF commands
- CODESYS treats every input as a toggle trigger
- If HA thinks light is ON and sends ON again, CODESYS toggles it OFF
- State becomes out of sync between HA and actual relay state
**Example Scenario**:
1. HA sends `sw_1 = TRUE` (turn ON)
2. CODESYS toggles: OFF → ON ✓
3. HA sends `sw_1 = TRUE` again (thinking it's already ON)
4. CODESYS toggles: ON → OFF ✗ (wrong!)
### Problem 2: No Direct Set/Reset Commands
**Issue**: Current structure only has toggle triggers, no explicit ON/OFF commands.
**Current Structure**:
```iec
struct_switches:
sw_1: BOOL; // Treated as toggle trigger
all_on: BOOL; // Toggle trigger
all_off: BOOL; // Toggle trigger
```
**What's needed**:
- Separate ON and OFF commands
- Edge detection for Zigbee switches (toggle behavior)
- Direct set/reset for Home Assistant
### Problem 3: Status Feedback Limitations
**Issue**: Current `lights.l_X` outputs represent toggle button state, not actual relay status.
**Problems**:
- No direct feedback from physical relay outputs
- Status may not match actual relay state if relay fails
- No way to detect relay hardware failures
## Recommended Redesign
### New Data Structure
```iec
TYPE struct_switches :
STRUCT
// Home Assistant Commands (set/reset)
ha_l1_on: BOOL; // HA command: Light 1 ON
ha_l1_off: BOOL; // HA command: Light 1 OFF
ha_l2_on: BOOL;
ha_l2_off: BOOL;
ha_l3_on: BOOL;
ha_l3_off: BOOL;
ha_l4_on: BOOL;
ha_l4_off: BOOL;
ha_l5_on: BOOL;
ha_l5_off: BOOL;
ha_l6_on: BOOL;
ha_l6_off: BOOL;
// Zigbee Switch Inputs (edge detection for toggle)
zigbee_sw1: BOOL; // Zigbee switch 1 (edge detected)
zigbee_sw2: BOOL;
zigbee_sw3: BOOL;
zigbee_sw4: BOOL;
zigbee_sw5: BOOL;
zigbee_sw6: BOOL;
// Global Commands
ha_all_on: BOOL; // HA: All lights ON
ha_all_off: BOOL; // HA: All lights OFF
END_STRUCT
END_TYPE
TYPE struct_lights:
STRUCT
l_1: BOOL; // Light 1 control output
l_2: BOOL; // Light 2 control output
l_3: BOOL; // Light 3 control output
l_4: BOOL; // Light 4 control output
l_5: BOOL; // Light 5 control output
l_6: BOOL; // Light 6 control output
// Status feedback (read from actual relay outputs)
l_1_status: BOOL; // Actual relay 1 state
l_2_status: BOOL; // Actual relay 2 state
l_3_status: BOOL; // Actual relay 3 state
l_4_status: BOOL; // Actual relay 4 state
l_5_status: BOOL; // Actual relay 5 state
l_6_status: BOOL; // Actual relay 6 state
END_STRUCT
END_TYPE
```
### New Function Block: fb_lightControl
```iec
FUNCTION_BLOCK fb_lightControl
VAR_INPUT
// Home Assistant Commands
ha_on: BOOL; // HA command: Turn ON
ha_off: BOOL; // HA command: Turn OFF
// Zigbee Switch Input
zigbee_sw: BOOL; // Zigbee switch (edge detected)
// Status Feedback
relay_status: BOOL; // Actual relay state (read from EtherCAT)
END_VAR
VAR_OUTPUT
light_output: BOOL; // Control output to relay
light_status: BOOL; // Status to send back (actual relay state)
END_VAR
VAR
// Edge detection for Zigbee
zigbee_prev: BOOL;
zigbee_edge: BOOL;
// Command processing
ha_on_prev: BOOL;
ha_off_prev: BOOL;
ha_on_edge: BOOL;
ha_off_edge: BOOL;
// Internal state
light_state: BOOL;
// Edge triggers
r_trig_ha_on: R_TRIG;
r_trig_ha_off: R_TRIG;
r_trig_zigbee: R_TRIG;
END_VAR
```
### Implementation Logic
**Priority Order** (highest to lowest):
1. **HA OFF command** - Always turns light OFF
2. **HA ON command** - Always turns light ON
3. **Zigbee toggle** - Toggles current state
4. **Maintain current state** - If no commands
**Logic Flow**:
```iec
// Edge detection for commands
r_trig_ha_on(CLK := ha_on);
ha_on_edge := r_trig_ha_on.Q;
r_trig_ha_off(CLK := ha_off);
ha_off_edge := r_trig_ha_off.Q;
r_trig_zigbee(CLK := zigbee_sw);
zigbee_edge := r_trig_zigbee.Q;
// State machine
IF ha_off_edge THEN
light_state := FALSE;
ELSIF ha_on_edge THEN
light_state := TRUE;
ELSIF zigbee_edge THEN
light_state := NOT light_state;
END_IF
// Output assignment
light_output := light_state;
// Status feedback (read from actual relay)
light_status := relay_status;
```
### New fb_switch Implementation
```iec
FUNCTION_BLOCK fb_switch
VAR_INPUT
switches: struct_switches;
relay_status: struct_lights; // Read from EtherCAT outputs
END_VAR
VAR_OUTPUT
lights: struct_lights;
END_VAR
VAR
l1: fb_lightControl;
l2: fb_lightControl;
l3: fb_lightControl;
l4: fb_lightControl;
l5: fb_lightControl;
l6: fb_lightControl;
END_VAR
// Light 1 Control
l1(
ha_on := switches.ha_l1_on,
ha_off := switches.ha_l1_off,
zigbee_sw := switches.zigbee_sw1,
relay_status := relay_status.l_1_status
);
lights.l_1 := l1.light_output;
lights.l_1_status := l1.light_status;
// Light 2 Control
l2(
ha_on := switches.ha_l2_on,
ha_off := switches.ha_l2_off,
zigbee_sw := switches.zigbee_sw2,
relay_status := relay_status.l_2_status
);
lights.l_2 := l2.light_output;
lights.l_2_status := l2.light_status;
// ... (repeat for l3-l6)
// Global Commands
IF switches.ha_all_off THEN
lights.l_1 := FALSE;
lights.l_2 := FALSE;
lights.l_3 := FALSE;
lights.l_4 := FALSE;
lights.l_5 := FALSE;
lights.l_6 := FALSE;
ELSIF switches.ha_all_on THEN
lights.l_1 := TRUE;
lights.l_2 := TRUE;
lights.l_3 := TRUE;
lights.l_4 := TRUE;
lights.l_5 := TRUE;
lights.l_6 := TRUE;
END_IF;
```
## Node-RED Integration Changes
### Current Flow (Toggle-Based)
```
Zigbee Switch → MQTT → Node-RED → CODESYS (sw_1 = TRUE) → Toggle
Home Assistant → MQTT → Node-RED → CODESYS (sw_1 = TRUE) → Toggle (WRONG!)
```
### New Flow (Command-Based)
```
Zigbee Switch → MQTT → Node-RED → CODESYS (zigbee_sw1 = edge) → Toggle
Home Assistant → MQTT → Node-RED → CODESYS (ha_l1_on = TRUE) → Set ON
Home Assistant → MQTT → Node-RED → CODESYS (ha_l1_off = TRUE) → Set OFF
```
### Node-RED Flow Example
**For Zigbee Switches**:
```javascript
// Detect button press (edge detection)
if (msg.payload.action === "single") {
// Send edge trigger to CODESYS
msg.payload = {
zigbee_sw1: true // Edge detected
};
return msg;
}
```
**For Home Assistant**:
```javascript
// Direct ON/OFF commands
if (msg.payload === "ON") {
msg.payload = {
ha_l1_on: true,
ha_l1_off: false
};
} else if (msg.payload === "OFF") {
msg.payload = {
ha_l1_on: false,
ha_l1_off: true
};
}
return msg;
```
**Status Feedback to Home Assistant**:
```javascript
// Read status from CODESYS
const status = msg.payload.l_1_status;
// Publish to HA
msg.topic = "homeassistant/light/room1_light1/state";
msg.payload = status ? "ON" : "OFF";
return msg;
```
## Home Assistant Configuration
### MQTT Light Entity
```yaml
light:
- platform: mqtt
name: "Room 1 Light 1"
state_topic: "homeassistant/light/room1_light1/state"
command_topic: "homeassistant/light/room1_light1/set"
state_value_template: "{{ value_json.state }}"
command_on_template: '{"state":"ON"}'
command_off_template: '{"state":"OFF"}'
qos: 1
retain: true
```
### Node-RED Flow for HA Integration
```
[HA Command] → [Parse] → [Convert to CODESYS format] → [Network Variable]
[CODESYS Status] → [Network Variable] → [Convert to HA format] → [HA State]
```
## Benefits of Redesign
### 1. State Synchronization
- ✅ HA always knows actual relay state
- ✅ No state desynchronization
- ✅ Reliable ON/OFF commands
### 2. Multiple Control Sources
- ✅ HA uses set/reset commands
- ✅ Zigbee switches use toggle (edge detection)
- ✅ Both work simultaneously without conflicts
### 3. Status Feedback
- ✅ Actual relay state read from EtherCAT
- ✅ Hardware failure detection possible
- ✅ Accurate status in Home Assistant
### 4. Better Debugging
- ✅ Clear separation of commands
- ✅ Can trace which source triggered action
- ✅ Easier troubleshooting
### 5. Extensibility
- ✅ Easy to add more control sources
- ✅ Can add priority levels
- ✅ Can add scheduling/automation
## Migration Path
### Step 1: Update Data Structures
1. Modify `struct_switches` to include HA commands and Zigbee inputs
2. Modify `struct_lights` to include status feedback
3. Keep old structure temporarily for backward compatibility
### Step 2: Create New Function Blocks
1. Implement `fb_lightControl` with new logic
2. Update `fb_switch` to use new function blocks
3. Test in simulation first
### Step 3: Update Node-RED Flows
1. Modify flows to send HA commands (ON/OFF)
2. Keep Zigbee flows with edge detection
3. Add status feedback flows
### Step 4: Update Home Assistant
1. Configure MQTT light entities
2. Test control from HA
3. Verify status updates
### Step 5: Testing
1. Test HA control (ON/OFF)
2. Test Zigbee switch control (toggle)
3. Test status feedback
4. Test both simultaneously
## Alternative: Simpler Approach (If Full Redesign Too Complex)
If the full redesign is too complex, here's a simpler improvement:
### Simplified Improvement
**Keep toggle logic but add state tracking**:
```iec
FUNCTION_BLOCK fb_lightControl_Simple
VAR_INPUT
toggle: BOOL; // Toggle command (edge detected)
set_on: BOOL; // Set ON command (edge detected)
set_off: BOOL; // Set OFF command (edge detected)
relay_status: BOOL; // Actual relay state
END_VAR
VAR_OUTPUT
output: BOOL;
status: BOOL;
END_VAR
VAR
state: BOOL;
r_trig_toggle: R_TRIG;
r_trig_on: R_TRIG;
r_trig_off: R_TRIG;
END_VAR
// Edge detection
r_trig_toggle(CLK := toggle);
r_trig_on(CLK := set_on);
r_trig_off(CLK := set_off);
// State machine
IF r_trig_off.Q THEN
state := FALSE;
ELSIF r_trig_on.Q THEN
state := TRUE;
ELSIF r_trig_toggle.Q THEN
state := NOT state;
END_IF;
output := state;
status := relay_status; // Read from actual relay
```
**Data Structure**:
```iec
struct_switches:
sw1_toggle: BOOL; // Zigbee toggle
sw1_on: BOOL; // HA ON command
sw1_off: BOOL; // HA OFF command
// ... repeat for sw2-sw6
```
This simpler approach:
- ✅ Keeps existing structure mostly intact
- ✅ Adds explicit ON/OFF commands for HA
- ✅ Maintains toggle for Zigbee
- ✅ Adds status feedback
- ⚠️ Still requires data structure changes
- ⚠️ Less clean than full redesign
## Recommendation
**I recommend the full redesign** because:
1. Better long-term maintainability
2. Clear separation of concerns
3. Easier to extend and debug
4. Proper state management
5. Industry-standard approach
However, if time is limited, the **simplified approach** is a good compromise that addresses the main issues.
---
**Next Steps**:
1. Review this recommendation
2. Decide on full redesign vs. simplified approach
3. Plan migration strategy
4. Update Node-RED flows accordingly
5. Test thoroughly before deploying

View File

@@ -0,0 +1,873 @@
# Light Naming Configuration - Hybrid Structure
## Overview
This document defines the naming convention and structure for all lights in the home automation system using the Hybrid Structure (Option 4). This will serve as the basis for the redesign.
**Structure**: Room-organized in CODESYS, flattened for Home Assistant
**Naming Convention**: `{room}_{function}` (e.g., `kitchen_main`, `master_bedroom_bedside_left`)
---
## Room-by-Room Light Configuration
### 1. Master Bedroom
**Room ID**: `master_bedroom`
**Display Name**: "Master Bedroom"
**Lights**:
- `main` - Main ceiling light
- `bedside_left` - Left bedside lamp
- `bedside_right` - Right bedside lamp
- `closet` - Closet light
- `reading` - Reading light (optional)
- `ambient` - Ambient/atmospheric lighting (optional)
**CODESYS Structure**:
```iec
rooms.master_bedroom:
main: struct_light_control;
bedside_left: struct_light_control;
bedside_right: struct_light_control;
closet: struct_light_control;
reading: struct_light_control; // Optional
ambient: struct_light_control; // Optional
```
**Home Assistant Entities**:
- `light.master_bedroom_main`
- `light.master_bedroom_bedside_left`
- `light.master_bedroom_bedside_right`
- `light.master_bedroom_closet`
- `light.master_bedroom_reading` (if used)
- `light.master_bedroom_ambient` (if used)
---
### 2. Master Bathroom
**Room ID**: `master_bathroom`
**Display Name**: "Master Bathroom"
**Lights**:
- `main` - Main ceiling light
- `mirror` - Mirror/vanity light
- `shower` - Shower light
- `night_light` - Night light (low brightness)
**CODESYS Structure**:
```iec
rooms.master_bathroom:
main: struct_light_control;
mirror: struct_light_control;
shower: struct_light_control;
night_light: struct_light_control;
```
**Home Assistant Entities**:
- `light.master_bathroom_main`
- `light.master_bathroom_mirror`
- `light.master_bathroom_shower`
- `light.master_bathroom_night_light`
---
### 3. Bedroom 1
**Room ID**: `bedroom_1`
**Display Name**: "Bedroom 1"
**Lights**:
- `main` - Main ceiling light
- `bedside` - Bedside lamp
- `desk` - Desk lamp (if applicable)
- `closet` - Closet light (if applicable)
**CODESYS Structure**:
```iec
rooms.bedroom_1:
main: struct_light_control;
bedside: struct_light_control;
desk: struct_light_control; // Optional
closet: struct_light_control; // Optional
```
**Home Assistant Entities**:
- `light.bedroom_1_main`
- `light.bedroom_1_bedside`
- `light.bedroom_1_desk` (if used)
- `light.bedroom_1_closet` (if used)
---
### 4. Bedroom 2
**Room ID**: `bedroom_2`
**Display Name**: "Bedroom 2"
**Lights**:
- `main` - Main ceiling light
- `bedside` - Bedside lamp
- `desk` - Desk lamp (if applicable)
- `closet` - Closet light (if applicable)
**CODESYS Structure**:
```iec
rooms.bedroom_2:
main: struct_light_control;
bedside: struct_light_control;
desk: struct_light_control; // Optional
closet: struct_light_control; // Optional
```
**Home Assistant Entities**:
- `light.bedroom_2_main`
- `light.bedroom_2_bedside`
- `light.bedroom_2_desk` (if used)
- `light.bedroom_2_closet` (if used)
---
### 5. Bathroom
**Room ID**: `bathroom`
**Display Name**: "Bathroom"
**Lights**:
- `main` - Main ceiling light
- `mirror` - Mirror/vanity light
- `night_light` - Night light
**CODESYS Structure**:
```iec
rooms.bathroom:
main: struct_light_control;
mirror: struct_light_control;
night_light: struct_light_control;
```
**Home Assistant Entities**:
- `light.bathroom_main`
- `light.bathroom_mirror`
- `light.bathroom_night_light`
---
### 6. Kitchen
**Room ID**: `kitchen`
**Display Name**: "Kitchen"
**Lights**:
- `main` - Main ceiling light
- `under_cabinet` - Under cabinet task lighting
- `island` - Island pendant light
- `pantry` - Pantry light (if separate from pantry room)
- `sink` - Sink area light
**CODESYS Structure**:
```iec
rooms.kitchen:
main: struct_light_control;
under_cabinet: struct_light_control;
island: struct_light_control;
pantry: struct_light_control; // If in kitchen
sink: struct_light_control;
```
**Home Assistant Entities**:
- `light.kitchen_main`
- `light.kitchen_under_cabinet`
- `light.kitchen_island`
- `light.kitchen_pantry` (if used)
- `light.kitchen_sink`
---
### 7. Living Room
**Room ID**: `living_room`
**Display Name**: "Living Room"
**Lights**:
- `main` - Main ceiling light
- `reading` - Reading lamp
- `tv` - TV area lighting
- `accent` - Accent lighting
- `fireplace` - Fireplace area lighting (if applicable)
**CODESYS Structure**:
```iec
rooms.living_room:
main: struct_light_control;
reading: struct_light_control;
tv: struct_light_control;
accent: struct_light_control;
fireplace: struct_light_control; // Optional
```
**Home Assistant Entities**:
- `light.living_room_main`
- `light.living_room_reading`
- `light.living_room_tv`
- `light.living_room_accent`
- `light.living_room_fireplace` (if used)
---
### 8. Dining Room
**Room ID**: `dining_room`
**Display Name**: "Dining Room"
**Lights**:
- `main` - Main chandelier/ceiling light
- `ambient` - Ambient lighting
- `buffet` - Buffet/sideboard lighting (if applicable)
**CODESYS Structure**:
```iec
rooms.dining_room:
main: struct_light_control;
ambient: struct_light_control;
buffet: struct_light_control; // Optional
```
**Home Assistant Entities**:
- `light.dining_room_main`
- `light.dining_room_ambient`
- `light.dining_room_buffet` (if used)
---
### 9. Hallway
**Room ID**: `hallway`
**Display Name**: "Hallway"
**Lights**:
- `main` - Main hallway light
- `secondary` - Secondary hallway light (if long hallway)
- `night_light` - Night light
**CODESYS Structure**:
```iec
rooms.hallway:
main: struct_light_control;
secondary: struct_light_control; // Optional
night_light: struct_light_control;
```
**Home Assistant Entities**:
- `light.hallway_main`
- `light.hallway_secondary` (if used)
- `light.hallway_night_light`
---
### 10. Pantry
**Room ID**: `pantry`
**Display Name**: "Pantry"
**Lights**:
- `main` - Main pantry light
**CODESYS Structure**:
```iec
rooms.pantry:
main: struct_light_control;
```
**Home Assistant Entities**:
- `light.pantry_main`
---
### 11. Entrance
**Room ID**: `entrance`
**Display Name**: "Entrance"
**Lights**:
- `main` - Main entrance light
- `security` - Security/porch light
**CODESYS Structure**:
```iec
rooms.entrance:
main: struct_light_control;
security: struct_light_control;
```
**Home Assistant Entities**:
- `light.entrance_main`
- `light.entrance_security`
---
### 12. Guest WC
**Room ID**: `guest_wc`
**Display Name**: "Guest WC"
**Lights**:
- `main` - Main light
- `night_light` - Night light
**CODESYS Structure**:
```iec
rooms.guest_wc:
main: struct_light_control;
night_light: struct_light_control;
```
**Home Assistant Entities**:
- `light.guest_wc_main`
- `light.guest_wc_night_light`
---
### 13. Outdoor Veranda
**Room ID**: `outdoor_veranda`
**Display Name**: "Outdoor Veranda"
**Lights**:
- `main` - Main veranda light
- `ambient` - Ambient/atmospheric lighting
- `security` - Security lighting
**CODESYS Structure**:
```iec
rooms.outdoor_veranda:
main: struct_light_control;
ambient: struct_light_control;
security: struct_light_control;
```
**Home Assistant Entities**:
- `light.outdoor_veranda_main`
- `light.outdoor_veranda_ambient`
- `light.outdoor_veranda_security`
---
### 14. Outdoor Front
**Room ID**: `outdoor_front`
**Display Name**: "Outdoor Front"
**Lights**:
- `porch` - Front porch light
- `security` - Security light
- `pathway` - Pathway lighting
**CODESYS Structure**:
```iec
rooms.outdoor_front:
porch: struct_light_control;
security: struct_light_control;
pathway: struct_light_control;
```
**Home Assistant Entities**:
- `light.outdoor_front_porch`
- `light.outdoor_front_security`
- `light.outdoor_front_pathway`
---
### 15. Outdoor Side
**Room ID**: `outdoor_side`
**Display Name**: "Outdoor Side"
**Lights**:
- `security` - Side security light
- `pathway` - Side pathway lighting
**CODESYS Structure**:
```iec
rooms.outdoor_side:
security: struct_light_control;
pathway: struct_light_control;
```
**Home Assistant Entities**:
- `light.outdoor_side_security`
- `light.outdoor_side_pathway`
---
### 16. Outdoor Back
**Room ID**: `outdoor_back`
**Display Name**: "Outdoor Back"
**Lights**:
- `patio` - Patio/backyard light
- `security` - Back security light
- `garden` - Garden lighting (if applicable)
**CODESYS Structure**:
```iec
rooms.outdoor_back:
patio: struct_light_control;
security: struct_light_control;
garden: struct_light_control; // Optional
```
**Home Assistant Entities**:
- `light.outdoor_back_patio`
- `light.outdoor_back_security`
- `light.outdoor_back_garden` (if used)
---
## Complete CODESYS Structure Definition
```iec
TYPE struct_light_control :
STRUCT
// Control Commands
ha_on: BOOL; // Home Assistant: Turn ON
ha_off: BOOL; // Home Assistant: Turn OFF
zigbee_toggle: BOOL; // Zigbee Switch: Toggle (edge detected)
// Status
state: BOOL; // Current light state
relay_status: BOOL; // Actual relay status (read from EtherCAT)
END_STRUCT
END_TYPE
TYPE struct_room_lights :
STRUCT
main: struct_light_control;
secondary: struct_light_control;
task: struct_light_control;
ambient: struct_light_control;
accent: struct_light_control;
security: struct_light_control;
// Room-specific lights defined per room
END_STRUCT
END_TYPE
VAR_GLOBAL
rooms: STRUCT
master_bedroom: STRUCT
main: struct_light_control;
bedside_left: struct_light_control;
bedside_right: struct_light_control;
closet: struct_light_control;
reading: struct_light_control;
ambient: struct_light_control;
END_STRUCT;
master_bathroom: STRUCT
main: struct_light_control;
mirror: struct_light_control;
shower: struct_light_control;
night_light: struct_light_control;
END_STRUCT;
bedroom_1: STRUCT
main: struct_light_control;
bedside: struct_light_control;
desk: struct_light_control;
closet: struct_light_control;
END_STRUCT;
bedroom_2: STRUCT
main: struct_light_control;
bedside: struct_light_control;
desk: struct_light_control;
closet: struct_light_control;
END_STRUCT;
bathroom: STRUCT
main: struct_light_control;
mirror: struct_light_control;
night_light: struct_light_control;
END_STRUCT;
kitchen: STRUCT
main: struct_light_control;
under_cabinet: struct_light_control;
island: struct_light_control;
pantry: struct_light_control;
sink: struct_light_control;
END_STRUCT;
living_room: STRUCT
main: struct_light_control;
reading: struct_light_control;
tv: struct_light_control;
accent: struct_light_control;
fireplace: struct_light_control;
END_STRUCT;
dining_room: STRUCT
main: struct_light_control;
ambient: struct_light_control;
buffet: struct_light_control;
END_STRUCT;
hallway: STRUCT
main: struct_light_control;
secondary: struct_light_control;
night_light: struct_light_control;
END_STRUCT;
pantry: STRUCT
main: struct_light_control;
END_STRUCT;
entrance: STRUCT
main: struct_light_control;
security: struct_light_control;
END_STRUCT;
guest_wc: STRUCT
main: struct_light_control;
night_light: struct_light_control;
END_STRUCT;
outdoor_veranda: STRUCT
main: struct_light_control;
ambient: struct_light_control;
security: struct_light_control;
END_STRUCT;
outdoor_front: STRUCT
porch: struct_light_control;
security: struct_light_control;
pathway: struct_light_control;
END_STRUCT;
outdoor_side: STRUCT
security: struct_light_control;
pathway: struct_light_control;
END_STRUCT;
outdoor_back: STRUCT
patio: struct_light_control;
security: struct_light_control;
garden: struct_light_control;
END_STRUCT;
END_STRUCT;
END_VAR
```
---
## Light Function Types Reference
Use these standard function names for consistency:
| Function | Description | Typical Use |
|----------|-------------|-------------|
| `main` | Primary/ceiling light | Main illumination in room |
| `secondary` | Secondary light | Additional main light |
| `bedside_left` | Left bedside lamp | Bedroom bedside |
| `bedside_right` | Right bedside lamp | Bedroom bedside |
| `bedside` | Single bedside lamp | Single bed rooms |
| `closet` | Closet light | Storage areas |
| `desk` | Desk lamp | Study/work areas |
| `reading` | Reading light | Reading areas |
| `mirror` | Mirror/vanity light | Bathrooms |
| `shower` | Shower light | Bathroom shower |
| `night_light` | Night light | Low brightness |
| `under_cabinet` | Under cabinet | Kitchen task lighting |
| `island` | Island pendant | Kitchen island |
| `sink` | Sink area light | Kitchen/bathroom |
| `tv` | TV area lighting | Living room |
| `accent` | Accent lighting | Decorative |
| `ambient` | Ambient lighting | Atmospheric |
| `fireplace` | Fireplace area | Living room |
| `buffet` | Buffet/sideboard | Dining room |
| `porch` | Porch light | Entrance |
| `patio` | Patio light | Backyard |
| `security` | Security light | Outdoor security |
| `pathway` | Pathway lighting | Outdoor paths |
| `garden` | Garden lighting | Outdoor garden |
---
## Water Boiler Control
### Water Boiler Structure
```iec
TYPE struct_water_boiler :
STRUCT
// Control Commands
ha_on: BOOL; // Home Assistant: Turn ON
ha_off: BOOL; // Home Assistant: Turn OFF
schedule_on: BOOL; // Scheduled ON (from automation)
schedule_off: BOOL; // Scheduled OFF (from automation)
// Status
state: BOOL; // Current boiler state (ON/OFF)
relay_status: BOOL; // Actual relay status
temperature: REAL; // Water temperature (if sensor available)
// Safety
safety_override: BOOL; // Safety system override (read-only)
error_state: BOOL; // Error state flag
last_error: STRING; // Last error message
END_STRUCT
END_TYPE
VAR_GLOBAL
water_boiler: struct_water_boiler;
END_VAR
```
### Water Boiler Function Block
```iec
FUNCTION_BLOCK fb_waterBoiler
VAR_INPUT
// Control
ha_on: BOOL;
ha_off: BOOL;
schedule_on: BOOL;
schedule_off: BOOL;
// Sensors
temperature: REAL; // Water temperature sensor
pressure: REAL; // Water pressure (if available)
// Safety Inputs
emergency_stop: BOOL; // Emergency stop button
flow_sensor: BOOL; // Water flow sensor
overtemp_sensor: BOOL; // Over-temperature sensor
pressure_sensor: BOOL; // Pressure sensor (if available)
// Relay Output
relay_output: BOOL; // Read actual relay state
END_VAR
VAR_OUTPUT
relay_control: BOOL; // Control output to relay
state: BOOL; // Current state
relay_status: BOOL; // Actual relay status
safety_override: BOOL; // Safety override active
error_state: BOOL; // Error detected
error_code: INT; // Error code
error_message: STRING; // Error description
END_VAR
VAR
// Internal State
internal_state: BOOL;
last_state: BOOL;
// Safety Timers
max_on_time: TIME := T#8H; // Maximum ON time (8 hours)
min_off_time: TIME := T#30M; // Minimum OFF time (30 minutes)
on_timer: TON;
off_timer: TON;
// Temperature Limits
max_temp: REAL := 80.0; // Maximum temperature (°C)
min_temp: REAL := 10.0; // Minimum temperature (°C)
// Safety Flags
temp_ok: BOOL;
pressure_ok: BOOL;
flow_ok: BOOL;
time_ok: BOOL;
// Edge Detection
r_trig_ha_on: R_TRIG;
r_trig_ha_off: R_TRIG;
r_trig_schedule_on: R_TRIG;
r_trig_schedule_off: R_TRIG;
r_trig_emergency: R_TRIG;
END_VAR
```
### Safety Logic Implementation
```iec
// Edge detection
r_trig_ha_on(CLK := ha_on);
r_trig_ha_off(CLK := ha_off);
r_trig_schedule_on(CLK := schedule_on);
r_trig_schedule_off(CLK := schedule_off);
r_trig_emergency(CLK := emergency_stop);
// Safety Checks
temp_ok := (temperature >= min_temp) AND (temperature <= max_temp);
pressure_ok := pressure_sensor; // Assuming normally closed safety switch
flow_ok := flow_sensor; // Water flow detected
time_ok := NOT on_timer.Q; // Not exceeded max ON time
// Safety Override (highest priority)
IF r_trig_emergency.Q OR NOT temp_ok OR NOT pressure_ok THEN
safety_override := TRUE;
internal_state := FALSE;
error_state := TRUE;
error_code := 1; // Safety override
error_message := 'Safety override active';
ELSIF NOT flow_ok AND internal_state THEN
// No water flow but boiler is on - turn off after delay
off_timer(IN := TRUE, PT := T#5M); // 5 minute delay
IF off_timer.Q THEN
internal_state := FALSE;
error_state := TRUE;
error_code := 2; // No flow
error_message := 'No water flow detected';
END_IF;
ELSIF NOT time_ok THEN
// Maximum ON time exceeded
internal_state := FALSE;
error_state := TRUE;
error_code := 3; // Time exceeded
error_message := 'Maximum ON time exceeded';
ELSE
safety_override := FALSE;
error_state := FALSE;
error_code := 0;
error_message := '';
END_IF;
// Control Logic (only if safety OK)
IF NOT safety_override THEN
// Priority: Emergency OFF > Manual OFF > Scheduled OFF > Manual ON > Scheduled ON
IF r_trig_ha_off.Q OR r_trig_schedule_off.Q THEN
internal_state := FALSE;
ELSIF r_trig_ha_on.Q OR r_trig_schedule_on.Q THEN
IF temp_ok AND flow_ok AND time_ok THEN
internal_state := TRUE;
on_timer(IN := internal_state, PT := max_on_time);
END_IF;
END_IF;
END_IF;
// Update timers
on_timer(IN := internal_state AND NOT safety_override, PT := max_on_time);
off_timer(IN := NOT internal_state, PT := min_off_time);
// Output Assignment
relay_control := internal_state AND NOT safety_override;
state := internal_state;
relay_status := relay_output; // Read from actual relay
```
### Safety Measures
#### 1. Temperature Protection
- **Max Temperature**: 80°C (configurable)
- **Min Temperature**: 10°C (freeze protection)
- **Action**: Auto-shutoff if temperature exceeds limits
#### 2. Time-Based Protection
- **Max ON Time**: 8 hours (prevents continuous operation)
- **Min OFF Time**: 30 minutes (prevents rapid cycling)
- **Action**: Force OFF after max time, prevent ON during min OFF time
#### 3. Flow Detection
- **Flow Sensor**: Monitors water flow
- **Action**: Shut off if no flow detected for 5 minutes (dry-run protection)
#### 4. Emergency Stop
- **Emergency Button**: Physical emergency stop
- **Action**: Immediate shutdown, requires manual reset
#### 5. Pressure Protection
- **Pressure Sensor**: Monitors system pressure
- **Action**: Shut off if pressure abnormal
#### 6. State Monitoring
- **Relay Status**: Read actual relay state
- **Action**: Detect relay failures, report status
#### 7. Error Reporting
- **Error Codes**:
- 0: No error
- 1: Safety override
- 2: No flow
- 3: Time exceeded
- 4: Temperature fault
- 5: Pressure fault
- **Error Messages**: Human-readable descriptions
### Water Boiler Network Variable
```iec
// Sent to Node-RED (Status)
VAR_GLOBAL
boiler_status: struct_water_boiler;
END_VAR
// Received from Node-RED (Commands)
VAR_GLOBAL
boiler_commands: STRUCT
ha_on: BOOL;
ha_off: BOOL;
schedule_on: BOOL;
schedule_off: BOOL;
END_STRUCT;
END_VAR
```
### Home Assistant Integration
**Entity Type**: `switch` or `water_heater`
```yaml
switch:
- platform: mqtt
name: "Water Boiler"
unique_id: "water_boiler"
state_topic: "homeassistant/water_boiler/state"
command_topic: "homeassistant/water_boiler/set"
state_value_template: "{{ value_json.state }}"
command_on_template: '{"ha_on":true}'
command_off_template: '{"ha_off":true}'
qos: 1
retain: true
sensor:
- platform: mqtt
name: "Water Boiler Temperature"
state_topic: "homeassistant/water_boiler/state"
value_template: "{{ value_json.temperature }}"
unit_of_measurement: "°C"
- platform: mqtt
name: "Water Boiler Error"
state_topic: "homeassistant/water_boiler/state"
value_template: "{{ value_json.error_message }}"
```
---
## Summary
### Light Configuration
- **Total Rooms**: 16 (15 indoor + outdoor areas)
- **Total Lights**: ~60-70 lights (varies by room)
- **Structure**: Hybrid (room-organized in CODESYS, flat in HA)
- **Naming**: `{room}_{function}` format
### Water Boiler
- **Control**: ON/OFF with scheduling
- **Safety**: 7 safety measures implemented
- **Monitoring**: Temperature, flow, pressure, time
- **Error Reporting**: Comprehensive error codes and messages
### Next Steps
1. Review and modify light names per room based on actual installation
2. Map lights to relay outputs
3. Implement new structure in CODESYS
4. Update Node-RED flows
5. Configure Home Assistant entities
6. Test all safety measures for water boiler
---
**Document Status**: Template - Modify with actual light configuration
**Last Updated**: January 27, 2026

View File

@@ -0,0 +1,239 @@
# Redesign Implementation Roadmap
## Overview
This document provides a step-by-step roadmap for implementing the redesigned structure based on the light naming configuration.
## Phase 1: Configuration & Planning
### Step 1.1: Review Light Naming Configuration
- [ ] Review `light-naming-configuration.md`
- [ ] Modify light names per room based on actual installation
- [ ] Remove unused lights from structure
- [ ] Add any missing lights
- [ ] Document relay-to-light mapping
### Step 1.2: Map Relays to Lights
- [ ] Create mapping table: Relay # → Room → Light Name
- [ ] Document in `relay-mapping.md`
- [ ] Verify all relays are accounted for
**Example Mapping**:
```
Relay 1 → kitchen → main
Relay 2 → kitchen → under_cabinet
Relay 3 → kitchen → island
Relay 4 → master_bedroom → main
Relay 5 → master_bedroom → bedside_left
...
```
### Step 1.3: Water Boiler Configuration
- [ ] Review water boiler safety requirements
- [ ] Configure temperature limits
- [ ] Configure time limits (max ON, min OFF)
- [ ] Identify sensor inputs (temperature, flow, pressure)
- [ ] Map boiler relay output
---
## Phase 2: CODESYS Structure Implementation
### Step 2.1: Create New Data Structures
- [ ] Create `struct_light_control` type
- [ ] Create `struct_water_boiler` type
- [ ] Create room-specific structures
- [ ] Create global `rooms` structure
### Step 2.2: Create Function Blocks
- [ ] Create `fb_lightControl` function block
- [ ] Create `fb_waterBoiler` function block
- [ ] Test function blocks in simulation
### Step 2.3: Update Network Variables
- [ ] Update `NVL_Sender` with new structure
- [ ] Update `NVL_Receiver` with new structure
- [ ] Add water boiler network variables
- [ ] Configure network variable properties
### Step 2.4: Implement Control Logic
- [ ] Replace `fb_switch` with new structure
- [ ] Implement light control per room
- [ ] Implement water boiler control
- [ ] Add relay output mapping
- [ ] Add relay status readback
### Step 2.5: Testing
- [ ] Test in simulation
- [ ] Test individual light control
- [ ] Test water boiler control
- [ ] Test safety measures
- [ ] Verify network variable transmission
---
## Phase 3: Node-RED Integration
### Step 3.1: Update Network Variable Nodes
- [ ] Update CODESYS network variable nodes
- [ ] Configure new variable structure
- [ ] Test bidirectional communication
### Step 3.2: Create Transformation Functions
- [ ] Create function to flatten room structure for HA
- [ ] Create function to convert HA commands to CODESYS format
- [ ] Create function for Zigbee edge detection
- [ ] Test transformations
### Step 3.3: Update MQTT Flows
- [ ] Update MQTT topics to new naming convention
- [ ] Configure Home Assistant auto-discovery
- [ ] Update Zigbee switch flows
- [ ] Add water boiler MQTT flows
### Step 3.4: Testing
- [ ] Test HA → CODESYS commands
- [ ] Test Zigbee → CODESYS commands
- [ ] Test CODESYS → HA status updates
- [ ] Test water boiler control
- [ ] Verify MQTT message flow
---
## Phase 4: Home Assistant Configuration
### Step 4.1: Entity Configuration
- [ ] Create light entities for all lights
- [ ] Configure entity names and icons
- [ ] Set up areas/rooms in HA
- [ ] Create water boiler entity
### Step 4.2: Dashboard Setup
- [ ] Create lighting dashboard
- [ ] Group lights by room
- [ ] Add water boiler control
- [ ] Add status indicators
### Step 4.3: Automations
- [ ] Update existing automations
- [ ] Create new automations if needed
- [ ] Test automations
---
## Phase 5: Migration & Deployment
### Step 5.1: Backup Current System
- [ ] Backup CODESYS project
- [ ] Export Node-RED flows
- [ ] Backup Home Assistant configuration
- [ ] Document current state
### Step 5.2: Parallel Testing
- [ ] Deploy new structure in test mode
- [ ] Run parallel with old system
- [ ] Compare behavior
- [ ] Fix any issues
### Step 5.3: Gradual Migration
- [ ] Migrate one room at a time
- [ ] Test each room thoroughly
- [ ] Migrate water boiler
- [ ] Complete migration
### Step 5.4: Validation
- [ ] Test all lights from HA
- [ ] Test all lights from Zigbee switches
- [ ] Verify status feedback
- [ ] Test water boiler control
- [ ] Test all safety measures
- [ ] Verify no regressions
---
## Implementation Checklist
### CODESYS
- [ ] New data structures defined
- [ ] Function blocks created and tested
- [ ] Network variables updated
- [ ] Control logic implemented
- [ ] Relay mapping configured
- [ ] Status readback implemented
- [ ] Water boiler safety measures implemented
- [ ] Code tested in simulation
### Node-RED
- [ ] Network variable nodes updated
- [ ] Transformation functions created
- [ ] MQTT flows updated
- [ ] HA auto-discovery configured
- [ ] Zigbee integration updated
- [ ] Water boiler flows added
- [ ] All flows tested
### Home Assistant
- [ ] All light entities created
- [ ] Water boiler entity created
- [ ] Areas/rooms configured
- [ ] Dashboard updated
- [ ] Automations updated
- [ ] All entities tested
### Documentation
- [ ] Light naming configuration finalized
- [ ] Relay mapping documented
- [ ] Network variable structure documented
- [ ] MQTT topics documented
- [ ] Safety measures documented
- [ ] Troubleshooting guide updated
---
## Key Files Reference
1. **Light Configuration**: `light-naming-configuration.md`
2. **Structure Analysis**: `structure-redesign-analysis.md`
3. **Visual Comparison**: `structure-comparison-visual.md`
4. **Function Block Redesign**: `fb_switch-redesign-recommendation.md`
5. **This Roadmap**: `redesign-implementation-roadmap.md`
---
## Estimated Timeline
- **Phase 1** (Planning): 1-2 days
- **Phase 2** (CODESYS): 2-3 days
- **Phase 3** (Node-RED): 1-2 days
- **Phase 4** (Home Assistant): 1 day
- **Phase 5** (Migration): 2-3 days
**Total**: ~7-11 days (depending on complexity and testing)
---
## Risk Mitigation
### Risks
1. **Network Variable Changes**: May break existing Node-RED flows
- **Mitigation**: Test thoroughly, have rollback plan
2. **State Synchronization**: During migration, states may be inconsistent
- **Mitigation**: Migrate during low-usage period, verify all states
3. **Water Boiler Safety**: Critical system, must work correctly
- **Mitigation**: Extensive testing, manual override available
4. **Home Assistant Entities**: May need to recreate entities
- **Mitigation**: Use unique_id to preserve entity history
### Rollback Plan
- Keep old CODESYS project as backup
- Keep old Node-RED flows as backup
- Document rollback procedure
- Test rollback procedure
---
**Status**: Planning Phase
**Next Step**: Review and modify `light-naming-configuration.md` with actual light configuration

View File

@@ -0,0 +1,101 @@
# Redesign Summary - Quick Reference
## What We're Changing
### Current Structure → New Structure
**Before**:
- Room-based with generic `l_1`, `l_2` names
- Fixed 6 lights per room
- Toggle-based control
- No status feedback from relays
**After**:
- Room-based in CODESYS, flat in Home Assistant
- Descriptive names: `kitchen_main`, `master_bedroom_bedside_left`
- Command-based control (ON/OFF for HA, toggle for Zigbee)
- Actual relay status feedback
- Water boiler with comprehensive safety
---
## Key Documents
1. **`light-naming-configuration.md`** ⭐ **START HERE**
- Complete light naming for all 16 rooms
- Water boiler control structure
- Safety measures
- **Action**: Review and modify with your actual lights
2. **`redesign-implementation-roadmap.md`**
- Step-by-step implementation guide
- Phase-by-phase checklist
- Timeline estimates
3. **`structure-redesign-analysis.md`**
- Detailed analysis of structure options
- Why Option 4 (Hybrid) was chosen
4. **`fb_switch-redesign-recommendation.md`**
- Function block redesign details
- Control logic improvements
---
## Quick Structure Reference
### Light Naming Convention
```
Format: {room}_{function}
Examples:
- kitchen_main
- master_bedroom_bedside_left
- outdoor_front_security
```
### Function Types
- `main` - Primary light
- `bedside_left/right` - Bedside lamps
- `under_cabinet` - Task lighting
- `security` - Security lighting
- `ambient` - Atmospheric lighting
- etc.
### CODESYS Access
```iec
rooms.kitchen.main.ha_on := TRUE;
rooms.master_bedroom.bedside_left.state;
```
### Home Assistant Entity
```
light.kitchen_main
light.master_bedroom_bedside_left
```
---
## Water Boiler Safety Features
1.**Temperature Protection** (max 80°C, min 10°C)
2.**Time Limits** (max 8h ON, min 30m OFF)
3.**Flow Detection** (shut off if no flow)
4.**Emergency Stop** (immediate shutdown)
5.**Pressure Protection** (if sensor available)
6.**State Monitoring** (relay status readback)
7.**Error Reporting** (comprehensive error codes)
---
## Next Steps
1. **Review** `light-naming-configuration.md`
2. **Modify** light names per room based on actual installation
3. **Map** relays to lights
4. **Start** Phase 1 of implementation roadmap
---
**Status**: Ready for configuration review
**Priority**: Review and customize light names first

View File

@@ -0,0 +1,362 @@
# Structure Comparison - Visual Guide
## Current Structure (Room-Centric)
```
CODESYS:
┌─────────────────────────────────────┐
│ masterBedroom: fb_switch │
│ ├─ l_1 (Light 1) │
│ ├─ l_2 (Light 2) │
│ ├─ l_3 (Light 3) │
│ ├─ l_4 (Light 4) │
│ ├─ l_5 (Light 5) │
│ └─ l_6 (Light 6) │
└─────────────────────────────────────┘
Network Variable:
l_masterBedroom.l_1
l_masterBedroom.l_2
...
Home Assistant:
light.master_bedroom_l1
light.master_bedroom_l2
light.master_bedroom_l3
...
```
**Problems**:
- ❌ Generic names (l_1, l_2)
- ❌ Fixed 6 lights per room
- ❌ Wasted space (most rooms don't use all 6)
- ❌ Hard to identify which light is which
---
## Option 1: Flat Light-Centric
```
CODESYS:
┌─────────────────────────────────────┐
│ lights: struct_all_lights │
│ ├─ kitchen_main │
│ ├─ kitchen_under_cabinet │
│ ├─ master_bedroom_main │
│ ├─ master_bedroom_bedside_left │
│ ├─ master_bedroom_bedside_right │
│ └─ ... (all lights flat) │
└─────────────────────────────────────┘
Network Variable:
lights.kitchen_main.on
lights.kitchen_main.state
lights.master_bedroom_main.on
...
Home Assistant:
light.kitchen_main
light.kitchen_under_cabinet
light.master_bedroom_main
light.master_bedroom_bedside_left
```
**Benefits**:
- ✅ Clear, descriptive names
- ✅ Easy to find lights
- ✅ No wasted space
- ✅ Perfect for HA organization
---
## Option 4: Hybrid (Recommended)
```
CODESYS (Room-organized):
┌─────────────────────────────────────┐
│ rooms: struct_rooms │
│ ├─ kitchen │
│ │ ├─ main │
│ │ ├─ under_cabinet │
│ │ └─ island │
│ ├─ master_bedroom │
│ │ ├─ main │
│ │ ├─ bedside_left │
│ │ └─ bedside_right │
│ └─ ... │
└─────────────────────────────────────┘
Network Variable:
rooms.kitchen.main.on
rooms.kitchen.main.state
rooms.master_bedroom.main.on
...
Node-RED (Flattened):
kitchen_main → HA
kitchen_under_cabinet → HA
master_bedroom_main → HA
master_bedroom_bedside_left → HA
Home Assistant:
light.kitchen_main
light.kitchen_under_cabinet
light.master_bedroom_main
light.master_bedroom_bedside_left
```
**Benefits**:
- ✅ Organized in CODESYS (by room)
- ✅ Flat in Home Assistant (by light)
- ✅ Descriptive names
- ✅ Easy to add lights
- ✅ Best of both worlds
---
## Real-World Example Comparison
### Scenario: Kitchen with 3 lights
**Current Structure**:
```iec
kitchen: fb_switch
l_1 = ??? (which light?)
l_2 = ??? (which light?)
l_3 = ??? (which light?)
l_4 = unused
l_5 = unused
l_6 = unused
```
**Hybrid Structure**:
```iec
rooms.kitchen:
main = Main ceiling light
under_cabinet = Under cabinet lights
island = Island pendant
(no unused slots)
```
**Home Assistant**:
```
Current:
light.kitchen_l1 ← What is this?
light.kitchen_l2 ← What is this?
light.kitchen_l3 ← What is this?
Hybrid:
light.kitchen_main ← Clear!
light.kitchen_under_cabinet ← Clear!
light.kitchen_island ← Clear!
```
---
## MQTT Topic Comparison
### Current
```
homeassistant/light/master_bedroom_l1/state
homeassistant/light/master_bedroom_l2/state
homeassistant/light/kitchen_l1/state
```
**Problems**: Generic, hard to identify
### Hybrid
```
homeassistant/light/kitchen_main/state
homeassistant/light/kitchen_under_cabinet/state
homeassistant/light/master_bedroom_main/state
homeassistant/light/master_bedroom_bedside_left/state
```
**Benefits**: Self-documenting, clear purpose
---
## Home Assistant Dashboard Comparison
### Current
```
Kitchen
├─ Light 1 ← What is this?
├─ Light 2 ← What is this?
└─ Light 3 ← What is this?
Master Bedroom
├─ Light 1 ← What is this?
├─ Light 2 ← What is this?
└─ Light 3 ← What is this?
```
### Hybrid
```
Kitchen
├─ Main Light
├─ Under Cabinet
└─ Island
Master Bedroom
├─ Main Light
├─ Bedside Left
└─ Bedside Right
```
**Much clearer!**
---
## Network Variable Efficiency
### Current
- 15 rooms × 6 lights = 90 potential lights
- Most rooms use 2-3 lights
- **Waste**: ~60 unused light slots
- **Network traffic**: Sends all 90 values every 50ms
### Hybrid
- Only define lights that exist
- Kitchen: 3 lights (not 6)
- Master Bedroom: 3 lights (not 6)
- **Efficiency**: ~50% less network traffic
- **Clarity**: Only relevant data
---
## Scalability Comparison
### Adding a New Light
**Current**:
1. Find unused `l_X` slot in room
2. Hope it's available
3. Update documentation
4. Update HA manually
**Hybrid**:
1. Add `new_light: struct_light_control` to room
2. Done! Auto-discovered in HA
### Adding a New Room
**Current**:
1. Add new room structure
2. Add all 6 light slots (even if unused)
3. Update network variables
4. Update HA manually
**Hybrid**:
1. Add room with only needed lights
2. Done! Auto-discovered in HA
---
## Implementation Example
### Hybrid Structure in CODESYS
```iec
TYPE struct_light_control :
STRUCT
on: BOOL;
off: BOOL;
toggle: BOOL;
state: BOOL;
relay_status: BOOL;
END_STRUCT
END_TYPE
TYPE struct_room_lights :
STRUCT
main: struct_light_control;
secondary: struct_light_control;
task: struct_light_control;
ambient: struct_light_control;
accent: struct_light_control;
security: struct_light_control;
END_STRUCT
END_TYPE
VAR_GLOBAL
rooms: STRUCT
kitchen: STRUCT
main: struct_light_control;
under_cabinet: struct_light_control;
island: struct_light_control;
END_STRUCT;
master_bedroom: STRUCT
main: struct_light_control;
bedside_left: struct_light_control;
bedside_right: struct_light_control;
END_STRUCT;
// ... other rooms
END_STRUCT;
END_VAR
```
### Node-RED Transformation
```javascript
// Transform room-based to flat structure for HA
function transformToHA(msg) {
const rooms = msg.payload.rooms;
const result = {};
for (const [roomName, roomLights] of Object.entries(rooms)) {
for (const [lightName, lightControl] of Object.entries(roomLights)) {
const lightId = `${roomName}_${lightName}`;
result[lightId] = {
on: lightControl.on,
off: lightControl.off,
state: lightControl.state,
status: lightControl.relay_status
};
}
}
return { payload: result };
}
```
### Home Assistant Auto-Discovery
```yaml
# Node-RED publishes this automatically
homeassistant/light/kitchen_main/config:
name: "Kitchen Main"
unique_id: "kitchen_main"
state_topic: "homeassistant/light/kitchen_main/state"
command_topic: "homeassistant/light/kitchen_main/set"
state_value_template: "{{ value_json.state }}"
command_on_template: '{"on":true}'
command_off_template: '{"off":true}'
```
---
## Recommendation Summary
**Use Hybrid Structure (Option 4)** because:
1.**Best Organization**: Room-based in CODESYS, flat in HA
2.**Clear Naming**: `kitchen_main` vs `l_1`
3.**Efficiency**: Only define existing lights
4.**Scalability**: Easy to add lights/rooms
5.**Maintainability**: Self-documenting structure
6.**HA Integration**: Perfect for Home Assistant
7.**Future-Proof**: Easy to extend
**Key Changes**:
- Replace `l_1`, `l_2` with descriptive names
- Use function-based naming: `main`, `secondary`, `task`, etc.
- Flatten structure in Node-RED for HA
- Only define lights that exist
- Add metadata for better organization
---
**See**: [Full Structure Redesign Analysis](structure-redesign-analysis.md) for complete details.

View File

@@ -0,0 +1,538 @@
# Room/Light Structure Redesign Analysis
## Current Structure Analysis
### Current Organization
**Room-Centric Approach**:
- 15 rooms, each with 1 `fb_switch` instance
- Each room controls up to 6 lights
- Network variables organized by room name
- Structure: `l_masterBedroom.l_1`, `l_masterBedroom.l_2`, etc.
**Current Data Flow**:
```
Room → fb_switch → 6 lights
Network Variable: l_masterBedroom (struct_lights with l_1 to l_6)
```
### Current Issues
1. **Limited Scalability**
- Fixed 6 lights per room
- Adding a 7th light requires structure changes
- Some rooms may only need 1-2 lights (waste)
2. **Home Assistant Organization**
- HA entities: `light.master_bedroom_l1`, `light.master_bedroom_l2`
- Not intuitive - hard to find lights
- No grouping by function or zone
3. **Network Variable Efficiency**
- 15 room structures × 6 lights = 90 potential lights
- Most rooms don't use all 6 lights
- Wasted network bandwidth
4. **Maintenance Complexity**
- Changes require updating room structures
- Hard to add new rooms
- No clear naming convention
5. **MQTT Topic Structure**
- Topics like: `homeassistant/light/master_bedroom_l1`
- Not standardized
- Hard to discover and manage
## Alternative Structures
### Option 1: Flat Light-Centric Structure (Recommended)
**Concept**: All lights in a single flat structure, organized by unique IDs.
**Data Structure**:
```iec
TYPE struct_light :
STRUCT
// Control
on: BOOL; // Turn ON command
off: BOOL; // Turn OFF command
toggle: BOOL; // Toggle command (for Zigbee)
// Status
state: BOOL; // Current state
relay_status: BOOL; // Actual relay status
// Metadata (for reference, not in network var)
room: STRING; // Room name
name: STRING; // Light name
zone: STRING; // Zone (indoor/outdoor)
END_STRUCT
END_TYPE
TYPE struct_all_lights :
STRUCT
// Master Bedroom
master_bedroom_main: struct_light;
master_bedroom_bedside: struct_light;
master_bedroom_closet: struct_light;
// Kitchen
kitchen_ceiling: struct_light;
kitchen_under_cabinet: struct_light;
kitchen_island: struct_light;
// Living Room
living_room_main: struct_light;
living_room_reading: struct_light;
living_room_tv: struct_light;
// Outdoor
outdoor_front_porch: struct_light;
outdoor_back_patio: struct_light;
outdoor_side: struct_light;
// ... all other lights
END_STRUCT
END_TYPE
```
**Network Variable**:
```iec
VAR_GLOBAL
lights: struct_all_lights; // All lights in one structure
END_VAR
```
**Function Block**:
```iec
FUNCTION_BLOCK fb_lightControl
VAR_INPUT
light: struct_light;
relay_output: BOOL; // Direct relay output
END_VAR
VAR_OUTPUT
relay_control: BOOL;
light_status: struct_light;
END_VAR
// Implementation...
END_FUNCTION_BLOCK
```
**Pros**:
- ✅ Each light is independent
- ✅ Easy to add/remove lights
- ✅ Clear naming: `lights.kitchen_ceiling.on`
- ✅ Better for Home Assistant (one entity per light)
- ✅ No wasted space
- ✅ Easy to group in HA by room/zone
**Cons**:
- ⚠️ Larger structure (but more efficient overall)
- ⚠️ Need to update structure when adding lights
**Home Assistant Organization**:
```
light.kitchen_ceiling
light.kitchen_under_cabinet
light.master_bedroom_main
light.master_bedroom_bedside
```
**MQTT Topics**:
```
homeassistant/light/kitchen_ceiling/state
homeassistant/light/kitchen_ceiling/set
homeassistant/light/master_bedroom_main/state
```
---
### Option 2: Hierarchical Room → Light Structure
**Concept**: Keep room structure but make it more flexible.
**Data Structure**:
```iec
TYPE struct_room :
STRUCT
room_id: STRING; // "master_bedroom"
room_name: STRING; // "Master Bedroom"
zone: STRING; // "indoor", "outdoor"
// Flexible light array (up to 10 lights)
lights: ARRAY[1..10] OF struct_light;
light_count: INT; // Actual number of lights
END_STRUCT
END_TYPE
TYPE struct_home :
STRUCT
rooms: ARRAY[1..20] OF struct_room;
room_count: INT;
END_STRUCT
END_TYPE
```
**Pros**:
- ✅ Maintains room grouping
- ✅ Flexible number of lights per room
- ✅ Can add rooms easily
**Cons**:
- ⚠️ More complex array handling
- ⚠️ CODESYS arrays less efficient for network vars
- ⚠️ Harder to access specific lights
---
### Option 3: Zone-Based Structure
**Concept**: Organize by functional zones rather than rooms.
**Data Structure**:
```iec
TYPE struct_zone :
STRUCT
zone_id: STRING; // "indoor_main", "outdoor_security"
zone_name: STRING; // "Indoor Main", "Outdoor Security"
// Lights in this zone
lights: ARRAY[1..20] OF struct_light;
light_count: INT;
END_STRUCT
END_TYPE
TYPE struct_home_zones :
STRUCT
indoor_main: struct_zone;
indoor_bedrooms: struct_zone;
indoor_bathrooms: struct_zone;
outdoor_security: struct_zone;
outdoor_ambient: struct_zone;
END_STRUCT
END_TYPE
```
**Zones**:
- **Indoor Main**: Kitchen, Living Room, Dining Room, Hallway
- **Indoor Bedrooms**: All bedrooms
- **Indoor Bathrooms**: All bathrooms
- **Outdoor Security**: Front, Back, Side (security-focused)
- **Outdoor Ambient**: Veranda, Patio (ambient lighting)
**Pros**:
- ✅ Logical grouping for automation
- ✅ Easy to control all security lights
- ✅ Better for scheduling (indoor vs outdoor)
**Cons**:
- ⚠️ Less intuitive for room-based control
- ⚠️ Lights may belong to multiple zones conceptually
---
### Option 4: Hybrid: Room + Light ID Structure (Best Balance)
**Concept**: Combine room organization with individual light control.
**Data Structure**:
```iec
TYPE struct_light_control :
STRUCT
// Control
on: BOOL;
off: BOOL;
toggle: BOOL;
// Status
state: BOOL;
relay_status: BOOL;
// Metadata (for HA, not in network var)
light_id: STRING; // Unique ID: "mb_main", "kit_ceiling"
light_name: STRING; // Display name: "Main Light", "Ceiling Light"
room: STRING; // Room: "master_bedroom", "kitchen"
zone: STRING; // Zone: "indoor", "outdoor"
function: STRING; // Function: "main", "task", "ambient", "security"
END_STRUCT
END_TYPE
// Organized by room for CODESYS, but flat for HA
TYPE struct_rooms :
STRUCT
// Master Bedroom
master_bedroom: STRUCT
main: struct_light_control;
bedside_left: struct_light_control;
bedside_right: struct_light_control;
closet: struct_light_control;
END_STRUCT;
// Kitchen
kitchen: STRUCT
ceiling: struct_light_control;
under_cabinet: struct_light_control;
island: struct_light_control;
END_STRUCT;
// ... other rooms
END_STRUCT
END_TYPE
```
**Network Variable**:
```iec
VAR_GLOBAL
rooms: struct_rooms; // Organized by room
END_VAR
```
**Access Pattern**:
- CODESYS: `rooms.kitchen.ceiling.on`
- Node-RED: Flatten to `kitchen_ceiling` for HA
- Home Assistant: `light.kitchen_ceiling`
**Pros**:
- ✅ Best of both worlds
- ✅ Organized in CODESYS (by room)
- ✅ Flat in Home Assistant (by light)
- ✅ Easy to add lights to rooms
- ✅ Clear naming convention
**Cons**:
- ⚠️ Requires Node-RED transformation
- ⚠️ Slightly more complex
---
## Recommended Structure: Option 4 (Hybrid)
### Implementation
**1. CODESYS Structure** (Room-organized):
```iec
TYPE struct_light_control :
STRUCT
on: BOOL;
off: BOOL;
toggle: BOOL;
state: BOOL;
relay_status: BOOL;
END_STRUCT
END_TYPE
TYPE struct_room_lights :
STRUCT
main: struct_light_control;
secondary: struct_light_control;
task: struct_light_control;
ambient: struct_light_control;
accent: struct_light_control;
security: struct_light_control;
END_STRUCT
END_TYPE
VAR_GLOBAL
rooms: STRUCT
master_bedroom: struct_room_lights;
master_bathroom: struct_room_lights;
bedroom_1: struct_room_lights;
bedroom_2: struct_room_lights;
bathroom: struct_room_lights;
kitchen: struct_room_lights;
living_room: struct_room_lights;
dining_room: struct_room_lights;
hallway: struct_room_lights;
pantry: struct_room_lights;
entrance: struct_room_lights;
guest_wc: struct_room_lights;
outdoor_veranda: struct_room_lights;
outdoor_front: struct_room_lights;
outdoor_side: struct_room_lights;
outdoor_back: struct_room_lights;
END_STRUCT;
END_VAR
```
**2. Node-RED Transformation** (Flatten for HA):
```javascript
// Transform CODESYS structure to flat HA structure
function transformToHA(msg) {
const rooms = msg.payload.rooms;
const haLights = {};
// Flatten structure
for (const [roomName, roomLights] of Object.entries(rooms)) {
for (const [lightName, lightControl] of Object.entries(roomLights)) {
const lightId = `${roomName}_${lightName}`;
haLights[lightId] = {
on: lightControl.on,
off: lightControl.off,
state: lightControl.state,
status: lightControl.relay_status,
room: roomName,
light: lightName
};
}
}
return { payload: haLights };
}
```
**3. Home Assistant Configuration**:
```yaml
# Auto-discovery via MQTT
light:
- platform: mqtt
name: "Kitchen Main"
unique_id: "kitchen_main"
state_topic: "homeassistant/light/kitchen_main/state"
command_topic: "homeassistant/light/kitchen_main/set"
# ... config
```
**4. MQTT Topic Structure**:
```
homeassistant/light/{room}_{light}/state
homeassistant/light/{room}_{light}/set
Examples:
homeassistant/light/kitchen_main/state
homeassistant/light/master_bedroom_main/state
homeassistant/light/outdoor_front_security/state
```
---
## Comparison Matrix
| Aspect | Current | Option 1 (Flat) | Option 2 (Hierarchical) | Option 3 (Zone) | Option 4 (Hybrid) |
|--------|---------|-----------------|-------------------------|------------------|-------------------|
| **CODESYS Organization** | Room-based | Flat | Array-based | Zone-based | Room-based |
| **HA Organization** | Room-based | Flat | Complex | Zone-based | Flat (transformed) |
| **Scalability** | Poor | Excellent | Good | Good | Excellent |
| **Maintainability** | Medium | Excellent | Medium | Medium | Excellent |
| **Network Efficiency** | Poor | Good | Medium | Medium | Good |
| **Naming Clarity** | Medium | Excellent | Medium | Good | Excellent |
| **Implementation Complexity** | Low | Medium | High | Medium | Medium |
| **Flexibility** | Low | High | High | Medium | High |
---
## Optimization Recommendations
### 1. Network Variable Optimization
**Current**: 15 rooms × 6 lights = 90 potential lights
**Optimized**: Only include lights that exist
**Example**:
```iec
// Only define lights that exist
master_bedroom: STRUCT
main: struct_light_control;
bedside: struct_light_control;
// No closet light if it doesn't exist
END_STRUCT;
```
### 2. Function-Based Naming
Instead of `l_1`, `l_2`, use descriptive names:
- `main` - Main/primary light
- `secondary` - Secondary light
- `task` - Task lighting
- `ambient` - Ambient/atmospheric
- `accent` - Accent lighting
- `security` - Security/outdoor
### 3. Metadata for Home Assistant
Add metadata structure (not in network var, but in Node-RED):
```javascript
const lightMetadata = {
"kitchen_main": {
name: "Kitchen Main Light",
room: "Kitchen",
zone: "indoor",
function: "main",
icon: "mdi:ceiling-light"
},
// ... more lights
};
```
### 4. Grouping in Home Assistant
Use HA groups and areas:
```yaml
# Automatically group by room
light:
- platform: group
name: "Kitchen Lights"
entities:
- light.kitchen_main
- light.kitchen_under_cabinet
- light.kitchen_island
# Use areas for room organization
areas:
- name: "Kitchen"
entities:
- light.kitchen_main
- light.kitchen_under_cabinet
```
---
## Migration Strategy
### Phase 1: Structure Redesign
1. Define new data structures
2. Create mapping from old to new
3. Update function blocks
### Phase 2: Node-RED Update
1. Update network variable mapping
2. Add transformation functions
3. Update MQTT topics
### Phase 3: Home Assistant Migration
1. Create new entities with new structure
2. Migrate automations
3. Update dashboards
### Phase 4: Testing & Validation
1. Test all control paths
2. Verify status feedback
3. Test HA integration
---
## Final Recommendation
**Use Option 4 (Hybrid Structure)** because:
1.**Best Organization**: Room-based in CODESYS, flat in HA
2.**Scalability**: Easy to add lights to any room
3.**Clarity**: Descriptive names (`kitchen_main` vs `l_1`)
4.**Flexibility**: Can group by room, zone, or function
5.**Efficiency**: Only define lights that exist
6.**Maintainability**: Clear structure, easy to understand
**Key Improvements**:
- Replace `l_1`, `l_2` with `main`, `secondary`, `task`, etc.
- Use descriptive light IDs: `kitchen_main`, `master_bedroom_bedside`
- Flatten structure in Node-RED for Home Assistant
- Add metadata for better HA organization
- Optimize network variables (only existing lights)
---
**Next Steps**:
1. Review this analysis
2. Choose structure option
3. Plan migration
4. Implement new structure
5. Update Node-RED and HA