硬件基本完成
This commit is contained in:
+86
-23
@@ -5,6 +5,8 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h> // ← 添加atoi函数声明
|
||||
|
||||
extern uint8_t g_server_connected;
|
||||
|
||||
// 配置参数
|
||||
#define MAX_ATTENDANCE_RECORDS 100 // 最大记录数量
|
||||
#define MIN_CONFIDENCE_THRESHOLD 0.75 // 最小置信度阈值
|
||||
@@ -17,7 +19,9 @@ static uint8_t time_slot_count = 0; // 当前有效时间段数量
|
||||
|
||||
// 今日已签到学号缓存(从服务器下载)
|
||||
static char cached_student_ids[MAX_CACHED_IDS][20];
|
||||
static int8_t cached_time_slots[MAX_CACHED_IDS];
|
||||
static uint8_t cached_id_count = 0;
|
||||
static int8_t active_cache_slot = -1;
|
||||
|
||||
// 默认时间段配置(在服务器配置下载失败时使用)
|
||||
static const TimeSlot default_time_slots[] = {
|
||||
@@ -37,6 +41,28 @@ static AttendanceRecord attendance_records[MAX_ATTENDANCE_RECORDS];
|
||||
static uint16_t record_count = 0;
|
||||
static uint32_t total_attendance_count = 0; // 总考勤人次
|
||||
|
||||
static int8_t Attendance_FindTimeSlot(uint8_t hour, uint8_t minute)
|
||||
{
|
||||
uint16_t current_minutes = hour * 60 + minute;
|
||||
|
||||
for (uint8_t i = 0; i < time_slot_count; i++)
|
||||
{
|
||||
if (!time_slots[i].enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t start_minutes = time_slots[i].start_hour * 60 + time_slots[i].start_minute;
|
||||
uint16_t end_minutes = time_slots[i].end_hour * 60 + time_slots[i].end_minute;
|
||||
|
||||
if (current_minutes >= start_minutes && current_minutes <= end_minutes)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化考勤模块
|
||||
*/
|
||||
@@ -55,6 +81,8 @@ void Attendance_Init(void)
|
||||
// 清空缓存
|
||||
cached_id_count = 0;
|
||||
memset(cached_student_ids, 0, sizeof(cached_student_ids));
|
||||
memset(cached_time_slots, 0xFF, sizeof(cached_time_slots));
|
||||
active_cache_slot = -1;
|
||||
|
||||
DEBUG_INFO("[Attendance] Initialized with time slot mode");
|
||||
}
|
||||
@@ -66,6 +94,8 @@ void Attendance_ClearCache(void)
|
||||
{
|
||||
cached_id_count = 0;
|
||||
memset(cached_student_ids, 0, sizeof(cached_student_ids));
|
||||
memset(cached_time_slots, 0xFF, sizeof(cached_time_slots));
|
||||
active_cache_slot = Attendance_GetCurrentTimeSlot();
|
||||
DEBUG_INFO("[Attendance] Cache cleared");
|
||||
}
|
||||
|
||||
@@ -74,23 +104,37 @@ void Attendance_ClearCache(void)
|
||||
*/
|
||||
void Attendance_AddToCache(const char* student_id)
|
||||
{
|
||||
int8_t current_slot = Attendance_GetCurrentTimeSlot();
|
||||
|
||||
if (current_slot < 0) {
|
||||
DEBUG_INFO("[Attendance] Not in any slot, skip cache add");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cached_id_count >= MAX_CACHED_IDS) {
|
||||
DEBUG_ERROR("[Attendance] Cache full, cannot add more IDs");
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_cache_slot != current_slot) {
|
||||
Attendance_ClearCache();
|
||||
active_cache_slot = current_slot;
|
||||
}
|
||||
|
||||
// 检查是否已存在
|
||||
for (uint8_t i = 0; i < cached_id_count; i++) {
|
||||
if (strcmp(cached_student_ids[i], student_id) == 0) {
|
||||
if (cached_time_slots[i] == current_slot && strcmp(cached_student_ids[i], student_id) == 0) {
|
||||
return; // 已存在,不重复添加
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(cached_student_ids[cached_id_count], student_id, 19);
|
||||
cached_student_ids[cached_id_count][19] = '\0';
|
||||
cached_time_slots[cached_id_count] = current_slot;
|
||||
cached_id_count++;
|
||||
|
||||
DEBUG_PRINT("[Attendance] Added to cache: %s (total: %d)\r\n", student_id, cached_id_count);
|
||||
DEBUG_PRINT("[Attendance] Added to cache: %s slot=%d (total: %d)\r\n",
|
||||
student_id, current_slot, cached_id_count);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,9 +143,20 @@ void Attendance_AddToCache(const char* student_id)
|
||||
*/
|
||||
uint8_t Attendance_IsDuplicateInCache(const char* student_id)
|
||||
{
|
||||
int8_t current_slot = Attendance_GetCurrentTimeSlot();
|
||||
if (current_slot < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (active_cache_slot != current_slot) {
|
||||
Attendance_ClearCache();
|
||||
active_cache_slot = current_slot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < cached_id_count; i++) {
|
||||
if (strcmp(cached_student_ids[i], student_id) == 0) {
|
||||
DEBUG_PRINT("[Attendance] Found in cache: %s\r\n", student_id);
|
||||
if (cached_time_slots[i] == current_slot && strcmp(cached_student_ids[i], student_id) == 0) {
|
||||
DEBUG_PRINT("[Attendance] Found in cache: %s slot=%d\r\n", student_id, current_slot);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -117,6 +172,13 @@ uint8_t Attendance_LoadTodayRecordsFromServer(void)
|
||||
char slot_start[8];
|
||||
char slot_end[8];
|
||||
char records_buffer[512];
|
||||
int8_t current_slot = Attendance_GetCurrentTimeSlot();
|
||||
|
||||
if (current_slot < 0) {
|
||||
Attendance_ClearCache();
|
||||
DEBUG_INFO("[Attendance] Not in time slot, skip loading all-day cache");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取当前时段时间
|
||||
Attendance_GetCurrentSlotTime(slot_start, slot_end);
|
||||
@@ -125,6 +187,7 @@ uint8_t Attendance_LoadTodayRecordsFromServer(void)
|
||||
|
||||
// 清空旧缓存
|
||||
Attendance_ClearCache();
|
||||
active_cache_slot = current_slot;
|
||||
|
||||
// 从服务器下载
|
||||
uint8_t count = ESP8266_DownloadTodayRecords(slot_start, slot_end, records_buffer, sizeof(records_buffer));
|
||||
@@ -333,8 +396,17 @@ uint8_t Attendance_ParseTimeSlotsJSON(const char* json_str)
|
||||
*/
|
||||
void Attendance_SetCurrentTime(uint8_t hour, uint8_t minute)
|
||||
{
|
||||
int8_t old_slot = Attendance_FindTimeSlot(current_hour, current_minute);
|
||||
int8_t new_slot = Attendance_FindTimeSlot(hour, minute);
|
||||
|
||||
current_hour = hour;
|
||||
current_minute = minute;
|
||||
|
||||
if (old_slot != new_slot) {
|
||||
Attendance_ClearCache();
|
||||
active_cache_slot = new_slot;
|
||||
DEBUG_PRINT("[Attendance] Slot changed: %d -> %d, cache reset\r\n", old_slot, new_slot);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -343,24 +415,7 @@ void Attendance_SetCurrentTime(uint8_t hour, uint8_t minute)
|
||||
*/
|
||||
int8_t Attendance_GetCurrentTimeSlot(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < time_slot_count; i++)
|
||||
{
|
||||
// 跳过禁用的时间段
|
||||
if (!time_slots[i].enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t current_minutes = current_hour * 60 + current_minute;
|
||||
uint16_t start_minutes = time_slots[i].start_hour * 60 + time_slots[i].start_minute;
|
||||
uint16_t end_minutes = time_slots[i].end_hour * 60 + time_slots[i].end_minute;
|
||||
|
||||
if (current_minutes >= start_minutes && current_minutes <= end_minutes)
|
||||
{
|
||||
return i; // 返回时段编号
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // 不在任何考勤时段内
|
||||
return Attendance_FindTimeSlot(current_hour, current_minute);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,7 +533,15 @@ AttendanceStatus Attendance_ProcessFaceResult(FaceRecognitionResult* result)
|
||||
return ATTENDANCE_DUPLICATE;
|
||||
}
|
||||
|
||||
// 6. 添加新记录
|
||||
// 6. 服务器在线时补一次服务端查重,避免多设备或缓存过期造成重复签到
|
||||
if (g_server_connected && Attendance_IsDuplicateOnServer(result->student_id))
|
||||
{
|
||||
DEBUG_PRINT("[Attendance] Server duplicate in slot: %s\r\n", time_slots[current_slot].name);
|
||||
Attendance_AddToCache(result->student_id);
|
||||
return ATTENDANCE_DUPLICATE;
|
||||
}
|
||||
|
||||
// 7. 添加新记录
|
||||
if (record_count < MAX_ATTENDANCE_RECORDS)
|
||||
{
|
||||
// 复制学号和姓名
|
||||
|
||||
Reference in New Issue
Block a user