[TOC]
elink体脂秤SDK 是提供给elink合作伙伴的蓝牙开发工具,该SDK对elink蓝牙协议进行了实现和封装,负责手机App与蓝牙体脂秤设备之间的通信,旨在方便合作伙伴定制自己的蓝牙体脂秤应用。
需要个性化定制自己的 Android 蓝牙体脂秤 APP 的合作伙伴。
1,最低版本 android4.4(API 19) 2,设备所使用的蓝牙版本需要4.0及以上 3,依赖环境androidx
repositories {
flatDir {
dirs 'libs'
}
}
步骤1.将JitPack存储库添加到您的构建文件中
将其添加到存储库末尾的root build.gradle中:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
步骤2.添加依赖项
dependencies {
implementation 'com.github.elinkthings:BodyFatScaleSDKRepositoryAndroid:1.2.4'
}
也可以使用aar包依赖,请自行下载放到项目的libs中
<!--In most cases, you need to ensure that the device supports BLE.-->
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!--Android 6.0 and above. Bluetooth scanning requires one of the following two permissions. You need to apply at run time.-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--Optional. If your app need dfu function.-->
<uses-permission android:name="android.permission.INTERNET"/>
6.0及以上系统必须要定位权限,且需要手动获取权限
首先给SDK配置key和secret,申请地址
//在主项目的application中调用
AiFitSDK.getInstance().init(this, key, secret);
在AndroidManifest.xml application标签下面增加
<application>
...
<service android:name="aicare.net.cn.iweightlibrary.wby.WBYService"/>
</application>
你可以直接让你自己的
Activity
类继承BleProfileServiceReadyActivity
public class MyActivity extends BleProfileServiceReadyActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//判断手机设备是否支持Ble
if (!ensureBLESupported()) {
T.showShort(this, R.string.not_support_ble);
finish();
}
//判断是否有定位权限,此方法没有进行封装具体代码可在demo中获得,也可按照自己方式去调用请求权限方法
initPermissions();
//判断蓝牙是否打开,若需要换样式,可自己去实现
if (!isBLEEnabled()) {
showBLEDialog();
}
}
与扫描相关的API如下,详情参考BleProfileServiceReadyActivity类,具体使用参考sample工程
//调用startScan方法开启扫描
startScan();
//getAicareDevice(final BroadData broadData)接口会回调获取到符合Aicare协议的体脂秤设备
@Override
protected void getAicareDevice(BroadData broadData) {
//符合Aicare协议的体脂秤设备
}
//调用stopScan方法停止扫描
stopScan();
//调用isScanning方法查看是否在扫描 true:正在扫描; false:已停止扫描
isScanning();
注意: 如果为广播秤,不需要去执行连接操作,在扫描的回调getAicareDevice(BroadData broadData)方法中可以直接去获取到体脂数据,广播秤调用 stopScan()回获取不到数据
@Override
protected void getAicareDevice(BroadData broadData) {
//广播秤可以直接在此获取数据
if (broadData.getDeviceType() == AicareBleConfig.BM_09) {
if (broadData.getSpecificData() != null) {
BM09Data data = AicareBleConfig.
getBm09Data(broadData.getAddress(),broadData.getSpecificData());
}else if (broadData.getDeviceType() == AicareBleConfig.BM_15) {
if (broadData.getSpecificData() != null) {
BM15Data data = AicareBleConfig.getBm15Data(broadData.getAddress(),
broadData.getSpecificData());
}
}else{
if (broadData.getSpecificData() != null) {
WeightData weightData =
AicareBleConfig.getWeightData(broadData.getSpecificData());
}
}
}
与连接相关的API如下,详情参考BleProfileServiceReadyActivity类,具体使用参考sample工程。
//调用startConnect方法去连接体脂秤设备 需要传入体脂秤设备的mac地址 mac地址
//可以在getAicareDevice(BroadData broadData)回调方法中获得 。
//如果在getAicareDevice(BroadData broadData) 没有做过滤,连接时要去过滤掉广播称,详情见demo连接处
startConnect(String address)
//在onStateChanged可以获取到连接状态
@Override
public void onStateChanged(String deviceAddress, int state) {
super.onStateChanged(deviceAddress, state);
//state 具体状态看类说明
}
//调用WBYService.WBYBinder类中disconnect方法去断开体脂秤
binder.disconnect()
使用
startConnect
方法连接体脂秤,使用onStateChanged
方法监听连接的状态,使用onError
方法监听连接过程中的异常,以便于进行额外的处理和问题排查。使用isDeviceConnected
方法判断连接是否已经建立。
以下方法或接口可直接在继承BleProfileServiceReadyActivity类后自动获得
//onServiceBinded方法中获得WBYService.WBYBinder的实例
@Override
protected void onServiceBinded(WBYService.WBYBinder binder) {
this.binder = binder;
}
//设备返回的变化和稳定的体重数据和温度(AC03才支持)
@Override
protected void onGetWeightData(WeightData weightData) {
//如果想要在这里获取到广播秤数据。需要在getAicareDevice(final BroadData broadData)方法中
//调用onGetWeightData(WeightData weightData)去把数据透传过来
}
//onGetSettingStatus方法中获得设置状态 详情查看AicareBleConfig.SettingStatus
@Override
protected void onGetSettingStatus(int status) {
}
//onGetResul方法中获得获得版本号,测量时间,用户编号,阻抗值
@Override
protected void onGetResult(int index, String result) {
}
// 获得设备返回据历史数据或体脂数据 true为历史数据
@Override
protected void onGetFatData(boolean isHistory, BodyFatData bodyFatData) {
}
//获取设备返回的小数点位数信息
@Override
protected void onGetDecimalInfo(DecimalInfo decimalInfo) {
}
//设备返回的算法序列信息
@Override
protected void onGetAlgorithmInfo(AlgorithmInfo algorithmInfo) {
}
注意:这些接口或方法部分需要APP给体脂下发命令才会有返回数据.
AicareBleConfig.getBodyFatData(AlgorithmUtil.AlgorithmType.TYPE_AIC
ARE, bodyFatData.getSex(), bodyFatData.getAge(),
Double.valueOf(ParseData.getKgWeight(bodyFatData.getWeight(),
bodyFatData.getDecimalInfo())), bodyFatData .getHeight(),
bodyFatData.getAdc());
AicareBleConfig.getMoreFatData(int sex, int height, double weight,
double bfr, double rom, double pp)
在BleProfileServiceReadyActivity.onServiceBinded(WBYService.WBYBinder binder)获得WBYService.WBYBinder的实例,调用binder里面方法
@Override
protected void onServiceBinded(WBYService.WBYBinder binder) {
this.binder = binder;
}
//如获取到历史记录
binder.syncHistory();
//WBYBinder的部分方法
public class WBYBinder extends LocalBinder {
/**
* 获取历史记录
*/
@Deprecated
public void syncHistory() {
mManager.sendCmd(AicareBleConfig.SYNC_HISTORY, AicareBleConfig.UNIT_KG);
}
/**
* 同步当前用户
*
* @param user
*/
public void syncUser(User user) {
if (user == null) {
return;
}
mManager.syncUser(user);
}
/**
* 同步用户列表
*
* @param userList
*/
@Deprecated
public void syncUserList(List<User> userList) {
mManager.syncUserList(userList);
}
/**
* 同步当前单位
*
* @param unit {@link AicareBleConfig#UNIT_KG}
* {@link AicareBleConfig#UNIT_LB}
* {@link AicareBleConfig#UNIT_ST}
* {@link AicareBleConfig#UNIT_JIN}
*/
public void syncUnit(byte unit) {
mManager.sendCmd(AicareBleConfig.SYNC_UNIT, unit);
}
/**
* 同步时间
*/
@Deprecated
public void syncDate() {
mManager.syncDate();
}
/**
* 查询蓝牙版本信息
*/
@Deprecated
public void queryBleVersion() {
mManager.sendCmd(AicareBleConfig.GET_BLE_VERSION, AicareBleConfig.UNIT_KG);
}
/**
* 更新用户信息
*
* @param user
*/
@Deprecated
public void updateUser(User user) {
if (user == null) {
return;
}
mManager.updateUser(user);
}
/**
* 设置模式
*/
public void setMode(@AicareBleConfig.MODE int cmd) {
mManager.setMode(cmd);
}
/**
* 校验是否授权
*/
@Deprecated
public void auth() {
mManager.auth();
}
/**
* 设置DID
*
* @param did
*/
@Deprecated
public void setDID(int did) {
mManager.sendDIDCmd(AicareBleConfig.SET_DID, did);
}
/**
* 查询DID
*/
@Deprecated
public void queryDID() {
mManager.sendDIDCmd(AicareBleConfig.QUERY_DID, 0);
}
/**
* 获取小数位数
*/
public void getDecimalInfo() {
mManager.getDecimalInfo();
}
}
类型 | 参数名 | 说明 |
---|---|---|
double | weight | 体重 |
int | algorithmId | 算法ID |
int | adc | 阻抗值 |
DecimalInfo | decimalInfo | 小数点位数 |
类型 | 参数名 | 说明 |
---|---|---|
int | agreementType | 协议类型 |
int | unitType | 单位类型 |
DecimalInfo | decimalInfp | 小数点位数 |
double | weight | 体重 |
int | adc | 阻抗值 |
double | temp | 温度 |
int | algorithmId | 算法ID |
int | did | (目前无用) |
String | bleVersion | 蓝牙版本 |
int | bleType | 蓝牙类型(0x09) |
String | address | 设备地址 |
long | timeMillis | 测量时间戳 |
boolean | isStable | 是否稳定 |
类型 | 参数名 | 说明 |
---|---|---|
String | version | 蓝牙版本 |
int | agreementType | 协议类型 |
int | unitType | 单位类型 |
double | weight | 体重 |
int | adc | 阻抗值 |
double | temp | 温度(若temp=6553.5,则表示秤不支持温度) |
int | algorithmId | 算法ID |
int | did | (目前无用) |
int | bleType | 蓝牙类型(0x15) |
String | address | 设备地址 |
类型 | 参数名 | 说明 |
---|---|---|
String | date | 测量日期 |
String | time | 测量时间 |
double | weight | 体重 |
double | bmi | 身体质量指数 |
double | bfr | 体脂率 |
double | sfr | 皮下脂肪率 |
int | uvi | 内脏脂肪指数 |
double | rom | 肌肉率 |
double | bmr | 基础代谢率 |
double | bm | 骨量 |
double | vwc | 水分率 |
double | bodyAge | 身体年龄 |
double | pp | 蛋白率 |
int | number | 编号 |
int | sex | 性别 |
int | age | 年龄(1、男;2、女) |
int | height | 身高 |
int | adc | 阻抗值 |
类型 | 参数名 | 说明 |
---|---|---|
String | name | 设备名 |
String | address | 设备地址 |
boolean | isBright | 是否亮屏 |
int | rssi | 信号值 |
byte[] | specificData | 广播数据 |
int | deviceType | 设备类型 |
类型 | 参数名 | 说明 |
---|---|---|
int | sourceDecimal | 源数据小数点位数 |
int | kgDecimal | kg小数点位数 |
int | lbDecimal | lb小数点位数 |
int | stDecimal | st小数点位数 |
int | kgGraduation | kg分度 |
int | lbGraduation | lb分度 |
类型 | 参数名 | 说明 |
---|---|---|
int | id | 编号 |
int | sex | 性别 |
int | age | 年龄(1、男;2、女) |
int | height | 身高 |
int | weight | 体重 |
int | adc | 阻抗值(弃用) |
类型 | 参数名 | 说明 |
---|---|---|
int | cmdType | 命令类型(1、变化;2、稳定;3、阻抗测量中) |
double | weight | 体重 |
double | temp | 温度(若温度为Double.MAX_VALUE则表示秤不支持温度) |
DecimalInfo | decimalInfo | 小数点位数信息 |
int | adc | 阻抗值 |
int | algorithmType | 算法ID |
int | unitType | 单位类型 |
int | deviceType | 设备类型 |
类型 | 参数名 | 说明 |
---|---|---|
double | bmi | 身体质量指数 |
double | bfr | 体脂率 body fat rate |
double | sfr | 皮下脂肪率 Subcutaneous fat rate |
int | uvi | 内脏脂肪指数 |
double | rom | 肌肉率 Rate of muscle |
int | bmr | 基础代谢率 basal metabolic rate |
double | bm | 骨骼质量 Bone Mass |
double | vwc | 水含量 |
int | bodyAge | 身体年龄 physical bodyAge |
double | pp | 蛋白率 protein percentage |
类型 | 参数名 | 说明 |
---|---|---|
double | standardWeight | 标准体重 |
double | controlWeight | 体重控制量 |
double | fat | 脂肪量 |
double | removeFatWeight | 去脂体重 |
double | muscleMass | 肌肉量 |
double | protein | 蛋白量 |
MoreFatData.FatLevel | fatLevel | 肥胖等级 |
public static enum FatLevel {
UNDER, 体重不足
THIN, 偏瘦
NORMAL, 标准
OVER, 偏重
FAT; 超重
}
public static final int STATE_CONNECTING = 4; //连接中
public static final int STATE_DISCONNECTED = 0; //断开连接
public static final int STATE_CONNECTED = 1;//连接成功
public static final int STATE_SERVICES_DISCOVERED = 2;//发现服务
public static final int STATE_INDICATION_SUCCESS = 3;//使能成功
public static final int STATE_TIME_OUT = 5;//连接超时
int NORMAL = 0;//正常
int LOW_POWER = 1;//低功耗
int LOW_VOLTAGE = 2;//低电压
int ERROR = 3;//超载
int TIME_OUT = 4;//超时
int UNSTABLE = 5;//称不稳定
int SET_UNIT_SUCCESS = 6;//设置单位成功
int SET_UNIT_FAILED = 7;//设置单位失败
int SET_TIME_SUCCESS = 8;//设置时间成功
int SET_TIME_FAILED = 9;//设置时间失败
int SET_USER_SUCCESS = 10;//设置用户成功
int SET_USER_FAILED = 11;//设置用户失败
int UPDATE_USER_LIST_SUCCESS = 12;//更新用户列表成功
int UPDATE_USER_LIST_FAILED = 13;//更新用户列表失败
int UPDATE_USER_SUCCESS = 14;//更新用户成功
int UPDATE_USER_FAILED = 15;//更新用户失败
int NO_HISTORY = 16;//没有历史数据
int HISTORY_START_SEND = 17;//历史数据开始发送
int HISTORY_SEND_OVER = 18;//历史数据发送完成
int NO_MATCH_USER = 19;//没有匹配的用户
int ADC_MEASURED_ING = 20;//阻抗测量中
int ADC_ERROR = 21;//阻抗测量失败
int REQUEST_DISCONNECT = 22;//设备请求断开
int SET_DID_SUCCESS = 23;//设置DID成功
int SET_DID_FAILED = 24;//设置DID失败
int DATA_SEND_END = 25;//测量数据发送完成
int UNKNOWN = -1;//未知
public final static int BLE_VERSION = 0; //蓝牙版本
public final static int MCU_DATE = 1; //mcu日期
public final static int MCU_TIME = 2; //mcu 时间
public final static int USER_ID = 3; //用户编号
public final static int ADC = 4; //阻抗值
版本号 | 更新时间 | 作者 | 更新信息 |
---|---|---|---|
1.0 | 2017/2/15 | Suzy | 初步版本 |
1.0.1 | 2017/7/31 | Suzy | 修复部分数据转换bug |
1.0.2 | 2017/9/11 | Suzy | 指令中的类型根据实际连上的设备类型设置 |
1.0.3 | 2017/11/16 | Suzy | 代码优化 |
1.0.4 | 2018/7/12 | Suzy | 兼容广播秤 |
1.0.5 | 2018/1/15 | Suzy | 兼容新协议 |
1.0.6 | 2018/2/25 | Suzy | 功能优化 |
1.0.7 | 2018/2/28 | Suzy | 封装小数点位数类 |
1.0.8 | 2018/3/14 | Suzy | 修复身体年龄错误的bug |
1.0.9 | 2018/4/9 | Suzy | 兼容BM09协议 |
1.1.1 | 2018/5/10 | Suzy | 兼容kg/lb分度协议 |
1.1.2 | 2018/5/11 | Suzy | 解决st单位数据跟秤端显示不一致的bug |
1.1.3 | 2018/6/22 | Suzy | 解决小数点位数有时获取不到的bug |
1.1.4 | 2018/7/7 | Suzy | 兼容BM15协议 |
1.1.5 | 2018/7/20 | Suzy | 兼容算法ID协议 |
1.1.7 | 2019/04/30 | Stan | 添加BM15体脂数据计算算法 |
1.1.8 | 2019/06/6 | Stan | 修改原始数据转lb ,st计算错误问题 |
1.1.9 | 2019/12/19 | 增加历史记录 | |
1.2.0 | 2019/1/17 | 更新优化蓝牙库 | |
1.2.1 | 2020/3/19 | 增加体脂数据计算方法和去脂体重算法等 | |
1.2.2 | 2020/3/23 | 修改SDK为gradle形式依赖 | |
1.2.3 | 2020/4/2 | 增加key校验,修改依赖环境为androidx | |
1.2.4 | 2020/4/10 | 修复已知bug |
如何判断区分当前扫描到的BroadData(设备)是广播秤还是连接秤? 1.根据BroadData的deviceType属性值区分: deviceType==AicareBleConfig.TYPE_WEI_BROAD是不带温度的广播秤 deviceType==AicareBleConfig.TYPE_WEI_TEMP_BROAD是有温度的广播秤 deviceType==AicareBleConfig.TYPE_WEI是不带温度的连接秤 deviceType==AicareBleConfig.TYPE_WEI_TEMP是有温度的连接秤
蓝牙协议支持哪些单位? 1.单位最多只支持4种(kg,lb,st,斤),具体支持什么单位请参照秤的出厂设置。
扫描不到蓝牙设备? 1.查看App权限是否正常,6.0及以上系统必须要定位权限,且需要手动获取权限 2.查看手机的定位服务是否开启,部分手机可能需要打开GPS 3.拔掉电池重启秤 4.是否被其他手机连接(秤未被连接时,秤盘上蓝牙图标会不断闪烁)
支持哪些设备? 1.支持BM系列的连接秤、BM15广播秤
连接秤如何判定测量结束? 1.onGetFatData()方法回调就代表测量完成
广播秤如何判定测量结束? 1.广播秤所有的数据都是从getAicareDevice返回并解析得到WeightData对象,WeightData中的getCmdType()==3表示测量完成,详细请参考demo
秤显示的数据和app收到的数据不一致 1.SDK会默认请求获取小数的,可使用WBYBinder中的getDecimalInfo()主动获取小数位 2.app计算重量的时候需要传入DecimalInfo(小数对象)进行计算
DecimalInfo{
private int sourceDecimal;//源数据小数位数
private int kgDecimal;//kg小数位数
private int lbDecimal;//lb小数位数
private int stDecimal;//st小数位数
private int kgGraduation;//kg分度
private int lbGraduation;//lb分度
}
为什么只能测到体重,没有其他体脂数据? 1.必须脱掉鞋和袜子,光脚站在体脂秤的电极片上,才能测出体脂数据。
称量时秤总是显示Error,app显示阻抗测量失败,是什么原因? 1.脱掉鞋和袜子,光脚站在体脂秤的电极片上测量,就不会再显示Error。
如何高效的向技术支持人员提供反馈? 1.SDK会在控制台打印log,反馈问题时请先将log保存为txt,发给技术人员 2.反馈问题时,尽可能将问题出现时的前后操作描述清楚,最好能录制视频告知问题如何复现。
是否有各项体脂数据的判定标准和文案呢? 1.体脂判定标准各厂商标准都可能不一样,目前并没有行业公认的参考标准。如下是我司使用的标准,仅供参考: 《蓝牙体脂秤判定标准及小程序文案20200416》
深圳市易连物联网有限公司
电话:0755-81773367
官网:www.elinkthings.com
邮箱:app@elinkthings.com