doubao_chat/apps/common/debug/debug_user.c

472 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "app_config.h"
#include "typedef.h"
#include "syscfg/syscfg_id.h"
//#define CONFIG_USER_DEBUG_ENABLE //开启user_printf
//#define CONFIG_SDCARD_DEBUG_ENABLE //开关SD卡记录打印信息
//#define CONFIG_NETWORK_DEBUG_ENABLE //可以触发打印信息上传到服务器端
//#define CONFIG_USB_DEBUG_ENABLE //开关USB虚拟串口打印信息
#if (defined CONFIG_DEBUG_ENABLE && defined CONFIG_NETWORK_DEBUG_ENABLE)
#include "os/os_api.h"
#include "spinlock.h"
#include "wifi/wifi_connect.h"
#include "device/device.h"
#include "http/http_cli.h"
#include "json_c/json_object.h"
extern unsigned int time_lapse(unsigned int *handle, unsigned int time_out);
extern int lwip_dhcp_bound(void);
extern struct json_object *json_tokener_parse(const char *str);
static u32 log_cnt, log_time_hdl;
static char log_part, uploading_log_flag;
static spinlock_t lock;
static char log_buf[100 * 1024];
static int tmp_cnt = 0;
static u8 mac[6];
static u8 keycode_legal = 0;
static u8 check_keycode_cnt = 0;
#define LOG_BRAND "jieli"
#define LOG_NAME "APP"
#define LOG_VERSION "1.0.0"
#define LOG_UUID "12345678"
#define LOG_KEYCODE "" //客户随机填写12-16个字符串,用于日志查询
static void upload_log_task(void *priv)
{
#define LOG_BOUNDARY "----385424468743051437018271"
#define LOG_HTTP_HEAD_OPTION_TWO \
"POST /status/v1/log/file HTTP/1.1\r\n"\
"cache-control: no-cache\r\n"\
"Host: log.jieliapp.com\r\n"\
"content-type: multipart/form-data; boundary="LOG_BOUNDARY"\r\n"\
"content-length: %lu\r\n"\
"Connection: close\r\n\r\n"
#define LOG_BODY_OPTION_THREE \
"--"LOG_BOUNDARY"\r\n" \
"Content-Disposition: form-data; name=\"file\"; filename=\"%s.txt\"\r\n" \
"Content-Type: text/plain\r\n\r\n"
#define LOG_BODY_OPTION_FOUR \
"\r\n--"LOG_BOUNDARY"\r\n"\
"Content-Disposition: form-data; name=\"filename\"\r\n\r\n"\
"%s.txt"\
"\r\n--"LOG_BOUNDARY"\r\n"\
"Content-Disposition: form-data; name=\"platform\"\r\n\r\n"\
"device"\
"\r\n--"LOG_BOUNDARY"\r\n"\
"Content-Disposition: form-data; name=\"brand\"\r\n\r\n"\
""LOG_BRAND""\
"\r\n--"LOG_BOUNDARY"\r\n"\
"Content-Disposition: form-data; name=\"name\"\r\n\r\n"\
""LOG_NAME""\
"\r\n--"LOG_BOUNDARY"\r\n"\
"Content-Disposition: form-data; name=\"version\"\r\n\r\n"\
""LOG_VERSION""\
"\r\n--"LOG_BOUNDARY"\r\n"\
"Content-Disposition: form-data; name=\"mac\"\r\n\r\n"\
"%s"\
"\r\n--"LOG_BOUNDARY"\r\n"\
"Content-Disposition: form-data; name=\"uuid\"\r\n\r\n"\
""LOG_UUID""\
"\r\n--"LOG_BOUNDARY"\r\n"\
"Content-Disposition: form-data; name=\"keycode\"\r\n\r\n"\
""LOG_KEYCODE""\
"\r\n--"LOG_BOUNDARY"--\r\n"
int ret = 0;
char http_body_begin[512] = {0};
char user_head_buf[512] = {0};
char http_body_end[1024] = {0};
char recv_buf[1024] = {0};
if (mac[0] == '\0') {
wifi_get_mac(mac);
}
char temp_buf1[20] = {0}, temp_buf2[20] = {0};
sprintf(temp_buf1, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
sprintf(temp_buf2, "%s-%d", temp_buf1, tmp_cnt++);
sprintf(http_body_begin, LOG_BODY_OPTION_THREE, temp_buf2);
sprintf(http_body_end, LOG_BODY_OPTION_FOUR, temp_buf2, temp_buf1);
httpcli_ctx ctx = {0};
//mode data的传输方式
int http_more_data_addr[3] = {0};
int http_more_data_len[3 + 1] = {0};
http_more_data_addr[0] = (int)(http_body_begin);
http_more_data_addr[1] = (int)log_buf;
http_more_data_addr[2] = (int)(http_body_end);
http_more_data_len[0] = strlen(http_body_begin);
http_more_data_len[1] = strlen(log_buf);
http_more_data_len[2] = strlen(http_body_end);
http_more_data_len[3] = 0;
ctx.more_data = http_more_data_addr;
ctx.more_data_len = http_more_data_len;
http_body_obj http_recv_body = {0};
http_recv_body.recv_len = 0;
http_recv_body.buf_len = 1024;
http_recv_body.buf_count = 1;
http_recv_body.p = recv_buf;
ctx.timeout_millsec = 5000;
ctx.priv = &http_recv_body;
ctx.url = "http://log.jieliapp.com/status/v1/log/file";
sprintf(user_head_buf, LOG_HTTP_HEAD_OPTION_TWO, strlen(http_body_begin) + strlen(log_buf) + strlen(http_body_end));
ctx.user_http_header = user_head_buf;
ret = httpcli_post(&ctx);
/* extern void efgh(int i); */
/* if (ret) { */
/* efgh(1); */
/* } else { */
/* efgh(0); */
/* } */
memset(log_buf, 0, sizeof(log_buf));
log_cnt = 0;
uploading_log_flag = 0;
}
static void check_keycode(void)
{
char url[128] = {0};
char recv_buf[1024] = {0};
http_body_obj http_recv_body = {0};
http_recv_body.recv_len = 0;
http_recv_body.buf_len = 1024;
http_recv_body.buf_count = 1;
http_recv_body.p = recv_buf;
httpcli_ctx ctx = {0};
sprintf(url, "http://log.jieliapp.com/status/v1/log/keycode/check?keycode=%s", LOG_KEYCODE);
ctx.timeout_millsec = 5000;
ctx.priv = &http_recv_body;
ctx.url = url;
ctx.connection = "close";
httpcli_post(&ctx);
json_object *root_node = NULL, *first_node = NULL, *second_node = NULL;
root_node = json_tokener_parse((unsigned char *)http_recv_body.p);
if (strcmp(json_object_get_string(json_object_object_get(root_node, "data")), "true") == 0) {
keycode_legal = 1;
}
json_object_put(root_node);
}
void upload_log_trig(void)
{
if (!lwip_dhcp_bound()) {
return;
}
while (keycode_legal == 0 && check_keycode_cnt < 5) {
check_keycode();
check_keycode_cnt++;
}
if (keycode_legal == 1) {
spin_lock(&lock);
if (!uploading_log_flag) {
uploading_log_flag = 1;
spin_unlock(&lock);
if (thread_fork("upload_log_task", 11, 2048, 0, 0, upload_log_task, NULL)) {
uploading_log_flag = 0;
}
return;
}
spin_unlock(&lock);
}
}
#endif
#if (defined CONFIG_DEBUG_ENABLE && defined CONFIG_SDCARD_DEBUG_ENABLE)
#include "system/includes.h"//cbuffer_t
#include "os/os_api.h"//创建线程,系统延时
#include "storage_device.h"//检查SD卡
#include "system/init.h"//early_initcall
#include "fs/fs.h"//操作写文件
/* 定义初始化循环BUF的大小 */
#define DATA_BUF_SIZE (20*1024)
/* CBUF数据多于DATA_BUF_SIZE/2就写入一次数据 */
#define WRITE_SIZE (DATA_BUF_SIZE/2)
static char lg_buf[DATA_BUF_SIZE]; //打印信息缓存buf
static u8 write_index; //记录写的乒乓buf的位置
static u8 write_busy; //SD卡写忙碌状态
static u8 write_flush;
static u32 write_flush_num;
static u32 write_flush_offset;
static u32 write_flush_fseek_offset;
static u8 write_flush_set_buf;
static OS_SEM sd_log_sem;
static void change_file_name(char *file_name, int len)
{
u32 log_num = 0; //文件序号变量
syscfg_read(VM_SD_LOG_INDEX, &log_num, sizeof(log_num)); //从VM读出
snprintf(file_name, len, CONFIG_ROOT_PATH"log%u.txt", log_num);
log_num++;
syscfg_write(VM_SD_LOG_INDEX, &log_num, sizeof(log_num)); //从VM写入
}
static int write_log_to_sd(const char *file_name, char *data, u32 len, u32 write_count, u8 index)
{
FILE *file = fopen(file_name, "w");
if (!file) {
file = fopen(file_name, "w+");
if (!file) {
return -1;
}
}
fseek(file, write_count * WRITE_SIZE + write_flush_fseek_offset, SEEK_SET);
if (write_flush == 1) {
write_flush_offset = write_flush_num;
if (index) {
write_flush_fseek_offset += write_flush_offset;
} else {
write_flush_fseek_offset += (write_flush_offset - WRITE_SIZE);
}
write_flush_set_buf = 1;
fwrite(index ? data : (data + WRITE_SIZE), index ? write_flush_offset : (write_flush_offset - WRITE_SIZE), 1, file);
} else {
fwrite(index ? data : (data + len), len, 1, file);
}
fclose(file);
return 0;
}
static void sd_log_task(void *priv)
{
u32 write_count = 0; //记录写的总次数
u8 last_write_time = 0xff;
u8 sd_state = 0;
char file_name[64];
write_flush = 0;
write_flush_offset = 0;
write_flush_fseek_offset = 0;
write_flush_set_buf = 0;
change_file_name(file_name, sizeof(file_name));
while (1) {
if (!storage_device_ready()) { //SD卡未就绪
if (sd_state) {
sd_state = 0;
/* write_busy = 0; //清空标记位 */
write_count = 0;
last_write_time = 0xff;
change_file_name(file_name, sizeof(file_name));
}
os_time_dly(20);
} else { //SD卡就绪
sd_state = 1;
if (last_write_time != write_index && write_busy) {
write_busy = 0; //标记已经写入数据
last_write_time = write_index; //记录上一包数据号
if (0 == write_log_to_sd(file_name, lg_buf, WRITE_SIZE, write_count, write_index)) {
if (write_flush == 1) {
write_flush = 0;
} else {
++write_count;
}
}
}
if (write_busy && last_write_time == write_index) { //需要写入数据并且数据包和上一包一样
printf("SD_WRITE_[ERROR],Packet maybe loss!!!!!");
}
os_sem_pend(&sd_log_sem, 0);
}
}
}
static int sd_log_task_create(void)
{
#define SD_LOG_STK_SIZE 512
static u8 sd_log_tcb_stk_q[sizeof(StaticTask_t) + SD_LOG_STK_SIZE * 4] ALIGNE(4);
os_sem_create(&sd_log_sem, 0);
os_task_create_static(sd_log_task, 0, 5, SD_LOG_STK_SIZE, 0, "sd_log_task", sd_log_tcb_stk_q);
return 0;
}
module_initcall(sd_log_task_create);
#endif
#if (defined CONFIG_DEBUG_ENABLE && defined CONFIG_USB_DEBUG_ENABLE)
#include "os/os_api.h"//创建线程,系统延时
#include "system/init.h"//early_initcall
extern u32 cdc_write_data(int usb_id, u8 *buf, u32 len);
#define DATA_BUF_SIZE (200 * 1024)
static u32 lg_cnt, last_cnt;
static char lg_buf[DATA_BUF_SIZE]; //打印信息缓存值
static void usb_log_task(void *priv)
{
os_time_dly(300);
while (1) {
if (lg_cnt > last_cnt && last_cnt != lg_cnt) {
if (lg_cnt / sizeof(lg_buf) > last_cnt / sizeof(lg_buf)) {
cdc_write_data(0, (u8 *)lg_buf + (last_cnt % sizeof(lg_buf)), sizeof(lg_buf) - last_cnt % sizeof(lg_buf));
cdc_write_data(1, (u8 *)lg_buf + (last_cnt % sizeof(lg_buf)), sizeof(lg_buf) - last_cnt % sizeof(lg_buf));
cdc_write_data(0, (u8 *)lg_buf, lg_cnt - last_cnt - (sizeof(lg_buf) - last_cnt % sizeof(lg_buf)));
cdc_write_data(1, (u8 *)lg_buf, lg_cnt - last_cnt - (sizeof(lg_buf) - last_cnt % sizeof(lg_buf)));
} else {
cdc_write_data(0, (u8 *)lg_buf + (last_cnt % sizeof(lg_buf)), lg_cnt - last_cnt);
cdc_write_data(1, (u8 *)lg_buf + (last_cnt % sizeof(lg_buf)), lg_cnt - last_cnt);
}
}
last_cnt = lg_cnt;
os_time_dly(10);
}
}
static int usb_log_task_create(void)
{
#define USB_LOG_STK_SIZE 256
static u8 usb_log_tcb_stk_q[sizeof(StaticTask_t) + USB_LOG_STK_SIZE * 4 + sizeof(StaticQueue_t)] ALIGNE(4);
return os_task_create_static(usb_log_task, 0, 1, USB_LOG_STK_SIZE, 0, "usb_log_task", usb_log_tcb_stk_q);
}
module_initcall(usb_log_task_create);
#endif
//////////////////////////////////////////
#if (defined CONFIG_NETWORK_DEBUG_ENABLE || defined CONFIG_SDCARD_DEBUG_ENABLE || defined CONFIG_USB_DEBUG_ENABLE)
void putbyte(char c)
{
#if defined CONFIG_NETWORK_DEBUG_ENABLE
log_buf[(log_cnt++) % (sizeof(log_buf))] = c;
#endif
#if defined CONFIG_SDCARD_DEBUG_ENABLE
static u32 lg_cnt = 0; //记录数据个数
static u8 first_write = 1;
u32 t;
if (write_flush_set_buf) {
if (write_index) {
lg_cnt = WRITE_SIZE;
} else {
lg_cnt = 0;
}
t = (lg_cnt++) % (sizeof(lg_buf));
first_write = 1;
write_flush_set_buf = 0;
} else {
t = (lg_cnt++) % (sizeof(lg_buf));
}
lg_buf[t] = c;
write_flush_num = t;
if (!first_write && !(t % WRITE_SIZE)) {//判断t为WRITE_SIZE的整数倍
write_busy = 1;//标记需要写入数据
write_index = t / WRITE_SIZE;//write_index只为0或1,为1时是第一包数据,为0时是第二包数据
if (os_sem_valid(&sd_log_sem)) {
os_sem_set(&sd_log_sem, 1);
os_sem_post(&sd_log_sem);
}
}
first_write = 0;
#endif
#if defined CONFIG_USB_DEBUG_ENABLE
if (c == '\r') {
return;
}
if (c == '\n') {
lg_buf[(lg_cnt++) % (sizeof(lg_buf))] = '\r';
}
lg_buf[(lg_cnt++) % (sizeof(lg_buf))] = c;
#endif
}
#if defined CONFIG_SDCARD_DEBUG_ENABLE
int sd_log_flush()
{
write_busy = 1;//标记需要写入数据
if (os_sem_valid(&sd_log_sem)) {
write_flush = 1;
if (write_index) {
write_index = 0;
} else {
write_index = 1;
}
os_sem_set(&sd_log_sem, 1);
os_sem_post(&sd_log_sem);
while (write_flush) {
os_time_dly(3);
printf("sd_log_flush wait write\n\r");
}
return 0;
}
return 1;
}
#endif
#endif
#if (!defined CONFIG_DEBUG_ENABLE && !defined CONFIG_USER_DEBUG_ENABLE)
//关闭user_printf用户打印
int user_putchar(int a)
{
return a;
}
int user_puts(const char *out)
{
return 0;
}
int user_printf(const char *format, ...)
{
return 0;
}
int user_vprintf(const char *restrict format, va_list arg)
{
return 0;
}
void user_put_buf(const u8 *buf, int len)
{
}
void user_put_u8hex(u8 dat)
{
}
void user_put_u16hex(u16 dat)
{
}
void user_put_u32hex(u32 dat)
{
}
#elif (defined CONFIG_USER_DEBUG_ENABLE)
int user_putchar(int a)//用户的user_printf 的底层发送函数
{
putbyte(a);//可以换用户的串口发送函数
return a;
}
#endif