// auto_trigger.cpp - Auto-Logging Trigger Implementation #include "auto_trigger.h" TriggerConfig triggerConfig; bool triggerActive = false; bool loggingActive = false; static uint32_t loggingStartTime = 0; void initAutoTrigger() { triggerConfig.conditionCount = 0; triggerConfig.logicOp = LOGIC_AND; triggerConfig.enabled = false; triggerConfig.autoStart = true; triggerConfig.autoStop = false; triggerConfig.durationMs = 0; triggerActive = false; loggingActive = false; loadTriggerConfig(); } bool addTriggerCondition(const char* signalName, TriggerOperator op, float threshold) { if (triggerConfig.conditionCount >= MAX_TRIGGER_CONDITIONS) { return false; } TriggerCondition* cond = &triggerConfig.conditions[triggerConfig.conditionCount++]; strncpy(cond->signalName, signalName, 31); cond->op = op; cond->threshold = threshold; cond->active = true; return true; } bool removeTriggerCondition(uint8_t index) { if (index >= triggerConfig.conditionCount) { return false; } // Shift conditions for (uint8_t i = index; i < triggerConfig.conditionCount - 1; i++) { triggerConfig.conditions[i] = triggerConfig.conditions[i + 1]; } triggerConfig.conditionCount--; return true; } void clearTriggerConditions() { triggerConfig.conditionCount = 0; } void setLogicalOperator(LogicalOperator op) { triggerConfig.logicOp = op; } void enableTrigger(bool enable) { triggerConfig.enabled = enable; if (!enable) { triggerActive = false; } } void setAutoStart(bool enable) { triggerConfig.autoStart = enable; } void setAutoStop(bool enable) { triggerConfig.autoStop = enable; } bool checkTriggerConditions() { if (triggerConfig.conditionCount == 0) { return false; } bool result = (triggerConfig.logicOp == LOGIC_AND); for (uint8_t i = 0; i < triggerConfig.conditionCount; i++) { TriggerCondition* cond = &triggerConfig.conditions[i]; if (!cond->active) continue; // Get current signal value SignalValue* sv = getSignalValue(cond->signalName); if (!sv || !sv->valid) { if (triggerConfig.logicOp == LOGIC_AND) { return false; } continue; } bool conditionMet = false; switch (cond->op) { case TRIGGER_OP_GREATER: conditionMet = sv->value > cond->threshold; break; case TRIGGER_OP_LESS: conditionMet = sv->value < cond->threshold; break; case TRIGGER_OP_EQUAL: conditionMet = fabs(sv->value - cond->threshold) < 0.001; break; case TRIGGER_OP_GREATER_EQ: conditionMet = sv->value >= cond->threshold; break; case TRIGGER_OP_LESS_EQ: conditionMet = sv->value <= cond->threshold; break; } if (triggerConfig.logicOp == LOGIC_AND) { result = result && conditionMet; if (!result) return false; } else { result = result || conditionMet; if (result) return true; } } return result; } void updateTrigger() { if (!triggerConfig.enabled) return; bool conditionsMet = checkTriggerConditions(); // Auto-start logging if (triggerConfig.autoStart && conditionsMet && !loggingActive) { loggingActive = true; triggerActive = true; loggingStartTime = millis(); // TODO: Start SD logging Serial.println("Auto-trigger: Started logging"); } // Auto-stop logging if (loggingActive) { bool shouldStop = false; // Stop if conditions no longer met (and autoStop enabled) if (triggerConfig.autoStop && !conditionsMet) { shouldStop = true; } // Stop if duration exceeded if (triggerConfig.durationMs > 0 && (millis() - loggingStartTime) >= triggerConfig.durationMs) { shouldStop = true; } if (shouldStop) { loggingActive = false; triggerActive = false; // TODO: Stop SD logging Serial.println("Auto-trigger: Stopped logging"); } } } bool loadTriggerConfig() { // TODO: Load from SD card return false; } bool saveTriggerConfig() { // TODO: Save to SD card return false; } void getTriggerStatusJSON(char* buffer, size_t bufferSize) { snprintf(buffer, bufferSize, "{\"enabled\":%s,\"active\":%s,\"logging\":%s,\"conditions\":%d,\"logic\":\"%s\"}", triggerConfig.enabled ? "true" : "false", triggerActive ? "true" : "false", loggingActive ? "true" : "false", triggerConfig.conditionCount, triggerConfig.logicOp == LOGIC_AND ? "AND" : "OR"); }