#include <ESP8266WiFi.h>
#include <MQTT.h>

// Wi-Fi credentials
const char* ssid = "StudentResidences";      // WIFI name
const char* pass = "";   // WIFI password

// MQTT details
const char* myBroker = "test.mosquitto.org";  // MQTT address
const char* mqttTopic = "HamishDB/SubHamish"; // Topic the data goes to

WiFiClient net;
MQTTClient client;

unsigned long lastMillis = 0; 

// Dust sensor units
#define COV_RATIO 0.2  // ug/mmm / mv
#define NO_DUST_VOLTAGE 400  // mv
#define SYS_VOLTAGE 5000

const int iled = D0;  
const int vout = A0;  
float density, voltage;
int adcvalue;

// to connect to the WIFI
void connectToWiFi() {
  Serial.print("Connecting to Wi-Fi...");
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("\nConnected to Wi-Fi!");
}

// to connect to the MQTT
void connectToMQTT() {
  Serial.print("Connecting to MQTT...");
  while (!client.connect("HamishB", "", "")) {  // client ID
    Serial.print(".");
    delay(1000);
  }
  Serial.println("\nConnected to MQTT!");
}

void setup() {
  Serial.begin(115200);

  // actually connects to Wi-Fi
  connectToWiFi();

  // Sets up the MQTT 
  client.begin(myBroker, net);
  connectToMQTT();
  
  // Sets up the dust sensor
  pinMode(iled, OUTPUT);
  digitalWrite(iled, LOW);  // Default closed
}

void loop() {
  client.loop();  // Keeps the MQTT connected

  // Reconnect to MQTT
  if (!client.connected()) {
    connectToMQTT();
  }

  // Dust sensor reading
  digitalWrite(iled, HIGH);
  delayMicroseconds(280);
  adcvalue = analogRead(vout);
  digitalWrite(iled, LOW);
  
  voltage = (SYS_VOLTAGE / 1024.0) * adcvalue * 11;

  // Calculate dust concentration
  if (voltage >= NO_DUST_VOLTAGE) {
    voltage -= NO_DUST_VOLTAGE;
    density = voltage * COV_RATIO;
  } else {
    density = 0;
  }

  // Send data to MQTT 
  if (millis() - lastMillis > 1) {
    lastMillis = millis();
    
    // Print out dust density in Serial Monitor
    Serial.print("Publishing dust concentration: ");
    Serial.println(density);

    // Publish the dust sensor data (density), including units
    String payload = "{\"dust_density\": " + String(density) + ", ";
    payload += "\"COV_ratio\": " + String(COV_RATIO) + ", ";
    payload += "\"units\": \"ug/m3\"}";

    
    client.publish(mqttTopic, payload);
  }

  delay(10);  // Delay
}
