/*
  Author: Siddhant Shah (21122012)

  Aim: To Receive/Transmit Push Button Press Event from/to Node-RED via MQTT.

  Apparatus: Wokwi & Node-RED
*/

// Libraries
#include <WiFi.h>
#include <PubSubClient.h>

// WiFi
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASS ""

// MQTT
#define MQTT_ID          "Push_Button"
#define MQTT_SERVER      "test.mosquitto.org"
#define MQTT_SERVER_PORT 1883
// Topics Subscribed to
#define MQTT_TOPIC_IN    "NUV/Push_Button/SOFTWARE"
// Topics Published on
#define MQTT_TOPIC_OUT   "NUV/Push_Button/HARDWARE"
// Publish Messages
#define MQTT_MESSAGE     "Hardware Push Button Press No. "

// Push Button
#define PUSH_BUTTON_PIN 14

// Instances
WiFiClient   wifiClient;
PubSubClient pubSubClient(wifiClient);

// Functions
// MQTT Call-Back Function
void callback(char* topic, uint8_t* payload, unsigned int length)
{
  String topicStr = String(topic);
  String data     = "";

  static uint16_t counter = 0; // Keeps Track of the Number of Times Software Push Button is Pressed.

  for (uint8_t i = 0; i < length; i++)
  {
    data += char(payload[i]);
  }

  // Software Push Button
  if (topicStr == String(MQTT_TOPIC_IN))
  {
    counter++;                              // Increment Counter by One
    Serial.println(data + String(counter)); // Show Data on Serial Monitor
  }
}

// Setup
void setup()
{
  // Serial (Debug Monitor)
  Serial.begin(115200);

  // WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  Serial.print("\nConnecting to WiFi Network: " + String(WIFI_SSID) + " ");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("\nConnected!");

  // MQTT
  pubSubClient.setServer(MQTT_SERVER, MQTT_SERVER_PORT);
  pubSubClient.setCallback(callback);

  // Hardware Push Button
  pinMode(PUSH_BUTTON_PIN, INPUT_PULLUP);
}

// Loop
void loop()
{
  //delay(10); // this speeds up the simulation

  // Local Variables
  static uint16_t counter = 0; // Keeps Track of the Number of Times Hardware Push Button is Pressed.
         String   data    = String(MQTT_MESSAGE);

  // MQTT
  while (!pubSubClient.connected())
  {
    Serial.println("Connecting to MQTT Server: \"" + String(MQTT_SERVER) + "\" as \"" + String(MQTT_ID) + "\"");
    if (pubSubClient.connect(MQTT_ID))
    {
      Serial.println("Successfully Connected to MQTT Server!");

      // Subscribe to MQTT Topic: In (SOFTWARE)
      if (pubSubClient.subscribe(MQTT_TOPIC_IN))
      {
        Serial.println("Successfully Subscribed to MQTT Topic: \"" + String(MQTT_TOPIC_IN) + "\"");
      }
      else
      {
        Serial.println("Error Subscribing to MQTT Topic: \"" + String(MQTT_TOPIC_IN) + "\"");
      }
    }
    else
    {
      Serial.println("Error Connecting to MQTT Server! (" + String(pubSubClient.state()) + ")");
    }
  }

  pubSubClient.loop();

  if (pubSubClient.connected())
  {
    // Hardware Push Button
    if (!digitalRead(PUSH_BUTTON_PIN))
    {
      counter++;                                          // Increment Counter by One
      data += String(counter);                            // Append Counter Value to the Message String
      Serial.println(data);                               // Show Data on Serial Monitor
      pubSubClient.publish(MQTT_TOPIC_OUT, data.c_str()); // Transmit Data
      delay(1000);                                        // Wait for One Second
    }
  }
}
esp:0
esp:2
esp:4
esp:5
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:21
esp:22
esp:23
esp:25
esp:26
esp:27
esp:32
esp:33
esp:34
esp:35
esp:3V3
esp:EN
esp:VP
esp:VN
esp:GND.1
esp:D2
esp:D3
esp:CMD
esp:5V
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:D1
esp:D0
esp:CLK
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r