MAJOR update. More like a Backup before things get Crazy
Added Websocket Support Added Universal Message Handling for both MQTT and WS Added Timekeeper Class, that handles Physical Clock and Scheduling Added Bell Assignment Settings, Note to Bell mapping
This commit is contained in:
@@ -1,27 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
extern uint16_t relayDurations[16];
|
||||
extern uint16_t bellDurations[16];
|
||||
|
||||
void loadRelayTimings();
|
||||
void saveRelayTimings();
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
// Sets Incoming Relay Durations to RAM and then call funtion to save them to file.
|
||||
void updateRelayTimings(JsonVariant doc) {
|
||||
// Iterate through the relays in the JSON payload
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
String key = String("b") + (i + 1); // Generate "b1", "b2", ...
|
||||
if (doc.containsKey(key)) {
|
||||
relayDurations[i] = doc[key].as<uint16_t>();
|
||||
LOG_DEBUG("Relay %d duration s1et to %d ms\n", i + 1, relayDurations[i]);
|
||||
} else {
|
||||
LOG_DEBUG("Relay %d not found in JSON payload. Keeping previous duration: %d ms\n", i + 1, relayDurations[i]);
|
||||
}
|
||||
}
|
||||
saveRelayTimings();
|
||||
LOG_INFO("Updated Relay Timings.")
|
||||
}
|
||||
|
||||
|
||||
// Save file "filename" with data: "data" to the "dirPath" directory of the SD card
|
||||
void saveFileToSD(const char* dirPath, const char* filename, const char* data) {
|
||||
@@ -59,7 +45,7 @@ void saveRelayTimings() {
|
||||
// Populate the JSON object with relay durations
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
String key = String("b") + (i + 1);
|
||||
doc[key] = relayDurations[i];
|
||||
doc[key] = bellDurations[i];
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
@@ -100,14 +86,14 @@ void loadRelayTimings() {
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
String key = String("b") + (i + 1);
|
||||
if (doc.containsKey(key)) {
|
||||
relayDurations[i] = doc[key].as<uint16_t>();
|
||||
LOG_DEBUG("Loaded relay %d duration: %d ms\n", i + 1, relayDurations[i]);
|
||||
bellDurations[i] = doc[key].as<uint16_t>();
|
||||
LOG_DEBUG("Loaded relay %d duration: %d ms", i + 1, bellDurations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Function to sync time with NTP server and update RTC
|
||||
/* Function to sync time with NTP server and update RTC
|
||||
void syncTimeWithNTP() {
|
||||
// Connect to Wi-Fi if not already connected
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
@@ -142,6 +128,8 @@ void syncTimeWithNTP() {
|
||||
timeInfo.tm_mday, timeInfo.tm_mon + 1, timeInfo.tm_year + 1900);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// Call this function with the Firebase URL and desired local filename
|
||||
bool downloadFileToSD(const String& url, const String& directory, const String& filename) {
|
||||
LOG_INFO("HTTP Starting download...");
|
||||
@@ -192,7 +180,6 @@ bool downloadFileToSD(const String& url, const String& directory, const String&
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Returns the list of melodies (the filenames) currently inside the SD Card.
|
||||
String listFilesAsJson(const char* dirPath) {
|
||||
if (!SD.begin(SD_CS)) {
|
||||
@@ -280,14 +267,14 @@ void printFileAsText(const String& path, const String& filename) {
|
||||
}
|
||||
|
||||
// Downloads a new melody from HTTP
|
||||
void addMelody(JsonVariant doc) {
|
||||
|
||||
LOG_INFO("Trying Saving...");
|
||||
const char* url = doc["url"];
|
||||
const char* filename = doc["filename"];
|
||||
downloadFileToSD(url, "/melodies", filename);
|
||||
|
||||
|
||||
bool addMelody(JsonVariant doc) {
|
||||
LOG_INFO("Trying Download of Melody...");
|
||||
const char* url = doc["download_url"];
|
||||
const char* filename = doc["melodys_uid"];
|
||||
if (downloadFileToSD(url, "/melodies", filename)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks the onboard SD Card for new firmware
|
||||
@@ -340,6 +327,59 @@ void checkFirmwareUpdate() {
|
||||
updateBin.close();
|
||||
}
|
||||
|
||||
// call this in setup() after WiFi is up
|
||||
void setupUdpDiscovery() {
|
||||
if (udp.listen(DISCOVERY_PORT)) {
|
||||
Serial.printf("UDP discovery listening on %u\n", DISCOVERY_PORT);
|
||||
|
||||
udp.onPacket([](AsyncUDPPacket packet) {
|
||||
// Parse request
|
||||
String msg = String((const char*)packet.data(), packet.length());
|
||||
Serial.printf("UDP from %s:%u -> %s\n",
|
||||
packet.remoteIP().toString().c_str(),
|
||||
packet.remotePort(),
|
||||
msg.c_str());
|
||||
|
||||
// Minimal: accept plain text or JSON
|
||||
bool shouldReply = false;
|
||||
|
||||
if (msg.indexOf("discover") >= 0) {
|
||||
shouldReply = true;
|
||||
} else {
|
||||
// Try JSON
|
||||
StaticJsonDocument<128> req;
|
||||
DeserializationError err = deserializeJson(req, msg);
|
||||
if (!err) {
|
||||
shouldReply = (req["op"] == "discover" && req["svc"] == "vesper");
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldReply) return;
|
||||
|
||||
// Build reply JSON
|
||||
StaticJsonDocument<256> doc;
|
||||
doc["op"] = "discover_reply";
|
||||
doc["svc"] = "vesper";
|
||||
doc["ver"] = 1;
|
||||
|
||||
doc["name"] = "Proj. Vesper v0.5"; // your device name
|
||||
doc["id"] = DEV_ID; // stable unique ID if you have one
|
||||
doc["ip"] = WiFi.localIP().toString();
|
||||
doc["ws"] = String("ws://") + WiFi.localIP().toString() + "/ws";
|
||||
doc["port"] = 80; // your WS server port
|
||||
doc["fw"] = "1.2.3"; // firmware version
|
||||
|
||||
String out;
|
||||
serializeJson(doc, out);
|
||||
|
||||
// Reply directly to the sender’s IP/port
|
||||
udp.writeTo((const uint8_t*)out.c_str(), out.length(),
|
||||
packet.remoteIP(), packet.remotePort());
|
||||
});
|
||||
} else {
|
||||
Serial.println("Failed to start UDP discovery.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// UNSUSED FUNCTIONS.
|
||||
|
||||
Reference in New Issue
Block a user