├── .gitattributes └── Alexa_Controlled_with_feedback_ESP32 └── Alexa_Controlled_with_feedback_ESP32.ino /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Alexa_Controlled_with_feedback_ESP32/Alexa_Controlled_with_feedback_ESP32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This is the code for the project called 3 | 4 | Alexa & Manual Controlled Home Automation using Sinric 5 | 6 | This code is written by Sachin Soni on 04.07.2020 7 | 8 | The tutorial Video for the project is uploaded on 9 | our YouTube channel called "techiesms" 10 | 11 | Channel Link - https://www.youtube.com/techiesms 12 | 13 | 14 | techiesms 15 | explore | learn | share 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include // https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries 22 | #include // https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries 23 | #include 24 | 25 | #include // https://github.com/bxparks/AceButton 26 | using namespace ace_button; 27 | WiFiMulti WiFiMulti; 28 | WebSocketsClient webSocket; 29 | WiFiClient client; 30 | 31 | #define MyApiKey "Your_API_Key" // TODO: Change to your sinric API Key. Your API Key is displayed on sinric.com dashboard 32 | #define MySSID "SSID" // TODO: Change to your Wifi network SSID 33 | #define MyWifiPassword "PASS" // TODO: Change to your Wifi network password 34 | 35 | #define HEARTBEAT_INTERVAL 300000 // 5 Minutes 36 | 37 | uint64_t heartbeatTimestamp = 0; 38 | bool isConnected = false; 39 | 40 | // Switch 41 | const int BUTTON1_PIN = 32; 42 | const int BUTTON2_PIN = 35; 43 | const int BUTTON3_PIN = 34; 44 | const int BUTTON4_PIN = 39; 45 | 46 | 47 | //Relays 48 | const int RELAY1_PIN = 15; 49 | const int RELAY2_PIN = 2; 50 | const int RELAY3_PIN = 4; 51 | const int RELAY4_PIN = 22; 52 | 53 | //Status LEDs 54 | const int LED1 = 26; 55 | const int LED2 = 25; 56 | const int LED3 = 27; 57 | 58 | 59 | String device_ID_1 = "DeviceID1"; 60 | String device_ID_2 = "DeviceID2"; 61 | String device_ID_3 = "DeviceID3"; 62 | String device_ID_4 = "DeviceID4"; 63 | 64 | 65 | 66 | ButtonConfig config1; 67 | AceButton button1(&config1); 68 | ButtonConfig config2; 69 | AceButton button2(&config2); 70 | ButtonConfig config3; 71 | AceButton button3(&config3); 72 | ButtonConfig config4; 73 | AceButton button4(&config4); 74 | 75 | 76 | 77 | 78 | void handleEvent1(AceButton*, uint8_t, uint8_t); 79 | void handleEvent2(AceButton*, uint8_t, uint8_t); 80 | void handleEvent3(AceButton*, uint8_t, uint8_t); 81 | void handleEvent4(AceButton*, uint8_t, uint8_t); 82 | 83 | void setPowerStateOnServer(String deviceId, String value); 84 | 85 | // deviceId is the ID assgined to your smart-home-device in sinric.com dashboard. Copy it from dashboard and paste it here 86 | 87 | void turnOn(String deviceId) { 88 | if (deviceId == device_ID_1) // Device ID of first device 89 | { 90 | Serial.print("Turn on device id: "); 91 | Serial.println(deviceId); 92 | digitalWrite(RELAY1_PIN, LOW); 93 | } 94 | if (deviceId == device_ID_2) // Device ID of first device 95 | { 96 | Serial.print("Turn on device id: "); 97 | Serial.println(deviceId); 98 | digitalWrite(RELAY2_PIN, LOW); 99 | } 100 | if (deviceId == device_ID_3) // Device ID of first device 101 | { 102 | Serial.print("Turn on device id: "); 103 | Serial.println(deviceId); 104 | digitalWrite(RELAY3_PIN, LOW); 105 | } 106 | if (deviceId == device_ID_4) // Device ID of first device 107 | { 108 | Serial.print("Turn on device id: "); 109 | Serial.println(deviceId); 110 | digitalWrite(RELAY4_PIN, LOW); 111 | } 112 | 113 | } 114 | 115 | void turnOff(String deviceId) { 116 | if (deviceId == device_ID_1) // Device ID of first device 117 | { 118 | Serial.print("Turn off Device ID: "); 119 | Serial.println(deviceId); 120 | digitalWrite(RELAY1_PIN, HIGH); 121 | } 122 | if (deviceId == device_ID_2) // Device ID of first device 123 | { 124 | Serial.print("Turn off Device ID: "); 125 | Serial.println(deviceId); 126 | digitalWrite(RELAY2_PIN, HIGH); 127 | } 128 | if (deviceId == device_ID_3) // Device ID of first device 129 | { 130 | Serial.print("Turn off Device ID: "); 131 | Serial.println(deviceId); 132 | digitalWrite(RELAY3_PIN, HIGH); 133 | } 134 | if (deviceId == device_ID_4) // Device ID of first device 135 | { 136 | Serial.print("Turn off Device ID: "); 137 | Serial.println(deviceId); 138 | digitalWrite(RELAY4_PIN, HIGH); 139 | } 140 | 141 | } 142 | 143 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 144 | switch (type) { 145 | case WStype_DISCONNECTED: 146 | isConnected = false; 147 | WiFiMulti.addAP(MySSID, MyWifiPassword); 148 | Serial.printf("[WSc] Webservice disconnected from sinric.com!\n"); 149 | break; 150 | case WStype_CONNECTED: { 151 | isConnected = true; 152 | Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload); 153 | Serial.printf("Waiting for commands from sinric.com ...\n"); 154 | } 155 | break; 156 | case WStype_TEXT: { 157 | Serial.printf("[WSc] get text: %s\n", payload); 158 | // Example payloads 159 | 160 | // For Switch or Light device types 161 | // {"deviceId": xxxx, "action": "setPowerState", value: "ON"} // https://developer.amazon.com/docs/device-apis/alexa-powercontroller.html 162 | 163 | // For Light device type 164 | // Look at the light example in github 165 | 166 | #if ARDUINOJSON_VERSION_MAJOR == 5 167 | DynamicJsonBuffer jsonBuffer; 168 | JsonObject& json = jsonBuffer.parseObject((char*)payload); 169 | #endif 170 | #if ARDUINOJSON_VERSION_MAJOR == 6 171 | DynamicJsonDocument json(1024); 172 | deserializeJson(json, (char*) payload); 173 | #endif 174 | String deviceId = json ["deviceId"]; 175 | String action = json ["action"]; 176 | 177 | if (action == "setPowerState") { // Switch or Light 178 | String value = json ["value"]; 179 | if (value == "ON") { 180 | turnOn(deviceId); 181 | } else { 182 | turnOff(deviceId); 183 | } 184 | } 185 | else if (action == "test") { 186 | Serial.println("[WSc] received test command from sinric.com"); 187 | } 188 | } 189 | break; 190 | case WStype_BIN: 191 | Serial.printf("[WSc] get binary length: %u\n", length); 192 | break; 193 | } 194 | } 195 | 196 | void setup() { 197 | Serial.begin(9600); 198 | 199 | WiFiMulti.addAP(MySSID, MyWifiPassword); 200 | Serial.println(); 201 | Serial.print("Connecting to Wifi: "); 202 | Serial.println(MySSID); 203 | 204 | // Waiting for Wifi connect 205 | if (WiFiMulti.run() != WL_CONNECTED) { 206 | delay(500); 207 | Serial.print("Connecting..."); 208 | } 209 | if (WiFiMulti.run() == WL_CONNECTED) { 210 | Serial.println(""); 211 | Serial.print("WiFi connected. "); 212 | Serial.print("IP address: "); 213 | Serial.println(WiFi.localIP()); 214 | } 215 | 216 | // Setup button 217 | // Button uses the built-in pull up register. 218 | pinMode(BUTTON1_PIN, INPUT_PULLUP); // INPUT_PULLUP so no need a 10K resistor 219 | pinMode(BUTTON2_PIN, INPUT_PULLUP); // INPUT_PULLUP so no need a 10K resistor 220 | pinMode(BUTTON3_PIN, INPUT_PULLUP); // INPUT_PULLUP so no need a 10K resistor 221 | pinMode(BUTTON4_PIN, INPUT_PULLUP); // INPUT_PULLUP so no need a 10K resistor 222 | 223 | pinMode(RELAY1_PIN, OUTPUT); 224 | pinMode(RELAY2_PIN, OUTPUT); 225 | pinMode(RELAY3_PIN, OUTPUT); 226 | pinMode(RELAY4_PIN, OUTPUT); 227 | 228 | pinMode(LED1, OUTPUT); 229 | pinMode(LED2, OUTPUT); 230 | pinMode(LED3, OUTPUT); 231 | 232 | digitalWrite(LED1, HIGH); 233 | delay(200); 234 | digitalWrite(LED2, HIGH); 235 | delay(200); 236 | digitalWrite(LED3, HIGH); 237 | delay(200); 238 | 239 | digitalWrite(LED1, LOW); 240 | digitalWrite(LED2, LOW); 241 | digitalWrite(LED3, LOW); 242 | delay(500); 243 | 244 | digitalWrite(LED1, HIGH); 245 | delay(200); 246 | digitalWrite(LED2, HIGH); 247 | delay(200); 248 | digitalWrite(LED3, HIGH); 249 | delay(200); 250 | 251 | digitalWrite(LED1, LOW); 252 | digitalWrite(LED2, LOW); 253 | digitalWrite(LED3, LOW); 254 | 255 | 256 | config1.setEventHandler(button1Handler); 257 | config2.setEventHandler(button2Handler); 258 | config3.setEventHandler(button3Handler); 259 | config4.setEventHandler(button4Handler); 260 | 261 | 262 | button1.init(BUTTON1_PIN); 263 | button2.init(BUTTON2_PIN); 264 | button3.init(BUTTON3_PIN); 265 | button4.init(BUTTON4_PIN); 266 | 267 | 268 | 269 | // server address, port and URL 270 | webSocket.begin("iot.sinric.com", 80, "/"); 271 | 272 | // event handler 273 | webSocket.onEvent(webSocketEvent); 274 | webSocket.setAuthorization("apikey", MyApiKey); 275 | 276 | // try again every 5000ms if connection has failed 277 | webSocket.setReconnectInterval(5000); // If you see 'class WebSocketsClient' has no member named 'setReconnectInterval' error update arduinoWebSockets 278 | } 279 | 280 | void loop() { 281 | 282 | if (WiFiMulti.run() != WL_CONNECTED) 283 | { 284 | Serial.println("Not Connected"); 285 | digitalWrite(LED1, HIGH); 286 | digitalWrite(LED2, LOW); 287 | digitalWrite(LED3, LOW); 288 | } 289 | else 290 | { 291 | Serial.println(" Connected"); 292 | digitalWrite(LED1, HIGH); 293 | digitalWrite(LED2, HIGH); 294 | digitalWrite(LED3, HIGH); 295 | webSocket.loop(); 296 | } 297 | 298 | 299 | button1.check(); 300 | button2.check(); 301 | button3.check(); 302 | button4.check(); 303 | 304 | 305 | if (isConnected) { 306 | uint64_t now = millis(); 307 | 308 | // Send heartbeat in order to avoid disconnections during ISP resetting IPs over night. Thanks @MacSass 309 | if ((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) { 310 | heartbeatTimestamp = now; 311 | webSocket.sendTXT("H"); 312 | } 313 | } 314 | } 315 | 316 | void setPowerStateOnServer(String deviceId, String value) { 317 | #if ARDUINOJSON_VERSION_MAJOR == 5 318 | DynamicJsonBuffer jsonBuffer; 319 | JsonObject& root = jsonBuffer.createObject(); 320 | #endif 321 | #if ARDUINOJSON_VERSION_MAJOR == 6 322 | DynamicJsonDocument root(1024); 323 | #endif 324 | 325 | root["deviceId"] = deviceId; 326 | root["action"] = "setPowerState"; 327 | root["value"] = value; 328 | StreamString databuf; 329 | #if ARDUINOJSON_VERSION_MAJOR == 5 330 | root.printTo(databuf); 331 | #endif 332 | #if ARDUINOJSON_VERSION_MAJOR == 6 333 | serializeJson(root, databuf); 334 | #endif 335 | webSocket.sendTXT(databuf); 336 | } 337 | 338 | void button1Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) { 339 | Serial.println("EVENT1"); 340 | switch (eventType) { 341 | case AceButton::kEventPressed: 342 | Serial.println("kEventPressed"); 343 | setPowerStateOnServer(device_ID_1, "ON"); 344 | digitalWrite(RELAY1_PIN, LOW); 345 | break; 346 | case AceButton::kEventReleased: 347 | Serial.println("kEventReleased"); 348 | setPowerStateOnServer(device_ID_1, "OFF"); 349 | digitalWrite(RELAY1_PIN, HIGH); 350 | break; 351 | } 352 | } 353 | 354 | void button2Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) { 355 | Serial.println("EVENT2"); 356 | switch (eventType) { 357 | case AceButton::kEventPressed: 358 | Serial.println("kEventPressed"); 359 | setPowerStateOnServer(device_ID_2, "ON"); 360 | digitalWrite(RELAY2_PIN, LOW); 361 | break; 362 | case AceButton::kEventReleased: 363 | Serial.println("kEventReleased"); 364 | setPowerStateOnServer(device_ID_2, "OFF"); 365 | digitalWrite(RELAY2_PIN, HIGH); 366 | break; 367 | } 368 | } 369 | 370 | void button3Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) { 371 | Serial.println("EVENT3"); 372 | switch (eventType) { 373 | case AceButton::kEventPressed: 374 | Serial.println("kEventPressed"); 375 | setPowerStateOnServer(device_ID_3, "ON"); 376 | digitalWrite(RELAY3_PIN, LOW); 377 | break; 378 | case AceButton::kEventReleased: 379 | Serial.println("kEventReleased"); 380 | setPowerStateOnServer(device_ID_3, "OFF"); 381 | digitalWrite(RELAY3_PIN, HIGH); 382 | break; 383 | } 384 | } 385 | 386 | void button4Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) { 387 | Serial.println("EVENT4"); 388 | switch (eventType) { 389 | case AceButton::kEventPressed: 390 | Serial.println("kEventPressed"); 391 | setPowerStateOnServer(device_ID_4, "ON"); 392 | digitalWrite(RELAY4_PIN, LOW); 393 | break; 394 | case AceButton::kEventReleased: 395 | Serial.println("kEventReleased"); 396 | setPowerStateOnServer(device_ID_4, "OFF"); 397 | digitalWrite(RELAY4_PIN, HIGH); 398 | break; 399 | } 400 | } 401 | --------------------------------------------------------------------------------