Refactor room and light configurations for Node-RED integration
- Updated global variable lists in GVL_IO.gvl and GVL_NVL_placeholders.gvl to reflect new room naming conventions and structures. - Revised PLC_App.st to map new room configurations for lighting control. - Enhanced documentation in all-lights-and-rooms.md and ha-lights-and-rooms.md to align with updated room and light entity naming. - Adjusted room-config.js and related Node-RED flows to support the new configuration structure. This update improves the organization and clarity of room and light management within the Node-RED integration, ensuring consistency across the system.
This commit is contained in:
@@ -1,27 +1,27 @@
|
||||
(*
|
||||
GVL: GVL_IO
|
||||
Option C relay feedback only. EL2809 DO: map channels directly in the device tree
|
||||
to NVL_Out (e.g. NVL_Out.l_masterBedroom.l_1..l_6, ...) and boiler relay.
|
||||
to NVL_Out (e.g. NVL_Out.l_open_plan_living_room.l_1..l_6, ...) and boiler relay.
|
||||
Initialize EtherCAT_RelayFeedback to zero at startup (or use default init).
|
||||
*)
|
||||
VAR_GLOBAL
|
||||
// ---------- Option C: relay feedback (copy of output for next cycle) ----------
|
||||
EtherCAT_RelayFeedback: STRUCT
|
||||
masterBedroom: struct_room_outs;
|
||||
masterBathroom: struct_room_outs;
|
||||
bedroom_1: struct_room_outs;
|
||||
bedroom_2: struct_room_outs;
|
||||
bathroom: struct_room_outs;
|
||||
guest_wc: struct_room_outs;
|
||||
kitchen: struct_room_outs;
|
||||
pantry: struct_room_outs;
|
||||
livingRoom: struct_room_outs;
|
||||
diningRoom: struct_room_outs;
|
||||
entrance: struct_room_outs;
|
||||
hallway: struct_room_outs;
|
||||
veranda: struct_room_outs;
|
||||
front: struct_room_outs;
|
||||
back: struct_room_outs;
|
||||
side: struct_room_outs;
|
||||
open_plan_living_room: struct_room_outs;
|
||||
open_plan_dining_room: struct_room_outs;
|
||||
open_plan_entrance: struct_room_outs;
|
||||
open_plan_guest_wc: struct_room_outs;
|
||||
kitchen_kitchen: struct_room_outs;
|
||||
kitchen_pantry: struct_room_outs;
|
||||
bedrooms_office: struct_room_outs;
|
||||
bedrooms_hallway: struct_room_outs;
|
||||
bedrooms_laundry: struct_room_outs;
|
||||
bedrooms_shower: struct_room_outs;
|
||||
bedrooms_bedroom: struct_room_outs;
|
||||
master_bedroom_suite: struct_room_outs;
|
||||
master_bedroom_bathroom: struct_room_outs;
|
||||
exterior_veranda: struct_room_outs;
|
||||
exterior_entrance: struct_room_outs;
|
||||
exterior_yard: struct_room_outs;
|
||||
END_STRUCT;
|
||||
END_VAR
|
||||
|
||||
@@ -5,42 +5,42 @@
|
||||
*)
|
||||
VAR_GLOBAL
|
||||
NVL_In: STRUCT
|
||||
masterBedroom: struct_room_cmds;
|
||||
masterBathroom: struct_room_cmds;
|
||||
bedroom_1: struct_room_cmds;
|
||||
bedroom_2: struct_room_cmds;
|
||||
bathroom: struct_room_cmds;
|
||||
guestWc: struct_room_cmds;
|
||||
kitchen: struct_room_cmds;
|
||||
pantry: struct_room_cmds;
|
||||
livingRoom: struct_room_cmds;
|
||||
dinningRoom: struct_room_cmds;
|
||||
entrance: struct_room_cmds;
|
||||
hallway: struct_room_cmds;
|
||||
outVeranda: struct_room_cmds;
|
||||
outFront: struct_room_cmds;
|
||||
outBack: struct_room_cmds;
|
||||
outSide: struct_room_cmds;
|
||||
open_plan_living_room: struct_room_cmds;
|
||||
open_plan_dining_room: struct_room_cmds;
|
||||
open_plan_entrance: struct_room_cmds;
|
||||
open_plan_guest_wc: struct_room_cmds;
|
||||
kitchen_kitchen: struct_room_cmds;
|
||||
kitchen_pantry: struct_room_cmds;
|
||||
bedrooms_office: struct_room_cmds;
|
||||
bedrooms_hallway: struct_room_cmds;
|
||||
bedrooms_laundry: struct_room_cmds;
|
||||
bedrooms_shower: struct_room_cmds;
|
||||
bedrooms_bedroom: struct_room_cmds;
|
||||
master_bedroom_suite: struct_room_cmds;
|
||||
master_bedroom_bathroom: struct_room_cmds;
|
||||
exterior_veranda: struct_room_cmds;
|
||||
exterior_entrance: struct_room_cmds;
|
||||
exterior_yard: struct_room_cmds;
|
||||
boiler: struct_boiler_cmd;
|
||||
END_STRUCT;
|
||||
|
||||
NVL_Out: STRUCT
|
||||
l_masterBedroom: struct_room_outs;
|
||||
l_masterBathroom: struct_room_outs;
|
||||
l_bedroom_1: struct_room_outs;
|
||||
l_bedroom_2: struct_room_outs;
|
||||
l_bathroom: struct_room_outs;
|
||||
l_guestWc: struct_room_outs;
|
||||
l_kitchen: struct_room_outs;
|
||||
l_pantry: struct_room_outs;
|
||||
l_livingRoom: struct_room_outs;
|
||||
l_dinningRoom: struct_room_outs;
|
||||
l_entrance: struct_room_outs;
|
||||
l_hallway: struct_room_outs;
|
||||
l_outVeranda: struct_room_outs;
|
||||
l_outFront: struct_room_outs;
|
||||
l_outBack: struct_room_outs;
|
||||
l_outSide: struct_room_outs;
|
||||
l_open_plan_living_room: struct_room_outs;
|
||||
l_open_plan_dining_room: struct_room_outs;
|
||||
l_open_plan_entrance: struct_room_outs;
|
||||
l_open_plan_guest_wc: struct_room_outs;
|
||||
l_kitchen_kitchen: struct_room_outs;
|
||||
l_kitchen_pantry: struct_room_outs;
|
||||
l_bedrooms_office: struct_room_outs;
|
||||
l_bedrooms_hallway: struct_room_outs;
|
||||
l_bedrooms_laundry: struct_room_outs;
|
||||
l_bedrooms_shower: struct_room_outs;
|
||||
l_bedrooms_bedroom: struct_room_outs;
|
||||
l_master_bedroom_suite: struct_room_outs;
|
||||
l_master_bedroom_bathroom: struct_room_outs;
|
||||
l_exterior_veranda: struct_room_outs;
|
||||
l_exterior_entrance: struct_room_outs;
|
||||
l_exterior_yard: struct_room_outs;
|
||||
boiler_status: struct_boiler_status;
|
||||
END_STRUCT;
|
||||
|
||||
|
||||
@@ -23,12 +23,14 @@ This folder describes the **network variable** setup used for CODESYS ↔ Node-R
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `l_masterBedroom` | struct_room_outs | 12 BOOLs (l_1..l_6, l_1_status..l_6_status) |
|
||||
| `l_masterBathroom` | struct_room_outs | same |
|
||||
| `l_bedroom_1` .. `l_bedroom_2` | struct_room_outs | same |
|
||||
| `l_bathroom`, `l_guestWc`, `l_kitchen`, `l_pantry` | struct_room_outs | same |
|
||||
| `l_livingRoom`, `l_dinningRoom`, `l_entrance`, `l_hallway` | struct_room_outs | same |
|
||||
| `l_outVeranda`, `l_outFront`, `l_outBack`, `l_outSide` | struct_room_outs | same |
|
||||
| `l_open_plan_living_room` | struct_room_outs | 6 BOOLs (`l_1..l_6`) |
|
||||
| `l_open_plan_dining_room` | struct_room_outs | same |
|
||||
| `l_open_plan_entrance` | struct_room_outs | same |
|
||||
| `l_open_plan_guest_wc` | struct_room_outs | same |
|
||||
| `l_kitchen_kitchen`, `l_kitchen_pantry` | struct_room_outs | same |
|
||||
| `l_bedrooms_office`, `l_bedrooms_hallway`, `l_bedrooms_laundry`, `l_bedrooms_shower`, `l_bedrooms_bedroom` | struct_room_outs | same |
|
||||
| `l_master_bedroom_suite`, `l_master_bedroom_bathroom` | struct_room_outs | same |
|
||||
| `l_exterior_veranda`, `l_exterior_entrance`, `l_exterior_yard` | struct_room_outs | same |
|
||||
| `boiler_status` | struct_boiler_status | state, relay_output, on_time_minutes, remaining_minutes, emergency_active, time_limit_reached, error_state, error_code |
|
||||
|
||||
**In CODESYS:** Create an **NVL Sender** (Network Variable List), bind it to the **NVL_Out** structure (the same struct as in `GVL_NVL_placeholders.gvl` → `NVL_Out`). Set protocol to UDP, destination IP/port to your Node-RED host, task and interval (e.g. EtherCAT_Task, 50 ms).
|
||||
@@ -43,7 +45,7 @@ This folder describes the **network variable** setup used for CODESYS ↔ Node-R
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `masterBedroom` .. `side` (15 rooms) | struct_room_cmds | ha_l1_on, ha_l1_off, ... ha_l6_on, ha_l6_off, zigbee_sw1..6, ha_all_on, ha_all_off |
|
||||
| `open_plan_living_room` .. `exterior_yard` (16 rooms) | struct_room_cmds | ha_l1_on, ha_l1_off, ... ha_l6_on, ha_l6_off, zigbee_sw1..6, ha_all_on, ha_all_off |
|
||||
| `boiler` | struct_boiler_cmd | ha_on, ha_off, schedule_on, schedule_off, emergency_stop, max_on_time_minutes |
|
||||
|
||||
**In CODESYS:** Create an **NVL Receiver**, bind it to the **NVL_In** structure. Set protocol to UDP, listen port, task and interval. The PLC will overwrite `NVL_In` with received data each cycle.
|
||||
|
||||
@@ -25,7 +25,7 @@ PLC sends one block: all rooms’ `struct_room_outs` followed by `struct_boiler_
|
||||
6 BOOLs in order: `l_1, l_2, l_3, l_4, l_5, l_6` (light state; with Option C this is both output and status).
|
||||
|
||||
- **Size per room:** 6 bytes.
|
||||
- **Rooms in order:** l_masterBedroom, l_masterBathroom, l_bedroom_1, l_bedroom_2, l_bathroom, l_guestWc, l_kitchen, l_pantry, l_livingRoom, l_dinningRoom, l_entrance, l_hallway, l_outVeranda, l_outFront, l_outBack, l_outSide.
|
||||
- **Rooms in order:** l_open_plan_living_room, l_open_plan_dining_room, l_open_plan_entrance, l_open_plan_guest_wc, l_kitchen_kitchen, l_kitchen_pantry, l_bedrooms_office, l_bedrooms_hallway, l_bedrooms_laundry, l_bedrooms_shower, l_bedrooms_bedroom, l_master_bedroom_suite, l_master_bedroom_bathroom, l_exterior_veranda, l_exterior_entrance, l_exterior_yard.
|
||||
- **Total for lights:** 16 × 6 = **96 bytes**.
|
||||
|
||||
### struct_boiler_status (after all rooms)
|
||||
@@ -50,7 +50,7 @@ PLC sends one block: all rooms’ `struct_room_outs` followed by `struct_boiler_
|
||||
// msg.payload = Buffer (UDP payload from PLC)
|
||||
const buf = msg.payload;
|
||||
const roomSize = 6;
|
||||
const roomNames = ['l_masterBedroom','l_masterBathroom','l_bedroom_1','l_bedroom_2','l_bathroom','l_guestWc','l_kitchen','l_pantry','l_livingRoom','l_dinningRoom','l_entrance','l_hallway','l_outVeranda','l_outFront','l_outBack','l_outSide'];
|
||||
const roomNames = ['l_open_plan_living_room','l_open_plan_dining_room','l_open_plan_entrance','l_open_plan_guest_wc','l_kitchen_kitchen','l_kitchen_pantry','l_bedrooms_office','l_bedrooms_hallway','l_bedrooms_laundry','l_bedrooms_shower','l_bedrooms_bedroom','l_master_bedroom_suite','l_master_bedroom_bathroom','l_exterior_veranda','l_exterior_entrance','l_exterior_yard'];
|
||||
|
||||
const out = { rooms: {}, boiler_status: {} };
|
||||
|
||||
@@ -90,7 +90,7 @@ PLC expects one block: all rooms’ `struct_room_cmds` followed by `struct_boile
|
||||
ha_l1_on, ha_l1_off, ha_l2_on, ha_l2_off, ha_l3_on, ha_l3_off, ha_l4_on, ha_l4_off, ha_l5_on, ha_l5_off, ha_l6_on, ha_l6_off, zigbee_sw1..6, ha_all_on, ha_all_off.
|
||||
|
||||
- **Size per room:** 20 bytes.
|
||||
- **Rooms in order:** masterBedroom, masterBathroom, bedroom_1, bedroom_2, bathroom, guestWc, kitchen, pantry, livingRoom, dinningRoom, entrance, hallway, outVeranda, outFront, outBack, outSide.
|
||||
- **Rooms in order:** open_plan_living_room, open_plan_dining_room, open_plan_entrance, open_plan_guest_wc, kitchen_kitchen, kitchen_pantry, bedrooms_office, bedrooms_hallway, bedrooms_laundry, bedrooms_shower, bedrooms_bedroom, master_bedroom_suite, master_bedroom_bathroom, exterior_veranda, exterior_entrance, exterior_yard.
|
||||
- **Total for rooms:** 16 × 20 = **320 bytes**.
|
||||
|
||||
### struct_boiler_cmd
|
||||
@@ -112,7 +112,7 @@ ha_l1_on, ha_l1_off, ha_l2_on, ha_l2_off, ha_l3_on, ha_l3_off, ha_l4_on, ha_l4_o
|
||||
```javascript
|
||||
// Build binary payload for PLC from commands
|
||||
const roomSize = 20;
|
||||
const roomNames = ['masterBedroom','masterBathroom','bedroom_1','bedroom_2','bathroom','guestWc','kitchen','pantry','livingRoom','dinningRoom','entrance','hallway','outVeranda','outFront','outBack','outSide'];
|
||||
const roomNames = ['open_plan_living_room','open_plan_dining_room','open_plan_entrance','open_plan_guest_wc','kitchen_kitchen','kitchen_pantry','bedrooms_office','bedrooms_hallway','bedrooms_laundry','bedrooms_shower','bedrooms_bedroom','master_bedroom_suite','master_bedroom_bathroom','exterior_veranda','exterior_entrance','exterior_yard'];
|
||||
|
||||
const buf = Buffer.alloc(328);
|
||||
const rooms = msg.payload.rooms || {};
|
||||
|
||||
@@ -2,112 +2,112 @@
|
||||
POU: PLC_App
|
||||
Main program (Option C: copy of output as relay feedback).
|
||||
Requires: NVL_In, NVL_Out, GVL_IO (EtherCAT_RelayFeedback).
|
||||
Map EL2809 DO channels in the device tree directly to NVL_Out (e.g. Ch0..5 = l_masterBedroom.l_1..l_6)
|
||||
Map EL2809 DO channels in the device tree directly to NVL_Out (e.g. Ch0..5 = l_open_plan_living_room.l_1..l_6)
|
||||
and Ch15 to boiler relay (e.g. NVL_Out.boiler_status.relay_output or a GVL BOOL).
|
||||
Optional: DI_Emergency_Stop (physical E-Stop input).
|
||||
*)
|
||||
PROGRAM PLC_App
|
||||
VAR
|
||||
masterBedroom: fb_room;
|
||||
masterBathroom: fb_room;
|
||||
bedroom_1: fb_room;
|
||||
bedroom_2: fb_room;
|
||||
bathroom: fb_room;
|
||||
guest_wc: fb_room;
|
||||
kitchen: fb_room;
|
||||
pantry: fb_room;
|
||||
livingRoom: fb_room;
|
||||
diningRoom: fb_room;
|
||||
entrance: fb_room;
|
||||
hallway: fb_room;
|
||||
veranda: fb_room;
|
||||
front: fb_room;
|
||||
back: fb_room;
|
||||
side: fb_room;
|
||||
open_plan_living_room: fb_room;
|
||||
open_plan_dining_room: fb_room;
|
||||
open_plan_entrance: fb_room;
|
||||
open_plan_guest_wc: fb_room;
|
||||
kitchen_kitchen: fb_room;
|
||||
kitchen_pantry: fb_room;
|
||||
bedrooms_office: fb_room;
|
||||
bedrooms_hallway: fb_room;
|
||||
bedrooms_laundry: fb_room;
|
||||
bedrooms_shower: fb_room;
|
||||
bedrooms_bedroom: fb_room;
|
||||
master_bedroom_suite: fb_room;
|
||||
master_bedroom_bathroom: fb_room;
|
||||
exterior_veranda: fb_room;
|
||||
exterior_entrance: fb_room;
|
||||
exterior_yard: fb_room;
|
||||
boiler: fb_boiler;
|
||||
END_VAR
|
||||
|
||||
// ========== SECTION 1: LIGHTING (Option C: relay feedback = copy of output) ==========
|
||||
|
||||
// Master Bedroom
|
||||
masterBedroom(switches := NVL_In.masterBedroom, relay_status := EtherCAT_RelayFeedback.masterBedroom);
|
||||
EtherCAT_RelayFeedback.masterBedroom := masterBedroom.lights;
|
||||
NVL_Out.l_masterBedroom := masterBedroom.lights;
|
||||
// Open Plan - Living Room
|
||||
open_plan_living_room(switches := NVL_In.open_plan_living_room, relay_status := EtherCAT_RelayFeedback.open_plan_living_room);
|
||||
EtherCAT_RelayFeedback.open_plan_living_room := open_plan_living_room.lights;
|
||||
NVL_Out.l_open_plan_living_room := open_plan_living_room.lights;
|
||||
|
||||
// Master Bathroom
|
||||
masterBathroom(switches := NVL_In.masterBathroom, relay_status := EtherCAT_RelayFeedback.masterBathroom);
|
||||
EtherCAT_RelayFeedback.masterBathroom := masterBathroom.lights;
|
||||
NVL_Out.l_masterBathroom := masterBathroom.lights;
|
||||
// Open Plan - Dining Room
|
||||
open_plan_dining_room(switches := NVL_In.open_plan_dining_room, relay_status := EtherCAT_RelayFeedback.open_plan_dining_room);
|
||||
EtherCAT_RelayFeedback.open_plan_dining_room := open_plan_dining_room.lights;
|
||||
NVL_Out.l_open_plan_dining_room := open_plan_dining_room.lights;
|
||||
|
||||
// Bedroom 1
|
||||
bedroom_1(switches := NVL_In.bedroom_1, relay_status := EtherCAT_RelayFeedback.bedroom_1);
|
||||
EtherCAT_RelayFeedback.bedroom_1 := bedroom_1.lights;
|
||||
NVL_Out.l_bedroom_1 := bedroom_1.lights;
|
||||
// Open Plan - Entrance
|
||||
open_plan_entrance(switches := NVL_In.open_plan_entrance, relay_status := EtherCAT_RelayFeedback.open_plan_entrance);
|
||||
EtherCAT_RelayFeedback.open_plan_entrance := open_plan_entrance.lights;
|
||||
NVL_Out.l_open_plan_entrance := open_plan_entrance.lights;
|
||||
|
||||
// Bedroom 2
|
||||
bedroom_2(switches := NVL_In.bedroom_2, relay_status := EtherCAT_RelayFeedback.bedroom_2);
|
||||
EtherCAT_RelayFeedback.bedroom_2 := bedroom_2.lights;
|
||||
NVL_Out.l_bedroom_2 := bedroom_2.lights;
|
||||
|
||||
// Bathroom
|
||||
bathroom(switches := NVL_In.bathroom, relay_status := EtherCAT_RelayFeedback.bathroom);
|
||||
EtherCAT_RelayFeedback.bathroom := bathroom.lights;
|
||||
NVL_Out.l_bathroom := bathroom.lights;
|
||||
|
||||
// Guest WC
|
||||
guest_wc(switches := NVL_In.guestWc, relay_status := EtherCAT_RelayFeedback.guest_wc);
|
||||
EtherCAT_RelayFeedback.guest_wc := guest_wc.lights;
|
||||
NVL_Out.l_guestWc := guest_wc.lights;
|
||||
// Open Plan - Guest WC
|
||||
open_plan_guest_wc(switches := NVL_In.open_plan_guest_wc, relay_status := EtherCAT_RelayFeedback.open_plan_guest_wc);
|
||||
EtherCAT_RelayFeedback.open_plan_guest_wc := open_plan_guest_wc.lights;
|
||||
NVL_Out.l_open_plan_guest_wc := open_plan_guest_wc.lights;
|
||||
|
||||
// Kitchen
|
||||
kitchen(switches := NVL_In.kitchen, relay_status := EtherCAT_RelayFeedback.kitchen);
|
||||
EtherCAT_RelayFeedback.kitchen := kitchen.lights;
|
||||
NVL_Out.l_kitchen := kitchen.lights;
|
||||
kitchen_kitchen(switches := NVL_In.kitchen_kitchen, relay_status := EtherCAT_RelayFeedback.kitchen_kitchen);
|
||||
EtherCAT_RelayFeedback.kitchen_kitchen := kitchen_kitchen.lights;
|
||||
NVL_Out.l_kitchen_kitchen := kitchen_kitchen.lights;
|
||||
|
||||
// Pantry
|
||||
pantry(switches := NVL_In.pantry, relay_status := EtherCAT_RelayFeedback.pantry);
|
||||
EtherCAT_RelayFeedback.pantry := pantry.lights;
|
||||
NVL_Out.l_pantry := pantry.lights;
|
||||
kitchen_pantry(switches := NVL_In.kitchen_pantry, relay_status := EtherCAT_RelayFeedback.kitchen_pantry);
|
||||
EtherCAT_RelayFeedback.kitchen_pantry := kitchen_pantry.lights;
|
||||
NVL_Out.l_kitchen_pantry := kitchen_pantry.lights;
|
||||
|
||||
// Living Room
|
||||
livingRoom(switches := NVL_In.livingRoom, relay_status := EtherCAT_RelayFeedback.livingRoom);
|
||||
EtherCAT_RelayFeedback.livingRoom := livingRoom.lights;
|
||||
NVL_Out.l_livingRoom := livingRoom.lights;
|
||||
// Bedrooms - Office
|
||||
bedrooms_office(switches := NVL_In.bedrooms_office, relay_status := EtherCAT_RelayFeedback.bedrooms_office);
|
||||
EtherCAT_RelayFeedback.bedrooms_office := bedrooms_office.lights;
|
||||
NVL_Out.l_bedrooms_office := bedrooms_office.lights;
|
||||
|
||||
// Dining Room
|
||||
diningRoom(switches := NVL_In.dinningRoom, relay_status := EtherCAT_RelayFeedback.diningRoom);
|
||||
EtherCAT_RelayFeedback.diningRoom := diningRoom.lights;
|
||||
NVL_Out.l_dinningRoom := diningRoom.lights;
|
||||
// Bedrooms - Hallway
|
||||
bedrooms_hallway(switches := NVL_In.bedrooms_hallway, relay_status := EtherCAT_RelayFeedback.bedrooms_hallway);
|
||||
EtherCAT_RelayFeedback.bedrooms_hallway := bedrooms_hallway.lights;
|
||||
NVL_Out.l_bedrooms_hallway := bedrooms_hallway.lights;
|
||||
|
||||
// Entrance
|
||||
entrance(switches := NVL_In.entrance, relay_status := EtherCAT_RelayFeedback.entrance);
|
||||
EtherCAT_RelayFeedback.entrance := entrance.lights;
|
||||
NVL_Out.l_entrance := entrance.lights;
|
||||
// Bedrooms - Laundry
|
||||
bedrooms_laundry(switches := NVL_In.bedrooms_laundry, relay_status := EtherCAT_RelayFeedback.bedrooms_laundry);
|
||||
EtherCAT_RelayFeedback.bedrooms_laundry := bedrooms_laundry.lights;
|
||||
NVL_Out.l_bedrooms_laundry := bedrooms_laundry.lights;
|
||||
|
||||
// Hallway
|
||||
hallway(switches := NVL_In.hallway, relay_status := EtherCAT_RelayFeedback.hallway);
|
||||
EtherCAT_RelayFeedback.hallway := hallway.lights;
|
||||
NVL_Out.l_hallway := hallway.lights;
|
||||
// Bedrooms - Shower
|
||||
bedrooms_shower(switches := NVL_In.bedrooms_shower, relay_status := EtherCAT_RelayFeedback.bedrooms_shower);
|
||||
EtherCAT_RelayFeedback.bedrooms_shower := bedrooms_shower.lights;
|
||||
NVL_Out.l_bedrooms_shower := bedrooms_shower.lights;
|
||||
|
||||
// Veranda
|
||||
veranda(switches := NVL_In.outVeranda, relay_status := EtherCAT_RelayFeedback.veranda);
|
||||
EtherCAT_RelayFeedback.veranda := veranda.lights;
|
||||
NVL_Out.l_outVeranda := veranda.lights;
|
||||
// Bedrooms - Bedroom
|
||||
bedrooms_bedroom(switches := NVL_In.bedrooms_bedroom, relay_status := EtherCAT_RelayFeedback.bedrooms_bedroom);
|
||||
EtherCAT_RelayFeedback.bedrooms_bedroom := bedrooms_bedroom.lights;
|
||||
NVL_Out.l_bedrooms_bedroom := bedrooms_bedroom.lights;
|
||||
|
||||
// Front
|
||||
front(switches := NVL_In.outFront, relay_status := EtherCAT_RelayFeedback.front);
|
||||
EtherCAT_RelayFeedback.front := front.lights;
|
||||
NVL_Out.l_outFront := front.lights;
|
||||
// Master Bedroom - Suite
|
||||
master_bedroom_suite(switches := NVL_In.master_bedroom_suite, relay_status := EtherCAT_RelayFeedback.master_bedroom_suite);
|
||||
EtherCAT_RelayFeedback.master_bedroom_suite := master_bedroom_suite.lights;
|
||||
NVL_Out.l_master_bedroom_suite := master_bedroom_suite.lights;
|
||||
|
||||
// Back
|
||||
back(switches := NVL_In.outBack, relay_status := EtherCAT_RelayFeedback.back);
|
||||
EtherCAT_RelayFeedback.back := back.lights;
|
||||
NVL_Out.l_outBack := back.lights;
|
||||
// Master Bedroom - Bathroom
|
||||
master_bedroom_bathroom(switches := NVL_In.master_bedroom_bathroom, relay_status := EtherCAT_RelayFeedback.master_bedroom_bathroom);
|
||||
EtherCAT_RelayFeedback.master_bedroom_bathroom := master_bedroom_bathroom.lights;
|
||||
NVL_Out.l_master_bedroom_bathroom := master_bedroom_bathroom.lights;
|
||||
|
||||
// Side
|
||||
side(switches := NVL_In.outSide, relay_status := EtherCAT_RelayFeedback.side);
|
||||
EtherCAT_RelayFeedback.side := side.lights;
|
||||
NVL_Out.l_outSide := side.lights;
|
||||
// Exterior - Veranda
|
||||
exterior_veranda(switches := NVL_In.exterior_veranda, relay_status := EtherCAT_RelayFeedback.exterior_veranda);
|
||||
EtherCAT_RelayFeedback.exterior_veranda := exterior_veranda.lights;
|
||||
NVL_Out.l_exterior_veranda := exterior_veranda.lights;
|
||||
|
||||
// Exterior - Entrance
|
||||
exterior_entrance(switches := NVL_In.exterior_entrance, relay_status := EtherCAT_RelayFeedback.exterior_entrance);
|
||||
EtherCAT_RelayFeedback.exterior_entrance := exterior_entrance.lights;
|
||||
NVL_Out.l_exterior_entrance := exterior_entrance.lights;
|
||||
|
||||
// Exterior - Yard
|
||||
exterior_yard(switches := NVL_In.exterior_yard, relay_status := EtherCAT_RelayFeedback.exterior_yard);
|
||||
EtherCAT_RelayFeedback.exterior_yard := exterior_yard.lights;
|
||||
NVL_Out.l_exterior_yard := exterior_yard.lights;
|
||||
|
||||
// ========== SECTION 2: BOILER ==========
|
||||
|
||||
|
||||
42
docs/Electrical/Ligts_Zones.csv
Normal file
42
docs/Electrical/Ligts_Zones.csv
Normal file
@@ -0,0 +1,42 @@
|
||||
#,Zone,Area,Light
|
||||
1,L1,Open Plan,Living Room Main
|
||||
2,L1,Open Plan,Living Room Spots
|
||||
3,L1,Open Plan,Dining room Main
|
||||
4,L1,Open Plan,Dining room Spots
|
||||
5,L1,Open Plan,Entrance Mirror
|
||||
6,L1,Open Plan,Entrance Main
|
||||
7,L1,Open Plan,Guest WC Main
|
||||
8,L1,Open Plan,Guiest WC Strip
|
||||
9,L1,Open Plan,Guest WC Fan
|
||||
10,L1,Open Plan,Living Room Strip
|
||||
11,L1,Open Plan,Living Room Strip
|
||||
12,L2,Ktchen,Kitchen Main
|
||||
13,L2,Ktchen,Island
|
||||
14,L2,Ktchen,Kitchen Cabinets
|
||||
15,L2,Ktchen,Fridge
|
||||
16,L2,Ktchen,Pantry
|
||||
17,L3,Bedrooms,Office Main
|
||||
18,L3,Bedrooms,Office Strip
|
||||
19,L3,Bedrooms,Hallway
|
||||
20,L3,Bedrooms,Wachine Machine
|
||||
21,L3,Bedrooms,Shower spots
|
||||
22,L3,Bedrooms,Shower fan
|
||||
23,L3,Bedrooms,Bedroom Main
|
||||
24,L3,Bedrooms,Bedroom Spots
|
||||
25,L4,Master Bedroom,Main
|
||||
26,L4,Master Bedroom,Spots
|
||||
27,L4,Master Bedroom,Strip
|
||||
28,L4,Master Bedroom,Door
|
||||
29,L4,Master Bedroom,Dresser
|
||||
30,L4,Master Bedroom,bathroom spots
|
||||
31,L4,Master Bedroom,bathroom fan
|
||||
32,L5,Exterior,Veranda
|
||||
33,L5,Exterior,BBQ
|
||||
34,L5,Exterior,Entrance Door
|
||||
35,L5,Exterior,Front Lights
|
||||
36,L5,Exterior,backyard flood light 1
|
||||
37,L5,Exterior,backyard flood light 2
|
||||
38,L5,Exterior,Master Bedroom flood light
|
||||
39,L5,exterior,Driveway
|
||||
40,L5,,
|
||||
41,L5,,
|
||||
|
40
docs/Electrical/lights_zones_canonical.csv
Normal file
40
docs/Electrical/lights_zones_canonical.csv
Normal file
@@ -0,0 +1,40 @@
|
||||
circuit_no,zone,area,room,light_type,index,light_no,codesys_in_key,codesys_out_key,nodered_room_key,ha_entity_id,source_light_label
|
||||
1,l1,open_plan,living_room,main,1,1,open_plan_living_room,l_open_plan_living_room,open_plan_living_room,input_boolean.open_plan_living_room_main_1,Living Room Main
|
||||
2,l1,open_plan,living_room,spots,1,2,open_plan_living_room,l_open_plan_living_room,open_plan_living_room,input_boolean.open_plan_living_room_spots_1,Living Room Spots
|
||||
3,l1,open_plan,dining_room,main,1,1,open_plan_dining_room,l_open_plan_dining_room,open_plan_dining_room,input_boolean.open_plan_dining_room_main_1,Dining room Main
|
||||
4,l1,open_plan,dining_room,spots,1,2,open_plan_dining_room,l_open_plan_dining_room,open_plan_dining_room,input_boolean.open_plan_dining_room_spots_1,Dining room Spots
|
||||
5,l1,open_plan,entrance,mirror,1,1,open_plan_entrance,l_open_plan_entrance,open_plan_entrance,input_boolean.open_plan_entrance_mirror_1,Entrance Mirror
|
||||
6,l1,open_plan,entrance,main,1,2,open_plan_entrance,l_open_plan_entrance,open_plan_entrance,input_boolean.open_plan_entrance_main_1,Entrance Main
|
||||
7,l1,open_plan,guest_wc,main,1,1,open_plan_guest_wc,l_open_plan_guest_wc,open_plan_guest_wc,input_boolean.open_plan_guest_wc_main_1,Guest WC Main
|
||||
8,l1,open_plan,guest_wc,strip,1,2,open_plan_guest_wc,l_open_plan_guest_wc,open_plan_guest_wc,input_boolean.open_plan_guest_wc_strip_1,Guiest WC Strip
|
||||
9,l1,open_plan,guest_wc,fan,1,3,open_plan_guest_wc,l_open_plan_guest_wc,open_plan_guest_wc,input_boolean.open_plan_guest_wc_fan_1,Guest WC Fan
|
||||
10,l1,open_plan,living_room,strip,1,3,open_plan_living_room,l_open_plan_living_room,open_plan_living_room,input_boolean.open_plan_living_room_strip_1,Living Room Strip
|
||||
11,l1,open_plan,living_room,strip,2,4,open_plan_living_room,l_open_plan_living_room,open_plan_living_room,input_boolean.open_plan_living_room_strip_2,Living Room Strip
|
||||
12,l2,kitchen,kitchen,main,1,1,kitchen_kitchen,l_kitchen_kitchen,kitchen_kitchen,input_boolean.kitchen_kitchen_main_1,Kitchen Main
|
||||
13,l2,kitchen,kitchen,island,1,2,kitchen_kitchen,l_kitchen_kitchen,kitchen_kitchen,input_boolean.kitchen_kitchen_island_1,Island
|
||||
14,l2,kitchen,kitchen,cabinets,1,3,kitchen_kitchen,l_kitchen_kitchen,kitchen_kitchen,input_boolean.kitchen_kitchen_cabinets_1,Kitchen Cabinets
|
||||
15,l2,kitchen,kitchen,fridge,1,4,kitchen_kitchen,l_kitchen_kitchen,kitchen_kitchen,input_boolean.kitchen_kitchen_fridge_1,Fridge
|
||||
16,l2,kitchen,pantry,main,1,1,kitchen_pantry,l_kitchen_pantry,kitchen_pantry,input_boolean.kitchen_pantry_main_1,Pantry
|
||||
17,l3,bedrooms,office,main,1,1,bedrooms_office,l_bedrooms_office,bedrooms_office,input_boolean.bedrooms_office_main_1,Office Main
|
||||
18,l3,bedrooms,office,strip,1,2,bedrooms_office,l_bedrooms_office,bedrooms_office,input_boolean.bedrooms_office_strip_1,Office Strip
|
||||
19,l3,bedrooms,hallway,main,1,1,bedrooms_hallway,l_bedrooms_hallway,bedrooms_hallway,input_boolean.bedrooms_hallway_main_1,Hallway
|
||||
20,l3,bedrooms,laundry,main,1,1,bedrooms_laundry,l_bedrooms_laundry,bedrooms_laundry,input_boolean.bedrooms_laundry_main_1,Wachine Machine
|
||||
21,l3,bedrooms,shower,spots,1,1,bedrooms_shower,l_bedrooms_shower,bedrooms_shower,input_boolean.bedrooms_shower_spots_1,Shower spots
|
||||
22,l3,bedrooms,shower,fan,1,2,bedrooms_shower,l_bedrooms_shower,bedrooms_shower,input_boolean.bedrooms_shower_fan_1,Shower fan
|
||||
23,l3,bedrooms,bedroom,main,1,1,bedrooms_bedroom,l_bedrooms_bedroom,bedrooms_bedroom,input_boolean.bedrooms_bedroom_main_1,Bedroom Main
|
||||
24,l3,bedrooms,bedroom,spots,1,2,bedrooms_bedroom,l_bedrooms_bedroom,bedrooms_bedroom,input_boolean.bedrooms_bedroom_spots_1,Bedroom Spots
|
||||
25,l4,master_bedroom,suite,main,1,1,master_bedroom_suite,l_master_bedroom_suite,master_bedroom_suite,input_boolean.master_bedroom_suite_main_1,Main
|
||||
26,l4,master_bedroom,suite,spots,1,2,master_bedroom_suite,l_master_bedroom_suite,master_bedroom_suite,input_boolean.master_bedroom_suite_spots_1,Spots
|
||||
27,l4,master_bedroom,suite,strip,1,3,master_bedroom_suite,l_master_bedroom_suite,master_bedroom_suite,input_boolean.master_bedroom_suite_strip_1,Strip
|
||||
28,l4,master_bedroom,suite,door,1,4,master_bedroom_suite,l_master_bedroom_suite,master_bedroom_suite,input_boolean.master_bedroom_suite_door_1,Door
|
||||
29,l4,master_bedroom,suite,dresser,1,5,master_bedroom_suite,l_master_bedroom_suite,master_bedroom_suite,input_boolean.master_bedroom_suite_dresser_1,Dresser
|
||||
30,l4,master_bedroom,bathroom,spots,1,1,master_bedroom_bathroom,l_master_bedroom_bathroom,master_bedroom_bathroom,input_boolean.master_bedroom_bathroom_spots_1,bathroom spots
|
||||
31,l4,master_bedroom,bathroom,fan,1,2,master_bedroom_bathroom,l_master_bedroom_bathroom,master_bedroom_bathroom,input_boolean.master_bedroom_bathroom_fan_1,bathroom fan
|
||||
32,l5,exterior,veranda,main,1,1,exterior_veranda,l_exterior_veranda,exterior_veranda,input_boolean.exterior_veranda_main_1,Veranda
|
||||
33,l5,exterior,yard,bbq,1,1,exterior_yard,l_exterior_yard,exterior_yard,input_boolean.exterior_yard_bbq_1,BBQ
|
||||
34,l5,exterior,entrance,door,1,1,exterior_entrance,l_exterior_entrance,exterior_entrance,input_boolean.exterior_entrance_door_1,Entrance Door
|
||||
35,l5,exterior,yard,front_lights,1,2,exterior_yard,l_exterior_yard,exterior_yard,input_boolean.exterior_yard_front_lights_1,Front Lights
|
||||
36,l5,exterior,yard,backyard_flood_light,1,3,exterior_yard,l_exterior_yard,exterior_yard,input_boolean.exterior_yard_backyard_flood_light_1,backyard flood light 1
|
||||
37,l5,exterior,yard,backyard_flood_light,2,4,exterior_yard,l_exterior_yard,exterior_yard,input_boolean.exterior_yard_backyard_flood_light_2,backyard flood light 2
|
||||
38,l5,exterior,yard,master_bedroom_flood_light,1,5,exterior_yard,l_exterior_yard,exterior_yard,input_boolean.exterior_yard_master_bedroom_flood_light_1,Master Bedroom flood light
|
||||
39,l5,exterior,yard,driveway,1,6,exterior_yard,l_exterior_yard,exterior_yard,input_boolean.exterior_yard_driveway_1,Driveway
|
||||
|
40
docs/Electrical/lights_zones_cleaned.csv
Normal file
40
docs/Electrical/lights_zones_cleaned.csv
Normal file
@@ -0,0 +1,40 @@
|
||||
#,zone,area,light
|
||||
1,l1,open_plan,living_room_main
|
||||
2,l1,open_plan,living_room_spots
|
||||
3,l1,open_plan,dining_room_main
|
||||
4,l1,open_plan,dining_room_spots
|
||||
5,l1,open_plan,entrance_mirror
|
||||
6,l1,open_plan,entrance_main
|
||||
7,l1,open_plan,guest_wc_main
|
||||
8,l1,open_plan,guest_wc_strip
|
||||
9,l1,open_plan,guest_wc_fan
|
||||
10,l1,open_plan,living_room_strip
|
||||
11,l1,open_plan,living_room_strip
|
||||
12,l2,kitchen,kitchen_main
|
||||
13,l2,kitchen,island
|
||||
14,l2,kitchen,kitchen_cabinets
|
||||
15,l2,kitchen,fridge
|
||||
16,l2,kitchen,pantry
|
||||
17,l3,bedrooms,office_main
|
||||
18,l3,bedrooms,office_strip
|
||||
19,l3,bedrooms,hallway
|
||||
20,l3,bedrooms,laundry
|
||||
21,l3,bedrooms,shower_spots
|
||||
22,l3,bedrooms,shower_fan
|
||||
23,l3,bedrooms,bedroom_main
|
||||
24,l3,bedrooms,bedroom_spots
|
||||
25,l4,master_bedroom,main
|
||||
26,l4,master_bedroom,spots
|
||||
27,l4,master_bedroom,strip
|
||||
28,l4,master_bedroom,door
|
||||
29,l4,master_bedroom,dresser
|
||||
30,l4,master_bedroom,bathroom_spots
|
||||
31,l4,master_bedroom,bathroom_fan
|
||||
32,l5,exterior,veranda
|
||||
33,l5,exterior,bbq
|
||||
34,l5,exterior,entrance_door
|
||||
35,l5,exterior,front_lights
|
||||
36,l5,exterior,backyard_flood_light_1
|
||||
37,l5,exterior,backyard_flood_light_2
|
||||
38,l5,exterior,master_bedroom_flood_light
|
||||
39,l5,exterior,driveway
|
||||
|
70
docs/Electrical/naming_rules.md
Normal file
70
docs/Electrical/naming_rules.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Uniform lighting naming rules
|
||||
|
||||
This project uses one canonical naming strategy for CODESYS, Node-RED, and Home Assistant.
|
||||
|
||||
## 1) Canonical token format
|
||||
|
||||
- All tokens are `snake_case`.
|
||||
- Allowed chars: `a-z`, `0-9`, `_`.
|
||||
- Normalize free text by:
|
||||
- lowercasing
|
||||
- trimming spaces
|
||||
- replacing spaces and dashes with `_`
|
||||
- collapsing repeated `_`
|
||||
- applying typo fixes (`ktchen -> kitchen`, `guiest -> guest`, `wachine -> laundry`)
|
||||
|
||||
## 2) Canonical data columns
|
||||
|
||||
Source of truth is `lights_zones_canonical.csv` with:
|
||||
|
||||
- `circuit_no`
|
||||
- `zone`
|
||||
- `area`
|
||||
- `room`
|
||||
- `light_type`
|
||||
- `index` (duplicate counter for same area+room+light_type)
|
||||
- `light_no` (PLC light channel inside room, 1..6)
|
||||
- `codesys_in_key`
|
||||
- `codesys_out_key`
|
||||
- `nodered_room_key`
|
||||
- `ha_entity_id`
|
||||
|
||||
## 3) ID generation formulas
|
||||
|
||||
- `codesys_in_key` = `<area>_<room>`
|
||||
- `codesys_out_key` = `l_<area>_<room>`
|
||||
- `nodered_room_key` = `<area>_<room>`
|
||||
- `ha_entity_id` = `input_boolean.<area>_<room>_<light_type>_<index>`
|
||||
|
||||
Examples:
|
||||
|
||||
- `input_boolean.open_plan_living_room_main_1`
|
||||
- `open_plan_guest_wc`
|
||||
- `l_master_bedroom_suite`
|
||||
|
||||
## 4) PLC mapping rule
|
||||
|
||||
- `light_no` maps to CODESYS `l_<N>` and Node-RED `light`:
|
||||
- `light_no = 1` -> `l_1`
|
||||
- `light_no = 2` -> `l_2`
|
||||
- ...
|
||||
- `light_no = 6` -> `l_6`
|
||||
|
||||
## 5) Reserved room keys used in this migration
|
||||
|
||||
- `open_plan_living_room`
|
||||
- `open_plan_dining_room`
|
||||
- `open_plan_entrance`
|
||||
- `open_plan_guest_wc`
|
||||
- `kitchen_kitchen`
|
||||
- `kitchen_pantry`
|
||||
- `bedrooms_office`
|
||||
- `bedrooms_hallway`
|
||||
- `bedrooms_laundry`
|
||||
- `bedrooms_shower`
|
||||
- `bedrooms_bedroom`
|
||||
- `master_bedroom_suite`
|
||||
- `master_bedroom_bathroom`
|
||||
- `exterior_veranda`
|
||||
- `exterior_entrance`
|
||||
- `exterior_yard`
|
||||
37
docs/Electrical/validation_report.md
Normal file
37
docs/Electrical/validation_report.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Validation report (uniform lighting naming migration)
|
||||
|
||||
## Static consistency checks completed
|
||||
|
||||
- Canonical lighting rows: `39` (`lights_zones_canonical.csv`)
|
||||
- CODESYS `NVL_In` room structs: `16`
|
||||
- CODESYS `NVL_Out` room structs: `16`
|
||||
- Node-RED `roomNames` entries: `16`
|
||||
- Node-RED `lightEntityMap` entries: `39`
|
||||
|
||||
## Mapping status
|
||||
|
||||
- `circuit_no -> area/room/type/index/light_no` is defined for all non-empty circuits.
|
||||
- `codesys_in_key` / `codesys_out_key` are defined for every canonical row.
|
||||
- `room-config.js` is aligned with canonical keys:
|
||||
- `roomNames` matches the 16-room CODESYS layout.
|
||||
- `lightEntityMap` has one entry per canonical row.
|
||||
- `entityToRoom` base keys map all canonical HA entity patterns.
|
||||
|
||||
## Verified constraints
|
||||
|
||||
- Canonical naming style: `snake_case`
|
||||
- Entity ID pattern: `input_boolean.<area>_<room>_<light_type>_<index>`
|
||||
- CODESYS legacy room names replaced in `codesys/src` runtime files:
|
||||
- `GVL_NVL_placeholders.gvl`
|
||||
- `GVL_IO.gvl`
|
||||
- `PLC_App.st`
|
||||
|
||||
## Residual runtime checks to perform on target system
|
||||
|
||||
Because this repository environment has no runtime binaries for Node-RED/CODESYS/HA validation, perform these on your deployed setup:
|
||||
|
||||
1. Deploy updated CODESYS project and confirm NVL sender/receiver symbol binding still resolves.
|
||||
2. Load updated `/root/.node-red/room-config.js` and redeploy flows.
|
||||
3. Import HA helpers from `lights_by_area_room_type_index.yaml`.
|
||||
4. Test one circuit per area end-to-end:
|
||||
- HA toggle -> Node-RED -> NVL_In -> PLC output -> NVL_Out -> HA sync.
|
||||
@@ -10,6 +10,11 @@ To avoid adding a new room or light in several places, use **one config file** t
|
||||
|
||||
**Config file:** [`node-red/config_files/room-config.js`](../../node-red/config_files/room-config.js) — exports `ROOM_CONFIG` with: **roomNames** (NVL SEND), **lightEntityMap** (NVL to HA Sync), **entityToRoom** (HA to NVL), **deviceToRoom** (Zigbee to NVL).
|
||||
|
||||
Canonical source-of-truth for this migration:
|
||||
|
||||
- Electrical mapping: [`../Electrical/lights_zones_canonical.csv`](../Electrical/lights_zones_canonical.csv)
|
||||
- Naming rules: [`../Electrical/naming_rules.md`](../Electrical/naming_rules.md)
|
||||
|
||||
**Server location:** `/root/.node-red/room-config.js` (uploaded via `scp`).
|
||||
|
||||
**Loader:** [`node-red/room-config-loader.js`](../../node-red/room-config-loader.js) — paste this code into a **Function node** named "Load room config". Connect an **Inject node** (once after 0.5 s) to it and deploy. It `require()`s the config file, clears the cache (so edits are picked up on redeploy), and sets `global.set('roomConfig', ...)`.
|
||||
@@ -39,14 +44,14 @@ Use a single list of room keys everywhere. Example (match your CODESYS NVL order
|
||||
|
||||
| Room key (Node-RED / NVL) | PLC NVL_Out (receive) | Lights per room |
|
||||
|---------------------------|------------------------|-----------------|
|
||||
| `livingRoom` | `l_livingRoom` | 1..6 |
|
||||
| `masterBedroom` | `l_masterBedroom` | 1..6 |
|
||||
| `kitchen` | `l_kitchen` | 1..6 |
|
||||
| `bathroom` | `l_bathroom` | 1..6 |
|
||||
| `open_plan_living_room` | `l_open_plan_living_room` | 1..6 |
|
||||
| `open_plan_guest_wc` | `l_open_plan_guest_wc` | 1..6 |
|
||||
| `kitchen_kitchen` | `l_kitchen_kitchen` | 1..6 |
|
||||
| `master_bedroom_suite` | `l_master_bedroom_suite` | 1..6 |
|
||||
| … | … | 1..6 |
|
||||
|
||||
- **NVL send (to PLC):** same keys as NVL_In in CODESYS (e.g. `livingRoom`, `masterBedroom`, … or `cmd_livingroom` for the test slot). Order and names must match the PLC.
|
||||
- **NVL receive (from PLC):** keys in the nvl-receive output (e.g. `l_livingRoom`, `light_livingRoom`) — use the same key in **LIGHT_ENTITY_MAP** in the sync function.
|
||||
- **NVL send (to PLC):** same keys as NVL_In in CODESYS (e.g. `open_plan_living_room`, `master_bedroom_suite`). Order and names must match the PLC.
|
||||
- **NVL receive (from PLC):** keys in the nvl-receive output (e.g. `l_open_plan_living_room`) — use the same key in **LIGHT_ENTITY_MAP** in the sync function.
|
||||
|
||||
Keep one list (e.g. in a comment or config file) and use it in:
|
||||
- **state-to-nvl-send-payload.js** → `roomNames`
|
||||
@@ -254,9 +259,9 @@ Add or remove lines to match your rooms and light counts. Entity IDs become `inp
|
||||
|
||||
Use a **consistent pattern** so you can derive room + light in Node-RED and in YAML:
|
||||
|
||||
- **Entity ID:** `input_boolean.<room>_<light>`
|
||||
Examples: `living_room_1`, `kitchen_2`, `master_bedroom_1`.
|
||||
- Then in HA to NVL you can parse: room from the first part, light from the trailing number.
|
||||
- **Entity ID:** `input_boolean.<area>_<room>_<light_type>_<index>`
|
||||
Examples: `input_boolean.open_plan_living_room_main_1`, `input_boolean.kitchen_kitchen_island_1`, `input_boolean.exterior_yard_driveway_1`.
|
||||
- In HA to NVL, parse room mapping from `entityToRoom` using the base without the trailing `_<index>`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
This guide covers how to create the light/switch entities that Node-RED and the PLC use, and how to assign them to **rooms** (HA **Areas**) so you can manage and display them by room.
|
||||
|
||||
Canonical naming in this project is now:
|
||||
|
||||
- `input_boolean.<area>_<room>_<light_type>_<index>`
|
||||
- Example: `input_boolean.open_plan_living_room_main_1`
|
||||
|
||||
Pre-generated helper YAML for the current electrical plan:
|
||||
|
||||
- [`lights_by_area_room_type_index.yaml`](lights_by_area_room_type_index.yaml)
|
||||
|
||||
---
|
||||
|
||||
## 1. Concepts
|
||||
@@ -41,18 +50,13 @@ Create one file per room (or one file with sections) so entities are grouped by
|
||||
|
||||
```yaml
|
||||
# PLC/Node-RED lights – entity_id must match room-config.js (entityToRoom, lightEntityMap)
|
||||
# Naming: <room>_<light_num> e.g. living_room_1, kitchen_2
|
||||
# Naming: <area>_<room>_<light_type>_<index> e.g. open_plan_living_room_main_1
|
||||
|
||||
input_boolean:
|
||||
# Living room
|
||||
living_room_1: { name: Living Room 1 }
|
||||
living_room_2: { name: Living Room 2 }
|
||||
# Kitchen
|
||||
kitchen_1: { name: Kitchen 1 }
|
||||
kitchen_2: { name: Kitchen 2 }
|
||||
# Hallway
|
||||
hallway_1: { name: Hallway 1 }
|
||||
# Add more: master_bedroom_1, bathroom_1, entrance_1, etc.
|
||||
open_plan_living_room_main_1: { name: Open Plan Living Room Main 1 }
|
||||
open_plan_living_room_spots_1: { name: Open Plan Living Room Spots 1 }
|
||||
kitchen_kitchen_main_1: { name: Kitchen Main 1 }
|
||||
bedrooms_hallway_main_1: { name: Bedrooms Hallway Main 1 }
|
||||
```
|
||||
|
||||
Ensure `configuration.yaml` has:
|
||||
@@ -62,7 +66,7 @@ homeassistant:
|
||||
packages: !include_dir_named packages
|
||||
```
|
||||
|
||||
Restart Home Assistant. All entities are created. Entity IDs will be `input_boolean.living_room_1`, etc.
|
||||
Restart Home Assistant. All entities are created. Entity IDs will be `input_boolean.open_plan_living_room_main_1`, etc.
|
||||
|
||||
### Option B: UI (one by one)
|
||||
|
||||
@@ -99,9 +103,9 @@ Use the **same entity_id and room logic** in both places.
|
||||
|
||||
**Naming convention that works well:**
|
||||
|
||||
- Entity ID: `input_boolean.<room>_<number>`
|
||||
Examples: `living_room_1`, `kitchen_2`, `hallway_1`.
|
||||
- In **entityToRoom** use the part without the number: `living_room`, `kitchen`, `hallway` (and any alias like `living_room_new` → `cmd_livingroom`).
|
||||
- Entity ID: `input_boolean.<area>_<room>_<light_type>_<index>`
|
||||
Examples: `open_plan_living_room_main_1`, `kitchen_kitchen_island_1`, `exterior_yard_driveway_1`.
|
||||
- In **entityToRoom** use the part without trailing `_<index>`, e.g. `open_plan_living_room_main` or `exterior_yard_driveway`.
|
||||
|
||||
When you add a new light in HA (new entity_id), add or update:
|
||||
|
||||
|
||||
47
docs/integration/lights_by_area_room_type_index.yaml
Normal file
47
docs/integration/lights_by_area_room_type_index.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
# Home Assistant helpers for the canonical lighting naming model.
|
||||
# Naming: input_boolean.<area>_<room>_<light_type>_<index>
|
||||
|
||||
input_boolean:
|
||||
open_plan_living_room_main_1: { name: Open Plan Living Room Main 1 }
|
||||
open_plan_living_room_spots_1: { name: Open Plan Living Room Spots 1 }
|
||||
open_plan_dining_room_main_1: { name: Open Plan Dining Room Main 1 }
|
||||
open_plan_dining_room_spots_1: { name: Open Plan Dining Room Spots 1 }
|
||||
open_plan_entrance_mirror_1: { name: Open Plan Entrance Mirror 1 }
|
||||
open_plan_entrance_main_1: { name: Open Plan Entrance Main 1 }
|
||||
open_plan_guest_wc_main_1: { name: Open Plan Guest WC Main 1 }
|
||||
open_plan_guest_wc_strip_1: { name: Open Plan Guest WC Strip 1 }
|
||||
open_plan_guest_wc_fan_1: { name: Open Plan Guest WC Fan 1 }
|
||||
open_plan_living_room_strip_1: { name: Open Plan Living Room Strip 1 }
|
||||
open_plan_living_room_strip_2: { name: Open Plan Living Room Strip 2 }
|
||||
|
||||
kitchen_kitchen_main_1: { name: Kitchen Main 1 }
|
||||
kitchen_kitchen_island_1: { name: Kitchen Island 1 }
|
||||
kitchen_kitchen_cabinets_1: { name: Kitchen Cabinets 1 }
|
||||
kitchen_kitchen_fridge_1: { name: Kitchen Fridge 1 }
|
||||
kitchen_pantry_main_1: { name: Kitchen Pantry Main 1 }
|
||||
|
||||
bedrooms_office_main_1: { name: Bedrooms Office Main 1 }
|
||||
bedrooms_office_strip_1: { name: Bedrooms Office Strip 1 }
|
||||
bedrooms_hallway_main_1: { name: Bedrooms Hallway Main 1 }
|
||||
bedrooms_laundry_main_1: { name: Bedrooms Laundry Main 1 }
|
||||
bedrooms_shower_spots_1: { name: Bedrooms Shower Spots 1 }
|
||||
bedrooms_shower_fan_1: { name: Bedrooms Shower Fan 1 }
|
||||
bedrooms_bedroom_main_1: { name: Bedrooms Bedroom Main 1 }
|
||||
bedrooms_bedroom_spots_1: { name: Bedrooms Bedroom Spots 1 }
|
||||
|
||||
master_bedroom_suite_main_1: { name: Master Bedroom Suite Main 1 }
|
||||
master_bedroom_suite_spots_1: { name: Master Bedroom Suite Spots 1 }
|
||||
master_bedroom_suite_strip_1: { name: Master Bedroom Suite Strip 1 }
|
||||
master_bedroom_suite_door_1: { name: Master Bedroom Suite Door 1 }
|
||||
master_bedroom_suite_dresser_1: { name: Master Bedroom Suite Dresser 1 }
|
||||
master_bedroom_bathroom_spots_1: { name: Master Bedroom Bathroom Spots 1 }
|
||||
master_bedroom_bathroom_fan_1: { name: Master Bedroom Bathroom Fan 1 }
|
||||
|
||||
exterior_veranda_main_1: { name: Exterior Veranda Main 1 }
|
||||
exterior_entrance_door_1: { name: Exterior Entrance Door 1 }
|
||||
exterior_yard_bbq_1: { name: Exterior Yard BBQ 1 }
|
||||
exterior_yard_front_lights_1: { name: Exterior Yard Front Lights 1 }
|
||||
exterior_yard_backyard_flood_light_1: { name: Exterior Yard Backyard Flood Light 1 }
|
||||
exterior_yard_backyard_flood_light_2: { name: Exterior Yard Backyard Flood Light 2 }
|
||||
exterior_yard_master_bedroom_flood_light_1: { name: Exterior Yard Master Bedroom Flood Light 1 }
|
||||
exterior_yard_driveway_1: { name: Exterior Yard Driveway 1 }
|
||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
ccc/**
|
||||
/**
|
||||
* Single source of truth for rooms and lights.
|
||||
* Lives on the Node-RED server at /root/.node-red/room-config.js
|
||||
* All function nodes use: global.get('roomConfig')
|
||||
@@ -9,56 +9,111 @@ ccc/**
|
||||
const ROOM_CONFIG = {
|
||||
// Order must match CODESYS NVL_In. Used by NVL SEND (state-to-nvl-send-payload).
|
||||
roomNames: [
|
||||
'cmd_livingroom',
|
||||
'cmd_out', // add other NVL room keys as needed
|
||||
// 'masterBedroom',
|
||||
// 'masterBathroom',
|
||||
// 'bedroom_1',
|
||||
// 'bedroom_2',
|
||||
// 'bathroom',
|
||||
// 'guestWc',
|
||||
// 'kitchen',
|
||||
// 'pantry',
|
||||
// 'livingRoom',
|
||||
// 'dinningRoom',
|
||||
// 'entrance',
|
||||
// 'hallway',
|
||||
// 'outVeranda',
|
||||
// 'outFront',
|
||||
// 'outBack',
|
||||
// 'outSide',
|
||||
'open_plan_living_room',
|
||||
'open_plan_dining_room',
|
||||
'open_plan_entrance',
|
||||
'open_plan_guest_wc',
|
||||
'kitchen_kitchen',
|
||||
'kitchen_pantry',
|
||||
'bedrooms_office',
|
||||
'bedrooms_hallway',
|
||||
'bedrooms_laundry',
|
||||
'bedrooms_shower',
|
||||
'bedrooms_bedroom',
|
||||
'master_bedroom_suite',
|
||||
'master_bedroom_bathroom',
|
||||
'exterior_veranda',
|
||||
'exterior_entrance',
|
||||
'exterior_yard',
|
||||
],
|
||||
|
||||
// PLC → HA sync. room = key in nvl-receive payload, light = 1..6, entityId = HA entity.
|
||||
lightEntityMap: [
|
||||
{ room: 'light_livingRoom', light: 1, entityId: 'input_boolean.living_room_new' },
|
||||
// { room: 'light_livingRoom', light: 2, entityId: 'input_boolean.living_room_2' },
|
||||
// { room: 'l_kitchen', light: 1, entityId: 'input_boolean.kitchen_1' },
|
||||
{ room: 'l_open_plan_living_room', light: 1, entityId: 'input_boolean.open_plan_living_room_main_1' },
|
||||
{ room: 'l_open_plan_living_room', light: 2, entityId: 'input_boolean.open_plan_living_room_spots_1' },
|
||||
{ room: 'l_open_plan_dining_room', light: 1, entityId: 'input_boolean.open_plan_dining_room_main_1' },
|
||||
{ room: 'l_open_plan_dining_room', light: 2, entityId: 'input_boolean.open_plan_dining_room_spots_1' },
|
||||
{ room: 'l_open_plan_entrance', light: 1, entityId: 'input_boolean.open_plan_entrance_mirror_1' },
|
||||
{ room: 'l_open_plan_entrance', light: 2, entityId: 'input_boolean.open_plan_entrance_main_1' },
|
||||
{ room: 'l_open_plan_guest_wc', light: 1, entityId: 'input_boolean.open_plan_guest_wc_main_1' },
|
||||
{ room: 'l_open_plan_guest_wc', light: 2, entityId: 'input_boolean.open_plan_guest_wc_strip_1' },
|
||||
{ room: 'l_open_plan_guest_wc', light: 3, entityId: 'input_boolean.open_plan_guest_wc_fan_1' },
|
||||
{ room: 'l_open_plan_living_room', light: 3, entityId: 'input_boolean.open_plan_living_room_strip_1' },
|
||||
{ room: 'l_open_plan_living_room', light: 4, entityId: 'input_boolean.open_plan_living_room_strip_2' },
|
||||
{ room: 'l_kitchen_kitchen', light: 1, entityId: 'input_boolean.kitchen_kitchen_main_1' },
|
||||
{ room: 'l_kitchen_kitchen', light: 2, entityId: 'input_boolean.kitchen_kitchen_island_1' },
|
||||
{ room: 'l_kitchen_kitchen', light: 3, entityId: 'input_boolean.kitchen_kitchen_cabinets_1' },
|
||||
{ room: 'l_kitchen_kitchen', light: 4, entityId: 'input_boolean.kitchen_kitchen_fridge_1' },
|
||||
{ room: 'l_kitchen_pantry', light: 1, entityId: 'input_boolean.kitchen_pantry_main_1' },
|
||||
{ room: 'l_bedrooms_office', light: 1, entityId: 'input_boolean.bedrooms_office_main_1' },
|
||||
{ room: 'l_bedrooms_office', light: 2, entityId: 'input_boolean.bedrooms_office_strip_1' },
|
||||
{ room: 'l_bedrooms_hallway', light: 1, entityId: 'input_boolean.bedrooms_hallway_main_1' },
|
||||
{ room: 'l_bedrooms_laundry', light: 1, entityId: 'input_boolean.bedrooms_laundry_main_1' },
|
||||
{ room: 'l_bedrooms_shower', light: 1, entityId: 'input_boolean.bedrooms_shower_spots_1' },
|
||||
{ room: 'l_bedrooms_shower', light: 2, entityId: 'input_boolean.bedrooms_shower_fan_1' },
|
||||
{ room: 'l_bedrooms_bedroom', light: 1, entityId: 'input_boolean.bedrooms_bedroom_main_1' },
|
||||
{ room: 'l_bedrooms_bedroom', light: 2, entityId: 'input_boolean.bedrooms_bedroom_spots_1' },
|
||||
{ room: 'l_master_bedroom_suite', light: 1, entityId: 'input_boolean.master_bedroom_suite_main_1' },
|
||||
{ room: 'l_master_bedroom_suite', light: 2, entityId: 'input_boolean.master_bedroom_suite_spots_1' },
|
||||
{ room: 'l_master_bedroom_suite', light: 3, entityId: 'input_boolean.master_bedroom_suite_strip_1' },
|
||||
{ room: 'l_master_bedroom_suite', light: 4, entityId: 'input_boolean.master_bedroom_suite_door_1' },
|
||||
{ room: 'l_master_bedroom_suite', light: 5, entityId: 'input_boolean.master_bedroom_suite_dresser_1' },
|
||||
{ room: 'l_master_bedroom_bathroom', light: 1, entityId: 'input_boolean.master_bedroom_bathroom_spots_1' },
|
||||
{ room: 'l_master_bedroom_bathroom', light: 2, entityId: 'input_boolean.master_bedroom_bathroom_fan_1' },
|
||||
{ room: 'l_exterior_veranda', light: 1, entityId: 'input_boolean.exterior_veranda_main_1' },
|
||||
{ room: 'l_exterior_yard', light: 1, entityId: 'input_boolean.exterior_yard_bbq_1' },
|
||||
{ room: 'l_exterior_entrance', light: 1, entityId: 'input_boolean.exterior_entrance_door_1' },
|
||||
{ room: 'l_exterior_yard', light: 2, entityId: 'input_boolean.exterior_yard_front_lights_1' },
|
||||
{ room: 'l_exterior_yard', light: 3, entityId: 'input_boolean.exterior_yard_backyard_flood_light_1' },
|
||||
{ room: 'l_exterior_yard', light: 4, entityId: 'input_boolean.exterior_yard_backyard_flood_light_2' },
|
||||
{ room: 'l_exterior_yard', light: 5, entityId: 'input_boolean.exterior_yard_master_bedroom_flood_light_1' },
|
||||
{ room: 'l_exterior_yard', light: 6, entityId: 'input_boolean.exterior_yard_driveway_1' },
|
||||
],
|
||||
|
||||
// HA entity_id substring (after domain.) without trailing _N → NVL room key. For HA to NVL.
|
||||
entityToRoom: {
|
||||
// living_room: 'livingRoom',
|
||||
living_room_new: 'cmd_livingroom',
|
||||
// kitchen: 'kitchen',
|
||||
// master_bedroom: 'masterBedroom',
|
||||
// bathroom: 'bathroom',
|
||||
// bedroom_1: 'bedroom_1',
|
||||
// bedroom_2: 'bedroom_2',
|
||||
// dinning_room: 'dinningRoom',
|
||||
// entrance: 'entrance',
|
||||
// hallway: 'hallway',
|
||||
// pantry: 'pantry',
|
||||
// guest_wc: 'guestWc',
|
||||
// out_veranda: 'outVeranda',
|
||||
// out_front: 'outFront',
|
||||
// out_back: 'outBack',
|
||||
// out_side: 'outSide',
|
||||
open_plan_living_room_main: 'open_plan_living_room',
|
||||
open_plan_living_room_spots: 'open_plan_living_room',
|
||||
open_plan_living_room_strip: 'open_plan_living_room',
|
||||
open_plan_dining_room_main: 'open_plan_dining_room',
|
||||
open_plan_dining_room_spots: 'open_plan_dining_room',
|
||||
open_plan_entrance_mirror: 'open_plan_entrance',
|
||||
open_plan_entrance_main: 'open_plan_entrance',
|
||||
open_plan_guest_wc_main: 'open_plan_guest_wc',
|
||||
open_plan_guest_wc_strip: 'open_plan_guest_wc',
|
||||
open_plan_guest_wc_fan: 'open_plan_guest_wc',
|
||||
kitchen_kitchen_main: 'kitchen_kitchen',
|
||||
kitchen_kitchen_island: 'kitchen_kitchen',
|
||||
kitchen_kitchen_cabinets: 'kitchen_kitchen',
|
||||
kitchen_kitchen_fridge: 'kitchen_kitchen',
|
||||
kitchen_pantry_main: 'kitchen_pantry',
|
||||
bedrooms_office_main: 'bedrooms_office',
|
||||
bedrooms_office_strip: 'bedrooms_office',
|
||||
bedrooms_hallway_main: 'bedrooms_hallway',
|
||||
bedrooms_laundry_main: 'bedrooms_laundry',
|
||||
bedrooms_shower_spots: 'bedrooms_shower',
|
||||
bedrooms_shower_fan: 'bedrooms_shower',
|
||||
bedrooms_bedroom_main: 'bedrooms_bedroom',
|
||||
bedrooms_bedroom_spots: 'bedrooms_bedroom',
|
||||
master_bedroom_suite_main: 'master_bedroom_suite',
|
||||
master_bedroom_suite_spots: 'master_bedroom_suite',
|
||||
master_bedroom_suite_strip: 'master_bedroom_suite',
|
||||
master_bedroom_suite_door: 'master_bedroom_suite',
|
||||
master_bedroom_suite_dresser: 'master_bedroom_suite',
|
||||
master_bedroom_bathroom_spots: 'master_bedroom_bathroom',
|
||||
master_bedroom_bathroom_fan: 'master_bedroom_bathroom',
|
||||
exterior_veranda_main: 'exterior_veranda',
|
||||
exterior_yard_bbq: 'exterior_yard',
|
||||
exterior_entrance_door: 'exterior_entrance',
|
||||
exterior_yard_front_lights: 'exterior_yard',
|
||||
exterior_yard_backyard_flood_light: 'exterior_yard',
|
||||
exterior_yard_master_bedroom_flood_light: 'exterior_yard',
|
||||
exterior_yard_driveway: 'exterior_yard',
|
||||
},
|
||||
|
||||
// // Zigbee: friendly_name → single room (fallback when switchBindings missing).
|
||||
// deviceToRoom: {
|
||||
// 'Office Switch': 'cmd_livingroom',
|
||||
// 'Office Switch': 'open_plan_living_room',
|
||||
// },
|
||||
|
||||
// When using a multi-device Zigbee node, payload is keyed by IEEE (e.g. 0xa4c138a5b9771b05). Map IEEE → friendly name so switchBindings by name still works.
|
||||
@@ -68,7 +123,7 @@ const ROOM_CONFIG = {
|
||||
|
||||
// Optional: bind by IEEE instead of friendly name (same shape as switchBindings). Use if the node never sends friendly_name.
|
||||
// switchBindingsByDeviceId: {
|
||||
// '0xa4c138a5b9771b05': { 1: { room: 'cmd_livingroom', light: 1 }, 2: { room: 'cmd_out', light: 2 } },
|
||||
// '0xa4c138a5b9771b05': { 1: { room: 'open_plan_living_room', light: 1 }, 2: { room: 'open_plan_dining_room', light: 1 } },
|
||||
// },
|
||||
|
||||
/**
|
||||
@@ -78,8 +133,8 @@ const ROOM_CONFIG = {
|
||||
*/
|
||||
switchBindings: {
|
||||
'Office Switch': {
|
||||
1: { room: 'cmd_livingroom', light: 1 }, // button 1 → light 1
|
||||
2: { room: 'cmd_livingroom', light: 2 }, // button 2 → light 1 (same light; other switches could do button 2 → light 2)
|
||||
1: { room: 'open_plan_living_room', light: 1 },
|
||||
2: { room: 'open_plan_dining_room', light: 1 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,17 +4,34 @@
|
||||
// 3. Replace the ROOM_CONFIG below with your paste. Keep the two lines at the end.
|
||||
|
||||
const ROOM_CONFIG = {
|
||||
roomNames: ['cmd_livingroom', 'cmd_out'],
|
||||
lightEntityMap: [
|
||||
{ room: 'light_livingRoom', light: 1, entityId: 'input_boolean.living_room_new' },
|
||||
roomNames: [
|
||||
'open_plan_living_room',
|
||||
'open_plan_dining_room',
|
||||
'open_plan_entrance',
|
||||
'open_plan_guest_wc',
|
||||
'kitchen_kitchen',
|
||||
'kitchen_pantry',
|
||||
'bedrooms_office',
|
||||
'bedrooms_hallway',
|
||||
'bedrooms_laundry',
|
||||
'bedrooms_shower',
|
||||
'bedrooms_bedroom',
|
||||
'master_bedroom_suite',
|
||||
'master_bedroom_bathroom',
|
||||
'exterior_veranda',
|
||||
'exterior_entrance',
|
||||
'exterior_yard',
|
||||
],
|
||||
entityToRoom: { living_room_new: 'cmd_livingroom' },
|
||||
deviceToRoom: { 'Office Switch': 'cmd_livingroom' },
|
||||
lightEntityMap: [
|
||||
{ room: 'l_open_plan_living_room', light: 1, entityId: 'input_boolean.open_plan_living_room_main_1' },
|
||||
],
|
||||
entityToRoom: { open_plan_living_room_main: 'open_plan_living_room' },
|
||||
deviceToRoom: { 'Office Switch': 'open_plan_living_room' },
|
||||
deviceIdToName: {},
|
||||
switchBindings: {
|
||||
'Office Switch': {
|
||||
1: { room: 'cmd_livingroom', light: 1 },
|
||||
2: { room: 'cmd_livingroom', light: 1 },
|
||||
1: { room: 'open_plan_living_room', light: 1 },
|
||||
2: { room: 'open_plan_dining_room', light: 1 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user