Files
kkelomatic_home/docs/integration/all-lights-and-rooms.md
nearxos 714aa84504 Add Node-RED documentation for lights and rooms integration
- Introduced new sections in README.md for Node-RED flows related to living room lighting and room management.
- Added links to specific documentation for living room flow, all lights and rooms configuration, and living room analysis.
- Enhanced overall organization of the README to improve user navigation and understanding of Node-RED integration with Home Assistant.

This update enriches the documentation for users implementing Node-RED in their home automation setups.
2026-02-08 17:38:24 +02:00

11 KiB
Raw Blame History

Using the flow for all lights and rooms

This doc explains how to scale the working “test light” setup to all your lights and rooms: what to configure in Node-RED, what to do in Home Assistant (including creating many entities efficiently), and how it fits with the PLC.


1. How it works (recap)

  • HA / Zigbee → Node-RED updates flow.nvlInState.rooms.<roomKey> (e.g. ha_l1_on, zigbee_sw2).
  • NVL SEND builds the payload from all room keys and sends to the PLC.
  • PLC drives relays; sends back light state in NVL_Out.
  • NVL to HA Sync reads NVL_Out and calls HA turn_on / turn_off so the UI matches the real state.

To support all lights you need:

  1. A room list that matches the PLC (NVL_In / NVL_Out).
  2. Node-RED: one state key per room, and mappings: HA entity → room + light index, Zigbee device → room, PLC payload key → HA entity.
  3. HA: one entity per light (or per zone) that you want to show in the UI and control.

2. Room list (align with PLC)

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
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.

Keep one list (e.g. in a comment or config file) and use it in:

  • state-to-nvl-send-payload.jsroomNames
  • NVL to HA SyncLIGHT_ENTITY_MAP[].room (must match nvl-receive payload keys)
  • HA to NVL / Zigbee to NVL → which room key to write to

3. Node-RED configuration for all lights

3.1 NVL SEND (state-to-nvl-send-payload.js)

Add every room that the PLC expects to the roomNames array. Each room uses the same struct_room_cmds shape.

const roomNames = [
  'livingRoom',      // or cmd_livingroom if thats your test slot
  'masterBedroom',
  'kitchen',
  'bathroom',
  'bedroom_1',
  'bedroom_2',
  'dinningRoom',
  'entrance',
  'hallway',
  'pantry',
  'guestWc',
  'outVeranda',
  'outFront',
  'outBack',
  'outSide',
];

Match this list to your CODESYS NVL_In layout and order.

3.2 HA → PLC: which room and light?

You have two patterns:

Option A One trigger-state per room (current pattern)

  • One tab (or subflow) per room.
  • trigger-state watches that rooms entities (e.g. input_boolean.living_room_1, input_boolean.living_room_2).
  • HA to NVL has ROOM_NAME = 'livingRoom' (or that rooms key).
  • Replicate for each room (or use a subflow and pass ROOM_NAME in msg).

Option B One trigger-state for all entities (recommended for many lights)

  • Single trigger-state (or events: state) that watches all your light/input_boolean entities (e.g. by substring input_boolean. or a list of entity IDs).
  • HA to NVL gets msg.topic = entity_id (e.g. input_boolean.kitchen_2).
  • In the function, derive room + light from the entity_id using a small config:
// Example: entity_id "input_boolean.kitchen_2" → room "kitchen", light 2
const ENTITY_TO_ROOM = {
  'living_room': 'livingRoom',
  'kitchen': 'kitchen',
  'master_bedroom': 'masterBedroom',
  'bathroom': 'bathroom',
  // ...
};
// Parse: input_boolean.living_room_1 → room livingRoom, light 1
const parts = (msg.topic || '').split('.');
const name = (parts[1] || '').replace(/_(\d+)$/, '_$1');
const roomKey = ENTITY_TO_ROOM[name.split('_').slice(0, -1).join('_')] || name;
const lightNum = parseInt((name.match(/_(\d+)$/) || [,'1'])[1], 10) || 1;

Then set state.rooms[roomKey]['ha_l' + lightNum + '_on'] or _off as you do now. So one HA to NVL function can serve all entities if you pass the right msg.topic and use a consistent naming (e.g. room_light_N).

3.3 Zigbee → PLC: which room?

  • Each zigbee2mqtt-in is one physical switch.
  • Zigbee to NVL must know which room that switch belongs to.
  • Either: one Zigbee to NVL per room (each has ROOM_NAME = 'kitchen' etc.) and wire each switch to the right one, or one Zigbee to NVL that gets device/entity from msg and uses a device → room map (e.g. friendly_name or device_id → room key).

Example map in Zigbee to NVL:

const DEVICE_TO_ROOM = {
  'Living Room Door Switch': 'livingRoom',
  'Office Switch': 'livingRoom',  // or 'office' if you add that room
  'Kitchen Switch': 'kitchen',
  // ...
};
const roomKey = DEVICE_TO_ROOM[msg.payload?.friendly_name || ''] || 'livingRoom';

Then use roomKey instead of a fixed ROOM_NAME when writing to state.rooms[roomKey].

3.4 PLC → HA: NVL to HA Sync (LIGHT_ENTITY_MAP)

Add one entry per light you want to sync from the PLC back to HA. The room key must match what nvl-receive puts in msg.payload (e.g. l_livingRoom or light_livingRoom).

const LIGHT_ENTITY_MAP = [
  { room: 'light_livingRoom', light: 1, entityId: 'input_boolean.living_room_1' },
  { room: 'light_livingRoom', light: 2, entityId: 'input_boolean.living_room_2' },
  { room: 'l_kitchen', light: 1, entityId: 'input_boolean.kitchen_1' },
  { room: 'l_kitchen', light: 2, entityId: 'input_boolean.kitchen_2' },
  { room: 'l_masterBedroom', light: 1, entityId: 'input_boolean.master_bedroom_1' },
  // ... one line per light
];

Generate this list from your room list + lights per room (e.g. 16 rooms × up to 6 lights = up to 96 entries; only add those you actually use).


4. Home Assistant: creating entities for all lights

You need one HA entity per light (or per zone) that Node-RED and the PLC treat as one target. Two common choices:

  • input_boolean simple on/off, good for “virtual” switches that only drive the PLC.
  • light (template or generic) if you want them to appear as lights in the HA UI and in dashboards.

You can create them one by one or in bulk.

4.1 Efficient way: YAML (many at once)

Define all helpers in YAML so HA creates them at startup. No need to click 50 times in the UI.

Option 1 configuration.yaml (or a package)

input_boolean:
  living_room_1:
    name: Living Room Light 1
  living_room_2:
    name: Living Room Light 2
  kitchen_1:
    name: Kitchen Light 1
  kitchen_2:
    name: Kitchen Light 2
  master_bedroom_1:
    name: Master Bedroom Light 1
  # ... add one block per entity
  • Entity IDs will be input_boolean.living_room_1, input_boolean.kitchen_1, etc.
  • Match these exactly in Node-RED (trigger-state and LIGHT_ENTITY_MAP).

Option 2 Package file (recommended)

Create a file under your config, e.g. packages/lights_nodered.yaml:

input_boolean:
  living_room_1:    { name: Living Room 1 }
  living_room_2:    { name: Living Room 2 }
  kitchen_1:        { name: Kitchen 1 }
  kitchen_2:        { name: Kitchen 2 }
  master_bedroom_1: { name: Master Bedroom 1 }
  bathroom_1:       { name: Bathroom 1 }
  # Add every light you want to control

In configuration.yaml ensure packages are loaded:

homeassistant:
  packages: !include_dir_named packages

Restart HA. All entities are created in one go. Then in Node-RED use the same IDs in your trigger and in LIGHT_ENTITY_MAP.

Example copy and adapt (save as packages/lights_nodered.yaml in your HA config folder):

# Input booleans for PLC lights. Entity IDs must match Node-RED LIGHT_ENTITY_MAP and trigger-state.
input_boolean:
  living_room_1:    { name: Living Room 1 }
  living_room_2:    { name: Living Room 2 }
  kitchen_1:        { name: Kitchen 1 }
  kitchen_2:        { name: Kitchen 2 }
  master_bedroom_1: { name: Master Bedroom 1 }
  master_bedroom_2: { name: Master Bedroom 2 }
  bathroom_1:       { name: Bathroom 1 }
  bedroom_1_1:      { name: Bedroom 1 Light 1 }
  bedroom_2_1:      { name: Bedroom 2 Light 1 }
  dinning_room_1:   { name: Dining Room 1 }
  entrance_1:       { name: Entrance 1 }
  hallway_1:        { name: Hallway 1 }
  pantry_1:         { name: Pantry 1 }
  guest_wc_1:       { name: Guest WC 1 }
  out_veranda_1:    { name: Veranda 1 }
  out_front_1:      { name: Front 1 }
  out_back_1:       { name: Back 1 }
  out_side_1:       { name: Side 1 }

Add or remove lines to match your rooms and light counts. Entity IDs become input_boolean.living_room_1, etc.

4.2 UI way (one by one)

  • SettingsDevices & servicesHelpersCreate HelperToggle.
  • Create a toggle, set name (e.g. “Living Room 1”). HA will assign an entity_id like input_boolean.living_room_1 (or similar, depending on the name you give).
  • Repeat for each light. Slower, but no YAML.

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.

5. Checklist: rolling out to all lights

Step Where Action
1 CODESYS Ensure NVL_In / NVL_Out include all rooms and lights in the order you use in Node-RED.
2 HA Create all entities (YAML package or UI). Use a clear naming scheme (e.g. room_light_N).
3 Node-RED NVL SEND Set roomNames in state-to-nvl-send-payload.js to the full list of room keys (same order as PLC).
4 Node-RED HA to NVL Either duplicate the flow per room (Option A) or use one flow and derive room + light from msg.topic (Option B). Ensure every HA entity is mapped to a room key and light index.
5 Node-RED Zigbee to NVL Map each Zigbee device (by name or id) to a room key so the correct state.rooms[roomKey] is updated.
6 Node-RED NVL to HA Sync Fill LIGHT_ENTITY_MAP with one entry per light: room (payload key from nvl-receive), light (1..6), entityId (HA entity).
7 Action nodes Keep one Action node (or two for on/off) with Block Input Overrides off so the syncs payload.action and payload.target.entity_id are used for all entities.

6. Summary

  • One shared state: flow.nvlInState.rooms.<roomKey> for all rooms; NVL SEND builds one payload for the PLC from that state.
  • One sync map: LIGHT_ENTITY_MAP in NVL to HA Sync defines which PLC light (room + index) updates which HA entity.
  • HA: Create all entities in bulk via a YAML package (or one-by-one in Helpers). Use a consistent entity_id pattern so Node-RED can map HA ↔ room + light without mistakes.

If you want, the next step can be a single example packages/lights_nodered.yaml and an example LIGHT_ENTITY_MAP and roomNames list tailored to your actual room names and light counts.