(*
  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)
  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;
    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;

// Master Bathroom
masterBathroom(switches := NVL_In.masterBathroom, relay_status := EtherCAT_RelayFeedback.masterBathroom);
EtherCAT_RelayFeedback.masterBathroom := masterBathroom.lights;
NVL_Out.l_masterBathroom := masterBathroom.lights;

// Bedroom 1..2, bathroom, guest_wc, kitchen, pantry, livingRoom, diningRoom,
// entrance, hallway, veranda, front, back, side: same pattern (fb_room, RelayFeedback, NVL_Out).
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;

// ========== SECTION 2: BOILER ==========

boiler(
    ha_on := NVL_In.boiler.ha_on,
    ha_off := NVL_In.boiler.ha_off,
    schedule_on := NVL_In.boiler.schedule_on,
    schedule_off := NVL_In.boiler.schedule_off,
    emergency_stop := NVL_In.boiler.emergency_stop OR DI_Emergency_Stop,
    max_on_time := T#8H
);
NVL_Out.boiler_status.relay_output := boiler.relay_control;
NVL_Out.boiler_status.state := boiler.state;
NVL_Out.boiler_status.on_time_minutes := DINT_TO_INT(boiler.on_time_seconds / 60);
NVL_Out.boiler_status.remaining_minutes := DINT_TO_INT(boiler.remaining_seconds / 60);
NVL_Out.boiler_status.emergency_active := boiler.emergency_active;
NVL_Out.boiler_status.time_limit_reached := boiler.time_limit_reached;
NVL_Out.boiler_status.error_state := boiler.error_state;
NVL_Out.boiler_status.error_code := boiler.error_code;
