diff --git a/Firmware/RTK_Surveyor/AP-Config/index.html b/Firmware/RTK_Surveyor/AP-Config/index.html
index 192bb1360..522d69cda 100644
--- a/Firmware/RTK_Surveyor/AP-Config/index.html
+++ b/Firmware/RTK_Surveyor/AP-Config/index.html
@@ -117,6 +117,42 @@
+
+
+ Profiles
+
+
+ 1: 12345678901234567890123456789012345678901234567890
+
+
+ 2: 12345678901234567890123456789012345678901234567890
+
+
+ 3: 12345678901234567890123456789012345678901234567890
+
+
+ 4: 12345678901234567890123456789012345678901234567890
+
+
+ 5: 12345678901234567890123456789012345678901234567890
+
+
+ 6: 12345678901234567890123456789012345678901234567890
+
+
+ 7: 12345678901234567890123456789012345678901234567890
+
+
+ 8: 12345678901234567890123456789012345678901234567890
+
+
+
diff --git a/Firmware/RTK_Surveyor/AP-Config/src/main.js b/Firmware/RTK_Surveyor/AP-Config/src/main.js
index 09c2f24f0..7ef832c45 100644
--- a/Firmware/RTK_Surveyor/AP-Config/src/main.js
+++ b/Firmware/RTK_Surveyor/AP-Config/src/main.js
@@ -84,6 +84,14 @@ function parseIncoming(msg) {
|| id.includes("zedFirmwareVersion")
|| id.includes("hardwareID")
|| id.includes("daysRemaining")
+ || id.includes("profile0Name")
+ || id.includes("profile1Name")
+ || id.includes("profile2Name")
+ || id.includes("profile3Name")
+ || id.includes("profile4Name")
+ || id.includes("profile5Name")
+ || id.includes("profile6Name")
+ || id.includes("profile7Name")
) {
ge(id).innerHTML = val;
}
@@ -124,6 +132,7 @@ function parseIncoming(msg) {
//Force element updates
ge("profileNumber").dispatchEvent(new CustomEvent('change'));
ge("profileName").dispatchEvent(new CustomEvent('change'));
+ ge("bootProfileNumber").dispatchEvent(new CustomEvent('change'));
ge("measurementRateHz").dispatchEvent(new CustomEvent('change'));
ge("baseTypeSurveyIn").dispatchEvent(new CustomEvent('change'));
ge("baseTypeFixed").dispatchEvent(new CustomEvent('change'));
@@ -208,8 +217,9 @@ function validateFields() {
errorCount = 0;
//Profile Config
- checkElementValue("profileNumber", 1, 4, "Must be between 1 and 4", "collapseProfileConfig");
+ checkElementValue("profileNumber", 1, 8, "Must be between 1 and 8", "collapseProfileConfig");
checkElementString("profileName", 1, 49, "Must be 1 to 49 characters", "collapseProfileConfig");
+ checkBitMapValue("bootProfileNumber", 1, 8, "activeProfiles", "Must be an active profile between 1 and 8", "collapseProfileConfig");
//GNSS Config
checkElementValue("measurementRateHz", 0.00012, 10, "Must be between 0.00012 and 10Hz", "collapseGNSSConfig");
@@ -459,6 +469,19 @@ function checkConstellations() {
clearError("ubxConstellations");
}
+function checkBitMapValue(id, min, max, bitMap, errorText, collapseID) {
+ value = ge(id).value;
+ mask = ge(bitMap).value;
+ if ((value < min) || (value > max) || ((mask & (1 << value)) == 0)) {
+ ge(id + 'Error').innerHTML = 'Error: ' + errorText;
+ ge(collapseID).classList.add('show');
+ errorCount++;
+ }
+ else {
+ clearError(id);
+ }
+}
+
function checkElementValue(id, min, max, errorText, collapseID) {
value = ge(id).value;
if (value < min || value > max) {
diff --git a/Firmware/RTK_Surveyor/Form.ino b/Firmware/RTK_Surveyor/Form.ino
index b6148ee20..57afb8edb 100644
--- a/Firmware/RTK_Surveyor/Form.ino
+++ b/Firmware/RTK_Surveyor/Form.ino
@@ -1,6 +1,8 @@
//Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to websocket
//After user clicks 'save', data is validated via main.js and a long string of values is returned.
+static uint8_t bootProfileNumber;
+
//Start webserver in AP mode
void startWebServer()
{
@@ -280,6 +282,9 @@ void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventT
void createSettingsString(char* settingsCSV)
{
#ifdef COMPILE_AP
+ char tagText[32];
+ char nameText[64];
+
//System Info
stringRecord(settingsCSV, "platformPrefix", platformPrefix);
@@ -407,6 +412,15 @@ void createSettingsString(char* settingsCSV)
//Profiles
stringRecord(settingsCSV, "profileNumber", profileNumber + 1);
stringRecord(settingsCSV, "profileName", profileNames[profileNumber]);
+ for (int index = 0; index < MAX_PROFILE_COUNT; index++)
+ {
+ sprintf(tagText, "profile%dName", index);
+ sprintf(nameText, "%d: %s", index + 1, profileNames[index]);
+ stringRecord(settingsCSV, tagText, nameText);
+ }
+ bootProfileNumber = profileNumber + 1;
+ stringRecord(settingsCSV, "bootProfileNumber", bootProfileNumber);
+ stringRecord(settingsCSV, "activeProfiles", activeProfiles);
//New settings not yet integrated
//...
@@ -503,7 +517,14 @@ void updateSettingWithValue(const char *settingName, const char* settingValueStr
recordProfileNumber(profileNumber);
}
}
-
+ else if (strcmp(settingName, "bootProfileNumber") == 0)
+ {
+ if ((sscanf(settingValueStr, "%d", &bootProfileNumber) != 1)
+ || (bootProfileNumber < 1)
+ || (bootProfileNumber > (MAX_PROFILE_COUNT + 1)))
+ bootProfileNumber = 1;
+Serial.printf("bootProfileNumber: %d\r\n", bootProfileNumber);
+ }
else if (strcmp(settingName, "enableNtripServer") == 0)
settings.enableNtripServer = settingValueBool;
else if (strcmp(settingName, "ntripServer_CasterHost") == 0)
@@ -579,6 +600,12 @@ void updateSettingWithValue(const char *settingName, const char* settingValueStr
{
if (newAPSettings == true) recordSystemSettings(); //If we've recieved settings, record before restart
+ //Determine which profile to boot
+ bootProfileNumber -= 1;
+ if (bootProfileNumber != profileNumber)
+ recordProfileNumber(bootProfileNumber);
+
+ //Reboot the machine
ESP.restart();
}
diff --git a/Firmware/RTK_Surveyor/RTK_Surveyor.ino b/Firmware/RTK_Surveyor/RTK_Surveyor.ino
index 5073a2c6b..1ceb5b23b 100644
--- a/Firmware/RTK_Surveyor/RTK_Surveyor.ino
+++ b/Firmware/RTK_Surveyor/RTK_Surveyor.ino
@@ -305,7 +305,7 @@ AsyncWebSocket ws("/ws");
//Because the incoming string is longer than max len, there are multiple callbacks so we
//use a global to combine the incoming
-#define AP_CONFIG_SETTING_SIZE 3500
+#define AP_CONFIG_SETTING_SIZE 5000
char incomingSettings[AP_CONFIG_SETTING_SIZE];
int incomingSettingsSpot = 0;
unsigned long timeSinceLastIncomingSetting = 0;
diff --git a/Firmware/RTK_Surveyor/form.h b/Firmware/RTK_Surveyor/form.h
index 6895a50d0..5a05d8844 100644
--- a/Firmware/RTK_Surveyor/form.h
+++ b/Firmware/RTK_Surveyor/form.h
@@ -107,6 +107,14 @@ function parseIncoming(msg) {
|| id.includes("zedFirmwareVersion")
|| id.includes("hardwareID")
|| id.includes("daysRemaining")
+ || id.includes("profile0Name")
+ || id.includes("profile1Name")
+ || id.includes("profile2Name")
+ || id.includes("profile3Name")
+ || id.includes("profile4Name")
+ || id.includes("profile5Name")
+ || id.includes("profile6Name")
+ || id.includes("profile7Name")
) {
ge(id).innerHTML = val;
}
@@ -147,6 +155,7 @@ function parseIncoming(msg) {
//Force element updates
ge("profileNumber").dispatchEvent(new CustomEvent('change'));
ge("profileName").dispatchEvent(new CustomEvent('change'));
+ ge("bootProfileNumber").dispatchEvent(new CustomEvent('change'));
ge("measurementRateHz").dispatchEvent(new CustomEvent('change'));
ge("baseTypeSurveyIn").dispatchEvent(new CustomEvent('change'));
ge("baseTypeFixed").dispatchEvent(new CustomEvent('change'));
@@ -231,8 +240,9 @@ function validateFields() {
errorCount = 0;
//Profile Config
- checkElementValue("profileNumber", 1, 4, "Must be between 1 and 4", "collapseProfileConfig");
+ checkElementValue("profileNumber", 1, 8, "Must be between 1 and 8", "collapseProfileConfig");
checkElementString("profileName", 1, 49, "Must be 1 to 49 characters", "collapseProfileConfig");
+ checkBitMapValue("bootProfileNumber", 1, 8, "activeProfiles", "Must be an active profile between 1 and 8", "collapseProfileConfig");
//GNSS Config
checkElementValue("measurementRateHz", 0.00012, 10, "Must be between 0.00012 and 10Hz", "collapseGNSSConfig");
@@ -482,6 +492,19 @@ function checkConstellations() {
clearError("ubxConstellations");
}
+function checkBitMapValue(id, min, max, bitMap, errorText, collapseID) {
+ value = ge(id).value;
+ mask = ge(bitMap).value;
+ if ((value < min) || (value > max) || ((mask & (1 << value)) == 0)) {
+ ge(id + 'Error').innerHTML = 'Error: ' + errorText;
+ ge(collapseID).classList.add('show');
+ errorCount++;
+ }
+ else {
+ clearError(id);
+ }
+}
+
function checkElementValue(id, min, max, errorText, collapseID) {
value = ge(id).value;
if (value < min || value > max) {
@@ -896,6 +919,42 @@ static const char *index_html = R"=====(
+
+
+ Profiles
+
+
+ 1: 12345678901234567890123456789012345678901234567890
+
+
+ 2: 12345678901234567890123456789012345678901234567890
+
+
+ 3: 12345678901234567890123456789012345678901234567890
+
+
+ 4: 12345678901234567890123456789012345678901234567890
+
+
+ 5: 12345678901234567890123456789012345678901234567890
+
+
+ 6: 12345678901234567890123456789012345678901234567890
+
+
+ 7: 12345678901234567890123456789012345678901234567890
+
+
+ 8: 12345678901234567890123456789012345678901234567890
+
+
+