// blynk code
#define BLYNK_TEMPLATE_ID "TMPL3LfQEa7Wh"
#define BLYNK_TEMPLATE_NAME "home automation"
#define BLYNK_AUTH_TOKEN "Aotyiq82Ix0jxVt_lgAB7Yr4rb6a_k1K"
char auth[] = BLYNK_AUTH_TOKEN;
// ESP32 Google Assistant + Alexa + Manual HomeAutomation with Sinric Pro
#define BLYNK_PRINT Serial
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <Arduino.h> //ArduinoJson Library: https://github.com/bblanchon/ArduinoJson
#include <WiFi.h>
#include "SinricPro.h" //SinricPro Library: https://sinricpro.github.io/esp8266-esp32-sdk/
#include "SinricProSwitch.h"
#include <map>
BlynkTimer timer;
// Uncomment the following line to enable serial debug output
//#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DEBUG_ESP_PORT Serial
#define NODEBUG_WEBSOCKETS //arduinoWebSockets Library: https://github.com/Links2004/arduinoWebSockets
#define NDEBUG
#endif
#define WIFI_SSID "Wokwi-GUEST" //Enter WiFi Name
#define WIFI_PASS "" //Enter WiFi Password
#define APP_KEY "6fbfa75c-6643-44f6-a1ee-e70971626509" //Enter APP-KEY
#define APP_SECRET "db8982bb-3e6d-4655-b83d-ee5008b979c9-26f3a03e-b5dc-4167-aed4-6852dd4aa620" //Enter APP-SECRET
//Enter the device IDs here
#define device_ID_1 "65dc3c7938f6f4a3cdb53097" //SWITCH 1 ID
#define device_ID_2 "65f94b1760d81635d1caf65d" //SWITCH 2 ID
#define device_ID_3 "65f94bf438f6f4a3cdc523e8" //SWITCH 3 ID
// define the GPIO connected with Relays and switches
#define RelayPin1 13 //D15
#define RelayPin2 12 //D2
#define RelayPin3 14 //D4
#define RelayPin4 27
#define SwitchPin1 26 //D23
#define SwitchPin2 25 //D22
#define SwitchPin3 33 //D21
#define SwitchPin4 32
int relay1_state = 0;
int relay2_state = 0;
int relay3_state = 0;
int relay4_state = 0;
#define button1_vpin V0
#define button2_vpin V1
#define button3_vpin V2
#define button4_vpin V3
BLYNK_CONNECTED() {
Blynk.syncVirtual(button1_vpin);
Blynk.syncVirtual(button2_vpin);
Blynk.syncVirtual(button3_vpin);
Blynk.syncVirtual(button4_vpin);
}
BLYNK_WRITE(button1_vpin) {
relay1_state = param.asInt();
digitalWrite(RelayPin1, relay1_state);
}
//--------------------------------------------------------------------------
BLYNK_WRITE(button2_vpin) {
relay2_state = param.asInt();
digitalWrite(RelayPin2, relay2_state);
}
//--------------------------------------------------------------------------
BLYNK_WRITE(button3_vpin) {
relay3_state = param.asInt();
digitalWrite(RelayPin3, relay3_state);
}
//--------------------------------------------------------------------------
BLYNK_WRITE(button4_vpin) {
relay4_state = param.asInt();
digitalWrite(RelayPin4, relay4_state);
}
//uncomment the following line if you use Push Buttons to toggle Relays
//#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;
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 = false; // 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.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED)
{
Serial.printf(".");
delay(250);
}
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);
setupRelays();
setupFlipSwitches();
setupWiFi();
setupSinricPro();
Serial.begin(115200);
pinMode(SwitchPin1, INPUT_PULLUP);
pinMode(SwitchPin2, INPUT_PULLUP);
pinMode(SwitchPin3, INPUT_PULLUP);
pinMode(SwitchPin4, INPUT_PULLUP);
pinMode(RelayPin1, OUTPUT);
pinMode(RelayPin2, OUTPUT);
pinMode(RelayPin3, OUTPUT);
pinMode(RelayPin4, OUTPUT);
digitalWrite(RelayPin1, HIGH);
digitalWrite(RelayPin2, HIGH);
digitalWrite(RelayPin3, HIGH);
digitalWrite(RelayPin4, HIGH);
Blynk.virtualWrite(button1_vpin, relay1_state);
Blynk.virtualWrite(button2_vpin, relay2_state);
Blynk.virtualWrite(button3_vpin, relay3_state);
Blynk.virtualWrite(button4_vpin, relay4_state);
Blynk.begin(auth, WIFI_SSID, WIFI_PASS);
}
void loop()
{
SinricPro.handle();
handleFlipSwitches();
listen_push_buttons();
Blynk.run();
timer.run();
}
void listen_push_buttons()
{
if(digitalRead(SwitchPin1) == LOW){
delay(200);
control_relay(1);
Blynk.virtualWrite(button1_vpin, !relay1_state); //update button state
}
else if (digitalRead(SwitchPin2) == LOW){
delay(200);
control_relay(2);
Blynk.virtualWrite(button2_vpin, relay2_state); //update button state
}
else if (digitalRead(SwitchPin3) == LOW){
delay(200);
control_relay(3);
Blynk.virtualWrite(button3_vpin, relay3_state); //update button state
}
else if (digitalRead(SwitchPin4) == LOW){
delay(200);
control_relay(4);
Blynk.virtualWrite(button4_vpin, relay4_state); //update button state
}
}
void control_relay(int relay)
{
if(relay == 1){
relay1_state = !relay1_state;
digitalWrite(RelayPin1, relay1_state);
Serial.print("Relay1 State = ");
Serial.println(relay1_state);
delay(50);
}
else if(relay == 2){
relay2_state = !relay2_state;
digitalWrite(RelayPin2, relay2_state);
delay(50);
}
else if(relay == 3){
relay3_state = !relay3_state;
digitalWrite(RelayPin3, relay3_state);
delay(50);
}
else if(relay == 4){
relay4_state = !relay4_state;
digitalWrite(RelayPin4, relay4_state);
delay(50);
}
}