CCCPaste

"ESP32 Automation" rev_01

/********* 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: "ESP32 Automation"
	- Source Code NOT compiled for: ESP32 DevKit V1
	- Source Code created on: 2024-07-17 00:16:29

********* Pleasedontcode.com **********/

/****** SYSTEM REQUIREMENTS *****/
/****** SYSTEM REQUIREMENT 1 *****/
	/* create a web server for setting sid and password */
	/* and showing time on rtc  once esp32 has wifi */
	/* connection update rtc from nst.  tun on relay1 */
	/* every second and relay2 every 30 seconds using */
	/* time from rtc */
/****** END SYSTEM REQUIREMENTS *****/

/****** DEFINITION OF LIBRARIES *****/
#include 
#include   //https://github.com/NorthernWidget/DS3231
#include   //https://github.com/tzapu/WiFiManager.git
#include 
#include 
#include 
#include 
#include 
#include 

#ifdef ESP32
  #include 
#endif

/****** FUNCTION PROTOTYPES *****/
void setup(void);
void loop(void);
void updateOutputs(void);
void saveConfigCallback(void);
void isr_TickTock(void);
void handleRoot(void);
void handleNotFound(void);
void updateRTCFromNTP(void);

/***** DEFINITION OF DIGITAL OUTPUT PINS *****/
const uint8_t relay1_RelayModule_Signal_PIN_D4 = 4;
const uint8_t relay2_RelayModule_Signal_PIN_D13 = 13;

/***** DEFINITION OF I2C PINS *****/
const uint8_t rtc_DS3231_I2C_PIN_SDA_D21 = 21;
const uint8_t rtc_DS3231_I2C_PIN_SCL_D22 = 22;
const uint8_t rtc_DS3231_I2C_SLAVE_ADDRESS = 104;

/***** DEFINITION OF OUTPUT RAW VARIABLES *****/
/***** used to store raw data *****/
bool relay1_RelayModule_Signal_PIN_D4_rawData = 0;
bool relay2_RelayModule_Signal_PIN_D13_rawData = 0;

/***** DEFINITION OF OUTPUT PHYSICAL VARIABLES *****/
/***** used to store data after characteristic curve transformation *****/
float relay1_RelayModule_Signal_PIN_D4_phyData = 0.0;
float relay2_RelayModule_Signal_PIN_D13_phyData = 0.0;

/****** DEFINITION OF LIBRARIES CLASS INSTANCES*****/
DS3231 myRTC;  // Initialize DS3231 object
WiFiManager wifiManager;  // Initialize WiFiManager object
WebServer server(80);  // Initialize WebServer on port 80
WiFiUDP ntpUDP;  // Initialize WiFiUDP object
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000);  // Initialize NTPClient to get time from NTP server

/****** WiFiManager Custom Parameters *****/
char mqtt_server[40];
char mqtt_port[6] = "8080";
char api_token[34] = "YOUR_API_TOKEN";
bool shouldSaveConfig = false;

/****** WiFiManager Custom Parameters Instances *****/
WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 6);
WiFiManagerParameter custom_api_token("apikey", "API token", api_token, 32);

void saveConfigCallback() {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

void setup(void) {
  // Initialize I2C communication
  Wire.begin(rtc_DS3231_I2C_PIN_SDA_D21, rtc_DS3231_I2C_PIN_SCL_D22);

  // Initialize Serial communication for debugging
  Serial.begin(9600);
  while (!Serial);

  // Print initialization message
  Serial.println("Starting Serial");

  // Initialize relay pins as outputs
  pinMode(relay1_RelayModule_Signal_PIN_D4, OUTPUT);
  pinMode(relay2_RelayModule_Signal_PIN_D13, OUTPUT);

  // Set Alarm 1 to fire every second
  myRTC.turnOffAlarm(1);
  myRTC.setA1Time(0, 0, 0, 0, 0b00001111, false, false, false);
  myRTC.turnOnAlarm(1);
  myRTC.checkIfAlarm(1);

  // Prevent Alarm 2 from interfering
  myRTC.setA2Time(0, 0, 0xFF, 0b01100000, false, false, false);
  myRTC.turnOffAlarm(2);
  myRTC.checkIfAlarm(2);

  // Attach clock interrupt
  pinMode(2, INPUT_PULLUP);  // Assuming interrupt pin is GPIO 2
  attachInterrupt(digitalPinToInterrupt(2), isr_TickTock, FALLING);

  // Use built-in LED to blink
  pinMode(LED_BUILTIN, OUTPUT);

  // Initialize SPIFFS
  if (SPIFFS.begin()) {
    if (SPIFFS.exists("/config.json")) {
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        size_t size = configFile.size();
        std::unique_ptr buf(new char[size]);
        configFile.readBytes(buf.get(), size);
        DynamicJsonDocument json(1024);
        if (!deserializeJson(json, buf.get())) {
          strcpy(mqtt_server, json["mqtt_server"]);
          strcpy(mqtt_port, json["mqtt_port"]);
          strcpy(api_token, json["api_token"]);
        }
        configFile.close();
      }
    }
  }

  // Set WiFiManager custom parameters
  wifiManager.setSaveConfigCallback(saveConfigCallback);
  wifiManager.addParameter(&custom_mqtt_server);
  wifiManager.addParameter(&custom_mqtt_port);
  wifiManager.addParameter(&custom_api_token);

  // Attempt to connect to WiFi
  if (!wifiManager.autoConnect("AutoConnectAP", "password")) {
    Serial.println("Failed to connect and hit timeout");
    ESP.restart();
  }

  Serial.println("Connected to WiFi");

  // Save custom parameters
  strcpy(mqtt_server, custom_mqtt_server.getValue());
  strcpy(mqtt_port, custom_mqtt_port.getValue());
  strcpy(api_token, custom_api_token.getValue());

  if (shouldSaveConfig) {
    DynamicJsonDocument json(1024);
    json["mqtt_server"] = mqtt_server;
    json["mqtt_port"] = mqtt_port;
    json["api_token"] = api_token;

    File configFile = SPIFFS.open("/config.json", "w");
    if (configFile) {
      serializeJson(json, configFile);
      configFile.close();
    }
  }

  Serial.println("Local IP: " + WiFi.localIP().toString());

  // Initialize web server routes
  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);
  server.begin();

  // Initialize NTP client
  timeClient.begin();
}

void loop(void) {
  // Handle web server
  server.handleClient();

  // Update NTP client
  timeClient.update();

  // Update RTC from NTP if not already updated
  static bool rtcUpdated = false;
  if (!rtcUpdated && WiFi.status() == WL_CONNECTED) {
    updateRTCFromNTP();
    rtcUpdated = true;
  }

  updateOutputs();  // Refresh output data

  static byte state = false;
  static volatile byte tick = 1;

  // If alarm went off, toggle LED
  if (tick) {
    tick = 0;
    state = !state;
    digitalWrite(LED_BUILTIN, state);

    // Optional serial output
    Serial.print("Turning LED ");
    Serial.println(state ? "ON" : "OFF");

    // Clear Alarm 1 flag
    myRTC.checkIfAlarm(1);
  }

  // Loop delay to emulate other running code
  delay(10);
}

void updateOutputs() {
  // Get current time from RTC
  DateTime now = myRTC.getDateTime();

  // Turn on relay1 every second
  relay1_RelayModule_Signal_PIN_D4_rawData = (now.second % 2 == 0);

  // Turn on relay2 every 30 seconds
  relay2_RelayModule_Signal_PIN_D13_rawData = (now.second % 30 == 0);

  // Update relay states
  digitalWrite(relay1_RelayModule_Signal_PIN_D4, relay1_RelayModule_Signal_PIN_D4_rawData);
  digitalWrite(relay2_RelayModule_Signal_PIN_D13, relay2_RelayModule_Signal_PIN_D13_rawData);
}

void isr_TickTock() {
  // Interrupt signals to loop
  static volatile byte tick = 1;
}

void handleRoot() {
  String html = "

ESP32 Web Server

"; html += "

Current Time: " + myRTC.getDateTime().toString() + "

"; html += "
"; html += "SSID:
"; html += "Password:
"; html += ""; html += "
"; server.send(200, "text/html", html); } void handleNotFound() { server.send(404, "text/plain", "404: Not found"); } void updateRTCFromNTP() { // Get time from NTP time_t epochTime = timeClient.getEpochTime(); struct tm *ptm = gmtime(&epochTime); // Update RTC with NTP time myRTC.setDateTime(ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); Serial.println("RTC updated from NTP"); }