| @@ -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> | |||