
/****************************************
* Time: July 13, 2021
  * Development team: Shenzhen Zhiyi Technology Co., Ltd. (Jack Yang )
  * Function introduction: infrared integrated smart home control code
  * Through the remote control 1 button to turn on the LCD backlight, 2 buttons to turn off the LCD backlight
  * Button 3 can turn on the fan, button 4 can turn off the fan
  * Press 5 to open the window, press 6 to close the window
  * Press 7 to open the gate; press 8 to close the gate
  * When the raindrop sensor senses moisture; the window will be closed automatically
  * When the yellow button is pressed, the LED module lights up; when the touch module is pressed, RGB lights up red, green, blue, white, and off respectively
  * When the remote control presses the "^" above the direction arrow: RGB lights up in white, and "V" below the direction arrow lights up in red;
  * The left of the direction arrow "<" RGB lights up green, the direction arrow ">" RGB lights up blue, click the "OK" button to close RGB
  * When methane and other gases are present, the MQ-2 gas sensor senses it and will start the buzzer to alarm, and the fan will rotate to discharge harmful gases outside the room.
  *
 **************************************/
#include <Adafruit_NeoPixel.h>  //RGB libraries
#include <dht.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <IRremote.h>          //Infrared libraries
#include <SPI.h> 
#include <RFID.h>
#include <Servo.h>    // Servo libraries
RFID rfid(10, 9);       //D10: the pin of the tag reader SDA. D9: Label reader RST pin
unsigned char status; 
unsigned char str[MAX_LEN]; //MAX_LEN is 16: size of the array 

String accessGranted [2] = {"1341312706", "31215123949"};  //Rfid serial number authorized access
int accessGrantedSize = 2;                                //Number of serial numbers
Servo lockServo;                //Locking mechanism servo
int lockPos = 0;               //Lock position limitation
int unlockPos =90;             //Limit of unlock position
boolean locked = true;
int rain;     
Servo myservo;  // Create a servo object to control the servo
int pos = 0;    // Variables store the servo position
int RainFlag = 0;   

unsigned long currentMillis;
unsigned long time1;

dht DHT;
#define NUMPIXELS      4          //Number of LED lamp beads
#define  RGB_PIN       5          // RGB module Arduino output control signal pin
#define  LED_PIN       8          //LED module Arduino output control signal pin
#define  KEY_1         A7         //Touch button Arduino output control signal pin A7
#define  KEY_2         A6         //Yellow button module Arduino output control signal pin
#define  buzzer        15         //Buzzer module Arduino output control signal pin
#define  smokeA0       A0         //MQ-2 gas sensor Arduino output control signal pin
#define DHT11_PIN      4          //DHT11 temperature and humidity Arduino output control signal pin
#define IR_PIN         7          //Infrared receiver Arduino output control signal pin
#define RelayPin       16         //Relay module Arduino output control signal pin    
#define FanPinA        2          //Fan motor module Arduino output control signal pin
#define Rain           A3         // Raindrop sensor Arduino output control signal pin


#define KEY11 16753245    //Control LCD to turn on the backlight
#define KEY22 16736925    //Control LCD to turn off backlight
#define KEY33 16769565    //Control fan start
#define KEY44 16720605    //Control fan off
#define KEY55 16712445    //Control window opening
#define KEY66 16761405    //Control window closing
#define KEY77 16769055    //Control gate open
#define KEY88 16754775    //Control door closing 

//Set the LCD address to 0x27 to display in 16 characters and 2 lines

LiquidCrystal_I2C lcd(0x27,20,4);  
IRrecv irrecv(IR_PIN);
decode_results results;
Adafruit_NeoPixel pixels(NUMPIXELS, RGB_PIN, NEO_GRB + NEO_KHZ800);//Create light objects


//Variable definitions
int count_R=0;
int count_G=0;
int count_B=0;
int count_key=0;
int Press=0;            //Defines key flag bits
int rotate=0;
int KEY_BIT=0;            //Defining status bits
int LED_BIT=0;            //Defining status bits
int sensorThres = 400;     //Set the gas concentration range
 

//The touch key initializes the function

void KEY()   //Key Function
{
  int i=analogRead(KEY_1);
  Serial.println(count_key);
  if(i)
  {
    delay(20);
    if(i)Press=1;             //Press the logo
  }
  
  i=analogRead(KEY_1);      //Whether the button is pressed
  if((i==0)&&(Press==1))   //Check whether the key is really pressed
  {
    Press=0;
    count_key++;
    
    if(count_key==6)count_key=1;  
   
  }
  
}
  

//LED function
void LED()
{
  if((analogRead(KEY_2))&&(KEY_BIT)) //Determine if the key is pressed
  {
    KEY_BIT=0;
    if(LED_BIT==0)LED_BIT=1;
    else LED_BIT=0;
  }
  else
  {
    delay(20);
    if(!analogRead(KEY_2))
    {
      KEY_BIT=1;
    }
  }
  
if(LED_BIT)digitalWrite(LED_PIN,HIGH);//MCU output high level
else digitalWrite(LED_PIN,LOW);      //MCU output low level

}

//RGB function  
void RGB()
{
  switch(count_key)    //Number of keys 
  {
    case 1 :            //The red light is on.

      pixels.setPixelColor(0, pixels.Color(255, 0, 0));
      pixels.setPixelColor(1, pixels.Color(255, 0, 0));
      pixels.setPixelColor(2, pixels.Color(255, 0, 0));
      pixels.setPixelColor(3, pixels.Color(255, 0, 0));
      pixels.show();
      break;
    case 2 :              //green light flashes

      pixels.setPixelColor(0, pixels.Color(0, 255, 0));
      pixels.setPixelColor(1, pixels.Color(0, 255, 0));
      pixels.setPixelColor(2, pixels.Color(0, 255, 0));
      pixels.setPixelColor(3, pixels.Color(0, 255, 0));
      pixels.show();
      break;
    case 3 :               //The blue lights

      pixels.setPixelColor(0, pixels.Color(0, 0, 255));
      pixels.setPixelColor(1, pixels.Color(0, 0, 255));
      pixels.setPixelColor(2, pixels.Color(0, 0, 255));
      pixels.setPixelColor(3, pixels.Color(0, 0, 255));
      pixels.show();
      break;
      case 4 :           //bright white light
         //delay(100);
         pixels.setPixelColor(0, pixels.Color(255, 255, 255));
         pixels.setPixelColor(1, pixels.Color(255, 255, 255));
         pixels.setPixelColor(2, pixels.Color(255, 255, 255));
         pixels.setPixelColor(3, pixels.Color(255, 255, 255));
         pixels.show();
          break;
       case 5 :        // Turn our the lights
      pixels.setPixelColor(0, pixels.Color(0, 0, 0));
      pixels.setPixelColor(1, pixels.Color(0, 0, 0));
      pixels.setPixelColor(2, pixels.Color(0, 0, 0));
      pixels.setPixelColor(3, pixels.Color(0, 0, 0));
      pixels.show();
      break;
     default : break;
  }
 
}

//Mq-2 gas function

void smoke()
{
   int analogSensor = analogRead(smokeA0); //Assign the check value of the MQ-2 sensor to the ALOG sensor variable

  Serial.print("Pin A0: ");
  Serial.println(analogSensor);
  //Check if the threshold has been reached
  if (analogSensor > sensorThres)
  {
   digitalWrite(buzzer,HIGH); //The output is high, the buzzer sounds
   delay(500);
   digitalWrite(RelayPin,HIGH);  //High output; Relay start
   digitalWrite(FanPinA, HIGH);  //The fan start
   delay(1000);
   digitalWrite(buzzer,LOW);  //The low output buzzer stops
   delay(500); 
   digitalWrite(RelayPin,LOW);  //The output is low; Relay off
   digitalWrite(FanPinA, LOW);   //Fan stop
   delay(1000);
  }
  else
  {   
  
  }
  delay(100);
}

  
//Infrared control LCD 1602, fan, door and window, LED function

void LCD()
{
   translateIR();  //Infrared controls RGB functions
   ShowHumiture();
    if (irrecv.decode(&results)) 
    {
        Serial.print("value = ");
        Serial.println(results.value, HEX);
     
        if (results.value == KEY11 )     // LCD boot
        {
          lcd.backlight(); //Turn on the backlight
            
        } 
        else if (results.value == KEY22 ) //LCD OFF
        {
            lcd.noBacklight(); // Turn off the backlight
            lcd.clear();
        } 
          if (results.value == KEY33 ) //Switch on and activate the relay
        {
           digitalWrite(RelayPin, HIGH);
           digitalWrite(FanPinA, HIGH);
           
        } 
        else if (results.value == KEY44 ) // Disconnect the relay
        {
            digitalWrite(RelayPin, LOW);
             digitalWrite(FanPinA, LOW);
             
        } 

       if (results.value == KEY55 )   //Open Window
        {
           myservo.write(0);
           delay(15);
           
        } 
        else if (results.value == KEY66 ) //close windows
        {
            myservo.write(90);  //Change the degree of rotation of the steering gear
            delay(15);
             
        }    


        if (results.value == KEY77)         //Open the door
          {   lockServo.write(0);
              delay(15);
           }
       else if (results.value == KEY88)     //Close the gate
       {
          lockServo.write(90);
          delay(15);
       }

        irrecv.resume(); // Receive the next value
      }
      delay(100);
  
 }
//Display temperature
void ShowHumiture()
{
   int chk = DHT.read11(DHT11_PIN);
    //Serial.println("DHT TEST PROGRAM ");
    lcd.setCursor(0,0);  
    lcd.print("humi:");
    lcd.setCursor(5,0);
    lcd.print(DHT.humidity);

    lcd.setCursor(0,1); 
    lcd.print("temp:");
    lcd.setCursor(5,1);
    lcd.print(DHT.temperature);

}
//Infrared control RGB 
void translateIR() // Act on received IR code
{
  switch(results.value)
  {
  case 0xFF4AB5:    count_key=1; break;   //Red
  case 0xFF10EF:    count_key=2; break;   //green
  case 0xFF5AA5:    count_key=3; break;   //blue
  case 0xFF18E7:    count_key=4; break;   //white 
  case 0XFF38C7:                         //Hit the OK button to turn off the lights
  if(count_key==5)count_key=5;       //
  else count_key=5;
  break;
  default: break;
  }

} 


//RFID

void RD()
{
  if (rfid.findCard(PICC_REQIDL, str) == MI_OK)   //Wait for a tag to be placed near the reader
  { 
    Serial.println("Card found"); 
    String temp = "";                             //A temporary variable that stores the READ RFID number
    if (rfid.anticoll(str) == MI_OK)              //Anti-collision detection, read the label serial number
    { 
      Serial.print("The card's ID number is : "); 
      for (int i = 0; i < 4; i++)                 //Record and display the label serial number
      { 
        temp = temp + (0x0F & (str[i] >> 4)); 
        temp = temp + (0x0F & str[i]); 
      } 
      Serial.println (temp);
      checkAccess (temp);     //Check whether the identified label is allowed to be opened
    } 
    rfid.selectTag(str); //Lock the card to prevent repeated reading, removing the line will cause the sketch to read the card continuously
  }
  rfid.halt();
  
 }
 
void checkAccess (String temp)    //The function checks whether a registered tag is accessible
{
  boolean granted = false;
  for (int i=0; i <= (accessGrantedSize-1); i++)    //Iterates over all tag ID numbers registered in the group
  {
    if(accessGranted[i] == temp)            //If a label is found, then open/close the lock
    {
      Serial.println ("Access Granted");
      granted = true;
      if (locked == true)         //If the lock is closed, open it
      {
          lockServo.write(unlockPos);
          locked = false;
      }
      else if (locked == false)   //If the lock is open, close it
      {
          lockServo.write(lockPos);
          locked = true;
      }

    }
  }
  if (granted == false)     //If no tags are found
  {
    Serial.println ("Access Denied");
  }
}

//Raindrop sensor
void rainwater()
 {
     
     currentMillis = millis();

    //Sensor data collection
    rain = map(analogRead(Rain), 0, 1023, 255, 0);
    
    Serial.print("RainData =");
    Serial.println(rain);

    //The steering gear turned in the rain to close the window
    if(rain > 130  && !RainFlag)
    {
        for ( pos = 0; pos < 180; pos++)
        {
          //'POS' is the rotation Angle of the servo motor
            myservo.write(pos); 
            delay(10);
        }
        RainFlag = 1;
    }
    
    //Steer before it rains. Open the window
    else if(rain < 130 && RainFlag)
    {
      //Wait ten seconds for it to rain before you open the window
        if (currentMillis - time1 >= 1000*10)
        {
            time1 = currentMillis;       
            for ( pos = 180; pos >= 0; pos--)
            {
              //'POS' is the rotation Angle of the servo motor
                myservo.write(pos);              
                delay(10);
            }
            RainFlag = 0;
        }
    }
    else
    { 
       time1 = currentMillis;    
    }
 
  }

void setup ()
{
  
	pinMode(KEY_1,INPUT);  //Touch definition input
	pinMode(KEY_2,INPUT);  //Key definition input
  pinMode(LED_PIN,OUTPUT);//LED
	pixels.begin(); //Initialize 2812 library functions
	pixels.show();
  pinMode(buzzer, OUTPUT); //The buzzer defines the output
  pinMode(smokeA0, INPUT); //Smoke definition input
  pinMode(FanPinA, OUTPUT);//fan
  pinMode(RelayPin,OUTPUT);//Relay module

   myservo.attach(6);  // Connect the servo on pin 6 to the servo object
  pinMode(Rain, INPUT);     
  digitalWrite(RelayPin, LOW);
  digitalWrite(FanPinA, LOW); 
  
  Serial.println("DHT TEST PROGRAM ");
  Serial.print("LIBRARY VERSION: ");
  Serial.println(DHT_LIB_VERSION);
  Serial.println();
  Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)");

  lcd.init();   // Initialized liquid crystal
  // Print message to LCD
  lcd.backlight();
  irrecv.enableIRIn(); // Starting receiver
	Serial.begin(9600);
  SPI.begin();            //Start SPI communication with the reader
  rfid.init();            //initialize 
  lockServo.attach(3);
  lockServo.write(lockPos);         //Move the servo to the locked position
  Serial.println("Place card/tag near reader...");
  
}


void loop()
{
	  pixels.clear(); // Backlight
	  KEY();            //The key function
	  RGB();           //RGB 
    LED();           //LED
    smoke();         //MQ-2 gas sensor
    LCD();          //DHT11
    RD();           //RFID
    rainwater();    //Raindrop sensor
}
