//industrial workers health and safety system based on IoT
#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

// Ultrasonic Sensor Constants
#define TRIGGER_PIN 12
#define ECHO_PIN 14

// Other Constants
#define DHTPIN 4
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

// Credentials of IBM Accounts
#define ORG "j1q0lx"
#define DEVICE_TYPE "abcd"
#define DEVICE_ID "1234"
#define TOKEN "12345678"

// Customize the above values
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
char publishTopic[] = "iot-2/evt/Data/fmt/json";
char subscribetopic[] = "iot-2/cmd/test/fmt/String";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;

WiFiClient wifiClient;
PubSubClient client(server, 1883, call back, wifiClient);

void setup() {
  Serial.begin(115200);
  dht.begin();
  pinMode(TRIGGER_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  delay(10);
  Serial.println();
  wificonnect();
  mqttconnect();
}

void loop() {
  float temperature = dht.readTemperature();
  int pulse = random(60, 150);
  float distance = getDistance();

  Serial.print("Temperature: ");
  Serial.println(temperature);
  Serial.print("Pulse: ");
  Serial.println(pulse);
  Serial.print("Distance: ");
  Serial.println(distance);

  PublishData(temperature, pulse, distance);
  delay(1000);
  
  if (!client.loop()) {
    mqttconnect();
  }
}

float getDistance() {
  digitalWrite(TRIGGER_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIGGER_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER_PIN, LOW);
  
  unsigned long pulseDuration = pulseIn(ECHO_PIN, HIGH);
  float distance = pulseDuration * 0.034 / 2;
  
  return distance;
}

void PublishData(float temperature, int pulse, float distance) {
  mqttconnect();
  
  String payload = "{\"temperature\":";
  payload += temperature;
  payload += ",\"Pulse\":";
  payload += pulse;
  payload += ",\"Distance\":";
  payload += distance;
  payload += "}";
  
  Serial.print("Sending payload: ");
  Serial.println(payload);
  
  if (client.publish(publishTopic, (char*)payload.c_str())) {
    Serial.println("Publish ok");
  } else {
    Serial.println("Publish failed");
  }
}

void mqttconnect() {
  if (!client.connected()) {
    Serial.print("Reconnecting client to ");
    Serial.println(server);
    while (!client.connect(clientId, authMethod, token)) {
      Serial.print(".");
      delay(500);
    }
    
    initManagedDevice();
    Serial.println();
  }
}

void wificonnect() {
  Serial.println();
  Serial.print("Connecting to ");
  
  WiFi.begin("Wokwi-GUEST", "", 6);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void initManagedDevice() {
  if (client.subscribe(subscribetopic)) {
    Serial.println(subscribetopic);
    Serial.println("subscribe to cmd OK");
  } else {
    Serial.println("subscribe to cmd FAILED");
  }
}

void callback(char* subscribetopic, byte* payload, unsigned int payloadLength) {
  Serial.print("Callback invoked for topic: ");
  Serial.println(subscribetopic);
  
  String data = "";
  for (int i = 0; i < payloadLength; i++) {
    data += (char)payload[i];
  }
  
  Serial.println("Data: " + data);
  data = "";
}