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

// 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;

// Kitchen
kitchen(switches := NVL_In.kitchen, relay_status := EtherCAT_RelayFeedback.kitchen);
EtherCAT_RelayFeedback.kitchen := kitchen.lights;
NVL_Out.l_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;

// Living Room
livingRoom(switches := NVL_In.livingRoom, relay_status := EtherCAT_RelayFeedback.livingRoom);
EtherCAT_RelayFeedback.livingRoom := livingRoom.lights;
NVL_Out.l_livingRoom := livingRoom.lights;

// Dining Room
diningRoom(switches := NVL_In.dinningRoom, relay_status := EtherCAT_RelayFeedback.diningRoom);
EtherCAT_RelayFeedback.diningRoom := diningRoom.lights;
NVL_Out.l_dinningRoom := diningRoom.lights;

// Entrance
entrance(switches := NVL_In.entrance, relay_status := EtherCAT_RelayFeedback.entrance);
EtherCAT_RelayFeedback.entrance := entrance.lights;
NVL_Out.l_entrance := entrance.lights;

// Hallway
hallway(switches := NVL_In.hallway, relay_status := EtherCAT_RelayFeedback.hallway);
EtherCAT_RelayFeedback.hallway := hallway.lights;
NVL_Out.l_hallway := hallway.lights;

// Veranda
veranda(switches := NVL_In.outVeranda, relay_status := EtherCAT_RelayFeedback.veranda);
EtherCAT_RelayFeedback.veranda := veranda.lights;
NVL_Out.l_outVeranda := veranda.lights;

// Front
front(switches := NVL_In.outFront, relay_status := EtherCAT_RelayFeedback.front);
EtherCAT_RelayFeedback.front := front.lights;
NVL_Out.l_outFront := front.lights;

// Back
back(switches := NVL_In.outBack, relay_status := EtherCAT_RelayFeedback.back);
EtherCAT_RelayFeedback.back := back.lights;
NVL_Out.l_outBack := back.lights;

// Side
side(switches := NVL_In.outSide, relay_status := EtherCAT_RelayFeedback.side);
EtherCAT_RelayFeedback.side := side.lights;
NVL_Out.l_outSide := side.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;
