#include #include #include #include #include #include #include // OLED display setup (on I2C bus 0) #define OLED_SDA 18 #define OLED_SCL 19 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 32 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // Second I2C bus for other sensors/devices #define I2C2_SDA 1 #define I2C2_SCL 2 TwoWire I2C_Two = TwoWire(1); // MQTT/WiFi config char mqtt_server[40] = ""; char mqtt_port[6] = "8080"; char api_token[34] = "YOUR_API_TOKEN"; bool shouldSaveConfig = false; void saveConfigCallback() { shouldSaveConfig = true; display.clearDisplay(); display.setCursor(0, 0); display.println("Saving config..."); display.display(); } void showStatus(const String& line1, const String& line2 = "", const String& line3 = "") { display.clearDisplay(); display.setCursor(0, 0); display.println(line1); if (!line2.isEmpty()) display.println(line2); if (!line3.isEmpty()) display.println(line3); display.display(); } void setup() { Serial.begin(115200); // Start both I2C buses Wire.begin(OLED_SDA, OLED_SCL); I2C_Two.begin(I2C2_SDA, I2C2_SCL); // OLED init if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println("SSD1306 allocation failed"); while (1); } display.setTextSize(1); display.setTextColor(WHITE); showStatus("Booting..."); // Mount SPIFFS if (!SPIFFS.begin(true)) { showStatus("SPIFFS mount", "failed!"); delay(2000); } else if (SPIFFS.exists("/config.json")) { File configFile = SPIFFS.open("/config.json", "r"); if (configFile) { DynamicJsonDocument json(256); DeserializationError err = deserializeJson(json, configFile); if (!err) { strlcpy(mqtt_server, json["mqtt_server"] | "", sizeof(mqtt_server)); strlcpy(mqtt_port, json["mqtt_port"] | "8080", sizeof(mqtt_port)); strlcpy(api_token, json["api_token"] | "YOUR_API_TOKEN", sizeof(api_token)); } configFile.close(); } } // WiFiManager parameters WiFiManagerParameter custom_mqtt_server("server", "MQTT Server", mqtt_server, 40); WiFiManagerParameter custom_mqtt_port("port", "MQTT Port", mqtt_port, 6); WiFiManagerParameter custom_api_token("apikey", "API Token", api_token, 33); WiFiManager wifiManager; wifiManager.setSaveConfigCallback(saveConfigCallback); wifiManager.addParameter(&custom_mqtt_server); wifiManager.addParameter(&custom_mqtt_port); wifiManager.addParameter(&custom_api_token); showStatus("Connecting WiFi..."); if (!wifiManager.autoConnect("AutoConnectAP", "password")) { showStatus("WiFi Connect", "Failed!", "Restarting..."); delay(3000); ESP.restart(); } // Update config values strlcpy(mqtt_server, custom_mqtt_server.getValue(), sizeof(mqtt_server)); strlcpy(mqtt_port, custom_mqtt_port.getValue(), sizeof(mqtt_port)); strlcpy(api_token, custom_api_token.getValue(), sizeof(api_token)); // Save config if needed if (shouldSaveConfig) { DynamicJsonDocument json(256); json["mqtt_server"] = mqtt_server; json["mqtt_port"] = mqtt_port; json["api_token"] = api_token; File configFile = SPIFFS.open("/config.json", "w"); if (configFile) { serializeJson(json, configFile); configFile.close(); } } // Show final info (truncate to fit OLED) String ipStr = WiFi.localIP().toString(); if (ipStr.length() > 15) ipStr = ipStr.substring(0, 15); showStatus("WiFi OK: " + ipStr, "MQTT: " + String(mqtt_server), "Port: " + String(mqtt_port)); } void loop() { // You can use I2C_Two for other sensors/devices here }