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:
362
docs/redesign/structure-comparison-visual.md
Normal file
362
docs/redesign/structure-comparison-visual.md
Normal 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.
|
||||
Reference in New Issue
Block a user