user2207791
Published © Apache-2.0

Quick & Cheap HomeKit RGB Controller

HomeKit compatible RGB LED controller using the Arduino Ethernet Shield

IntermediateFull instructions provided1,940
Quick & Cheap HomeKit RGB Controller

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Arduino Ethernet Shield 2
Arduino Ethernet Shield 2
×1
LED Strip, 1 m
LED Strip, 1 m
×1
MOSFET Transistor, Switching
MOSFET Transistor, Switching
×3
Resistor 1k ohm
Resistor 1k ohm
×3
AC/DC Power Supply, External Plug In
AC/DC Power Supply, External Plug In
×1
Tactile Switch, Top Actuated
Tactile Switch, Top Actuated
×1
Breadboard (generic)
Breadboard (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×1
iPhone
Apple iPhone
×1

Software apps and online services

HomeKit
Apple HomeKit

Story

Read more

Schematics

button diagram

led strip diagram

Code

ArduinoHomeKitClient.ino

Arduino
/*
  Arduino HomeKit Accessory

 An HTTP server/client interfacing with HomeBridge via the 
 homebridge-http-rgb-push and homebridge-http-notification-server
 plugins. Controls the input of a RGB LED/LED strip via the Home app.

 created 3 aug 2022
 by Francesco Mattiussi
 
 */

#include <SPI.h>
#include <Ethernet.h>

// connections of the three LED outputs and the button input
#define outRed 3
#define outGreen 5
#define outBlue 6
#define switchButton 7

// network properties
char homebridgeServer[] = "your.ip.address.here";
int homebridgePort = 8581;
IPAddress ip(192, 168, 1, 177); // IP address of Arduino (must be equal to the one set on homebridge!)

// request handling
String requestBuffer;

// variables
int powerStatus = 0;
int brightness = 100;
int buttonState = 0;

// color properties
String color = "FFFFFF";
long colorR = 0;
long colorG = 0;
long colorB = 0;

// notification handling
EthernetClient notificationClient;

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {

  pinMode(outRed, OUTPUT);
  pinMode(outGreen, OUTPUT);
  pinMode(outBlue, OUTPUT);
  pinMode(switchButton, INPUT);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print("Arduino HomeKit Accessory");

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start the server
  server.begin();
  Serial.print(" is running at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("==========");
    Serial.println("New client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        
        requestBuffer += c;
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {

          Serial.println("The request has finished, the following data was received: ");

          // extracting the first line
          String firstLine = requestBuffer.substring(0, requestBuffer.indexOf('\n'));
          Serial.println(firstLine);

          // check if the command is present inside the line
          if (firstLine.indexOf("on") != -1) {
            Serial.println("Turning ON");

            powerStatus = 1;

            analogWrite(outRed, colorR);
            analogWrite(outGreen, colorG);
            analogWrite(outBlue, colorB);

            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            client.println(powerStatus);
          }

          if (firstLine.indexOf("off") != -1) {
            Serial.println("Turning OFF");

            powerStatus = 0;

            analogWrite(outRed, 0);
            analogWrite(outGreen, 0);
            analogWrite(outBlue, 0);

            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            client.println(powerStatus);

          }

          if (firstLine.indexOf("set") != -1) {
            color = firstLine.substring(9, 15);
            Serial.print("Color set to: ");
            Serial.println(color);

            long number = strtol( &color[0], NULL, 16);
            colorR = number >> 16;
            colorG = number >> 8 & 0xFF;
            colorB = number & 0xFF;

            Serial.print("With RGB values of R: ");
            Serial.print(colorR);
            Serial.print(" G: ");
            Serial.print(colorG);
            Serial.print(" B: ");
            Serial.println(colorB);

            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            client.println(color);
          }

          if (firstLine.indexOf("brightness") != -1) {
            brightness = firstLine.substring(16, firstLine.indexOf(" ", 16)).toInt();
            Serial.print("Brightness set to: ");
            Serial.println(brightness);

            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            client.println(brightness);
          }

          if (firstLine.indexOf("statuspower") != -1) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            client.println(powerStatus);
            
            Serial.print("Power status sent");
          }

          if (firstLine.indexOf("statusbrightness") != -1) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            client.println(brightness);
            
            Serial.println("Brightness status sent");
          }

          if (firstLine.indexOf("statuscolor") != -1) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            client.println(color);
            
            Serial.println("Color status sent");
          }
          

          requestBuffer = "";
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("Client disconnected");
    Serial.println("==========");
  }

  // switching the status physically by pressing a button
  buttonState = digitalRead(switchButton);

  if (buttonState == HIGH) {
    Serial.println("==========");
    Serial.println("Button changed the state, sending a notification to HomeBridge");
  
    if (notificationClient.connect(homebridgeServer, homebridgePort)) {

      if (powerStatus == 0) {
        powerStatus = 1;
      } else {
        powerStatus = 0;
      }
  
      Serial.print("Successfully connected to: ");
      Serial.println(notificationClient.remoteIP());
  
      notificationClient.println("POST /47110815 HTTP/1.1");
      notificationClient.print("Host: ");
      notificationClient.print(homebridgeServer);
      notificationClient.print(":");
      notificationClient.println(homebridgePort);
      notificationClient.println("User-Agent: Arduino/1.0");

      if (powerStatus == 0) {
        notificationClient.println("Content-Length: 41");
      } else {
        notificationClient.println("Content-Length: 40");
      }
      
      notificationClient.println("Content-Type: application/json");
      notificationClient.println();

      if (powerStatus == 0) {
        notificationClient.println("{\"characteristic\": \"On\",\"value\": \"false\"}");
      } else {
        notificationClient.println("{\"characteristic\": \"On\",\"value\": \"true\"}");
      }
  
      delay(1);
      notificationClient.stop();

      Serial.println("Notification sent");
      Serial.println("==========");
    } else {
      Serial.println("Connection failed");
      Serial.println("==========");
    }
  }
  
}

homebridge-http-rgb-push

homebridge-http-notification-server

Credits

user2207791

user2207791

0 projects • 0 followers

Comments