| @@ -11,10 +11,12 @@ | |||
| <uses-permission android:name="android.permission.INTERNET" /> | |||
| <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | |||
| <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> | |||
| <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" | |||
| android:maxSdkVersion="30"/> | |||
| <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" | |||
| android:maxSdkVersion="30"/> | |||
| <uses-permission | |||
| android:name="android.permission.ACCESS_COARSE_LOCATION" | |||
| android:maxSdkVersion="30" /> | |||
| <uses-permission | |||
| android:name="android.permission.ACCESS_FINE_LOCATION" | |||
| android:maxSdkVersion="30" /> | |||
| <!--OTA需要读写文件--> | |||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | |||
| @@ -26,9 +28,10 @@ | |||
| android:name="android.permission.BLUETOOTH_ADMIN" | |||
| android:maxSdkVersion="30" /> | |||
| <!--android12还需要增加如下权限,也需求动态申请--> | |||
| <uses-permission android:name="android.permission.BLUETOOTH_SCAN" | |||
| <uses-permission | |||
| android:name="android.permission.BLUETOOTH_SCAN" | |||
| android:usesPermissionFlags="neverForLocation" | |||
| tools:targetApi="s"/> | |||
| tools:targetApi="s" /> | |||
| <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> | |||
| <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> | |||
| <!-- 声明前台服务连接设备的权限(非必须) --> | |||
| @@ -47,7 +50,8 @@ | |||
| android:usesCleartextTraffic="true" | |||
| tools:targetApi="q"> | |||
| <activity android:name=".home.MainActivity" | |||
| <activity | |||
| android:name=".home.MainActivity" | |||
| android:exported="true"> | |||
| <intent-filter> | |||
| <action android:name="android.intent.action.VIEW" /> | |||
| @@ -125,9 +129,6 @@ | |||
| <activity | |||
| android:name=".TransmissionActivity" | |||
| android:screenOrientation="portrait" /> | |||
| <activity | |||
| android:name=".BroadcastBloodOxygenActivity" | |||
| android:screenOrientation="portrait" /> | |||
| <activity | |||
| android:name=".modules.toothbrush.ToothBrushWifiOnOnBleActivity" | |||
| android:screenOrientation="portrait" /> | |||
| @@ -277,6 +278,9 @@ | |||
| <activity | |||
| android:name=".modules.toothbrush.ToothBrushWifiNewBleActivity" | |||
| android:screenOrientation="portrait" /> | |||
| <activity | |||
| android:name=".modules.broadcastOxygen.BroadcastBloodOxygenActivity" | |||
| android:screenOrientation="portrait" /> | |||
| <provider | |||
| android:name="androidx.core.content.FileProvider" | |||
| @@ -292,6 +296,10 @@ | |||
| android:name="org.eclipse.paho.android.service.MqttService" | |||
| android:enabled="true" | |||
| android:exported="true"></service> | |||
| <service android:name="com.pingwang.bluetoothlib.server.ELinkBleServer" | |||
| android:foregroundServiceType="connectedDevice" | |||
| /> | |||
| </application> | |||
| </manifest> | |||
| @@ -10,7 +10,6 @@ import aicare.net.cn.sdk.ailinksdkdemoandroid.BabyCmdActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.BleCmdActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.BloodOxygenActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.BloodSugar4GActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.BroadcastBloodOxygenActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.BroadcastScaleActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.ConnectBleTestActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.HeightCmdActivity; | |||
| @@ -38,6 +37,7 @@ import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.ble_speed_test.BleSpeedTes | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.blood_glucose.BloodGlucoseActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.blood_pressure_tc.BloodPressureTcActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.body_scale_4g.BodyScale4GActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.broadcastOxygen.BroadcastBloodOxygenActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.broadcast_height.BroadcastHeightActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.broadcast_nutrition.BroadNutritionActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.broadcast_weight_sacle.BroadcastWeightScaleActivity; | |||
| @@ -1,4 +1,4 @@ | |||
| package aicare.net.cn.sdk.ailinksdkdemoandroid; | |||
| package aicare.net.cn.sdk.ailinksdkdemoandroid.modules.broadcastOxygen; | |||
| import android.content.Context; | |||
| import android.os.Bundle; | |||
| @@ -15,19 +15,18 @@ import androidx.annotation.Nullable; | |||
| import com.pingwang.bluetoothlib.bean.BleValueBean; | |||
| import com.pingwang.bluetoothlib.config.BleConfig; | |||
| import com.pingwang.bluetoothlib.listener.OnBleBroadcastDataListener; | |||
| import com.pingwang.bluetoothlib.listener.OnCallbackDis; | |||
| import com.pingwang.bluetoothlib.listener.OnScanFilterListener; | |||
| import com.pingwang.bluetoothlib.utils.BleDensityUtil; | |||
| import com.pingwang.bluetoothlib.utils.BleLog; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.UUID; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.R; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.base.BleBaseActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.utils.TimeUtils; | |||
| import cn.net.aicare.modulelibrary.module.BloodOxygen.BroadcastBloodOxygenBleConfig; | |||
| import cn.net.aicare.modulelibrary.module.BloodOxygen.BroadcastBloodOxygenDeviceData; | |||
| /** | |||
| @@ -35,7 +34,7 @@ import cn.net.aicare.modulelibrary.module.BloodOxygen.BroadcastBloodOxygenDevice | |||
| * 2020/09/09<br> | |||
| * 广播血氧仪 | |||
| */ | |||
| public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnCallbackDis, BroadcastBloodOxygenDeviceData.onNotifyData, OnScanFilterListener, View.OnClickListener { | |||
| public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnCallbackDis, OnBleBroadcastDataListener, View.OnClickListener { | |||
| private static String TAG = BroadcastBloodOxygenActivity.class.getName(); | |||
| private final int REFRESH_DATA = 3; | |||
| @@ -45,7 +44,6 @@ public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnC | |||
| private List<String> mList; | |||
| private ArrayAdapter listAdapter; | |||
| private Context mContext; | |||
| private BroadcastBloodOxygenDeviceData mDevice; | |||
| private String mAddress = ""; | |||
| private Handler mHandler = new Handler(Looper.getMainLooper()) { | |||
| @@ -93,7 +91,7 @@ public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnC | |||
| mHandler.sendEmptyMessage(REFRESH_DATA); | |||
| } else if (id == R.id.open) { | |||
| if (mAILinkBleManager != null) { | |||
| mAILinkBleManager.startScan(0, UUID.fromString("0000F0A0-0000-1000-8000-00805F9B34FB")); | |||
| mAILinkBleManager.startScan(0, BleConfig.UUID_SERVER_BROADCAST_AILINK); | |||
| } | |||
| } else if (id == R.id.stop) { | |||
| if (mAILinkBleManager != null) { | |||
| @@ -111,9 +109,7 @@ public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnC | |||
| BleLog.i(TAG, "服务与界面建立连接成功"); | |||
| //与服务建立连接 | |||
| if (mAILinkBleManager != null) { | |||
| mDevice = BroadcastBloodOxygenDeviceData.getInstance(); | |||
| mDevice.setOnNotifyData(this); | |||
| mAILinkBleManager.setOnScanFilterListener(this); | |||
| mAILinkBleManager.addOnBleBroadcastDataListener(this); | |||
| mAILinkBleManager.startScan(0, BleConfig.UUID_SERVER_BROADCAST_AILINK); | |||
| } | |||
| } | |||
| @@ -127,10 +123,7 @@ public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnC | |||
| @Override | |||
| public void unbindServices() { | |||
| if (mDevice != null) { | |||
| mDevice.clear(); | |||
| mDevice = null; | |||
| } | |||
| } | |||
| @@ -153,7 +146,6 @@ public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnC | |||
| //-----------------通知------------------- | |||
| @Override | |||
| public void getBloodOxygenData(int status, int bloodOxygen, int pulseRate, int plethysmogram, int power) { | |||
| String statusStr = "状态="; | |||
| @@ -190,7 +182,6 @@ public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnC | |||
| mHandler.sendEmptyMessage(REFRESH_DATA); | |||
| } | |||
| @Override | |||
| public void OnDID(int cid, int vid, int pid) { | |||
| String didStr = "cid:" + cid + "||vid:" + vid + "||pid:" + pid; | |||
| mList.add(TimeUtils.getTime() + "ID:" + didStr); | |||
| @@ -206,27 +197,65 @@ public class BroadcastBloodOxygenActivity extends BleBaseActivity implements OnC | |||
| @Override | |||
| public boolean onFilter(BleValueBean bleValueBean) { | |||
| return true; | |||
| public void onBleBroadcastData(BleValueBean bleValueBean, byte[] payload) { | |||
| if (bleValueBean.isBroadcastModule() && bleValueBean.getCid() == BroadcastBloodOxygenBleConfig.BROADCAST_BLOOD_OXYGEN) { | |||
| if (TextUtils.isEmpty(mAddress) && bleValueBean.isBroadcastModule()) { | |||
| mAddress = bleValueBean.getMac(); | |||
| if (tv_broadcast_mac != null) { | |||
| tv_broadcast_mac.setText(mAddress); | |||
| } | |||
| } | |||
| //地址相同,并且是广播秤 | |||
| if (mAddress.equalsIgnoreCase(bleValueBean.getMac()) && bleValueBean.isBroadcastModule()) { | |||
| byte[] manufacturerData = bleValueBean.getManufacturerData(); | |||
| int cid = bleValueBean.getCid(); | |||
| int vid = bleValueBean.getVid(); | |||
| int pid = bleValueBean.getPid(); | |||
| OnDID(cid, vid, pid); | |||
| dataCheck(payload); | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void onScanRecord(BleValueBean bleValueBean) { | |||
| if (TextUtils.isEmpty(mAddress) && bleValueBean.isBroadcastModule()) { | |||
| mAddress = bleValueBean.getMac(); | |||
| if (tv_broadcast_mac != null) { | |||
| tv_broadcast_mac.setText(mAddress); | |||
| private int mOldNumberId = -1; | |||
| /** | |||
| * 校验解析数据 | |||
| * | |||
| * @param data Payload数据 | |||
| */ | |||
| public void dataCheck(byte[] data) { | |||
| if (data == null) | |||
| return; | |||
| if (data.length >= 9) { | |||
| int numberId = data[0] & 0xff;//数据ID | |||
| if (mOldNumberId == numberId) { | |||
| //数据相同,已处理过了.不再处理 | |||
| return; | |||
| } | |||
| mOldNumberId = numberId; | |||
| //0x00 :开始测试 | |||
| //0x01 :正在测试 | |||
| //0xFF :测试结束 | |||
| int status = data[1] & 0xff; | |||
| //0-100 % | |||
| // 若该值无效,则为 0xFF | |||
| int bloodOxygen = data[2] & 0xff;//血氧浓度百分比(SpO2 ,单位 %) | |||
| //0-254 | |||
| //若该值无效,则为 0xFF | |||
| int pulseRate = data[3] & 0xff;//脉率(pulse rate ,单位 bpm) | |||
| // | |||
| int plethysmogram = data[4] & 0xff;//PI ( Plethysmogram 无单位 ,1 位小数 ) | |||
| int power = data[5] & 0xff;//电量(power ,单位%) | |||
| getBloodOxygenData(status, bloodOxygen, pulseRate, plethysmogram, power); | |||
| } | |||
| //地址相同,并且是广播秤 | |||
| if (mAddress.equalsIgnoreCase(bleValueBean.getMac()) && bleValueBean.isBroadcastModule()) { | |||
| byte[] manufacturerData = bleValueBean.getManufacturerData(); | |||
| int cid = bleValueBean.getCid(); | |||
| int vid = bleValueBean.getVid(); | |||
| int pid = bleValueBean.getPid(); | |||
| if (mDevice != null) | |||
| mDevice.onNotifyData("",manufacturerData, cid, vid, pid); | |||
| } | |||
| } | |||
| @@ -1,7 +1,6 @@ | |||
| package aicare.net.cn.sdk.ailinksdkdemoandroid.modules.broadcast_nutrition; | |||
| import android.os.Bundle; | |||
| import android.util.Log; | |||
| import android.view.View; | |||
| import android.widget.ArrayAdapter; | |||
| import android.widget.Button; | |||
| @@ -12,10 +11,6 @@ import androidx.annotation.Nullable; | |||
| import com.pingwang.bluetoothlib.bean.BleValueBean; | |||
| import com.pingwang.bluetoothlib.config.BleConfig; | |||
| import com.pingwang.bluetoothlib.listener.OnBleBroadcastDataListener; | |||
| import com.pingwang.bluetoothlib.listener.OnScanFilterListener; | |||
| import com.pingwang.bluetoothlib.utils.BleLog; | |||
| import com.pingwang.bluetoothlib.utils.BleStrUtils; | |||
| import com.pinwang.ailinkble.AiLinkPwdUtil; | |||
| import java.math.BigDecimal; | |||
| import java.text.SimpleDateFormat; | |||
| @@ -25,8 +20,9 @@ import java.util.Locale; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.R; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.base.BleBaseActivity; | |||
| import aicare.net.cn.sdk.ailinksdkdemoandroid.utils.L; | |||
| public class BroadNutritionActivity extends BleBaseActivity implements View.OnClickListener, OnScanFilterListener, OnBleBroadcastDataListener { | |||
| public class BroadNutritionActivity extends BleBaseActivity implements View.OnClickListener, OnBleBroadcastDataListener { | |||
| private ListView list_view; | |||
| private Button btn_start; | |||
| @@ -78,7 +74,7 @@ public class BroadNutritionActivity extends BleBaseActivity implements View.OnCl | |||
| @Override | |||
| public void onServiceSuccess() { | |||
| mAILinkBleManager.setOnScanFilterListener(this); | |||
| L.i("绑定服务成功"); | |||
| mAILinkBleManager.addOnBleBroadcastDataListener(this); | |||
| } | |||
| @@ -92,21 +88,14 @@ public class BroadNutritionActivity extends BleBaseActivity implements View.OnCl | |||
| } | |||
| @Override | |||
| public boolean onFilter(BleValueBean bleValueBean) { | |||
| if (bleValueBean.getCid() == 4) { | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| private String mMac; | |||
| @Override | |||
| public void onBleBroadcastData(BleValueBean bleValueBean, byte[] payload) { | |||
| mMac = bleValueBean.getMac(); | |||
| notifyData(payload); | |||
| if (bleValueBean.getCid() == 0x04 && bleValueBean.isBroadcastModule()) { | |||
| mMac = bleValueBean.getMac(); | |||
| notifyData(payload); | |||
| } | |||
| } | |||
| private String mOldText = ""; | |||
| @@ -133,55 +122,6 @@ public class BroadNutritionActivity extends BleBaseActivity implements View.OnCl | |||
| mListAdapter.notifyDataSetChanged(); | |||
| } | |||
| private long mOldNumberId; | |||
| /** | |||
| * @param manufacturerData 自定义厂商数据0xFF后面的数据 | |||
| * @param cid cid 设备类型 | |||
| * @param vid vid | |||
| * @param pid pid | |||
| */ | |||
| public void onNotifyData(String uuid, byte[] manufacturerData, int cid, int vid, int pid) { | |||
| if (manufacturerData == null) { | |||
| BleLog.i("Tag1", "接收到的数据:null"); | |||
| return; | |||
| } | |||
| // if (manufacturerData.length >= 20) { | |||
| byte sum = manufacturerData[9]; | |||
| byte[] data = new byte[10]; | |||
| System.arraycopy(manufacturerData, 10, data, 0, data.length); | |||
| byte newSum = cmdSum(data); | |||
| if (newSum == sum) { | |||
| int numberId = data[0] & 0xff;//数据ID | |||
| // if (mOldNumberId == numberId) { | |||
| // //数据相同,已处理过了.不再处理 | |||
| // return; | |||
| // } | |||
| mOldNumberId = numberId; | |||
| byte[] bytes; | |||
| if (cid != 0 || vid != 0 || pid != 0) { | |||
| bytes = AiLinkPwdUtil.decryptBroadcast(cid, vid, pid, data); | |||
| } else { | |||
| bytes = data; | |||
| } | |||
| Log.i("Tag1", "接收到的数据:" + BleStrUtils.byte2HexStr(bytes)); | |||
| notifyData(bytes); | |||
| } else { | |||
| Log.i("Tag1", "校验和错误"); | |||
| } | |||
| // } | |||
| } | |||
| /** | |||
| * 校验累加,从1开始加 | |||
| */ | |||
| private byte cmdSum(byte[] data) { | |||
| byte sum = 0; | |||
| for (byte datum : data) { | |||
| sum += datum; | |||
| } | |||
| return sum; | |||
| } | |||
| /** | |||
| * 解析数据 | |||