1
#include <WiFi.h>
#include <BluetoothSerial.h>
#include <Preferences.h>
#include <WiFiUdp.h>
#include <ArtnetWifi.h>
#include <FastLED.h>
#define CONFIG_PIN 0 // DIO pin to enter config mode (e.g. GPIO0)

// LED Strip
int numLeds = 10; // Default number of LEDs
const int numberOfChannels = numLeds * 3; // Total number of DMX channels you want to receive (1 led = 3 channels)
#define DATA_PIN 12 //The data pin that the WS2812 strips are connected to.
CRGB leds[numLeds];   //<<<<<<<<<<<<<<<<<<<<<<<<<<THIS B@STARD ##########################

// Artnet settings
ArtnetWifi artnet;
const int startUniverse = 0;
bool sendFrame = 1;
int previousDataLength = 0;

BluetoothSerial SerialBT;
// Preferences library instance for NVS storage

Preferences preferences;
String ssid, password;
IPAddress localIP, gateway, subnet, dns;

bool configMode = false;

void saveConfig() {
  preferences.begin("wifi_conf", false);
  preferences.putString("ssid", ssid);
  preferences.putString("pass", password);
  preferences.putUInt("ip", localIP);
  preferences.putUInt("gw", gateway);
  preferences.putUInt("mask", subnet);
  preferences.putUInt("dns", dns);
  preferences.putUInt("numLeds",numLeds);
  preferences.end();
  SerialBT.println("āœ… Configuration saved.");
}

bool loadConfig() {
  preferences.begin("wifi_conf", true);
  ssid = preferences.getString("ssid", "");
  password = preferences.getString("pass", "");
  localIP = IPAddress(preferences.getUInt("ip", 0));
  gateway = IPAddress(preferences.getUInt("gw", 0));
  subnet = IPAddress(preferences.getUInt("mask", 0));
  dns = IPAddress(preferences.getUInt("dns", 0));
  numLeds = IPAddress(preferences.getUInt("numLeds", 0));
 // numberOfChannels = IPAddress(preferences.getUInt("numberOfChannels", 0));
  preferences.end();
  return ssid.length() > 0;
}

void resetConfig() {
  preferences.begin("wifi_conf", false);
  preferences.clear();
  preferences.end();
  SerialBT.println("šŸ”„ WiFi settings cleared.");
}

IPAddress inputIP() {
  SerialBT.println("Enter IP (xxx.xxx.xxx.xxx): ");
  while (!SerialBT.available()) delay(100);
  String ipStr = SerialBT.readStringUntil('\n');
  ipStr.trim();
  return IPAddress(
    ipStr.substring(0, ipStr.indexOf('.')).toInt(),
    ipStr.substring(ipStr.indexOf('.') + 1, ipStr.indexOf('.', ipStr.indexOf('.') + 1)).toInt(),
    ipStr.substring(ipStr.indexOf('.', ipStr.indexOf('.') + 1) + 1, ipStr.lastIndexOf('.')).toInt(),
    ipStr.substring(ipStr.lastIndexOf('.') + 1).toInt()
  );
}

void connectToWiFi() {
  Serial.printf("šŸ”Œ Connecting to SSID: %s\n", ssid.c_str());

  if (localIP != IPAddress(0, 0, 0, 0)) {
    WiFi.config(localIP, gateway, subnet, dns);
    Serial.println("šŸ“ Using static IP settings");
  }

  WiFi.begin(ssid.c_str(), password.c_str());

  int attempts = 20;
  while (WiFi.status() != WL_CONNECTED && attempts-- > 0) {
    delay(500);
    Serial.print(".");
  }

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nāœ… Connected!");
    Serial.print("šŸ“¶ IP Address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("\nāŒ Failed to connect.");
  }
}

void printMenu() {
  String mac = WiFi.macAddress(); // Get MAC address
  SerialBT.println("\n=== ESP32 WiFi Config Menu ===");
  SerialBT.print("šŸ†” MAC Address: ");
  SerialBT.println(mac);
  SerialBT.println("------------------------------");
  SerialBT.println("1. Set SSID");
  SerialBT.println("2. Set Password");
  SerialBT.println("3. Set Static IP");
  SerialBT.println("4. Set Subnet Mask");
  SerialBT.println("5. Set Gateway");
  SerialBT.println("6. Set DNS");
  SerialBT.println("7. Save & Connect to WiFi");
  SerialBT.println("8. Show Current Settings");
  SerialBT.println("9. Reset WiFi/LED Settings");
  SerialBT.println("0. Exit Menu");
  SerialBT.println("------------------------------");
  SerialBT.println("10. Set numLeds");
  SerialBT.print(">> ");
}

void showConfig() {
  SerialBT.println("\nšŸ“„ Current Configuration:");
  SerialBT.printf("SSID: %s\n", ssid.c_str());
  SerialBT.printf("Password: %s\n", password.c_str());
  SerialBT.printf("IP Address: %s\n", localIP.toString().c_str());
  SerialBT.printf("Gateway: %s\n", gateway.toString().c_str());
  SerialBT.printf("Subnet: %s\n", subnet.toString().c_str());
  SerialBT.printf("DNS: %s\n", dns.toString().c_str());
  SerialBT.println("------------------------------");
  SerialBT.printf("Number of LEDs: %d\n", numLeds);
}

void enterConfigMenu() {
  SerialBT.begin("ESP32_Config");
  SerialBT.println("šŸ“² Entering WiFi Config Mode via Bluetooth...");
  printMenu();

  bool inMenu = true;

  while (inMenu) {
    if (SerialBT.available()) {
      char option = SerialBT.read();
      SerialBT.read(); // consume newline
      switch (option) {
        case '1':
          SerialBT.print("Enter SSID: ");
          while (!SerialBT.available()) delay(10);
          ssid = SerialBT.readStringUntil('\n'); ssid.trim();
          break;
        case '2':
          SerialBT.print("Enter Password: ");
          while (!SerialBT.available()) delay(10);
          password = SerialBT.readStringUntil('\n'); password.trim();
          break;
        case '3': localIP = inputIP(); break;
        case '4': subnet = inputIP(); break;
        case '5': gateway = inputIP(); break;
        case '6': dns = inputIP(); break;
        case '7':
          saveConfig();
          connectToWiFi();
          break;
        case '8': showConfig(); break;
        case '9': resetConfig(); break;
        case '0':
          inMenu = false;
          SerialBT.println("šŸ‘‹ Exiting menu.");
          break;
        case '10':
		  SerialBT.print("Enter number of LEDs: ");
          while (!SerialBT.available()) delay(10);
          numLeds = SerialBT.readStringUntil('\n').toInt(); // Add this line to set numLeds
          break;
        default:
          SerialBT.println("āš ļø Invalid option.");
      }
      if (inMenu) printMenu();
    }
  }

  SerialBT.end();
}

void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
{
  sendFrame = 1;
  // set brightness of the whole strip 
  if (universe == 15)
  {
    FastLED.setBrightness(data[0]);
  }
  // read universe and put into the right part of the display buffer
  for (int i = 0; i < length / 3; i++)
  {
    int led = i + (universe - startUniverse) * (previousDataLength / 3);
    if (led < numLeds)
    {
      leds[led] = CRGB(data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
    }
  }
  previousDataLength = length;     
  FastLED.show();
}

void setup() {
  pinMode(CONFIG_PIN, INPUT_PULLDOWN);
  Serial.begin(115200);
  delay(100);
  configMode = digitalRead(CONFIG_PIN);
  Serial.printf("āš™ļø Config Pin is %s\n", configMode ? "HIGH (Entering Config)" : "LOW (Running Main App)");
  if (configMode) {
    enterConfigMenu();
  } else {
    if (loadConfig()) {
      Serial.println("šŸ“‚ Loaded WiFi config. Connecting...");
      connectToWiFi();
  artnet.begin();
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, numLeds);
  // onDmxFrame will execute every time a packet is received by the ESP32
  artnet.setArtDmxCallback(onDmxFrame);
    } else {
      Serial.println("āš ļø No config found. Please reboot with CONFIG_PIN HIGH to set.");
    }
  }
}

void loop() {
  if (!configMode) {
    // šŸ” Your main application logic goes here
  // we call the read function inside the loop
  artnet.read();
  }
}

For immediate assistance, please email our customer support: [email protected]

Download RAW File