    /**
 *  @file
 *  @Author Septillion (https://github.com/sseptillion)
 *  @date 2016-08-11
 *  6/16/18 - WJL modified to work for lighthouse
 *  6/17/18 - Modified to add four scenarios
 *  6/18/18 - Modified to use LINK system with 5-stand REV_1 board
 *  7/22/18 - Changed to 4 LED
 *  6/12/19 Added delay(500) to on-off switch
 *  EAGLE BOARD "LIGHTHOUSE_LINX_4LED_NORELAY
 *  4/22/2021 MADE NEW BOARD REV A
 *  6/6/2023 - DEVELOPED NEW PROJECT USING MONTEINO,THIS FILE IS FOR RECEIVER 
 *    scene sets pattern(i.e.patA), patA calls the routine to use 
 *     and also establishes that the routine is called each cycle.
 *  6/21/2023 - modified code to fix on_off switch
 */

#include <FadeLed.h>
//added for Moteino thru line 28
#include <RHReliableDatagram.h>
#include <RH_RF95.h>
//#include <SPI.h>

#define CLIENT_ADDRESS 102    //FIELD#1 is 1, PICKLE is 2
#define SERVER_ADDRESS 101    //FIELD#1 is 1, RECEIVER is 1

// Singleton instance of the radio driver
RH_RF95 driver;

// Class to manage message delivery and receipt, using the driver declared above
RHReliableDatagram manager(driver, SERVER_ADDRESS);

//make four FadeLed objects for pin 3 (leds[0]), pin 6 (leds[1], pin 9(leds[2] and pin 12(leds[3]) MOTEINO
FadeLed leds[] = {3, 6, 9, 11};   //MOTEINO PWM pins
//leds[0] = WHITE
//leds[1] = GREEN
//leds[2] = BLUE
//leds[3] = RED

int out_on_off = 16;  //POLOLU SWITCH A2
int state = LOW;       //current state of the output pin

unsigned long millisLast_0;
unsigned long millisLast_1;
unsigned long millisLast_2;
unsigned long millisLast_3;
unsigned long millisLast_4;
unsigned long millisLast_5;
unsigned long millisLast_6;

int patA_A = 1;
int patB_A = 0;
int patC_A = 0;
int patD_A = 0;
int patE_A = 0;
int patF_A = 0;
int patG_A = 0;
int patH_A = 0;

byte currentLed = 0;

void setup() 
{
  Serial.begin(115200);
  //added for moterino thru line 91
  //while (!Serial) ; // Wait for serial port to be available
  if (!manager.init())
    Serial.println("init failed");
    
  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
  // 915Mhz band is 902-928 Mhz
  driver.setFrequency(915);
  
  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then 
  // you can set transmitter powers from 5 to 23 dBm:
  driver.setTxPower(23, false);
  delay(5000);

  //pinMode (in_on_off, INPUT); 
  pinMode (out_on_off, OUTPUT);  
  delay(5000);
  Serial.println("File name = LIGHTHOUSE_MONTEINO_REC_6_21_2023");
}

//added for moteino
uint8_t data[] = "And hello back to you";
// Dont put this on the stack:
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];

void loop() 
{
  FadeLed::update();

  if (manager.available())
    {
      // Wait for a message addressed to us from the client
      uint8_t len = sizeof(buf);
      uint8_t from;
      if (manager.recvfromAck(buf, &len, &from)) {
        buf[len] = 0; // zero out remaining string
        
        Serial.print("got request from : 0x");
        Serial.print(from, HEX);
        Serial.print(": ");
        Serial.println((char*)buf);

        if (strstr((char *)buf, "ON_OFF"))
        {
          Serial.println("RECEIVED ON_OFF");
          if (state == HIGH)
            {
              Serial.println("TURN OFF");
              state = LOW;
            }
            else
            {
              state = HIGH;
              //At power-on set lights to routineA()
              Serial.println("TURN ON");  
              patA();
            }
          digitalWrite(out_on_off, state);
          delay(500);
        
          // Send a reply back to the originator client
        //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending ON_OFF failed (no ack)");
        }

        if (strstr((char *)buf, "scene_1"))
        {
          Serial.println("RECEIVED scene_1");
          patA();
          //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending LOW failed (no ack)");
        }      

        if (strstr((char *)buf, "scene_2"))
        {
          Serial.println("RECEIVED scene_2");
          patB();
          //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending LOW failed (no ack)");
        }

        if (strstr((char *)buf, "scene_3"))
        {
          Serial.println("RECEIVED scene_3");
          patC();
          //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending LOW failed (no ack)");
        }

        if (strstr((char *)buf, "scene_4"))
        {
          Serial.println("RECEIVED scene_4");
          patD();
          //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending LOW failed (no ack)");
        }

        if (strstr((char *)buf, "scene_5"))
        {
          Serial.println("RECEIVED scene_5");
          patE();
          //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending LOW failed (no ack)");
        }

        if (strstr((char *)buf, "scene_6"))
        {
          Serial.println("RECEIVED scene_6");
          patF();
          //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending LOW failed (no ack)");
        }
      }

      if (strstr((char *)buf, "scene_7"))
        {
          Serial.println("RECEIVED scene_7");
          patG();
          //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending LOW failed (no ack)");
        }

        if (strstr((char *)buf, "scene_8"))
        {
          Serial.println("RECEIVED scene_8");
          patH();
          //if (!manager.sendtoWait(data, sizeof(data), from))
          //Serial.println("Sending LOW failed (no ack)");
        }
      else 
      {
        //Serial.println("Receive failed");
      }
    }

    if (patA_A == 1)
      {
        routineA();
      }
    if (patB_A == 1)
      {
        routineB();
      }
    if (patC_A == 1)
      {
        routineC();
      } 
    if (patD_A == 1)
      {
        routineD();
      }
    /*********************************
    if (patE_A == 1)
      {
        routineE();
      }
    if (patF_A == 1)
      {
        routineF();
      }
    if (patG_A == 1)
      {
        routineG();
      }
    if (patH_A == 1)
      {
        routineH();
      }
    **********************************/
}

void patA()
  {
    patA_A = 1;
    patB_A = 0;
    patC_A = 0;
    patD_A = 0;
    patE_A = 0;
    patF_A = 0;
    patG_A = 0;
    patH_A = 0;

    leds[0].off();
    leds[1].off();
    leds[2].off();
    leds[3].off();

    leds[0].setTime(2000,true);
    leds[1].setTime(2000,true);
    leds[2].setTime(2000,true);
    leds[3].setTime(2000,true);  
    //and I start fading the first
    currentLed = 0; //white
    leds[currentLed].on();
    routineA(); 
  }

void patB()
  {
    patA_A = 0;
    patB_A = 1;
    patC_A = 0;
    patD_A = 0;
    patE_A = 0;
    patF_A = 0;
    patG_A = 0;
    patH_A = 0;

    leds[0].off();
    leds[1].off();
    leds[2].off();
    leds[3].off();

    leds[0].setTime(2000,true);
    leds[1].setTime(2000,true);
    leds[2].setTime(2000,true);
    leds[3].setTime(2000,true);  
    //and I start fading the first
    currentLed = 3;   //3 = RED
    leds[currentLed].on(); 
    routineB();
  }

void patC()
  {
    patA_A = 0;
    patB_A = 0;
    patC_A = 1;
    patD_A = 0;
    patE_A = 0;
    patF_A = 0;
    patG_A = 0;
    patH_A = 0;

    leds[0].off();
    leds[1].off();
    leds[2].off();
    leds[3].off();

    routineC();
  }

void patD()
  {
    patA_A = 0;
    patB_A = 0;
    patC_A = 0;
    patD_A = 1;
    patE_A = 0;
    patF_A = 0;
    patG_A = 0;
    patH_A = 0;

    leds[0].off();
    leds[1].off();
    leds[2].off();
    leds[3].off();

    routineD  ();
  } 

void patE()
  {
    patA_A = 0;
    patB_A = 0;
    patC_A = 0;
    patD_A = 0;
    patE_A = 1;
    patF_A = 0;
    patG_A = 0;
    patH_A = 0;

    leds[0].off();
    leds[1].off();
    leds[2].off();
    leds[3].off();

    leds[0].setTime(2000,true);
    leds[1].setTime(2000,true);
    leds[2].setTime(2000,true);
    leds[3].setTime(2000,true);  
    //and I start fading the first
    currentLed = 3;   //3 = RED
    leds[currentLed].on(); 
    routineE  ();
  }

void patF()
  {
    patA_A = 0;
    patB_A = 0;
    patC_A = 0;
    patD_A = 0;
    patE_A = 0;
    patF_A = 1;
    patG_A = 0;
    patH_A = 0;

    leds[0].off();
    leds[1].off();
    leds[2].off();
    leds[3].off();
    routineD  ();

  }

void patG()
  {
    patA_A = 0;
    patB_A = 0;
    patC_A = 0;
    patD_A = 0;
    patE_A = 0;
    patF_A = 0;
    patG_A = 1;
    patH_A = 0;

    leds[0].off();
    leds[1].off();
    leds[2].off();
    leds[3].off();
    routineD  ();
  }

void patH()
  {
    patA_A = 0;
    patB_A = 0;
    patC_A = 0;
    patD_A = 0;
    patE_A = 0;
    patF_A = 0;
    patG_A = 0;
    patH_A = 1;

    leds[0].off();
    leds[1].off();
    leds[2].off();
    leds[3].off(); 
    routineD();
  } 

void routineA()       //RED-WHITE-GREEN-BLUE, LINX BUTTON #1
 { 
  //Serial.println("AT routineA()");
  if(leds[currentLed].done() && leds[currentLed].get())
    {
      //Serial.print("FADE DOWN - leds[current.led].get = "); Serial.println(leds[currentLed].get());
      //fade down again
      leds[currentLed].off();
    }
    //if done fading down
    else if(leds[currentLed].done() && !leds[currentLed].get())
    {
    //      Serial.print("FADE UP - !leds[current.led].get = "); Serial.println(leds[currentLed].get());
    //go to next led
    currentLed++;
    if(currentLed >= 4)
    {
      currentLed = 0;
      //Serial.println("ROUTINE A, NEXT LED");
    }
   
    //and start fading that
    leds[currentLed].set(75);
   }
 }

void routineB()   //RED-WHITE-BLUE, LINX BUITTON #2
 {
  //Serial.println("AT routineB()");
  if(leds[currentLed].done() && leds[currentLed].get())
    {
      //fade down again
      leds[currentLed].off();
   }
  //if done fading down
   else if(leds[currentLed].done() && !leds[currentLed].get())
   {
    //go to next led
    if(currentLed == 3)
    {
      Serial.println("ROUTINE b, NEXT LED #0");
      Serial.print("currentLed = "); Serial.println(currentLed);
      currentLed = 0;
      leds[currentLed].set(75);
    }
    else if(currentLed == 0)
    {
      Serial.println("ROUTINE b, NEXT LED #2");
      Serial.print("currentLed = "); Serial.println(currentLed);
      currentLed = 2;
      leds[currentLed].set(75);
    }
    else if(currentLed == 2)
    {
      Serial.println("ROUTINE b, NEXT LED #3");
      Serial.print("currentLed = "); Serial.println(currentLed);
      currentLed = 3;
      leds[currentLed].set(75);
    }
    /*
    else if   (currentLed == 3)
    {
      Serial.println("ROUTINE b, NEXT LED #3");
      Serial.print("currentLed = "); Serial.println(currentLed);
      currentLed = 0;
      leds[currentLed].set(75); 
    }
    */
    //and start fading that
    //leds[currentLed].set(75);
   }
 }

void routineC()       //BLUE LED, LINX BUTON#3
 {
  //Serial.println("at routineC()");
  if(leds[2].done())            //BLUE LED
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[2].get())
    {
      leds[2].setTime(1000,true);
      //then we are done fading up, let's fade down again
      leds[2].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_2 > 7000)
      {
      leds[2].setTime(1000,true);
      //then we are done fading down, let's fade up again
      leds[2].set(25);
      millisLast_2 = millis();
      }
    }
  }
 }  

void routineD()         //WHITE LED, LINX BUTTON #4
 {
  //Serial.println("at routineD()");
  if(leds[0].done())        //WHITE LED
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[0].get())
    {
      leds[0].setTime(1000, true);
      //then we are done fading up, let's fade down again
      leds[0].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_0 > 7000)
      {
        leds[0].setTime(1000,true);
      //then we are done fading down, let's fade up again
      leds[0].set(25);
      millisLast_0 = millis();
      }
    }
  }
 }

 void routineE()   //RED-WHITE-GREEN, LINX BUTTON #5
 {
  Serial.println("at routinE()");
  if(leds[currentLed].done() && leds[currentLed].get())
    {
      //fade down again
      leds[currentLed].off();
   }
  //if done fading down
   else if(leds[currentLed].done() && !leds[currentLed].get())
   {
    //go to next led
    if(currentLed == 3)
    {
      Serial.println("ROUTINE b, NEXT LED #0");
      Serial.print("currentLed = "); Serial.println(currentLed);
      currentLed = 0;
      leds[currentLed].set(75);
    }
    else if(currentLed == 0)
    {
      Serial.println("ROUTINE b, NEXT LED #1");
      Serial.print("currentLed = "); Serial.println(currentLed);
      currentLed = 1;
      leds[currentLed].set(75);
    }
    else if(currentLed == 1)
    {
      Serial.println("ROUTINE b, NEXT LED #3");
      Serial.print("currentLed = "); Serial.println(currentLed);
      currentLed = 3;
      leds[currentLed].set(75);
    }
    /*
    else if   (currentLed == 3)
    {
      Serial.println("ROUTINE b, NEXT LED #3");
      Serial.print("currentLed = "); Serial.println(currentLed);
      currentLed = 0;
      leds[currentLed].set(75); 
    }
    */
    //and start fading that
    //leds[currentLed].set(75);
   }
 }
/**********************************************
    if(leds[1].done())          //GREEN LED
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[1].get())
    {
       leds[1].setTime(3000,true);
      //then we are done fading up, let's fade down again
      leds[1].off();
    }
    //or we are at 0
    else
    {
      //if (millis() - millisLast_1 > 7000)
      //{
      leds[1].setTime(3000,true);
      //then we are done fading down, let's fade up again
      leds[1].set(25);
      //millisLast_1 = millis();
      //}
    }
  }

    if(leds[2].done())            //WHITE LED
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[2].get())
    {
      leds[2].setTime(1000,true);
      //then we are done fading up, let's fade down again
      leds[2].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_2 > 7000)
      {
      leds[2].setTime(1000,true);
      //then we are done fading down, let's fade up again
      leds[2].set(25);
      millisLast_2 = millis();
      }
    }
  }
 }

void routineE()
 {
  Serial.println("at routineE");
  if(leds[0].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[0].get())
    {
      //then we are done fading up, let's fade down again
      leds[0].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_0 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[0].set(50);
      millisLast_0 = millis();
      }
    }
  }

    if(leds[1].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[1].get())
    {
      //then we are done fading up, let's fade down again
      leds[1].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_1 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[1].set(50);
      millisLast_1 = millis();
      }
    }
  }

    if(leds[2].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[2].get())
    {
      //then we are done fading up, let's fade down again
      leds[2].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_2 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[2].set(50);
      millisLast_2 = millis();
      }
    }
  }
 }

void routineF()
 {
  Serial.println("at routineE");
  if(leds[0].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[0].get())
    {
      //then we are done fading up, let's fade down again
      leds[0].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_0 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[0].set(50);
      millisLast_0 = millis();
      }
    }
  }

    if(leds[1].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[1].get())
    {
      //then we are done fading up, let's fade down again
      leds[1].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_1 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[1].set(50);
      millisLast_1 = millis();
      }
    }
  }

    if(leds[2].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[2].get())
    {
      //then we are done fading up, let's fade down again
      leds[2].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_2 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[2].set(50);
      millisLast_2 = millis();
      }
    }
  }
 }

void routineG()
 {
  Serial.println("at routineF");
  if(leds[0].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0 or using !xxx if we are at zero
    if(leds[0].get())
    {
      //then we are done fading up, let's fade down again
      leds[0].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_0 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[0].set(50);
      millisLast_0 = millis();
      }
    }
  }

    if(leds[1].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[1].get())
    {
      //then we are done fading up, let's fade down again
      leds[1].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_1 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[1].set(50);
      millisLast_1 = millis();
      }
    }
  }

    if(leds[2].done())
  {
    //.get() will return the current brightness
    //so this will tell us if we are not at 0
    if(leds[2].get())
    {
      //then we are done fading up, let's fade down again
      leds[2].off();
    }
    //or we are at 0
    else
    {
      if (millis() - millisLast_2 > 14000)
      {
      //then we are done fading down, let's fade up again
      leds[2].set(50);
      millisLast_2 = millis();
      }
    }
  }
 }
*******************************************/  
