Skip to content

Commit 77d25eb

Browse files
Copilotdorkmo
andcommitted
Add relay trigger condition option to allow alarm-specific relay activation
Co-authored-by: dorkmo <[email protected]>
1 parent c9b53c1 commit 77d25eb

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

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

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ enum SensorType : uint8_t {
157157
SENSOR_HALL_EFFECT_RPM = 3
158158
};
159159

160+
// Relay trigger conditions - which alarm type triggers the relay
161+
enum RelayTrigger : uint8_t {
162+
RELAY_TRIGGER_ANY = 0, // Trigger on any alarm (high or low)
163+
RELAY_TRIGGER_HIGH = 1, // Trigger only on high alarm
164+
RELAY_TRIGGER_LOW = 2 // Trigger only on low alarm
165+
};
166+
160167
struct TankConfig {
161168
char id; // Friendly identifier (A, B, C ...)
162169
char name[24]; // Site/tank label shown in reports
@@ -175,6 +182,7 @@ struct TankConfig {
175182
bool enableServerUpload; // Send telemetry to server
176183
char relayTargetClient[48]; // Client UID to trigger relays on (empty = none)
177184
uint8_t relayMask; // Bitmask of relays to trigger (bit 0=relay 1, etc.)
185+
RelayTrigger relayTrigger; // Which alarm type triggers the relay (any, high, low)
178186
};
179187

180188
struct ClientConfig {
@@ -447,6 +455,7 @@ static void createDefaultConfig(ClientConfig &cfg) {
447455
cfg.tanks[0].enableServerUpload = true;
448456
cfg.tanks[0].relayTargetClient[0] = '\0'; // No relay target by default
449457
cfg.tanks[0].relayMask = 0; // No relays triggered by default
458+
cfg.tanks[0].relayTrigger = RELAY_TRIGGER_ANY; // Default: trigger on any alarm
450459
}
451460

452461
static bool loadConfigFromFlash(ClientConfig &cfg) {
@@ -516,6 +525,15 @@ static bool loadConfigFromFlash(ClientConfig &cfg) {
516525
const char *relayTarget = t["relayTargetClient"].as<const char *>();
517526
strlcpy(cfg.tanks[i].relayTargetClient, relayTarget ? relayTarget : "", sizeof(cfg.tanks[i].relayTargetClient));
518527
cfg.tanks[i].relayMask = t["relayMask"].is<uint8_t>() ? t["relayMask"].as<uint8_t>() : 0;
528+
// Load relay trigger condition (defaults to 'any' for backwards compatibility)
529+
const char *relayTriggerStr = t["relayTrigger"].as<const char *>();
530+
if (relayTriggerStr && strcmp(relayTriggerStr, "high") == 0) {
531+
cfg.tanks[i].relayTrigger = RELAY_TRIGGER_HIGH;
532+
} else if (relayTriggerStr && strcmp(relayTriggerStr, "low") == 0) {
533+
cfg.tanks[i].relayTrigger = RELAY_TRIGGER_LOW;
534+
} else {
535+
cfg.tanks[i].relayTrigger = RELAY_TRIGGER_ANY;
536+
}
519537
}
520538

521539
return true;
@@ -563,6 +581,12 @@ static bool saveConfigToFlash(const ClientConfig &cfg) {
563581
// Save relay control settings
564582
t["relayTargetClient"] = cfg.tanks[i].relayTargetClient;
565583
t["relayMask"] = cfg.tanks[i].relayMask;
584+
// Save relay trigger condition as string
585+
switch (cfg.tanks[i].relayTrigger) {
586+
case RELAY_TRIGGER_HIGH: t["relayTrigger"] = "high"; break;
587+
case RELAY_TRIGGER_LOW: t["relayTrigger"] = "low"; break;
588+
default: t["relayTrigger"] = "any"; break;
589+
}
566590
}
567591

568592
File file = LittleFS.open(CLIENT_CONFIG_PATH, "w");
@@ -931,6 +955,16 @@ static void applyConfigUpdate(const JsonDocument &doc) {
931955
if (t.containsKey("relayMask")) {
932956
gConfig.tanks[i].relayMask = t["relayMask"].as<uint8_t>();
933957
}
958+
if (t.containsKey("relayTrigger")) {
959+
const char *triggerStr = t["relayTrigger"].as<const char *>();
960+
if (triggerStr && strcmp(triggerStr, "high") == 0) {
961+
gConfig.tanks[i].relayTrigger = RELAY_TRIGGER_HIGH;
962+
} else if (triggerStr && strcmp(triggerStr, "low") == 0) {
963+
gConfig.tanks[i].relayTrigger = RELAY_TRIGGER_LOW;
964+
} else {
965+
gConfig.tanks[i].relayTrigger = RELAY_TRIGGER_ANY;
966+
}
967+
}
934968
}
935969
}
936970

@@ -1425,9 +1459,25 @@ static void sendAlarm(uint8_t idx, const char *alarmType, float inches) {
14251459
Serial.print(F(" type "));
14261460
Serial.println(alarmType);
14271461

1428-
// Trigger remote relays if configured
1462+
// Trigger remote relays if configured and alarm type matches trigger condition
14291463
if (isAlarm && cfg.relayTargetClient[0] != '\0' && cfg.relayMask != 0) {
1430-
triggerRemoteRelays(cfg.relayTargetClient, cfg.relayMask, isAlarm);
1464+
bool shouldTriggerRelay = false;
1465+
1466+
// Check if this alarm type matches the relay trigger condition
1467+
if (cfg.relayTrigger == RELAY_TRIGGER_ANY) {
1468+
shouldTriggerRelay = true;
1469+
} else if (cfg.relayTrigger == RELAY_TRIGGER_HIGH && strcmp(alarmType, "high") == 0) {
1470+
shouldTriggerRelay = true;
1471+
} else if (cfg.relayTrigger == RELAY_TRIGGER_LOW && strcmp(alarmType, "low") == 0) {
1472+
shouldTriggerRelay = true;
1473+
}
1474+
1475+
if (shouldTriggerRelay) {
1476+
triggerRemoteRelays(cfg.relayTargetClient, cfg.relayMask, isAlarm);
1477+
Serial.print(F("Relay triggered for "));
1478+
Serial.print(alarmType);
1479+
Serial.println(F(" alarm"));
1480+
}
14311481
}
14321482
} else {
14331483
Serial.print(F("Network offline - local alarm only for tank "));

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,9 +606,16 @@ static const char CONFIG_GENERATOR_HTML[] PROGMEM = R"HTML(
606606
<label class="field"><span>High Alarm</span><input type="number" class="high-alarm" value="100"></label>
607607
<label class="field"><span>Low Alarm</span><input type="number" class="low-alarm" value="20"></label>
608608
</div>
609-
<h4 style="margin: 16px 0 8px; font-size: 0.95rem; border-top: 1px solid var(--card-border); padding-top: 12px;">Relay Switch Control</h4>
609+
<h4 style="margin: 16px 0 8px; font-size: 0.95rem; border-top: 1px solid var(--card-border); padding-top: 12px;">Relay Switch Control (Triggered by This Sensor's Alarm)</h4>
610610
<div class="form-grid">
611611
<label class="field"><span>Target Client UID</span><input type="text" class="relay-target" placeholder="dev:IMEI (optional)"></label>
612+
<label class="field"><span>Trigger On</span>
613+
<select class="relay-trigger">
614+
<option value="any">Any Alarm (High or Low)</option>
615+
<option value="high">High Alarm Only</option>
616+
<option value="low">Low Alarm Only</option>
617+
</select>
618+
</label>
612619
<label class="field"><span>Relay Outputs</span>
613620
<div style="display: flex; gap: 12px; padding: 8px 0;">
614621
<label style="display: flex; align-items: center; gap: 4px;"><input type="checkbox" class="relay-1" value="1"> R1</label>
@@ -743,6 +750,7 @@ static const char CONFIG_GENERATOR_HTML[] PROGMEM = R"HTML(
743750
if (card.querySelector('.relay-4').checked) relayMask |= 8;
744751
745752
const relayTarget = card.querySelector('.relay-target').value.trim();
753+
const relayTrigger = card.querySelector('.relay-trigger').value;
746754
747755
const tank = {
748756
id: String.fromCharCode(65 + index), // A, B, C...
@@ -765,6 +773,7 @@ static const char CONFIG_GENERATOR_HTML[] PROGMEM = R"HTML(
765773
if (relayTarget || relayMask) {
766774
tank.relayTargetClient = relayTarget;
767775
tank.relayMask = relayMask;
776+
tank.relayTrigger = relayTrigger; // 'any', 'high', or 'low'
768777
}
769778
config.tanks.push(tank);
770779
});

0 commit comments

Comments
 (0)