#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <dirent.h>
#include <time.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/inotify.h>
#include <errno.h>
#include <sys/inotify.h>
#include <limits.h>
#include "LedManage.h"
#include "MD5.h"
#include "USBUnloadData.h"
#include "Errorlog.h"
// 全局标志位,默认未插入
volatile int usb_inserted = 0;
volatile int upgrade_done = 0;
#define USB_DIR_LEN 256
char USB_DIR[USB_DIR_LEN];
uint8_t IsConfig=0;
uint8_t log_day = 0; // 用于存储200Clog参数
uint32_t sam_DL_day, mid_DL_day, dtl_DL_day,btm_DL_day;
//16byte二进制数据转换为32bit十六进制字符串
void HexToStr(char *pbDest, unsigned char *pbSrc, int nLen)
{
char ddl, ddh;
int i;
for (i = 0; i < nLen; i++)
{
ddh = 48 + pbSrc[i] / 16; //48->0ascii
ddl = 48 + pbSrc[i] % 16;
if (ddh > 57) ddh = ddh + 7; //57->9ascii +7 ->A-F
if (ddl > 57) ddl = ddl + 7;
pbDest[i * 2] = ddh;
pbDest[i * 2 + 1] = ddl;
}
pbDest[nLen*2] = '\0';
}
//0成功 1失败 2 U盘容量不足
int USB_FileDLoad_Init(void) {
FILE *file;
char buf[256];
char second_line[256];
uint64_t freebyte, needbyte;
MD5_CTX md5;
unsigned char decrypt[16];
char md5str[32 + 1];
char filepath[100]; // 确保字符串足够长以容纳整个路径
snprintf(filepath, sizeof(filepath), "%s/DRU_200C_USBCONFIG.cfg",USB_DIR);
// 获取设备序列号字符串长度
char *deviceSerialNumString = get_usb_serial();
uint8_t tarstrlen = strlen(deviceSerialNumString);
printf("number serial:%s\n",deviceSerialNumString);
// 计算MD5
MD5Init(&md5);
MD5Update(&md5, deviceSerialNumString, tarstrlen);
MD5Final(&md5,decrypt);
HexToStr(md5str, decrypt, 16);
printf("md5str: %s\n", md5str);
// 打开配置文件
file = fopen(filepath, "r");
IsConfig=1;
if (!file) {
perror("Don't Find File");
IsConfig=0;
log_error_to_file(303);
return 1;
}
// 读取第一行并丢弃
if (fgets(buf, sizeof(buf), file) == NULL) {
printf("Failed to read the first line\n");
fclose(file);
return 1;
}
// 读取第二行
if (fgets(second_line, sizeof(second_line), file) == NULL) {
printf("Failed to read the second line\n");
fclose(file);
return 1;
}
// 去掉末尾的换行符
second_line[strcspn(second_line, "\r\n")] = '\0';
printf("Second line: %s\n", second_line);
// 校验第二行的MD5字符串
if (strncmp(second_line, md5str,32) != 0) {
printf("Serial failed\n");
fclose(file);
log_error_to_file(302);
IsConfig=0;
return 1;
}
// 读取文件内容并提取参数值
while (fgets(buf, sizeof(buf), file) != NULL) {
if (sscanf(buf, "SAM_DL_DAY:%u", &sam_DL_day) == 1) {
printf("SAM_DL_DAY: %u\n", sam_DL_day);
} else if (sscanf(buf, "MID_DL_DAY:%u", &mid_DL_day) == 1) {
printf("MID_DL_DAY: %u\n", mid_DL_day);
} else if (sscanf(buf, "DTL_DL_DAY:%u", &dtl_DL_day) == 1) {
printf("DTL_DL_DAY: %u\n", dtl_DL_day);
} else if (sscanf(buf, "BTM_DL_DAY:%u", &btm_DL_day) == 1) {
printf("BTM_DL_DAY: %u\n", btm_DL_day);
} else if (sscanf(buf, "200C_LOG_DAY:%hhu", &log_day ) == 1) {
printf("200C_LOG_DAY: %u\n", log_day );
}
}
// 获取U盘可用空间
printf("\nDevice path: %s\n", USB_DIR);
DiskCapacityInfo capacity = get_disk_capacity(USB_DIR);
freebyte = capacity.free_space;
printf("\nFree byte: %llu\n", freebyte);
// 计算所需空间
needbyte = ((dtl_DL_day+1) * DTL_MSG_SIZE) +((mid_DL_day+1) * MID_MSG_SIZE) +((sam_DL_day+1) * SAM_MSG_SIZE)+
((btm_DL_day+1)*BTM_MSG_SIZE)+((log_day+1) *LOG_200C_SIZE);
printf("\nNeed byte: %llu\n", needbyte);
if (needbyte >= freebyte) {
printf("\n not enough");
log_error_to_file(304);
IsConfig=0;
fclose(file);
return 2;
}
// 关闭文件
fclose(file);
return 0;
}
void copy_200C_log_to_usb(const char *emmc_dir, const char *usb_dir) {
char src_path[512], dst_path[512];
snprintf(src_path, sizeof(src_path), "%s/200Clog.txt", emmc_dir);
snprintf(dst_path, sizeof(dst_path), "%s/200Clog.txt", usb_dir);
printf("Copying %s to %s\n", src_path, dst_path);
copy_file(src_path, dst_path);
}
char* get_usb_serial() {
static char serial[256];
FILE *file = fopen(USB_DEVICE_PATH, "r");
if (file == NULL) {
perror("Failed to open serial file");
return NULL;
}
if (fgets(serial, sizeof(serial), file) != NULL) {
// Remove newline character if present
size_t len = strlen(serial);
if (len > 0 && serial[len-1] == '\n') {
serial[len-1] = '\0';
}
fclose(file);
return serial;
}
fclose(file);
return NULL;
}
DiskCapacityInfo get_disk_capacity(char *device_path) {
struct statvfs fs_info;
DiskCapacityInfo capacity_info = {0, 0}; // 初始化为0
if (statvfs(device_path, &fs_info) == 0) {
capacity_info.total_space = (uint64_t)fs_info.f_blocks * fs_info.f_bsize;
capacity_info.free_space = (uint64_t)fs_info.f_bfree * fs_info.f_bsize;
} else {
perror("Statvfs error");
}
return capacity_info;
}
// 得到USB_DIR
void find_usb_mount() {
FILE *file;
char line[256];
char device[256];
char mount_point[256];
const char *file_path = "/proc/mounts";
file = fopen(file_path, "r");
if (file == NULL) {
perror("Failed to open /proc/mounts");
return;
}
while (fgets(line, sizeof(line), file)) {
if (sscanf(line, "%s %s", device, mount_point) == 2) {
if (strstr(device, "/dev/sd") == device && strstr(mount_point, "/media") == mount_point) {
// Ensure the mount_point ends with a slash
size_t len = strlen(mount_point);
if (mount_point[len - 1] != '/') {
strncat(mount_point, "/", sizeof(mount_point) - len - 1);
}
snprintf(USB_DIR, USB_DIR_LEN, "%s", mount_point);
// printf("Device: %s is mounted on: %s\n", device, mount_point);
fclose(file);
return;
}
}
}
// If no USB device found, clear the USB_DIR
USB_DIR[0] = '\0';
fclose(file);
}
void get_date_string(char *buffer, size_t size, int offset_days) {
time_t rawtime;
struct tm *timeinfo;
// 获取当前时间
time(&rawtime);
// 根据 offset_days 调整时间
rawtime += offset_days * 24 * 60 * 60;
// 转换为本地时间
timeinfo = localtime(&rawtime);
// 格式化日期字符串
strftime(buffer, size, "%Y-%m-%d", timeinfo);
}
void copy_file(const char *src, const char *dst) {
FILE *src_file = fopen(src, "rb");
FILE *dst_file = fopen(dst, "wb");
char buffer[8192];
size_t bytes;
if (!src_file || !dst_file) {
perror("File open error");
return;
}
while ((bytes = fread(buffer, 1, sizeof(buffer), src_file)) > 0) {
fwrite(buffer, 1, bytes, dst_file);
}
fclose(src_file);
fclose(dst_file);
}
void process_files(const char *dir, const char *usb_dir, uint32_t days, const char *suffix) {
char date_str[11];
char src_path[512], dst_path[512];
struct dirent *entry;//用于存储目录信息
DIR *dp;
char *filename_start;
int i;
for (i = 0; i <= days; i++) {
get_date_string(date_str, sizeof(date_str), -i);//负数代表过去天数
printf("Processing date: %s\n", date_str);
dp = opendir(dir);
if (dp == NULL) {
perror("opendir error");
return;
}
while ((entry = readdir(dp)) != NULL) {
// 仅处理带有指定后缀的小写文件
if (strstr(entry->d_name, date_str) != NULL && strstr(entry->d_name, suffix) != NULL) {
snprintf(src_path, sizeof(src_path), "%s%s", dir, entry->d_name);
filename_start = strstr(entry->d_name, date_str); // 从文件名截取日期后的部分
if (filename_start) {
snprintf(dst_path, sizeof(dst_path), "%s%s", usb_dir, filename_start);
}
printf("Copying %s to %s\n", src_path, dst_path);
copy_file(src_path, dst_path);
}
}
closedir(dp);
}
}
void USB_Download(void){
// // 确认各个参数值在循环外部也正确
// printf("After file read, SAM_DL_DAY: %u\n", sam_DL_day);
// printf("After file read, MID_DL_DAY: %u\n", mid_DL_day);
// printf("After file read, DTL_DL_DAY: %u\n", dtl_DL_day);
// printf("After file read, BTM_DL_DAY: %u\n", btm_DL_day);
if (IsConfig) {
// 处理不同类型的数据
process_files(SAM_DIR, USB_DIR, sam_DL_day, "_sam");
process_files(MID_DIR, USB_DIR, mid_DL_day, "_mid");
process_files(DTL_DIR, USB_DIR, dtl_DL_day, "_dtl");
process_files(BTM_DIR, USB_DIR, btm_DL_day, "_btm");
process_files(LOG_DIR, USB_DIR, log_day , "_200Clog");
}
return ;
}
// 检测 U 盘是否插入的函数
int detect_usb_insertion() {
struct stat sb;
// 检查 /media/sda1 目录是否存在
if (stat(USB_DIR, &sb) == 0 && S_ISDIR(sb.st_mode)) {
return 1;
}
return 0;
}
// U盘检测线程函数
void* usb_monitor_thread(void* arg) {
while (1) {
find_usb_mount();
if (detect_usb_insertion()) {
if (usb_inserted == 0 && upgrade_done == 0) {
usb_inserted = 1;
log_error_to_file(301);
printf("U盘插入,开始升级...\n");
int ret = system("/opt/update.sh");
if (WIFEXITED(ret) && WEXITSTATUS(ret) == 1) {
printf("升级成功,开始转储...\n");
log_error_to_file(305);
USB_FileDLoad_Init();
USB_Download();
printf("转储完成,等待U盘移除...\n");
} else {
printf("升级失败,返回值: %d\n", WEXITSTATUS(ret));
log_error_to_file(306);
}
// 设置升级完成标志
upgrade_done = 1;
}
} else {
if (usb_inserted == 1) {
usb_inserted = 0;
upgrade_done = 0;
printf("U盘已移除。\n");
log_error_to_file(309);
}
}
sleep(5); // 每5秒检测一次
}
return NULL;
}
int main() {
pthread_t thread_id;
LED1_Init();//LED初始化
// 创建U盘检测线程
if (pthread_create(&thread_id, NULL, usb_monitor_thread, NULL) != 0) {
perror("Failed to create thread");
return 1;
}
// 主函数继续执行其他工作
while (1) {
// 主函数的其他工作
LedOnOff(J1_LED,LED_ON_YELLOW,0);
LedOnOff(MMC_LED,LED_ON_GREEN,0);
log_run_status(3000);
}
return 0;
}
#ifndef APP_SOURCE_USBUNLOADDATA_H_
#define APP_SOURCE_USBUNLOADDATA_H_
#define SAM_DIR "/Data/SAM/"
#define MID_DIR "/Data/MID/"
#define DTL_DIR "/Data/DTL/"
#define BTM_DIR "/Data/BTM/"
typedef uint8_t UINT;
#define MID_MSG_SIZE (49.913*1024)
#define SAM_MSG_SIZE (60.81*1024)
#define DTL_MSG_SIZE (150*1024)
#define BTM_MSG_SIZE (150*1024)
#define LOG_200C_SIZE (1024*1024)
#define USB_DEVICE_PATH "/sys/bus/usb/devices/1-1/serial"
#define LOG_DIR "/media/mmc/"
typedef struct {
uint64_t total_space;
uint64_t free_space;
} DiskCapacityInfo;
void copy_file(const char *src, const char *dst);
DiskCapacityInfo get_disk_capacity(char *device_path);
char* get_usb_serial(void);
int32_t USB_FileDLoad_Init(void);
#endif /* APP_SOURCE_USBUNLOADDATA_H_ */
先放这,过两天空了来分析一下。