4.3.13. FindMy
4.3.13.1. findmy原理简介和概述
支持的板级: br25、br23、bd19、br34
支持的芯片: AC636N、AC635N、AC632N、AC638N
Find My 是苹果公司提供的一种寻找丢失设备的服务和协议。它可以帮助用户定位并追踪丢失的苹果设备,如 AirTag 和 AirPods 等。findmy协议依托庞大的findmy network网络,即使本身没有 GPS 模块,也能利用它周围的苹果设备(iPhone,iPad,Mac)来帮助其定位。
如图1,在findmy协议中主要可以分为以下角色:
拥有者设备(Owner device)
:拥有者设备是用户的苹果设备,如iPhone或iPad,通过使用Find My应用程序与外设进行连接和配对。拥有者设备与用户的Apple ID关联,并成为Find My网络的拥有者设备角色。Find My服务器(findmy apple server)
:Find My功能涉及到苹果的服务器,用于处理设备的定位和数据传输。这些服务器经过IOS设备通过网络协议接收来自支持Find My功能的设备发送的定位数据,并将其提供给用户的Find My应用程序进行显示和处理。外设(Accessory)
:外设是实现了Find My网络协议的设备,如AirTag或其他支持Find My功能的设备(使用烧录JL FindMy SDK的芯片的产品)。外设可以通过与拥有者设备进行BLE协议连接和配对数据交互,加入Find My网络。
4.3.13.2. 快速上手
本章节主要介绍拿到sdk后如何快速运行findmy应用功能
4.3.13.2.1. 开发环境搭建
首先请确保正确的搭建了 Windows 下的第三方集成开发环境 CodeBlocks和杰理的编译工具链 jl_toolchain。
https://doc.zh-jieli.com/AC63/zh-cn/master/getting_started/environmental_install/index.html
4.3.13.2.2. 板级配置和app应用选择
先配置板级apps\spp_and_le\board\bd19\board_config.h
(以AC632系列为例)。
/*
* 板级配置选择
*/
// #define CONFIG_BOARD_AC632N_DEMO
#define CONFIG_BOARD_AC6323A_FMY
// #define CONFIG_BOARD_AC6321A_DEMO
// #define CONFIG_BOARD_AC6323A_DEMO
// #define CONFIG_BOARD_AC6328A_DEMO
// #define CONFIG_BOARD_AC6328B_DONGLE
// #define CONFIG_BOARD_AC6329B_DEMO
// #define CONFIG_BOARD_AC6329C_DEMO
// #define CONFIG_BOARD_AC6329E_DEMO
// #define CONFIG_BOARD_AC6329F_DEMO
配置app选择:apps\spp_and_le\include\app_config.h
//apps example 选择,只能选1个,要配置对应的board_config.h
#define CONFIG_APP_SPP_LE 0 //SPP + LE or LE's client
#define CONFIG_APP_FINDMY 1 //FINDMY
#define CONFIG_APP_MULTI 0 //蓝牙LE多连 + spp
#define CONFIG_APP_DONGLE 0 //usb + 蓝牙(ble 主机),PC hid设备
#define CONFIG_APP_CENTRAL 0 //ble client,中心设备
#define CONFIG_APP_LL_SYNC 0 //腾讯连连
#define CONFIG_APP_BEACON 0 //蓝牙BLE ibeacon
#define CONFIG_APP_NONCONN_24G 0 //2.4G 非连接收发
#define CONFIG_APP_TUYA 0 //涂鸦协议
#define CONFIG_APP_AT_COM 0 //AT com HEX格式命令
#define CONFIG_APP_AT_CHAR_COM 0 //AT com 字符串格式命令
#define CONFIG_APP_IDLE 0 //空闲任务
#define CONFIG_APP_CONN_24G 0 //基于BLE的2.4g,板级只需要开BLE
#define CONFIG_APP_HILINK 0 //华为协议
#define CONFIG_APP_ELECTROCAR 0 //电车项目,注意将板级处ADKEY以及别的IO占用失能, 关闭低功耗:TCFG_LOWPOWER_LOWPOWER_SEL设置为0
4.3.13.2.3. 添加苹果授权信息
Note
由于findmy配件还需要依赖苹果服务器去做功能的运转,因此还需要向苹果申请对应的授权信息才能成功绑定入网,注意第一次烧写一定要修改以下信息,这个只是JL的示例数据无法正常使用,否则无法配对入网。
授权信息的修改文件位于:ble_fmy_fmna.c
//==================================================================================
// !!!!!重要说明事项!!!!!!
// 下列是测试findmy功能需要填入自己的token信息格式示例
// 只能被搜索,不能配对绑定连接; 如要正常使用功能需要向苹果申请自己的token信息替换写入测试
//用户申请的UID,需要修改填入
static const uint8_t fmy_serial_number[16] = "";
//用户申请的product_data,需要修改填入
static const uint8_t fmy_product_data[8] = {};//JL
//默认使用的base64的公钥key,一般不需要修改
static const char fmy_Server_Encryption_Key[] = "";
static const char fmy_Signature_Verification_Key[] = "";
//用户申请的token,base64格式或者hex格式,需要修改填入
#if UUID_TOKEN_IS_BASE64_MODE
static const char fmy_token_uuid_char[] = "";
static const char fmy_token_auth_char[] = "";
#else
static const uint8_t fmy_token_uuid_hex[16] = {
};
static const uint8_t fmy_token_auth_hex[] = {
....
};
#endif
fmy_serial_number
:从apple申请的序列序列号fmy_product_data
:从apple申请的产品信息fmy_Server_Encryption_Key
:从apple申请的Encryption_Keyfmy_Signature_Verification_Key
:从apple申请的Verification_Keyfmy_token_uuid_char
:从mfi申请的每个产品授权的uuidfmy_token_auth_char
:从mfi申请的每个产品授权的token
4.3.13.2.4. 添加杰理授权使用
目前JL FindMy SDK对fmna.a库进行授权的方式进行生产样机个数进行收费,有关授权算法的使用介绍如下:
https://doc.zh-jieli.com/Tools/zh-cn/mass_prod_tools/multi_auth/index.html
并且参考以下步骤完成对授权数据的烧录:
https://doc.zh-jieli.com/Tools/zh-cn/mass_prod_tools/multi_auth/prod-user.html#authroization-id
操作步骤提示如下(以AC632系列为例):
获取授权Lic: 请在下单采购632N具体芯片型号时,备注“findmy多算法授权”,并联系珠海杰理客服。
修改授权文件名称,并放在cpu的下载目录(cpu\bd19\tools\download\data_trans)才能编译生成带算法授权功能的fw文件。其中tkn文件的名字应与
isd_config.ini
的配置信息一致file_authrunFindmyAC632N.tkn
,生成完fw文件后使用烧写器进行算法授权信息的烧录运行的芯片第一次需要经过1拖2或者1拖8烧写器(lastest version)烧写授权码;如果你未完成这一步直接烧写固件,如果fw程序运行出现异常复位或者添加调试信息后出现
ASSERT-FAILD: 0 fmna forbidden cfg!!!
,说明芯片还没被授权,需要通过烧写器写入授权数据。
// ini文件的最后一段配置
[FW_ADDITIONAL]
FILE_LIST=(file=file_authrunFindmyAC632N.tkn:type=0xec)
Note
正确烧写杰理授权数据后,此时之后的固件烧写不会影响杰理的授权数据(除非你擦除了所有的flash数据,非必要不要擦除所有flash数据)。
4.3.13.2.5. 烧录固件
Note
如果杰理授权数据已经烧录到芯片里面,并且你也正确的修改了sdk的苹果授权信息,那么现在把findmy固件写入,打开codeblocks工程,apps\spp_and_le\board\bd19\AC632N_spp_and_le.cbp
,点击编译烧录,编译烧录教程参考:
https://doc.zh-jieli.com/Tools/zh-cn/dev_tools/build_download/build_with_codeblocks.html
4.3.13.2.6. 测试使用
Note
烧录完上电后,findm配件不默认打开广播,可以查看fmy_ble_key_event_handler
函数逻辑, 单击触发ADKEY0事件打开广播,此时可以打开IOS终端查找应用->物品->添加其他应用->搜索到设备->命名绑定连接
if (event_type == KEY_EVENT_CLICK) {
switch (key_value) {
case TCFG_ADKEY_VALUE0:
log_info(">>>test to enable start pairing adv");
#if FMY_MAC_CHANGE_LOCK
fmy_pairing_reset_address();
#endif
fmy_pairing_restart_adv();
}
Important
如果成功连接绑定连接并且可以控制播声,那么恭喜你!已经完成了JL Findmy SDK的上手使用,可以依靠后续章节去开发属于你的findmy应用
4.3.13.3. 代码架构介绍
4.3.13.3.1. FindMy SDK框图介绍
Note
上图为JL FINDMY SDK的框图架构,依托杰理的平台和fmna协议库,用户工程师不需要关注fmna中findmy状态机的转换运作原理,也不需要关注findmy协议是如何和IOS进行加密交握手完成配对,只需要简单的在我们上层留出的接口和杰理SDK原有的功能去适配自己产品上层的交互逻辑和外设即可。
4.3.13.3.2. 应用层代码文件介绍
fmy功能接口应用层文件架构介绍见上图
4.3.13.4. findmy状态介绍
4.3.13.4.1. 状态介绍
findmy通过状态机的控制会在不同行为场景中转化为不同的状态,常见的状态如下:
等待配对状态(pair mode)
:产品还未与苹果设备(例如iPhone或者iPad)配对时,或者产品从Find My应用中移除配对时,此状态会发送等待配对的蓝牙广播。为了尽可能快的被苹果设备发现,此状态会高速广播,功耗比较大。配对连接状态(pairing)
:产品与苹果设备连接完成配对过程,此状态产品与苹果设备交换大量的数据,功耗也比较大,因为此状态出现非常低频, 所以此状态对产品续航影响小。高速连接并寻找状态(产品响铃)(high connected)
:完成配对的产品,可以在Find My应用中点击 “播放声音”按钮,可以使产品响铃,来找到产品,因为此状态出现低频, 所以此状态对产品续航影响小。低速连接状态(low connected)
:如果已配对产品与苹果设备重连时,会处于高速连接过程(高速可以理解为产品与苹果设备的数据交互高速很高),如果没有“播放声音”操作,30秒后就会进入低速连接状态。此状态下功耗比较低。如果产品与苹果设备不断开,此状态会一直保持着。慢速广播状态(待机状态)(separated)
:如果已配对产品与苹果设备远离,产品与苹果设备蓝牙断开了,此时产品就会发送慢速蓝牙广播,等待下一次重连被寻找,如果用户不尝试“播放声音”功能,产品会一直处于此状态。
4.3.13.4.2. findmy状态回调函数
JL FindMy SDK中在外部设置定义了回调函数供用户捕捉对应的状态以便用户自定义外设行为(例如配对完成后或者解绑有特殊的铃声)。
ble_fmy_fmna.c
/*
* @brief findmy state callback,状态类别参考FMNA_SM_State_t枚举体
*/
static uint16_t fmy_state_callback(FMNA_SM_State_t fmy_state, const char *state_string)
{
log_info("fmy state change->fmy_state:%s", state_string);
switch (fmy_state) {
case FMNA_SM_FMNA_PAIR_COMPLETE:
log_info(">>>findmy pair success!!");
break;
case FMNA_SM_UNPAIR:
log_info(">>>findmy unpair success!!");
break;
default:
break;
}
return 0;
}
fmna_api.h
typedef enum {
FMNA_SM_BOOT = 0,
FMNA_SM_PAIR,
FMNA_SM_SEPARATED,
FMNA_SM_NEARBY,
FMNA_SM_CONNECTING,
FMNA_SM_FMNA_PAIR,
FMNA_SM_FMNA_PAIR_COMPLETE,
FMNA_SM_CONNECTED,
FMNA_SM_DISCONNECTING,
FMNA_SM_NOCHANGE,
FMNA_SM_UNPAIR
} FMNA_SM_State_t;
4.3.13.5. apple license和产品信息配置
4.3.13.5.1. 产品信息配置
ble_fmy.c
static const char FMY_ManufacturerName[64] = "Zhuhai Jieli Technology Co.,Ltd.";
static const char FMY_ModelName[64] = "JLtag";
static const uint8_t FMY_AccessoryCategory[8] = {FMY_CATEGORY_Finder, 0, 0, 0, 0, 0, 0, 0};
FMY_ManufacturerName
:公司名称FMY_ModelName
:配件名字FMY_AccessoryCategory
:产品类型
ble_fmy_cfg.h
TOKEN_ID_PRODUCTION_MODE
:选择debug模式还是productionFMY_FW_VERSION_MAJOR_NUMBER
:固件主要版本FMY_FW_VERSION_MINOR_NUMBER
:固件次要版本FMY_FW_VERSION_REVISION_NUMBER
:固件修订版本号
固件版本需遵循以下规则
The firmware revision string shall use the x[.y[.z]] format where :
• <x> is the major version number, required.
• <y> is the minor version number, required if it is non zero or if <z> is present.
• <z> is the revision version number, required if non zero.
4.3.13.5.2. apple license信息配置和说明
ble_fmy_cfg.h
#define UUID_TOKEN_IS_BASE64_MODE 1 //0--hex, 1--base64
static const uint8_t fmy_serial_number[16] = "";
static const uint8_t fmy_product_data[8] = {};
static const char fmy_Server_Encryption_Key[] = "";
static const char fmy_Signature_Verification_Key[] = "";
static const char fmy_token_uuid_char[] = "";
static const char fmy_token_auth_char[] = "";
TOKEN_ID_PRODUCTION_MODE
:产品模式选择(debug和production)UUID_TOKEN_IS_BASE64_MODE
:UUID和TOKEN数据格式(hex:以十六进制填入,base64:以base64数据格式填入)fmy_serial_number
:从apple申请的序列序列号fmy_product_data
:从apple申请的产品信息fmy_Server_Encryption_Key
:从apple申请的Encryption_Keyfmy_Signature_Verification_Key
:从apple申请的Verification_Keyfmy_token_uuid_char
:从mfi申请的每个产品授权的uuidfmy_token_auth_char
:从mfi申请的每个产品授权的token
有关apple findmy开发资格申请可参考以下链接:
https://www.apple.com/newsroom/2021/04/apples-find-my-network-now-offers-new-third-party-finding-experiences/
授权信息写入函数如下:
ble_fmy_fmna.c
/*************************************************************************************************/
/*!
* \brief 配置用户认证信息
*
* \param [in]
*
* \return
*
* \note token信息写入,慎重修改!!!!!!
*/
/*************************************************************************************************/
static int fmy_set_user_infomation(void)
{
ret_code_t ret = FMY_SUCCESS;
fmna_input_cfg_t input_cfg;
fmna_user_cfg_set_patch(fmy_user_config_path);
fmna_set_product_data(fmy_product_data);
fmna_set_crypto_enc_key_config(fmy_Server_Encryption_Key, fmy_Signature_Verification_Key);
//!!!配置区写入有效的token,为空时默认写入一次,使用后token会被手机更新
//注意不要重复写入,以免token被手机更新后,丢失失效
uint8_t *data_ram = zalloc(16 + 1024);
if (data_ram) {
fmna_user_cfg_set_patch(fmy_user_config_path);
ret = fmna_user_cfg_open();
if (ret != FMY_SUCCESS) {
log_info("open user_cfg fail,%d", ret);
goto w_end_free;
}
if (fmna_user_cfg_is_exist()) {
//用户可确定保存的token是否有效,如果无效可修改流程,写入新的token替换
//注意不要重复写入,以免token被手机更新后,丢失失效
fmy_read_last_user_config();
fmna_user_cfg_close();
log_info("exist user_cfg info");
goto w_end_free;
}
//配置区有效,并且为空才写入
input_cfg.serial_number = fmy_serial_number;
input_cfg.uuid = data_ram;
input_cfg.token = &data_ram[16];
#if UUID_TOKEN_IS_BASE64_MODE
int len = uuid_str_to_hex(fmy_token_uuid_char, input_cfg.uuid);
if (len != 16) {
log_info("err uuid char");
ret = FMY_ERROR_INVALID_DATA;
} else {
len = fmna_Base64Decode(fmy_token_auth_char, input_cfg.token, 1024);
if (len == 0) {
log_info("err token char");
ret = FMY_ERROR_INVALID_DATA;
}
}
#else
memcpy(input_cfg.uuid, fmy_token_uuid_hex, 16);
memcpy(input_cfg.token, fmy_token_auth_hex, sizeof(fmy_token_auth_hex));
#endif
if (ret == FMY_SUCCESS) {
ret = fmna_user_cfg_write(&input_cfg);
fmna_user_cfg_close();
}
w_end_free:
free(data_ram);
} else {
ret = FMY_ERROR_NO_MEM;
}
if (ret == FMY_SUCCESS) {
log_info("set user_cfg succ");
} else {
log_info("set user_cfg fail,%d", ret);
}
return ret;
}
if (fmna_user_cfg_is_exist()) {
//用户可确定保存的token是否有效,如果无效可修改流程,写入新的token替换
//注意不要重复写入,以免token被手机更新后,丢失失效
fmy_read_last_user_config();
fmna_user_cfg_close();
log_info("exist user_cfg info");
goto w_end_free;
}
Note
参考上述流程,如果当前授权数据不正确,可以注释掉这部分逻辑重新烧录新的apple授权数据,但上电更新后,需要重新打开这段代码再烧一次回来避免每次上电后又覆盖之前的apple授权数据信息。 其中fmy_token_uuid_char和fmy_token_auth_char都将写入在flash自定义区域,并且在每次配对绑定时会进行轮转,不可随意擦除此区域数据,否则之后将无法成功绑定,起始地址和大小如下(以512k AC63x平台为例),可在isd_config.ini见。
isd_config.ini
[RESERVED_EXPAND_CONFIG]
FINDMY_ADR=0x7D000;
FINDMY_LEN=0x2000;
FINDMY_OPT=1;
4.3.13.5.3. fmy功能特性设置
fmna_api.h
//Accessory capability
#define FMY_CAPABILITY_SUPPORTS_PLAY_SOUND BIT(0) //Supports play sound
#define FMY_CAPABILITY_SUPPORTS_MOTION_DETECTOR_UT BIT(1) //Supports motion detector UT
#define FMY_CAPABILITY_SUPPORTS_SN_LOOKUP_BY_NFC BIT(2) //Supports serial number lookup by NFC
#define FMY_CAPABILITY_SUPPORTS_SN_LOOKUP_BY_BLE BIT(3) //Supports serial number lookup by BLE
#define FMY_CAPABILITY_SUPPORTS_FW_UPDATE_SERVICE BIT(4) //Supports firmware update service
ble_fmy.c
//set capability
static const uint8_t FMY_AccessoryCapabilities[4] = {
(FMY_CAPABILITY_SUPPORTS_PLAY_SOUND
#if FMY_OTA_SUPPORT_CONFIG
| FMY_CAPABILITY_SUPPORTS_FW_UPDATE_SERVICE
#endif
#if TCFG_GSENSOR_ENABLE
| FMY_CAPABILITY_SUPPORTS_MOTION_DETECTOR_UT
#endif
| FMY_CAPABILITY_SUPPORTS_SN_LOOKUP_BY_BLE),
0x00, 0x00, 0x00
};
Note
AccessoryCapabilities描述了findmy配件支持的各种功能,默认打开play sound和serial_number_look_up功能,motion_detection和uarp用户可根据产品特性选择打开对应的宏控制,如何控制可见下表:
Characteristic name |
Data type |
Size(octets) |
Description |
---|---|---|---|
Accessory capability |
Uint32 |
4 |
Bit 0 : Supports play sound Bit 1 :Supports motion detector UT Bit 2 : Supports serial number lookup by NFC Bit 3 : Supports serial number lookup by BLE Bit 4: Supports firmware update service |
例如我要打开playSound, Supports serial number lookup by BLE, motion detector,firmware update service 功能,则可以将这个数组的第一个字节的前五个bit设置对应的二进制值即可:10101,由于findmy产品定位是防丢器,其中motion detection和play sound是否需要取决于产品的体积,当符合以下所有标准则需要这两项功能:
The accessory is ≤ 30 cm in at least one dimension.
The accessory is ≤ 18 cm X 13 cm in two of its dimensions.
The accessory is ≤ 250 cm3 in three dimensional space.
4.3.13.6. play sound功能
4.3.13.6.1. play sound功能介绍
Note
play sound功能是fmna官方定义的近距离查找功能,SDK中默认打开
,当IOS终端靠近findmy设备并且点击findmy app 的播放声音的按键则可以通过ble连接gatt控制触发这种行为,SDK中默认的方案使用GPIO驱动蜂鸣器(有源或无源)来实现响声。
4.3.13.6.2. play sound配置
board_ac6323a_fmy_cfg.h
//*********************************************************************************//
// fmy //
//*********************************************************************************//
#define SOUND_GPIO_PORT IO_PORTA_00
#define SOUND_PASSIVE_BUZZER ENABLE_THIS_MOUDLE // 是否采用无源蜂鸣器-PWM推声
#if SOUND_PASSIVE_BUZZER
#define DEV_SOUND_PWM_CH pwm_ch0 //选择PWM输出通道
#endif
其中:
SOUND_GPIO_PORT
为蜂鸣器驱动GPIO口SOUND_PASSIVE_BUZZER
为是否采用无源蜂鸣器发声(用pwm波推声),DISABLE则采用有源蜂鸣器驱动,只是简单的GPIO翻转来驱动发声
4.3.13.6.3. play sound 驱动函数
ble_fmy_fmna.c
#if SOUND_PASSIVE_BUZZER
// 无源蜂鸣器需要交流信号去驱动,用pwm来推信号
struct pwm_platform_data p_buzzer_pwm_data;
static void fmy_sound_passive_buzzer_init(u32 gpio, pwm_ch_num_type pwm_ch)
{
p_buzzer_pwm_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐
p_buzzer_pwm_data.frequency = 5000; // 5KHz
p_buzzer_pwm_data.pwm_ch_num = pwm_ch; //通道选择
p_buzzer_pwm_data.duty = 5000; //占空比50%
// 指定PWM(AC635)硬件管脚的芯片需要注意高低引脚的选择
p_buzzer_pwm_data.h_pin = -1; //没有则填 -1。h_pin_output_ch_num无效,可不配置
p_buzzer_pwm_data.l_pin = gpio; //硬件引脚,l_pin_output_ch_num无效,可不配置
p_buzzer_pwm_data.complementary_en = 0; //两个引脚的波形, 1: 互补, 0: 同步;
mcpwm_init(&p_buzzer_pwm_data);
}
static void fmy_sound_passive_onoff(pwm_ch_num_type pwm_ch, bool on_off)
{
// 开关低功耗,pwm模块会在低功耗时被关闭
fmy_state_idle_set_active(on_off);
// 开、关pwm输出
PORT_IO_INIT(SOUND_GPIO_PORT, !on_off)
mcpwm_ch_open_or_close(pwm_ch, on_off);
}
#endif
static void fmy_sound_timer_control(void)
{
DEV_SOUND_STATE(__fydata->sound_onoff);
__fydata->sound_onoff = !__fydata->sound_onoff;
}
Note
用户可以自行修改这部分声音外设逻辑来达到自己的发声效果
4.3.13.7. Motion Detection功能
4.3.13.7.1. Motion Detection功能介绍
Note
由于findmy产品定位为防丢器协议,因此为了如何防止findmy设备被用于恶意跟踪,findmy协议设计了Motion Detection功能,当别人的设备混入您的随身物品时,并跟踪超过一段时间(设备远离拥有者设备时将会处于待机分离状态),此时设备将会开启加速度传感器gsensor检测设备是否移动,当移动时,将会发出响声提醒此时你正在被findmy设备跟踪。JL FINDMY SDK中默认集成了三种加速度传感器来采集加速度数据来完成这个功能。
4.3.13.7.2. gsensor外设配置
Note
默认采用软件IIC的方式驱动加速度传感器来获取加速度数据,可以根据产品外围设计选择io口和gsensor驱动类型,也可以参照原有代码架构自行添加加速度传感器型号并调试功能。
board_ac6323a_fmy_cfg.h
//*********************************************************************************//
// IIC配置 //
//*********************************************************************************//
/*软件IIC设置*/
#define TCFG_SW_I2C0_CLK_PORT IO_PORTB_06 //软件IIC CLK脚选择
#define TCFG_SW_I2C0_DAT_PORT IO_PORTB_07 //软件IIC DAT脚选择
#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率
//*********************************************************************************//
// g-sensor配置 //
//*********************************************************************************//
#define TCFG_GSENSOR_ENABLE 1 //gSensor使能
// 选择findmy产品使用的加速度传感器,需有且只选一款
#define TCFG_SC7A20_EN 1
#define TCFG_SC7A20_E_EN 0
#define TCFG_MSA310_EN 0
#define GSENSOR_POWER_IO IO_PORTA_07 // gsensor是否采用IO口供电,如不采用IO口供电,需注释此宏定义
#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC 目前只适配软件IIC
4.3.13.7.3. gsensor调试功能
以下步骤为为测试gsensor初始化和工作是否正常
打开gsensor相关文件打印
Motion_api.h
- #define GSENSOR_PRINTF_ENABLE 0//contrl debug printf
+ #define GSENSOR_PRINTF_ENABLE 1//contrl debug printf
app_config.h
//debug for test sensor is moving
- #define FMY_DEBUG_TEST_MOTION_DETETION 0
+ #define FMY_DEBUG_TEST_MOTION_DETETION 1
按键测试(短按两下adkey1每10s采集一次gsensor数据进行运动检测,而后再短按两下adkey1关闭gsensor数据采集)。
ble_fmy_fmna.c
if (event_type == KEY_EVENT_DOUBLE_CLICK) {
switch (key_value) {
case TCFG_ADKEY_VALUE0:
#if FMY_DEBUG_TEST_MOTION_DETETION
if (motion_test_flag) {
sensor_init();
motion_test_id = sys_timer_add(NULL, fmy_test_get_send_sensor_data, 10000);
} else {
sys_timer_del(motion_test_id);
motion_test_id = 0;
sensor_deinit();
}
motion_test_flag = !motion_test_flag;
#endif
break;
}
}
Note
如果传感器初始化和采集数据正常,可以尝试移动旋转传感器观察打印信息看是否检测到移动,如未观测到,则需要检测传感器是否工作正常。
4.3.13.8. UARP功能
4.3.13.8.1. UARP简介
Note
UARP协议是apple 私有的固件升级协议,JL FINDMY SDK已经接入了UARP固件升级功能,用户只需要打开配置即可。
4.3.13.8.2. 使用介绍
board_ac6323a_fmy_global_build_cfg.h
- #define CONFIG_DOUBLE_BANK_ENABLE 0 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构,适用于接入第三方协议的OTA, PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
- #define CONFIG_APP_OTA_ENABLE 0 //是否支持RCSP升级(JL-OTA)
- #define CONFIG_DB_UPDATE_DATA_GENERATE_EN 0 //是否生成db_data.bin(用于第三方协议接入使用)
+#define CONFIG_DOUBLE_BANK_ENABLE 1 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构,适用于接入第三方协议的OTA, PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
+#define CONFIG_APP_OTA_ENABLE 1 //是否支持RCSP升级(JL-OTA)
+ #define CONFIG_DB_UPDATE_DATA_GENERATE_EN 1 //是否生成db_data.bin(用于第三方协议接入使用)
这三个宏也对应打开FMY_AccessoryCapabilities
的FMY_CAPABILITY_SUPPORTS_FW_UPDATE_SERVICE
的特性
ble_fmy_ota.h
#define FMY_OTA_SUPPORT_CONFIG (CONFIG_DOUBLE_BANK_ENABLE && CONFIG_APP_OTA_ENABLE && CONFIG_DB_UPDATE_DATA_GENERATE_EN)
ble_fmy.c
//set capability
static const uint8_t FMY_AccessoryCapabilities[4] = {
.....
#if FMY_OTA_SUPPORT_CONFIG
| FMY_CAPABILITY_SUPPORTS_FW_UPDATE_SERVICE
#endif
.....
};
Note
值得注意的是,打开UARP功能后,编译烧录时可能会提示flash不足的问题,可以尝试关闭一些打印开关后重新调试。(选择512k的flash)
//flash size vaule definition
#define FLASH_SIZE_256K 0x40000
#define FLASH_SIZE_512K 0x80000
#define FLASH_SIZE_1M 0x100000
#define FLASH_SIZE_2M 0x200000
#define FLASH_SIZE_4M 0x400000
#define CONFIG_FLASH_SIZE FLASH_SIZE_512K //配置FLASH大小
//存放token信息
#define CONFIG_FINDMY_INFO_ENABLE 1 //配置是否支持FINDMY存储
#if CONFIG_FINDMY_INFO_ENABLE
#if(CONFIG_FLASH_SIZE == FLASH_SIZE_1M)
//INI里面有个规则是VM一定会放到最前面
#define CONFIG_VM_ADDR 0xFA000 //8K
#define CONFIG_BTIF_ADDR 0xFC000 //4k
#define CONFIG_BTIF_LEN 0x1000
#define CONFIG_BTIF_OPT 1
#define CONFIG_FINDMY_INFO_ADDR 0xFD000 //config user space
#define CONFIG_FINDMY_INFO_LEN 0x2000 //need 8K
#define CONFIG_FINDMY_INFO_OPT 1
#else
#define CONFIG_VM_ADDR 0x7A000 //8K
#define CONFIG_BTIF_ADDR 0x7C000 //4k
#define CONFIG_BTIF_LEN 0x1000
#define CONFIG_BTIF_OPT 1
#define CONFIG_FINDMY_INFO_ADDR 0x7D000 //config user space
#define CONFIG_FINDMY_INFO_LEN 0x2000 //need 8K
#define CONFIG_FINDMY_INFO_OPT 1
#endif
#endif
app_config.h
#ifdef CONFIG_RELEASE_ENABLE
#define LIB_DEBUG 0
#else
- #define LIB_DEBUG 1
+ #define LIB_DEBUG 0
#endif
log_config.c
const char log_tag_const_v_GATT_COMM AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_i_GATT_COMM AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_d_GATT_COMM AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_w_GATT_COMM AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_e_GATT_COMM AT(.LOG_TAG_CONST) = 1;
const char log_tag_const_v_GATT_SERVER AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_i_GATT_SERVER AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_d_GATT_SERVER AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_w_GATT_SERVER AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_e_GATT_SERVER AT(.LOG_TAG_CONST) = 1;
const char log_tag_const_v_GATT_CLIENT AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_i_GATT_CLIENT AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_d_GATT_CLIENT AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_w_GATT_CLIENT AT(.LOG_TAG_CONST) = 0;
const char log_tag_const_e_GATT_CLIENT AT(.LOG_TAG_CONST) = 0;
4.3.13.8.3. UARP功能使用测试
首先按照快速上手的章节成功完成了findmy的绑定配置并且配置了UARP功能,打印显示UARP功能已开启,完成绑定连接后可以看到固件的版本号
在sdk工程修改
ble_fmy_cfg.h
文件将默认版本号修改(需要领先于当前版本号)
//===============================================================
//firmware version config
#define FMY_FW_VERSION_MAJOR_NUMBER 1
#define FMY_FW_VERSION_MINOR_NUMBER 0
#define FMY_FW_VERSION_REVISION_NUMBER 10
重新编译工程,可以在
fw-AC63_BT_SDK-master\cpu\bd19\tools\download\data_trans
看到新生成的db_update_data.bin
文件,可以使用改文件进行UARP文件的打包
使用U盘将该文件传输到MAC电脑,使用mac电脑上的
mfigr2
工具生成uarp文件依次输入下面两条命令,生成完UARPMFiMetaDataTable2文件后修改UARPMFiMetaDataTable2的信息
./mfigr2 superbinary generate mfiMetaData=UARPMFiMetaDataTable2.plist ./mfigr2 superbinary generate mfiPlist=MyUARPSuperBinary.plist
SuperBinary Firmware Version(对应SDK中的固件版本1.0.10)
Payload Filepath(从u盘拷贝过来的杰理bin文件)
Payload Version ((对应SDK中的固件版本1.0.10))
输入下面命令生成.uarp升级文件,文件名字要对应
db_update_bin_v1010.bin
./mfigr2 superbinary compose metaDataFilepath=UARPMFiMetaDataTable2.plist payloadsFilepath=db_update_bin_v1010.bin plistFilepath=MyUARPSuperBinary.plist superBinaryFilepath=test-23-v144.uarp
Note
在mac电脑生成完UARP文件后将其使用隔空投送发送到iphone上,就使用FMCA软件进行firmware update的测试操作,点击升级即可(偶尔会未有升级可用按键,可以尝试重启手机,重新选择uarp文件,再回到查找app),此时可以看到打印在不断的刷屏打印ota数据说明正在升级中,升级完成后会自动重启!
4.3.13.9. 按键调试
用户可以添加button行为来调试产品的一些按键特性
配置io_key或者ad_key:board_ac6323a_fmy_cfg.h
//*********************************************************************************//
// iokey 配置 //
//*********************************************************************************//
#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键
#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO
#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口
#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO
#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00
#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO
#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02
//*********************************************************************************//
// adkey 配置 //
//*********************************************************************************//
#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE //是否使能AD按键
#define TCFG_ADKEY_PORT IO_PORTA_09 //AD按键端口(需要注意选择的IO口是否支持AD功能)
/*AD通道选择,需要和AD按键的端口相对应:
AD_CH_PA1 AD_CH_PA3 AD_CH_PA4 AD_CH_PA5
AD_CH_PA9 AD_CH_PA1 AD_CH_PB1 AD_CH_PB4
AD_CH_PB6 AD_CH_PB7 AD_CH_DP AD_CH_DM
AD_CH_PB2
*/
按键行为控制:ble_fmy_fmna.c
void fmy_ble_key_event_handler(u8 event_type, u8 key_value)
{
log_info("%s: event= %d,key= %d", __FUNCTION__, event_type, key_value);
if (event_type == KEY_EVENT_DOUBLE_CLICK) {
switch (key_value) {
case TCFG_ADKEY_VALUE0:
#if FMY_DEBUG_TEST_MOTION_DETETION
if (motion_test_flag) {
sensor_init();
motion_test_id = sys_timer_add(NULL, fmy_test_get_send_sensor_data, 10000);
} else {
sys_timer_del(motion_test_id);
motion_test_id = 0;
sensor_deinit();
}
motion_test_flag = !motion_test_flag;
#endif
break;
}
}
if (event_type == KEY_EVENT_CLICK) {
switch (key_value) {
case TCFG_ADKEY_VALUE0:
log_info(">>>test to enable start pairing adv");
fmy_pairing_reset_address();
fmy_pairing_restart_adv();
break;
case TCFG_ADKEY_VALUE1:
case TCFG_ADKEY_VALUE7:
log_info(">>>test to low battery");
fmy_test_switch_battery_level(BAT_STATE_CRITICALLY_LOW);
break;
case TCFG_ADKEY_VALUE2:
case TCFG_ADKEY_VALUE8:
log_info(">>>test to enable serialnumber_lookup read");
fmna_paired_serialnumber_lookup_enable(1);
break;
default:
break;
}
}
if (event_type == KEY_EVENT_LONG) {
switch (key_value) {
case TCFG_ADKEY_VALUE0:
log_info(">>>test to reset accessory");
__fy_vm->reset_config = 1;
fmy_vm_deal(__fy_vm, 1);
fmna_plaform_reset_config();
fmy_systerm_reset(30);
break;
case TCFG_ADKEY_VALUE1:
case TCFG_ADKEY_VALUE7:
log_info(">>>test to full battery");
fmy_test_switch_battery_level(BAT_STATE_FULL);
break;
case TCFG_ADKEY_VALUE2:
case TCFG_ADKEY_VALUE8:
log_info(">>>test to disable serialnumber_lookup read");
fmna_paired_serialnumber_lookup_enable(0);
break;
default:
break;
}
}
if (event_type == KEY_EVENT_CLICK || event_type == KEY_EVENT_LONG) {
#ifdef LED_KEY_GAPIO_PORT
PORT_IO_OUPUT(LED_KEY_GAPIO_PORT, PORT_VALUE_HIGH);
sys_timeout_add(0, fmy_led_timeout_handle, 500);
#endif
}
}
4.3.13.10. findmy电池相关功能
在配对时,IOS主机将会读取配件的产品信息,其中包括此时产品的电量,用户根据产品电池特性来设置电池类型。
fmna_api.h
/*
0 = Powered
1 = Non-rechargeable battery
2 = Rechargeable battery
*/
typedef enum {
FMNA_BAT_POWERED = 0,
FMNA_BAT_NON_RECHARGEABLE,
FMNA_BAT_RECHARGEABLE,
} FMNA_battery_level_t;
使用杰理平台的电量检测来获取产品的电量数据
fmna_api.h
typedef enum {
BAT_STATE_FULL = 0,
BAT_STATE_MEDIUM,
BAT_STATE_LOW,
BAT_STATE_CRITICALLY_LOW,//5.1.4,stop advertising
} fmna_bat_state_level_t;
ble_fmy.c
static void fmy_update_battery_level(void)
{
#if TCFG_SYS_LVD_EN
uint8_t bat_level = get_cur_battery_level();//0~9
log_info("read vbat:%d\n", bat_level);
if (bat_level > 8) {
__fydata->battery_level = BAT_STATE_FULL;
} else if (bat_level < 2) {
__fydata->battery_level = BAT_STATE_CRITICALLY_LOW;
} else if (bat_level < 4) {
__fydata->battery_level = BAT_STATE_LOW;
} else {
__fydata->battery_level = BAT_STATE_MEDIUM;
}
#else
__fydata->battery_level = BAT_STATE_FULL;
#endif
log_info("%s,bat_lev= %d", __FUNCTION__, __fydata->battery_level);
}
4.3.13.11. 常用api介绍
已封装以下控制行为函数,可根据产品特性功能使用
模拟设置配件电量
void fmy_test_switch_battery_level(u8 bat_val);
bat_val – 电池状态值可参考以下结构体
typedef enum {
BAT_STATE_FULL = 0,
BAT_STATE_MEDIUM,
BAT_STATE_LOW,
BAT_STATE_CRITICALLY_LOW,//5.1.4,stop advertising
} fmna_bat_state_level_t;
获得电池电量状态
static int fmy_get_battery_level(void);
打开/关闭serial number_lookup read
void fmna_paired_serialnumber_lookup_enable(uint8_t enable)
enable:true/false打开或关闭
恢复出厂设置并重启
void fmna_plaform_reset_config(void)
static void fmy_systerm_reset(u32 delay_ticks);
进入软关机
void fmy_power_event_to_user(u8 event);
想要进入软关机可调用:fmy_power_event_to_user(POWER_EVENT_POWER_SOFTOFF);
更换mac地址重新打开广播
static void fmy_pairing_reset_address(void);
static void fmy_pairing_restart_adv(void)
4.3.13.12. 常见问题汇总
codeblocks提示tkn文件不存在
Warning
没有把tkn文件放到指定路径,需要向杰理申请tkn授权文件
绑定时显示无法继续
Note
没有使用正确的apple授权信息,或者存储信息错误,需要重新擦写授权信息