Removed Ethernet, added default WiFi (mikrotik AP) and fixed various Clock bugs.

This commit is contained in:
2026-01-07 01:02:57 +02:00
parent 9f07e9ea39
commit 51b7722e1d
5 changed files with 251 additions and 169 deletions

View File

@@ -524,14 +524,14 @@ void CommandHandler::handleSetRtcTimeCommand(JsonVariant contents, const Message
// Verify the time was set correctly by reading it back
unsigned long verifyTime = _timeKeeper->getTime();
if (verifyTime > 0 && abs((long)verifyTime - (long)timestamp) < 5) { // Allow 5 second tolerance
if (verifyTime > 0 && abs((long)verifyTime - (long)localTimestamp) < 5) { // Allow 5 second tolerance
sendSuccessResponse("set_rtc_time",
"RTC time and timezone updated successfully", context);
LOG_INFO("RTC time set with timezone: UTC %lu + %ld = local %lu",
timestamp, totalOffset, localTimestamp);
} else {
sendErrorResponse("set_rtc_time", "Failed to verify RTC time was set correctly", context);
LOG_ERROR("RTC time verification failed - expected: %lu, got: %lu", timestamp, verifyTime);
LOG_ERROR("RTC time verification failed - expected: %lu, got: %lu", localTimestamp, verifyTime);
}
} else {
// Legacy method: Use device's existing timezone config

View File

@@ -529,13 +529,19 @@ void ConfigManager::updateClockAlerts(JsonVariant doc) {
clockConfig.alertRingInterval = doc["alertRingInterval"].as<uint16_t>();
}
if (doc.containsKey("hourBell")) {
clockConfig.hourBell = doc["hourBell"].as<uint8_t>();
uint8_t bellNum = doc["hourBell"].as<uint8_t>();
// Convert from 1-based (API) to 0-based (internal), or keep 255 (disabled)
clockConfig.hourBell = (bellNum == 255) ? 255 : bellNum - 1;
}
if (doc.containsKey("halfBell")) {
clockConfig.halfBell = doc["halfBell"].as<uint8_t>();
uint8_t bellNum = doc["halfBell"].as<uint8_t>();
// Convert from 1-based (API) to 0-based (internal), or keep 255 (disabled)
clockConfig.halfBell = (bellNum == 255) ? 255 : bellNum - 1;
}
if (doc.containsKey("quarterBell")) {
clockConfig.quarterBell = doc["quarterBell"].as<uint8_t>();
uint8_t bellNum = doc["quarterBell"].as<uint8_t>();
// Convert from 1-based (API) to 0-based (internal), or keep 255 (disabled)
clockConfig.quarterBell = (bellNum == 255) ? 255 : bellNum - 1;
}
LOG_DEBUG("ConfigManager - Updated Clock alerts");
}
@@ -593,7 +599,7 @@ bool ConfigManager::loadClockConfig() {
return false;
}
StaticJsonDocument<512> doc;
StaticJsonDocument<1024> doc; // Increased size for all settings
DeserializationError error = deserializeJson(doc, file);
file.close();
@@ -602,12 +608,34 @@ bool ConfigManager::loadClockConfig() {
return false;
}
// Clock enable/outputs
if (doc.containsKey("enabled")) clockConfig.enabled = doc["enabled"].as<bool>();
if (doc.containsKey("c1output")) clockConfig.c1output = doc["c1output"].as<uint8_t>();
if (doc.containsKey("c2output")) clockConfig.c2output = doc["c2output"].as<uint8_t>();
if (doc.containsKey("pulseDuration")) clockConfig.pulseDuration = doc["pulseDuration"].as<uint16_t>();
if (doc.containsKey("pauseDuration")) clockConfig.pauseDuration = doc["pauseDuration"].as<uint16_t>();
// Alert settings
if (doc.containsKey("alertType")) clockConfig.alertType = doc["alertType"].as<String>();
if (doc.containsKey("alertRingInterval")) clockConfig.alertRingInterval = doc["alertRingInterval"].as<uint16_t>();
if (doc.containsKey("hourBell")) clockConfig.hourBell = doc["hourBell"].as<uint8_t>();
if (doc.containsKey("halfBell")) clockConfig.halfBell = doc["halfBell"].as<uint8_t>();
if (doc.containsKey("quarterBell")) clockConfig.quarterBell = doc["quarterBell"].as<uint8_t>();
// Backlight settings
if (doc.containsKey("backlight")) clockConfig.backlight = doc["backlight"].as<bool>();
if (doc.containsKey("backlightOutput")) clockConfig.backlightOutput = doc["backlightOutput"].as<uint8_t>();
if (doc.containsKey("backlightOnTime")) clockConfig.backlightOnTime = doc["backlightOnTime"].as<String>();
if (doc.containsKey("backlightOffTime")) clockConfig.backlightOffTime = doc["backlightOffTime"].as<String>();
// Silence period settings
if (doc.containsKey("daytimeSilenceEnabled")) clockConfig.daytimeSilenceEnabled = doc["daytimeSilenceEnabled"].as<bool>();
if (doc.containsKey("daytimeSilenceOnTime")) clockConfig.daytimeSilenceOnTime = doc["daytimeSilenceOnTime"].as<String>();
if (doc.containsKey("daytimeSilenceOffTime")) clockConfig.daytimeSilenceOffTime = doc["daytimeSilenceOffTime"].as<String>();
if (doc.containsKey("nighttimeSilenceEnabled")) clockConfig.nighttimeSilenceEnabled = doc["nighttimeSilenceEnabled"].as<bool>();
if (doc.containsKey("nighttimeSilenceOnTime")) clockConfig.nighttimeSilenceOnTime = doc["nighttimeSilenceOnTime"].as<String>();
if (doc.containsKey("nighttimeSilenceOffTime")) clockConfig.nighttimeSilenceOffTime = doc["nighttimeSilenceOffTime"].as<String>();
LOG_DEBUG("ConfigManager - Clock config loaded");
return true;
}
@@ -615,14 +643,37 @@ bool ConfigManager::loadClockConfig() {
bool ConfigManager::saveClockConfig() {
if (!ensureSDCard()) return false;
StaticJsonDocument<512> doc;
StaticJsonDocument<1024> doc; // Increased size for all settings
// Clock enable/outputs
doc["enabled"] = clockConfig.enabled;
doc["c1output"] = clockConfig.c1output;
doc["c2output"] = clockConfig.c2output;
doc["pulseDuration"] = clockConfig.pulseDuration;
doc["pauseDuration"] = clockConfig.pauseDuration;
char buffer[512];
// Alert settings
doc["alertType"] = clockConfig.alertType;
doc["alertRingInterval"] = clockConfig.alertRingInterval;
doc["hourBell"] = clockConfig.hourBell;
doc["halfBell"] = clockConfig.halfBell;
doc["quarterBell"] = clockConfig.quarterBell;
// Backlight settings
doc["backlight"] = clockConfig.backlight;
doc["backlightOutput"] = clockConfig.backlightOutput;
doc["backlightOnTime"] = clockConfig.backlightOnTime;
doc["backlightOffTime"] = clockConfig.backlightOffTime;
// Silence period settings
doc["daytimeSilenceEnabled"] = clockConfig.daytimeSilenceEnabled;
doc["daytimeSilenceOnTime"] = clockConfig.daytimeSilenceOnTime;
doc["daytimeSilenceOffTime"] = clockConfig.daytimeSilenceOffTime;
doc["nighttimeSilenceEnabled"] = clockConfig.nighttimeSilenceEnabled;
doc["nighttimeSilenceOnTime"] = clockConfig.nighttimeSilenceOnTime;
doc["nighttimeSilenceOffTime"] = clockConfig.nighttimeSilenceOffTime;
char buffer[1024];
size_t len = serializeJson(doc, buffer, sizeof(buffer));
if (len == 0 || len >= sizeof(buffer)) {

View File

@@ -70,6 +70,8 @@ public:
String apPass; // 🔐 AP is Open. No Password
uint16_t discoveryPort = 32101; // 📡 Fixed discovery port
bool permanentAPMode = false; // 🔘 Permanent AP mode toggle (stored on SD)
String defaultWifiSsid = "BellSystemsInfra"; // 📡 Default WiFi SSID to try on boot
String defaultWifiPsk = "v3sp3r_8998!"; // 🔐 Default WiFi password to try on boot
};
/**

View File

@@ -71,63 +71,97 @@ void Networking::begin() {
return;
}
// ETHERNET DISABLED - WiFi only mode
// Start Ethernet hardware
auto& hwConfig = _configManager.getHardwareConfig();
ETH.begin(hwConfig.ethPhyType, hwConfig.ethPhyAddr, hwConfig.ethPhyCs,
hwConfig.ethPhyIrq, hwConfig.ethPhyRst, SPI);
// auto& hwConfig = _configManager.getHardwareConfig();
// ETH.begin(hwConfig.ethPhyType, hwConfig.ethPhyAddr, hwConfig.ethPhyCs,
// hwConfig.ethPhyIrq, hwConfig.ethPhyRst, SPI);
// Start connection sequence
LOG_INFO("Starting network connection sequence...");
startEthernetConnection();
// Start connection sequence - Skip Ethernet, go directly to WiFi
LOG_INFO("Starting WiFi connection (Ethernet disabled)...");
startWiFiConnection();
}
void Networking::startEthernetConnection() {
LOG_INFO("Attempting Ethernet connection...");
setState(NetworkState::CONNECTING_ETHERNET);
// Check if Ethernet hardware initialization failed
if (!ETH.linkUp()) {
LOG_WARNING("Ethernet hardware not detected or failed to initialize");
LOG_INFO("Falling back to WiFi immediately");
// ETHERNET DISABLED - Skip to WiFi immediately
LOG_DEBUG("Ethernet connection disabled - falling back to WiFi");
startWiFiConnection();
return;
}
// Ethernet will auto-connect via events
// Set timeout for Ethernet attempt (5 seconds)
_lastConnectionAttempt = millis();
// Start reconnection timer to handle timeout
xTimerStart(_reconnectionTimer, 0);
// Original Ethernet code (DISABLED):
// LOG_INFO("Attempting Ethernet connection...");
// setState(NetworkState::CONNECTING_ETHERNET);
//
// // Check if Ethernet hardware initialization failed
// if (!ETH.linkUp()) {
// LOG_WARNING("Ethernet hardware not detected or failed to initialize");
// LOG_INFO("Falling back to WiFi immediately");
// startWiFiConnection();
// return;
// }
//
// // Ethernet will auto-connect via events
// // Set timeout for Ethernet attempt (5 seconds)
// _lastConnectionAttempt = millis();
//
// // Start reconnection timer to handle timeout
// xTimerStart(_reconnectionTimer, 0);
}
void Networking::startWiFiConnection() {
LOG_INFO("Attempting WiFi connection...");
setState(NetworkState::CONNECTING_WIFI);
if (!hasValidWiFiCredentials()) {
LOG_WARNING("No valid WiFi credentials found");
if (!_bootSequenceComplete) {
// No credentials during boot - start portal
startWiFiPortal();
}
return;
}
// ALWAYS try default credentials first (for bundled router deployment)
auto& netConfig = _configManager.getNetworkConfig();
// Get and log saved credentials (for debugging)
String savedSSID = _wifiManager->getWiFiSSID(true);
LOG_INFO("Using WiFiManager saved credentials - SSID: %s", savedSSID.c_str());
LOG_INFO("Using DEFAULT WiFi credentials - SSID: %s", netConfig.defaultWifiSsid.c_str());
applyNetworkConfig(false); // false = WiFi config
WiFi.mode(WIFI_STA);
// Let WiFiManager handle credentials (uses saved SSID/password)
WiFi.begin();
WiFi.begin(netConfig.defaultWifiSsid.c_str(), netConfig.defaultWifiPsk.c_str());
_lastConnectionAttempt = millis();
// Start reconnection timer to handle timeout
xTimerStart(_reconnectionTimer, 0);
// Original WiFiManager fallback code (DISABLED for fixed deployment):
// // First, try default credentials if this is the first boot attempt
// if (!_bootSequenceComplete && !hasValidWiFiCredentials()) {
// LOG_INFO("No saved credentials - trying default WiFi credentials");
// auto& netConfig = _configManager.getNetworkConfig();
//
// applyNetworkConfig(false); // false = WiFi config
// WiFi.mode(WIFI_STA);
// WiFi.begin(netConfig.defaultWifiSsid.c_str(), netConfig.defaultWifiPsk.c_str());
//
// _lastConnectionAttempt = millis();
// xTimerStart(_reconnectionTimer, 0);
// return;
// }
//
// // Check if we have valid saved credentials
// if (!hasValidWiFiCredentials()) {
// LOG_WARNING("No valid WiFi credentials found");
// if (!_bootSequenceComplete) {
// // No credentials during boot - start portal
// startWiFiPortal();
// }
// return;
// }
//
// // Get and log saved credentials (for debugging)
// String savedSSID = _wifiManager->getWiFiSSID(true);
// LOG_INFO("Using WiFiManager saved credentials - SSID: %s", savedSSID.c_str());
//
// applyNetworkConfig(false); // false = WiFi config
// WiFi.mode(WIFI_STA);
//
// // Let WiFiManager handle credentials (uses saved SSID/password)
// WiFi.begin();
//
// _lastConnectionAttempt = millis();
//
// // Start reconnection timer to handle timeout
// xTimerStart(_reconnectionTimer, 0);
}
void Networking::startWiFiPortal() {
@@ -171,16 +205,17 @@ void Networking::handleReconnection() {
LOG_DEBUG("Attempting reconnection...");
// ETHERNET DISABLED - Skip Ethernet timeout checks
// Check for Ethernet timeout (fall back to WiFi)
if (_state == NetworkState::CONNECTING_ETHERNET) {
unsigned long now = millis();
if (now - _lastConnectionAttempt > 5000) { // 5 second timeout
LOG_INFO("Ethernet connection timeout - falling back to WiFi");
startWiFiConnection();
return;
}
return; // Still waiting for Ethernet
}
// if (_state == NetworkState::CONNECTING_ETHERNET) {
// unsigned long now = millis();
// if (now - _lastConnectionAttempt > 5000) { // 5 second timeout
// LOG_INFO("Ethernet connection timeout - falling back to WiFi");
// startWiFiConnection();
// return;
// }
// return; // Still waiting for Ethernet
// }
// Check for WiFi timeout
if (_state == NetworkState::CONNECTING_WIFI) {
@@ -216,12 +251,8 @@ void Networking::handleReconnection() {
return; // Still waiting for WiFi
}
// State is DISCONNECTED - decide what to try
if (_ethernetCableConnected) {
LOG_INFO("Ethernet cable detected - trying Ethernet");
startEthernetConnection();
} else {
LOG_INFO("No Ethernet - trying WiFi");
// State is DISCONNECTED - WiFi only mode (Ethernet disabled)
LOG_INFO("Disconnected - trying WiFi");
if (hasValidWiFiCredentials()) {
startWiFiConnection();
} else if (!_bootSequenceComplete) {
@@ -230,7 +261,6 @@ void Networking::handleReconnection() {
} else {
LOG_WARNING("No WiFi credentials and boot sequence complete - waiting");
}
}
}
// ════════════════════════════════════════════════════════════════════════════
@@ -244,8 +274,8 @@ bool Networking::isHealthy() const {
return false;
}
// Check connection state
if (_state != NetworkState::CONNECTED_ETHERNET && _state != NetworkState::CONNECTED_WIFI) {
// Check connection state (Ethernet disabled, only check WiFi or AP)
if (_state != NetworkState::CONNECTED_WIFI && _state != NetworkState::AP_MODE_PERMANENT) {
LOG_DEBUG("Networking: Unhealthy - Not in connected state");
return false;
}
@@ -272,13 +302,14 @@ bool Networking::isHealthy() const {
}
}
// ETHERNET DISABLED - Removed Ethernet link check
// For Ethernet connections, check link status
if (_activeConnection == ConnectionType::ETHERNET) {
if (!ETH.linkUp()) {
LOG_DEBUG("Networking: Unhealthy - Ethernet link down");
return false;
}
}
// if (_activeConnection == ConnectionType::ETHERNET) {
// if (!ETH.linkUp()) {
// LOG_DEBUG("Networking: Unhealthy - Ethernet link down");
// return false;
// }
// }
return true;
}
@@ -305,35 +336,43 @@ void Networking::notifyConnectionChange(bool connected) {
}
}
// Event handlers
// Event handlers (ETHERNET DISABLED)
void Networking::onEthernetConnected() {
LOG_INFO("Ethernet connected successfully");
setState(NetworkState::CONNECTED_ETHERNET);
setActiveConnection(ConnectionType::ETHERNET);
// ETHERNET DISABLED - This should never be called
LOG_WARNING("Ethernet event received but Ethernet is disabled - ignoring");
// Stop WiFi if it was running
if (WiFi.getMode() != WIFI_OFF) {
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
// Stop reconnection timer
xTimerStop(_reconnectionTimer, 0);
notifyConnectionChange(true);
// Original code (DISABLED):
// LOG_INFO("Ethernet connected successfully");
// setState(NetworkState::CONNECTED_ETHERNET);
// setActiveConnection(ConnectionType::ETHERNET);
//
// // Stop WiFi if it was running
// if (WiFi.getMode() != WIFI_OFF) {
// WiFi.disconnect(true);
// WiFi.mode(WIFI_OFF);
// }
//
// // Stop reconnection timer
// xTimerStop(_reconnectionTimer, 0);
//
// notifyConnectionChange(true);
}
void Networking::onEthernetDisconnected() {
LOG_WARNING("Ethernet disconnected");
// ETHERNET DISABLED - This should never be called
LOG_WARNING("Ethernet disconnect event received but Ethernet is disabled - ignoring");
if (_activeConnection == ConnectionType::ETHERNET) {
setState(NetworkState::DISCONNECTED);
setActiveConnection(ConnectionType::NONE);
notifyConnectionChange(false);
// Start reconnection attempts
xTimerStart(_reconnectionTimer, 0);
}
// Original code (DISABLED):
// LOG_WARNING("Ethernet disconnected");
//
// if (_activeConnection == ConnectionType::ETHERNET) {
// setState(NetworkState::DISCONNECTED);
// setActiveConnection(ConnectionType::NONE);
// notifyConnectionChange(false);
//
// // Start reconnection attempts
// xTimerStart(_reconnectionTimer, 0);
// }
}
void Networking::onWiFiConnected() {
@@ -367,35 +406,37 @@ void Networking::onWiFiDisconnected() {
}
void Networking::onEthernetCableChange(bool connected) {
_ethernetCableConnected = connected;
LOG_INFO("Ethernet cable %s", connected ? "connected" : "disconnected");
// ETHERNET DISABLED - Ignore cable events
LOG_DEBUG("Ethernet cable event ignored (Ethernet disabled)");
if (connected && _activeConnection != ConnectionType::ETHERNET) {
// Cable connected and we're not using Ethernet - try to connect
startEthernetConnection();
}
// Original code (DISABLED):
// _ethernetCableConnected = connected;
// LOG_INFO("Ethernet cable %s", connected ? "connected" : "disconnected");
//
// if (connected && _activeConnection != ConnectionType::ETHERNET) {
// // Cable connected and we're not using Ethernet - try to connect
// startEthernetConnection();
// }
}
// Utility methods
void Networking::applyNetworkConfig(bool ethernet) {
auto& netConfig = _configManager.getNetworkConfig();
// ETHERNET DISABLED - Only apply WiFi config
if (ethernet) {
LOG_WARNING("applyNetworkConfig called with ethernet=true but Ethernet is disabled");
return;
}
if (netConfig.useStaticIP) {
LOG_INFO("Applying static IP configuration");
if (ethernet) {
ETH.config(netConfig.ip, netConfig.gateway, netConfig.subnet, netConfig.dns1, netConfig.dns2);
} else {
WiFi.config(netConfig.ip, netConfig.gateway, netConfig.subnet, netConfig.dns1, netConfig.dns2);
}
} else {
LOG_INFO("Using DHCP configuration");
}
if (ethernet) {
ETH.setHostname(netConfig.hostname.c_str());
} else {
WiFi.setHostname(netConfig.hostname.c_str());
}
}
bool Networking::hasValidWiFiCredentials() {
@@ -413,7 +454,9 @@ bool Networking::isConnected() const {
String Networking::getLocalIP() const {
switch (_activeConnection) {
case ConnectionType::ETHERNET:
return ETH.localIP().toString();
// ETHERNET DISABLED - Should never reach here
LOG_WARNING("getLocalIP called with ETHERNET type but Ethernet is disabled");
return "0.0.0.0";
case ConnectionType::WIFI:
return WiFi.localIP().toString();
case ConnectionType::AP:
@@ -426,7 +469,9 @@ String Networking::getLocalIP() const {
String Networking::getGateway() const {
switch (_activeConnection) {
case ConnectionType::ETHERNET:
return ETH.gatewayIP().toString();
// ETHERNET DISABLED - Should never reach here
LOG_WARNING("getGateway called with ETHERNET type but Ethernet is disabled");
return "0.0.0.0";
case ConnectionType::WIFI:
return WiFi.gatewayIP().toString();
default:
@@ -445,9 +490,9 @@ void Networking::forceReconnect() {
WiFi.mode(WIFI_OFF);
}
// Restart connection sequence
// Restart connection sequence - WiFi only (Ethernet disabled)
delay(1000);
startEthernetConnection();
startWiFiConnection();
}
// Static callbacks
@@ -457,32 +502,16 @@ void Networking::networkEventHandler(arduino_event_id_t event, arduino_event_inf
LOG_DEBUG("Network event: %d", event);
switch (event) {
// ETHERNET EVENTS DISABLED - Ignored
case ARDUINO_EVENT_ETH_START:
LOG_DEBUG("ETH Started");
break;
case ARDUINO_EVENT_ETH_CONNECTED:
LOG_DEBUG("ETH Cable Connected");
_instance->onEthernetCableChange(true);
break;
case ARDUINO_EVENT_ETH_GOT_IP:
LOG_INFO("ETH Got IP: %s", ETH.localIP().toString().c_str());
_instance->applyNetworkConfig(true);
_instance->onEthernetConnected();
break;
case ARDUINO_EVENT_ETH_DISCONNECTED:
LOG_WARNING("ETH Cable Disconnected");
_instance->onEthernetCableChange(false);
_instance->onEthernetDisconnected();
break;
case ARDUINO_EVENT_ETH_STOP:
LOG_INFO("ETH Stopped");
_instance->onEthernetDisconnected();
LOG_DEBUG("Ethernet event ignored (Ethernet disabled)");
break;
// WiFi events (ACTIVE)
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
LOG_INFO("WiFi Got IP: %s", WiFi.localIP().toString().c_str());
_instance->onWiFiConnected();

View File

@@ -64,19 +64,19 @@
* 👨‍💻 AUTHOR: BellSystems bonamin
*/
#define FW_VERSION "137"
#define FW_VERSION "138"
/*
* ═══════════════════════════════════════════════════════════════════════════════
* 📅 VERSION HISTORY:
* NOTE: Versions are now stored as integers (v1.3 = 130)
* ═══════════════════════════════════════════════════════════════════════════════
* v0.1 (100) - Vesper Launch Beta
* v1.2 (120) - Added Log Level Configuration via App/MQTT
* v1.3 (130) - Added Telemetry Reports to App, Various Playback Fixes
* v137 - Made OTA and MQTT delays Async
* ═══════════════════════════════════════════════════════════════════════════════
* NOTE: Versions are now stored as integers (v1.3 = 130)
* v138 - Removed Ethernet, added default WiFi creds (Mikrotik AP) and fixed various Clock issues
* ═══════════════════════════════════════════════════════════════════════════════
*/