Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /********* Pleasedontcode.com **********
- Pleasedontcode thanks you for automatic code generation! Enjoy your code!
- - Terms and Conditions:
- You have a non-exclusive, revocable, worldwide, royalty-free license
- for personal and commercial use. Attribution is optional; modifications
- are allowed, but you're responsible for code maintenance. We're not
- liable for any loss or damage. For full terms,
- please visit pleasedontcode.com/termsandconditions.
- - Project: # Relay Controller
- - Source Code NOT compiled for: ESP8266 NodeMCU V1.0
- - Source Code created on: 2026-02-05 14:55:51
- ********* Pleasedontcode.com **********/
- /****** SYSTEM REQUIREMENTS *****/
- /****** SYSTEM REQUIREMENT 1 *****/
- /* add i2c gpio expander PCF8574 */
- /****** END SYSTEM REQUIREMENTS *****/
- #include "PCF8574.h"
- #include "Relay.h"
- #include "VoiceAssistant.h"
- // Create PCF8574 instance with default I2C address 0x20
- // Address range: 0x20 to 0x27 depending on A0, A1, A2 pins
- PCF8574 expander(0x20);
- // Create Relay instance for managing 8 relays
- Relay relayController(&expander, 8);
- // Create VoiceAssistant instance
- VoiceAssistant* voiceAssistant = nullptr;
- // WiFi Configuration
- // IMPORTANT: Replace these with your actual WiFi credentials
- const char* WIFI_SSID = "YourWiFiSSID";
- const char* WIFI_PASSWORD = "YourWiFiPassword";
- // Google Cloud Speech-to-Text API Configuration
- // IMPORTANT: Replace these with your actual Google Cloud credentials
- const char* GOOGLE_API_KEY = "YOUR_GOOGLE_CLOUD_API_KEY_HERE";
- const char* GOOGLE_PROJECT_ID = "YOUR_GOOGLE_PROJECT_ID_HERE";
- // Serial command buffer
- String commandBuffer = "";
- // Timestamp for periodic status monitoring
- unsigned long lastStatusTime = 0;
- unsigned long statusInterval = 5000; // Print status every 5 seconds
- // Voice command request flag
- volatile bool voiceCommandRequested = false;
- unsigned long voiceCommandRequestTime = 0;
- const unsigned long voiceCommandDebounce = 1000; // Debounce time for voice command requests
- // Relay state change log
- struct RelayLog {
- uint32_t timestamp;
- uint8_t relayNum;
- bool state; // true = ON, false = OFF
- char action[20];
- };
- // Log buffer for relay state changes (last 10 changes)
- RelayLog relayLogs[10];
- uint8_t logIndex = 0;
- /****** FUNCTION PROTOTYPES *****/
- void setup(void);
- void loop(void);
- void processSerialCommand(String command);
- void handleRelayCommand(String command);
- void printAvailableCommands(void);
- void logRelayStateChange(uint8_t relayNum, bool newState, const char* action);
- void printRelayLogs(void);
- void printRelayStatusMonitoring(void);
- void processVoiceCommand(void);
- void initializeVoiceAssistant(void);
- void setup(void)
- {
- // Initialize Serial communication
- Serial.begin(115200);
- delay(100);
- Serial.println("\n\n================================================");
- Serial.println(" PCF8574 I2C GPIO Expander with Relays ");
- Serial.println(" + Voice Assistant Support ");
- Serial.println("================================================");
- Serial.println();
- // Initialize PCF8574 with I2C address 0x20
- // Using default ESP8266 pins: SDA=4 (D2), SCL=5 (D1)
- Serial.println("Initializing PCF8574 I2C GPIO Expander...");
- if (expander.begin()) {
- Serial.println("[SUCCESS] PCF8574 initialized successfully!");
- Serial.print("[INFO] I2C Address: 0x");
- Serial.println(0x20, HEX);
- Serial.println("[INFO] I2C Pins: SDA=4 (D2), SCL=5 (D1)");
- // Initialize all relay pins to HIGH (default/inactive state)
- expander.writePort(0xFF);
- Serial.println("[INFO] All relay pins set to HIGH (inactive)");
- delay(500);
- // Initialize Relay controller
- Serial.println();
- Serial.println("Initializing Relay Controller...");
- relayController.init();
- Serial.println();
- Serial.println("[SUCCESS] System fully initialized and ready!");
- Serial.println();
- // Initialize Voice Assistant with WiFi and Google Cloud API
- delay(1000);
- Serial.println();
- initializeVoiceAssistant();
- delay(1000);
- // Print help information
- printAvailableCommands();
- // Initialize log timestamps
- lastStatusTime = millis();
- } else {
- Serial.println("[ERROR] Failed to initialize PCF8574!");
- Serial.println("[ERROR] Please check:");
- Serial.println(" - I2C connections (SDA=D2/GPIO4, SCL=D1/GPIO5)");
- Serial.println(" - PCF8574 I2C address (default 0x20, check A0/A1/A2 pins)");
- Serial.println(" - PCF8574 power supply (VCC and GND)");
- Serial.println();
- Serial.println("System will continue but relay control may not work.");
- }
- delay(1000);
- }
- void loop(void)
- {
- // Check for serial commands
- if (Serial.available()) {
- char inChar = Serial.read();
- // Handle enter key (carriage return or newline)
- if (inChar == '\r' || inChar == '\n') {
- if (commandBuffer.length() > 0) {
- Serial.println(); // Echo newline
- Serial.print("[COMMAND] ");
- Serial.println(commandBuffer);
- processSerialCommand(commandBuffer);
- commandBuffer = ""; // Clear buffer
- }
- }
- // Handle backspace
- else if (inChar == '\b') {
- if (commandBuffer.length() > 0) {
- commandBuffer.remove(commandBuffer.length() - 1);
- Serial.print(inChar); // Echo backspace
- }
- }
- // Add character to buffer
- else if (inChar >= 32 && inChar <= 126) { // Printable ASCII characters
- commandBuffer += inChar;
- Serial.print(inChar); // Echo character
- }
- }
- // Check if voice command was requested via serial
- if (voiceCommandRequested && (millis() - voiceCommandRequestTime >= voiceCommandDebounce)) {
- voiceCommandRequested = false;
- processVoiceCommand();
- }
- // Periodic status monitoring and logging
- if (millis() - lastStatusTime >= statusInterval) {
- lastStatusTime = millis();
- printRelayStatusMonitoring();
- }
- // Small delay to prevent watchdog timeout
- delay(10);
- }
- // Initialize VoiceAssistant with WiFi and Google Cloud API credentials
- void initializeVoiceAssistant(void) {
- Serial.println("=== Initializing Voice Assistant System ===");
- // Create VoiceAssistant instance
- voiceAssistant = new VoiceAssistant(&relayController);
- if (voiceAssistant == nullptr) {
- Serial.println("[ERROR] Failed to allocate memory for VoiceAssistant!");
- return;
- }
- // Begin voice assistant initialization with WiFi and API credentials
- if (voiceAssistant->begin(WIFI_SSID, WIFI_PASSWORD, GOOGLE_API_KEY, GOOGLE_PROJECT_ID)) {
- Serial.println("[SUCCESS] Voice Assistant initialized successfully!");
- // Configure audio settings (16kHz, Mono, 16-bit, 10 second timeout)
- voiceAssistant->setAudioConfig(16000, 1, 16, 10000);
- // Print voice assistant status
- voiceAssistant->printStatus();
- voiceAssistant->printConfiguration();
- Serial.println("=== Voice Assistant Ready ===");
- Serial.println("[INFO] Voice commands are now available!");
- Serial.println("[INFO] Type 'voice' command to process voice commands");
- Serial.println("[INFO] Type 'vtest <command>' to test voice parsing");
- Serial.println();
- } else {
- Serial.println("[ERROR] Failed to initialize Voice Assistant!");
- Serial.println("[ERROR] WiFi connection failed or API credentials invalid");
- Serial.println("[INFO] System will continue with relay control only");
- // Clean up on failure
- delete voiceAssistant;
- voiceAssistant = nullptr;
- }
- Serial.println("========================================");
- Serial.println();
- }
- // Process voice command from microphone
- void processVoiceCommand(void) {
- if (voiceAssistant == nullptr) {
- Serial.println("[ERROR] Voice Assistant not initialized!");
- return;
- }
- if (!voiceAssistant->isInitialized()) {
- Serial.println("[ERROR] Voice Assistant not ready!");
- return;
- }
- Serial.println();
- Serial.println("================================================");
- Serial.println(" Starting Voice Command Processing ");
- Serial.println("================================================");
- // Process voice command from microphone
- VoiceCommandResult result = voiceAssistant->processVoiceCommand();
- Serial.println();
- Serial.print("[VOICE] Processing Result: ");
- switch(result) {
- case VOICE_CMD_SUCCESS:
- Serial.println("SUCCESS");
- Serial.println("[VOICE] Command executed successfully!");
- break;
- case VOICE_CMD_WIFI_NOT_CONNECTED:
- Serial.println("ERROR - WiFi Not Connected");
- Serial.println("[VOICE] Attempting to reconnect to WiFi...");
- voiceAssistant->reconnectWiFi();
- break;
- case VOICE_CMD_API_ERROR:
- Serial.println("ERROR - Google Cloud API Error");
- Serial.println("[VOICE] Failed to communicate with Google Cloud Speech-to-Text API");
- break;
- case VOICE_CMD_AUDIO_CAPTURE_FAILED:
- Serial.println("ERROR - Audio Capture Failed");
- Serial.println("[VOICE] Failed to capture audio from microphone");
- break;
- case VOICE_CMD_PARSE_FAILED:
- Serial.println("ERROR - Command Parse Failed");
- Serial.println("[VOICE] Could not parse the recognized speech into a valid command");
- break;
- case VOICE_CMD_INVALID_RELAY:
- Serial.println("ERROR - Invalid Relay Number");
- Serial.println("[VOICE] The recognized relay number is out of range (0-7)");
- break;
- case VOICE_CMD_TIMEOUT:
- Serial.println("ERROR - Command Timeout");
- Serial.println("[VOICE] Voice command processing timed out");
- break;
- case VOICE_CMD_BUSY:
- Serial.println("ERROR - System Busy");
- Serial.println("[VOICE] Voice Assistant is currently busy processing a command");
- break;
- default:
- Serial.println("UNKNOWN ERROR");
- break;
- }
- Serial.println();
- Serial.println("================================================");
- Serial.println();
- // Print current relay status
- relayController.printStatus();
- // Print voice command log
- voiceAssistant->printVoiceCommandLog();
- }
- // Process serial commands from user
- void processSerialCommand(String command) {
- // Convert to lowercase for case-insensitive handling
- command.toLowerCase();
- // Trim whitespace
- command.trim();
- // Empty command
- if (command.length() == 0) {
- return;
- }
- // Help command
- if (command == "help" || command == "?") {
- printAvailableCommands();
- return;
- }
- // Status command - print current relay states
- if (command == "status" || command == "s") {
- Serial.println();
- relayController.printStatus();
- Serial.println();
- return;
- }
- // Logs command - print relay change logs
- if (command == "logs" || command == "l") {
- Serial.println();
- printRelayLogs();
- Serial.println();
- return;
- }
- // Clear logs command
- if (command == "clrlogs" || command == "cl") {
- logIndex = 0;
- Serial.println("[INFO] Relay logs cleared");
- Serial.println();
- return;
- }
- // Voice Assistant commands
- if (voiceAssistant != nullptr) {
- // Voice command - process audio from microphone
- if (command == "voice" || command == "v") {
- voiceCommandRequested = true;
- voiceCommandRequestTime = millis();
- return;
- }
- // Voice test command - test voice parsing with a string
- if (command.startsWith("vtest ")) {
- String testCommand = command.substring(6);
- testCommand.trim();
- if (testCommand.length() > 0) {
- Serial.println();
- Serial.println("=== Testing Voice Command Parsing ===");
- Serial.print("[VOICE] Test command: ");
- Serial.println(testCommand);
- VoiceCommandResult result = voiceAssistant->executeCommandFromString(testCommand);
- Serial.println();
- Serial.print("[VOICE] Parse result: ");
- switch(result) {
- case VOICE_CMD_SUCCESS:
- Serial.println("SUCCESS");
- break;
- case VOICE_CMD_PARSE_FAILED:
- Serial.println("PARSE FAILED");
- break;
- case VOICE_CMD_INVALID_RELAY:
- Serial.println("INVALID RELAY");
- break;
- default:
- Serial.println("ERROR");
- break;
- }
- Serial.println("[VOICE] ====================================");
- Serial.println();
- relayController.printStatus();
- } else {
- Serial.println("[ERROR] Please provide a test command. Usage: vtest <command>");
- }
- return;
- }
- // Voice command log command
- if (command == "vlogs" || command == "vl") {
- voiceAssistant->printVoiceCommandLog();
- return;
- }
- // Clear voice command logs
- if (command == "vclrlogs" || command == "vcl") {
- voiceAssistant->clearVoiceCommandLog();
- Serial.println();
- return;
- }
- // Voice assistant status command
- if (command == "vstatus" || command == "vs") {
- voiceAssistant->printStatus();
- return;
- }
- // Voice assistant configuration command
- if (command == "vconfig" || command == "vc") {
- voiceAssistant->printConfiguration();
- return;
- }
- }
- // Turn off all relays
- if (command == "alloff" || command == "off") {
- Serial.println();
- relayController.turnOffAll();
- logRelayStateChange(255, false, "ALL OFF");
- relayController.printStatus();
- Serial.println();
- return;
- }
- // Test mode - cycle through all relays
- if (command == "test" || command == "t") {
- Serial.println();
- Serial.println("[TEST] Starting relay test sequence...");
- Serial.println("[TEST] Turning ON each relay for 1 second...");
- Serial.println();
- for (uint8_t i = 0; i < 8; i++) {
- Serial.print("[TEST] Testing Relay ");
- Serial.println(i);
- relayController.turnOn(i);
- delay(1000);
- relayController.turnOff(i);
- delay(200);
- }
- Serial.println();
- Serial.println("[TEST] Relay test sequence completed!");
- Serial.println();
- return;
- }
- // Relay control commands
- if (command.startsWith("on ") || command.startsWith("off ") ||
- command.startsWith("toggle ") || command.startsWith("tog ")) {
- handleRelayCommand(command);
- return;
- }
- // Check for single digit commands (quick on/off)
- if (command.length() == 1 && isDigit(command[0])) {
- uint8_t relayNum = command[0] - '0';
- if (relayNum < 8) {
- Serial.println();
- relayController.toggle(relayNum);
- logRelayStateChange(relayNum, relayController.getState(relayNum), "TOGGLE");
- relayController.printStatus();
- Serial.println();
- return;
- }
- }
- // Unknown command
- Serial.println("[ERROR] Unknown command. Type 'help' for available commands.");
- Serial.println();
- }
- // Handle relay-specific commands (on/off/toggle)
- void handleRelayCommand(String command) {
- String action = "";
- uint8_t relayNum = 255;
- Serial.println();
- // Parse "on" commands
- if (command.startsWith("on ")) {
- action = "ON";
- command = command.substring(3);
- command.trim();
- if (command.length() > 0 && isDigit(command[0])) {
- relayNum = command[0] - '0';
- }
- }
- // Parse "off" commands
- else if (command.startsWith("off ")) {
- action = "OFF";
- command = command.substring(4);
- command.trim();
- if (command.length() > 0 && isDigit(command[0])) {
- relayNum = command[0] - '0';
- }
- }
- // Parse "toggle" or "tog" commands
- else if (command.startsWith("toggle ")) {
- action = "TOGGLE";
- command = command.substring(7);
- command.trim();
- if (command.length() > 0 && isDigit(command[0])) {
- relayNum = command[0] - '0';
- }
- }
- else if (command.startsWith("tog ")) {
- action = "TOGGLE";
- command = command.substring(4);
- command.trim();
- if (command.length() > 0 && isDigit(command[0])) {
- relayNum = command[0] - '0';
- }
- }
- // Execute command if relay number is valid
- if (relayNum < 8) {
- if (action == "ON") {
- relayController.turnOn(relayNum);
- logRelayStateChange(relayNum, true, "ON");
- }
- else if (action == "OFF") {
- relayController.turnOff(relayNum);
- logRelayStateChange(relayNum, false, "OFF");
- }
- else if (action == "TOGGLE") {
- relayController.toggle(relayNum);
- logRelayStateChange(relayNum, relayController.getState(relayNum), "TOGGLE");
- }
- relayController.printStatus();
- } else {
- Serial.print("[ERROR] Invalid relay number. Use 0-7. Got: ");
- Serial.println(command);
- }
- Serial.println();
- }
- // Print available commands
- void printAvailableCommands(void) {
- Serial.println();
- Serial.println("================================================");
- Serial.println(" Available Serial Commands ");
- Serial.println("================================================");
- Serial.println();
- Serial.println("Relay Control Commands:");
- Serial.println(" on <n> - Turn ON relay n (0-7)");
- Serial.println(" off <n> - Turn OFF relay n (0-7)");
- Serial.println(" toggle <n> - Toggle relay n (0-7)");
- Serial.println(" tog <n> - Toggle relay n (0-7) [shorthand]");
- Serial.println(" <n> - Quick toggle relay n (0-7)");
- Serial.println(" alloff - Turn OFF all relays");
- Serial.println(" off - Turn OFF all relays [shorthand]");
- Serial.println();
- Serial.println("Voice Assistant Commands (requires WiFi & API credentials):");
- Serial.println(" voice, v - Process voice command from microphone");
- Serial.println(" vtest <cmd> - Test voice parsing with command string");
- Serial.println(" vlogs, vl - Display voice command logs");
- Serial.println(" vclrlogs,vc - Clear voice command logs");
- Serial.println(" vstatus, vs - Display voice assistant status");
- Serial.println(" vconfig, vc - Display voice assistant configuration");
- Serial.println();
- Serial.println("System Commands:");
- Serial.println(" status, s - Display current relay status");
- Serial.println(" logs, l - Display relay change log");
- Serial.println(" clrlogs, cl - Clear relay change log");
- Serial.println(" test, t - Run relay test sequence");
- Serial.println(" help, ? - Display this help message");
- Serial.println();
- Serial.println("Example: Type 'on 0' to turn ON relay 0");
- Serial.println("Example: Type 'vtest turn on relay 3' to test voice parsing");
- Serial.println("================================================");
- Serial.println();
- }
- // Log relay state changes
- void logRelayStateChange(uint8_t relayNum, bool newState, const char* action) {
- // Special handling for "ALL OFF" action
- if (relayNum == 255) {
- // Log all relays being turned off
- for (uint8_t i = 0; i < 8; i++) {
- RelayLog& log = relayLogs[logIndex % 10];
- log.timestamp = millis();
- log.relayNum = i;
- log.state = false;
- strncpy(log.action, action, sizeof(log.action) - 1);
- log.action[sizeof(log.action) - 1] = '\0';
- logIndex++;
- }
- } else {
- RelayLog& log = relayLogs[logIndex % 10];
- log.timestamp = millis();
- log.relayNum = relayNum;
- log.state = newState;
- strncpy(log.action, action, sizeof(log.action) - 1);
- log.action[sizeof(log.action) - 1] = '\0';
- logIndex++;
- }
- }
- // Print relay state change logs
- void printRelayLogs(void) {
- Serial.println("=== Relay Change Log (Last 10 changes) ===");
- if (logIndex == 0) {
- Serial.println("No relay changes recorded yet.");
- } else {
- // Calculate start index for circular buffer
- uint8_t startIdx = (logIndex >= 10) ? (logIndex % 10) : 0;
- uint8_t count = (logIndex >= 10) ? 10 : logIndex;
- for (uint8_t i = 0; i < count; i++) {
- uint8_t idx = (startIdx + i) % 10;
- RelayLog& log = relayLogs[idx];
- Serial.print("[");
- Serial.print(log.timestamp / 1000);
- Serial.print("s] Relay ");
- Serial.print(log.relayNum);
- Serial.print(": ");
- Serial.print(log.state ? "ON" : "OFF");
- Serial.print(" (");
- Serial.print(log.action);
- Serial.println(")");
- }
- }
- Serial.println("===========================================");
- }
- // Print relay status monitoring with periodic updates
- void printRelayStatusMonitoring(void) {
- // Calculate uptime
- uint32_t uptimeSeconds = millis() / 1000;
- uint8_t hours = uptimeSeconds / 3600;
- uint8_t minutes = (uptimeSeconds % 3600) / 60;
- uint8_t seconds = uptimeSeconds % 60;
- Serial.println();
- Serial.println("--------- Relay Status Monitor (Periodic) --------");
- Serial.print("Uptime: ");
- if (hours < 10) Serial.print("0");
- Serial.print(hours);
- Serial.print(":");
- if (minutes < 10) Serial.print("0");
- Serial.print(minutes);
- Serial.print(":");
- if (seconds < 10) Serial.print("0");
- Serial.println(seconds);
- // Print all relay states
- Serial.println("Current Relay States:");
- for (uint8_t i = 0; i < 8; i++) {
- Serial.print(" Relay ");
- Serial.print(i);
- Serial.print(": ");
- Serial.println(relayController.getState(i) ? "ON " : "OFF");
- }
- // Print number of logged changes
- Serial.print("Total logged relay changes: ");
- Serial.println(logIndex);
- // Print voice assistant status if available
- if (voiceAssistant != nullptr && voiceAssistant->isInitialized()) {
- Serial.print("Voice Assistant WiFi: ");
- Serial.println(voiceAssistant->isWiFiConnected() ? "CONNECTED" : "DISCONNECTED");
- Serial.print("Voice Commands Logged: ");
- Serial.println(voiceAssistant->getCommandLogCount());
- // Attempt to reconnect WiFi if disconnected
- if (!voiceAssistant->isWiFiConnected()) {
- Serial.println("[INFO] Attempting WiFi reconnection...");
- voiceAssistant->reconnectWiFi();
- }
- }
- Serial.println("--------------------------------------------------");
- Serial.println();
- }
- /* END CODE */
Advertisement
Add Comment
Please, Sign In to add comment