VibeMon ESP32 devices support automatic WiFi and WebSocket token configuration through a captive portal web interface. No need to hardcode credentials in the firmware!
cp credentials.h.example credentials.h
# Edit credentials.h: uncomment BOARD_TYPE for your board (BOARD_1_47 or BOARD_1_9)
# Flash to ESP32 (WiFi and WebSocket enabled by default)
VibeMon-Setupvibemon123http://192.168.4.1)When the device has no saved WiFi credentials, it automatically enters Provisioning Mode:
┌─────────────────────────────────────────┐
│ No WiFi credentials detected │
│ ↓ │
│ Create Access Point │
│ - SSID: VibeMon-Setup │
│ - Password: vibemon123 │
│ - IP: 192.168.4.1 │
│ ↓ │
│ DNS Server (Captive Portal) │
│ ↓ │
│ User connects & configures │
│ ↓ │
│ Save to NVS Flash → Reboot │
│ ↓ │
│ Connect to configured WiFi │
└─────────────────────────────────────────┘
Features:
Fields:
Credentials are stored in ESP32’s NVS (Non-Volatile Storage):
| Key | Type | Description |
|---|---|---|
wifiSSID |
String | WiFi network name |
wifiPassword |
String | WiFi password |
wsToken |
String | WebSocket authentication token |
Persistence:
Best for: New devices, easy setup, changing WiFi networks
# 1. Copy credentials template
cp credentials.h.example credentials.h
# 2. Set BOARD_TYPE (uncomment BOARD_1_47 or BOARD_1_9)
# 3. Flash firmware (USE_WIFI and USE_WEBSOCKET enabled by default)
# 4. Power on device → Automatically enters provisioning mode
# 5. Connect to VibeMon-Setup and configure via web
Best for: Production deployments, known WiFi networks
// credentials.h
#define USE_WIFI
#define USE_WEBSOCKET
#define WIFI_SSID "MyNetwork"
#define WIFI_PASSWORD "MyPassword"
#define WS_TOKEN "vbm-secret-token" // Optional
#define BOARD_TYPE BOARD_1_47 // or BOARD_1_9
These are used as defaults if no saved credentials exist.
┌────────────────────────┐
│ Setup Mode │
│ SSID: VibeMon-Setup │
│ Password: vibemon123 │
│ IP: 192.168.4.1 │
│ │
│ [Character] │
└────────────────────────┘
┌────────────────────────┐
│ WiFi: OK │
│ IP: 192.168.1.42 │
│ │
│ [Character] │
│ Status: working │
└────────────────────────┘
Clear saved credentials and return to provisioning mode:
curl -X POST http://DEVICE_IP/wifi-reset \
-H "Content-Type: application/json" \
-d '{"confirm":true}'
Device will:
wifiSSID, wifiPassword from NVS (WebSocket token is preserved)curl http://DEVICE_IP/health
# Returns: {"status":"ok"}
The token is used for authentication when connecting to VibeMon WebSocket servers:
wss://ws.vibemon.io/?token=YOUR_TOKEN{"type":"auth","token":"YOUR_TOKEN"}Via Provisioning Interface:
Via credentials.h:
#define WS_TOKEN "your_access_token"
Priority: Saved token in NVS > WS_TOKEN define
Solutions:
http://192.168.4.1What happens:
Check:
Solutions:
Solutions:
USE_WIFI is defined in credentials.h/wifi-reset endpoint to clear credentialsesptool.py --port /dev/ttyUSB0 erase_region 0x9000 0x6000
Provisioning Mode:
| Endpoint | Method | Description |
|---|---|---|
/* |
GET | Configuration page (HTML) |
/scan |
GET | WiFi networks list (JSON) |
/save |
POST | Save WiFi + token, reboot |
Normal Mode:
| Endpoint | Method | Description |
|---|---|---|
/status |
POST | Update device status |
/status |
GET | Get current status |
/health |
GET | Health check |
/lock |
POST | Lock to a specific project |
/unlock |
POST | Unlock project |
/lock-mode |
GET | Get current lock mode |
/lock-mode |
POST | Set lock mode |
/reboot |
POST | Reboot device |
/wifi-reset |
POST | Clear credentials, restart provisioning |
See API Reference for full request/response details.
| Indicator | RSSI Range | Quality |
|---|---|---|
| ▰▰▰▰ | > -50 dBm | Excellent |
| ▰▰▰▱ | -50 to -60 dBm | Good |
| ▰▰▱▱ | -60 to -70 dBm | Fair |
| ▰▱▱▱ | < -70 dBm | Weak |
void setup() {
// Load WiFi credentials from NVS (fallback to credentials.h defines)
loadWiFiCredentials();
if (strlen(wifiSSID) == 0) {
// No credentials → Start provisioning
startProvisioningMode();
} else {
// Try to connect (3 rounds × 20 attempts)
WiFi.begin(wifiSSID, wifiPassword);
if (connection fails after all retries) {
// Enter provisioning mode directly
// Saved credentials are preserved for retry
startProvisioningMode();
}
}
}
void setupWebSocket() {
// Load token from NVS (or use WS_TOKEN define as fallback)
loadWebSocketToken();
// Add token to WebSocket URL
snprintf(wsPath, "/?token=%s", wsToken);
// Connect to WebSocket server
webSocket.beginSSL(WS_HOST, WS_PORT, wsPath);
}
Security Measures:
Security Limitations:
vibemon123) is known - configure quickly!Recommendations:
Connect a physical alert light (e.g., warning beacon) to an available GPIO pin. The light turns ON when the device enters alert state and OFF when the state changes.
ESP32 GPIO pin ──── Alert light (+)
ESP32 GND ──── Alert light (-)
Note: ESP32-C6 GPIO output is 3.3V, max ~40mA. Ensure your light operates within these limits. For higher voltage lights (5V/12V/24V), use a relay module.
Add to credentials.h:
#define ALERT_PIN 2
Any unused GPIO pin can be used. Recommended: GPIO2 (safe for both boards).
⚠️ Pin conflicts by board:
Board LCD pins in use (do NOT use for ALERT_PIN) 1.47” 6 (MOSI), 7 (SCK), 14 (CS), 15 (DC), 21 (RST), 22 (BL) 1.9” 4 (MOSI), 5 (SCK), 6 (DC), 7 (CS), 14 (RST), 15 (BL) GPIO4 is safe on the 1.47” board but conflicts with 1.9” MOSI — do not use it if supporting both boards.
If ALERT_PIN is not defined, the feature is disabled and no extra code is compiled.
Two ESP32-C6 LCD boards are supported. Set BOARD_TYPE in credentials.h to match your hardware:
#define BOARD_TYPE BOARD_1_47 // ESP32-C6-LCD-1.47 (default)
#define BOARD_TYPE BOARD_1_9 // ESP32-C6-LCD-1.9
| Board | LCD | Resolution | Backlight | SPI Freq | SPI Pins (MOSI/SCK/DC/CS/RST) |
|---|---|---|---|---|---|
| ESP32-C6-LCD-1.47 | ST7789V2 | 172×320 | GPIO22 PWM | 40MHz | 6/7/15/14/21 |
| ESP32-C6-LCD-1.9 | ST7789V2 | 170×320 | GPIO15 direct (active-low) | 20MHz | 4/5/6/7/14 |
To disable features, edit credentials.h:
// Disable WiFi
// #define USE_WIFI
// Disable WebSocket (WiFi still works)
// #define USE_WEBSOCKET
To change the provisioning AP name/password, edit state.h:
const char* AP_SSID = "MyCustomSSID";
const char* AP_PASSWORD = "MyCustomPassword";
Each device can be configured independently:
Expected Timing: