Skip to content

Commit 3e5dc29

Browse files
Implement Analysis Task for background operations (Issue #17)
This commit implements Phase 5 of the RTOS implementation requirements, adding background execution of long-running analysis operations with progress reporting and cancellation support. Major Features: - AnalysisTask class for managing background analysis operations - Support for three analysis types: * Channel congestion scanning * Latency testing (ping/ICMP) * iPerf bandwidth testing (client/server modes) - Concurrent operation management with counting semaphore (max 2) - Progress reporting (0-100%) via dedicated progress queue - Cancellation support with per-operation flags - Non-blocking result delivery via result queue Implementation Details: - AnalysisRequest structure with type-specific configurations * No unions used to avoid C++ restrictions with non-trivial types * Separate fields: channelConfig, latencyConfig, iperfConfig - AnalysisProgress structure for incremental progress updates - AnalysisTaskResult structure (renamed from AnalysisResult to avoid conflict with queue_manager.h) - Active operation tracking with request IDs and cancellation flags - Task runs on Core 0 (WiFi Core) with MEDIUM priority - Stack size: 12288 bytes Public API Functions: - queueChannelScan(): Submit channel scan request - queueLatencyTest(): Submit latency test request - queueIPerfTest(): Submit iPerf test request - cancelAnalysisRequest(): Cancel running operation by request ID - getAnalysisProgress(): Poll for progress updates (non-blocking) - getAnalysisResult(): Poll for completed results (non-blocking) Integration: - Integrated into main.cpp after WebTask initialization - Conditional compilation for RTOS mode only - Both builds verified: esp32dev_rtos (85.6%), esp32dev (83.1%) Addresses: #17 (Analysis Task Implementation, Phase 5) Part of: #12 (RTOS Implementation Requirements) for v4.1.0 milestone
1 parent a345007 commit 3e5dc29

File tree

3 files changed

+981
-0
lines changed

3 files changed

+981
-0
lines changed

include/analysis_task.h

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
#pragma once
2+
3+
#include <Arduino.h>
4+
#include "task_base.h"
5+
#include "queue_manager.h"
6+
#include "config.h"
7+
#include "channel_analyzer.h"
8+
#include "latency_analyzer.h"
9+
#include "iperf_manager.h"
10+
11+
#ifdef USE_RTOS
12+
13+
// ==========================================
14+
// CONSTANTS
15+
// ==========================================
16+
#define ANALYSIS_REQUEST_QUEUE_LENGTH 5
17+
#define ANALYSIS_PROGRESS_QUEUE_LENGTH 10
18+
#define ANALYSIS_RESULT_QUEUE_LENGTH 5
19+
#define MAX_CONCURRENT_ANALYSES 2 // Maximum 2 concurrent analyses
20+
21+
// ==========================================
22+
// ANALYSIS REQUEST STRUCTURES
23+
// ==========================================
24+
25+
/**
26+
* @brief Analysis operation types
27+
*/
28+
enum class AnalysisType {
29+
CHANNEL_SCAN, ///< Channel congestion analysis
30+
LATENCY_TEST, ///< Network latency testing
31+
IPERF_TEST, ///< iPerf throughput testing
32+
NONE ///< No operation
33+
};
34+
35+
/**
36+
* @brief Analysis request structure
37+
*/
38+
struct AnalysisRequest {
39+
AnalysisType type;
40+
uint32_t requestId; ///< Unique request identifier
41+
uint32_t timestamp; ///< Request timestamp
42+
bool cancellable; ///< Can this request be cancelled?
43+
44+
// Type-specific parameters (only one will be valid based on type)
45+
ChannelScanConfig channelConfig;
46+
LatencyConfig latencyConfig;
47+
IperfConfig iperfConfig;
48+
};
49+
50+
/**
51+
* @brief Analysis progress update structure
52+
*/
53+
struct AnalysisProgress {
54+
AnalysisType type;
55+
uint32_t requestId;
56+
uint8_t progressPercent; ///< 0-100
57+
String statusMessage;
58+
unsigned long timestamp;
59+
};
60+
61+
/**
62+
* @brief Analysis task result structure
63+
*/
64+
struct AnalysisTaskResult {
65+
AnalysisType type;
66+
uint32_t requestId;
67+
bool success;
68+
String errorMessage;
69+
unsigned long duration_ms;
70+
unsigned long timestamp;
71+
72+
// Type-specific results (only one will be valid based on type)
73+
ChannelAnalysisResults channelResults;
74+
LatencyTestResults latencyResults;
75+
IperfResults iperfResults;
76+
};
77+
78+
/**
79+
* @brief Analysis task state
80+
*/
81+
enum class AnalysisTaskState {
82+
UNINITIALIZED, ///< Task not initialized
83+
IDLE, ///< Task running, waiting for requests
84+
PROCESSING, ///< Processing analysis request
85+
ERROR ///< Error state
86+
};
87+
88+
// ==========================================
89+
// ANALYSIS TASK CLASS
90+
// ==========================================
91+
92+
/**
93+
* @brief Analysis Task
94+
*
95+
* Manages long-running analysis operations in background with progress reporting.
96+
* Supports concurrent execution (max 2) and cancellation.
97+
*/
98+
class AnalysisTask : public TaskBase {
99+
private:
100+
// State management
101+
AnalysisTaskState currentState;
102+
uint32_t nextRequestId;
103+
104+
// Concurrent operation management
105+
SemaphoreHandle_t concurrentOpsSemaphore; // Counting semaphore (max 2)
106+
uint8_t activeOperations;
107+
108+
// Request and result queues
109+
QueueHandle_t requestQueue;
110+
QueueHandle_t progressQueue;
111+
QueueHandle_t resultQueue;
112+
113+
// Active operations tracking
114+
struct ActiveOperation {
115+
bool active;
116+
AnalysisType type;
117+
uint32_t requestId;
118+
unsigned long startTime;
119+
bool cancellationRequested;
120+
};
121+
ActiveOperation activeOps[MAX_CONCURRENT_ANALYSES];
122+
123+
// Request processing
124+
void processRequestQueue();
125+
bool processRequest(const AnalysisRequest& request);
126+
int findFreeSlot();
127+
int findActiveSlot(uint32_t requestId);
128+
void releaseSlot(int slot);
129+
130+
// Analysis handlers
131+
bool handleChannelScan(const AnalysisRequest& request, int slot);
132+
bool handleLatencyTest(const AnalysisRequest& request, int slot);
133+
bool handleIPerfTest(const AnalysisRequest& request, int slot);
134+
135+
// Progress reporting
136+
void reportProgress(uint32_t requestId, AnalysisType type, uint8_t percent, const String& message);
137+
void reportResult(const AnalysisTaskResult& result);
138+
139+
// Cancellation
140+
bool isCancellationRequested(int slot);
141+
void markCancelled(int slot);
142+
143+
// State transitions
144+
void transitionState(AnalysisTaskState newState);
145+
const char* stateToString(AnalysisTaskState state);
146+
const char* analysisTypeToString(AnalysisType type);
147+
148+
protected:
149+
/**
150+
* @brief Task setup - Initialize analysis handling
151+
*/
152+
void setup() override;
153+
154+
/**
155+
* @brief Task main loop - Process analysis requests
156+
*/
157+
void loop() override;
158+
159+
/**
160+
* @brief Task cleanup
161+
*/
162+
void cleanup() override;
163+
164+
public:
165+
/**
166+
* @brief Constructor
167+
* @param name Task name
168+
* @param stackSize Stack size in bytes (default 12288)
169+
* @param priority Task priority (default MEDIUM)
170+
* @param core Core to run on (default 0 - WiFi Core)
171+
*/
172+
AnalysisTask(const char* name,
173+
uint32_t stackSize = 12288,
174+
TaskPriority priority = static_cast<TaskPriority>(2),
175+
BaseType_t core = 0);
176+
177+
/**
178+
* @brief Destructor
179+
*/
180+
virtual ~AnalysisTask();
181+
182+
/**
183+
* @brief Queue an analysis request (thread-safe)
184+
* @param request Request to queue
185+
* @return Request ID (0 if failed)
186+
*/
187+
uint32_t queueRequest(const AnalysisRequest& request);
188+
189+
/**
190+
* @brief Cancel an analysis operation
191+
* @param requestId Request ID to cancel
192+
* @return true if cancellation requested
193+
*/
194+
bool cancelRequest(uint32_t requestId);
195+
196+
/**
197+
* @brief Get progress update (non-blocking)
198+
* @param progress Output progress structure
199+
* @return true if progress available
200+
*/
201+
bool getProgress(AnalysisProgress& progress);
202+
203+
/**
204+
* @brief Get result (non-blocking)
205+
* @param result Output result structure
206+
* @return true if result available
207+
*/
208+
bool getResult(AnalysisTaskResult& result);
209+
210+
/**
211+
* @brief Get current task state
212+
* @return Current state
213+
*/
214+
AnalysisTaskState getState() const { return currentState; }
215+
216+
/**
217+
* @brief Get number of active operations
218+
* @return Active operation count
219+
*/
220+
uint8_t getActiveOperationCount() const { return activeOperations; }
221+
222+
/**
223+
* @brief Get request queue fill level
224+
* @return Number of requests in queue
225+
*/
226+
uint32_t getQueuedRequestCount() const;
227+
};
228+
229+
// ==========================================
230+
// GLOBAL ANALYSIS TASK MANAGEMENT
231+
// ==========================================
232+
233+
/**
234+
* @brief Initialize Analysis Task
235+
* @return true if initialization successful
236+
*/
237+
bool initializeAnalysisTask();
238+
239+
/**
240+
* @brief Shutdown Analysis Task
241+
*/
242+
void shutdownAnalysisTask();
243+
244+
/**
245+
* @brief Check if Analysis Task is running
246+
* @return true if running
247+
*/
248+
bool isAnalysisTaskRunning();
249+
250+
/**
251+
* @brief Queue a channel scan analysis
252+
* @param config Channel scan configuration
253+
* @return Request ID (0 if failed)
254+
*/
255+
uint32_t queueChannelScan(const ChannelScanConfig& config);
256+
257+
/**
258+
* @brief Queue a latency test
259+
* @param config Latency test configuration
260+
* @return Request ID (0 if failed)
261+
*/
262+
uint32_t queueLatencyTest(const LatencyConfig& config);
263+
264+
/**
265+
* @brief Queue an iPerf test
266+
* @param config iPerf test configuration
267+
* @return Request ID (0 if failed)
268+
*/
269+
uint32_t queueIPerfTest(const IperfConfig& config);
270+
271+
/**
272+
* @brief Cancel an analysis operation
273+
* @param requestId Request ID to cancel
274+
* @return true if cancellation requested
275+
*/
276+
bool cancelAnalysisRequest(uint32_t requestId);
277+
278+
/**
279+
* @brief Get analysis progress (non-blocking)
280+
* @param progress Output progress structure
281+
* @return true if progress available
282+
*/
283+
bool getAnalysisProgress(AnalysisProgress& progress);
284+
285+
/**
286+
* @brief Get analysis result (non-blocking)
287+
* @param result Output result structure
288+
* @return true if result available
289+
*/
290+
bool getAnalysisResult(AnalysisTaskResult& result);
291+
292+
/**
293+
* @brief Get Analysis Task state
294+
* @return Current state
295+
*/
296+
AnalysisTaskState getAnalysisTaskState();
297+
298+
/**
299+
* @brief Get active operation count
300+
* @return Number of active operations
301+
*/
302+
uint8_t getActiveAnalysisCount();
303+
304+
/**
305+
* @brief Get queued request count
306+
* @return Number of requests in queue
307+
*/
308+
uint32_t getQueuedAnalysisCount();
309+
310+
#endif // USE_RTOS

0 commit comments

Comments
 (0)