// Writes to state.rooms.. Room from entity_id via global roomConfig.entityToRoom. See /root/.node-red/room-config.js. const entityId = (msg.topic || '').toString(); const config = global.get('roomConfig'); const entityToRoom = (config && config.entityToRoom) ? config.entityToRoom : { living_room_new: 'cmd_livingroom' }; // Parse entity_id e.g. input_boolean.living_room_1 → base "living_room_1", then room + light const base = (entityId.split('.')[1] || '').replace(/\s/g, ''); const numMatch = base.match(/_(\d+)$/); const lightNum = (numMatch && parseInt(numMatch[1], 10) >= 1) ? Math.min(6, parseInt(numMatch[1], 10)) : 1; const baseWithoutNum = base.replace(/_?\d+$/, '') || base; const ROOM_NAME = entityToRoom[baseWithoutNum] || entityToRoom[base] || 'cmd_livingroom'; // 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 ' + ROOM_NAME + ' 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;