/** * @file task_udp.c * @brief UDP通信任务处理模块 * @details 处理充电桩与服务器之间的UDP通信协议,包括UDP数据接收、数据解析和路由分发等功能。 * 支持JSON格式的数据交互,通过FreeRTOS任务和队列机制实现异步数据处理。 * 包含两个主要任务:UDP数据接收任务(udp_recv_task_function)和UDP数据解析任务(udp_parse_task_function)。 * @date 2025-01-09 14:32:15 * @version 1.0.0 * @copyright Copyright (c) 2026 */ #include "task_udp.h" /** * @brief udp_recv_task:UDP 数据接受任务 * * @note none * * @param taskID : 任务ID * * @retval runtime : 任务周期 */ void udp_recv_task_function(void const *argument) { err_t recv_err; struct netbuf *datalink_buf = NULL; datalink_conn = netconn_new(NETCONN_UDP); netconn_bind(datalink_conn, IP_ADDR_ANY, LINK_SERVER_PORT); UDP_Message_Queue_Init(); // 初始化UDP接收队列 /*桩UDP通讯初始化完成 发送云快充任务通知*/ xTaskNotifyGive(YkcTaskHandle); xTaskNotifyGive(Air724_ParseTaskHandle); xTaskNotifyGive(UDP_ParseTaskHandle); while (1) { /*获取任务运行状态*/ TaskRunTimeStat.UPLinkTask.threads_runtime = GetTask_RunTime(UPLinkTaskID); TaskRunTimeStat.UPLinkTask.threads_counter = GetTask_Beatcnt(UPLinkTaskID); TaskRunTimeStat.UPLinkTask.threads_freestack = Get_Free_Stack(UPLinkTaskID); recv_err = netconn_recv(datalink_conn, &datalink_buf); if (recv_err == ERR_OK && datalink_buf != NULL) { uint8_t *playload; uint16_t playload_len; netbuf_data(datalink_buf, (void *)&playload, &playload_len); if (playload_len > 0) { UdpMsg_t msg; ip_addr_copy(msg.src_ip, *netbuf_fromaddr(datalink_buf)); // 获取UDP源IP msg.src_port = netbuf_fromport(datalink_buf); // 获取UDP源端口 msg.len = playload_len; msg.data = (char *)pvPortMalloc(playload_len + 1); if (msg.data != NULL) { memcpy(msg.data, playload, playload_len); msg.data[playload_len] = '\0'; // 队列满,释放数据内存 if (xQueueSend(UDP_Message_Queue, &msg, 0) != pdPASS) { vPortFree(msg.data); } } } netbuf_delete(datalink_buf); // 释放UDP网络缓冲区 } else { if (recv_err != ERR_TIMEOUT && recv_err != ERR_WOULDBLOCK) { printf("datalink netconn_recv err: %d\r\n", recv_err); } } } } /** * @brief UDP_ParseTask_Function:UDP 数据解析任务 * * @note none * * @param taskID : 任务ID * * @retval runtime : 任务周期 */ void udp_parse_task_function(void const *argument) { UdpMsg_t msg; cJSON *root = NULL, *cmd = NULL, *id = NULL; ulTaskNotifyTake(pdTRUE, portMAX_DELAY); /* 等待桩通讯协议层完成*/ while (1) { if (xQueueReceive(UDP_Message_Queue, &msg, portMAX_DELAY) == pdPASS) { root = cJSON_Parse((const char *)msg.data); if (root == NULL) { printf("JSON Parse Failed: %s\r\n", msg.data); vPortFree(msg.data); continue; } id = cJSON_GetObjectItem(root, "id"); cmd = cJSON_GetObjectItem(root, "cmd"); if (cmd != NULL && id != NULL) { const char *cmd_str = cmd->valuestring; udp_route_dispatch((uint8_t)id->valueint, cmd->valuestring, root); //送入路由处理 cJSON_Delete(root); } else { printf("Missing 'code' field from \r\n"); cJSON_Delete(root); } vPortFree(msg.data); msg.data = NULL; } } }