@@ -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+
160167struct 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
180188struct 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
452461static 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 " ));
0 commit comments