#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash
#include <dht.h>
#include <math.h>
#include <WirelessHEX69.h>

#define NODEID        1    //unique for each node on same network
#define NETWORKID     98  //the same on all nodes that talk to each other
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "somethingierased" //exactly the same 16 characters/bytes on all nodes!
#define SERIAL_BAUD   115200

#ifdef __AVR_ATmega1284P__
#define LED           15 // Moteino MEGAs have LEDs on D15
#define FLASH_SS      23 // and FLASH SS on D23
#else
#define LED           9 // Moteinos have LEDs on D9
#define FLASH_SS      8 // and FLASH SS on D8
#endif

#define dht_dpin A0 //no ; here. Set equal to channel sensor is on
dht DHT;
double FahTemp;
RFM69 radio;
char c;
char temp[25];
int inputnode;
int sendcount;
int sendLen;
int i=0;
int pgmcheck=0;
char input[50];

SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network

void setup()
{
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(promiscuousMode);
  Serial.println("McLean Gateway Node Version 7.1.");
  flash.initialize();
}
void loop()
{
  strcpy(input,"");
  i=0;
  while (Serial.available())
  {
    delay(5);
    c = Serial.read();  //gets one byte from serial buffer
    input[i]=c;
    i++;
    input[i]='\0';
    if(c=='\0')
      break;
    if(c=='.')
      break;
  }
  if(strncmp(input,"01",2)==0)
  {
  if(strncmp(input,"01temperature",13)==0)
  {
    byte temperature =  radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient
    byte fTemp = 1.8 * temperature + 32; // 9/5=1.8
    DHT.read11(dht_dpin);
    Serial.print(NODEID);
    Serial.print(" Radio Temp: ");
    Serial.print(temperature);
    Serial.print("C, ");
    Serial.print(fTemp); //converting to F loses some resolution, obvious when C is on edge between 2 values (ie 26C=78F, 27C=80F)
    Serial.println('F');
    DHT.read11(dht_dpin);
    Serial.print(NODEID);
    Serial.print(" humidity = ");
    Serial.print(DHT.humidity);
    Serial.print("%  ");
    Serial.print("DHP temp = ");
    Serial.print(DHT.temperature); 
    Serial.print("C  ");
    FahTemp = (DHT.temperature * 9.0)/ 5.0 + 32.0; // Convert from Celcius
    Serial.print(FahTemp); 
    Serial.println("F  ");
    strcpy(input,"");
  }
  if(strncmp(input,"01stat",6)==0)
  {
    Serial.print(NODEID);
    Serial.println(" OK.");
    strcpy(input,"");
  }
  if(strncmp(input,"01reboot",8)==0)
  {
    Serial.print(NODEID);
    Serial.println(" Gateway Rebooting.");
    resetUsingWatchdog(true);
  }
  if(strncmp(input,"01command",9)==0)
  {
    Serial.print(NODEID);
    Serial.println(" Gateway Commands are 'reboot' 'stat' 'temperature'");
    strcpy(input,"");
    if(pgmcheck==0)
        pgmcheck=1;
    else
        pgmcheck=0;
  }
  }
  else
  {
  if(strcmp(input,"")!=0)
  {
    Serial.print(NODEID);
    Serial.print(" serial input: ");
    Serial.println(input);
    strncpy(temp,input,2);
    temp[2]='\0';
    inputnode=atoi(temp);
    strcpy(temp,&input[2]);
    strcpy(input,"");
    sendLen = strlen(temp);
    sendcount=1;
    while(sendcount<50)
    {
      if(radio.sendWithRetry(inputnode,temp,sendLen))
      {
        Serial.print(NODEID);
        Serial.print(" message sent OK to node ");
        Serial.print(inputnode);
        Serial.print(" in ");
        Serial.print(sendcount);
        Serial.println(" tries");
        if(inputnode==4)
        {
            inputnode=3;
            sendcount=1;
        }
        sendcount=100;
      }
      else
      {
         sendcount++;
         if(sendcount>40)
         {
            Serial.print(NODEID);
            Serial.print(" send-err to:");
            Serial.println(inputnode);
            sendcount=100;
         }
         delay(2);
      }
    }
  }
  }
  if (radio.receiveDone())
  {
      char radinput[60];
      if(pgmcheck==1)
          CheckForWirelessHEX(radio, flash, true);
      for (i = 0; i < radio.DATALEN; i++)
      {
          radinput[i]=radio.DATA[i];
          radinput[i+1]='\0';
      }
      if (radio.ACKRequested())
          radio.sendACK();
      Serial.println(radinput);
   }
   Blink(LED,3);
}
void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}