C語言訪問者模式詳解與實踐 - 傳感器數據處理系統
1. 什么是訪問者模式?
在嵌入式系統中,我們經常需要對不同傳感器的數據進行多種處理,如數據校準、過濾、存儲等。訪問者模式允許我們在不修改傳感器代碼的情況下,添加新的數據處理方法。
2. 為什么需要訪問者模式?
- 分離數據采集和處理邏輯
- 便于添加新的數據處理方法
- 避免修改現有傳感器代碼
- 便于數據處理的復用
- 結構清晰,易于維護
3. 實際應用場景
- 多傳感器數據處理
- 數據校準和濾波
- 傳感器狀態監控
- 數據記錄和分析
- 故障診斷系統
4. 代碼實現
4.1 頭文件 (sensor_visitor.h)
#ifndef SENSOR_VISITOR_H
#define SENSOR_VISITOR_H#include <stdint.h>// 傳感器類型
typedef enum {TEMP_SENSOR,HUMIDITY_SENSOR
} SensorType;// 傳感器數據結構
typedef struct {uint16_t raw_data; // 原始數據uint32_t timestamp; // 時間戳SensorType type; // 傳感器類型
} SensorData;// 溫度傳感器
typedef struct {SensorData data;float offset; // 溫度補償值
} TempSensor;// 濕度傳感器
typedef struct {SensorData data;uint8_t threshold; // 濕度閾值
} HumiditySensor;// 訪問者接口
typedef struct {void (*visit_temp)(void* self, TempSensor* sensor);void (*visit_humidity)(void* self, HumiditySensor* sensor);void* context; // 訪問者上下文
} SensorVisitor;// 傳感器操作接口
void accept_visitor(void* sensor, SensorType type, SensorVisitor* visitor);// 創建傳感器
TempSensor* create_temp_sensor(uint16_t raw_data, float offset);
HumiditySensor* create_humidity_sensor(uint16_t raw_data, uint8_t threshold);// 創建訪問者
SensorVisitor* create_calibration_visitor(void); // 校準訪問者
SensorVisitor* create_filter_visitor(void); // 濾波訪問者
SensorVisitor* create_alarm_visitor(void); // 報警訪問者// 銷毀函數
void destroy_sensor(void* sensor);
void destroy_visitor(SensorVisitor* visitor);#endif // SENSOR_VISITOR_H
4.2 實現文件 (sensor_visitor.c)
#include "sensor_visitor.h"
#include <stdio.h>
#include <stdlib.h>// 傳感器創建函數
TempSensor* create_temp_sensor(uint16_t raw_data, float offset) {TempSensor* sensor = (TempSensor*)malloc(sizeof(TempSensor));sensor->data.raw_data = raw_data;sensor->data.timestamp = 0; // 實際應用中需要獲取真實時間戳sensor->data.type = TEMP_SENSOR;sensor->offset = offset;return sensor;
}HumiditySensor* create_humidity_sensor(uint16_t raw_data, uint8_t threshold) {HumiditySensor* sensor = (HumiditySensor*)malloc(sizeof(HumiditySensor));sensor->data.raw_data = raw_data;sensor->data.timestamp = 0;sensor->data.type = HUMIDITY_SENSOR;sensor->threshold = threshold;return sensor;
}// 校準訪問者實現
static void calibrate_temp(void* self, TempSensor* sensor) {float real_temp = sensor->data.raw_data * 0.1f + sensor->offset;printf("溫度校準: %.1f°C (原始值: %d, 偏移: %.1f)\n", real_temp, sensor->data.raw_data, sensor->offset);
}static void calibrate_humidity(void* self, HumiditySensor* sensor) {float real_humidity = sensor->data.raw_data * 0.1f;printf("濕度校準: %.1f%% (原始值: %d)\n", real_humidity, sensor->data.raw_data);
}// 濾波訪問者實現
static void filter_temp(void* self, TempSensor* sensor) {// 簡單的閾值濾波if (sensor->data.raw_data > 1000) {printf("溫度數據濾波: 數值異常\n");} else {printf("溫度數據濾波: 數值正常\n");}
}static void filter_humidity(void* self, HumiditySensor* sensor) {if (sensor->data.raw_data > 1000) {printf("濕度數據濾波: 數值異常\n");} else {printf("濕度數據濾波: 數值正常\n");}
}// 報警訪問者實現
static void alarm_temp(void* self, TempSensor* sensor) {float real_temp = sensor->data.raw_data * 0.1f + sensor->offset;if (real_temp > 50.0f) {printf("溫度報警: 溫度過高 (%.1f°C)\n", real_temp);}
}static void alarm_humidity(void* self, HumiditySensor* sensor) {if (sensor->data.raw_data > sensor->threshold) {printf("濕度報警: 超過閾值 %d\n", sensor->threshold);}
}// 創建訪問者
SensorVisitor* create_calibration_visitor(void) {SensorVisitor* visitor = (SensorVisitor*)malloc(sizeof(SensorVisitor));visitor->visit_temp = calibrate_temp;visitor->visit_humidity = calibrate_humidity;return visitor;
}SensorVisitor* create_filter_visitor(void) {SensorVisitor* visitor = (SensorVisitor*)malloc(sizeof(SensorVisitor));visitor->visit_temp = filter_temp;visitor->visit_humidity = filter_humidity;return visitor;
}SensorVisitor* create_alarm_visitor(void) {SensorVisitor* visitor = (SensorVisitor*)malloc(sizeof(SensorVisitor));visitor->visit_temp = alarm_temp;visitor->visit_humidity = alarm_humidity;return visitor;
}// accept函數實現
void accept_visitor(void* sensor, SensorType type, SensorVisitor* visitor) {switch (type) {case TEMP_SENSOR:visitor->visit_temp(visitor, (TempSensor*)sensor);break;case HUMIDITY_SENSOR:visitor->visit_humidity(visitor, (HumiditySensor*)sensor);break;}
}// 銷毀函數
void destroy_sensor(void* sensor) {free(sensor);
}void destroy_visitor(SensorVisitor* visitor) {free(visitor);
}
4.3 使用示例 (main.c)
#include "sensor_visitor.h"
#include <stdio.h>int main() {// 創建傳感器TempSensor* temp_sensor = create_temp_sensor(250, -2.5f); // 25.0°C, -2.5偏移HumiditySensor* humidity_sensor = create_humidity_sensor(650, 800); // 65.0%, 閾值80%// 創建訪問者SensorVisitor* calibration = create_calibration_visitor();SensorVisitor* filter = create_filter_visitor();SensorVisitor* alarm = create_alarm_visitor();// 處理溫度傳感器數據printf("=== 溫度傳感器處理 ===\n");accept_visitor(temp_sensor, TEMP_SENSOR, calibration);accept_visitor(temp_sensor, TEMP_SENSOR, filter);accept_visitor(temp_sensor, TEMP_SENSOR, alarm);// 處理濕度傳感器數據printf("\n=== 濕度傳感器處理 ===\n");accept_visitor(humidity_sensor, HUMIDITY_SENSOR, calibration);accept_visitor(humidity_sensor, HUMIDITY_SENSOR, filter);accept_visitor(humidity_sensor, HUMIDITY_SENSOR, alarm);// 清理資源destroy_sensor(temp_sensor);destroy_sensor(humidity_sensor);destroy_visitor(calibration);destroy_visitor(filter);destroy_visitor(alarm);return 0;
}
5. 代碼分析
5.1 關鍵設計點
- 傳感器數據結構清晰
- 處理邏輯分離
- 易于擴展新的處理方法
- 資源管理完善
5.2 實現特點
- 適合嵌入式系統
- 代碼簡潔高效
- 內存占用小
- 處理流程清晰
6. 編譯和運行
gcc -c sensor_visitor.c -o sensor_visitor.o
gcc -c main.c -o main.o
gcc sensor_visitor.o main.o -o sensor_demo
7. 注意事項
- 內存使用要謹慎
- 避免過度設計
- 考慮實時性要求
- 錯誤處理要完善
8. 改進建議
- 添加數據存儲功能
- 實現數據平滑處理
- 添加更多傳感器類型
- 支持批量數據處理
9. 總結
這個例子展示了訪問者模式在嵌入式系統中的實際應用。通過將傳感器數據采集和處理邏輯分離,我們可以靈活地添加新的數據處理方法,同時保持代碼的清晰和可維護性。
參考資料
- 《嵌入式系統設計》
- 《C語言程序設計》
- 《傳感器技術手冊》