Skip to content

Commit f296f19

Browse files
authored
Merge pull request #42 from RTGS-Lab/bugfix/configuration-updates
Configuration Updates and SD Card Updates
2 parents e71aee7 + c0ec67d commit f296f19

7 files changed

Lines changed: 250 additions & 62 deletions

File tree

.github/workflows/release-workflow.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,18 @@ jobs:
181181
product_id_secret: "PARTICLE_WINTERTURF_PRODUCT_ID"
182182
- name: "Plant Pathways"
183183
product_id_secret: "PARTICLE_PLANT_PATHWAYS_PRODUCT_ID"
184-
- name: "LCCMR Irrigation"
185-
product_id_secret: "PARTICLE_LCCMR_IRRIGATION_PRODUCT_ID"
184+
- name: "Sharma V3 Irrigation"
185+
product_id_secret: "PARTICLE_SHARMA_V3_IRRIGATION_PRODUCT_ID"
186186
- name: "Roadside Turf"
187187
product_id_secret: "PARTICLE_ROADSIDE_TURF_PRODUCT_ID"
188188
- name: "PepsiCo"
189189
product_id_secret: "PARTICLE_PEPSICO_PRODUCT_ID"
190190
- name: "Precision Ag Pilot"
191191
product_id_secret: "PARTICLE_PRECISION_AG_PILOT_PRODUCT_ID"
192+
- name: "Turf Disease Pilot"
193+
product_id_secret: "PARTICLE_TURF_DISEASE_PILOT_PRODUCT_ID"
194+
- name: "Legacy Irrigation"
195+
product_id_secret: "PARTICLE_LEGACY_IRRIGATION_PRODUCT_ID"
192196
steps:
193197
- name: Checkout code
194198
uses: actions/checkout@v4

CONFIGURATION.md

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@
44

55
Configuration is loaded at startup in the following priority order:
66

7-
1. **SD Card**: `config.json` file on the SD card
8-
2. **Default**: Built-in default configuration if SD file not found
7+
1. **SD Card**: `config.json` file on the SD card (primary storage)
8+
2. **EEPROM Backup**: Configuration restored from EEPROM if SD card fails
9+
3. **Default**: Built-in default configuration if both SD and EEPROM unavailable
10+
11+
The system automatically creates EEPROM backups when configurations are successfully loaded from SD card or applied via cloud functions. When EEPROM backup is used, the configuration is automatically restored to the SD card.
912

1013
#### Updating Configuration
1114

1215
Configuration can be updated through:
1316

1417
1. **Cloud Function**: `updateConfig` Particle function
15-
- copy the intended config.json and paste it as and argument into updateConfig
16-
- If successful, the device will restart without returning any value.
17-
- verify that the first metadata packet after reset matches your configuration
18-
- See below for other types of responses.
18+
- Configuration is always saved to EEPROM backup for reliability
19+
- SD card is updated when possible, but function succeeds if EEPROM update works
20+
- Device will restart automatically on successful configuration update
21+
- Verify success by checking metadata packet includes new configuration UIDs
1922
3. **SD Card**: Replace `config.json` file and restart system
2023

2124
#### updateConfig Function Details
@@ -50,15 +53,12 @@ The function returns specific error codes when configuration updates fail:
5053

5154
| Error Code | Description | Troubleshooting |
5255
|------------|-------------|-----------------|
53-
| `0` | Success - Configuration removed from SD card | |
54-
| `1` | Success - Configuration updated, system restarting | |
55-
| `-1` | Failed to remove configuration from SD card | |
56-
| `-2` | Invalid configuration format - Missing 'config' element | |
57-
| `-3` | Invalid configuration format - Missing 'system' element | |
58-
| `-4` | Invalid configuration format - Missing 'sensors' element | |
59-
| `-5` | Failed to write test file to SD card | |
60-
| `-6` | Failed to remove current configuration from SD card | |
61-
| `-7` | Failed to write new configuration to SD card | |
56+
| `0` | Success - Configuration removed from SD card and EEPROM | |
57+
| `1` | Success - Configuration updated and saved to EEPROM, system restarting | May show SD card warnings but still succeeds |
58+
| `-2` | Invalid configuration format - Missing 'config' element | Check JSON structure |
59+
| `-3` | Invalid configuration format - Missing 'system' element | Ensure 'system' section exists |
60+
| `-4` | Invalid configuration format - Missing 'sensors' element | Ensure 'sensors' section exists |
61+
| `-8` | Failed to parse configuration - Invalid JSON or values | Check JSON syntax and parameter ranges |
6262

6363
##### Configuration Validation Rules
6464

@@ -70,13 +70,14 @@ The system performs several validation checks:
7070
- Must contain "sensors" section within config (checked by string search)
7171
- All whitespace, newlines, carriage returns, and tabs are automatically stripped
7272

73-
2. **SD Card Validation**
74-
- SD card must be accessible for writing
75-
- System tests write capability before attempting configuration update
76-
- Current configuration must be removable before writing new configuration
73+
2. **Configuration Processing**
74+
- Configuration is parsed and applied first (automatically saves to EEPROM backup)
75+
- SD card is updated when possible, but failures don't prevent success
76+
- System succeeds if configuration parsing works, regardless of SD card status
77+
- Warning messages indicate SD card issues but don't cause operation failure
7778

7879
3. **Special Commands**
79-
- Use "remove" as the configuration string to delete config.json and revert to defaults
80+
- Use "remove" as the configuration string to delete config.json and clear EEPROM backup
8081

8182
##### Example Error Scenarios
8283

@@ -92,17 +93,25 @@ particle call device_name updateConfig '{"config":{"system":{"logPeriod":300}}}'
9293
# Returns: -4
9394
```
9495

95-
###### SD Card Issues
96+
###### SD Card Issues (Non-Critical)
9697
```bash
97-
# If SD card is not available or full
98-
particle call device_name updateConfig '{"config":{"system":{"logPeriod":300},"sensors":{}}}'
99-
# May return: -5, -6, or -7 depending on the specific SD card failure point
98+
# Configuration update succeeds even if SD card fails
99+
particle call device_name updateConfig '{"config":{"system":{"logPeriod":300},"sensors":{"numSoil":3}}}'
100+
# Returns: 1 (success) - Configuration saved to EEPROM, may show SD warnings in logs
101+
# Serial output: "Warning: Failed to write configuration to SD card, but EEPROM backup is available."
100102
```
101103

102104
###### Configuration Removal
103105
```bash
104106
particle call device_name updateConfig 'remove'
105-
# Returns: 0 (success) or -1 (failed to remove)
107+
# Returns: 0 (success) - Removes SD config and clears EEPROM backup
108+
```
109+
110+
###### Parsing Failures (Critical)
111+
```bash
112+
# Invalid JSON structure causes complete failure
113+
particle call device_name updateConfig '{"config":{"system":{"logPeriod":"invalid"}}}'
114+
# Returns: -8 (failed to parse configuration)
106115
```
107116

108117
##### Best Practices
@@ -111,7 +120,9 @@ particle call device_name updateConfig 'remove'
111120
2. **Check Parameter Ranges**: Verify all values are within acceptable ranges
112121
3. **Plan Hardware Requirements**: Ensure sufficient Talons for sensor configuration
113122
4. **Monitor Device Status**: Watch for restart after successful configuration
114-
5. **Verify Configuration**: Check UIDs after restart to confirm changes applied
123+
5. **Verify Configuration**: Check UIDs in metadata packets to confirm changes applied
124+
6. **EEPROM Backup Reliability**: Configuration updates work even with SD card failures
125+
7. **Field Recovery**: Insert fresh SD cards - system automatically restores config from EEPROM
115126

116127
#### Configuration UIDs
117128

lib/Driver_-_Kestrel

src/FlightControl.cpp

Lines changed: 89 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,9 @@ String getMetadataString()
841841
output = output + "\"Update\":" + String(logPeriod) + ",";
842842
output = output + "\"Backhaul\":" + String(backhaulCount) + ",";
843843
output = output + "\"LogMode\":" + String(loggingMode) + ",";
844-
output = output + "\"Sleep\":" + String(powerSaveMode) + "}},";
844+
output = output + "\"Sleep\":" + String(powerSaveMode) + ",";
845+
output = output + "\"SysConfigUID\":" + String(configManager.updateSystemConfigurationUid()) + ",";
846+
output = output + "\"SensorConfigUID\":" + String(configManager.updateSensorConfigurationUid()) + "}},";
845847
//FIX! Add support for device name
846848

847849
uint8_t deviceCount = 0; //Used to keep track of how many devices have been appended
@@ -1074,6 +1076,40 @@ void systemConfig()
10741076
Serial.println("\tDone");
10751077
}
10761078

1079+
if(ReadString.equalsIgnoreCase("Dump SD")) {
1080+
fileSys.dumpSDOverSerial();
1081+
Serial.println("\tDump Complete");
1082+
}
1083+
1084+
if(ReadString.startsWith("Dump SD Recent ")) {
1085+
String countStr = ReadString.substring(15); // "Dump SD Recent " is 15 chars
1086+
uint32_t count = countStr.toInt();
1087+
if (count > 0) {
1088+
fileSys.dumpSDOverSerial(count);
1089+
Serial.print("\tDump Complete (");
1090+
Serial.print(count);
1091+
Serial.println(" recent files per type)");
1092+
} else {
1093+
Serial.println("\tInvalid count parameter");
1094+
}
1095+
}
1096+
1097+
if(ReadString.startsWith("Write SD ")) {
1098+
String filename = ReadString.substring(9); // "Write SD " is 9 chars
1099+
filename.trim();
1100+
if (filename.length() > 0) {
1101+
Serial.print("\tStarting file write: ");
1102+
Serial.println(filename);
1103+
if (fileSys.writeFileOverSerial(filename.c_str())) {
1104+
Serial.println("\tWrite Complete");
1105+
} else {
1106+
Serial.println("\tWrite Failed");
1107+
}
1108+
} else {
1109+
Serial.println("\tInvalid filename parameter");
1110+
}
1111+
}
1112+
10771113
if(ReadString.equalsIgnoreCase("Exit")) {
10781114
return; //Exit the setup function
10791115
}
@@ -1346,15 +1382,17 @@ int setNodeID(String nodeID)
13461382

13471383
int updateConfiguration(String configJson) {
13481384
if(configJson == "remove") {
1349-
// Remove the configuration file from the SD card
1350-
if (!fileSys.removeFileFromSD("config.json")) {
1351-
Serial.println("Error: Failed to remove configuration from SD card.");
1352-
return -1; // Failed to remove config
1353-
}
1354-
else {
1355-
Serial.println("Configuration removed from SD card.");
1385+
// Remove the configuration file from the SD card and clear EEPROM
1386+
bool sdRemoved = fileSys.removeFileFromSD("config.json");
1387+
configManager.clearConfigEEPROM();
1388+
1389+
if (sdRemoved) {
1390+
Serial.println("Configuration removed from SD card and EEPROM.");
1391+
return 0; // Success
1392+
} else {
1393+
Serial.println("Warning: Failed to remove SD config, but EEPROM cleared.");
1394+
return 0; // Still success since EEPROM was cleared
13561395
}
1357-
return 0; // Success
13581396
}
13591397

13601398
Serial.println("Updating configuration...");
@@ -1382,24 +1420,30 @@ int updateConfiguration(String configJson) {
13821420
return -4; // Invalid format
13831421
}
13841422

1385-
// test write to SD card
1386-
if (!fileSys.writeToSD("", "config.json")) {
1387-
Serial.println("Error: Failed to write to SD card.");
1388-
return -5; // Failed to write config
1423+
// First, try to parse and apply the configuration (this will also save to EEPROM)
1424+
bool configParsed = configManager.setConfiguration(configJson.c_str());
1425+
if (!configParsed) {
1426+
Serial.println("Error: Failed to parse configuration.");
1427+
return -8; // Failed to parse config
13891428
}
1429+
Serial.println("Configuration parsed successfully and saved to EEPROM.");
13901430

1391-
//clear current config.json
1392-
if(!fileSys.removeFileFromSD("config.json")) {
1393-
Serial.println("Error: Failed to remove current configuration from SD card.");
1394-
return -6; // Failed to remove current config
1395-
}
1431+
// Try to write to SD card (optional - don't fail if this doesn't work)
1432+
bool sdSuccess = false;
1433+
1434+
// Remove old config first
1435+
fileSys.removeFileFromSD("config.json"); // Don't check return value
13961436

13971437
// Write new configuration to SD card
1398-
if (!fileSys.writeToSD(configJson.c_str(), "config.json")) {
1399-
Serial.println("Error: Failed to write new configuration to SD card.");
1400-
return -7; // Failed to write new config
1438+
if (fileSys.writeToSD(configJson.c_str(), "config.json")) {
1439+
Serial.println("Configuration written to SD card.");
1440+
sdSuccess = true;
1441+
} else {
1442+
Serial.println("Warning: Failed to write configuration to SD card, but EEPROM backup is available.");
14011443
}
14021444

1445+
// Success if config was parsed (EEPROM updated), regardless of SD card status
1446+
Serial.println("Configuration update completed. System will restart to apply changes.");
14031447
System.reset(); //restart the system to apply new configuration
14041448
return 1; //Success
14051449
}
@@ -1524,12 +1568,34 @@ bool loadConfiguration() {
15241568
configLoaded = configManager.setConfiguration(configStr);
15251569
}
15261570

1571+
// If SD card config failed, try EEPROM backup
1572+
if (!configLoaded) {
1573+
Serial.println("SD config failed, trying EEPROM backup...");
1574+
configLoaded = configManager.loadConfigFromEEPROM();
1575+
if (configLoaded) {
1576+
Serial.println("Configuration loaded from EEPROM backup");
1577+
// Restore the config to SD card from EEPROM backup
1578+
std::string eepromConfig = configManager.getConfiguration();
1579+
if (fileSys.writeToSD(eepromConfig.c_str(), "config.json")) {
1580+
Serial.println("EEPROM config restored to SD card");
1581+
} else {
1582+
Serial.println("Warning: Could not restore config to SD card");
1583+
}
1584+
}
1585+
}
1586+
1587+
// If both SD and EEPROM failed, use defaults
15271588
if (!configLoaded) {
15281589
Serial.println("Loading default configuration...");
15291590
std::string defaultConfig = configManager.getDefaultConfigurationJson();
15301591
configLoaded = configManager.setConfiguration(defaultConfig);
1531-
fileSys.removeFileFromSD("config.json");
1532-
fileSys.writeToSD(defaultConfig.c_str(), "config.json");
1592+
// Only write default config to SD if no config file exists, not if parsing failed
1593+
if (configStr.empty()) {
1594+
Serial.println("No config file found, writing default config to SD card...");
1595+
fileSys.writeToSD(defaultConfig.c_str(), "config.json");
1596+
} else {
1597+
Serial.println("Config file exists but parsing failed, keeping existing file on SD card");
1598+
}
15331599
}
15341600

15351601
// Set global variables from configuration

0 commit comments

Comments
 (0)