// Writes to state.rooms.cmd_livingroom (NVL variable cmd_livingroom). const ROOM_NAME = 'cmd_livingroom'; const entityId = (msg.topic || '').toString(); const parts = entityId.split('_'); const last = parts[parts.length - 1] || ''; const num = parseInt(last, 10); const lightNum = (!isNaN(num) && num >= 1) ? Math.min(6, num) : 1; // Normalize state: HA / trigger-state can send payload as string, object with .state, or data.new_state.state let rawState = msg.payload; if (rawState !== null && typeof rawState === 'object' && rawState.state !== undefined) rawState = rawState.state; if (msg.data && msg.data.new_state && msg.data.new_state.state !== undefined) rawState = msg.data.new_state.state; const isOn = (rawState === 'on' || rawState === true); node.warn('[HA to NVL] topic=' + entityId + ' rawState=' + JSON.stringify(rawState) + ' → lightNum=' + lightNum + ' isOn=' + isOn); if (!flow.get('nvlInState')) flow.set('nvlInState', { rooms: {}, boiler: {} }); const state = flow.get('nvlInState'); if (!state.rooms[ROOM_NAME]) state.rooms[ROOM_NAME] = {}; const r = state.rooms[ROOM_NAME]; r['ha_l' + lightNum + '_on'] = false; r['ha_l' + lightNum + '_off'] = false; if (isOn) r['ha_l' + lightNum + '_on'] = true; else r['ha_l' + lightNum + '_off'] = true; flow.set('nvlInState', state); node.warn('[HA to NVL] set cmd_livingroom ha_l' + lightNum + '_' + (isOn ? 'on' : 'off') + '=true, buildAndSend'); // PLC uses R_TRIG (rising edge). If "off" still doesn’t work, add a flow: after this node, 80ms delay then clear ha_l*_off and buildAndSend again (pulse). msg.payload = { buildAndSend: true }; return msg;