// ---------------------- BLYNK SETUP ----------------------
#define BLYNK_TEMPLATE_ID "TMPL6LAORBBx2" //masukin template ID kalian
#define BLYNK_TEMPLATE_NAME "gemini"
#define BLYNK_DEVICE_NAME "gemini"
#define BLYNK_AUTH_TOKEN "ENA0lg268mxnv-7RRWYqz3gX2MmvhVAy" //masukin token kalian
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <BlynkSimpleEsp32.h>
#include "secrets.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>
// ---------------------- KONFIGURASI ----------------------
#define LED_PIN 23 //Menetapkan "nama" LED_PIN untuk pin 23, agar kode lebih mudah dibaca.
String inputStr = ""; //simpan input dari blynk
bool newInput = false; //mengecek input baru
// Endpoint Gemini API
const String endpoint = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=" + String(API_KEY);
// ---------------------- WIFI CONNECT ----------------------
void connectWifi() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(400);
Serial.print(".");
}
Serial.println();
Serial.print("Connected. IP: ");
Serial.println(WiFi.localIP());
}
// ---------------------- GEMINI REQUEST ----------------------
String makeGeminiRequest(const String& userInput) {
//deklar objek client dan objek http untuk komunikasi
WiFiClientSecure client;
client.setInsecure();
HTTPClient http;
//buat url= pastikan url endpoint selalu string
String url = String(endpoint);
//mulai komunikasi, berikan tanda apakah komunikasi gagal
if(!http.begin(client, url)){
return "failed begin HTTP";
}
http.addHeader("Content-Type", "application/json");
/*siapkan data yang dikirim, dengan header, prompt, dan integrasi user input,
hingga menjadi payload yang bisa dikirk
Yang akan digunakan : */
String systemPrompt =
"You are a simple classifier. "
"Only answer with one word: HIGH or LOW. "
"Rules: If the situation describes day, bright, light, or visible → respond LOW. "
"If the situation describes night, dark, not visible → respond HIGH. "
"Do not explain.";
String finalPrompt = systemPrompt + String("user input : " + userInput);
String payload = String("{\"contents\":[{\"parts\":[{\"text\":\"") + finalPrompt + "\"}]}]}";
/*
format JSON yang akan dikirim "{\"contents\":[{\"parts\":[{\"text\":\"" +
finalPrompt + "\"}]}]}".
*/
//kirim payload, simoan kode status (integer) dan siapkan tempat untuk respon
int httpCode = http.POST(payload);
String response;
if(httpCode > 0){
response = http.getString();
}else{
response = String("HTTP error") + http.errorToString(httpCode);
}
//tutp koneksi, kirim respon
http.end();
return response;
}
// ---------------------- SETUP ----------------------
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW); //LED mati di awal
connectWifi(); //koneksi WiFi manual
Blynk.begin(BLYNK_AUTH_TOKEN, WIFI_SSID , WIFI_PASSWORD);
Serial.println("ESP32 siap terhubung ke Blynk dan Gemini.");
}
// ---------------------- CALLBACK BLYNK ----------------------
BLYNK_WRITE(V0) {
inputStr = param.asStr(); //baca input sebagai string
newInput = true; //tandai ada input baru
Serial.print("Teks dari Blynk: ");
Serial.println(inputStr);
}
// ---------------------- LOOP ----------------------
void loop() {
Blynk.run();
//hanya jalankan saat ada input baru
if (newInput) {
//reset new input
newInput = false;
//printput input blynk
Serial.println("Mengirim ke gemini : " + inputStr);
String resp = makeGeminiRequest(inputStr);
Serial.println("full respon : ");
Serial.println(resp);
//kirim input blynk dengan function gemini, lalu assign respon di string
//Tetapkan berapa byte (gunakan 2048 saja, pastikan repon tidak terlalu panjang)
DynamicJsonDocument doc(2048);
DeserializationError error = deserializeJson(doc, resp);
//buat objek DeserializationError untuk parameter JSON valid, deserializeJson() parsing JSON ke doc
//jika tidak error proses jawaban
if (!error) {
//ambil data yang diparsing docs, disimpan dengan pointer
const char* text = doc["candidates"][0]["content"]["parts"][0]["text"];
if (text) {
//ubah ke objek string dan proses hasilnya (hapus spasi & uppercase biar bisa dibandingin)
String answer = String(text);
answer.trim();
answer.toUpperCase();
//print out hasil
Serial.println(answer);
//ubah lampu sesuai parameter
if (answer == "HIGH") {
digitalWrite(LED_PIN, HIGH);
Serial.println("LED ON (HIGH)");
} else if (answer == "LOW") {
digitalWrite(LED_PIN, LOW);
Serial.println("LED OFF (LOW)");
} else {
Serial.println("Unknown : " + answer);
}
} else {
Serial.println("teks gaada");
//tidak menemukan text
}
} else { //JSON parsing gagal
Serial.println("JSON parsing gagal : ");
Serial.println(error.c_str());
}
}
}