#include <WiFi.h>
#include <WebSocketsClient.h>
#include <ArduinoJson.h>

/**
  HCSR04 - 2 (D2, D4, D5<trig>)
  Valves - 2 (D18, D19)
  Pump - 1 (D15/GPIO 15)

  Digital pins: 5.
*/

//Sense
const int TANK1 = 2;
const int TANK2 = 4;
const int TRIG = 5;
//const int TRIG2 = 17;
//Act
const int VALVE1 = 18;
const int VALVE2 = 19;
const int PUMP = 14;

//State
int pS = 0;
int vS[2] = {0, 0};
int waterDistances[2] = { 0, 0 };

//Websocket Server
const char* websocketServer = ":8000/ws/socket-server/";

//ws instance/object
WebSocketsClient WebSocket;

//json
StaticJsonDocument<200> doc;
String jsonString;

void initPins() {
  pinMode(TANK1, INPUT);
  pinMode(TANK2, INPUT);
  pinMode(TRIG, OUTPUT);
  //pinMode(TRIG2, OUTPUT);
  pinMode(VALVE1, OUTPUT);
  pinMode(VALVE2, OUTPUT);
  pinMode(PUMP, OUTPUT);
}

void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) {
  switch (type) {
    case WStype_DISCONNECTED:
      Serial.println("[WebSocket] Disconnected!");
      break;
    case WStype_CONNECTED:
      Serial.println("[WebSocket] Connected!");
      // Send a message after connection
      doc["type"] = "chat_message";
      doc["tank_1"] = "0";
      doc["tank_2"] = "0";
      serializeJson(doc, jsonString);
      Serial.println(jsonString);
      WebSocket.sendTXT(jsonString);
      break;
    case WStype_TEXT:
      Serial.printf("[WebSocket] Message received: %s\n", payload);
      break;
  }
}

void initNetwork(char* SSID, char* password) {
  WiFi.begin("Wokwi-GUEST", "", 6);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("..");
  }
  Serial.println("WiFi connected successfully!");

  WebSocket.begin("47.254.203.55", 80, "/ws/socket-server/");
  WebSocket.onEvent(webSocketEvent);
}

int toggle(int id, int state){
  
  int dev[3] = {VALVE1, VALVE2, PUMP};
  int states[2] = {LOW, HIGH};
  digitalWrite(dev[id], states[!state]);

  return !state;
}

void moderateTank(int* waterDistances) {
  int min, max;
  min = 3, max = 11;

  for (int i = 0; i < 2; i++)
  {
    //if tank i is at min and valve is OFF
    if (waterDistances[i] <= min && !vS[i])
    {
      //open valve i and turn on pump
      vS[i] = toggle(i, vS[i]);
      if (!pS)
        pS = toggle(2, pS);
    }
    //if tank i is at max and valve is ON
    if (waterDistances[i] >= max && vS[i])
    {
      //check if other tank is also full else dont off pump
      //int t = i > 0 ? 1 : 0;
      if (waterDistances[!i] >= max)
      {
        pS = toggle(2, pS);
        vS[i] = toggle(i, vS[i]);
      }
      else
        vS[i] = toggle(i, vS[i]);
    }
  }
}

void getTankLevel(int* waterDistances) {
  unsigned long pulse_duration_1, distance_1, pulse_duration_2, distance_2;
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(20);
  digitalWrite(TRIG, LOW);

  pulse_duration_1 = pulseIn(TANK1, HIGH, 30000);

  // delay(1000);
  // digitalWrite(TRIG2, LOW);
  // delayMicroseconds(2);
  // digitalWrite(TRIG2, HIGH);
  // delayMicroseconds(20);
  // digitalWrite(TRIG2, LOW);
  // pulse_duration_2 = pulseIn(TANK2, HIGH, 30000);

  distance_1 = (pulse_duration_1 * 0.034) / 2;
  //distance_2 = (pulse_duration_2 * 0.034) / 2;

  Serial.println(distance_1);
  delay(1000);
  //Serial.println(distance_2);
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  
  Serial.println("Hello, ESP32!");
  initPins();
  initNetwork("MikOs-PC", "7M9@26a3");
  //initNe();
}

void loop() {
  WebSocket.loop();
  getTankLevel(waterDistances);
  moderateTank(waterDistances);
}
$abcdeabcde151015202530fghijfghij