#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SDA_PIN 21 // Replace with your actual SDA pin
#define SCL_PIN 22 // Replace with your actual SCL pin
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET, SDA_PIN, SCL_PIN);
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DEBUG_ESP_PORT Serial
#define NODEBUG_WEBSOCKETS
#define NDEBUG
#endif
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include "SinricPro.h"
#include "SinricProSwitch.h"
#include <map>
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASS ""
#define APP_KEY "c9b93268-8e83-4217-9e4b-a5b85a530322"
#define APP_SECRET "09ee2670-76d4-41c3-8b18-211c1e6da614-31465693-d034-4cec-ad84-737147fb8b0b"
#define device_ID_1 "6555a3cd22527fb23182836e"
#define device_ID_2 "6555a3fb22527fb23182838d"
#define device_ID_3 "6555a416377c5cde8693c77a"
#define device_ID_4 "SWITCH_ID_NO_4_HERE"
#define RelayPin1 13
#define RelayPin2 12
#define RelayPin3 14
#define RelayPin4 27
#define SwitchPin1 26
#define SwitchPin2 25
#define SwitchPin3 33
#define SwitchPin4 32
#define wifiLed 16
#define BAUD_RATE 9600
#define DEBOUNCE_TIME 250
typedef struct {
int relayPIN;
int flipSwitchPIN;
} deviceConfig_t;
std::map<String, deviceConfig_t> devices = {
{"Light-1", { RelayPin1, SwitchPin1 }},
{"Light-2", { RelayPin2, SwitchPin2 }},
{"Light-3", { RelayPin3, SwitchPin3 }},
{"Light-4", { RelayPin4, SwitchPin4 }}
};
typedef struct {
String deviceId;
bool lastFlipSwitchState;
unsigned long lastFlipSwitchChange;
} flipSwitchConfig_t;
std::map<int, flipSwitchConfig_t> flipSwitches;
void setupRelays() {
for (auto &device : devices) {
int relayPIN = device.second.relayPIN;
pinMode(relayPIN, OUTPUT);
digitalWrite(relayPIN, HIGH);
}
}
void setupFlipSwitches() {
for (auto &device : devices) {
flipSwitchConfig_t flipSwitchConfig;
flipSwitchConfig.deviceId = device.first;
flipSwitchConfig.lastFlipSwitchChange = 0;
flipSwitchConfig.lastFlipSwitchState = true;
int flipSwitchPIN = device.second.flipSwitchPIN;
flipSwitches[flipSwitchPIN] = flipSwitchConfig;
pinMode(flipSwitchPIN, INPUT_PULLUP);
}
}
bool onPowerState(String deviceId, bool &state) {
Serial.printf("%s: %s\r\n", deviceId.c_str(), state ? "on" : "off");
int relayPIN = devices[deviceId].relayPIN;
digitalWrite(relayPIN, state ? HIGH : LOW); // Toggle the relay state
return true;
}
void handleFlipSwitches() {
unsigned long actualMillis = millis();
for (auto &flipSwitch : flipSwitches) {
unsigned long lastFlipSwitchChange = flipSwitch.second.lastFlipSwitchChange;
if (actualMillis - lastFlipSwitchChange > DEBOUNCE_TIME) {
int flipSwitchPIN = flipSwitch.first;
bool lastFlipSwitchState = flipSwitch.second.lastFlipSwitchState;
bool flipSwitchState = digitalRead(flipSwitchPIN);
if (flipSwitchState != lastFlipSwitchState) {
#ifdef TACTILE_BUTTON
if (flipSwitchState) {
#endif
flipSwitch.second.lastFlipSwitchChange = actualMillis;
String deviceId = flipSwitch.second.deviceId;
int relayPIN = devices[deviceId].relayPIN;
// Toggle the relay state only when the button is pressed (not released)
if (flipSwitchState) {
bool newRelayState = !digitalRead(relayPIN);
digitalWrite(relayPIN, newRelayState);
SinricProSwitch &mySwitch = SinricPro[deviceId];
mySwitch.sendPowerStateEvent(!newRelayState);
}
#ifdef TACTILE_BUTTON
}
#endif
flipSwitch.second.lastFlipSwitchState = flipSwitchState;
}
}
}
}
void setupWiFi() {
Serial.printf("\r\n[Wifi]: Connecting");
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != 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();
// Initialize the OLED display
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
delay(2000); // Pause for 2 seconds
display.clearDisplay();
display.display();
}
void updateOledDisplay() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("WiFi: ");
display.println(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected");
display.print("IP: ");
display.println(WiFi.localIP());
display.setCursor(0, 20); // Adjust the Y position based on your preference
// Display LED status for each relay
for (auto &device : devices) {
String deviceId = device.first;
int relayPIN = device.second.relayPIN;
bool relayState = digitalRead(relayPIN);
display.print(deviceId + ": ");
display.println(relayState ? "ON" : "OFF");
}
display.display();
}
void loop() {
SinricPro.handle();
handleFlipSwitches();
updateOledDisplay();
}