Hi!
I recently modified the relay example sketch so that it fits my needs; maybe some of you can make use of my little work too.
Here's what you can do / what the features are:
- Easily add as much Relays / FETs as you want (or as much as the arduino allows) by entering the according pin numbers in the RELAYS[ ]-Array
- You can trigger each relay from your controller
- You can add a motion sensor and specify which (MOTION_ACTIVATED_RELAYS[ ]) of your relays should be triggered through motion and for how long (ON_TIMES[ ])
- The state of the motion sensor will be reported to your controller
- When a relay is changed through motion, the change will also be reported to your controller
- You can send a manual override from your controller, so that the motion will still be reported, but none of the relays will be triggered through motion
/**
   The MySensors Arduino library handles the wireless radio link and protocol
   between your home built sensors/actuators and HA controller of choice.
   The sensors forms a self healing radio network with optional repeaters. Each
   repeater and gateway builds a routing tables in EEPROM which keeps track of the
   network topology allowing messages to be routed to nodes.
   Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
   Copyright (C) 2013-2015 Sensnology AB
   Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
   Documentation: http://www.mysensors.org
   Support Forum: http://forum.mysensors.org
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   version 2 as published by the Free Software Foundation.
 *******************************
   REVISION HISTORY
   Version 1.0 - Henrik Ekblad
   Version 1.1 - HenryWhite
   DESCRIPTION
   Example sketch showing how to control physical relays.
   This example will remember relay state after power failure.
   Optional attachment of motion sensor to control the relays is possible.
   Notes:
      -- The Child-IDs of the attached relays range from 1 up to (1-(NUMBER_OF_RELAYS))
      -- Make sure to adjust the potentiometer for triggertime on your motion sensor as leftmost as possible,
         because the countdown will not start until the motion sensor reports back a "0" (no movement)
*/
//----------------------- Library Configuration ---------------------
//#define MY_DEBUG                          // uncomment to enable debug prints to serial monitor
//#define MY_REPEATER_FEATURE               // uncomment to enable repeater functionality for this node
//#define MY_NODE_ID 20                     // uncomment to define static node ID
// Enable and uncomment attached radio type
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
//#define MY_TRANSPORT_WAIT_READY_MS 1      // uncomment this to enter the loop() and setup()-function even when the node cannot be registered to gw
//----------------------- Relay and Motion Sensor Configuration -----------------------
#define MOTION                                                    // un-comment to enable motion sensing
#define NUMBER_OF_RELAYS  2                                       // Total number of attached relays. Must be equal to total number of elements in array below!
const int RELAYS[]                  =     {3,  5};                // digital pins of attached relays
const int MOTION_ACTIVATED_RELAYS[] =     {1,  0};                // 1 to trigger the relay through motion, 0 to not trigger. Array length must correspond to RELAYS[] array.
const long ON_TIMES[]               =     {300, 0};               // Specify for each element in MOTION_ACTIVATED_RELAYS, how long the specified relay should be active in seconds.
#define RELAY_ON          1                                       // GPIO value to write to turn on attached relay
#define RELAY_OFF         0                                       // GPIO value to write to turn off attached relay
#define MOTION_PIN        2                                       // The digital input pin of the motion sensor
#define MOTION_CHILD_ID   0                                       // Set the child id of the motion sensor
bool ack = 1;                                                     // set this to 1 if you want destination node to send ack back to this node
//----------------------- DO NOT CHANGE -----------------------------
#include <MySensors.h>
MyMessage motion_msg(MOTION_CHILD_ID, V_TRIPPED);   // Initialize motion message
unsigned long trigger_millis[NUMBER_OF_RELAYS];     // Used for the timer
bool lastTripped = 0;                               // Used to store last motion sensor value
bool manual_override = 0;                           // if this gets set to 1 (e.g. by a switch or a command from the gateway), motion triggering of relays is deactivated
MyMessage relay_msg;                                // Initialize relay message
void before()
{
  int i;
  for (int sensor = 1, i = 0; sensor <= NUMBER_OF_RELAYS; sensor++, i++) {
    // set relay pins to output mode
    pinMode(RELAYS[i], OUTPUT);
    // Restore relay to last known state (using eeprom storage)
    digitalWrite(RELAYS[i], loadState(sensor) ? RELAY_ON : RELAY_OFF);
  }
  // set motion pin to output mode, if MOTION is defined
#ifdef MOTION
  pinMode(MOTION_PIN, INPUT);
#endif
}
void setup()
{
#ifdef MOTION
  // give the motion sensor some time to settle
  Serial.println("Starting up. Please wait 8 seconds...");
  delay(8000);
#endif
}
void presentation()
{
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Relay/Motion", "1.0");
  // Register all sensors to gw (they will be created as child devices)
  for (int sensor = 1; sensor <= NUMBER_OF_RELAYS; sensor++) {
    present(sensor, S_BINARY, "Relay", ack);
  }
#ifdef MOTION
  present(MOTION_CHILD_ID, S_MOTION, "Motion Sensor", ack);
#endif
}
void loop()
{
#ifdef MOTION
  if (!manual_override) {
    // Read digital motion value
    bool tripped = digitalRead(MOTION_PIN) == HIGH;
    if (lastTripped != tripped) {
      Serial.print("New Motion State: ");
      Serial.println(tripped);
      // Send tripped value to gw
      send(motion_msg.set(tripped ? "1" : "0"));
      lastTripped = tripped;
      // Change relay states, send new state to gw and store state in eeprom
      if (tripped == 1) {
        for (int i = 0; i < NUMBER_OF_RELAYS; i++) {
          if (MOTION_ACTIVATED_RELAYS[i] == 1) {
            digitalWrite(RELAYS[i], RELAY_ON);
            relay_msg_constructor(i + 1, V_STATUS);
            send(relay_msg.set(RELAY_ON));
            trigger_millis[i] = millis();
            Serial.print("Relay ");
            Serial.print(RELAYS[i]);
            Serial.println(" turned on");
            saveState(i, 1);
          }
        }
      }
    }
    for (int i = 0; i < NUMBER_OF_RELAYS; i++) {
      if (tripped == 1 and MOTION_ACTIVATED_RELAYS[i] == 1 and trigger_millis[i] != 0) {
        trigger_millis[i] = millis();
      }
      if ((trigger_millis[i] + ON_TIMES[i] * 1000 < millis()) and MOTION_ACTIVATED_RELAYS[i] == 1 and trigger_millis[i] != 0) {
        digitalWrite(RELAYS[i], RELAY_OFF);
        relay_msg_constructor(i + 1, V_STATUS);
        send(relay_msg.set(RELAY_OFF));
        Serial.print("Relay ");
        Serial.print(RELAYS[i]);
        Serial.println(" turned off");
        saveState(i, 0);
        trigger_millis[i] = 0;
      }
    }
  }
  else {
    bool tripped = digitalRead(MOTION_PIN) == HIGH;
    if (lastTripped != tripped) {
      Serial.print("New Motion State: ");
      Serial.println(tripped);
      // Send tripped value to gw
      send(motion_msg.set(tripped ? "1" : "0"));
      lastTripped = tripped;
    }
    for (int i = 0; i < NUMBER_OF_RELAYS; i++) {
      if (MOTION_ACTIVATED_RELAYS[i] == 1 and trigger_millis[i] != 0) {
        trigger_millis[i] = 0;                            // reset running timers
      }
    }
  }
#endif
}
void receive(const MyMessage &message)
{
  // Handle incoming relay commands
  if (message.type == V_STATUS) {
    // Change relay state
    if (RELAYS[message.sensor - 1]) {
      digitalWrite(RELAYS[message.sensor - 1], message.getBool() ? RELAY_ON : RELAY_OFF);
      // Store state in eeprom
      saveState(message.sensor - 1, message.getBool());
      // Write some debug info
      Serial.print("Incoming change for sensor:");
      Serial.print(message.sensor);
      Serial.print(", New status: ");
      Serial.println(message.getBool());
    }
  }
  // Handle incoming manual override/bypass of motion sensor
  if (message.type == V_ARMED and message.sensor == 0) {
    manual_override = message.getBool();
    Serial.print("Manual Override: ");
    Serial.println(manual_override);
  }
}
void relay_msg_constructor(int sensor, uint8_t type)
{
  relay_msg.setSensor(sensor);
  relay_msg.setType(type);
}
Additional Notes:
- The Child-IDs of the attached relays range from 1 up to (1-(NUMBER_OF_RELAYS))
- The default Child-ID for the motion sensor is 0
- Make sure to adjust the potentiometer for triggertime on your motion sensor as leftmost as possible, because the countdown-timer will not start until the motion sensor reports back a "0" (no movement)