Skip to content

Commit c37fefa

Browse files
authored
Merge pull request #152 from SenaxInc/copilot/fix-compile-errors-in-tankalarm
Fix Arduino compilation errors and filesystem bug in BluesOpta sketches
2 parents 37fe966 + 75d0c08 commit c37fefa

File tree

3 files changed

+88
-67
lines changed

3 files changed

+88
-67
lines changed

TankAlarm-112025-Client-BluesOpta/TankAlarm-112025-Client-BluesOpta.ino

Lines changed: 66 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -276,28 +276,6 @@ static float getDistanceConversionFactor(const char* unit) {
276276
return 1.0f; // Default: assume inches
277277
}
278278

279-
// Helper function: Get tank height/capacity based on sensor configuration
280-
static float getMonitorHeight(const MonitorConfig &cfg) {
281-
if (cfg.sensorInterface == SENSOR_CURRENT_LOOP) {
282-
if (cfg.currentLoopType == CURRENT_LOOP_ULTRASONIC) {
283-
// For ultrasonic sensors, mount height IS the tank height (distance to bottom)
284-
return cfg.sensorMountHeight;
285-
} else {
286-
// For pressure sensors, max range + mount height approximates full tank height
287-
float rangeInches = cfg.sensorRangeMax * getPressureConversionFactor(cfg.sensorRangeUnit);
288-
return rangeInches + cfg.sensorMountHeight;
289-
}
290-
} else if (cfg.sensorInterface == SENSOR_ANALOG) {
291-
// For analog sensors, max range + mount height approximates full tank height
292-
float rangeInches = cfg.sensorRangeMax * getPressureConversionFactor(cfg.sensorRangeUnit);
293-
return rangeInches + cfg.sensorMountHeight;
294-
} else if (cfg.sensorInterface == SENSOR_DIGITAL) {
295-
// Digital sensors are binary, treat 1.0 as full
296-
return 1.0f;
297-
}
298-
return 0.0f;
299-
}
300-
301279
static const uint8_t NOTECARD_I2C_ADDRESS = 0x17;
302280
static const uint32_t NOTECARD_I2C_FREQUENCY = 400000UL;
303281

@@ -517,45 +495,6 @@ struct PulseSamplingRecommendation {
517495
const char *description; // Human-readable description
518496
};
519497

520-
static PulseSamplingRecommendation getRecommendedPulseSampling(float expectedRate) {
521-
PulseSamplingRecommendation rec;
522-
523-
if (expectedRate <= 0.0f) {
524-
// No expected rate configured - use defaults
525-
rec.sampleDurationMs = RPM_SAMPLE_DURATION_MS;
526-
rec.accumulatedMode = false;
527-
rec.description = "Default (60s sample)";
528-
} else if (expectedRate < 1.0f) {
529-
// Very low rate (< 1 RPM/GPM): use accumulated mode
530-
// Count pulses over entire telemetry interval for accuracy
531-
rec.sampleDurationMs = 60000; // 60s sample within each interval
532-
rec.accumulatedMode = true;
533-
rec.description = "Accumulated mode (very low rate)";
534-
} else if (expectedRate < 10.0f) {
535-
// Low rate (1-10 RPM/GPM): longer sample for accuracy
536-
rec.sampleDurationMs = 60000; // 60 seconds
537-
rec.accumulatedMode = false;
538-
rec.description = "60s sample (low rate)";
539-
} else if (expectedRate < 100.0f) {
540-
// Medium rate (10-100 RPM/GPM): moderate sample
541-
rec.sampleDurationMs = 30000; // 30 seconds
542-
rec.accumulatedMode = false;
543-
rec.description = "30s sample (medium rate)";
544-
} else if (expectedRate < 1000.0f) {
545-
// High rate (100-1000 RPM/GPM): shorter sample is sufficient
546-
rec.sampleDurationMs = 10000; // 10 seconds
547-
rec.accumulatedMode = false;
548-
rec.description = "10s sample (high rate)";
549-
} else {
550-
// Very high rate (> 1000 RPM): quick sample
551-
rec.sampleDurationMs = 3000; // 3 seconds
552-
rec.accumulatedMode = false;
553-
rec.description = "3s sample (very high rate)";
554-
}
555-
556-
return rec;
557-
}
558-
559498
// Serial log buffer structure for client
560499
struct SerialLogEntry {
561500
double timestamp;
@@ -572,6 +511,8 @@ static ClientSerialLog gSerialLog;
572511
static unsigned long gLastSerialRequestCheckMillis = 0;
573512

574513
// Forward declarations
514+
static PulseSamplingRecommendation getRecommendedPulseSampling(float expectedRate);
515+
static float getMonitorHeight(const MonitorConfig &cfg);
575516
static void initializeStorage();
576517
static void ensureConfigLoaded();
577518
static void createDefaultConfig(ClientConfig &cfg);
@@ -789,6 +730,70 @@ void loop() {
789730
#endif
790731
}
791732

733+
// Helper: Get recommended pulse sampling parameters based on expected rate
734+
// This helps configure optimal sampling for the expected RPM/flow rate range
735+
// Returns: pulseSampleDurationMs, pulseAccumulatedMode recommendations
736+
static PulseSamplingRecommendation getRecommendedPulseSampling(float expectedRate) {
737+
PulseSamplingRecommendation rec;
738+
739+
if (expectedRate <= 0.0f) {
740+
// No expected rate configured - use defaults
741+
rec.sampleDurationMs = RPM_SAMPLE_DURATION_MS;
742+
rec.accumulatedMode = false;
743+
rec.description = "Default (60s sample)";
744+
} else if (expectedRate < 1.0f) {
745+
// Very low rate (< 1 RPM/GPM): use accumulated mode
746+
// Count pulses over entire telemetry interval for accuracy
747+
rec.sampleDurationMs = 60000; // 60s sample within each interval
748+
rec.accumulatedMode = true;
749+
rec.description = "Accumulated mode (very low rate)";
750+
} else if (expectedRate < 10.0f) {
751+
// Low rate (1-10 RPM/GPM): longer sample for accuracy
752+
rec.sampleDurationMs = 60000; // 60 seconds
753+
rec.accumulatedMode = false;
754+
rec.description = "60s sample (low rate)";
755+
} else if (expectedRate < 100.0f) {
756+
// Medium rate (10-100 RPM/GPM): moderate sample
757+
rec.sampleDurationMs = 30000; // 30 seconds
758+
rec.accumulatedMode = false;
759+
rec.description = "30s sample (medium rate)";
760+
} else if (expectedRate < 1000.0f) {
761+
// High rate (100-1000 RPM/GPM): shorter sample is sufficient
762+
rec.sampleDurationMs = 10000; // 10 seconds
763+
rec.accumulatedMode = false;
764+
rec.description = "10s sample (high rate)";
765+
} else {
766+
// Very high rate (> 1000 RPM): quick sample
767+
rec.sampleDurationMs = 3000; // 3 seconds
768+
rec.accumulatedMode = false;
769+
rec.description = "3s sample (very high rate)";
770+
}
771+
772+
return rec;
773+
}
774+
775+
// Helper function: Get tank height/capacity based on sensor configuration
776+
static float getMonitorHeight(const MonitorConfig &cfg) {
777+
if (cfg.sensorInterface == SENSOR_CURRENT_LOOP) {
778+
if (cfg.currentLoopType == CURRENT_LOOP_ULTRASONIC) {
779+
// For ultrasonic sensors, mount height IS the tank height (distance to bottom)
780+
return cfg.sensorMountHeight;
781+
} else {
782+
// For pressure sensors, max range + mount height approximates full tank height
783+
float rangeInches = cfg.sensorRangeMax * getPressureConversionFactor(cfg.sensorRangeUnit);
784+
return rangeInches + cfg.sensorMountHeight;
785+
}
786+
} else if (cfg.sensorInterface == SENSOR_ANALOG) {
787+
// For analog sensors, max range + mount height approximates full tank height
788+
float rangeInches = cfg.sensorRangeMax * getPressureConversionFactor(cfg.sensorRangeUnit);
789+
return rangeInches + cfg.sensorMountHeight;
790+
} else if (cfg.sensorInterface == SENSOR_DIGITAL) {
791+
// Digital sensors are binary, treat 1.0 as full
792+
return 1.0f;
793+
}
794+
return 0.0f;
795+
}
796+
792797
static void initializeStorage() {
793798
#ifdef FILESYSTEM_AVAILABLE
794799
#if defined(ARDUINO_OPTA) || defined(ARDUINO_ARCH_MBED)

TankAlarm-112025-Server-BluesOpta/TankAlarm-112025-Server-BluesOpta.ino

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,14 +1919,22 @@ static bool ftpRestoreClientConfigs(FtpSession &session, char *error, size_t err
19191919
}
19201920

19211921
// Open cache file for writing (truncate)
1922-
if (SD.exists(CLIENT_CONFIG_CACHE_PATH)) {
1923-
SD.remove(CLIENT_CONFIG_CACHE_PATH);
1922+
#if defined(ARDUINO_OPTA) || defined(ARDUINO_ARCH_MBED)
1923+
FILE *cacheFile = fopen("/fs/client_config_cache.txt", "w");
1924+
if (!cacheFile) {
1925+
snprintf(error, errorSize, "Failed to open cache file");
1926+
return false;
19241927
}
1925-
File cacheFile = SD.open(CLIENT_CONFIG_CACHE_PATH, FILE_WRITE);
1928+
#else
1929+
if (LittleFS.exists(CLIENT_CONFIG_CACHE_PATH)) {
1930+
LittleFS.remove(CLIENT_CONFIG_CACHE_PATH);
1931+
}
1932+
File cacheFile = LittleFS.open(CLIENT_CONFIG_CACHE_PATH, "w");
19261933
if (!cacheFile) {
19271934
snprintf(error, errorSize, "Failed to open cache file");
19281935
return false;
19291936
}
1937+
#endif
19301938

19311939
// Parse manifest lines: uid \t site
19321940
char *lineStart = manifest;
@@ -1974,10 +1982,14 @@ static bool ftpRestoreClientConfigs(FtpSession &session, char *error, size_t err
19741982
while(cEnd >= cStart && isspace(*cEnd)) *cEnd-- = 0;
19751983

19761984
if (strlen(cStart) > 0) {
1985+
#if defined(ARDUINO_OPTA) || defined(ARDUINO_ARCH_MBED)
1986+
fprintf(cacheFile, "%s\t%s\n", uid, cStart);
1987+
#else
19771988
cacheFile.print(uid);
19781989
cacheFile.print('\t');
19791990
cacheFile.print(cStart);
19801991
cacheFile.print('\n');
1992+
#endif
19811993
restoredFiles++;
19821994
Serial.print(F("FTP restore client config: "));
19831995
Serial.println(remotePath);
@@ -1990,7 +2002,11 @@ static bool ftpRestoreClientConfigs(FtpSession &session, char *error, size_t err
19902002
lineStart = lineEnd + 1;
19912003
}
19922004

2005+
#if defined(ARDUINO_OPTA) || defined(ARDUINO_ARCH_MBED)
2006+
fclose(cacheFile);
2007+
#else
19932008
cacheFile.close();
2009+
#endif
19942010
return true;
19952011
}
19962012

@@ -3197,9 +3213,9 @@ static void handleFtpRestorePost(EthernetClient &client, const String &body) {
31973213
DynamicJsonDocument resp(192);
31983214
resp["ok"] = ok;
31993215
if (ok) {
3200-
resp["message"] = F("Restore completed from FTP");
3216+
resp["message"] = "Restore completed from FTP";
32013217
} else {
3202-
resp["error"] = error.length() ? error : F("Restore failed");
3218+
resp["error"] = strlen(error) ? error : "Restore failed";
32033219
}
32043220
String json;
32053221
serializeJson(resp, json);

TankAlarm-112025-Viewer-BluesOpta/TankAlarm-112025-Viewer-BluesOpta.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ static void sendDashboard(EthernetClient &client) {
527527
static void sendTankJson(EthernetClient &client) {
528528
std::unique_ptr<DynamicJsonDocument> docPtr(new DynamicJsonDocument(TANK_JSON_CAPACITY + 256));
529529
if (!docPtr) {
530-
respondStatus(client, 500, F("Out of Memory"));
530+
respondStatus(client, 500, "Out of Memory");
531531
return;
532532
}
533533
DynamicJsonDocument &doc = *docPtr;

0 commit comments

Comments
 (0)