@@ -81,6 +81,8 @@ | |||
<activity android:name=".modules.blood_glucose.BloodGlucoseActivity" /> | |||
<activity android:name=".modules.blood_glucose.BloodGlucoseTestActivity" /> | |||
<activity android:name=".BLDWeightScaleBleActivity" /> | |||
<activity android:name=".ToothBrushBleActivity"/> | |||
<service android:name="com.pingwang.bluetoothlib.server.ELinkBleServer"/> | |||
</application> |
@@ -2,11 +2,9 @@ package aicare.net.cn.sdk.ailinksdkdemoandroid; | |||
import android.content.Intent; | |||
import android.os.Message; | |||
import android.util.Log; | |||
import android.view.View; | |||
import android.widget.TextView; | |||
import com.besthealth.bhBodyComposition120.BhBodyComposition; | |||
import com.pingwang.bluetoothlib.AILinkSDK; | |||
import com.pingwang.bluetoothlib.utils.BleLog; | |||
@@ -124,6 +122,7 @@ public class MainActivity extends BleAppBaseActivity { | |||
mList.add(findViewById(R.id.btn_rope_skip)); | |||
mList.add(findViewById(R.id.btn_broadcast_nutrition)); | |||
mList.add(findViewById(R.id.btn_ble_nutrition)); | |||
mList.add(findViewById(R.id.btn_toothbrush_ble)); | |||
for (View view : mList) { | |||
view.setOnClickListener(listener); | |||
} | |||
@@ -224,6 +223,9 @@ public class MainActivity extends BleAppBaseActivity { | |||
case R.id.btn_wifi_ble_tooth: | |||
type = BleDeviceConfig.TOOTHBRUSH_WIFI_BLE; | |||
break; | |||
case R.id.btn_toothbrush_ble: | |||
type = BleDeviceConfig.TOOTHBRUSH_BLE; | |||
break; | |||
case R.id.btn_ble_weight: | |||
type = BleDeviceConfig.WEIGHT_BODY_FAT_SCALE; | |||
break; |
@@ -48,6 +48,7 @@ import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.food_temp.FoodTempActivity | |||
import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_charger.ShareChargerActivity; | |||
import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_condom.ShareCondomActivity; | |||
import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_socket.ShareSocketActivity; | |||
import androidx.annotation.NonNull; | |||
import androidx.annotation.Nullable; | |||
import androidx.appcompat.app.AppCompatActivity; | |||
@@ -193,14 +194,23 @@ public class ShowBleActivity extends AppCompatActivity implements OnCallbackBle, | |||
showLoading(); | |||
} | |||
} else if (BleDeviceConfig.TOOTHBRUSH_WIFI_BLE == mType) { | |||
mBluetoothService.stopScan(); | |||
Intent intent = new Intent(); | |||
intent.setClass(ShowBleActivity.this, ToothBrushWifiBleActivity.class); | |||
intent.putExtra("type", mType); | |||
intent.putExtra("type", mCid); | |||
intent.putExtra("mac", mac); | |||
startActivity(intent); | |||
finish(); | |||
} else { | |||
} else if (BleDeviceConfig.TOOTHBRUSH_BLE==mType){ | |||
mBluetoothService.stopScan(); | |||
Intent intent = new Intent(); | |||
intent.setClass(ShowBleActivity.this, ToothBrushBleActivity.class); | |||
intent.putExtra("type", mCid); | |||
intent.putExtra("mac", mac); | |||
startActivity(intent); | |||
finish(); | |||
}else { | |||
if (mCid == BleDeviceConfig.BLE_BOOLD_OXYGEN && mVid == 0x0012) { | |||
//vid=12的不用握手校验,不加密 | |||
mNoEncryptionMac = mac; | |||
@@ -365,8 +375,12 @@ public class ShowBleActivity extends AppCompatActivity implements OnCallbackBle, | |||
intent.setClass(ShowBleActivity.this, WeightScaleWifiBleActivity.class); | |||
break; | |||
case BleDeviceConfig.TOOTHBRUSH_WIFI_BLE: | |||
intent.setClass(ShowBleActivity.this, ToothBrushWifiBleActivity.class); | |||
break; | |||
case BleDeviceConfig.TOOTHBRUSH_BLE: | |||
intent.setClass(ShowBleActivity.this, ToothBrushBleActivity.class); | |||
break; | |||
case BleDeviceConfig.EIGHT_BODY_FAT_SCALE: | |||
intent.setClass(ShowBleActivity.this, EightBodyfatActivity.class); | |||
break; | |||
@@ -420,6 +434,11 @@ public class ShowBleActivity extends AppCompatActivity implements OnCallbackBle, | |||
case BleDeviceConfig.ROPE_SKIPPING: | |||
intent.setClass(ShowBleActivity.this, RopeSkippingActivity.class); | |||
break; | |||
// case BleDeviceConfig.TOOTHBRUSH_TEST: | |||
// // 牙刷测试 | |||
// intent.setClass(ShowBleActivity.this, ToothbrushTestActivity.class); | |||
// break; | |||
case BleDeviceConfig.BLE_NUTRITION_SCALE: | |||
// 蓝牙营养秤 | |||
// intent.setClass(ShowBleActivity.this, BleNutritionActivity.class); | |||
@@ -487,6 +506,7 @@ public class ShowBleActivity extends AppCompatActivity implements OnCallbackBle, | |||
} | |||
return false; | |||
} else { | |||
return mType == cid; | |||
} | |||
@@ -0,0 +1,347 @@ | |||
package aicare.net.cn.sdk.ailinksdkdemoandroid; | |||
import android.content.Intent; | |||
import android.content.pm.ActivityInfo; | |||
import android.os.Bundle; | |||
import android.os.Handler; | |||
import android.os.Message; | |||
import android.util.Log; | |||
import android.view.View; | |||
import android.widget.ArrayAdapter; | |||
import android.widget.EditText; | |||
import android.widget.ListView; | |||
import android.widget.Toast; | |||
import androidx.annotation.Nullable; | |||
import com.pingwang.bluetoothlib.bean.BleValueBean; | |||
import com.pingwang.bluetoothlib.device.BleDevice; | |||
import com.pingwang.bluetoothlib.listener.OnCallbackBle; | |||
import com.pingwang.bluetoothlib.utils.BleLog; | |||
import com.pingwang.bluetoothlib.utils.BleStrUtils; | |||
import java.lang.ref.WeakReference; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import aicare.net.cn.sdk.ailinksdkdemoandroid.base.BleBaseActivity; | |||
import aicare.net.cn.sdk.ailinksdkdemoandroid.config.BleDeviceConfig; | |||
import cn.net.aicare.modulelibrary.module.ToothBrush.ToothBrushBleCmd; | |||
/** | |||
* ble 牙刷 | |||
*/ | |||
public class ToothBrushBleActivity extends BleBaseActivity implements View.OnClickListener, OnCallbackBle,ToothBrushBleUtilsData.BleToothBrushCallback { | |||
private String TAG = ToothBrushBleActivity.class.getName(); | |||
private String mAddress; | |||
private int type; | |||
private List<String> mList; | |||
private ArrayAdapter listAdapter; | |||
private MHandler mMHandler; | |||
private EditText select_gears_et; | |||
private ToothBrushBleUtilsData mToothBrushBleUtilsData; | |||
@Override | |||
protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
super.onCreate(savedInstanceState); | |||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//禁止横屏 | |||
setContentView(R.layout.activity_tooth_brush_ble); | |||
findViewById(R.id.support_unit).setOnClickListener(this); | |||
findViewById(R.id.default_try_out).setOnClickListener(this); | |||
findViewById(R.id.default_time_mode).setOnClickListener(this); | |||
findViewById(R.id.default_mode).setOnClickListener(this); | |||
select_gears_et = findViewById(R.id.select_gears_et); | |||
mAddress = getIntent().getStringExtra("mac"); | |||
type = getIntent().getIntExtra("type", BleDeviceConfig.TOOTHBRUSH_BLE); | |||
mList = new ArrayList<>(); | |||
ListView listView = findViewById(R.id.log_list); | |||
listAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mList); | |||
listView.setAdapter(listAdapter); | |||
WeakReference weakReference = new WeakReference(new MHandler()); | |||
mMHandler = (MHandler) weakReference.get(); | |||
} | |||
@Override | |||
protected void onNewIntent(Intent intent) { | |||
super.onNewIntent(intent); | |||
setIntent(intent); | |||
} | |||
@Override | |||
public void onServiceSuccess() { | |||
//与服务建立连接 | |||
mList.add(0, "服务与界面建立连接成功"); | |||
// mList.add(0, "搜索设备"); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
mBluetoothService.setOnCallback(this); | |||
mBluetoothService.scanLeDevice(30 * 1000); | |||
} | |||
@Override | |||
public void onServiceErr() { | |||
} | |||
@Override | |||
public void unbindServices() { | |||
} | |||
@Override | |||
public void onStartScan() { | |||
} | |||
@Override | |||
public void onScanning(BleValueBean data) { | |||
BleLog.i(TAG, "MAC=" + mAddress + "||CID=" + data.getCid() + "||VID=" + data.getVid() + "||PID=" + data.getPid()); | |||
if (data.getMac().equalsIgnoreCase(mAddress)) { | |||
mBluetoothService.stopScan(); | |||
mBluetoothService.connectDevice(data.getMac()); | |||
} | |||
} | |||
@Override | |||
public void onScanTimeOut() { | |||
} | |||
@Override | |||
public void onConnecting(String mac) { | |||
} | |||
@Override | |||
public void onDisConnected(String mac, int code) { | |||
mList.add(0, "蓝牙已断开"); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onServicesDiscovered(String mac) { | |||
mList.add(0, "蓝牙已连接"); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
stopScanBle(); | |||
BleDevice bleDevice = mBluetoothService.getBleDevice(mAddress); | |||
if (bleDevice != null) { | |||
ToothBrushBleUtilsData.init(bleDevice,this); | |||
mToothBrushBleUtilsData =ToothBrushBleUtilsData.getInstance(); | |||
mMHandler.sendEmptyMessageDelayed(ToRequestToken, 600); | |||
mMHandler.sendEmptyMessageDelayed(GETBATTERY, 800); | |||
} | |||
} | |||
@Override | |||
public void bleOpen() { | |||
} | |||
@Override | |||
public void bleClose() { | |||
} | |||
@Override | |||
public void onClick(View v) { | |||
int id = v.getId(); | |||
if (mToothBrushBleUtilsData != null) | |||
switch (id) { | |||
case R.id.support_unit: | |||
mToothBrushBleUtilsData.getSupportGears(); | |||
break; | |||
case R.id.default_mode: | |||
String gear = select_gears_et.getText().toString().trim(); | |||
if (!gear.isEmpty()) { | |||
String[] gears = null; | |||
if (gear.contains(",")) { | |||
gears = gear.split(","); | |||
} else if (gear.contains(",")) { | |||
gears = gear.split(","); | |||
} else { | |||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||
} | |||
if (gears != null) { | |||
try { | |||
mToothBrushBleUtilsData.setDefault(Integer.parseInt(gears[0]), Integer.parseInt(gears[1]), Integer.parseInt(gears[2])); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||
} | |||
} | |||
} | |||
break; | |||
case R.id.default_try_out: | |||
String gear1 = select_gears_et.getText().toString().trim(); | |||
if (!gear1.isEmpty()) { | |||
String[] gears = null; | |||
if (gear1.contains(",")) { | |||
gears = gear1.split(","); | |||
} else if (gear1.contains(",")) { | |||
gears = gear1.split(","); | |||
} else { | |||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||
} | |||
if (gears != null) { | |||
try { | |||
mToothBrushBleUtilsData.setTryOut(Integer.parseInt(gears[1]), Integer.parseInt(gears[2]), 0, 0); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||
} | |||
} | |||
} | |||
break; | |||
case R.id.default_time_mode: | |||
mToothBrushBleUtilsData.getdefaultGearAndDuration(); | |||
break; | |||
} | |||
} | |||
private final int ToRefreUi = 300; | |||
private final int ConnectWifi = 400; | |||
private final int ToRequestToken = 500; | |||
private final int GETBATTERY = 600; | |||
@Override | |||
public void onVersion(String version) { | |||
mList.add(0, "版本号:" + version); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onGetSupportGears(List<Integer> staif, List<Integer> secondLevel) { | |||
mList.add(0, "牙刷支持的一级档位:" + Arrays.toString(staif.toArray()) + " 二级档位:" + Arrays.toString(secondLevel.toArray())); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onGetBattery(int batteryStatus, int batteryQuantity) { | |||
mList.add(0, "电池状态:" + batteryStatus + " 电量:" + batteryQuantity); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onGetDefaultGearAndDuration(int time, int gear, int gearFrom) { | |||
mList.add(0, "获得到默认的刷牙档位和时长:" + time + " 档位:" + gear + " 档位级别" + gearFrom); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onGetTokenResult(int result) { | |||
String s = ""; | |||
if (result == ToothBrushBleCmd.NO_TOKEN) { | |||
s = "没有"; | |||
} else if (result == ToothBrushBleCmd.HAS_TOKEN) { | |||
s = "已经授权"; | |||
} else if (result == ToothBrushBleCmd.WITHOUT_TOKEN) { | |||
s = "不需要授权"; | |||
} else if (result == ToothBrushBleCmd.SUCCESSTOKEN) { | |||
s = "授权成功"; | |||
} | |||
mList.add(0, "请求授权结果" + result + " " + s); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onGetManualParameter(int time, int hz, int duty) { | |||
mList.add(0, " 获取手动档位的参数: 时长" + time + " 频率" + hz + " 占空比" + duty); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onSetDefaultModeAndManualModeResult(byte type, int result) { | |||
String s = ""; | |||
if (result == 0) { | |||
s = "设置成功"; | |||
} else if (result == 1) { | |||
s = "设置失败"; | |||
} else if (result == 2) { | |||
s = "不支持设置"; | |||
} | |||
if (type == ToothBrushBleCmd.SET_TOOTHBRUSH_TIME_GEARS) { | |||
mList.add(0, " 设置默认刷牙时长和工作档位: 结果" + result + " " + s); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} else { | |||
mList.add(0, " 设置手动设置(自定义)档位: 结果" + result + " " + s); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
} | |||
@Override | |||
public void onTestFinish(int totalTime, int leftTime, int rightTime, int mode, int battery) { | |||
mList.add(0, "刷牙完成: 总时长:" + totalTime + " 左时长:" + leftTime + " 右时长:" + rightTime + " 模式:" + mode + " 电量:" + battery); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onTryOutResult(int result) { | |||
mList.add(0, "设置使用结果:" + result + " ( 0:设置成功 1:设置失败,原因未知 2:不支持设置)"); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onTwoLevelModeDefault(int mode) { | |||
mList.add(0, "获取二级档位默认值:" + mode); | |||
mMHandler.sendEmptyMessage(ToRefreUi); | |||
} | |||
@Override | |||
public void onShowData(String data) { | |||
Log.e("蓝牙牙刷",data); | |||
} | |||
private class MHandler extends Handler { | |||
@Override | |||
public void handleMessage(Message msg) { | |||
super.handleMessage(msg); | |||
switch (msg.what) { | |||
case ToRefreUi: | |||
if (listAdapter != null) { | |||
listAdapter.notifyDataSetChanged(); | |||
} | |||
break; | |||
case ToRequestToken: | |||
mList.add(0, "请求授权"); | |||
mToothBrushBleUtilsData.requestToken(System.currentTimeMillis()); | |||
if (listAdapter != null) { | |||
listAdapter.notifyDataSetChanged(); | |||
} | |||
break; | |||
case GETBATTERY: | |||
mToothBrushBleUtilsData.getBattery(); | |||
break; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,561 @@ | |||
package aicare.net.cn.sdk.ailinksdkdemoandroid; | |||
import com.pingwang.bluetoothlib.device.BaseBleDeviceData; | |||
import com.pingwang.bluetoothlib.device.BleDevice; | |||
import com.pingwang.bluetoothlib.device.BleSendCmdUtil; | |||
import com.pingwang.bluetoothlib.device.SendBleBean; | |||
import com.pingwang.bluetoothlib.device.SendMcuBean; | |||
import com.pingwang.bluetoothlib.listener.OnBleOtherDataListener; | |||
import com.pingwang.bluetoothlib.listener.OnBleVersionListener; | |||
import com.pingwang.bluetoothlib.listener.OnMcuParameterListener; | |||
import com.pingwang.bluetoothlib.utils.BleStrUtils; | |||
import java.lang.ref.WeakReference; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import cn.net.aicare.modulelibrary.module.ToothBrush.ToothBrushBleCmd; | |||
/** | |||
* 如果在解析包中。找不到这个类。可以直接把代码复制过去 | |||
* 如果有这个类。这个类只演示用 | |||
*/ | |||
public class ToothBrushBleUtilsData extends BaseBleDeviceData { | |||
public final static int TOOTHBRUSH_BLE = 0x2d; | |||
private BleDevice mBleDevice = null; | |||
private volatile static ToothBrushBleUtilsData toothBrushBleUtilsData = null; | |||
private ToothBrushBleUtilsData(BleDevice bleDevice, BleToothBrushCallback bleToothBrushCallback) { | |||
super(bleDevice); | |||
mBleDevice = bleDevice; | |||
this.bleToothBrushCallback = bleToothBrushCallback; | |||
mBleDevice.setOnBleVersionListener(new OnBleVersionListener() { | |||
@Override | |||
public void onBmVersion(String version) { | |||
//蓝牙版本号 | |||
if (bleToothBrushCallback != null) | |||
bleToothBrushCallback.onVersion(version); | |||
} | |||
}); | |||
bleDevice.setOnMcuParameterListener(new OnMcuParameterListener() { | |||
@Override | |||
public void onMcuBatteryStatus(int status, int battery) { | |||
if (bleToothBrushCallback != null) | |||
bleToothBrushCallback.onGetBattery(status, battery); | |||
} | |||
}); | |||
mBleDevice.setOnBleOtherDataListener(new OnBleOtherDataListener() { | |||
@Override | |||
public void onNotifyOtherData(byte[] data) { | |||
} | |||
}); | |||
} | |||
public static ToothBrushBleUtilsData getInstance() { | |||
return toothBrushBleUtilsData; | |||
} | |||
/** | |||
* 初始化话 | |||
* | |||
* @param bleDevice 蓝牙操作类 | |||
* @param bleCallback 蓝牙基础回调接口 | |||
*/ | |||
public static void init(BleDevice bleDevice, BleToothBrushCallback bleCallback) { | |||
toothBrushBleUtilsData=null; | |||
toothBrushBleUtilsData=new ToothBrushBleUtilsData(bleDevice,bleCallback); | |||
} | |||
/** | |||
* 获取到蓝牙设备对象 | |||
* | |||
* @return 蓝牙设备 | |||
*/ | |||
public BleDevice getBleDevice() { | |||
WeakReference weakReference = new WeakReference(mBleDevice); | |||
return (BleDevice) weakReference.get(); | |||
} | |||
@Override | |||
public void onNotifyData(byte[] bytes, int type) { | |||
if (bleToothBrushCallback != null) | |||
bleToothBrushCallback.onShowData("蓝牙返回的A7: " + BleStrUtils.byte2HexStr(bytes)); | |||
switch (bytes[0]) { | |||
case ToothBrushBleCmd.GET_TOOTHBRUSH_TIME_GEARS: | |||
if (bytes.length >= 5) { | |||
int highTime = (bytes[1] & 0xff) << 8; | |||
int lowTime = bytes[2] & 0xff; | |||
int gears = bytes[3] & 0xff; | |||
int gearsfrom = bytes[4] & 0xff; | |||
if (bleToothBrushCallback != null) | |||
bleToothBrushCallback.onGetDefaultGearAndDuration(highTime + lowTime, gears, gearsfrom); | |||
} | |||
break; | |||
case ToothBrushBleCmd.SET_TOOTHBRUSH_TIME_GEARS: | |||
case ToothBrushBleCmd.Set_Manual_Mode: | |||
if (bytes.length >= 2) { | |||
if (bleToothBrushCallback != null) | |||
bleToothBrushCallback.onSetDefaultModeAndManualModeResult(bytes[0], bytes[1] & 0xff); | |||
} | |||
break; | |||
case ToothBrushBleCmd.Get_Manual_Mode: | |||
if (bytes.length >= 7) { | |||
int hzH = (bytes[2] & 0xff) << 8; | |||
int hzl = bytes[3] & 0xff; | |||
int duty = bytes[4] & 0xff; | |||
int timeH = (bytes[5] & 0xff) << 8; | |||
int timeL = bytes[6] & 0xff; | |||
if (bleToothBrushCallback != null) { | |||
bleToothBrushCallback.onGetManualParameter(timeH + timeL, hzH + hzl, duty); | |||
} | |||
} | |||
break; | |||
case (byte) ToothBrushBleCmd.Brush_Teeth_to_Complete: | |||
if (bytes.length >= 9) { | |||
int mode = bytes[1] & 0xff; | |||
int timeH = (bytes[2] & 0xff) << 8; | |||
int timeL = bytes[3] & 0xff; | |||
int lTimeH = (bytes[4] & 0xff) << 8; | |||
int lTimeL = bytes[5] & 0xff; | |||
int rTimeH = (bytes[6] & 0xff) << 8; | |||
int rTimeL = bytes[7] & 0xff; | |||
int battery = bytes[8] & 0xff; | |||
if (bleToothBrushCallback != null) { | |||
bleToothBrushCallback.onTestFinish(timeH + timeL, lTimeH + lTimeL, rTimeH + rTimeL, mode, battery); | |||
} | |||
} | |||
break; | |||
case ToothBrushBleCmd.The_Trial_Order: | |||
//试用指令 | |||
if (bytes.length >= 2) | |||
if (bleToothBrushCallback != null) { | |||
bleToothBrushCallback.onTryOutResult(bytes[1] & 0xff); | |||
} | |||
break; | |||
case ToothBrushBleCmd.Get_Second_GEARS: | |||
if (bytes.length >= 2) | |||
if (bleToothBrushCallback != null) { | |||
bleToothBrushCallback.onTwoLevelModeDefault(bytes[1] & 0xff); | |||
} | |||
} | |||
} | |||
@Override | |||
public void onNotifyDataA6(byte[] hex) { | |||
if (bleToothBrushCallback != null) | |||
bleToothBrushCallback.onShowData("蓝牙返回的A6: " + BleStrUtils.byte2HexStr(hex)); | |||
switch (hex[0]) { | |||
case (byte) ToothBrushBleCmd.GET_TOOTHBRUSH_GEARS: | |||
disposeSupportGears(hex); | |||
break; | |||
case ToothBrushBleCmd.REQUEST_TOKEN: | |||
int result = hex[1] & 0xff; | |||
if (bleToothBrushCallback != null) { | |||
bleToothBrushCallback.onGetTokenResult(result); | |||
} | |||
break; | |||
} | |||
} | |||
private void disposeSupportGears(byte[] hex) { | |||
if (hex.length > 4 && hex[1] == 0x01) { | |||
int stair = hex[2] & 0xff; | |||
int secondLevel = hex[3] & 0xff; | |||
List<Integer> stairs = new ArrayList<>(); | |||
List<Integer> secondLevels = new ArrayList<>(); | |||
if (hex.length >= 4 + stair) { | |||
for (int i = 0; i < stair; i++) { | |||
stairs.add((int) hex[i + 4] & 0xff); | |||
} | |||
} | |||
if (hex.length >= 4 + stair + secondLevel) { | |||
for (int i = 0; i < secondLevel; i++) { | |||
secondLevels.add((int) hex[i + 4 + stair] & 0xff); | |||
} | |||
} | |||
if (bleToothBrushCallback != null) | |||
bleToothBrushCallback.onGetSupportGears(stairs, secondLevels); | |||
} | |||
} | |||
private BleToothBrushCallback bleToothBrushCallback; | |||
public interface BleToothBrushCallback { | |||
/** | |||
* 版本号 | |||
* version number | |||
* | |||
* @param Version | |||
*/ | |||
void onVersion(String Version); | |||
/** | |||
* 牙刷支持的档位 | |||
* Gear supported by toothbrush | |||
* | |||
* @param staif 一级档位 First gear | |||
* @param secondLevel 二级档位 Second gear | |||
*/ | |||
void onGetSupportGears(List<Integer> staif, List<Integer> secondLevel); | |||
/** | |||
* 获取电量 | |||
* Get battery | |||
* | |||
* @param batteryStatus 电池充电状态 Battery charging status | |||
* 0x00:没有充电(默认) 0x00: No charging (default) | |||
* 0x01:充电中 0x01: Charging | |||
* 0x02:充满电 0x02: Fully charged | |||
* 0x03:充电异常 0x03: abnormal charging | |||
* @param batteryQuantity 电池电量百分比 (0—100) Battery power percentage (0-100) | |||
*/ | |||
void onGetBattery(int batteryStatus, int batteryQuantity); | |||
/** | |||
* 获得到默认的刷牙档位和时长 | |||
* Get the default brushing position and duration | |||
* | |||
* @param time 刷牙时长 Brushing time | |||
* @param gear 刷牙档位 Brushing gear | |||
* @param gearFrom 刷牙档位级别 Brushing gear level | |||
*/ | |||
void onGetDefaultGearAndDuration(int time, int gear, int gearFrom); | |||
/** | |||
* 请求授权的回调 | |||
* Callback to request authorization | |||
* | |||
* @param result 0:没有 1:已经授权 2:不需要授权 3:授权成功 {@link ToothBrushBleCmd#NO_TOKEN} | |||
*/ | |||
void onGetTokenResult(int result); | |||
/** | |||
* 获取手动档位的参数 | |||
* Get the parameters of manual gear | |||
* | |||
* @param time 时长 duration | |||
* @param hz 频率 frequency | |||
* @param duty 占空比 Duty cycle | |||
*/ | |||
void onGetManualParameter(int time, int hz, int duty); | |||
/** | |||
* 设置默认档位和手动模式结果回调 | |||
* | |||
* @param type 类型 {@link ToothBrushBleCmd#SET_TOOTHBRUSH_TIME_GEARS, ToothBrushBleCmd#Set_Manual_Mode} | |||
* @param result 0:设置成功 1:设置失败 2:不支持设置 | |||
*/ | |||
void onSetDefaultModeAndManualModeResult(byte type, int result); | |||
/** | |||
* 刷牙完成 | |||
* Brushing is done | |||
* | |||
* @param totalTime 刷牙总时长 Total brushing time | |||
* @param leftTime 左边刷牙时间 Brushing time on the left | |||
* @param rightTime 右边刷牙时间 Brushing time on the right | |||
* @param mode 刷牙模式 Brushing mode | |||
* @param battery 电量 Power | |||
*/ | |||
void onTestFinish(int totalTime, int leftTime, int rightTime, int mode, int battery); | |||
/** | |||
* 试用回调 | |||
* Trial callback | |||
* | |||
* @param result 0:设置成功 0: Setting is successful | |||
* 1:设置失败,原因未知 1: Setting fails, the reason is unknown | |||
* 2:不支持设置 2: Setting is not supported | |||
*/ | |||
void onTryOutResult(int result); | |||
/** | |||
* 获取二级档位默认值 | |||
* Get the default value of the second gear | |||
* | |||
* @param mode 0x00:不支持 0x00: not supported | |||
* 0x01-0xfe:工作档位编号 0x01-0xfe: working gear number | |||
* 0xFF:手动设置档位 0xFF: manual setting of gear | |||
*/ | |||
void onTwoLevelModeDefault(int mode); | |||
/** | |||
* 蓝牙返回的数据 | |||
* Data returned by Bluetooth | |||
* | |||
* @param data | |||
*/ | |||
void onShowData(String data); | |||
} | |||
/** | |||
* 获取支持的单位 A6指令 | |||
* Supported unit | |||
*/ | |||
public void getSupportGears() { | |||
byte[] bytes = new byte[2]; | |||
bytes[0] = ToothBrushBleCmd.GET_TOOTHBRUSH_GEARS; | |||
bytes[1] = 0x01; | |||
sendA6(bytes); | |||
} | |||
/** | |||
* 获取到电量 | |||
* Get power | |||
*/ | |||
public void getBattery() { | |||
sendA6(BleSendCmdUtil.getInstance().getMcuBatteryStatus()); | |||
} | |||
/** | |||
* 获取默认模式和时长 | |||
* Get the default mode and duration | |||
*/ | |||
public void getdefaultGearAndDuration() { | |||
byte[] bytes = new byte[1]; | |||
bytes[0] = ToothBrushBleCmd.GET_TOOTHBRUSH_TIME_GEARS; | |||
sendA7(bytes); | |||
} | |||
public void setOta() { | |||
// 91 01 | |||
byte[] bytes = new byte[2]; | |||
bytes[0] = (byte) 0x91; | |||
bytes[1] = 0x01; | |||
sendA6(bytes); | |||
} | |||
/** | |||
* 发起连接 | |||
* Initiate connection | |||
* | |||
* @return | |||
*/ | |||
public void connectWifi() { | |||
byte[] bytes = new byte[2]; | |||
bytes[0] = (byte) 0x88; | |||
bytes[1] = 0x01; | |||
sendA6(bytes); | |||
} | |||
/** | |||
* 设置试用 | |||
* Set up trial | |||
*/ | |||
public void setTryOut(int id, int level, int hz, int duty) { | |||
byte[] bytes = new byte[14]; | |||
bytes[0] = ToothBrushBleCmd.The_Trial_Order; | |||
bytes[1] = (byte) id; | |||
bytes[2] = (byte) level; | |||
bytes[3] = (byte) 0xff; | |||
bytes[4] = (byte) (hz >> 8); | |||
bytes[5] = (byte) hz; | |||
bytes[6] = (byte) duty; | |||
bytes[7] = (byte) 0; | |||
bytes[8] = (byte) 0; | |||
bytes[9] = (byte) 0; | |||
bytes[10] = (byte) 0; | |||
bytes[11] = (byte) 0; | |||
bytes[12] = (byte) 0; | |||
bytes[13] = (byte) 0; | |||
sendA7(bytes); | |||
} | |||
/** | |||
* 设置默认 | |||
* Set the default | |||
*/ | |||
public void setDefault(int time, int mode, int level) { | |||
byte[] bytes = new byte[5]; | |||
bytes[0] = ToothBrushBleCmd.SET_TOOTHBRUSH_TIME_GEARS; | |||
bytes[1] = (byte) (time >> 8); | |||
bytes[2] = (byte) time; | |||
bytes[3] = (byte) mode; | |||
bytes[4] = (byte) level; | |||
sendA7(bytes); | |||
} | |||
/** | |||
* 下发数据上报成功 | |||
* Successfully sent data and reported | |||
*/ | |||
public void testFinishSuccess() { | |||
byte[] bytes = new byte[2]; | |||
bytes[0] = (byte) ToothBrushBleCmd.Issue_Data_Report_Completed; | |||
bytes[1] = 0x01; | |||
sendA7(bytes); | |||
} | |||
/** | |||
* APP 设置二级档位默认值 | |||
* Set the default value of the second gear | |||
*/ | |||
public void setTwoLevelDefault(int modeId) { | |||
byte[] bytes = new byte[2]; | |||
bytes[0] = ToothBrushBleCmd.Set_Second_GEARS; | |||
bytes[1] = (byte) modeId; | |||
sendA7(bytes); | |||
} | |||
/** | |||
* APP 获取二级档位默认值 | |||
*/ | |||
public void getTwoLevelDefault() { | |||
byte[] bytes = new byte[1]; | |||
bytes[0] = ToothBrushBleCmd.Get_Second_GEARS; | |||
sendA7(bytes); | |||
} | |||
/** | |||
* 开始刷牙 | |||
* Get the default value of the second gear | |||
*/ | |||
public void starTooth() { | |||
byte[] bytes = new byte[1]; | |||
bytes[0] = ToothBrushBleCmd.Start_Close_ToothBrush; | |||
sendA7(bytes); | |||
} | |||
/** | |||
* 设置手动模式的参数 | |||
* Set the parameters of manual mode | |||
*/ | |||
public void setManualParameter(int hz, int duty, int time) { | |||
byte[] bytes = new byte[7]; | |||
bytes[0] = ToothBrushBleCmd.Set_Manual_Mode; | |||
bytes[1] = 0x00; | |||
bytes[2] = (byte) (hz >> 8); | |||
bytes[3] = (byte) hz; | |||
bytes[4] = (byte) duty; | |||
bytes[5] = (byte) (time >> 8); | |||
bytes[6] = (byte) time; | |||
sendA7(bytes); | |||
} | |||
/** | |||
* 获取手动模式的参数 | |||
* Get the parameters of manual mode | |||
*/ | |||
public void getManualParameter() { | |||
byte[] bytes = new byte[1]; | |||
bytes[0] = ToothBrushBleCmd.Get_Manual_Mode; | |||
sendA7(bytes); | |||
} | |||
/** | |||
* APP 请求授权 Payload | |||
* Request authorization | |||
* | |||
* @param toothbrushId 时间搓 | |||
*/ | |||
public void requestToken(long toothbrushId) { | |||
byte[] timebyte = long2Bytes(toothbrushId); //long 长度8 byte 时间搓是6个byte 所以去后面6位 | |||
byte[] bytes = new byte[7]; | |||
bytes[0] = ToothBrushBleCmd.REQUEST_TOKEN; | |||
bytes[1] = timebyte[2]; | |||
bytes[2] = timebyte[3]; | |||
bytes[3] = timebyte[4]; | |||
bytes[4] = timebyte[5]; | |||
bytes[5] = timebyte[6]; | |||
bytes[6] = timebyte[7]; | |||
sendA6(bytes); | |||
} | |||
private byte[] long2Bytes(long num) { | |||
byte[] byteNum = new byte[8]; | |||
for (int ix = 0; ix < 8; ++ix) { | |||
int offset = 64 - (ix + 1) * 8; | |||
byteNum[ix] = (byte) ((num >> offset) & 0xff); | |||
} | |||
return byteNum; | |||
} | |||
private SendBleBean sendBleBean; | |||
/** | |||
* 发送A6指令 | |||
* | |||
* @param bytes | |||
*/ | |||
public void sendA6(byte[] bytes) { | |||
if (sendBleBean == null) | |||
sendBleBean = new SendBleBean(); | |||
sendBleBean.setHex(bytes); | |||
sendData(sendBleBean); | |||
} | |||
/** | |||
* 断开连接 | |||
* Disconnect | |||
* | |||
* @return SendBleBean | |||
*/ | |||
public void disconnectWifi() { | |||
byte[] bytes = new byte[2]; | |||
bytes[0] = (byte) 0x88; | |||
bytes[1] = 0x00; | |||
sendA6(bytes); | |||
} | |||
/** | |||
* 发送A7指令 | |||
* | |||
* @param bytes | |||
*/ | |||
public void sendA7(byte[] bytes) { | |||
SendMcuBean sendMcuBean = new SendMcuBean(); | |||
sendMcuBean.setHex(TOOTHBRUSH_BLE, bytes); | |||
sendData(sendMcuBean); | |||
} | |||
} |
@@ -1,5 +1,6 @@ | |||
package aicare.net.cn.sdk.ailinksdkdemoandroid; | |||
import android.content.Intent; | |||
import android.content.pm.ActivityInfo; | |||
import android.os.Bundle; | |||
import android.os.Handler; | |||
@@ -35,6 +36,7 @@ import cn.net.aicare.modulelibrary.module.ToothBrush.ToothBrushWiFiBleUtilsData; | |||
public class ToothBrushWifiBleActivity extends BleBaseActivity implements View.OnClickListener, OnCallbackBle, ToothBrushWiFiBleUtilsData.BleToothBrushWiFiCallback, ToothBrushWiFiBleUtilsData.BleToothBrushCallback { | |||
private String TAG = ToothBrushWifiBleActivity.class.getName(); | |||
private String mAddress; | |||
private List<String> mList; | |||
private ArrayAdapter listAdapter; | |||
@@ -75,6 +77,12 @@ public class ToothBrushWifiBleActivity extends BleBaseActivity implements View.O | |||
} | |||
@Override | |||
protected void onNewIntent(Intent intent) { | |||
super.onNewIntent(intent); | |||
setIntent(intent); | |||
} | |||
@Override | |||
public void onServiceSuccess() { | |||
@@ -135,6 +143,7 @@ public class ToothBrushWifiBleActivity extends BleBaseActivity implements View.O | |||
mBluetoothService.setOnCallback(this); | |||
BleDevice bleDevice = mBluetoothService.getBleDevice(mAddress); | |||
if (bleDevice != null) { | |||
ToothBrushWiFiBleUtilsData.init(bleDevice, this, this); | |||
mToothBrushWiFiBleUtilsData = ToothBrushWiFiBleUtilsData.getInstance(); | |||
mMHandler.sendEmptyMessageDelayed(ToRequestToken, 600); | |||
@@ -341,7 +350,7 @@ public class ToothBrushWifiBleActivity extends BleBaseActivity implements View.O | |||
if (gears != null) { | |||
try { | |||
mToothBrushWiFiBleUtilsData.setTryOut(Integer.parseInt(gears[1]), Integer.parseInt(gears[2]), 0, 0); | |||
} catch (NumberFormatException e) { | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||
} |
@@ -71,6 +71,11 @@ public class BleDeviceConfig { | |||
*/ | |||
public final static int TOOTHBRUSH_WIFI_BLE=0x12; | |||
/** | |||
* 蓝牙牙刷 | |||
*/ | |||
public final static int TOOTHBRUSH_BLE = 0x2D; | |||
/** | |||
* 八电极体脂秤 | |||
*/ | |||
@@ -197,4 +202,5 @@ public class BleDeviceConfig { | |||
*/ | |||
public final static int BROADCAST_NUTRITION = 0x10003; | |||
} |
@@ -94,7 +94,11 @@ | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:text="口罩" /> | |||
<Button | |||
android:id="@+id/btn_toothbrush_ble" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:text="蓝牙牙刷" /> | |||
</LinearLayout> | |||
@@ -0,0 +1,65 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<RelativeLayout | |||
xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:orientation="vertical"> | |||
<Button | |||
android:id="@+id/default_try_out" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="5dp" | |||
android:text="试用" /> | |||
<Button | |||
android:id="@+id/default_mode" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_below="@+id/sn" | |||
android:layout_toEndOf="@id/default_try_out" | |||
android:layout_marginStart="9dp" | |||
android:layout_marginTop="5dp" | |||
android:text="默认档位" /> | |||
<EditText | |||
android:id="@+id/select_gears_et" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_alignTop="@id/default_mode" | |||
android:layout_toEndOf="@id/default_mode" | |||
android:hint="时长(s),档位,档位级别" | |||
android:textSize="14dp" /> | |||
<Button | |||
android:id="@+id/support_unit" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_below="@+id/default_mode" | |||
android:layout_marginTop="5dp" | |||
android:text="获取支持档位" /> | |||
<Button | |||
android:id="@+id/default_time_mode" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_toEndOf="@id/support_unit" | |||
android:layout_below="@+id/default_mode" | |||
android:layout_marginTop="5dp" | |||
android:text="获取时长和档位" /> | |||
<ListView | |||
android:id="@+id/log_list" | |||
android:layout_marginTop="10dp" | |||
android:layout_below="@id/default_time_mode" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent"> | |||
</ListView> | |||
</RelativeLayout> |
@@ -0,0 +1,12 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:orientation="vertical"> | |||
<androidx.recyclerview.widget.RecyclerView | |||
android:id="@+id/recycler_view" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" /> | |||
</LinearLayout> |
@@ -0,0 +1,41 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:minHeight="50dp" | |||
android:orientation="vertical"> | |||
<LinearLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="0dp" | |||
android:layout_weight="1" | |||
android:orientation="horizontal"> | |||
<TextView | |||
android:id="@+id/tv_title" | |||
android:layout_width="0dp" | |||
android:layout_height="match_parent" | |||
android:layout_marginStart="15dp" | |||
android:layout_weight="1" | |||
android:ellipsize="end" | |||
android:gravity="center_vertical" | |||
android:textColor="@android:color/black" | |||
tools:text="请求授权" /> | |||
<TextView | |||
android:id="@+id/tv_result" | |||
android:layout_width="50dp" | |||
android:layout_height="match_parent" | |||
android:gravity="center" | |||
android:textColor="@android:color/holo_blue_dark" | |||
tools:text="OK" /> | |||
</LinearLayout> | |||
<View | |||
android:layout_width="match_parent" | |||
android:layout_height="1dp" | |||
android:background="?android:attr/listDivider" /> | |||
</LinearLayout> |
@@ -0,0 +1,29 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="25dp" | |||
android:background="@android:color/holo_orange_light" | |||
android:orientation="vertical"> | |||
<LinearLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="0dp" | |||
android:layout_weight="1" | |||
android:orientation="horizontal"> | |||
<TextView | |||
android:id="@+id/tv_title" | |||
android:layout_width="0dp" | |||
android:layout_height="match_parent" | |||
android:layout_marginStart="15dp" | |||
android:layout_weight="1" | |||
android:ellipsize="end" | |||
android:gravity="center_vertical" | |||
android:maxLines="2" | |||
android:textColor="@android:color/black" | |||
tools:text="自动测试" /> | |||
</LinearLayout> | |||
</LinearLayout> |