#include <WiFi.h>
#include <HTTPClient.h>
#include <SoftwareSerial.h>
#include <ESP32Servo.h>
#include <WiFiClientSecure.h>

// Ganti dengan SSID dan password Wi-Fi Anda
const char * ssid = "Wokwi-GUEST";
const char * password = "";
//const char * serverName = "http://api.dilaundry.online/iot/smart-washing-machine";
const char * serverName = "http://jsonplaceholder.typicode.com/posts/1";

unsigned long previousMillis = 0;
const unsigned long interval = 5000; // Interval pengiriman data (5 detik)

// Pin
const int trigPin = 12;
const int echoPin = 14;
const int vibrationButtonPin = 23;
const int relaySolenoidInletPin = 22;
const int relayBuzzerPin = 16;
const int relayMotorWasherPin = 21;
const int relayMotorSpinnerPin = 17;
const int relayMotorOutletPin = 19;

const int waterSensor1Pin = 32; //inner water level
const int waterSensor2Pin = 33; //outlet water exists
const int turbidityPin = 34;
const int rainDropPin = 35; //spinner

int servoWasherPin = 26;
int servoWasherModePin = 14;
int servoSpinnerPin = 25;
int servoOutletPin = 27;

Servo servoWasher;
Servo servoWasherMode;
Servo servoSpinner;
Servo servoOutlet;
void setup() {
	Serial.begin(9600);
	Serial.println("Starting script!");

	WiFi.begin(ssid, password);

	pinMode(trigPin, OUTPUT);
	pinMode(echoPin, INPUT);
	pinMode(vibrationButtonPin, INPUT_PULLUP);
	pinMode(relaySolenoidInletPin, OUTPUT);
	pinMode(relayBuzzerPin, OUTPUT);
	pinMode(relayMotorWasherPin, OUTPUT);
	pinMode(relayMotorSpinnerPin, OUTPUT);
	pinMode(relayMotorOutletPin, OUTPUT);
	pinMode(waterSensor1Pin, INPUT);
	pinMode(waterSensor2Pin, INPUT);
	pinMode(turbidityPin, INPUT);
	pinMode(rainDropPin, INPUT);


	setupServos();

	while (WiFi.status() != WL_CONNECTED) {
		delay(1000);
		Serial.println("Connecting to WiFi...");
	}
	Serial.println("Connected to WiFi");
}

void setupServos() {
	// Mengatur pin untuk masing-masing servo
	servoWasher.attach(servoWasherPin);
	servoWasherMode.attach(servoWasherModePin);
	servoSpinner.attach(servoSpinnerPin);
	servoOutlet.attach(servoOutletPin);

	// Mengatur posisi akhir servo
	servoWasher.write(180); delay(1000); servoWasher.write(0); delay(1000);
	servoWasherMode.write(180); delay(1000); servoWasherMode.write(0); delay(1000);
	servoSpinner.write(180); delay(1000); servoSpinner.write(0); delay(1000);
	servoOutlet.write(180); delay(1000); servoOutlet.write(0); delay(1000);
}
void loop() {
	delay(1000);
	Serial.println("Loop!");


	unsigned long currentMillis = millis();
	String dataToSend = "";

	if (currentMillis - previousMillis >= interval) {
		previousMillis = currentMillis;

		int ultrasonicValue = readUltrasonicSensor();
		int turbidityValue = readTurbiditySensor();
		int vibrationValue = readVibrationButton();
		int waterSensor1Value = readWaterSensor1();
		int waterSensor2Value = readWaterSensor2();
		int rainDropValue = readRainDropSensor();

		dataToSend += "sensor_ultrasonic:" + String(ultrasonicValue) + "|";
		dataToSend += "sensor_turbidity:" + String(turbidityValue) + "|";
		dataToSend += "sensor_getaran:" + String(vibrationValue) + "|";
		dataToSend += "sensor_ketinggian_air:" + String(waterSensor1Value) + "|";
		dataToSend += "sensor_water_outlet:" + String(waterSensor2Value) + "|";
		dataToSend += "sensor_raindrop:" + String(rainDropValue) + "|";

		sendData(dataToSend);
	}
}

int readUltrasonicSensor() {
	long duration;
	int distance;
	digitalWrite(trigPin, LOW);
	delayMicroseconds(2);
	digitalWrite(trigPin, HIGH);
	delayMicroseconds(10);
	digitalWrite(trigPin, LOW);
	duration = pulseIn(echoPin, HIGH);
	distance = duration * 0.0344 / 2; // Menghitung jarak dalam cm
	return distance;
}

int readTurbiditySensor() {
	return analogRead(turbidityPin);
}

int readVibrationButton() {
	return digitalRead(vibrationButtonPin) == LOW ? 1 : 0;
}

int readWaterSensor1() {
	return analogRead(waterSensor1Pin);
}

int readWaterSensor2() {
	return analogRead(waterSensor2Pin);
}

int readRainDropSensor() {
	return analogRead(rainDropPin);
}

void sendData(String data) {
	if (WiFi.status() == WL_CONNECTED) {
		WiFiClientSecure client;
		client.setInsecure(); // This is not secure, use setCACert for production

		HTTPClient http;
		http.begin(client, serverName);
		//http.addHeader("Content-Type", "application/x-www-form-urlencoded");



		//HTTPClient http;
		//http.begin(serverName);
		http.addHeader("Content-Type", "text/plain");

		String postData = "data=" + data;
		Serial.print("serverName:");
		Serial.print(serverName);
		Serial.print("SendData:");
		Serial.print(postData);
		int httpResponseCode = http.POST(postData);

		if (httpResponseCode > 0) {
			Serial.print("HttpReq Finish");
			String response = http.getString();
			parseServerResponse(response);
		} else {

			Serial.print("Error on HTTP request. HTTP Response Code: ");
			Serial.println(httpResponseCode);
			Serial.print("Error Message: ");
			Serial.println(http.errorToString(httpResponseCode));
		}
		http.end();
	} else {
		Serial.println("WiFi Disconnected");
	}
}

void parseServerResponse(String response){
	Serial.println("parseServerResponse: start");
	int pos;
	while ((pos = response.indexOf('|')) >= 0) {
		String line = response.substring(0, pos);
		response.remove(0, pos + 1);

		int delimiterPos = line.indexOf(':');
		if (delimiterPos >= 0) {
			String key = line.substring(0, delimiterPos);
			String value = line.substring(delimiterPos + 1);

			if (key.startsWith("relay_")) {
	      		Serial.println("parseServerResponse: relay: " + key + " = " + value);
				bool state = (value == "true");
				if (key == "relay_solenoid_inlet") {
					digitalWrite(relaySolenoidInletPin, state ? HIGH : LOW);
				}else if (key == "relay_buzzer") {
					digitalWrite(relayBuzzerPin, state ? HIGH : LOW);
				}else if (key == "relay_motor_washer") {
					digitalWrite(relayMotorWasherPin, state ? HIGH : LOW);
				}else if (key == "relay_motor_spinner") {
					digitalWrite(relayMotorSpinnerPin, state ? HIGH : LOW);
				}else if (key == "relay_motor_outlet") {
					digitalWrite(relayMotorOutletPin, state ? HIGH : LOW);
				}
			}else if (key.startsWith("servo_")) {
	      		Serial.println("parseServerResponse: servo: " + key + " = " + value);
				// servo_washer:12|servo_washer_mode:10|servo_spinner:21|servo_outlet:112
				int angle = value.toInt();

				// Mengatur posisi servo
				if (key == "servo_washer") {
					servoWasher.write(angle);
				}else if (key == "servo_washer_mode") {
					servoWasherMode.write(angle);
				}else if (key == "servo_spinner") {
					servoSpinner.write(angle);
				}else if (key == "servo_outlet") {
					servoOutlet.write(angle);
				}
			}

		}
	}
}
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module