{"status":"success","endpoint":"http://www.api.petani-sikap.com/api/iot/telemetry","sketch":"/*\n  ==============================================================\n  PeTani SIKAP - Program Mikrokontroler ESP32\n  Penerapan Teknologi Artificial dan IoT untuk Sekolah Inovasi Ketahanan Pangan\n  ==============================================================\n  Sensor:\n  - Capacitive Soil Moisture Sensor v1.2 (Pin Analog GPIO 34)\n  - DHT22 Suhu & Kelembaban Udara (Pin Digital GPIO 4)\n  - Relay Pompa Air Otomatis (Pin Digital GPIO 26)\n  - Relay Grow Light / Solenoid (Pin Digital GPIO 27)\n  ==============================================================\n*/\n\n#include <WiFi.h>\n#include <HTTPClient.h>\n#include <ArduinoJson.h> // Library ArduinoJson v6\n#include <DHT.h>\n\n// 1. Pengaturan Wi-Fi Sekolah / Hotspot\nconst char* ssid = \"WiFi_SEKOLAH_SIKAP\";\nconst char* password = \"PasswordSekolah123\";\n\n// 2. URL Endpoint Backend PeTani SIKAP\nconst char* serverUrl = \"http://www.api.petani-sikap.com/api/iot/telemetry\";\nconst char* deviceId = \"ESP32-SIKAP-01\";\n\n// 3. Pin Konfigurasi Sensor & Aktuator\n#define SOIL_PIN 34\n#define DHTPIN 4\n#define DHTTYPE DHT22\n#define RELAY_PUMP 26\n#define RELAY_LAMP 27\n\nDHT dht(DHTPIN, DHTTYPE);\n\n// Kalibrasi Nilai Sensor Tanah Kapasitif (Sesuaikan dengan pengukuran kering/air)\nconst int AirValue = 3200;   // Nilai analog saat sensor kering di udara\nconst int WaterValue = 1300; // Nilai analog saat sensor dicelupkan di air\n\nvoid setup() {\n  Serial.begin(115200);\n  delay(1000);\n  Serial.println(\"\\n=== PeTani SIKAP ESP32 Booting ===\");\n\n  pinMode(RELAY_PUMP, OUTPUT);\n  pinMode(RELAY_LAMP, OUTPUT);\n  digitalWrite(RELAY_PUMP, HIGH); // Relay active LOW (HIGH = MATI)\n  digitalWrite(RELAY_LAMP, HIGH);\n\n  dht.begin();\n\n  // Koneksi ke Wi-Fi\n  Serial.print(\"Menghubungkan ke Wi-Fi \");\n  WiFi.begin(ssid, password);\n  int retry = 0;\n  while (WiFi.status() != WL_CONNECTED && retry < 20) {\n    delay(500);\n    Serial.print(\".\");\n    retry++;\n  }\n\n  if (WiFi.status() == WL_CONNECTED) {\n    Serial.println(\"\\nTerhubung! IP ESP32: \" + WiFi.localIP().toString());\n  } else {\n    Serial.println(\"\\nGagal terhubung WiFi, akan mencoba lagi di loop.\");\n  }\n}\n\nvoid loop() {\n  if (WiFi.status() == WL_CONNECTED) {\n    // 1. Baca Sensor\n    float temp = dht.readTemperature();\n    float hum = dht.readHumidity();\n\n    int rawSoil = analogRead(SOIL_PIN);\n    // Konversi nilai ADC ke persentase 0 - 100%\n    float soilMoisturePercent = map(rawSoil, AirValue, WaterValue, 0, 100);\n    soilMoisturePercent = constrain(soilMoisturePercent, 0, 100);\n\n    // Default pH & TDS (atau dari sensor probe analog jika terpasang)\n    float phLevel = 6.45;\n    int ecTds = 780;\n    float waterLevel = 85.0;\n\n    Serial.printf(\"Suhu: %.1f C | Hum: %.1f %% | Tanah: %.1f %%\n\", temp, hum, soilMoisturePercent);\n\n    // 2. Format JSON Payload\n    StaticJsonDocument<256> doc;\n    doc[\"device_id\"] = deviceId;\n    doc[\"temperature\"] = isnan(temp) ? 27.0 : temp;\n    doc[\"humidity\"] = isnan(hum) ? 65.0 : hum;\n    doc[\"soil_moisture\"] = soilMoisturePercent;\n    doc[\"ph_level\"] = phLevel;\n    doc[\"ec_tds\"] = ecTds;\n    doc[\"water_level\"] = waterLevel;\n\n    String jsonString;\n    serializeJson(doc, jsonString);\n\n    // 3. Kirim via HTTP POST ke Server\n    HTTPClient http;\n    http.begin(serverUrl);\n    http.addHeader(\"Content-Type\", \"application/json\");\n\n    int httpCode = http.POST(jsonString);\n\n    if (httpCode > 0) {\n      String response = http.getString();\n      Serial.println(\"Server Response: \" + response);\n\n      // Parse perintah kontrol relay dari server\n      StaticJsonDocument<300> resDoc;\n      DeserializationError error = deserializeJson(resDoc, response);\n      if (!error && resDoc.containsKey(\"control\")) {\n        int pumpCommand = resDoc[\"control\"][\"pump_state\"];\n        int lampCommand = resDoc[\"control\"][\"lamp_state\"];\n\n        // Eksekusi Relay (Active LOW)\n        digitalWrite(RELAY_PUMP, pumpCommand == 1 ? LOW : HIGH);\n        digitalWrite(RELAY_LAMP, lampCommand == 1 ? LOW : HIGH);\n        Serial.printf(\"Aktuator Update -> Pompa: %d | Lampu: %d\\n\", pumpCommand, lampCommand);\n      }\n    } else {\n      Serial.printf(\"Gagal kirim HTTP, Error: %s\\n\", http.errorToString(httpCode).c_str());\n    }\n    http.end();\n  }\n\n  // Interval pengiriman data setiap 10 detik\n  delay(10000);\n}\n"}