add:增加上位机交互框架、Flash R/W 框架

This commit is contained in:
2026-05-08 18:17:26 +08:00
parent f858a672a4
commit 8a5a32b139
21 changed files with 1131 additions and 381 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -67,8 +67,8 @@
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES ( 7 )
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
#define configTOTAL_HEAP_SIZE ((size_t)40960)
#define configMINIMAL_STACK_SIZE ((uint16_t)512)
#define configTOTAL_HEAP_SIZE ((size_t)81920)
#define configMAX_TASK_NAME_LEN ( 16 )
#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_TRACE_FACILITY 1

View File

@@ -94,7 +94,7 @@
/*----- Value in opt.h for DEFAULT_THREAD_PRIO: 1 -----*/
#define DEFAULT_THREAD_PRIO 3
/*----- Value in opt.h for DEFAULT_UDP_RECVMBOX_SIZE: 0 -----*/
#define DEFAULT_UDP_RECVMBOX_SIZE 20
#define DEFAULT_UDP_RECVMBOX_SIZE 40
/*----- Value in opt.h for DEFAULT_TCP_RECVMBOX_SIZE: 0 -----*/
#define DEFAULT_TCP_RECVMBOX_SIZE 20
/*----- Value in opt.h for DEFAULT_ACCEPTMBOX_SIZE: 0 -----*/
@@ -107,7 +107,7 @@
#define LWIP_CHECKSUM_CTRL_PER_NETIF 1
/*-----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
#define MEMP_NUM_NETBUF 48
#define MEMP_NUM_NETBUF 80
/* USER CODE END 1 */

View File

@@ -90,6 +90,8 @@ virtualFolder:
- name: Driver
files:
- path: ../User/Driver/drv_init.c
- path: ../User/Driver/drv_flash.c
- path: ../User/Driver/flash_config.c
folders: []
- name: Task
files:

View File

@@ -1,54 +1,44 @@
#if 1
#include "global.h"
#include "charger_to_server.h"
/************参数修改****************/
#define GUN_NUM 2 // 枪数量
#define TELE_FACTORY 0 // 0x00,移动,02:电信,03:联通,04:其他
const uint8_t SERVER_PROTOCOL_VER = 0x10; // 协议版本BCD 0x16 => V1.6
const char iccid_ascii[10] = {0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a}; // SIM卡号BCD
uint16_t pack_serial = 0;
// 充电桩登录认证
void charger_to_server_0X01(uint8_t stake_index)
{
PACK_DATA_0X01 data = {0};
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
data.charger_type = CHARGER_TYPE_DC;
data.gun_num = GUN_NUM;
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
data.charger_type = g_charger_manager.charger_piles[stake_index - 1].login_info.charger_type;
data.gun_num = g_charger_manager.charger_piles[stake_index - 1].login_info.gun_num;
data.protocol_ver = g_charger_manager.charger_piles[stake_index - 1].login_info.protocol_ver;
memcpy(data.software_ver, SOFTWARE_VERSION, strlen(SOFTWARE_VERSION));
data.net_conn_type = NET_CONN_TYPE;
data.tele_factory = TELE_FACTORY;
memcpy(data.sim, iccid_ascii, strlen(iccid_ascii));
printf("北向:对电桩 %d 发送登录认证,序列号:%s\r\n", stake_index,data.charger_serial);
pack_and_send_server_data(FRAME_TYPE_0X01, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X01),stake_index);
memcpy(data.software_ver, g_charger_manager.charger_piles[stake_index - 1].login_info.software_ver, 8);
data.net_conn_type = g_charger_manager.charger_piles[stake_index - 1].login_info.net_conn_type;
data.tele_factory = g_charger_manager.charger_piles[stake_index - 1].login_info.tele_factory;
memcpy(data.sim, g_charger_manager.charger_piles[stake_index - 1].login_info.sim, 10);
printf("北向:对电桩 %d 发送登录认证,序列号:%s\r\n", stake_index, data.charger_serial);
pack_and_send_server_data(FRAME_TYPE_0X01, (uint8_t *)&data, sizeof(PACK_DATA_0X01), stake_index);
}
void charger_to_server_0X03(uint8_t stake_index,uint8_t gun_index, uint8_t gun_status)
void charger_to_server_0X03(uint8_t stake_index, uint8_t gun_index, uint8_t gun_status)
{
PACK_DATA_0X03 data = {0};
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
data.gun_index = gun_index;
data.gun_status = gun_status;
printf("北向:对电桩 %d 发送心跳请求,枪号:%d状态%d\r\n", stake_index,gun_index,gun_status);
pack_and_send_server_data(FRAME_TYPE_0X03, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X03),stake_index);
printf("北向:对电桩 %d 发送心跳请求,枪号:%d状态%d\r\n", stake_index, gun_index, gun_status);
pack_and_send_server_data(FRAME_TYPE_0X03, (uint8_t *)&data, sizeof(PACK_DATA_0X03), stake_index);
}
// 计费模型验证请求
void charger_to_server_0X05(uint16_t num,uint8_t stake_index)
// 计费模型验证请求
void charger_to_server_0X05(uint16_t num, uint8_t stake_index)
{
PACK_DATA_0X05 data = {0};
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
data.fee_model_no = num;
printf("北向:对电桩 %d 计费模型验证请求,模型号:%d\r\n", stake_index,num);
pack_and_send_server_data(FRAME_TYPE_0X05, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X05),stake_index);
printf("北向:对电桩 %d 计费模型验证请求,模型号:%d\r\n", stake_index, num);
pack_and_send_server_data(FRAME_TYPE_0X05, (uint8_t *)&data, sizeof(PACK_DATA_0X05), stake_index);
}
// 充电桩计费模型请求
@@ -56,60 +46,103 @@ void charger_to_server_0X09(uint8_t stake_index)
{
PACK_DATA_0X09 data = {0};
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
printf("北向:对电桩 %d 计费模型请求,序列号:%s\r\n", stake_index,data.charger_serial);
pack_and_send_server_data(FRAME_TYPE_0X09, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X09),stake_index);
load_charger_serial(stake_index, data.charger_serial); // 加载充电桩序列号
printf("北向:对电桩 %d 计费模型请求,序列号:%s\r\n", stake_index, data.charger_serial);
pack_and_send_server_data(FRAME_TYPE_0X09, (uint8_t *)&data, sizeof(PACK_DATA_0X09), stake_index);
}
// 上传实时监测数据
void charger_to_server_0X13(uint8_t stake_index,uint8_t gun_index)
void charger_to_server_0X13(uint8_t stake_index, uint8_t gun_index)
{
const unsigned char trade_data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
};
PACK_DATA_0X13 data = {0};
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
ChargerGun *gun = &g_charger_manager.charger_piles[stake_index - 1].guns[gun_index - 1]; // 获取枪指针
data = gun->real_time_data;// 复制结构体
// 覆盖需要重新加载的字段
load_charger_serial(stake_index, data.charger_serial);
load_trade_serial(stake_index, gun_index, data.trade_serial);
data.gun_index = gun_index;
//data.gun_back = getGunBack(All_status[gun_index-1]);
// data.gun_is_insert = getGunIsInsert(All_status[gun_index-1]);
data.gun_back = g_charger_manager.charger_piles[stake_index - 1].guns[gun_index - 1].real_time_data.gun_back;
data.gun_is_insert = 1;
//Serial.printf("data.gun_is_insert====%d\n",data.gun_is_insert);
data.status =2;
if(data.status ==0x01 || data.status==0X02 )
{
memcpy(data.trade_serial, trade_data,16);
data.out_voltage = 0;
data.charge_energy = 0;
data.out_current = 0;
// 根据状态清零特定字段
if (data.status == 0x01 || data.status == 0x02||data.status == 0x00)
{
memset(data.trade_serial, 0, sizeof(data.trade_serial));
data.out_voltage = 0;
data.out_current = 0;
data.charge_energy = 0;
data.charge_time = 0;
data.charge_money = 0;
data.hard_fault = 0;
}
printf("北向:对电桩 %d 上传实时监测数据,枪号:%d状态%d返回%d是否插入%d\r\n", stake_index,gun_index,data.status,data.gun_back,data.gun_is_insert);
pack_and_send_server_data(FRAME_TYPE_0X13, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X13),stake_index);
pack_and_send_server_data(FRAME_TYPE_0X13, (uint8_t *)&data, sizeof(PACK_DATA_0X13), stake_index);
}
// 充电结束上报
void charger_to_server_0X19(uint8_t stake_index, uint8_t gun_index)
{
PACK_DATA_0X19 data = {0};
load_charger_serial(stake_index, data.charger_serial);
load_trade_serial(stake_index, gun_index, data.trade_serial);
pack_and_send_server_data(FRAME_TYPE_0X19, (uint8_t *)&data, sizeof(PACK_DATA_0X19), stake_index);
}
//平台启动回复
void charger_to_server_0X33(uint8_t stake_mark,uint8_t gun_index,uint8_t result,uint8_t err_code)
// 平台启动回复
void charger_to_server_0X33(uint8_t stake_index, uint8_t gun_index, uint8_t result, uint8_t err_code)
{
PACK_DATA_0X33 data = {0};
load_charger_serial(stake_mark,data.charger_serial);
load_trade_serial(stake_mark,gun_index,data.trade_serial);
load_charger_serial(stake_index, data.charger_serial);
load_trade_serial(stake_index, gun_index, data.trade_serial);
data.gun_index = gun_index;
data.result = result;
data.err_code = err_code;
printf("北向:对电桩 %d 的平台启动回复,结果:%d错误码%d\r\n", stake_mark,result,err_code);
pack_and_send_server_data(FRAME_TYPE_0X33, stake_mark, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X33), stake_mark);
uint8_t *trade_serial = g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.trade_serial;
printf("回复订单ID: ");
for (int i = 0; i < 16; i++)
{
printf("%02X", trade_serial[i]);
}
printf("\r\n");
printf("北向:对电桩 %d 的平台启动回复,结果:%d错误码%d\r\n", stake_index, result, err_code);
pack_and_send_server_data(FRAME_TYPE_0X33, (uint8_t *)&data, sizeof(PACK_DATA_0X33), stake_index);
}
// 平台停机回复
void charger_to_server_0X35(uint8_t stake_index, uint8_t gun_index, uint8_t result, uint8_t err_code)
{
PACK_DATA_0X35 data = {0};
load_charger_serial(stake_index, data.charger_serial);
data.gun_index = gun_index;
data.result = result;
data.err_code = err_code;
printf("北向:对电桩 %d 的平台停机回复,结果:%d错误码%d\r\n", stake_index, result, err_code);
pack_and_send_server_data(FRAME_TYPE_0X35, (uint8_t *)&data, sizeof(PACK_DATA_0X35), stake_index);
}
#endif
// 上传交易记录
void charger_to_server_0X3B(uint8_t stake_index, uint8_t gun_index)
{
PACK_DATA_0X3B data = {0};
load_charger_serial(stake_index, data.charger_serial);
load_trade_serial(stake_index, gun_index, data.trade_serial);
data.gun_index = gun_index;
pack_and_send_server_data(FRAME_TYPE_0X3B, (uint8_t *)&data, sizeof(PACK_DATA_0X3B), stake_index);
}
// 计费模型主动更新回复
void charger_to_server_0x57(uint8_t stake_index)
{
PACK_DATA_0X57 data = {0};
load_charger_serial(stake_index, data.charger_serial);
data.result = 0x01;
printf("北向:对电桩 %d 的计费模型主动更新回复\r\n", stake_index);
pack_and_send_server_data(FRAME_TYPE_0X57, (uint8_t *)&data, sizeof(PACK_DATA_0X57), stake_index);
}

View File

@@ -5,6 +5,7 @@
#include "server_common.h"
extern uint16_t pack_serial;
uint32_t get_current_rtc_sec();
//充电桩登录认证请求
@@ -23,13 +24,11 @@ extern void charger_to_server_0X09(uint8_t stake_index);
extern void charger_to_server_0X13(uint8_t stake_index,uint8_t gun_index);
// 充电结束
extern void charger_to_server_0X19(uint8_t gun_index);
extern void charger_to_server_0X19(uint8_t stake_index,uint8_t gun_index);
// 报文被改为A5A8
extern void charger_to_server_0X31(uint8_t gun_index,uint32_t card_id); //0x31-0x34改为0xA5-0xA8
extern void charger_to_server_0X33(uint8_t stake_index,uint8_t gun_index,uint8_t result,uint8_t err_code); //0x310x33
extern void charger_to_server_0X35(uint8_t gun_index,uint8_t err_code,uint8_t result);
extern void charger_to_server_0X33(uint8_t stake_index,uint8_t gun_index,uint8_t result,uint8_t err_code);
extern void charger_to_server_0X35(uint8_t stake_index, uint8_t gun_index, uint8_t result, uint8_t err_code);
extern void charger_to_server_0x3B(uint8_t gun_index,uint32_t card_id,uint8_t trade_flag,uint8_t stop_reason); //3B改为3D
@@ -41,7 +40,7 @@ extern void charger_to_server_0X55(uint32_t time);
//计费模型应答
extern void charger_to_server_0X57(uint8_t result);
extern void charger_to_server_0X57(uint8_t stake_index);
extern uint8_t get_real_status_for_server(uint8_t idx);
//远程启机命令回复

View File

@@ -1,6 +1,7 @@
#if 1
#include "global.h"
#include "server_common.h"
#include "time.h"
#include <string.h>
@@ -210,7 +211,7 @@ uint8_t unpack_server_data(uint8_t *buf, uint8_t len, SERVER_PACK *pack)
return ret;
}
void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, uint8_t *pdata, uint8_t len, uint8_t stake_mark)
void pack_and_send_server_data(uint8_t type, uint8_t *pdata, uint8_t len, uint8_t stake_mark)
{
uint8_t index = 0;
uint16_t crc = 0;
@@ -223,10 +224,10 @@ void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, u
}
/* 原子获取全局包序号,避免多任务竞争 */
taskENTER_CRITICAL();
// taskENTER_CRITICAL();
current_serial = pack_serial;
pack_serial++;
taskEXIT_CRITICAL();
// taskEXIT_CRITICAL();
buf[index++] = 0x55;
buf[index++] = 0xAA;
@@ -238,7 +239,7 @@ void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, u
buf[index++] = (current_serial >> 8) & 0xFF;
buf[index++] = current_serial & 0xFF;
buf[index++] = encrypt;
buf[index++] = 0x00;
buf[index++] = type;
if ((len > 0) && (pdata))
{
@@ -250,11 +251,6 @@ void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, u
buf[index++] = (crc >> 8) & 0xFF;
buf[index++] = 0xAA;
buf[index++] = 0x55;
// for (int i = 4; i < index - 2; i++)
// {
// printf("%02X", buf[i]);
// }
Air724_Message_Send(buf, index);
vPortFree(buf);
}
@@ -285,13 +281,16 @@ int get_num_from_string(const char *str, int *num)
void get_cp56time_from_sec(uint8_t *buff, uint32_t sec)
{
st_cp56time2a cp56time;
cp56time.Compts.year = 25;
cp56time.Compts.month = 9;
cp56time.Compts.mday = 23;
cp56time.Compts.hour = 15;
cp56time.Compts.min = 56;
cp56time.Compts.msec = 47 * 1000;
struct tm timeinfo;
st_cp56time2a cp56time = {0};
time_t rawtime = sec;
localtime_r(&rawtime, &timeinfo);
cp56time.Compts.year = timeinfo.tm_year % 100; // 获取年份的最后两位数
cp56time.Compts.month = timeinfo.tm_mon + 1; // tm_mon是从0开始的所以需要加1
cp56time.Compts.mday = timeinfo.tm_mday;
cp56time.Compts.hour = timeinfo.tm_hour;
cp56time.Compts.min = timeinfo.tm_min;
cp56time.Compts.msec = timeinfo.tm_sec * 1000;
buff[0] = cp56time.time & 0xFF;
buff[1] = (cp56time.time >> 8) & 0xFF;
buff[2] = (cp56time.time >> 16) & 0xFF;

View File

@@ -47,7 +47,7 @@
#define FRAME_TYPE_0X36 0x36 // 运营平台远程停机
//---------------------------------------
#define FRAME_TYPE_0X3D 0x3D // 交易记录
#define FRAME_TYPE_0X3B 0x3B // 交易记录
#define FRAME_TYPE_0X40 0x40 // 交易记录确认
#define FRAME_TYPE_0X41 0x41 // 交易更新应答
#define FRAME_TYPE_0X42 0x42 // 远程账户余额更新
@@ -291,7 +291,7 @@ typedef struct
{
uint8_t charger_serial[CHARGER_SERIAL_LENGTH]; // 桩编号
uint8_t gun_index; // 枪编号
uint8_t reseut; // 停止结果,0x00失败 0x01成功
uint8_t result; // 停止结果,0x00失败 0x01成功
uint8_t err_code; // 失败原因,0x0无
} __attribute__((packed)) PACK_DATA_0X35; // 0x35
@@ -343,7 +343,7 @@ typedef struct
uint8_t trade_data[7]; // 交易日期
uint8_t stop_reason; // 停止原因
uint8_t phy_cardid[8]; // 物理卡号
} __attribute__((packed)) PACK_DATA_0X3D; // 0x3D
} __attribute__((packed)) PACK_DATA_0X3B; // 0x3B
typedef struct
{
@@ -460,7 +460,7 @@ extern void increase_heart_beat_cnt(void);
extern void reset_heart_beat_cnt(void);
extern uint32_t get_heart_beat_cnt(void);
extern uint8_t unpack_server_data(uint8_t *buf, uint8_t len, SERVER_PACK *pack);
extern void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, uint8_t *data, uint8_t len, uint8_t stake_mark);
extern void pack_and_send_server_data(uint8_t type, uint8_t *data, uint8_t len, uint8_t stake_mark);
extern int get_num_from_string(const char *str, int *num);
extern uint32_t get_card_logic_num(uint8_t idx);
extern uint32_t get_card_phy_num(uint8_t idx);

View File

@@ -53,7 +53,7 @@ void on_cmd_frame_type_0X0A(uint8_t stake_index, SERVER_PACK *pack)
g_charger_manager.charger_piles[stake_index - 1].get_model = true;
#ifdef DEBUG
printf("北向:接收到计费模型应答,模型ID:%d\r\n", g_charger_manager.fee_model_global.fee_model_no);
printf("尖电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.shark_fee_ratio, g_charger_manager.fee_model_global.shark_service_ratio);
printf("峰电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.peak_fee_ratio, g_charger_manager.fee_model_global.peak_service_ratio);
@@ -116,7 +116,6 @@ void on_cmd_frame_type_0X0A(uint8_t stake_index, SERVER_PACK *pack)
end_hour, end_min,
fee_name);
i = j; // 跳到下一个不同费率段
}
printf("================================================================\r\n");
@@ -200,57 +199,73 @@ void on_cmd_frame_type_0X58(uint8_t stake_index, SERVER_PACK *pack)
i = j; // 跳到下一个不同费率段
}
printf("================================================================\r\n");
charger_to_server_0x57(stake_index);
#endif
}
}
// 平台控制充电
// 平台控制充电
void on_cmd_frame_type_0X34(uint8_t stake_index, SERVER_PACK *pack)
{
PACK_DATA_0X34 data;
uint8_t result = 1;
uint8_t err_code = 0;
uint8_t result = TRUE; // 默认启动结果成功
uint8_t err_code = 0; // 默认错误码为0
memcpy(&data, pack->data, sizeof(PACK_DATA_0X34));
set_trade_serial(stake_index,data.gun_index, data.trade_serial);
set_trade_serial(stake_index, data.gun_index, data.trade_serial);
printf("北向:平台控制充电,桩ID:%d, 枪ID:%d, 金额:%d\r\n", stake_index, data.gun_index, data.remain_money);
uint8_t *trade_serial = data.trade_serial;
memcpy(g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.trade_serial, data.trade_serial, 16);
if (!is_my_charger_serial(stake_index, data.charger_serial))
{
result = 0;
err_code = 0x1; // 桩编号不匹配
}
// else if (get_user_current_action(data.gun_index - 1))
// {
// result = 0;
// err_code = 0x2; // 枪在使用
// }
// else if (is_gun_fault_occur(data.gun_index - 1))
// {
// result = 0;
// err_code = 0x3; // 设备故障
// }
// else if (get_gun_status(data.gun_index - 1) == GUN_STATUS_UN_INSERT)
// {
// result = 0;
// err_code = 0x5; // 未插枪
// }
// else
// {
// Serial.print("In %s\r\n", __func__);
// uint32_t id = *(uint32_t *)&data.trade_serial[12];
// pack_cmd_to_charge_task(data.gun_index - 1, CHARGE_TASK_CMD_USER_START_CHARGE, id);
// set_charge_start_mode(data.gun_index - 1, CAHRGE_START_MODE_APP);
// update_remain_money_to_gun(data.gun_index - 1, data.remain_money);
// }
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.status == 3)
{
result = 0;
err_code = 0x2; // 枪在使用
}
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.status == 1)
{
result = 0;
err_code = 0x3; // 故障
}
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.status == 0)
{
result = 0;
err_code = 0x4; // 枪离线
}
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.gun_is_insert == FALSE)
{
result = 0;
err_code = 0x5; // 未插枪
}
charger_to_server_0X33(stake_index, data.gun_index, result, err_code);
}
#if 0
// 平台控制停止充电
void on_cmd_frame_type_0X36(uint8_t stake_index, SERVER_PACK *pack)
{
PACK_DATA_0X36 data;
uint8_t result = TRUE; // 默认启动结果成功
uint8_t err_code = 0; // 默认错误码为0
memcpy(&data, pack->data, sizeof(PACK_DATA_0X36));
printf("北向:平台控制停止充电,桩ID:%d, 枪ID:%d\r\n", stake_index, data.gun_index);
//计费模型应答
#endif
if (!is_my_charger_serial(stake_index, data.charger_serial))
{
result = 0;
err_code = 0x1; // 桩编号不匹配
}
else if (g_charger_manager.charger_piles[stake_index - 1].guns[data.gun_index - 1].real_time_data.status != 3)
{
result = 0;
err_code = 0x2; // 枪未在使用
}
charger_to_server_0X33(stake_index, data.gun_index, result, err_code);
}

View File

@@ -1,2 +1,3 @@
### 生产代码设置
- /User/Global/g_decpile -> void init_chargers(void) 需要修改预设 ,从电桩全局结构体拿
![alt text](9e12a2e4a7f3dc87fa034aecf79e893c.png)

View File

@@ -0,0 +1,166 @@
#include "drv_flash.h"
/* flash数据帧格式 */
/* 帧头, 同时表示当前帧状态 */
/* 整帧大小, 5~65536 */
/* 帧类型, 用于区分不同存储数据, 0~255*/
/* 帧数据 */
/* 帧尾, 同时表示当前帧状态 */
/* 可读帧表,存放不同帧类型的第一个可读帧的地址与大小 */
type_readable_frame_t data_form[255] = {0};
/* 首个可写地址 */
uint32_t writeable_addr = 0;
uint8_t erase_flag = 0;
/* 地址对齐向高地址取整 */
#define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
uint32_t i = 0;
int8_t flash_manage_init(flash_manage_t *flash_manage)
{
uint8_t buff[4] = {0}; /* 存放帧头,帧大小,帧类型 */
if (flash_manage->manage_sector_num == 0 || flash_manage->sector_size == 0 || flash_manage->read_flash == 0 ||
flash_manage->write_flash == 0 || flash_manage->erase_sector == 0) {
return -1;
}
/* 遍历管理的空间以更新地址 */
for (; i < flash_manage->manage_sector_num * flash_manage->sector_size; ) {
/* 取出帧信息 */
flash_manage->read_flash(buff, ALIGN_UP(flash_manage->flash_start_address + i, flash_manage->align_num), 4);
/* 只获取该类帧类型的首个可读帧地址 */
if (buff[0] == FLASH_READABLE_HEAD) {
if (data_form[buff[3]].state == 0) {
uint8_t frame_tail = 0;
flash_manage->read_flash(&frame_tail, ALIGN_UP(flash_manage->flash_start_address + i, flash_manage->align_num) + (buff[2] << 8 | buff[1]) - 1, 1);
if (frame_tail == FLASH_READABLE_TAIL) {
/* 只有帧头帧尾均为可读, 才把对齐后的地址填入 */
data_form[buff[3]].addr = ALIGN_UP(flash_manage->flash_start_address + i, flash_manage->align_num);
/* 帧大小按小端排列 */
data_form[buff[3]].size = buff[2] << 8 | buff[1];
data_form[buff[3]].state = 1;
}
}
i = i + ALIGN_UP(buff[2] << 8 | buff[1], flash_manage->align_num);
} else if ((buff[0] & buff[1] & buff[2] & buff[3]) == FLASH_WRITABLE) {
/* 遍历提前结束 */
writeable_addr = ALIGN_UP(flash_manage->flash_start_address + i, flash_manage->align_num);
return 1;
} else {
i += flash_manage->align_num;
}
}
erase_flag = 1;
return 1;
}
void update_readable_frame(flash_manage_t *flash_manage, uint32_t addr, uint8_t frame_type)
{
uint8_t buff[4] = {0}; /* 存放帧头,帧大小,帧类型 */
/* 从当前位置遍历剩余空间 */
for (uint32_t i = 0; i < flash_manage->manage_sector_num * flash_manage->sector_size - (addr - flash_manage->flash_start_address);) {
/* 取出帧信息 */
flash_manage->read_flash(buff, ALIGN_UP(addr + i, flash_manage->align_num), 4);
/* 寻找相同类型的帧数据 */
if (buff[0] == FLASH_READABLE_HEAD) {
if (buff[3] == frame_type) {
uint8_t frame_tail = 0;
flash_manage->read_flash(&frame_tail, ALIGN_UP(addr + i, flash_manage->align_num) + (buff[2] << 8 | buff[1]) - 1, 1);
if (frame_tail == FLASH_READABLE_TAIL) {
/* 只有帧头帧尾均为可读, 才把地址填入 */
data_form[buff[3]].addr = ALIGN_UP(addr + i, flash_manage->align_num);
data_form[buff[3]].size = buff[2] << 8 | buff[1];
data_form[buff[3]].state = 1;
return;
}
}
i += ALIGN_UP(buff[2] << 8 | buff[1], flash_manage->align_num);
} else if ((buff[0] | buff[1] | buff[2] | buff[3]) == FLASH_WRITABLE) {
return;
} else {
i += flash_manage->align_num;
}
}
}
int8_t flash_manage_read(flash_manage_t *flash_manage, uint8_t *pbuf, uint8_t frame_type)
{
if (flash_manage->manage_sector_num == 0 || flash_manage->sector_size == 0 || flash_manage->read_flash == 0 ||
flash_manage->write_flash == 0 || flash_manage->erase_sector == 0) {
return -1;
}
/* 可读表存在数据 */
if (data_form[frame_type].state != 0) {
flash_manage->read_flash(pbuf, data_form[frame_type].addr + 4, data_form[frame_type].size - 5);
if (flash_manage->flash_read_mode == FLASH_CLEAR_MODE) {
/* 将flash内部数据帧头尾置为无效数据 */
uint8_t frame_head[flash_manage->align_num];
memset(frame_head, FLASH_NULL, flash_manage->align_num);
flash_manage->write_flash(frame_head, data_form[frame_type].addr, flash_manage->align_num);
flash_manage->write_flash(frame_head, data_form[frame_type].addr + data_form[frame_type].size - 32, flash_manage->align_num);
/* 将对应类型的可读表置0 */
data_form[frame_type].state = 0;
if (flash_manage->flash_write_mode == FLASH_NO_OVERWRITING_MODE) {
/* flash处于覆写模式下, 可读帧是唯一的,故无需更新可读表, 而非覆写模式, 需要更新可读表 */
update_readable_frame(flash_manage, ALIGN_UP(data_form[frame_type].addr + data_form[frame_type].size, flash_manage->align_num), frame_type);
}
}
return 1;
}
return 0;
}
int8_t flash_manage_write(flash_manage_t *flash_manage, uint8_t *pbuf, uint16_t size, uint8_t frame_type)
{
uint8_t buff[size + 5];
uint16_t len = 0;
memset(buff, 0, size + 5);
len = size + 5;
if (flash_manage->manage_sector_num == 0 || flash_manage->sector_size == 0 || flash_manage->read_flash == 0 ||
flash_manage->write_flash == 0 || flash_manage->erase_sector == 0) {
return -1;
}
if (writeable_addr > flash_manage->flash_start_address + flash_manage->manage_sector_num * flash_manage->sector_size - len || erase_flag == 1) {
erase_flag = 0;
flash_manage->erase_sector(flash_manage->flash_start_address);
writeable_addr = ALIGN_UP(flash_manage->flash_start_address, flash_manage->align_num);
/* 重置可读表 */
for (uint8_t i = 0; i < 255; i++) {
data_form[i].state = 0;
}
}
buff[0] = FLASH_READABLE_HEAD;
buff[1] = len & 0xff;
buff[2] = len >> 8 & 0xff;
buff[3] = frame_type;
buff[len - 1] = FLASH_READABLE_TAIL;
memcpy(buff + 4, pbuf, size);
flash_manage->write_flash(buff, writeable_addr, len);
if (data_form[frame_type].state == 0) {
/* 可读表为空时更新 */
data_form[frame_type].addr = writeable_addr;
data_form[frame_type].size = len;
data_form[frame_type].state = 1;
} else if (flash_manage->flash_write_mode == FLASH_OVERWRITING_MODE && data_form[frame_type].state == 1) {
/* 将flash内部上一个相同类型的数据帧头置为无效数据 */
uint8_t frame_head[flash_manage->align_num];
memset(frame_head, FLASH_NULL, flash_manage->align_num);
flash_manage->write_flash(frame_head, data_form[frame_type].addr, flash_manage->align_num);
data_form[frame_type].addr = writeable_addr;
data_form[frame_type].size = len;
}
writeable_addr = ALIGN_UP(writeable_addr + len, flash_manage->align_num);
return 1;
}

View File

@@ -0,0 +1,70 @@
#ifndef __DRV_FLASH_H__
#define __DRV_FLASH_H__
#include <stdint.h>
#include <string.h>
enum flash_state {
/* 数据无效帧头/帧尾等于flash擦除后的值取反 */
FLASH_NULL = 0x00,
/* 数据可读帧头 */
FLASH_READABLE_HEAD = 0xa5,
/* 数据可读帧尾 */
FLASH_READABLE_TAIL = 0x5a,
/* 数据可写帧头/帧尾等于flash擦除后的值 */
FLASH_WRITABLE = 0xff,
};
typedef enum {
/* 不覆写模式 */
FLASH_NO_OVERWRITING_MODE = 0x00,
/* 覆写模式, 即写入数据后将先前同类型数据置为无效 */
FLASH_OVERWRITING_MODE,
/* 读取不清空模式 */
FLASH_NO_CLEAR_MODE,
/* 读取清空模式即读取数据所在的flash位置0 */
FLASH_CLEAR_MODE,
} flash_write_read_mode_t;
typedef struct {
/* 可读表标志位,表示当前是否存在可读数据 */
uint8_t state;
/* 可读数据大小, 包含帧头帧尾 */
uint16_t size;
/* 可读数据起始地址, 包含帧头 */
uint32_t addr;
} type_readable_frame_t;
typedef struct
{
/* 地址对齐数, 1-2^5 */
uint8_t align_num;
/* flash写入模式 */
flash_write_read_mode_t flash_write_mode;
/* flashdu'q'b模式 */
flash_write_read_mode_t flash_read_mode;
/* 管理的flash起始地址,按扇区对齐 */
uint32_t flash_start_address;
/* 管理的flash扇区数量 */
uint32_t manage_sector_num;
/* flash的扇区大小 */
uint32_t sector_size;
/* 开启flash */
void (*open_flash)(void);
/* 关闭flash */
void (*close_flash)(void);
/* 读flash */
void (*read_flash)(uint8_t *pbuf, uint32_t addr, uint16_t datalen);
/* 写flash */
void (*write_flash)(uint8_t *pbuf, uint32_t addr, uint16_t datalen);
/* 擦除flash */
uint8_t (*erase_sector)(uint32_t addr);
} flash_manage_t;
int8_t flash_manage_init(flash_manage_t *flash_manage);
int8_t flash_manage_read(flash_manage_t *flash_manage, uint8_t *pbuf, uint8_t frame_type);
int8_t flash_manage_write(flash_manage_t *flash_manage, uint8_t *pbuf, uint16_t size, uint8_t frame_type);
#endif /* _FLASH_MANAGE_H__ */

View File

@@ -10,6 +10,7 @@
/* Includes -------------------------------------------------------------------*/
#include "drv_init.h"
#include <stdint.h>
#include "flash_config.h"
/* code -----------------------------------------------------------------------*/
void send_cmd_to_air724(uint8_t *cmd, uint16_t len)
@@ -37,6 +38,7 @@ void send_server_address_to_air724(void)
pos = 0;
memset(config_cmd, 0, sizeof(config_cmd));
}
/**
* @brief drv_all_Init所有传感器、外设芯片、外部设备初始化
*
@@ -50,4 +52,5 @@ void send_server_address_to_air724(void)
void drv_all_Init(void)
{
AIR724_RESET(); /* AIR724 复位 */
stm_flash_init();/* 初始化flash */
}

View File

@@ -0,0 +1,150 @@
#include "flash_config.h"
#include "stm32h7xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
void stmflash_read_data(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{
if (pbuf == NULL || datalen == 0) {
return;
}
memcpy(pbuf, (const void *)addr, datalen);
}
/* ============================================================
* 写 Flash
* 函数指针原型: void (*write_flash)(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
*
* H743 写入规则:
* - 每次必须写 32字节 (FLASH_TYPEPROGRAM_FLASHWORD)
* - 写入地址必须 32字节对齐
* - 不满 32字节的部分用 0xFF 填充
* ============================================================ */
void stmflash_write_data(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
{
if (pbuf == NULL || datalen == 0) {
return;
}
/* 地址必须32字节对齐 */
if ((addr % 32) != 0) {
return;
}
/* 计算对齐后的长度 */
uint16_t aligned_len = (datalen + 31) & ~31U;
/* 构建对齐缓冲区, 多余部分填 0xFF */
uint8_t buf[aligned_len];
memset(buf, 0xFF, aligned_len);
memcpy(buf, pbuf, datalen);
HAL_FLASH_Unlock();
uint32_t address = addr;
uint8_t *writePtr = buf;
uint16_t remain = aligned_len;
while (remain >= 32)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD,
address,
(uint32_t)writePtr) != HAL_OK)
{
/* 写入失败,退出 */
break;
}
address += 32;
writePtr += 32;
remain -= 32;
}
HAL_FLASH_Lock();
}
/* ============================================================
* 擦除 Flash Sector
* 函数指针原型: uint8_t (*erase_sector)(uint32_t addr)
*
* H743 参数:
* - Bank2, Sector0 起始地址 0x08100000
* - 每个 Sector = 128KB
* - VoltageRange = FLASH_VOLTAGE_RANGE_3 (2.7V ~ 3.6V)
* ============================================================ */
uint8_t flash_sector_erase(uint32_t addr)
{
FLASH_EraseInitTypeDef EraseInitStruct = {0};
uint32_t SECTORError = 0;
/* 根据地址计算 Sector 编号 */
/* Bank2: 0x08100000 ~ 0x081FFFFF, 共8个Sector, 每个128KB */
uint32_t sector = (addr - 0x08100000) / (128 * 1024);
if (sector > 7) {
return 0;
}
HAL_FLASH_Unlock();
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Banks = FLASH_BANK_2;
EraseInitStruct.Sector = sector;
EraseInitStruct.NbSectors = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
{
HAL_FLASH_Lock();
return 0;
}
HAL_FLASH_Lock();
return 1;
}
flash_manage_t stm_flash_manage = {0};
/* demo */
// stm_flash_read(data[0], 1);
// stm_flash_read(data[1], 0);
// stm_flash_read(data[0], 1);
// stm_flash_read(data[1], 0);
// stm_flash_write("12345678912345678912345678912345678912345", 41, 1);
// stm_flash_write("abcdef", 6, 0);
// stm_flash_write("12345678912345678912345678912345678912345", 41, 1);
// stm_flash_write("abcdef", 6, 0);
void stm_flash_init(void)
{
stm_flash_manage.align_num = 32;
stm_flash_manage.flash_write_mode = FLASH_OVERWRITING_MODE;
stm_flash_manage.flash_read_mode = FLASH_NO_CLEAR_MODE;
stm_flash_manage.flash_start_address = 0x08180000;
stm_flash_manage.manage_sector_num = 1;
stm_flash_manage.sector_size = 128 * 1024;
stm_flash_manage.open_flash = NULL;
stm_flash_manage.close_flash = NULL;
stm_flash_manage.read_flash = stmflash_read_data;
stm_flash_manage.write_flash = stmflash_write_data;
stm_flash_manage.erase_sector = flash_sector_erase;
// stm_flash_manage.open_flash();
flash_manage_init(&stm_flash_manage);
}
int8_t stm_flash_read(uint8_t *pbuf, uint8_t frame_type)
{
taskENTER_CRITICAL();
int8_t flag = flash_manage_read(&stm_flash_manage, pbuf, frame_type);
taskEXIT_CRITICAL();
return flag;
}
int8_t stm_flash_write(uint8_t *pbuf, uint16_t size, uint8_t frame_type)
{
taskENTER_CRITICAL();
int8_t flag = flash_manage_write(&stm_flash_manage, pbuf, size, frame_type);
taskEXIT_CRITICAL();
return flag;
}

View File

@@ -0,0 +1,13 @@
#ifndef _FLASH_CONFIG_H__
#define _FLASH_CONFIG_H__
#include "drv_flash.h"
void stm_flash_init(void);
int8_t stm_flash_read(uint8_t *pbuf, uint8_t frame_type);
int8_t stm_flash_write(uint8_t *pbuf, uint16_t size, uint8_t frame_type);
extern flash_manage_t stm_flash_manage; // 声明flash管理结构体
#endif /* _FLASH_CONFIG_H__ */

View File

@@ -5,7 +5,10 @@ ChargerManager g_charger_manager = {0};
/*充电桩序列号*/
const uint8_t piles_serial[6][7] = {
// {0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x01},
{0x32, 0x01, 0x06, 0x01, 0x11, 0x15, 0x58},
{0x32, 0x01, 0x06, 0x01, 0x11, 0x16, 0x54},
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x01},
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x02},
@@ -19,7 +22,7 @@ const uint8_t piles_serial[6][7] = {
* @note 初始化充电桩管理器,设置充电桩数量和每个充电桩的初始状态
*/
void init_chargers(void) {
g_charger_manager.charger_count = 6;
g_charger_manager.charger_count = MAX_CHARGER_COUNT;
for (int i = 0; i < g_charger_manager.charger_count; i++) {
ChargerPile *ctx = &g_charger_manager.charger_piles[i];
@@ -28,7 +31,7 @@ void init_chargers(void) {
ctx->get_model = false;
ctx->is_udp_online = false;
ctx->login_info.charger_type = CHARGER_TYPE_DC;
ctx->login_info.gun_num = 2;
ctx->login_info.gun_num = MAX_GUN_PER_CHARGER;
ctx->login_info.protocol_ver = 0x10; // V1.6
strcpy((char*)ctx->login_info.software_ver, "V4.1.50");
ctx->login_info.net_conn_type = 0; // SIM
@@ -36,10 +39,9 @@ void init_chargers(void) {
ctx->login_info.tele_factory = 0x00; // 移动
// 初始化枪
for (int g = 0; g < ctx->login_info.gun_num && g < MAX_GUN_PER_CHARGER; g++) {
for (int g = 0; g < ctx->login_info.gun_num; g++) {
ctx->guns[g].gun_index = g + 1;
ctx->guns[g].status = 0; // 正常
ctx->guns[g].real_time_data.status = 0; // 离线
}
}
}

View File

@@ -12,10 +12,7 @@
typedef struct
{
uint8_t gun_index; // 枪索引
bool is_changing; // 是否正在充电
bool is_plugged; // 是否已插入枪
bool is_gun_returned; // 是否已返回枪
uint8_t status; // 状态
PACK_DATA_0X13 real_time_data; // 实时数据
} ChargerGun;

View File

@@ -61,6 +61,9 @@
#define TRUE 1
#define FALSE 0
#define PI 3.1415926f
#define SOFTWARE_VERSION "JSBRv1.2" // 软件版本
@@ -115,6 +118,7 @@
#define get_sys_time_msec() HAL_GetTick()
#define CONSTRAIN(x, max, min) (x > max ? max : (x < min ? min : x))
#endif /* __GLOBAL_H */

View File

@@ -56,10 +56,10 @@ void Os_Task_Init(void) /*任务入口函数、任务名字、任务栈大小、
xReturn = xTaskCreate((TaskFunction_t)DownLinkTask_Function, "DownLinkTask", 1024, NULL, osPriorityAboveNormal, &DownLinkTaskHandle);
/* UDP 消息队列接受任务 */
xReturn = xTaskCreate((TaskFunction_t)UDPTask_Function, "UDPTask", 512, NULL, osPriorityAboveNormal, &UDPTaskHandle);
xReturn = xTaskCreate((TaskFunction_t)UDPTask_Function, "UDPTask", 1536, NULL, osPriorityHigh, &UDPTaskHandle);
/* UDP 消息解析任务 */
xReturn = xTaskCreate((TaskFunction_t)UDP_ParseTask_Function, "UDPParseTask", 1024, NULL, osPriorityAboveNormal, &UDP_ParseTaskHandle);
xReturn = xTaskCreate((TaskFunction_t)UDP_ParseTask_Function, "UDPParseTask", 2048, NULL, osPriorityAboveNormal, &UDP_ParseTaskHandle);
/* 云快充平台交互任务 */
xReturn = xTaskCreate((TaskFunction_t)YkcTask_Function, "YKCTask", 1024, NULL, osPriorityAboveNormal, &YkcTaskHandle);

View File

@@ -15,6 +15,34 @@ ip4_addr_t stake_ip_4 = IPADDR4_INIT_BYTES(10, 12, 19, 104); // 桩 4 IP地址
ip4_addr_t stake_ip_5 = IPADDR4_INIT_BYTES(10, 12, 19, 105); // 桩 5 IP地址
ip4_addr_t stake_ip_6 = IPADDR4_INIT_BYTES(10, 12, 19, 106); // 桩 6 IP地址
ip4_addr_t server_ip = IPADDR4_INIT_BYTES(10, 12, 19, 107); // 上位机管理地址
/**
* @brief 将十六进制字符串转换为字节数组
* @note 输入字符串长度必须为偶数
*/
int hex_string_to_bytes(const char *hex_str, uint8_t *bytes, int len)
{
for (int i = 0; i < len; i++)
{
unsigned int val;
sscanf(hex_str + i * 2, "%02x", &val);
bytes[i] = (uint8_t)val;
}
return 0;
}
/**
* @brief 将字节数组转换为十六进制字符串
* @note 输出字符串长度必须为32
*/
void bytes_to_hex_string(const uint8_t *bytes, char *hex_str)
{
for (int i = 0; i < 16; i++)
{
sprintf(hex_str + i * 2, "%02X", bytes[i]);
}
}
/**
* @brief UDP发送
* @note 发送数据到指定桩
@@ -26,31 +54,49 @@ ip4_addr_t stake_ip_6 = IPADDR4_INIT_BYTES(10, 12, 19, 106); // 桩 6 IP地址
err_t udp_send_response(uint8_t stake_index, uint8_t *data, u16_t len)
{
struct netbuf *buf = netbuf_new();
if (!buf) {
if (!buf)
{
return ERR_MEM;
}
ip4_addr_t *dst_ip = NULL;
switch (stake_index) {
case 1: dst_ip = &stake_ip_1; break;
case 2: dst_ip = &stake_ip_2; break;
case 3: dst_ip = &stake_ip_3; break;
case 4: dst_ip = &stake_ip_4; break;
case 5: dst_ip = &stake_ip_5; break;
case 6: dst_ip = &stake_ip_6; break;
switch (stake_index)
{
case 1:
dst_ip = &stake_ip_1;
break;
case 2:
dst_ip = &stake_ip_2;
break;
case 3:
dst_ip = &stake_ip_3;
break;
case 4:
dst_ip = &stake_ip_4;
break;
case 5:
dst_ip = &stake_ip_5;
break;
case 6:
dst_ip = &stake_ip_6;
break;
case 7:
dst_ip = &server_ip;
break;
default:
printf("Invalid stake index\r\n");
netbuf_delete(buf);
return ERR_VAL; // ← 修复 return 无返回值
return ERR_VAL; // ← 修复 return 无返回值
}
void *buf_data = netbuf_alloc(buf, len); // ← 在 netbuf 内部分配内存
if (!buf_data) {
void *buf_data = netbuf_alloc(buf, len); // ← 在 netbuf 内部分配内存
if (!buf_data)
{
netbuf_delete(buf);
return ERR_MEM;
}
memcpy(buf_data, data, len); // ← 拷贝数据,不再依赖外部指针
memcpy(buf_data, data, len); // ← 拷贝数据,不再依赖外部指针
err_t err = netconn_sendto(datalink_conn, buf, dst_ip, LINK_STAKE_PORT);
netbuf_delete(buf);
return err;
@@ -166,7 +212,7 @@ void UDPTask_Function(void const *argument)
*/
void local_on_cmd_callback_power_on(uint8_t stake_index, cJSON *json_pack)
{
if (stake_index > 6)
if (stake_index > MAX_CHARGER_COUNT)
{
return;
}
@@ -203,7 +249,7 @@ void local_on_cmd_callback_power_on(uint8_t stake_index, cJSON *json_pack)
*/
void local_on_cmd_callback_heartbeat_response(uint8_t stake_index, cJSON *json_pack)
{
if (stake_index > 6)
if (stake_index > MAX_CHARGER_COUNT)
{
return;
}
@@ -258,6 +304,432 @@ void local_on_cmd_callback_heartbeat_response(uint8_t stake_index, cJSON *json_p
printf("南向:对电桩 %d 心跳回复成功\r\n", stake_index);
}
/**
* @brief 解析充电桩实时数据指令
* @note 回复实时数据应答
* @param stake_index 桩索引
* @param json_pack json数据包
*/
void local_on_cmd_callback_realtime_data_response(uint8_t stake_index, cJSON *json_pack)
{
if (stake_index > MAX_CHARGER_COUNT)
{
return;
}
cJSON *transaction_id = cJSON_GetObjectItem(json_pack, "transaction_id"); // 提取交易序列号
cJSON *gun_id = cJSON_GetObjectItem(json_pack, "gun_id"); // 提取枪号
cJSON *state = cJSON_GetObjectItem(json_pack, "state"); // 提取枪状态
cJSON *gun_back = cJSON_GetObjectItem(json_pack, "gun_back"); // 提取枪归位状态
cJSON *gun_insert = cJSON_GetObjectItem(json_pack, "gun_insert"); // 提取枪插入状态
cJSON *voltage = cJSON_GetObjectItem(json_pack, "voltage"); // 提取电压
cJSON *current = cJSON_GetObjectItem(json_pack, "current"); // 提取电流
cJSON *cable_temp = cJSON_GetObjectItem(json_pack, "cable_temp"); // 提取电缆温度
cJSON *cable_code = cJSON_GetObjectItem(json_pack, "cable_code"); // 提取电缆编码
cJSON *soc = cJSON_GetObjectItem(json_pack, "soc"); // 提取SOC
cJSON *battery_temp = cJSON_GetObjectItem(json_pack, "battery_temp"); // 提取电池温度
cJSON *charge_time = cJSON_GetObjectItem(json_pack, "charge_time"); // 提取充电时间
cJSON *remain_time = cJSON_GetObjectItem(json_pack, "remain_time"); // 提取剩余时间
cJSON *charge_kwh = cJSON_GetObjectItem(json_pack, "charge_kwh"); // 提取充电量
cJSON *loss_kwh = cJSON_GetObjectItem(json_pack, "loss_kwh"); // 提取损失量
cJSON *charge_amount = cJSON_GetObjectItem(json_pack, "charge_amount"); // 提取充电金额
cJSON *fault = cJSON_GetObjectItem(json_pack, "fault"); // 提取故障状态
// 检查交易序列号、枪号、状态字段是否存在
if (!transaction_id || !gun_id || !state)
{
printf(" └── [error] 缺少必要字段 transaction_id/gun_id/state\r\n");
return;
}
// 检查交易序列号长度是否为32位
if (strlen(transaction_id->valuestring) != 32)
{
printf(" └── [error] transaction_id长度错误: %d\r\n", (int)strlen(transaction_id->valuestring));
return;
}
// 检查枪号是否有效
uint8_t gun_idx = (uint8_t)gun_id->valueint;
if (gun_idx == 0 || gun_idx > MAX_GUN_PER_CHARGER)
{
printf(" └── [error] 无效的gun_id: %d\r\n", gun_idx);
return;
}
ChargerPile *pile = &g_charger_manager.charger_piles[stake_index - 1];
ChargerGun *gun = &pile->guns[gun_idx - 1];
// 更新枪状态
gun->real_time_data.status = (uint8_t)state->valueint;
// 更新枪归位状态
gun->real_time_data.gun_back = (uint8_t)gun_back->valueint;
// 更新枪插入状态
gun->real_time_data.gun_is_insert = (uint8_t)gun_insert->valueint;
// 更新电压
gun->real_time_data.out_voltage = (uint16_t)(voltage->valuedouble * 10);
// 更新电流
gun->real_time_data.out_current = (uint16_t)(current->valuedouble * 10);
// 更新电缆温度
gun->real_time_data.gun_line_temp = (uint8_t)cable_temp->valueint;
// 更新SOC
gun->real_time_data.soc = (uint8_t)soc->valueint;
// 更新电池温度
gun->real_time_data.battery_temp = (uint8_t)battery_temp->valueint;
// 更新累计充电时间
gun->real_time_data.charge_time = (uint16_t)charge_time->valueint;
// 更新剩余时间
gun->real_time_data.remain_time = (uint16_t)remain_time->valueint;
// 更新充电量
gun->real_time_data.charge_energy = (uint32_t)(charge_kwh->valuedouble * 10000);
// 更新损失量
gun->real_time_data.loss_energy = (uint32_t)(loss_kwh->valuedouble * 10000);
// 更新充电金额
gun->real_time_data.charge_money = (uint32_t)(charge_amount->valuedouble * 10000);
// 更新故障状态
gun->real_time_data.hard_fault = (uint16_t)fault->valueint;
// 回复实时数据应答
cJSON *root = NULL;
char *str = NULL;
root = cJSON_CreateObject();
if (root == NULL)
{
printf("Failed to create JSON object for stake %d\r\n", stake_index);
return;
}
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(root, "id", stake_index);
cJSON_AddStringToObject(root, "cmd", "realtime data");
cJSON_AddStringToObject(root, "type", "response");
str = cJSON_Print(root);
udp_send_response(stake_index, str, strlen(str));
free(str);
cJSON_Delete(root);
printf("南向:对电桩 %d 实时数据回复成功\r\n", stake_index);
}
/**
* @brief 主动下发启动指令
* @note 发送启动指令到充电桩,符合协议格式要求
* @param stake_index 桩索引 (1~6)
* @param gun_id 枪编码 (1~N)
*/
void local_on_cmd_send_start_charging(uint8_t stake_index, uint8_t gun_id)
{
if (stake_index > 6 || stake_index == 0)
{
printf("Invalid stake index: %d\r\n", stake_index);
return;
}
if (gun_id == 0 || gun_id > MAX_GUN_PER_CHARGER)
{
printf("Invalid gun id: %d\r\n", gun_id);
return;
}
// 检查是否已获取费率模型
if (!g_charger_manager.charger_piles[stake_index - 1].get_model)
{
printf("Stake %d fee model not ready\r\n", stake_index);
return;
}
cJSON *root = NULL;
cJSON *billing_array = NULL;
cJSON *billing_item = NULL;
char *str = NULL;
// 转换交易ID16位数组转字符串
char transaction_id_str[33] = {0}; // 32位 + 结束符
uint8_t *trade_serial = g_charger_manager.charger_piles[stake_index - 1].guns[gun_id - 1].real_time_data.trade_serial;
trade_serial_to_string(trade_serial, transaction_id_str);
root = cJSON_CreateObject();
if (root == NULL)
{
printf("Failed to create JSON object for stake %d\r\n", stake_index);
return;
}
/* 添加基本字段 */
cJSON_AddNumberToObject(root, "id", stake_index);
cJSON_AddStringToObject(root, "cmd", "start charging");
cJSON_AddStringToObject(root, "transaction_id", transaction_id_str); // 使用转换后的32位字符串
cJSON_AddNumberToObject(root, "gun_id", gun_id);
cJSON_AddStringToObject(root, "type", "request");
/* 添加限制金额(根据实际业务设置)*/
cJSON_AddNumberToObject(root, "limit_amount", 00.00);
/* 创建计费模型数组 */
billing_array = cJSON_CreateArray();
if (billing_array == NULL)
{
printf("Failed to create billing array\r\n");
cJSON_Delete(root);
return;
}
/* 计费时段:生成简化格式 [start_time, end_time, electricity_fee, service_fee] */
int i = 0;
while (i < 48) // 48个半小时时段
{
uint8_t current_type = g_charger_manager.fee_model_global.fee_num[i];
// 跳过无效费率
if (current_type == 0xFF)
{
i++;
continue;
}
// 查找连续相同费率的结束位置
int j = i;
while (j < 48 && g_charger_manager.fee_model_global.fee_num[j] == current_type)
{
j++;
}
// 计算起始时间(小时.半小时6.0=6:00, 6.5=6:30
float start_time = i * 0.5f;
float end_time = j * 0.5f;
// 跨天处理24.0显示为0.0
if (end_time == 24.0f)
{
end_time = 0.0f;
}
// 根据费率类型设置电费和服务费
float electricity_fee = 0.0f;
float service_fee = 0.0f;
switch (current_type)
{
case 0x00: // 尖时
electricity_fee = g_charger_manager.fee_model_global.shark_fee_ratio / 100000.0f;
service_fee = g_charger_manager.fee_model_global.shark_service_ratio / 100000.0f;
break;
case 0x01: // 峰时
electricity_fee = g_charger_manager.fee_model_global.peak_fee_ratio / 100000.0f;
service_fee = g_charger_manager.fee_model_global.peak_service_ratio / 100000.0f;
break;
case 0x02: // 平时
electricity_fee = g_charger_manager.fee_model_global.flat_fee_ratio / 100000.0f;
service_fee = g_charger_manager.fee_model_global.flat_service_ratio / 100000.0f;
break;
case 0x03: // 谷时
electricity_fee = g_charger_manager.fee_model_global.valley_fee_ratio / 100000.0f;
service_fee = g_charger_manager.fee_model_global.valley_service_ratio / 100000.0f;
break;
default:
electricity_fee = 0.0f;
service_fee = 0.0f;
break;
}
// 创建计费时段数组 [start_time, end_time, electricity_fee, service_fee]
if (electricity_fee > 0 || service_fee > 0)
{
billing_item = cJSON_CreateArray();
if (billing_item != NULL)
{
cJSON_AddNumberToObject(billing_item, NULL, start_time);
cJSON_AddNumberToObject(billing_item, NULL, end_time);
cJSON_AddNumberToObject(billing_item, NULL, electricity_fee);
cJSON_AddNumberToObject(billing_item, NULL, service_fee);
cJSON_AddItemToArray(billing_array, billing_item);
}
}
i = j; // 跳到下一个不同费率段
}
// 将数组添加到根对象
cJSON_AddItemToObject(root, "billing_model", billing_array);
// 转换为JSON字符串并发送
str = cJSON_Print(root);
if (str != NULL)
{
// #ifdef DEBUG
// printf("Send start command JSON: %s\r\n", str);
// #endif
udp_send_response(stake_index, str, strlen(str));
free(str);
}
else
{
printf("Failed to print JSON for stake %d\r\n", stake_index);
}
cJSON_Delete(root);
printf("Southbound: Start command sent to stake %d, gun %d, total %d billing periods\r\n",
stake_index, gun_id, (int)cJSON_GetArraySize(billing_array));
}
void local_on_cmd_callback_server_login_response(cJSON *json_pack)
{
cJSON *request_id = cJSON_GetObjectItem(json_pack, "request_id");
cJSON *username = cJSON_GetObjectItem(json_pack, "username");
cJSON *password = cJSON_GetObjectItem(json_pack, "password");
cJSON *root = NULL;
char *str = NULL;
root = cJSON_CreateObject();
if (root == NULL)
{
printf("Failed to create JSON object for server login\r\n");
return;
}
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddStringToObject(root, "request_id", request_id->valuestring);
if (strcmp(username->valuestring, "admin") != 0 || strcmp(password->valuestring, "123456") != 0)
{
cJSON_AddStringToObject(root, "error", "用户或密码错误 ");
cJSON_AddBoolToObject(root, "success", cJSON_False);
printf("登录失败\r\n");
}
else
{
cJSON_AddBoolToObject(root, "success", cJSON_True);
printf("登录成功\r\n");
}
str = cJSON_Print(root);
udp_send_response(7, str, strlen(str));
free(str);
cJSON_Delete(root);
}
// 处理获取状态查询指令
void local_on_cmd_callback_server_get_status_response(cJSON *json_pack)
{
cJSON *request_id = cJSON_GetObjectItem(json_pack, "request_id");
cJSON *root = NULL;
cJSON *piles = NULL;
cJSON *pile = NULL;
cJSON *guns = NULL;
cJSON *gun = NULL;
char *str = NULL;
root = cJSON_CreateObject();
if (root == NULL)
{
printf("Failed to create JSON object for get_status\r");
return;
}
cJSON_AddStringToObject(root, "request_id", request_id->valuestring);
cJSON_AddBoolToObject(root, "success", cJSON_True);
/* ── piles 数组 ── */
piles = cJSON_CreateArray();
/* 桩 1 */
pile = cJSON_CreateObject();
cJSON_AddStringToObject(pile, "serial", "32010601111558");
cJSON_AddBoolToObject(pile, "is_online", cJSON_True);
guns = cJSON_CreateArray();
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 1);
cJSON_AddItemToArray(guns, gun);
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 0);
cJSON_AddItemToArray(guns, gun);
cJSON_AddItemToObject(pile, "guns", guns);
cJSON_AddItemToArray(piles, pile);
/* 桩 2 */
pile = cJSON_CreateObject();
cJSON_AddStringToObject(pile, "serial", "32010601111559");
cJSON_AddBoolToObject(pile, "is_online", cJSON_True);
guns = cJSON_CreateArray();
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 1);
cJSON_AddItemToArray(guns, gun);
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 1);
cJSON_AddItemToArray(guns, gun);
cJSON_AddItemToObject(pile, "guns", guns);
cJSON_AddItemToArray(piles, pile);
/* 桩 3 */
pile = cJSON_CreateObject();
cJSON_AddStringToObject(pile, "serial", "32010601111560");
cJSON_AddBoolToObject(pile, "is_online", cJSON_True);
guns = cJSON_CreateArray();
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 0);
cJSON_AddItemToArray(guns, gun);
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 0);
cJSON_AddItemToArray(guns, gun);
cJSON_AddItemToObject(pile, "guns", guns);
cJSON_AddItemToArray(piles, pile);
/* 桩 4 */
pile = cJSON_CreateObject();
cJSON_AddStringToObject(pile, "serial", "32010601111561");
cJSON_AddBoolToObject(pile, "is_online", cJSON_False);
guns = cJSON_CreateArray();
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 0);
cJSON_AddItemToArray(guns, gun);
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 0);
cJSON_AddItemToArray(guns, gun);
cJSON_AddItemToObject(pile, "guns", guns);
cJSON_AddItemToArray(piles, pile);
/* 桩 5 */
pile = cJSON_CreateObject();
cJSON_AddStringToObject(pile, "serial", "32010601111562");
cJSON_AddBoolToObject(pile, "is_online", cJSON_True);
guns = cJSON_CreateArray();
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 1);
cJSON_AddItemToArray(guns, gun);
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 0);
cJSON_AddItemToArray(guns, gun);
cJSON_AddItemToObject(pile, "guns", guns);
cJSON_AddItemToArray(piles, pile);
/* 桩 6 */
pile = cJSON_CreateObject();
cJSON_AddStringToObject(pile, "serial", "32010601111563");
cJSON_AddBoolToObject(pile, "is_online", cJSON_False);
guns = cJSON_CreateArray();
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 0);
cJSON_AddItemToArray(guns, gun);
gun = cJSON_CreateObject();
cJSON_AddNumberToObject(gun, "status", 0);
cJSON_AddItemToArray(guns, gun);
cJSON_AddItemToObject(pile, "guns", guns);
cJSON_AddItemToArray(piles, pile);
cJSON_AddItemToObject(root, "piles", piles);
/* ── 发送 ── */
str = cJSON_Print(root);
udp_send_response(7, str, strlen(str));
free(str);
cJSON_Delete(root);
printf("get_status 回复已发送 \r\n");
}
void handle_udp_downlink(uint8_t id, const char *cmd, cJSON *json_pack)
{
@@ -275,6 +747,26 @@ void handle_udp_downlink(uint8_t id, const char *cmd, cJSON *json_pack)
printf("南向:收到电桩 %d 心跳指令\r\n", id);
local_on_cmd_callback_heartbeat_response(id, json_pack);
}
// 处理实时数据指令
else if (strcmp(cmd, "realtime data") == 0)
{
printf("南向:收到电桩 %d 实时数据指令 \r\n", id);
local_on_cmd_callback_realtime_data_response(id, json_pack);
}
/*处理上位机指令 */
// 处理登录指令
else if (strcmp(cmd, "server_login") == 0)
{
printf("上位机:收到登录指令 \r\n");
local_on_cmd_callback_server_login_response(json_pack);
}
// 处理获取状态查询指令
else if (strcmp(cmd, "server_get_status") == 0)
{
printf("上位机:收到获取状态查询指令 \r\n");
local_on_cmd_callback_server_get_status_response(json_pack);
}
else
{
printf("Unknown CMD: '%s' from ID %d\r\n", cmd, id);
@@ -292,209 +784,10 @@ void trade_serial_to_string(uint8_t *trade_serial, char *output_str)
{
return;
}
for (int i = 0; i < 16; i++)
{
sprintf(&output_str[i * 2], "%02X", trade_serial[i]);
}
output_str[32] = '\0';
}
/**
* @brief 主动下发启动指令
* @note 发送启动指令到充电桩,符合协议格式要求
* @param stake_index 桩索引 (1~6)
* @param gun_id 枪编码 (1~N)
*/
void local_on_cmd_send_start_charging(uint8_t stake_index, uint8_t gun_id)
{
if (stake_index > 6 || stake_index == 0)
{
printf("Invalid stake index: %d\r\n", stake_index);
return;
}
if (gun_id == 0 || gun_id > MAX_GUN_PER_CHARGER)
{
printf("Invalid gun id: %d\r\n", gun_id);
return;
}
// 检查是否已获取费率模型
if (!g_charger_manager.charger_piles[stake_index - 1].get_model)
{
printf("Stake %d fee model not ready\r\n", stake_index);
return;
}
cJSON *root = NULL;
cJSON *billing_array = NULL;
cJSON *billing_item = NULL;
char *str = NULL;
// 转换交易ID16位数组转字符串
char transaction_id_str[33] = {0}; // 32位 + 结束符
uint8_t *trade_serial = g_charger_manager.charger_piles[stake_index - 1].guns[gun_id - 1].real_time_data.trade_serial;
trade_serial_to_string(trade_serial, transaction_id_str);
root = cJSON_CreateObject();
if (root == NULL)
{
printf("Failed to create JSON object for stake %d\r\n", stake_index);
return;
}
/* 添加基本字段 */
cJSON_AddNumberToObject(root, "id", stake_index);
cJSON_AddStringToObject(root, "cmd", "start charging");
cJSON_AddStringToObject(root, "transaction_id", transaction_id_str); // 使用转换后的32位字符串
cJSON_AddNumberToObject(root, "gun_id", gun_id);
cJSON_AddStringToObject(root, "type", "request");
/* 添加限制金额(根据实际业务设置)*/
cJSON_AddNumberToObject(root, "limit_amount", 30.00);
/* 创建计费模型数组 */
billing_array = cJSON_CreateArray();
if (billing_array == NULL)
{
printf("Failed to create billing array\r\n");
cJSON_Delete(root);
return;
}
/* 计费时段:根据费率表生成 period_id 1:尖 2:峰 3:平 4:谷 */
int period_id = 1;
int i = 0;
while (i < 48) // 48个半小时时段
{
uint8_t current_type = g_charger_manager.fee_model_global.fee_num[i];
// 跳过无效费率
if (current_type == 0xFF)
{
i++;
continue;
}
// 查找连续相同费率的结束位置
int j = i;
while (j < 48 && g_charger_manager.fee_model_global.fee_num[j] == current_type)
{
j++;
}
// 计算起始时间第i个半小时段
int start_hour = i / 2;
int start_min = (i % 2) * 30;
// 计算结束时间第j个半小时段的起始时间
int end_hour = j / 2;
int end_min = (j % 2) * 30;
// 格式化时间字符串 "HH:MM"
char start_time[6];
char end_time[6];
sprintf(start_time, "%02d:%02d", start_hour, start_min);
if (end_hour == 24 && end_min == 0)
{
sprintf(end_time, "00:00"); // 跨天显示为00:00
}
else
{
sprintf(end_time, "%02d:%02d", end_hour, end_min);
}
// 根据费率类型设置电费和服务费
float electricity_fee = 0.0f;
float service_fee = 0.0f;
int mapped_period_id = 0; // 映射到协议要求的period_id
switch (current_type)
{
case 0x00: // 尖时
electricity_fee = g_charger_manager.fee_model_global.shark_fee_ratio / 100000.0f;
service_fee = g_charger_manager.fee_model_global.shark_service_ratio / 100000.0f;
mapped_period_id = 1; // 1:尖
break;
case 0x01: // 峰时
electricity_fee = g_charger_manager.fee_model_global.peak_fee_ratio / 100000.0f;
service_fee = g_charger_manager.fee_model_global.peak_service_ratio / 100000.0f;
mapped_period_id = 2; // 2:峰
break;
case 0x02: // 平时
electricity_fee = g_charger_manager.fee_model_global.flat_fee_ratio / 100000.0f;
service_fee = g_charger_manager.fee_model_global.flat_service_ratio / 100000.0f;
mapped_period_id = 3; // 3:平
break;
case 0x03: // 谷时
electricity_fee = g_charger_manager.fee_model_global.valley_fee_ratio / 100000.0f;
service_fee = g_charger_manager.fee_model_global.valley_service_ratio / 100000.0f;
mapped_period_id = 4; // 4:谷
break;
default:
electricity_fee = 0.0f;
service_fee = 0.0f;
mapped_period_id = 0;
break;
}
// 创建计费时段对象(只有有效费率类型才添加)
if (mapped_period_id > 0)
{
billing_item = cJSON_CreateObject();
if (billing_item != NULL)
{
cJSON_AddNumberToObject(billing_item, "period_id", mapped_period_id);
cJSON_AddStringToObject(billing_item, "start_time", start_time);
cJSON_AddStringToObject(billing_item, "end_time", end_time);
cJSON_AddNumberToObject(billing_item, "electricity_fee", electricity_fee);
cJSON_AddNumberToObject(billing_item, "service_fee", service_fee);
cJSON_AddItemToArray(billing_array, billing_item);
// 调试打印
#ifdef DEBUG
const char *period_name = "";
switch(mapped_period_id)
{
case 1: period_name = "Sharp"; break;
case 2: period_name = "Peak"; break;
case 3: period_name = "Flat"; break;
case 4: period_name = "Valley"; break;
}
printf("Period %d: %s-%s [%s] electricity:%.3f service:%.3f\r\n",
mapped_period_id, start_time, end_time, period_name,
electricity_fee, service_fee);
#endif
}
}
i = j; // 跳到下一个不同费率段
}
// 将数组添加到根对象
cJSON_AddItemToObject(root, "billing_model", billing_array);
// 转换为JSON字符串并发送
str = cJSON_Print(root);
if (str != NULL)
{
#ifdef DEBUG
printf("Send start command JSON: %s\r\n", str);
#endif
udp_send_response(stake_index, str, strlen(str));
free(str);
}
else
{
printf("Failed to print JSON for stake %d\r\n", stake_index);
}
cJSON_Delete(root);
printf("Southbound: Start command sent to stake %d, gun %d, total %d billing periods\r\n",
stake_index, gun_id, (int)cJSON_GetArraySize(billing_array));
}

View File

@@ -24,13 +24,12 @@
*/
uint8_t SETP = 0;
void YkcTask_Function(void const *argument)
{
init_chargers(); /* 初始化桩结构体*/
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); /* 等待桩通讯协议层完成*/
osDelay(5000);
// send_server_address_to_air724();
// send_server_address_to_air724();
while (1)
{
TaskRunTimeStat.YkcTask.threads_runtime = GetTask_RunTime(YkcTaskID);
@@ -39,52 +38,56 @@ void YkcTask_Function(void const *argument)
switch (SETP)
{
case 0:
{
if (g_charger_manager.charger_piles[1 - 1].is_udp_online)
{
uint8_t open_cmd[] = { 0x55, 0xAA, 0x3, 0x01, 0x01, 0xAA, 0x55};
Air724_Message_Send(open_cmd, sizeof(open_cmd));
osDelay(3000);
SETP = 1;
}
else
{
printf("网关:等待桩上电指令\r\n");
osDelay(1000);
SETP = 0;
}
case 0:
{
// 等待桩上电
if (!g_charger_manager.charger_piles[1 - 1].is_udp_online)
{
uint8_t open_cmd[] = {0x55, 0xAA, 0x3, 0x01, 0x01, 0xAA, 0x55};
Air724_Message_Send(open_cmd, sizeof(open_cmd));
osDelay(3000);
SETP = 1;
}
break;
else
{
printf("网关:等待桩上电指令\r\n");
osDelay(1000);
SETP = 0;
}
}
break;
// 云快充登录认证
case 1:
{
if (!g_charger_manager.charger_piles[1 - 1].is_online)
{
charger_to_server_0X01(1);
}
else
{
SETP = 2;
charger_to_server_0X05(1,1);
}
osDelay(5000);
osDelay(5000);
}
break;
// 云快充计费模型请求
case 2:
{
if (!g_charger_manager.charger_piles[1 - 1].get_model)
charger_to_server_0X09(1); // 桩1计费模型请求
else
SETP = 3;
osDelay(3000);
}
break;
case 3:
{
charger_to_server_0X13(1, 1); // 上传状态
local_on_cmd_send_start_charging(1,1);
// local_on_cmd_send_start_charging(1, 1);
osDelay(3000);
}
break;
@@ -92,7 +95,7 @@ void YkcTask_Function(void const *argument)
break;
}
//osDelay(2000);
// osDelay(2000);
}
}