# 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