1、封装 usr_le_code 为静态库,并增加 Release 客户包自动生成工具
2、将 BLE 协议实现收敛为 libusr_le_code.a + 公开头文件,应用侧通过 usr_le_api / usr_le_product 对接;新增 package_release.py,按 version.txt 3、生成去除协议源码的客户交付包,开发工程继续保留完整源码。
This commit is contained in:
@@ -81,6 +81,12 @@ $RECYCLE.BIN/
|
|||||||
*.orig
|
*.orig
|
||||||
*.rej
|
*.rej
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Release 交付产物(由 tools/package_release.py 生成,勿提交)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
release/
|
||||||
|
Release_Project_*/
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# 注意:以下内容请保留上传,不要忽略
|
# 注意:以下内容请保留上传,不要忽略
|
||||||
# - cpu/br28/liba/*.a SDK 预编译库
|
# - cpu/br28/liba/*.a SDK 预编译库
|
||||||
|
|||||||
+3
-18
@@ -257,6 +257,7 @@
|
|||||||
<Add option="cpu/br28/liba/libllns.a" />
|
<Add option="cpu/br28/liba/libllns.a" />
|
||||||
<Add option="cpu/br28/liba/libkwscommon.a" />
|
<Add option="cpu/br28/liba/libkwscommon.a" />
|
||||||
<Add option="apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a" />
|
<Add option="apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a" />
|
||||||
|
<Add option="apps/usr_le_code/lib/libusr_le_code.a" />
|
||||||
<Add option="cpu/br28/liba/lib_icsd_adt.a" />
|
<Add option="cpu/br28/liba/lib_icsd_adt.a" />
|
||||||
<Add option="cpu/br28/liba/lib_diafx.a" />
|
<Add option="cpu/br28/liba/lib_diafx.a" />
|
||||||
<Add option="cpu/br28/liba/libFFT_pi32v2_OnChip.a" />
|
<Add option="cpu/br28/liba/libFFT_pi32v2_OnChip.a" />
|
||||||
@@ -777,29 +778,13 @@
|
|||||||
<Unit filename="apps/usr_jb_proto/usr_jb_main.c">
|
<Unit filename="apps/usr_jb_proto/usr_jb_main.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
<Unit filename="apps/usr_le_code/ble_proto.c">
|
|
||||||
<Option compilerVar="CC" />
|
|
||||||
</Unit>
|
|
||||||
<Unit filename="apps/usr_le_code/ble_proto.h" />
|
<Unit filename="apps/usr_le_code/ble_proto.h" />
|
||||||
<Unit filename="apps/usr_le_code/bleproto.c">
|
|
||||||
<Option compilerVar="CC" />
|
|
||||||
</Unit>
|
|
||||||
<Unit filename="apps/usr_le_code/bleproto.h" />
|
<Unit filename="apps/usr_le_code/bleproto.h" />
|
||||||
<Unit filename="apps/usr_le_code/bleproto_api.h" />
|
<Unit filename="apps/usr_le_code/bleproto_api.h" />
|
||||||
<Unit filename="apps/usr_le_code/bleproto_packer.c">
|
|
||||||
<Option compilerVar="CC" />
|
|
||||||
</Unit>
|
|
||||||
<Unit filename="apps/usr_le_code/bleproto_packer.h" />
|
<Unit filename="apps/usr_le_code/bleproto_packer.h" />
|
||||||
<Unit filename="apps/usr_le_code/thirdpart/mjson/mjson.c">
|
|
||||||
<Option compilerVar="CC" />
|
|
||||||
</Unit>
|
|
||||||
<Unit filename="apps/usr_le_code/thirdpart/mjson/mjson.h" />
|
<Unit filename="apps/usr_le_code/thirdpart/mjson/mjson.h" />
|
||||||
<Unit filename="apps/usr_le_code/usr_le_adv.c">
|
<Unit filename="apps/usr_le_code/usr_le_api.h" />
|
||||||
<Option compilerVar="CC" />
|
<Unit filename="apps/usr_le_code/usr_le_product.h" />
|
||||||
</Unit>
|
|
||||||
<Unit filename="apps/usr_le_code/usr_le_recieve.c">
|
|
||||||
<Option compilerVar="CC" />
|
|
||||||
</Unit>
|
|
||||||
<Unit filename="cpu/br28/adc_api.c">
|
<Unit filename="cpu/br28/adc_api.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
|
|||||||
@@ -245,6 +245,11 @@ INCLUDES := \
|
|||||||
-Iinclude_lib/media/aispeech/enc/include \
|
-Iinclude_lib/media/aispeech/enc/include \
|
||||||
-Icpu/br28/audio_hearing \
|
-Icpu/br28/audio_hearing \
|
||||||
-Iinclude_lib/media/cvp \
|
-Iinclude_lib/media/cvp \
|
||||||
|
-Iapps/usr_le_code \
|
||||||
|
-Iapps/usr_le_code/thirdpart \
|
||||||
|
-Iapps/usr_le_code/thirdpart/mjson \
|
||||||
|
-Iapps/usr_jb_proto/Protocol \
|
||||||
|
-Iapps/usr_jb_proto/Utils \
|
||||||
-I$(SYS_INC_DIR) \
|
-I$(SYS_INC_DIR) \
|
||||||
|
|
||||||
|
|
||||||
@@ -479,6 +484,7 @@ c_SRC_FILES := \
|
|||||||
apps/earphone/bt_emitter.c \
|
apps/earphone/bt_emitter.c \
|
||||||
apps/earphone/bt_tws.c \
|
apps/earphone/bt_tws.c \
|
||||||
apps/earphone/default_event_handler.c \
|
apps/earphone/default_event_handler.c \
|
||||||
|
apps/earphone/dual_update_demo.c \
|
||||||
apps/earphone/earphone.c \
|
apps/earphone/earphone.c \
|
||||||
apps/earphone/eartch_event_deal.c \
|
apps/earphone/eartch_event_deal.c \
|
||||||
apps/earphone/font/fontinit.c \
|
apps/earphone/font/fontinit.c \
|
||||||
@@ -608,6 +614,24 @@ c_SRC_FILES := \
|
|||||||
cpu/br28/tws_audio.c \
|
cpu/br28/tws_audio.c \
|
||||||
cpu/br28/uart_dev.c \
|
cpu/br28/uart_dev.c \
|
||||||
cpu/br28/umidigi_chargestore.c \
|
cpu/br28/umidigi_chargestore.c \
|
||||||
|
apps/usr_jb_proto/Protocol/jb_product.c \
|
||||||
|
apps/usr_jb_proto/Protocol/jb_protocol.c \
|
||||||
|
apps/usr_jb_proto/Utils/jb_common.c \
|
||||||
|
apps/usr_jb_proto/Utils/jb_ringbuffer.c \
|
||||||
|
apps/usr_jb_proto/usr_jb_main.c \
|
||||||
|
|
||||||
|
|
||||||
|
# usr_le_code 静态库(协议编解码 + 广播/收发)
|
||||||
|
USR_LE_LIB := apps/usr_le_code/lib/libusr_le_code.a
|
||||||
|
USR_LE_SRC_FILES := \
|
||||||
|
apps/usr_le_code/ble_proto.c \
|
||||||
|
apps/usr_le_code/bleproto.c \
|
||||||
|
apps/usr_le_code/bleproto_packer.c \
|
||||||
|
apps/usr_le_code/thirdpart/mjson/mjson.c \
|
||||||
|
apps/usr_le_code/usr_le_adv.c \
|
||||||
|
apps/usr_le_code/usr_le_recieve.c
|
||||||
|
|
||||||
|
USR_LE_OBJS := $(addprefix $(BUILD_DIR)/, $(USR_LE_SRC_FILES:%.c=%.c.o))
|
||||||
|
|
||||||
|
|
||||||
# 需要编译的 .S 文件
|
# 需要编译的 .S 文件
|
||||||
@@ -711,6 +735,7 @@ LFLAGS := \
|
|||||||
cpu/br28/liba/libllns.a \
|
cpu/br28/liba/libllns.a \
|
||||||
cpu/br28/liba/libkwscommon.a \
|
cpu/br28/liba/libkwscommon.a \
|
||||||
apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a \
|
apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a \
|
||||||
|
apps/usr_le_code/lib/libusr_le_code.a \
|
||||||
cpu/br28/liba/lib_icsd_adt.a \
|
cpu/br28/liba/lib_icsd_adt.a \
|
||||||
cpu/br28/liba/lib_diafx.a \
|
cpu/br28/liba/lib_diafx.a \
|
||||||
cpu/br28/liba/libFFT_pi32v2_OnChip.a \
|
cpu/br28/liba/libFFT_pi32v2_OnChip.a \
|
||||||
@@ -769,16 +794,25 @@ LINK_AT ?= 1
|
|||||||
# 表示下面的不是一个文件的名字,无论是否存在 all, clean, pre_build 这样的文件
|
# 表示下面的不是一个文件的名字,无论是否存在 all, clean, pre_build 这样的文件
|
||||||
# 还是要执行命令
|
# 还是要执行命令
|
||||||
# see: https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
# see: https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
||||||
.PHONY: all clean pre_build
|
.PHONY: all clean pre_build lib_usr_le
|
||||||
|
|
||||||
# 不要使用 make 预设置的规则
|
# 不要使用 make 预设置的规则
|
||||||
# see: https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html
|
# see: https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
|
||||||
all: pre_build $(OUT_ELF)
|
all: pre_build $(USR_LE_LIB) $(OUT_ELF)
|
||||||
$(info +POST-BUILD)
|
$(info +POST-BUILD)
|
||||||
$(QUITE) $(RUN_POST_SCRIPT) sdk
|
$(QUITE) $(RUN_POST_SCRIPT) sdk
|
||||||
|
|
||||||
|
# 单独编译 usr_le_code 静态库: make lib_usr_le
|
||||||
|
lib_usr_le: $(USR_LE_LIB)
|
||||||
|
|
||||||
|
$(USR_LE_LIB): $(USR_LE_OBJS)
|
||||||
|
$(info +AR $@)
|
||||||
|
$(shell $(MKDIR) $(@D))
|
||||||
|
$(QUITE) $(RM) $@
|
||||||
|
$(QUITE) $(AR) rcs $@ $(USR_LE_OBJS)
|
||||||
|
|
||||||
pre_build:
|
pre_build:
|
||||||
$(info +PRE-BUILD)
|
$(info +PRE-BUILD)
|
||||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br28/sdk_used_list.c -o cpu/br28/sdk_used_list.used
|
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br28/sdk_used_list.c -o cpu/br28/sdk_used_list.used
|
||||||
@@ -794,13 +828,13 @@ clean:
|
|||||||
|
|
||||||
|
|
||||||
ifeq ($(LINK_AT), 1)
|
ifeq ($(LINK_AT), 1)
|
||||||
$(OUT_ELF): $(OBJS)
|
$(OUT_ELF): $(OBJS) $(USR_LE_LIB)
|
||||||
$(info +LINK $@)
|
$(info +LINK $@)
|
||||||
$(shell $(MKDIR) $(@D))
|
$(shell $(MKDIR) $(@D))
|
||||||
$(file >$(OBJ_FILE), $(OBJS))
|
$(file >$(OBJ_FILE), $(OBJS))
|
||||||
$(QUITE) $(LD) -o $(OUT_ELF) @$(OBJ_FILE) $(LFLAGS) $(LIBPATHS) $(LIBS)
|
$(QUITE) $(LD) -o $(OUT_ELF) @$(OBJ_FILE) $(LFLAGS) $(LIBPATHS) $(LIBS)
|
||||||
else
|
else
|
||||||
$(OUT_ELF): $(OBJS)
|
$(OUT_ELF): $(OBJS) $(USR_LE_LIB)
|
||||||
$(info +LINK $@)
|
$(info +LINK $@)
|
||||||
$(shell $(MKDIR) $(@D))
|
$(shell $(MKDIR) $(@D))
|
||||||
$(QUITE) $(LD) -o $(OUT_ELF) $(OBJS) $(LFLAGS) $(LIBPATHS) $(LIBS)
|
$(QUITE) $(LD) -o $(OUT_ELF) $(OBJS) $(LFLAGS) $(LIBPATHS) $(LIBS)
|
||||||
|
|||||||
@@ -57,9 +57,6 @@
|
|||||||
#include "chgbox_box.h"
|
#include "chgbox_box.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void usr_ble_adv_updata();
|
|
||||||
|
|
||||||
|
|
||||||
extern void usr_le_data_recieve(u8* data,u16 len);
|
extern void usr_le_data_recieve(u8* data,u16 len);
|
||||||
extern void usr_ble_adv_init();
|
extern void usr_ble_adv_init();
|
||||||
#if 1
|
#if 1
|
||||||
@@ -934,7 +931,6 @@ void ble_trans_module_enable(u8 flag)
|
|||||||
ble_module_enable(flag);
|
ble_module_enable(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void usr_ble_adv_init();
|
|
||||||
void bt_ble_init(void)
|
void bt_ble_init(void)
|
||||||
{
|
{
|
||||||
log_info("***** ble_init******\n");
|
log_info("***** ble_init******\n");
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#ifndef APP_MAIN_H
|
#ifndef APP_MAIN_H
|
||||||
#define APP_MAIN_H
|
#define APP_MAIN_H
|
||||||
#include "bleproto.h"
|
|
||||||
#include "bleproto_api.h"
|
|
||||||
|
|
||||||
typedef struct _USR_VAR {
|
typedef struct _USR_VAR {
|
||||||
u8 usr_start_write_flash ;
|
u8 usr_start_write_flash ;
|
||||||
@@ -131,7 +129,6 @@ typedef struct _BT_USER_COMM_VAR {
|
|||||||
extern APP_VAR app_var;
|
extern APP_VAR app_var;
|
||||||
extern USR_VAR usr_var;
|
extern USR_VAR usr_var;
|
||||||
extern BT_USER_PRIV_VAR bt_user_priv_var;
|
extern BT_USER_PRIV_VAR bt_user_priv_var;
|
||||||
extern bleproto_authsetup_req_t usr_auth_data;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,6 @@
|
|||||||
/* #define LOG_DUMP_ENABLE */
|
/* #define LOG_DUMP_ENABLE */
|
||||||
#define LOG_CLI_ENABLE
|
#define LOG_CLI_ENABLE
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "bleproto.h"
|
|
||||||
#include "bleproto_api.h"
|
|
||||||
|
|
||||||
#define POWER_OFF_CNT 10
|
#define POWER_OFF_CNT 10
|
||||||
|
|
||||||
@@ -46,7 +44,6 @@ extern bool get_tws_sibling_connect_state(void);
|
|||||||
extern int bt_get_low_latency_mode();
|
extern int bt_get_low_latency_mode();
|
||||||
extern void bt_set_low_latency_mode(int enable);
|
extern void bt_set_low_latency_mode(int enable);
|
||||||
|
|
||||||
extern void usr_ble_adv_init();
|
|
||||||
void audio_aec_pitch_change_ctrl();
|
void audio_aec_pitch_change_ctrl();
|
||||||
void audio_surround_voice_ctrl();
|
void audio_surround_voice_ctrl();
|
||||||
extern void start_streamer_test(void);
|
extern void start_streamer_test(void);
|
||||||
|
|||||||
@@ -34,10 +34,13 @@
|
|||||||
#define REPORT_DEBOUNCE 2000 /* 变化上报防抖时间(ms) */
|
#define REPORT_DEBOUNCE 2000 /* 变化上报防抖时间(ms) */
|
||||||
#define REPORT_PERIOD 600000 /* 定时全量上报周期(ms) */
|
#define REPORT_PERIOD 600000 /* 定时全量上报周期(ms) */
|
||||||
|
|
||||||
/* Device identity: change these values for the target product. */
|
/* Device identity: change these values for the target product.
|
||||||
|
* JB_CATEGORY_CODE: 必须 4 字符 ASCII,供 BLE 广播 prodcode 使用
|
||||||
|
* JB_PRODUCT_CODE : 必须 6 字符 ASCII,供 BLE 广播 pcode 使用
|
||||||
|
*/
|
||||||
#define JB_PROTOCOL_VERSION 0x0100 /* V1.0 */
|
#define JB_PROTOCOL_VERSION 0x0100 /* V1.0 */
|
||||||
#define JB_CATEGORY_CODE "CBXX"
|
#define JB_CATEGORY_CODE "CBC0"
|
||||||
#define JB_PRODUCT_CODE "CBXX"
|
#define JB_PRODUCT_CODE "PICBC0"
|
||||||
#define JB_DEVICE_SN 0x00
|
#define JB_DEVICE_SN 0x00
|
||||||
#define JB_DEVICE_CAPABILITY 0ULL
|
#define JB_DEVICE_CAPABILITY 0ULL
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,18 @@
|
|||||||
#include "jb_product.h"
|
#include "jb_product.h"
|
||||||
#include "jb_ringbuffer.h"
|
#include "jb_ringbuffer.h"
|
||||||
#include "jb_common.h"
|
#include "jb_common.h"
|
||||||
|
#include "usr_le_product.h"
|
||||||
|
|
||||||
|
/* 向 usr_le_code 库提供产品身份(换产品只改 jb_protocol.h 宏即可) */
|
||||||
|
const uint8_t g_usr_le_prodcode[USR_LE_PRODCODE_LEN] = {
|
||||||
|
JB_CATEGORY_CODE[0], JB_CATEGORY_CODE[1],
|
||||||
|
JB_CATEGORY_CODE[2], JB_CATEGORY_CODE[3]
|
||||||
|
};
|
||||||
|
const uint8_t g_usr_le_pcode[USR_LE_PCODE_LEN] = {
|
||||||
|
JB_PRODUCT_CODE[0], JB_PRODUCT_CODE[1], JB_PRODUCT_CODE[2],
|
||||||
|
JB_PRODUCT_CODE[3], JB_PRODUCT_CODE[4], JB_PRODUCT_CODE[5]
|
||||||
|
};
|
||||||
|
|
||||||
void usr_timer_1_ms();
|
void usr_timer_1_ms();
|
||||||
static int jb_timer_id=0;
|
static int jb_timer_id=0;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
REM Rebuild apps/usr_le_code/lib/libusr_le_code.a
|
||||||
|
REM Double-click this bat; window will pause so you can read the result.
|
||||||
|
|
||||||
|
cd /d "%~dp0..\.."
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [FAIL] cannot cd to project root
|
||||||
|
echo SCRIPT dir: %~dp0
|
||||||
|
goto :END
|
||||||
|
)
|
||||||
|
|
||||||
|
echo ==== build libusr_le_code.a ====
|
||||||
|
echo Project root: %CD%
|
||||||
|
echo.
|
||||||
|
|
||||||
|
SET PATH=%CD%\tools\utils;C:\JL\pi32\bin;%PATH%
|
||||||
|
|
||||||
|
where make >nul 2>&1
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [FAIL] make.exe not found
|
||||||
|
echo Check: %CD%\tools\utils\make.exe
|
||||||
|
goto :END
|
||||||
|
)
|
||||||
|
|
||||||
|
where clang.exe >nul 2>&1
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [FAIL] clang.exe not found
|
||||||
|
echo Check: C:\JL\pi32\bin\clang.exe
|
||||||
|
goto :END
|
||||||
|
)
|
||||||
|
|
||||||
|
make lib_usr_le -j %NUMBER_OF_PROCESSORS%
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo.
|
||||||
|
echo [FAIL] build libusr_le_code.a
|
||||||
|
goto :END
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
if exist "apps\usr_le_code\lib\libusr_le_code.a" (
|
||||||
|
echo [OK] apps\usr_le_code\lib\libusr_le_code.a
|
||||||
|
dir "apps\usr_le_code\lib\libusr_le_code.a"
|
||||||
|
) else (
|
||||||
|
echo [FAIL] lib file not found after build
|
||||||
|
)
|
||||||
|
|
||||||
|
:END
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
Binary file not shown.
@@ -14,8 +14,7 @@
|
|||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "bleproto.h"
|
#include "bleproto.h"
|
||||||
#include "bleproto_api.h"
|
#include "bleproto_api.h"
|
||||||
|
#include "usr_le_product.h"
|
||||||
#include "bleproto.h"
|
|
||||||
#define LOG_TAG_CONST APP
|
#define LOG_TAG_CONST APP
|
||||||
#define LOG_TAG "[APP]"
|
#define LOG_TAG "[APP]"
|
||||||
#define LOG_ERROR_ENABLE
|
#define LOG_ERROR_ENABLE
|
||||||
@@ -28,6 +27,9 @@
|
|||||||
extern u8 muti_adv_data[31];//={0};
|
extern u8 muti_adv_data[31];//={0};
|
||||||
extern u8 muti_adv_data_len;
|
extern u8 muti_adv_data_len;
|
||||||
|
|
||||||
|
/* 定义在 usr_le_recieve.c,库内共用,不对外导出 */
|
||||||
|
extern bleproto_authsetup_req_t usr_auth_data;
|
||||||
|
|
||||||
extern u8 usr_get_full();
|
extern u8 usr_get_full();
|
||||||
extern u16 usr_get_conn_service();
|
extern u16 usr_get_conn_service();
|
||||||
extern int muti_make_set_adv_data(u8* data,u8 data_len);
|
extern int muti_make_set_adv_data(u8* data,u8 data_len);
|
||||||
@@ -95,9 +97,14 @@ void usr_ble_adv_init()
|
|||||||
{
|
{
|
||||||
int8_t txpower = 0;
|
int8_t txpower = 0;
|
||||||
uint8_t manucode[BLEPROTO_ADV_TLV_LENGTH_MANUCODE] = { 0 };
|
uint8_t manucode[BLEPROTO_ADV_TLV_LENGTH_MANUCODE] = { 0 };
|
||||||
uint8_t prodcode[BLEPROTO_ADV_TLV_LENGTH_PRODCODE] = {'C', 'B', 'C', '0'};///CBP0
|
uint8_t prodcode[BLEPROTO_ADV_TLV_LENGTH_PRODCODE];
|
||||||
uint8_t gmac[6]={0};
|
uint8_t gmac[6] = {0};
|
||||||
uint8_t pcode[6]={'P','I','C','B','C','0'};
|
uint8_t pcode[BLE_PROTO_ADV_LENGTH_PCODE];
|
||||||
|
|
||||||
|
/* 产品身份由应用层 g_usr_le_* 提供(见 usr_jb_main.c) */
|
||||||
|
memcpy(prodcode, g_usr_le_prodcode, BLEPROTO_ADV_TLV_LENGTH_PRODCODE);
|
||||||
|
memcpy(pcode, g_usr_le_pcode, BLE_PROTO_ADV_LENGTH_PCODE);
|
||||||
|
|
||||||
usr_set_adv_interval(80);
|
usr_set_adv_interval(80);
|
||||||
if(usr_var.usr_ota_succ_flag)return;
|
if(usr_var.usr_ota_succ_flag)return;
|
||||||
//muti_adv_data
|
//muti_adv_data
|
||||||
@@ -214,29 +221,51 @@ void usr_soft_off()
|
|||||||
void usr_ble_adv_updata_OTA()
|
void usr_ble_adv_updata_OTA()
|
||||||
{
|
{
|
||||||
//printf("usr_ble_adv_updata\n");
|
//printf("usr_ble_adv_updata\n");
|
||||||
if(1)
|
|
||||||
{
|
|
||||||
ble_trans_module_enable(0);
|
ble_trans_module_enable(0);
|
||||||
usr_var.usr_adv_flag=0;
|
usr_var.usr_adv_flag=0;
|
||||||
|
|
||||||
#if 1
|
|
||||||
extern u8 usr_mac_addr[6];
|
extern u8 usr_mac_addr[6];
|
||||||
//u8 ble_mac[6];
|
|
||||||
extern int le_controller_set_mac(void *addr);
|
extern int le_controller_set_mac(void *addr);
|
||||||
//extern void lib_make_ble_address(u8 * ble_address, u8 * edr_address);
|
|
||||||
//bt_update_mac_addr(mac);
|
|
||||||
//lmp_hci_write_local_address(mac);
|
|
||||||
//bt_update_testbox_addr(mac);
|
|
||||||
//lib_make_ble_address(ble_mac, mac);
|
|
||||||
usr_mac_addr[0]=usr_mac_addr[0]+1;
|
usr_mac_addr[0]=usr_mac_addr[0]+1;
|
||||||
le_controller_set_mac(usr_mac_addr); //修改BLE地址
|
le_controller_set_mac(usr_mac_addr); //修改BLE地址
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
muti_make_set_adv_data_updata();
|
muti_make_set_adv_data_updata();
|
||||||
printf("###muti_adv_data = ");
|
printf("###muti_adv_data = ");
|
||||||
printf_buf(muti_adv_data,muti_adv_data_len);
|
printf_buf(muti_adv_data,muti_adv_data_len);
|
||||||
ble_trans_module_enable(1);
|
ble_trans_module_enable(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usr_ota_process()
|
||||||
|
{
|
||||||
|
static u8 cnt = 0;
|
||||||
|
if (cnt == 0)
|
||||||
|
{
|
||||||
|
ble_multi_trans_disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usr_get_conn_service() == 0)
|
||||||
|
{
|
||||||
|
cnt++;
|
||||||
|
if (cnt == 2)
|
||||||
|
{
|
||||||
|
usr_ble_adv_updata_OTA();
|
||||||
|
}
|
||||||
|
if (cnt >= 60)
|
||||||
|
{
|
||||||
|
cnt = 0;
|
||||||
|
cpu_reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cnt = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usr_app_ota_init()
|
||||||
|
{
|
||||||
|
usr_var.usr_goto_updata = 1;
|
||||||
|
if (usr_var.ota_timer == 0)
|
||||||
|
{
|
||||||
|
usr_var.ota_timer = sys_timer_add(NULL, usr_ota_process, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file usr_le_api.h
|
||||||
|
* @brief usr_le_code 静态库对外 API(广播 / 收发 / 配网)
|
||||||
|
* @author cyWu <1917507415@qq.com>
|
||||||
|
* @date 2026.08.03
|
||||||
|
* @version V1.0.0
|
||||||
|
* @history
|
||||||
|
* - V1.0.0, 2026.08.03, cyWu, 首次发布
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __USR_LE_API_H__
|
||||||
|
#define __USR_LE_API_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化 BLE 广播数据(绑定广播或重连广播)
|
||||||
|
* @note 根据配对状态与 usr_goto_pair 选择 bind/reconn 广播,并启动 500ms 周期更新
|
||||||
|
*/
|
||||||
|
void usr_ble_adv_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief BLE 协议栈接收数据入口
|
||||||
|
* @param data 接收缓冲区
|
||||||
|
* @param len 本次接收长度
|
||||||
|
* @note 组包后解析 bleproto,并分发 DEVICEINFO/AUTH/RUNCMD/OTA 等服务
|
||||||
|
*/
|
||||||
|
void usr_le_data_recieve(uint8_t *data, uint16_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 进入配对/配网模式
|
||||||
|
* @note 断开当前连接、清除配对信息(不复位),重新发绑定广播
|
||||||
|
*/
|
||||||
|
void usr_goto_pair_mode(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 清除配对信息但不复位
|
||||||
|
*/
|
||||||
|
void usr_clear_pair_info_noreset(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 清除配对信息并延时复位
|
||||||
|
*/
|
||||||
|
void usr_clear_pair_info(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取当前是否已配对
|
||||||
|
* @return 1=已配对,0=未配对
|
||||||
|
*/
|
||||||
|
uint8_t usr_get_pair_flag(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 启动应用侧 OTA 流程
|
||||||
|
* @note 置位 usr_goto_updata,并创建 1s 周期定时器驱动断连与 OTA 广播切换
|
||||||
|
*/
|
||||||
|
void usr_app_ota_init(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __USR_LE_API_H__ */
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file usr_le_product.h
|
||||||
|
* @brief usr_le_code 产品身份配置接口(由应用层提供符号,库内不写死)
|
||||||
|
* @author cyWu <1917507415@qq.com>
|
||||||
|
* @date 2026.08.03
|
||||||
|
* @version V1.0.0
|
||||||
|
* @history
|
||||||
|
* - V1.0.0, 2026.08.03, cyWu, 首次发布
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __USR_LE_PRODUCT_H__
|
||||||
|
#define __USR_LE_PRODUCT_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** 与 bleproto_packer.h 中 BLEPROTO_ADV_TLV_LENGTH_PRODCODE 一致 */
|
||||||
|
#ifndef USR_LE_PRODCODE_LEN
|
||||||
|
#define USR_LE_PRODCODE_LEN 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** 与 bleproto_packer.h 中 BLE_PROTO_ADV_LENGTH_PCODE 一致 */
|
||||||
|
#ifndef USR_LE_PCODE_LEN
|
||||||
|
#define USR_LE_PCODE_LEN 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 产品类别码,对应 BLE 广播 prodcode(固定 4 字节 ASCII)
|
||||||
|
* @note 应用层用 JB_CATEGORY_CODE 填充,见 usr_jb_main.c
|
||||||
|
*/
|
||||||
|
extern const uint8_t g_usr_le_prodcode[USR_LE_PRODCODE_LEN];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 平台产品码,对应 BLE 广播 pcode(固定 6 字节 ASCII)
|
||||||
|
* @note 应用层用 JB_PRODUCT_CODE 填充,见 usr_jb_main.c
|
||||||
|
*/
|
||||||
|
extern const uint8_t g_usr_le_pcode[USR_LE_PCODE_LEN];
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __USR_LE_PRODUCT_H__ */
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "bleproto.h"
|
#include "bleproto.h"
|
||||||
#include "bleproto_api.h"
|
#include "bleproto_api.h"
|
||||||
#include "ble_proto.h"
|
#include "ble_proto.h"
|
||||||
#include "jb_protocol.h"
|
|
||||||
#define LOG_TAG_CONST APP
|
#define LOG_TAG_CONST APP
|
||||||
#define LOG_TAG "[APP]"
|
#define LOG_TAG "[APP]"
|
||||||
#define LOG_ERROR_ENABLE
|
#define LOG_ERROR_ENABLE
|
||||||
@@ -37,7 +36,6 @@ static u8 ota_source_data[FIRM_PACK_LEN * 2] = {0};
|
|||||||
|
|
||||||
extern u16 usr_get_conn_service();
|
extern u16 usr_get_conn_service();
|
||||||
extern void ble_multi_trans_disconnect(void);
|
extern void ble_multi_trans_disconnect(void);
|
||||||
extern void usr_ble_adv_updata_OTA();
|
|
||||||
extern void usr_ble_send_data(u8 *data, u16 len); /// BLE发送接口,MTU 244
|
extern void usr_ble_send_data(u8 *data, u16 len); /// BLE发送接口,MTU 244
|
||||||
extern void usr_write_pair_info();
|
extern void usr_write_pair_info();
|
||||||
extern void usr_clear_pair_info();
|
extern void usr_clear_pair_info();
|
||||||
@@ -45,6 +43,8 @@ extern void app_audio_volume_set(u8 value);
|
|||||||
extern int dual_ota_app_data_deal(u32 msg, u8 *buf, u32 len);
|
extern int dual_ota_app_data_deal(u32 msg, u8 *buf, u32 len);
|
||||||
extern int uart_tr_send_data(u8 *data, u32 len);
|
extern int uart_tr_send_data(u8 *data, u32 len);
|
||||||
extern void usr_intterupt_close();
|
extern void usr_intterupt_close();
|
||||||
|
extern void usr_jb_le_recieve_data(u8 *data, u16 len);
|
||||||
|
extern int8_t jbReportAckCheck(u16 cmd, u8 gateway_int_cnt, int32_t gateway_int0);
|
||||||
|
|
||||||
void usr_ota_deal_task();
|
void usr_ota_deal_task();
|
||||||
void usr_data_ana(bleproto_appdata_desc_t *desc);
|
void usr_data_ana(bleproto_appdata_desc_t *desc);
|
||||||
@@ -429,10 +429,9 @@ void usr_ota_deal_task()
|
|||||||
|
|
||||||
/* 最近一次收到 RUNCMD_V2 请求的 msgid,应答时回填 */
|
/* 最近一次收到 RUNCMD_V2 请求的 msgid,应答时回填 */
|
||||||
static u8 s_last_runcmd_msgid = 0;
|
static u8 s_last_runcmd_msgid = 0;
|
||||||
extern void usr_jb_le_recieve_data(u8 *data, u16 len);
|
|
||||||
void usr_run_cmd_code_v2(ble_proto_packet_t *runcmd_par, u8 usr_msg_id)
|
void usr_run_cmd_code_v2(ble_proto_packet_t *runcmd_par, u8 usr_msg_id)
|
||||||
{
|
{
|
||||||
u8 jb_frame[MAX_PACKAGE_LEN];
|
u8 jb_frame[128]; /* 与 jb_protocol.h MAX_PACKAGE_LEN 一致 */
|
||||||
u16 copy_len;
|
u16 copy_len;
|
||||||
|
|
||||||
if (!runcmd_par || !runcmd_par->bytes_data || runcmd_par->device_bytes_len == 0)
|
if (!runcmd_par || !runcmd_par->bytes_data || runcmd_par->device_bytes_len == 0)
|
||||||
|
|||||||
@@ -0,0 +1,634 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
###############################################################################
|
||||||
|
# @file package_release.py
|
||||||
|
# @brief 根据当前开发工程自动生成客户交付 Release 工程
|
||||||
|
# @author cyWu <1917507415@qq.com>
|
||||||
|
# @date 2026.08.04
|
||||||
|
# @version V1.0.0
|
||||||
|
# @history
|
||||||
|
# - V1.0.0, 2026.08.04, cyWu, 首次发布
|
||||||
|
# - V1.0.1, 2026.08.04, cyWu, 产物统一输出到 release/ 目录
|
||||||
|
#
|
||||||
|
# 使用方式(在项目根或任意目录):
|
||||||
|
# python tools/package_release.py
|
||||||
|
#
|
||||||
|
# 约束:
|
||||||
|
# - 仅使用 Python 标准库
|
||||||
|
# - 所有删除 / 过滤 / 复制只作用于 Release 副本
|
||||||
|
# - 绝不修改开发工程业务源码、Makefile、build_lib.bat、CodeBlocks 工程
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import fnmatch
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import zipfile
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, Iterable, List, Set
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 可配置区域(集中管理,扩展模块只改这里)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# 版本文件(相对项目根)
|
||||||
|
VERSION_FILE = "version.txt"
|
||||||
|
|
||||||
|
# Release 输出根目录(相对项目根,产物全部放这里)
|
||||||
|
RELEASE_OUTPUT_DIR = "release"
|
||||||
|
|
||||||
|
# Release 命名规则
|
||||||
|
RELEASE_DIR_PREFIX = "Release_Project_V"
|
||||||
|
RELEASE_ZIP_SUFFIX = ".zip"
|
||||||
|
README_NAME = "Release_Project_README.md"
|
||||||
|
|
||||||
|
# 工程展示名称(写入 README)
|
||||||
|
PROJECT_DISPLAY_NAME = "AC701N Earphone SDK"
|
||||||
|
CHIP_DISPLAY_NAME = "AC7016C(BR28)"
|
||||||
|
|
||||||
|
# 复制时跳过的目录名(任意层级)
|
||||||
|
SKIP_DIR_NAMES: Set[str] = {
|
||||||
|
".git",
|
||||||
|
".vscode",
|
||||||
|
".idea",
|
||||||
|
"objs",
|
||||||
|
"obj",
|
||||||
|
"__pycache__",
|
||||||
|
RELEASE_OUTPUT_DIR, # 不把已有交付产物拷进新包
|
||||||
|
}
|
||||||
|
|
||||||
|
# 复制时跳过的根目录文件(仅项目根下,不进客户包)
|
||||||
|
SKIP_ROOT_FILES: Set[str] = {
|
||||||
|
".gitignore",
|
||||||
|
"version.txt",
|
||||||
|
}
|
||||||
|
|
||||||
|
# 复制时跳过的文件通配(任意层级,按文件名匹配)
|
||||||
|
SKIP_FILE_PATTERNS: List[str] = [
|
||||||
|
"*.o",
|
||||||
|
"*.d",
|
||||||
|
"*.dep",
|
||||||
|
"*.obj",
|
||||||
|
"*.bak",
|
||||||
|
"*.log",
|
||||||
|
"*.tmp",
|
||||||
|
"*.temp",
|
||||||
|
"*.swp",
|
||||||
|
"*.swo",
|
||||||
|
"*.orig",
|
||||||
|
"*.rej",
|
||||||
|
"*.pyc",
|
||||||
|
"*.layout",
|
||||||
|
"*.depend",
|
||||||
|
"Thumbs.db",
|
||||||
|
".DS_Store",
|
||||||
|
]
|
||||||
|
|
||||||
|
# 复制时跳过的路径前缀(相对项目根,防自复制嵌套)
|
||||||
|
SKIP_PATH_PREFIXES: List[str] = [
|
||||||
|
RELEASE_OUTPUT_DIR,
|
||||||
|
"Release_Project_V", # 兼容旧版曾放在项目根的产物
|
||||||
|
]
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 需要封装交付的模块配置
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# public_headers : 保留的公开头文件(仅文件名,相对模块根或子目录中同名匹配)
|
||||||
|
# remove_patterns : 删除的源码通配(递归)
|
||||||
|
# remove_internal_headers : True 时删除非 public_headers 的所有 .h/.hpp
|
||||||
|
# prune_empty_dirs : 清理后删除空目录
|
||||||
|
# remove_extra : 额外删除的相对路径(相对模块根)
|
||||||
|
# keep_extra : 额外强制保留的相对路径(文件或目录,相对模块根)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
MODULE_CONFIG: Dict[str, dict] = {
|
||||||
|
"apps/usr_le_code": {
|
||||||
|
"public_headers": [
|
||||||
|
"usr_le_api.h",
|
||||||
|
"usr_le_product.h",
|
||||||
|
],
|
||||||
|
"remove_patterns": [
|
||||||
|
"*.c",
|
||||||
|
"*.cpp",
|
||||||
|
"*.cc",
|
||||||
|
],
|
||||||
|
"remove_internal_headers": True,
|
||||||
|
"prune_empty_dirs": True,
|
||||||
|
"remove_extra": [
|
||||||
|
"build_lib.bat",
|
||||||
|
],
|
||||||
|
"keep_extra": [
|
||||||
|
"lib/",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 路径管理
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
def get_project_root() -> Path:
|
||||||
|
"""
|
||||||
|
@brief 由脚本位置推导项目根目录(tools/ 的上一级)
|
||||||
|
@return 项目根 Path
|
||||||
|
"""
|
||||||
|
return Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
def read_version(project_root: Path) -> str:
|
||||||
|
"""
|
||||||
|
@brief 读取 version.txt
|
||||||
|
@param project_root 项目根
|
||||||
|
@return 版本号字符串,例如 "1.0.0"
|
||||||
|
"""
|
||||||
|
version_path = project_root / VERSION_FILE
|
||||||
|
if not version_path.is_file():
|
||||||
|
raise FileNotFoundError(f"version file not found: {version_path}")
|
||||||
|
|
||||||
|
version = version_path.read_text(encoding="utf-8").strip()
|
||||||
|
if not version:
|
||||||
|
raise ValueError(f"version file is empty: {version_path}")
|
||||||
|
|
||||||
|
# 简单校验:不允许路径分隔符,避免生成非法目录名
|
||||||
|
if any(ch in version for ch in ("/", "\\", "..")):
|
||||||
|
raise ValueError(f"invalid version string: {version!r}")
|
||||||
|
|
||||||
|
return version
|
||||||
|
|
||||||
|
|
||||||
|
def get_release_paths(project_root: Path, version: str) -> dict:
|
||||||
|
"""
|
||||||
|
@brief 统一生成 Release 相关路径(均位于 release/ 下)
|
||||||
|
@param project_root 项目根
|
||||||
|
@param version 版本号
|
||||||
|
@return 含 output_dir / dir / zip / readme 的字典
|
||||||
|
"""
|
||||||
|
dir_name = f"{RELEASE_DIR_PREFIX}{version}"
|
||||||
|
output_dir = project_root / RELEASE_OUTPUT_DIR
|
||||||
|
release_dir = output_dir / dir_name
|
||||||
|
release_zip = output_dir / f"{dir_name}{RELEASE_ZIP_SUFFIX}"
|
||||||
|
readme_path = release_dir / README_NAME
|
||||||
|
return {
|
||||||
|
"dir_name": dir_name,
|
||||||
|
"output_dir": output_dir,
|
||||||
|
"release_dir": release_dir,
|
||||||
|
"release_zip": release_zip,
|
||||||
|
"readme_path": readme_path,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 复制过滤
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
def _match_any(name: str, patterns: Iterable[str]) -> bool:
|
||||||
|
"""
|
||||||
|
@brief 判断文件名是否匹配任一通配符
|
||||||
|
"""
|
||||||
|
return any(fnmatch.fnmatch(name, pat) for pat in patterns)
|
||||||
|
|
||||||
|
|
||||||
|
def should_skip_path(rel_path: Path) -> bool:
|
||||||
|
"""
|
||||||
|
@brief 判断相对项目根的路径在复制时是否应跳过
|
||||||
|
@param rel_path 相对路径
|
||||||
|
@return True=跳过
|
||||||
|
"""
|
||||||
|
parts = rel_path.parts
|
||||||
|
if not parts:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 跳过项目根下指定文件(如 .gitignore / version.txt)
|
||||||
|
if len(parts) == 1 and parts[0] in SKIP_ROOT_FILES:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 跳过指定目录名(任意层级)
|
||||||
|
for part in parts:
|
||||||
|
if part in SKIP_DIR_NAMES:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 跳过 Release 产物路径(防嵌套)
|
||||||
|
rel_posix = rel_path.as_posix()
|
||||||
|
for prefix in SKIP_PATH_PREFIXES:
|
||||||
|
if rel_posix == prefix.rstrip("/") or rel_posix.startswith(prefix):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 跳过匹配的文件名
|
||||||
|
if _match_any(rel_path.name, SKIP_FILE_PATTERNS):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 跳过已有 zip 包(根目录下)
|
||||||
|
if len(parts) == 1 and rel_path.name.endswith(RELEASE_ZIP_SUFFIX):
|
||||||
|
if rel_path.name.startswith(RELEASE_DIR_PREFIX):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def copy_project(project_root: Path, release_dir: Path) -> int:
|
||||||
|
"""
|
||||||
|
@brief 过滤复制整工程到 Release 目录
|
||||||
|
@param project_root 开发工程根
|
||||||
|
@param release_dir 目标 Release 目录
|
||||||
|
@return 复制的文件数量
|
||||||
|
"""
|
||||||
|
copied = 0
|
||||||
|
|
||||||
|
for root, dirs, files in os.walk(project_root):
|
||||||
|
root_path = Path(root)
|
||||||
|
rel_root = root_path.relative_to(project_root)
|
||||||
|
|
||||||
|
# 就地过滤子目录,避免继续向下遍历
|
||||||
|
keep_dirs: List[str] = []
|
||||||
|
for d in dirs:
|
||||||
|
candidate = rel_root / d if str(rel_root) != "." else Path(d)
|
||||||
|
if should_skip_path(candidate):
|
||||||
|
continue
|
||||||
|
keep_dirs.append(d)
|
||||||
|
dirs[:] = keep_dirs
|
||||||
|
|
||||||
|
# 目标目录
|
||||||
|
dst_root = release_dir if str(rel_root) == "." else release_dir / rel_root
|
||||||
|
dst_root.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
for name in files:
|
||||||
|
rel_file = rel_root / name if str(rel_root) != "." else Path(name)
|
||||||
|
if should_skip_path(rel_file):
|
||||||
|
continue
|
||||||
|
|
||||||
|
src = root_path / name
|
||||||
|
dst = dst_root / name
|
||||||
|
shutil.copy2(src, dst)
|
||||||
|
copied += 1
|
||||||
|
|
||||||
|
return copied
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 模块清理(仅作用于 Release 副本)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
def _is_under_keep_extra(rel_posix: str, keep_extra: List[str]) -> bool:
|
||||||
|
"""
|
||||||
|
@brief 判断模块内相对路径是否属于 keep_extra 保护范围
|
||||||
|
"""
|
||||||
|
for keep in keep_extra:
|
||||||
|
keep_norm = keep.replace("\\", "/").rstrip("/")
|
||||||
|
if not keep_norm:
|
||||||
|
continue
|
||||||
|
# 目录保护:keep 以 / 结尾或配置为目录前缀
|
||||||
|
if rel_posix == keep_norm or rel_posix.startswith(keep_norm + "/"):
|
||||||
|
return True
|
||||||
|
# 兼容配置写成 "lib/" 的情况已在上方处理
|
||||||
|
if keep.endswith("/") and (rel_posix == keep_norm or rel_posix.startswith(keep_norm + "/")):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _prune_empty_dirs(module_dir: Path) -> int:
|
||||||
|
"""
|
||||||
|
@brief 自底向上删除空目录
|
||||||
|
@return 删除的空目录数量
|
||||||
|
"""
|
||||||
|
removed = 0
|
||||||
|
# 深度优先:按路径长度降序
|
||||||
|
all_dirs = sorted(
|
||||||
|
(p for p in module_dir.rglob("*") if p.is_dir()),
|
||||||
|
key=lambda p: len(p.parts),
|
||||||
|
reverse=True,
|
||||||
|
)
|
||||||
|
for d in all_dirs:
|
||||||
|
try:
|
||||||
|
if not any(d.iterdir()):
|
||||||
|
d.rmdir()
|
||||||
|
removed += 1
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return removed
|
||||||
|
|
||||||
|
|
||||||
|
def clean_module(release_dir: Path, module_rel: str, cfg: dict) -> dict:
|
||||||
|
"""
|
||||||
|
@brief 按配置清理单个封装模块(仅 Release 内)
|
||||||
|
@param release_dir Release 根目录
|
||||||
|
@param module_rel 模块相对路径,如 apps/usr_le_code
|
||||||
|
@param cfg MODULE_CONFIG 中的单项配置
|
||||||
|
@return 统计信息字典
|
||||||
|
"""
|
||||||
|
module_dir = release_dir / module_rel
|
||||||
|
stats = {
|
||||||
|
"module": module_rel,
|
||||||
|
"removed_sources": 0,
|
||||||
|
"removed_headers": 0,
|
||||||
|
"removed_extra": 0,
|
||||||
|
"pruned_dirs": 0,
|
||||||
|
"missing": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
if not module_dir.is_dir():
|
||||||
|
stats["missing"] = True
|
||||||
|
print(f"[WARN] module not found in Release: {module_rel}")
|
||||||
|
return stats
|
||||||
|
|
||||||
|
public_headers: Set[str] = set(cfg.get("public_headers", []))
|
||||||
|
remove_patterns: List[str] = list(cfg.get("remove_patterns", []))
|
||||||
|
remove_internal_headers: bool = bool(cfg.get("remove_internal_headers", True))
|
||||||
|
prune_empty_dirs: bool = bool(cfg.get("prune_empty_dirs", True))
|
||||||
|
remove_extra: List[str] = list(cfg.get("remove_extra", []))
|
||||||
|
keep_extra: List[str] = list(cfg.get("keep_extra", []))
|
||||||
|
|
||||||
|
# 1) 删除匹配 remove_patterns 的源文件
|
||||||
|
for path in list(module_dir.rglob("*")):
|
||||||
|
if not path.is_file():
|
||||||
|
continue
|
||||||
|
rel = path.relative_to(module_dir).as_posix()
|
||||||
|
if _is_under_keep_extra(rel, keep_extra):
|
||||||
|
continue
|
||||||
|
if _match_any(path.name, remove_patterns):
|
||||||
|
path.unlink()
|
||||||
|
stats["removed_sources"] += 1
|
||||||
|
|
||||||
|
# 2) 删除非公开头文件
|
||||||
|
if remove_internal_headers:
|
||||||
|
header_patterns = ["*.h", "*.hpp"]
|
||||||
|
for path in list(module_dir.rglob("*")):
|
||||||
|
if not path.is_file():
|
||||||
|
continue
|
||||||
|
if not _match_any(path.name, header_patterns):
|
||||||
|
continue
|
||||||
|
rel = path.relative_to(module_dir).as_posix()
|
||||||
|
if _is_under_keep_extra(rel, keep_extra):
|
||||||
|
continue
|
||||||
|
# 公开头文件按“文件名”匹配,便于配置只写文件名
|
||||||
|
if path.name in public_headers:
|
||||||
|
continue
|
||||||
|
path.unlink()
|
||||||
|
stats["removed_headers"] += 1
|
||||||
|
|
||||||
|
# 3) 删除额外指定文件/目录
|
||||||
|
for extra in remove_extra:
|
||||||
|
target = module_dir / extra
|
||||||
|
if not target.exists():
|
||||||
|
continue
|
||||||
|
if target.is_dir():
|
||||||
|
shutil.rmtree(target)
|
||||||
|
else:
|
||||||
|
target.unlink()
|
||||||
|
stats["removed_extra"] += 1
|
||||||
|
|
||||||
|
# 4) 清理空目录
|
||||||
|
if prune_empty_dirs:
|
||||||
|
stats["pruned_dirs"] = _prune_empty_dirs(module_dir)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
|
||||||
|
def clean_all_modules(release_dir: Path) -> List[dict]:
|
||||||
|
"""
|
||||||
|
@brief 遍历 MODULE_CONFIG 清理所有模块
|
||||||
|
"""
|
||||||
|
results = []
|
||||||
|
for module_rel, cfg in MODULE_CONFIG.items():
|
||||||
|
print(f"[INFO] cleaning module: {module_rel}")
|
||||||
|
results.append(clean_module(release_dir, module_rel, cfg))
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize_release_makefile(release_dir: Path) -> None:
|
||||||
|
"""
|
||||||
|
@brief 调整 Release 副本中的 Makefile:仅链接预编译 libusr_le_code.a
|
||||||
|
开发工程 Makefile 不动;客户包不得再尝试用已删除源码重建库
|
||||||
|
@param release_dir Release 根目录
|
||||||
|
"""
|
||||||
|
makefile = release_dir / "Makefile"
|
||||||
|
if not makefile.is_file():
|
||||||
|
print("[WARN] Makefile not found in Release, skip sanitize")
|
||||||
|
return
|
||||||
|
|
||||||
|
text = makefile.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
# 1) 去掉源码列表与 OBJS,仅保留预编译库路径
|
||||||
|
text2, n1 = re.subn(
|
||||||
|
r"# usr_le_code 静态库[^\n]*\n"
|
||||||
|
r"USR_LE_LIB := apps/usr_le_code/lib/libusr_le_code\.a\n"
|
||||||
|
r"USR_LE_SRC_FILES := \\\n"
|
||||||
|
r"(?:[ \t]+apps/usr_le_code/[^\n]+\n)+"
|
||||||
|
r"\n"
|
||||||
|
r"USR_LE_OBJS :=[^\n]+\n",
|
||||||
|
"# usr_le_code 预编译静态库(Release 不附带协议源码,禁止本地重建)\n"
|
||||||
|
"USR_LE_LIB := apps/usr_le_code/lib/libusr_le_code.a\n"
|
||||||
|
"\n",
|
||||||
|
text,
|
||||||
|
count=1,
|
||||||
|
)
|
||||||
|
if n1 == 0:
|
||||||
|
raise RuntimeError("sanitize Makefile failed: USR_LE_SRC_FILES block not found")
|
||||||
|
|
||||||
|
# 2) .PHONY 去掉 lib_usr_le
|
||||||
|
text2, n2 = re.subn(
|
||||||
|
r"\.PHONY:\s*all clean pre_build lib_usr_le\b",
|
||||||
|
".PHONY: all clean pre_build",
|
||||||
|
text2,
|
||||||
|
count=1,
|
||||||
|
)
|
||||||
|
if n2 == 0:
|
||||||
|
# 兼容顺序变化,尽量剥离 lib_usr_le
|
||||||
|
text2 = re.sub(r"\s+lib_usr_le\b", "", text2, count=1)
|
||||||
|
|
||||||
|
# 3) 删除 lib_usr_le 目标与 $(USR_LE_LIB): $(USR_LE_OBJS) 重建规则
|
||||||
|
# 保留 all / OUT_ELF 对 $(USR_LE_LIB) 的依赖:库文件已存在即可链接
|
||||||
|
text2, n3 = re.subn(
|
||||||
|
r"\n# 单独编译 usr_le_code 静态库:[^\n]*\n"
|
||||||
|
r"lib_usr_le:[^\n]*\n"
|
||||||
|
r"\n"
|
||||||
|
r"\$\(USR_LE_LIB\): \$\(USR_LE_OBJS\)\n"
|
||||||
|
r"(?:[ \t]+[^\n]+\n)+",
|
||||||
|
"\n",
|
||||||
|
text2,
|
||||||
|
count=1,
|
||||||
|
)
|
||||||
|
if n3 == 0:
|
||||||
|
raise RuntimeError("sanitize Makefile failed: lib_usr_le rebuild rule not found")
|
||||||
|
|
||||||
|
makefile.write_text(text2, encoding="utf-8")
|
||||||
|
print("[INFO] sanitized Release Makefile (prebuilt libusr_le_code.a only)")
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# README / ZIP
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
def write_readme(readme_path: Path, version: str, module_stats: List[dict]) -> None:
|
||||||
|
"""
|
||||||
|
@brief 生成 Release_Project_README.md
|
||||||
|
@param readme_path README 路径
|
||||||
|
@param version 版本号
|
||||||
|
@param module_stats 模块清理统计(用于目录说明)
|
||||||
|
"""
|
||||||
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
lines: List[str] = [
|
||||||
|
f"# {PROJECT_DISPLAY_NAME}",
|
||||||
|
"",
|
||||||
|
"## 基本信息",
|
||||||
|
"",
|
||||||
|
f"- 工程名称:{PROJECT_DISPLAY_NAME}",
|
||||||
|
f"- 版本号:V{version}",
|
||||||
|
f"- 生成时间:{now}",
|
||||||
|
f"- 适用芯片:{CHIP_DISPLAY_NAME}",
|
||||||
|
"",
|
||||||
|
"## 目录说明",
|
||||||
|
"",
|
||||||
|
"```",
|
||||||
|
f"Release_Project_V{version}/",
|
||||||
|
"├── apps/",
|
||||||
|
"│ ├── common/ # SDK 公共模块",
|
||||||
|
"│ ├── earphone/ # 耳机应用",
|
||||||
|
"│ ├── usr_jb_proto/ # 应用协议层",
|
||||||
|
"│ └── usr_le_code/ # BLE 协议库(库文件 + 公开头文件)",
|
||||||
|
"├── cpu/ # 芯片相关代码与工具",
|
||||||
|
"├── include_lib/ # SDK 头文件",
|
||||||
|
"├── tools/ # 工程工具",
|
||||||
|
"├── Makefile",
|
||||||
|
"├── AC701N.cbp",
|
||||||
|
f"└── {README_NAME}",
|
||||||
|
"```",
|
||||||
|
"",
|
||||||
|
"### 封装模块公开接口",
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
|
||||||
|
for module_rel, cfg in MODULE_CONFIG.items():
|
||||||
|
public_headers = cfg.get("public_headers", [])
|
||||||
|
lines.append(f"**{module_rel}**")
|
||||||
|
lines.append("")
|
||||||
|
lines.append(f"- 静态库:`{module_rel}/lib/`")
|
||||||
|
lines.append("- 公开头文件:")
|
||||||
|
for h in public_headers:
|
||||||
|
lines.append(f" - `{module_rel}/{h}`")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
lines.append("---")
|
||||||
|
lines.append("")
|
||||||
|
lines.append("*本文件由 tools/package_release.py 自动生成。*")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
readme_path.write_text("\n".join(lines), encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def make_zip(release_dir: Path, release_zip: Path) -> None:
|
||||||
|
"""
|
||||||
|
@brief 将 Release 目录压缩为 zip(与目录同级)
|
||||||
|
@param release_dir Release 目录
|
||||||
|
@param release_zip 目标 zip 路径
|
||||||
|
"""
|
||||||
|
if release_zip.exists():
|
||||||
|
release_zip.unlink()
|
||||||
|
|
||||||
|
with zipfile.ZipFile(release_zip, "w", compression=zipfile.ZIP_DEFLATED) as zf:
|
||||||
|
for path in release_dir.rglob("*"):
|
||||||
|
if path.is_file():
|
||||||
|
arcname = path.relative_to(release_dir.parent)
|
||||||
|
zf.write(path, arcname.as_posix())
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 主流程
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
def remove_old_release(release_dir: Path, release_zip: Path) -> None:
|
||||||
|
"""
|
||||||
|
@brief 删除已有同名 Release 目录与 zip
|
||||||
|
"""
|
||||||
|
if release_dir.exists():
|
||||||
|
print(f"[INFO] remove old release dir: {release_dir.name}")
|
||||||
|
shutil.rmtree(release_dir)
|
||||||
|
|
||||||
|
if release_zip.exists():
|
||||||
|
print(f"[INFO] remove old release zip: {release_zip.name}")
|
||||||
|
release_zip.unlink()
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
"""
|
||||||
|
@brief Release 打包主入口
|
||||||
|
@return 进程退出码,0=成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
project_root = get_project_root()
|
||||||
|
version = read_version(project_root)
|
||||||
|
paths = get_release_paths(project_root, version)
|
||||||
|
|
||||||
|
release_dir: Path = paths["release_dir"]
|
||||||
|
release_zip: Path = paths["release_zip"]
|
||||||
|
readme_path: Path = paths["readme_path"]
|
||||||
|
dir_name: str = paths["dir_name"]
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print(" AC701N Release Package Tool")
|
||||||
|
print("=" * 60)
|
||||||
|
output_dir: Path = paths["output_dir"]
|
||||||
|
|
||||||
|
print(f"[INFO] project root : {project_root}")
|
||||||
|
print(f"[INFO] version : {version}")
|
||||||
|
print(f"[INFO] output dir : {RELEASE_OUTPUT_DIR}/")
|
||||||
|
print(f"[INFO] release dir : {RELEASE_OUTPUT_DIR}/{dir_name}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# 确保 release/ 输出目录存在
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# ① 删除旧产物
|
||||||
|
remove_old_release(release_dir, release_zip)
|
||||||
|
|
||||||
|
# ② 过滤复制
|
||||||
|
print("[INFO] copying project ...")
|
||||||
|
copied = copy_project(project_root, release_dir)
|
||||||
|
print(f"[INFO] copied files : {copied}")
|
||||||
|
|
||||||
|
# ③ 模块清理(仅 Release 副本)
|
||||||
|
print("[INFO] cleaning encapsulated modules ...")
|
||||||
|
module_stats = clean_all_modules(release_dir)
|
||||||
|
for st in module_stats:
|
||||||
|
if st["missing"]:
|
||||||
|
continue
|
||||||
|
print(
|
||||||
|
f" - {st['module']}: "
|
||||||
|
f"src={st['removed_sources']}, "
|
||||||
|
f"hdr={st['removed_headers']}, "
|
||||||
|
f"extra={st['removed_extra']}, "
|
||||||
|
f"empty_dirs={st['pruned_dirs']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# ④ Release Makefile:禁止用已删除源码重建库(开发工程 Makefile 不动)
|
||||||
|
print("[INFO] sanitizing Release Makefile ...")
|
||||||
|
sanitize_release_makefile(release_dir)
|
||||||
|
|
||||||
|
# ⑤ README
|
||||||
|
print("[INFO] writing README ...")
|
||||||
|
write_readme(readme_path, version, module_stats)
|
||||||
|
|
||||||
|
# ⑥ ZIP
|
||||||
|
print("[INFO] creating zip ...")
|
||||||
|
make_zip(release_dir, release_zip)
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("=" * 60)
|
||||||
|
print("[OK] Release package generated successfully")
|
||||||
|
print(f" dir : {release_dir}")
|
||||||
|
print(f" zip : {release_zip}")
|
||||||
|
print("=" * 60)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"[FAIL] {exc}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
1.0.0
|
||||||
Reference in New Issue
Block a user