Imagine a world where your home adapts to your needs effortlessly. In this comprehensive guide, we delve into the realm of home automation using the ESP32 microcontroller and the Senric Pro platform. With the power of Google Assistant, Alexa, and manual switches, you can now control your home appliances with ease, making your living space truly intelligent and responsive.
ESP32 Board: A versatile microcontroller with built-in WiFi and Bluetooth capabilities.
Senric Pro Account: Create an account on the Senric Pro platform for seamless device management.
Home Appliances: Choose appliances compatible with relays or smart plugs.
Relays or Smart Plugs: Essential for remote appliance control.
Manual Switches: For physical control alongside digital methods.
Google Assistant Account: Set up a Google Assistant account.
Amazon Alexa Account: Prepare an Alexa developer account.
The goal of this project is to establish a streamlined home automation system that employs the ESP32 and the Senric Pro platform. By integrating Google Assistant, Alexa, and manual switches, you'll achieve a unified control mechanism for your appliances.
#include <Arduino.h>
#include "SinricPro.h"
#include "SinricProSwitch.h"
#include <map>
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti;
const uint32_t connectTimeoutMs = 5000;
#define WIFI_SSID "veera"
#define WIFI_PASS "87654321"
#define APP_KEY "bbd9f3b7-c981-46d4-9f5b-5be348b4b0d0" // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET "8238eaa4-a4df-4e0c-809f-cef99d0f8708-6d5ed641-50a1-4950-80ce-5ea398562c9d" // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
//Enter the device IDs here
#define device_ID_1 "645ba775743f912070158163"
#define device_ID_2 "645ba7ff929949c1da637f62"
#define device_ID_3 "645ba82c743f912070158435"
#define device_ID_4 "SWITCH_ID_NO_4_HERE"
// define the GPIO connected with Relays and switches
#define RelayPin1 5 //d1
#define RelayPin2 4//d2
#define RelayPin3 0//d3
#define SwitchPin1 14//d5
#define SwitchPin2 12//d6
#define SwitchPin3 13//d7
#define wifiLed 2
// comment the following line if you use a toggle switches instead of tactile buttons
//#define TACTILE_BUTTON 1
#define BAUD_RATE 9600
#define DEBOUNCE_TIME 250
typedef struct { // struct for the std::map below
int relayPIN;
int flipSwitchPIN;
} deviceConfig_t;
// this is the main configuration
// please put in your deviceId, the PIN for Relay and PIN for flipSwitch
// this can be up to N devices...depending on how much pin's available on your device ;)
// right now we have 4 devicesIds going to 4 relays and 4 flip switches to switch the relay manually
std::map<String, deviceConfig_t> devices = {
//{deviceId, {relayPIN, flipSwitchPIN}}
{device_ID_1, { RelayPin1, SwitchPin1 }},
{device_ID_2, { RelayPin2, SwitchPin2 }},
{device_ID_3, { RelayPin3, SwitchPin3 }}
};
typedef struct { // struct for the std::map below
String deviceId;
bool lastFlipSwitchState;
unsigned long lastFlipSwitchChange;
} flipSwitchConfig_t;
std::map<int, flipSwitchConfig_t> flipSwitches; // this map is used to map flipSwitch PINs to deviceId and handling debounce and last flipSwitch state checks
// it will be setup in "setupFlipSwitches" function, using informations from devices map
void setupRelays() {
for (auto &device : devices) { // for each device (relay, flipSwitch combination)
int relayPIN = device.second.relayPIN; // get the relay pin
pinMode(relayPIN, OUTPUT); // set relay pin to OUTPUT
digitalWrite(relayPIN, HIGH);
}
}
void setupFlipSwitches() {
for (auto &device : devices) { // for each device (relay / flipSwitch combination)
flipSwitchConfig_t flipSwitchConfig; // create a new flipSwitch configuration
flipSwitchConfig.deviceId = device.first; // set the deviceId
flipSwitchConfig.lastFlipSwitchChange = 0; // set debounce time
flipSwitchConfig.lastFlipSwitchState = true; // set lastFlipSwitchState to false (LOW)--
int flipSwitchPIN = device.second.flipSwitchPIN; // get the flipSwitchPIN
flipSwitches[flipSwitchPIN] = flipSwitchConfig; // save the flipSwitch config to flipSwitches map
pinMode(flipSwitchPIN, INPUT_PULLUP); // set the flipSwitch pin to INPUT
}
}
bool onPowerState(String deviceId, bool &state)
{
Serial.printf("%s: %s\r\n", deviceId.c_str(), state ? "on" : "off");
int relayPIN = devices[deviceId].relayPIN; // get the relay pin for corresponding device
digitalWrite(relayPIN, !state); // set the new relay state
return true;
}
void handleFlipSwitches() {
unsigned long actualMillis = millis(); // get actual millis
for (auto &flipSwitch : flipSwitches) { // for each flipSwitch in flipSwitches map
unsigned long lastFlipSwitchChange = flipSwitch.second.lastFlipSwitchChange; // get the timestamp when flipSwitch was pressed last time (used to debounce / limit events)
if (actualMillis - lastFlipSwitchChange > DEBOUNCE_TIME) { // if time is > debounce time...
int flipSwitchPIN = flipSwitch.first; // get the flipSwitch pin from configuration
bool lastFlipSwitchState = flipSwitch.second.lastFlipSwitchState; // get the lastFlipSwitchState
bool flipSwitchState = digitalRead(flipSwitchPIN); // read the current flipSwitch state
if (flipSwitchState != lastFlipSwitchState) { // if the flipSwitchState has changed...
#ifdef TACTILE_BUTTON
if (flipSwitchState) { // if the tactile button is pressed
#endif
flipSwitch.second.lastFlipSwitchChange = actualMillis; // update lastFlipSwitchChange time
String deviceId = flipSwitch.second.deviceId; // get the deviceId from config
int relayPIN = devices[deviceId].relayPIN; // get the relayPIN from config
bool newRelayState = !digitalRead(relayPIN); // set the new relay State
digitalWrite(relayPIN, newRelayState); // set the trelay to the new state
SinricProSwitch &mySwitch = SinricPro[deviceId]; // get Switch device from SinricPro
mySwitch.sendPowerStateEvent(!newRelayState); // send the event
#ifdef TACTILE_BUTTON
}
#endif
flipSwitch.second.lastFlipSwitchState = flipSwitchState; // update lastFlipSwitchState
}
}
}
}
void setupWiFi()
{
Serial.printf("\r\n[Wifi]: Connecting");
WiFi.persistent(false);
Serial.println("\nESP8266 Multi WiFi example");
// Set WiFi to station mode
WiFi.mode(WIFI_STA);
// Register multi WiFi networks
wifiMulti.addAP("veera", "87654321");
wifiMulti.addAP("mewt", "87654321");
wifiMulti.addAP("GOONWIFI_83A8", "0000003814");
wifiMulti.addAP("Redmi K20 Pro", "87654321");
if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED)
{
Serial.printf(".");
delay(250);
}
digitalWrite(wifiLed, LOW);
Serial.printf("connected!\r\n[WiFi]: IP-Address is %s\r\n", WiFi.localIP().toString().c_str());
}
void setupSinricPro()
{
for (auto &device : devices)
{
const char *deviceId = device.first.c_str();
SinricProSwitch &mySwitch = SinricPro[deviceId];
mySwitch.onPowerState(onPowerState);
}
SinricPro.begin(APP_KEY, APP_SECRET);
SinricPro.restoreDeviceStates(true);
}
void setup()
{
Serial.begin(BAUD_RATE);
pinMode(wifiLed, OUTPUT);
digitalWrite(wifiLed, HIGH);
setupRelays();
setupFlipSwitches();
setupWiFi();
setupSinricPro();
}
void loop()
{
if (WiFi.status() != WL_CONNECTED)
{
digitalWrite(wifiLed, LOW);
}
else{
digitalWrite(wifiLed, 1);
}
SinricPro.handle();
handleFlipSwitches();
}
With the ESP32, Senric Pro, Google Assistant, Alexa, and manual switches working in harmony, you've successfully orchestrated a symphony of home automation. Your home responds to your voice and touch, turning your living space into an intelligent haven. This project not only showcases your technical prowess but also empowers you to redefine how you interact with your environment. So, gather your tools, follow the steps outlined in this guide, and embark on the journey of creating a seamlessly automated home that truly understands and caters to your needs.
0 Comments