forked from gary/BCU
2
0
Fork 0
This commit is contained in:
Carl 2025-08-06 13:38:43 +08:00
parent 894f88b9a8
commit 2e7d11c6a8
9 changed files with 6661 additions and 7928 deletions

View File

@ -6,6 +6,110 @@
******************************************************************************/
#include "task_register.h"
#define MQTT_TOPIC_PREFIX "bluesun/bms/period/"
// 字符集0-9 + a-z + A-Z共62个字符
const char CHAR_SET[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#define CHAR_COUNT 62 // 字符总数
/**
* STM32F407ZGTx的唯一设备标识符(UID)
* @param uid 12
*/
void GetUniqueID(uint8_t *uid) {
// STM32F4系列的96位UID存储地址
uint32_t *uid_addr = (uint32_t *)0x1FFFF7E8;
// 读取3个32位值共12字节
// 高32位
uid[0] = (uint8_t)(uid_addr[0] >> 24);
uid[1] = (uint8_t)(uid_addr[0] >> 16);
uid[2] = (uint8_t)(uid_addr[0] >> 8);
uid[3] = (uint8_t)(uid_addr[0]);
// 中32位
uid[4] = (uint8_t)(uid_addr[1] >> 24);
uid[5] = (uint8_t)(uid_addr[1] >> 16);
uid[6] = (uint8_t)(uid_addr[1] >> 8);
uid[7] = (uint8_t)(uid_addr[1]);
// 低32位
uid[8] = (uint8_t)(uid_addr[2] >> 24);
uid[9] = (uint8_t)(uid_addr[2] >> 16);
uid[10] = (uint8_t)(uid_addr[2] >> 8);
uid[11] = (uint8_t)(uid_addr[2]);
}
/**
* 32CRC
* @param crc CRC值
* @param buf
* @param len
* @return CRC值
*/
static uint32_t crc32(uint32_t crc, const uint8_t *buf, uint32_t len) {
crc = ~crc;
while (len--) {
crc ^= *buf++;
for (int i = 0; i < 8; i++) {
crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320 : 0);
}
}
return ~crc;
}
/**
* 12UID转换为16字符唯一SN
* @param uid GetUniqueID获取的12字节数组
* @param sn 16SN缓冲区17
*/
void UIDTo16CharSN(const uint8_t *uid, char *sn) {
// 1. 对UID进行多段哈希计算增强随机性
uint32_t hash[4] = {0};
// 分块处理UID生成4个哈希值
hash[0] = crc32(0x5A5A5A5A, &uid[0], 3); // 处理前3字节
hash[1] = crc32(0xA5A5A5A5, &uid[3], 3); // 处理中间3字节
hash[2] = crc32(0x3C3C3C3C, &uid[6], 3); // 处理后3字节
hash[3] = crc32(0xC3C3C3C3, uid, 12); // 处理全部12字节
// 2. 生成16个字符
for (int i = 0; i < 16; i++) {
// 轮询使用4个哈希值增加多样性
uint32_t current_hash = hash[i % 4];
// 使用质数作为位移量,避免规律性
uint8_t shift = (i * 13) % 24; // 13是质数增强分散性
uint32_t fragment = (current_hash >> shift) & 0x3F; // 取6位值(0-63)
// 确保索引在0-61范围内62个字符
uint8_t char_index = fragment % CHAR_COUNT;
// 映射到字符集
sn[i] = CHAR_SET[char_index];
}
// 3. 添加字符串结束符
sn[16] = '\0';
}
/**
* 16SN的完整流程
* @param sn 17
* @return 0
*/
uint8_t GenerateDeviceSN(char *sn) {
if (sn == NULL) return 1;
uint8_t uid[12];
GetUniqueID(uid); // 获取STM32F407的UID
UIDTo16CharSN(uid, sn); // 转换为16字符SN
return 0;
}
char deviceSN[17];
char mqtt_topic_period[42];
task_array_t tcp_server_task[W5500_MODBUS_NUM];// __attribute__((section (".CCM_RAM")));
//OS_STK tcp_server_stk[W5500_MODBUS_NUM][300];
@ -203,6 +307,12 @@ void poll_10ms_task_init(void)
void poll_mqtt_init(void)
{
if (GenerateDeviceSN(deviceSN) != 0)
{
strcpy(deviceSN, "1234567812345678");
}
snprintf(mqtt_topic_period, sizeof(mqtt_topic_period), "%s%s", MQTT_TOPIC_PREFIX, deviceSN);
static uint16_t qfc41d_init_count = 0;
while (drv_qfc41d_init() && qfc41d_init_count < 2)

View File

@ -48,6 +48,7 @@ extern "C" {
#include "bmu_manager.h"
#include "bmu_adbms1818.h"
#include "protocol_comm.h"
#include <string.h>
typedef void (*SN_BMS_INIT_CALL)(uint32_t base_time);
int sn_bms_init(SN_BMS_INIT_CALL call);

View File

@ -50,7 +50,7 @@
<InvalidFlash>1</InvalidFlash>
</TargetStatus>
<OutputDirectory>.\Objects\</OutputDirectory>
<OutputName>BCU15</OutputName>
<OutputName>BCU17</OutputName>
<CreateExecutable>1</CreateExecutable>
<CreateLib>0</CreateLib>
<CreateHexFile>1</CreateHexFile>
@ -83,7 +83,7 @@
<AfterMake>
<RunUserProg1>1</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>D:\CodeHvStack\BCU\app\stm32fxxx_app\hex2bin.exe D:\CodeHvStack\BCU\app\stm32fxxx_app\prj\Objects\BCU15.hex</UserProg1Name>
<UserProg1Name>D:\CodeHvStack\BCU\app\stm32fxxx_app\hex2bin.exe D:\CodeHvStack\BCU\app\stm32fxxx_app\prj\Objects\BCU17.hex</UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,8 @@
//#include "bms_app.h"
#include "ucos_ii.h"
extern char deviceSN[17];
uint16_t snModbusRegs[8];
struct{
uint16_t req_bcu_num;//请求单体信息分簇地址
@ -36,8 +38,26 @@ struct{
struct tm telnet_time;
void InitSNModbusRegs(void)
{
// 确保字符串长度正确
if (strlen(deviceSN) != 16) {
// 错误处理:使用默认值填充
strcpy(deviceSN, "1234567812345678");
}
// 拆分16位字符串到8个16位寄存器
for (int i = 0; i < 8; i++) {
// 每个寄存器存储2个字符高8位 + 低8位
uint8_t highByte = (uint8_t)deviceSN[2*i]; // 第2i个字符
uint8_t lowByte = (uint8_t)deviceSN[2*i + 1]; // 第2i+1个字符
snModbusRegs[i] = (highByte << 8) | lowByte; // 组合为16位值
}
}
uint16_t bcu_total_msg_fill(uint16_t start_addr, uint8_t reg_num, uint8_t *buf)
{
InitSNModbusRegs();
// static uint16_t test99 = 0;
uint16_t index, data, i;
uint32_t addr = 0,temp_soe;
@ -327,6 +347,15 @@ uint16_t bcu_total_msg_fill(uint16_t start_addr, uint8_t reg_num, uint8_t *buf)
//120 休眠状态
READ_FC03_F04_ITEM(120,bms_get_signal(kSignalIdx_StandbySleep))
READ_FC03_F04_ITEM(121, snModbusRegs[0]) // 对应deviceSN[0]和[1]
READ_FC03_F04_ITEM(122, snModbusRegs[1]) // 对应deviceSN[2]和[3]
READ_FC03_F04_ITEM(123, snModbusRegs[2]) // 对应deviceSN[4]和[5]
READ_FC03_F04_ITEM(124, snModbusRegs[3]) // 对应deviceSN[6]和[7]
READ_FC03_F04_ITEM(125, snModbusRegs[4]) // 对应deviceSN[8]和[9]
READ_FC03_F04_ITEM(126, snModbusRegs[5]) // 对应deviceSN[10]和[11]
READ_FC03_F04_ITEM(127, snModbusRegs[6]) // 对应deviceSN[12]和[13]
READ_FC03_F04_ITEM(128, snModbusRegs[7]) // 对应deviceSN[14]和[15]
READ_FC03_F04_END();
WRITE_BT_INT16U(buf, addr, data);

View File

@ -23,6 +23,8 @@
#include "protocol_comm.h"
#include "drv_qfc41d.h"
extern char deviceSN[17];
uint32_t bms_get_baseInfo(uint16_t input)
{
uint32_t tmp;
@ -953,7 +955,7 @@ void protocol_build_json(uint16_t groupId, uint32_t time)
cJSON_AddStringToObject(deviceObj, "devType", "4");
cJSON_AddStringToObject(deviceObj, "devName", "BCU");
cJSON_AddStringToObject(deviceObj, "devId", "001");
cJSON_AddStringToObject(deviceObj, "sn", "SN11223344");
cJSON_AddStringToObject(deviceObj, "sn", deviceSN);
cJSON_AddNumberToObject(deviceObj, "currentPack", groupId);
cJSON_AddNumberToObject(deviceObj, "totalPack", 16);
@ -1013,7 +1015,7 @@ void protocol_build_volt_json(uint8_t i, uint32_t time)
cJSON_AddStringToObject(deviceObj, "devType", "4");
cJSON_AddStringToObject(deviceObj, "devName", "BCU");
cJSON_AddStringToObject(deviceObj, "devId", "001");
cJSON_AddStringToObject(deviceObj, "sn", "SN11223344");
cJSON_AddStringToObject(deviceObj, "sn", deviceSN);
cJSON_AddNumberToObject(deviceObj, "currentPack", groupId); // 当前包数
cJSON_AddNumberToObject(deviceObj, "totalPack", 16); // 总包数
@ -1071,7 +1073,7 @@ void protocol_build_temp_json(uint8_t i, uint32_t time)
cJSON_AddStringToObject(deviceObj, "devType", "4");
cJSON_AddStringToObject(deviceObj, "devName", "BCU");
cJSON_AddStringToObject(deviceObj, "devId", "001");
cJSON_AddStringToObject(deviceObj, "sn", "SN11223344");
cJSON_AddStringToObject(deviceObj, "sn", deviceSN);
cJSON_AddNumberToObject(deviceObj, "currentPack", groupId); // 当前包数
cJSON_AddNumberToObject(deviceObj, "totalPack", 16); // 总包数
@ -1173,12 +1175,21 @@ void mqtt_publish_bms_data(uint32_t basetime)
// drv_mqtt_publish_no_respose("1", 1);
// }
// 定期检测是否依然订阅主题
if (sub_read_control_flag == 1)
if (sub_read_control_flag == 1)
{
if (drv_at_send_cmd("AT+QMTSUB=0,1,\"bluesun/bms/control/11223344\",0,\"bluesun/bms/read/11223344\",0", "OK", WIFI_TIMEOUT))
char control_topic[44];
char read_topic[44];
char mqtt_sub_cmd[128];
snprintf(control_topic, sizeof(control_topic), "bluesun/bms/control/%s", deviceSN);
snprintf(read_topic, sizeof(read_topic), "bluesun/bms/read/%s", deviceSN);
snprintf(mqtt_sub_cmd, sizeof(mqtt_sub_cmd), "AT+QMTSUB=0,1,\"%s\",0,\"%s\",0", control_topic, read_topic);
// 发送命令
if (drv_at_send_cmd(mqtt_sub_cmd, "OK", WIFI_TIMEOUT))
{
sub_read_control_flag = 0;
sub_read_control_flag = 0; // 成功订阅后清除标志
}
}

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,8 @@
#define UART2_BAUDRATE 115200
#define MAX_RETRY 3
extern char deviceSN[17];
//4G实例化
static uint8_t sim_rec_buf[MAX_RECV_LEN] = {0};
LTE4G_STATIC_INIT(sim_item, 1, 0, 0, 1024,sim_rec_buf);
@ -107,14 +109,12 @@ void drv_eg25g_init2(void)
#define MQTT_CLIENT_ID "fc41d_client" // 客户端 ID
#define MQTT_USER "user" // MQTT 用户名
#define MQTT_PASSWORD "password" // MQTT 密码
#define MQTT_TOPIC "bluesun/bms/period/11223344" // ¶©ÔÄ/·¢²¼µÄÖ÷Ìâ
#define MQTT_MESSAGE "Hello from FC41D!" // 发送的消息
#define WIFI_TIMEOUT 1000
// 连接 MQTT 服务器
uint8_t drv_mqtt_connect()
{
//1、设置 MQTT 协议的版本号为 V4
// snprintf(cmd, sizeof(cmd), "AT+QMTCFG=\"version\",1,4");
// if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
@ -132,19 +132,31 @@ uint8_t drv_mqtt_connect()
// KIT_PRINTF("Failed to set MQTT server!\r\n");
return 1;
}
char mqtt_conn_cmd[52]; // 缓冲区足够存放完整 AT 指令
snprintf(mqtt_conn_cmd, sizeof(mqtt_conn_cmd), "AT+QMTCONN=0,\"BCU%s\"", deviceSN);
// 发送命令
if (!drv_at_send_cmd(mqtt_conn_cmd, "OK", WIFI_TIMEOUT))
{
// 处理错误
}
//2、MQTT 客户端与服务器之间建立 MQTT 连接 AT+QMTCONN=<clientID>,<client_identity>,<username>,<password>
//snprintf(cmd, sizeof(cmd), "AT+QMTCONN=0,%s,%s,%s",MQTT_CLIENT_ID,MQTT_USER, MQTT_PASSWORD);
if (!drv_at_send_cmd("AT+QMTCONN=0,\"clientBCUwifi11223344\"", "OK", WIFI_TIMEOUT))
{
// KIT_PRINTF("Failed to set MQTT client credentials!\r\n");
}
if (!drv_at_send_cmd("AT+QMTSUB=0,1,\"bluesun/bms/control/11223344\",0,\"bluesun/bms/read/11223344\",0", "OK", WIFI_TIMEOUT))
{
// KIT_PRINTF("Failed to set MQTT client credentials!\r\n");
}
char control_topic[42], read_topic[42], mqtt_sub_cmd[128];
snprintf(control_topic, sizeof(control_topic), "bluesun/bms/control/%s", deviceSN);
snprintf(read_topic, sizeof(read_topic), "bluesun/bms/read/%s", deviceSN);
// 构造 AT+QMTSUB 命令
snprintf(mqtt_sub_cmd, sizeof(mqtt_sub_cmd), "AT+QMTSUB=0,1,\"%s\",0,\"%s\",0", control_topic, read_topic);
// 发送 AT+QMTSUB
if (!drv_at_send_cmd(mqtt_sub_cmd, "OK", WIFI_TIMEOUT))
{
// 处理错误
}
//
// if (!drv_at_send_cmd("AT+QMTSUB=1,1,\"bluesun/bms/read/11223344\",0,\"bluesun/bms/control/11223344\",0", "OK", WIFI_TIMEOUT))
// {

View File

@ -21,6 +21,9 @@ volatile uint8_t dma_tx_busy = 0;
uint8_t dma_tx_buffer[2][TX_DMA_BUFFER_SIZE] __attribute__((section(".sram2")));
volatile uint8_t current_buffer = 0; // 0表示正常缓冲区1表示高优先级缓冲区
extern char deviceSN[17];
extern char mqtt_topic_period[42];
//定义
WifiBleItem qfc41dItem = {
.dev = QFC41D_UART_PORT,
@ -354,16 +357,19 @@ static uint8_t drv_wifi_init()
uint8_t drv_ble_init()
{
char at_cmd[42];
snprintf(at_cmd, sizeof(at_cmd), "AT+QBLENAME=BSM%s", deviceSN);
if (!drv_at_send_cmd("AT+QBLEINIT=3", "OK", WIFI_TIMEOUT))
{
return 1;
}
//设置wifi名称必须以BSM开头后缀可以加sn码
if (!drv_at_send_cmd("AT+QBLENAME=BSM11223344", "OK", WIFI_TIMEOUT))
{
return 1;
}
if (!drv_at_send_cmd(at_cmd, "OK", WIFI_TIMEOUT))
{
return 1;
}
return 0;
}
@ -392,21 +398,20 @@ uint8_t drv_qfc41d_init(void)
#define MQTT_PORT 3011 // MQTT 端口
#define MQTT_CLIENT_ID "fc41d_client" // 客户端 ID
#define MQTT_USER "user" // MQTT 用户名
#define MQTT_PASSWORD "password" // MQTT ÃÜÂë
#define MQTT_TOPIC "bluesun/bms/period/11223344"
#define MQTT_TOPIC_control "bluesun/bms/control/reply/11223344"
#define MQTT_TOPIC_read "bluesun/bms/read/reply/11223344"
#define MQTT_PASSWORD "password" // MQTT ÃÜÂë
#define MQTT_TOPIC_CONTROL_PREFIX "bluesun/bms/control/reply/"
#define MQTT_TOPIC_READ_PREFIX "bluesun/bms/read/reply/"
static uint8_t drv_mqtt_subscribe()
{
snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=0,1,\"%s\",2", MQTT_TOPIC);
snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=0,1,\"%s\",2", mqtt_topic_period);
drv_wireless_send_string(cmd);
return 0;
}
uint8_t drv_mqtt_publish(char* str,uint16_t length)
{
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,2,0,%s,%d,%s",MQTT_TOPIC, length, str);
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,2,0,%s,%d,%s",mqtt_topic_period, length, str);
if (!drv_at_send_cmd(cmd, "OK\0", WIFI_TIMEOUT))
{
return 1;
@ -418,22 +423,27 @@ uint8_t drv_mqtt_publish(char* str,uint16_t length)
uint8_t drv_mqtt_publish_no_respose(char* str,uint16_t length)
{
// snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,%s,%d,%s",MQTT_TOPIC, length, str);
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC, length, str);
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", mqtt_topic_period, length, str);
// drv_wireless_send_string(cmd); // 未使用DMA
drv_wireless_send_string_dma(cmd); // 使用DMA
return 0;
}
uint8_t drv_mqtt_publish_control_no_respose(char* str,uint16_t length)
{
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC_control, length, str);
drv_wireless_send_string_dma_high_priority(cmd);
uint8_t drv_mqtt_publish_control_no_respose(char* str, uint16_t length) {
char full_topic[44];
snprintf(full_topic, sizeof(full_topic), "%s%s", MQTT_TOPIC_CONTROL_PREFIX, deviceSN);
// ¹¹Ôì AT ÃüÁî
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", full_topic, length, str);
drv_wireless_send_string_dma_high_priority(cmd);
return 0;
}
uint8_t drv_mqtt_publish_read_no_respose(char* str,uint16_t length)
{
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC_read, length, str);
drv_wireless_send_string_dma_high_priority(cmd);
uint8_t drv_mqtt_publish_read_no_respose(char* str, uint16_t length) {
char full_topic[44];
snprintf(full_topic, sizeof(full_topic), "%s%s", MQTT_TOPIC_READ_PREFIX, deviceSN);
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", full_topic, length, str);
drv_wireless_send_string_dma_high_priority(cmd);
return 0;
}