Davide Vertuani
Published © GPL3+

Homotica - a simple, cost-effective home control system

Create a simple home automation system using Arduino and an Android phone.

IntermediateShowcase (no instructions)64,497
Homotica - a simple, cost-effective home control system

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
Any other Arduino board compatible with the Ethernet or wifi shield will be ok
×1
Arduino Ethernet Shield 2
Arduino Ethernet Shield 2
If your Arduino already provides internet connectivity, you don't need this
×1
Relay (generic)
Any relay/relay board will be fine
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Wiring diagram

Code

Arduino sketch code

C/C++
//Sketch for Homotica Android App
#include <Homotica.h>
#include <Ethernet.h>
#include <SPI.h>
#include <RFID.h>
#include <EthernetUdp.h>

#define DEBUG_MODE
#define SKETCH_NAME "HomoticaSketch"
#define SKETCH_VERSION "1.0"
#define ACTIVE_LOW                //delete the line if you're using active_high setup

#ifdef ACTIVE_LOW
#define MHIGH 0x0
#define MLOW  0x1
#else
#define MHIGH 0x1
#define MLOW  0x0
#endif

#ifdef DEBUG_MODE
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTLN(x) Serial.println(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#endif

#define SDA_PIN 9
#define RESET_PIN 8

IPAddress ip(192, 168, 1, 20);
byte mac[] = {0x90, 0xA2, 0xDA, 0x0E, 0xBD, 0x21};
char Data_RX;
int PIN, del, charsIndex[4], relayMode;
static int startingPIN = 4, finishPIN = 7;
unsigned const int localPort = 80;
String msg, request, recivedCode;
static String code = "abcdefgh";

char packetBuffer[200];
const char wrongAuth[] = "2";
const char positiveResponse[] = "1";
const char negativeResponse[] = "0";
EthernetUDP Udp;

Homotica homotica;

RFID mRFID(SDA_PIN, RESET_PIN);
int lastRFIDAction = 0;
static String allowedCards[] = {"6C69A3CU89", "77698D5R23"};

static String openDoor = "!7!2!1000!";
static String closeDoor = "!6!2!1000!";

void setup() {
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  SPI.begin();
  mRFID.init();

  Serial.begin(9600);
  DEBUG_PRINT("UDP is at ");
  DEBUG_PRINTLN(Ethernet.localIP());
  DEBUG_PRINTLN("");

  for (int i = startingPIN; i < finishPIN + 1;  i++) {
    pinMode(i, OUTPUT);
    digitalWrite(i, MLOW);
  }
}

void loop() {
  checkUDP();
  checkRFID();
  homotica.refresh();
}

void checkUDP() {
  msg = "";
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    
    DEBUG_PRINTLN();
    DEBUG_PRINTLN("********************NEW INCOMING PACKET**************************");
    
    Udp.read(packetBuffer, 200);
    msg = packetBuffer;

    recivedCode = msg.substring(msg.indexOf("=") + 1 , msg.indexOf("!"));
    request = msg.substring(msg.indexOf("?") + 1 , msg.indexOf("="));
  
    if (recivedCode == code) {
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
      String myString = msg.substring(msg.indexOf("!"));

      DEBUG_PRINT("Recived: ");
      DEBUG_PRINTLN(msg);
      DEBUG_PRINT("Substring: ");
      DEBUG_PRINTLN(myString);

      if (request == "QU") {
        charsIndex[0] = msg.indexOf("!");
        charsIndex[1] = msg.indexOf("!", charsIndex[0] + 1);
        PIN = msg.substring(charsIndex[0] + 1 , charsIndex[1]).toInt();
        String sensorReading = String(analogRead(PIN));
        char output[sensorReading.length() + 1];
        sensorReading.toCharArray(output, sensorReading.length() + 1);
        Udp.write(output);
      }
      else if (request == "ST") {
        Udp.write(positiveResponse);
        Udp.endPacket();
        processSingleRunnable(myString);
      }
      else if (request == "MT") {
        Udp.write(positiveResponse);
        Udp.endPacket();
        processMultipleRunnable(myString);
      }
      else if (request == "CH") {
        Udp.write(positiveResponse);
        Udp.endPacket();
      }
      else {
        Udp.write(negativeResponse);
        Udp.endPacket();
      }
    }
    else{
      Udp.write(wrongAuth);
      Udp.endPacket();
    }
    for ( int i = 0; i < sizeof(packetBuffer);  ++i ) {
      packetBuffer[i] = (char)0;
    }
  }
  delay(10);
}

void checkRFID() {
  if (mRFID.isCard()) {
    mRFID.readCardSerial();
    String code = "";
    for (byte i = 0; i <= 4; i++)
    {
      code += String (mRFID.serNum[i], HEX);
      code.toUpperCase();
    }
    DEBUG_PRINTLN("Read code:");
    DEBUG_PRINTLN(code);
    DEBUG_PRINTLN();
    
    for (String allowedCode : allowedCards) {
      if (allowedCode == code) {
        if (lastRFIDAction == 0) { //checks if the door has been closed or opened the last time
          processSingleRunnable(openDoor);
          lastRFIDAction = 1;
        } else if (lastRFIDAction == 1) {
          processSingleRunnable(closeDoor);
          lastRFIDAction = 0;
        }
      }
    }
    delay(2000);
  }
}

void processSingleRunnable(String msg) {
  charsIndex[0] = msg.indexOf("!");
  charsIndex[1] = msg.indexOf("!", charsIndex[0] + 1);
  charsIndex[2] = msg.indexOf("!", charsIndex[1] + 1);
  charsIndex[3] = msg.indexOf("!", charsIndex[2] + 1);
  
  PIN = msg.substring(charsIndex[0] + 1 , charsIndex[1]).toInt();
  relayMode = msg.substring(charsIndex[1] + 1, charsIndex[2]).toInt();
  del = msg.substring(charsIndex[2] + 1, charsIndex[3]).toInt();

  DEBUG_PRINTLN();
  DEBUG_PRINTLN("- OPENING -");
  DEBUG_PRINT("Pin: ");
  DEBUG_PRINT(String(PIN));
  DEBUG_PRINT("; Mode: ");
  DEBUG_PRINT(String(relayMode));
  DEBUG_PRINT("; Delay: ");
  DEBUG_PRINTLN(msg.substring(charsIndex[2] + 1, charsIndex[3]));
  DEBUG_PRINTLN("(0 --> ON, 1 --> OFF, 2 --> PUSH, 3 --> TOGGLE)");

  if (0 <= relayMode <= 2 && startingPIN <= PIN <= finishPIN)
  {
    if (relayMode == 0) {
      digitalWrite(PIN, MHIGH); //relay on
    }
    else if (relayMode == 1) {
      digitalWrite(PIN, MLOW);
    }
    else if (relayMode == 2) {
      homotica.pushPin(PIN, del, digitalRead(PIN));
    }
    else if (relayMode == 3) {
      digitalWrite(PIN, !digitalRead(PIN));
    }
  }
}

void processMultipleRunnable(String msg) {
  char input[msg.length() + 1];
  msg.toCharArray(input, msg.length() + 1);
  const char* divider = ("+");
  int lastIndex = 0;
  for (int k = 0; k < sizeof(input); k++) {
    if (String(input[k]) == "+") {
      processSingleRunnable(msg.substring(lastIndex, k));
      k += 1;
      lastIndex = k;
    }
  }
}

Homotica library

Credits

Davide Vertuani

Davide Vertuani

3 projects • 71 followers

Comments