add:增加上位机交互框架、Flash R/W 框架
This commit is contained in:
BIN
Core/9e12a2e4a7f3dc87fa034aecf79e893c.png
Normal file
BIN
Core/9e12a2e4a7f3dc87fa034aecf79e893c.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
149
Core/Middlewares/Third_Party/Ykc/charger_to_server.c
vendored
149
Core/Middlewares/Third_Party/Ykc/charger_to_server.c
vendored
@@ -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 )
|
||||
// 根据状态清零特定字段
|
||||
if (data.status == 0x01 || data.status == 0x02||data.status == 0x00)
|
||||
{
|
||||
|
||||
memcpy(data.trade_serial, trade_data,16);
|
||||
memset(data.trade_serial, 0, sizeof(data.trade_serial));
|
||||
data.out_voltage = 0;
|
||||
data.charge_energy = 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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
// 报文被改为A5,A8
|
||||
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); //0x31,0x33
|
||||
|
||||
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);
|
||||
|
||||
//远程启机命令回复
|
||||
|
||||
31
Core/Middlewares/Third_Party/Ykc/server_common.c
vendored
31
Core/Middlewares/Third_Party/Ykc/server_common.c
vendored
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,6 +199,7 @@ 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
|
||||
}
|
||||
}
|
||||
@@ -208,49 +208,64 @@ void on_cmd_frame_type_0X58(uint8_t stake_index, SERVER_PACK *pack)
|
||||
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);
|
||||
|
||||
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; // 枪未在使用
|
||||
}
|
||||
|
||||
|
||||
|
||||
//计费模型应答
|
||||
|
||||
#endif
|
||||
charger_to_server_0X33(stake_index, data.gun_index, result, err_code);
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
### 生产代码设置
|
||||
- /User/Global/g_decpile -> void init_chargers(void) 需要修改预设 ,从电桩全局结构体拿
|
||||

|
||||
166
Core/User/Driver/drv_flash.c
Normal file
166
Core/User/Driver/drv_flash.c
Normal 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;
|
||||
}
|
||||
70
Core/User/Driver/drv_flash.h
Normal file
70
Core/User/Driver/drv_flash.h
Normal 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__ */
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
150
Core/User/Driver/flash_config.c
Normal file
150
Core/User/Driver/flash_config.c
Normal 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;
|
||||
}
|
||||
13
Core/User/Driver/flash_config.h
Normal file
13
Core/User/Driver/flash_config.h
Normal 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__ */
|
||||
@@ -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; // 离线
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,18 +54,35 @@ 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);
|
||||
@@ -45,7 +90,8 @@ err_t udp_send_response(uint8_t stake_index, uint8_t *data, u16_t len)
|
||||
}
|
||||
|
||||
void *buf_data = netbuf_alloc(buf, len); // ← 在 netbuf 内部分配内存
|
||||
if (!buf_data) {
|
||||
if (!buf_data)
|
||||
{
|
||||
netbuf_delete(buf);
|
||||
return ERR_MEM;
|
||||
}
|
||||
@@ -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,46 +304,110 @@ void local_on_cmd_callback_heartbeat_response(uint8_t stake_index, cJSON *json_p
|
||||
|
||||
printf("南向:对电桩 %d 心跳回复成功\r\n", stake_index);
|
||||
}
|
||||
|
||||
void handle_udp_downlink(uint8_t id, const char *cmd, cJSON *json_pack)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return;
|
||||
// 处理上电指令
|
||||
if (strcmp(cmd, "online") == 0)
|
||||
{
|
||||
printf("南向:收到电桩 %d 上电指令\r\n", id);
|
||||
local_on_cmd_callback_power_on(id, json_pack);
|
||||
}
|
||||
// 处理心跳指令
|
||||
else if (strcmp(cmd, "heartbeat") == 0)
|
||||
{
|
||||
printf("南向:收到电桩 %d 心跳指令\r\n", id);
|
||||
local_on_cmd_callback_heartbeat_response(id, json_pack);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unknown CMD: '%s' from ID %d\r\n", cmd, id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将16字节的交易序列号转换为32位16进制字符串
|
||||
* @param trade_serial 16字节数组
|
||||
* @param output_str 输出缓冲区(至少33字节)
|
||||
* @brief 解析充电桩实时数据指令
|
||||
* @note 回复实时数据应答
|
||||
* @param stake_index 桩索引
|
||||
* @param json_pack json数据包
|
||||
*/
|
||||
void trade_serial_to_string(uint8_t *trade_serial, char *output_str)
|
||||
void local_on_cmd_callback_realtime_data_response(uint8_t stake_index, cJSON *json_pack)
|
||||
{
|
||||
if (trade_serial == NULL || output_str == NULL)
|
||||
if (stake_index > MAX_CHARGER_COUNT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
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)
|
||||
{
|
||||
sprintf(&output_str[i * 2], "%02X", trade_serial[i]);
|
||||
printf(" └── [error] 缺少必要字段 transaction_id/gun_id/state\r\n");
|
||||
return;
|
||||
}
|
||||
output_str[32] = '\0';
|
||||
// 检查交易序列号长度是否为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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,7 +462,7 @@ void local_on_cmd_send_start_charging(uint8_t stake_index, uint8_t gun_id)
|
||||
cJSON_AddStringToObject(root, "type", "request");
|
||||
|
||||
/* 添加限制金额(根据实际业务设置)*/
|
||||
cJSON_AddNumberToObject(root, "limit_amount", 30.00);
|
||||
cJSON_AddNumberToObject(root, "limit_amount", 00.00);
|
||||
|
||||
/* 创建计费模型数组 */
|
||||
billing_array = cJSON_CreateArray();
|
||||
@@ -363,8 +473,7 @@ void local_on_cmd_send_start_charging(uint8_t stake_index, uint8_t gun_id)
|
||||
return;
|
||||
}
|
||||
|
||||
/* 计费时段:根据费率表生成 period_id 1:尖 2:峰 3:平 4:谷 */
|
||||
int period_id = 1;
|
||||
/* 计费时段:生成简化格式 [start_time, end_time, electricity_fee, service_fee] */
|
||||
int i = 0;
|
||||
|
||||
while (i < 48) // 48个半小时时段
|
||||
@@ -385,90 +494,55 @@ void local_on_cmd_send_start_charging(uint8_t stake_index, uint8_t gun_id)
|
||||
j++;
|
||||
}
|
||||
|
||||
// 计算起始时间(第i个半小时段)
|
||||
int start_hour = i / 2;
|
||||
int start_min = (i % 2) * 30;
|
||||
// 计算起始时间(小时.半小时:6.0=6:00, 6.5=6:30)
|
||||
float start_time = i * 0.5f;
|
||||
float end_time = j * 0.5f;
|
||||
|
||||
// 计算结束时间(第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)
|
||||
// 跨天处理:24.0显示为0.0
|
||||
if (end_time == 24.0f)
|
||||
{
|
||||
sprintf(end_time, "00:00"); // 跨天显示为00:00
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(end_time, "%02d:%02d", end_hour, end_min);
|
||||
end_time = 0.0f;
|
||||
}
|
||||
|
||||
// 根据费率类型设置电费和服务费
|
||||
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)
|
||||
// 创建计费时段数组 [start_time, end_time, electricity_fee, service_fee]
|
||||
if (electricity_fee > 0 || service_fee > 0)
|
||||
{
|
||||
billing_item = cJSON_CreateObject();
|
||||
billing_item = cJSON_CreateArray();
|
||||
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_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);
|
||||
|
||||
// 调试打印
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,11 +556,12 @@ void local_on_cmd_send_start_charging(uint8_t stake_index, uint8_t gun_id)
|
||||
str = cJSON_Print(root);
|
||||
if (str != NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Send start command JSON: %s\r\n", str);
|
||||
#endif
|
||||
// #ifdef DEBUG
|
||||
// printf("Send start command JSON: %s\r\n", str);
|
||||
// #endif
|
||||
|
||||
udp_send_response(stake_index, str, strlen(str));
|
||||
|
||||
free(str);
|
||||
}
|
||||
else
|
||||
@@ -498,3 +573,221 @@ void local_on_cmd_send_start_charging(uint8_t stake_index, uint8_t gun_id)
|
||||
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)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return;
|
||||
// 处理上电指令
|
||||
if (strcmp(cmd, "online") == 0)
|
||||
{
|
||||
printf("南向:收到电桩 %d 上电指令\r\n", id);
|
||||
local_on_cmd_callback_power_on(id, json_pack);
|
||||
}
|
||||
// 处理心跳指令
|
||||
else if (strcmp(cmd, "heartbeat") == 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将16字节的交易序列号转换为32位16进制字符串
|
||||
* @param trade_serial 16字节数组
|
||||
* @param output_str 输出缓冲区(至少33字节)
|
||||
*/
|
||||
void trade_serial_to_string(uint8_t *trade_serial, char *output_str)
|
||||
{
|
||||
if (trade_serial == NULL || output_str == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
sprintf(&output_str[i * 2], "%02X", trade_serial[i]);
|
||||
}
|
||||
output_str[32] = '\0';
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
uint8_t SETP = 0;
|
||||
|
||||
void YkcTask_Function(void const *argument)
|
||||
{
|
||||
init_chargers(); /* 初始化桩结构体*/
|
||||
@@ -41,10 +40,10 @@ void YkcTask_Function(void const *argument)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
|
||||
if (g_charger_manager.charger_piles[1 - 1].is_udp_online)
|
||||
// 等待桩上电
|
||||
if (!g_charger_manager.charger_piles[1 - 1].is_udp_online)
|
||||
{
|
||||
uint8_t open_cmd[] = { 0x55, 0xAA, 0x3, 0x01, 0x01, 0xAA, 0x55};
|
||||
uint8_t open_cmd[] = {0x55, 0xAA, 0x3, 0x01, 0x01, 0xAA, 0x55};
|
||||
Air724_Message_Send(open_cmd, sizeof(open_cmd));
|
||||
osDelay(3000);
|
||||
SETP = 1;
|
||||
@@ -55,36 +54,40 @@ void YkcTask_Function(void const *argument)
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user