/*
Wokwi-GUEST

*/


#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "Wokwi-GUEST";       // Replace with your network SSID
const char* password = ""; // Replace with your network password

const char* apiURL = "https://3bb47076-4984-4a3f-b3d1-936e93feabcf-00-23zb62ohp06ip.pike.replit.dev/getotp"; // API URL

const int relayPin = 4;
const int ledPin = 16;

int otpCheckInterval = 20000;  // Interval to make API call (20 seconds)
unsigned long previousMillis = 0;  // Store the time of the last API call

String latestOtp = "";  // Store the OTP from the API

void setup() {
  Serial.begin(115200);
  pinMode(relayPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(relayPin, LOW);  // Initially set relay OFF

  // Connect to WiFi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("Connected!");
}

void loop() {
  unsigned long currentMillis = millis();

  // Check if it's time to make an API call
  if (currentMillis - previousMillis >= otpCheckInterval) {
    previousMillis = currentMillis;

    // Blink the LED 2 times to indicate an API call is being made
    blinkLED(2);

    // Fetch the OTP from the API
    latestOtp = fetchOTPFromAPI();
    Serial.println("Fetched OTP: " + latestOtp);
  }

  // Check if user entered an OTP from Serial Monitor
  if (Serial.available() > 0) {
    String userOtp = Serial.readStringUntil('\n');  // Read input from Serial
    userOtp.trim();  // Remove any trailing spaces or newline characters

    if (userOtp.length() == 4) {  // Ensure it's a 4-character string
      if (userOtp == latestOtp) {
        Serial.println("OTP matched, unlocking door.");
        digitalWrite(relayPin, HIGH);  // Unlock (turn relay ON)
      } else {
        Serial.println("Incorrect OTP, door remains locked.");
        digitalWrite(relayPin, LOW);   // Keep the door locked (relay OFF)
      }
    } else {
      Serial.println("Invalid OTP input. Please enter a 4-digit OTP.");
    }
  }

  delay(10);  // Small delay for stability
}

// Function to blink the LED a certain number of times
void blinkLED(int times) {
  for (int i = 0; i < times; i++) {
    digitalWrite(ledPin, HIGH);  // Turn LED on
    delay(200);
    digitalWrite(ledPin, LOW);   // Turn LED off
    delay(200);
  }
}

// Function to fetch OTP from the API
String fetchOTPFromAPI() {
  if (WiFi.status() == WL_CONNECTED) {  // Check WiFi connection
    HTTPClient http;
    http.begin(apiURL);                 // Specify the URL

    int httpResponseCode = http.GET();  // Send GET request

    if (httpResponseCode == 200) {  // If the response is OK
      String responseBody = http.getString();  // Get the response
      int otpStart = responseBody.indexOf("\"otp\":\"") + 7;  // Find start of OTP
      int otpEnd = responseBody.indexOf("\"", otpStart);      // Find end of OTP
      String otp = responseBody.substring(otpStart, otpEnd);  // Extract OTP
      http.end();  // Close the connection
      return otp;
    } else {
      Serial.println("Error: Unable to fetch OTP. HTTP response code: " + String(httpResponseCode));
      http.end();  // Close the connection
    }
  } else {
    Serial.println("Error: WiFi not connected.");
  }

  return "";  // Return empty string if something goes wrong
}




/*
FlaskApp.py

from flask import Flask, render_template, request, redirect, url_for, jsonify
import random
import sqlite3
import datetime

app = Flask(__name__)


# Function to initialize the SQLite database (called during app startup)
def init_db():
    try:
        conn = sqlite3.connect('otp.db')
        c = conn.cursor()
        # Create table if it doesn't exist
        c.execute('''
            CREATE TABLE IF NOT EXISTS otps (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp TEXT,
                otpvalue TEXT  -- Change OTP value to TEXT
            )
        ''')
        conn.commit()
    except sqlite3.Error as e:
        print(f"Error while creating the database or table: {e}")
    finally:
        if conn:
            conn.close()


# Helper function to ensure the table exists
def ensure_table_exists():
    try:
        conn = sqlite3.connect('otp.db')
        c = conn.cursor()
        # Ensure the table exists, if not create it
        c.execute('''
            CREATE TABLE IF NOT EXISTS otps (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp TEXT,
                otpvalue TEXT
            )
        ''')
        conn.commit()
    except sqlite3.Error as e:
        print(f"Error ensuring the table exists: {e}")
    finally:
        if conn:
            conn.close()


# Helper function to get the latest OTP if it's less than 10 minutes old
def get_latest_valid_otp():
    try:
        ensure_table_exists()  # Ensure table exists before selecting data
        conn = sqlite3.connect('otp.db')
        c = conn.cursor()

        # Retrieve the latest OTP
        c.execute(
            'SELECT timestamp, otpvalue FROM otps ORDER BY id DESC LIMIT 1')
        result = c.fetchone()

        if result:
            otp_time = datetime.datetime.strptime(result[0],
                                                  '%Y-%m-%d %H:%M:%S')
            current_time = datetime.datetime.now()

            # Check if the OTP is less than 10 minutes old
            if (current_time -
                    otp_time).seconds < 600:  # 600 seconds = 10 minutes
                return result[1]
    except sqlite3.Error as e:
        print(f"Error retrieving the OTP from the database: {e}")
    finally:
        if conn:
            conn.close()

    return None


# Route to render the index.html with the OTP if available
@app.route('/')
def index():
    otp = get_latest_valid_otp()  # Get the latest valid OTP
    return render_template('index.html', otp=otp)


# Route to generate OTP
@app.route('/genotp', methods=['POST'])
def generate_otp():
    try:
        otp = str(random.randint(1000,
                                 9999))  # Generate 4-digit OTP as a string
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        ensure_table_exists()  # Ensure table exists before inserting data

        # Save OTP to SQLite database
        conn = sqlite3.connect('otp.db')
        c = conn.cursor()
        c.execute('INSERT INTO otps (timestamp, otpvalue) VALUES (?, ?)',
                  (timestamp, otp))
        conn.commit()

    except sqlite3.Error as e:
        print(f"Error inserting OTP into the database: {e}")
    finally:
        if conn:
            conn.close()

    return redirect(url_for('index'))


# Route to get the latest OTP
@app.route('/getotp', methods=['GET'])
def get_otp():
    conn = sqlite3.connect('otp.db')
    c = conn.cursor()

    # Retrieve the latest OTP
    c.execute('SELECT timestamp, otpvalue FROM otps ORDER BY id DESC LIMIT 1')
    result = c.fetchone()
    conn.close()

    if result:
        otp_time = datetime.datetime.strptime(result[0], '%Y-%m-%d %H:%M:%S')
        current_time = datetime.datetime.now()

        # Check if the OTP is less than 10 seconds old
        if (current_time - otp_time).seconds < 1000:
            return jsonify({'otp': result[1]})  # Return OTP as string
        else:
            return jsonify({'otp': "0000"})  # Return default OTP as string
    else:
        return jsonify({'otp':
                        "0000"})  # Return default OTP as string if no record


if __name__ == '__main__':
    # Initialize the database and ensure table exists on startup
    init_db()
    app.run(debug=True, host='0.0.0.0', port=5000)



index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>OTP Generator</title>
</head>
<body>
    <h1>Generate OTP</h1>
    <form action="/genotp" method="post">
        <button type="submit">Generate OTP</button>
    </form>

    <h2>Latest OTP:</h2>
    {% if otp %}
        <p>Your OTP is: <strong>{{ otp }}</strong></p>
    {% else %}
        <p>No valid OTP available.</p>
    {% endif %}
</body>
</html>



*/
NOCOMNCVCCGNDINLED1PWRRelay Module