#include <WiFi.h>
#include <ThingerESP32.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ====== Konfigurasi Thinger.io ======
#define USERNAME "ibnuyunanto"
#define DEVICE_ID "esp32relay"
#define DEVICE_CREDENTIAL "ibnuganteng"
// ====== WiFi Wokwi ======
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
ThingerESP32 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
// ====== OLED Setting ======
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// ====== Pin Hardware ======
#define SENSOR_PIN 34
#define RELAY1 25
#define RELAY2 26
// ====== Batas Suhu Default ======
int T_ON1 = 30;
int T_ON2 = 40;
// ====== Variabel Runtime ======
float tempC = 0.0;
bool wifiConnected = false;
bool thingerConnected = false;
// ====== Fungsi baca suhu (ADC → °C) ======
float readTemperature() {
int adc = analogRead(SENSOR_PIN);
float volt = adc * (3.3 / 4095.0);
float temp = volt * 100.0;
return temp;
}
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println();
Serial.println("=== ESP32 Temperature Control System ===");
// pin relay
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, LOW);
// OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED gagal!");
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("Starting...");
display.display();
// WiFi connection dengan timeout
Serial.println("Connecting to WiFi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
int wifiTimeout = 0;
while (WiFi.status() != WL_CONNECTED && wifiTimeout < 20) {
delay(500);
Serial.print(".");
wifiTimeout++;
}
if(WiFi.status() == WL_CONNECTED) {
wifiConnected = true;
Serial.println();
Serial.print("WiFi Connected! IP: ");
Serial.println(WiFi.localIP());
// Setup Thinger.io resources
thing["relay1"] << digitalPin(RELAY1);
thing["relay2"] << digitalPin(RELAY2);
// Resource untuk mengirim data suhu (OUTPUT)
thing["temperature"] >> [](pson& out){
out = tempC;
};
// Resource threshold (INPUT/OUTPUT)
thing["threshold"] << [](pson& in){
if(in["t1"].is_empty() == false) T_ON1 = (int)in["t1"];
if(in["t2"].is_empty() == false) T_ON2 = (int)in["t2"];
Serial.print("Threshold updated - T1: ");
Serial.print(T_ON1);
Serial.print(", T2: ");
Serial.println(T_ON2);
};
thing["threshold"] >> [](pson& out){
out["t1"] = T_ON1;
out["t2"] = T_ON2;
};
Serial.println("Thinger.io resources configured");
} else {
wifiConnected = false;
Serial.println();
Serial.println("WiFi connection failed! Running in offline mode...");
}
Serial.println("Setup complete!");
}
void loop() {
// baca suhu PERTAMA
tempC = readTemperature();
Serial.print("Temp: ");
Serial.print(tempC);
Serial.println("°C");
// Handle Thinger.io hanya jika WiFi connected
if(wifiConnected && WiFi.status() == WL_CONNECTED) {
thing.handle();
// Stream data temperature ke Thinger.io
thing.stream(thing["temperature"]);
Serial.println("Data sent to Thinger.io");
thingerConnected = true;
} else {
thingerConnected = false;
if(WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi disconnected, trying to reconnect...");
WiFi.reconnect();
delay(5000);
}
}
// kontrol otomatis relay
bool relay1State = (tempC > T_ON1);
bool relay2State = (tempC > T_ON2);
digitalWrite(RELAY1, relay1State ? HIGH : LOW);
digitalWrite(RELAY2, relay2State ? HIGH : LOW);
// tampilkan di OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
// Status koneksi
display.print("WiFi: ");
display.println(wifiConnected ? "OK" : "FAIL");
display.print("Thinger: ");
display.println(thingerConnected ? "OK" : "FAIL");
// Data suhu dan relay
display.print("Temp: ");
display.print(tempC, 1);
display.println(" C");
display.print("T1:");
display.print(T_ON1);
display.print(" R1:");
display.println(relay1State ? "ON":"OFF");
display.print("T2:");
display.print(T_ON2);
display.print(" R2:");
display.println(relay2State ? "ON":"OFF");
display.display();
delay(2000);
}