#include #include #include #include // --- WiFi --- #define WIFI_SSID "GL-AXT1800-714" #define WIFI_PASS "BDX924MWFW" // --- MQTT --- #define MQTT_HOST "192.168.8.101" // your HA IP #define MQTT_PORT 1883 #define MQTT_USER "mqtt_user" // Mosquitto user #define MQTT_PASS "Naughty0pArrot" #define MQTT_CLIENT "esp32c3_fan" // Topics #define TOPIC_TEMP "esp32c3_fan/temperature" #define TOPIC_HUMIDITY "esp32c3_fan/humidity" #define TOPIC_FAN_STATE "esp32c3_fan/fan/state" #define TOPIC_FAN_CMD "esp32c3_fan/fan/set" // HA sends ON/OFF here // --- Pins --- #define DHTPIN 2 #define DHTTYPE DHT22 #define RELAY_PIN 3 // --- Thresholds --- #define TEMP_ON 28.0 #define TEMP_OFF 25.0 // --- OLED --- #define OLED_RESET U8X8_PIN_NONE #define OLED_SDA 5 #define OLED_SCL 6 U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, OLED_RESET, OLED_SCL, OLED_SDA); DHT dht(DHTPIN, DHTTYPE); WiFiClient wifiClient; PubSubClient mqtt(wifiClient); int xOffset = 30; int yOffset = 30; bool fanState = false; void setFan(bool on) { fanState = on; digitalWrite(RELAY_PIN, on ? LOW : HIGH); // active-LOW relay mqtt.publish(TOPIC_FAN_STATE, on ? "ON" : "OFF", true); } void connectWiFi() { Serial.printf("Connecting to %s", WIFI_SSID); WiFi.begin(WIFI_SSID, WIFI_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.printf("\nWiFi connected: %s\n", WiFi.localIP().toString().c_str()); } void connectMQTT() { while (!mqtt.connected()) { Serial.print("Connecting MQTT..."); if (mqtt.connect(MQTT_CLIENT, MQTT_USER, MQTT_PASS)) { Serial.println("connected!"); } else { Serial.printf("failed rc=%d, retry in 5s\n", mqtt.state()); delay(5000); } } } void handle_oled(float tempC, float humidity) { char line1[20], line2[20], line3[20]; snprintf(line1, sizeof(line1), "T: %.1f C", tempC); snprintf(line2, sizeof(line2), "H: %.0f %%", humidity); snprintf(line3, sizeof(line3), "Fan: %s", fanState ? "ON" : "OFF"); u8g2.clearDisplay(); u8g2.clearBuffer(); u8g2.setFont(u8g2_font_4x6_tr); u8g2.drawStr(xOffset, yOffset, line1); u8g2.drawStr(xOffset, yOffset + 10, line2); u8g2.drawStr(xOffset, yOffset + 20, line3); u8g2.sendBuffer(); } void setup() { Serial.begin(115200); dht.begin(); pinMode(RELAY_PIN, OUTPUT); setFan(false); // fan OFF at boot u8g2.begin(); u8g2.setContrast(255); u8g2.setBusClock(400000); u8g2.clearDisplay(); connectWiFi(); mqtt.setServer(MQTT_HOST, MQTT_PORT); connectMQTT(); Serial.println("Ready."); } void loop() { if (!mqtt.connected()) connectMQTT(); mqtt.loop(); float tempC = dht.readTemperature(); float humidity = dht.readHumidity(); if (isnan(tempC) || isnan(humidity)) { Serial.println("DHT22 read failed"); delay(2000); return; } // Auto fan control with hysteresis if (!fanState && tempC >= TEMP_ON) setFan(true); if (fanState && tempC <= TEMP_OFF) setFan(false); // Publish to MQTT char buf[10]; dtostrf(tempC, 4, 1, buf); mqtt.publish(TOPIC_TEMP, buf); dtostrf(humidity, 4, 0, buf); mqtt.publish(TOPIC_HUMIDITY, buf); Serial.printf("T:%.1fC H:%.0f%% Fan:%s\n", tempC, humidity, fanState ? "ON" : "OFF"); handle_oled(tempC, humidity); delay(3000); }