package com.shlb.comb.activity; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.text.InputType; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; import com.blakequ.bluetooth_manager_lib.connect.BluetoothConnectManager; import com.blakequ.bluetooth_manager_lib.connect.BluetoothSubScribeData; import com.blakequ.bluetooth_manager_lib.connect.ConnectState; import com.blakequ.bluetooth_manager_lib.connect.ConnectStateListener; import com.blakequ.bluetooth_manager_lib.device.BluetoothLeDevice; import com.blakequ.bluetooth_manager_lib.util.BluetoothUtils; import com.blakequ.bluetooth_manager_lib.util.ByteUtils; import com.blankj.utilcode.util.LogUtils; import com.blankj.utilcode.util.ThreadUtils; import com.qmuiteam.qmui.util.QMUIDisplayHelper; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; import com.qmuiteam.qmui.widget.grouplist.QMUICommonListItemView; import com.qmuiteam.qmui.widget.grouplist.QMUIGroupListView; import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; import com.shlb.comb.R; import com.shlb.comb.base.BaseActivity; import com.shlb.comb.event.UpdateEvent; import com.shlb.comb.util.CMD; import com.shlb.comb.util.CRCutil; import com.shlb.comb.util.Singletion; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; public class NormalWriteActivity extends BaseActivity { QMUIGroupListView mGroupListView; Button send; LinearLayout llRoot; private BluetoothConnectManager connectManager; private BluetoothGatt gatt; private BluetoothGattCharacteristic characteristic; @Override protected void contentView() { setContentView(R.layout.normal_activity_write); } @Override protected void initView() { super.initHead(); mGroupListView = findViewById(R.id.groupListView); send = findViewById(R.id.send); llRoot = findViewById(R.id.ll_root); initTitlebar(); tv_center.setText("编址"); initGroupListView(); } @Override protected void initData() { String uuid = Singletion.getInstance().uuid; initWrite(uuid); } @Override protected void initEvent() { send.setOnClickListener(this); int[] ids = {R.id.btnExit, R.id.btnInto, R.id.btnClean, R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, R.id.btn5, R.id.btn6, R.id.btn7, R.id.btn8, R.id.btn9, R.id.btn10, R.id.btn11, R.id.btn12, R.id.btn13, R.id.btn14, R.id.btn15, R.id.btn16}; for (int id : ids) { View v = findViewById(id); if (v != null) v.setOnClickListener(this); } } @Override public void onClick(View v) { int id = v.getId(); if (id == R.id.iv_left) { finish(); } else if (id == R.id.btnExit) { writeCmd(CMD.EXIT); } else if (id == R.id.btnInto) { writeCmd(CMD.GETINTO); } else if (id == R.id.btnClean) { writeCmd(CMD.CLEAN); } else if (id == R.id.btn1) { sendYJCmd(1); } else if (id == R.id.btn2) { sendYJCmd(2); } else if (id == R.id.btn3) { sendYJCmd(3); } else if (id == R.id.btn4) { sendYJCmd(4); } else if (id == R.id.btn5) { sendYJCmd(5); } else if (id == R.id.btn6) { sendYJCmd(6); } else if (id == R.id.btn7) { sendYJCmd(7); } else if (id == R.id.btn8) { sendYJCmd(8); } else if (id == R.id.btn9) { sendYJCmd(9); } else if (id == R.id.btn10) { sendYJCmd(10); } else if (id == R.id.btn11) { sendYJCmd(11); } else if (id == R.id.btn12) { sendYJCmd(12); } else if (id == R.id.btn13) { sendYJCmd(13); } else if (id == R.id.btn14) { sendYJCmd(14); } else if (id == R.id.btn15) { sendYJCmd(15); } else if (id == R.id.btn16) { sendYJCmd(16); } } @Subscribe(threadMode = ThreadMode.MAIN) public void onEventReceiveNotify(UpdateEvent event) { if (event != null && event.getType() == UpdateEvent.Type.BLE_DATA) { BluetoothGattCharacteristic characteristic = (BluetoothGattCharacteristic) event.getObj(); final byte[] dataArr = characteristic.getValue(); final String flag = event.getMsg(); if (dataArr != null && dataArr.length > 0) { if (flag.equals("read")) { } else if (flag.equals("write")) { } else if (flag.equals("notify")) { //返回结果 String crc = CRCutil.getCRC(dataArr); LogUtils.e("resCRC", crc); //CRC计算结果为0时命令执行成功,自动执行退出命令 if (crc.equals("0")) { writeCmd(CMD.EXIT); Toast("操作成功,自动执行退出编址指令"); curCmd = -1; item6.setText("编址成功"); } //计算返回为0时 自动退出 LogUtils.e("res", ByteUtils.byteArrayToHexString(dataArr)); } else { Toast("解析返回信息失败!"); } } else { Toast("返回信息为空!"); } } } QMUICommonListItemView item1; QMUICommonListItemView item2; QMUICommonListItemView item3; QMUICommonListItemView item4; QMUICommonListItemView item5; QMUICommonListItemView item6; View.OnClickListener onClickListener; int curCmd = -1; String[] cmdName = {"进入编址", "清除地址", "编辑地址", "退出编址", "一键编址"}; private void initGroupListView() { item1 = mGroupListView.createItemView(null, cmdName[0], "", QMUICommonListItemView.HORIZONTAL, QMUICommonListItemView.ACCESSORY_TYPE_CHEVRON); item2 = mGroupListView.createItemView(null, cmdName[1], "", QMUICommonListItemView.HORIZONTAL, QMUICommonListItemView.ACCESSORY_TYPE_CHEVRON); item3 = mGroupListView.createItemView(null, cmdName[2], "点击选择编号", QMUICommonListItemView.HORIZONTAL, QMUICommonListItemView.ACCESSORY_TYPE_CHEVRON); item4 = mGroupListView.createItemView(null, cmdName[3], "", QMUICommonListItemView.HORIZONTAL, QMUICommonListItemView.ACCESSORY_TYPE_CHEVRON); onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { if (v instanceof QMUICommonListItemView) { CharSequence text = ((QMUICommonListItemView) v).getText(); //进入编址 if (text.equals(cmdName[0])) { curCmd = 1; item6.setText(cmdName[0]); item6.setDetailText(""); //清除地址 } else if (text.equals(cmdName[1])) { curCmd = 2; item6.setText(cmdName[1]); item6.setDetailText(""); //编辑地址 } else if (text.equals(cmdName[2])) { showEditTextDialog(); //退出编址 } else if (text.equals(cmdName[3])) { curCmd = 4; item6.setText(cmdName[3]); item6.setDetailText(""); //一键编址 } else if (text.equals(cmdName[4])) { showQuickDialog(); } } } }; int size = QMUIDisplayHelper.dp2px(this, 20); QMUIGroupListView.newSection(this) .setTitle("Section 1:操作指令") .setDescription("") .setLeftIconSize(size, ViewGroup.LayoutParams.WRAP_CONTENT) .addItemView(item1, onClickListener) .addItemView(item2, onClickListener) .addItemView(item3, onClickListener) .addItemView(item4, onClickListener) .addTo(mGroupListView); item5 = mGroupListView.createItemView(cmdName[4]); item5.setOrientation(QMUICommonListItemView.VERTICAL); item5.setDetailText("进入-清除-编址-退出"); item5.setAccessoryType(QMUICommonListItemView.ACCESSORY_TYPE_CHEVRON); item6 = mGroupListView.createItemView("待选择"); item6.setOrientation(QMUICommonListItemView.HORIZONTAL); QMUIGroupListView.newSection(this) .setTitle("Section 2:快捷指令") .setDescription("") .setLeftIconSize(size, ViewGroup.LayoutParams.WRAP_CONTENT) .addItemView(item5, onClickListener) .addTo(mGroupListView); QMUIGroupListView.newSection(this) .setTitle("Section 3:当前指令") .setDescription("") .setLeftIconSize(size, ViewGroup.LayoutParams.WRAP_CONTENT) .addItemView(item6, onClickListener) .addTo(mGroupListView); } /** * 初始化写入服务 * * @param uu */ private void initWrite(String uu) { BluetoothLeDevice mDevice = Singletion.getInstance().mDevice; connectManager = BluetoothConnectManager.getInstance(this); connectManager.addConnectStateListener(listener); String uuid = uu; UUID serverUUid = null; gatt = connectManager.getBluetoothGatt(mDevice.getAddress()); if (gatt != null) { List list = gatt.getServices(); if (list != null) { for (BluetoothGattService service : list) { for (BluetoothGattCharacteristic characteristics : service.getCharacteristics()) { if (characteristics.getUuid().toString().equals(uuid)) { characteristic = characteristics; serverUUid = service.getUuid(); break; } } } } } if (serverUUid == null) { Toast("serverUUid不能为空!"); return; } //1.set service uuid connectManager.setServiceUUID(serverUUid.toString()); //2.clean history descriptor data connectManager.cleanSubscribeData(); //3.add subscribe params if (BluetoothUtils.isCharacteristicRead(characteristic.getProperties())) { connectManager.addBluetoothSubscribeData( new BluetoothSubScribeData.Builder().setCharacteristicRead(characteristic.getUuid()).build()); } if (BluetoothUtils.isCharacteristicNotify(characteristic.getProperties())) { connectManager.addBluetoothSubscribeData( new BluetoothSubScribeData.Builder().setCharacteristicNotify(characteristic.getUuid()).build() ); } connectManager.startSubscribe(gatt); } private void writeCmd(String cmd) { int len = cmd.length(); if (len > 0 && len % 2 == 0) { byte[] bytes = invertStringToBytes(cmd); if (bytes != null) { characteristic.setValue(bytes); gatt.writeCharacteristic(characteristic); runOnUiThread(() -> { item6.setDetailText(item6.getDetailText() + " 已发送"); }); } else { Log.e("tag", "write value fail"); } } else { runOnUiThread(() -> { Toast("指令错误!"); }); } } private byte[] invertStringToBytes(String value) { int len = value.length() / 2; if (len > 0) { byte[] bytes = new byte[len]; for (int i = 0; i < len; i++) { Integer val = Integer.valueOf(value.substring(i * 2, i * 2 + 2), 16); bytes[i] = val.byteValue(); } return bytes; } return null; } private List> getWriteData() { List> res = new ArrayList<>(); Map map1 = new HashMap<>(); map1.put("name", "进入编址状态"); map1.put("flag", "0"); map1.put("value", "A55A060100000000002F35"); res.add(map1); Map map2 = new HashMap<>(); map2.put("name", "退出编址状态"); map2.put("flag", "0"); map2.put("value", "A55A060400000000002F60"); res.add(map2); Map map3 = new HashMap<>(); map3.put("name", "编址"); map3.put("flag", "0"); map3.put("value", "A55A060300020000002F6F"); res.add(map3); Map map4 = new HashMap<>(); map4.put("name", "清除地址"); map4.put("flag", "0"); map4.put("value", "A55A060200000000002F06"); res.add(map4); return res; } private ConnectStateListener listener = new ConnectStateListener() { @Override public void onConnectStateChanged(String address, ConnectState state) { switch (state) { case CONNECTED: break; case CONNECTING: break; case NORMAL: break; } } }; /** * 输入编址序号后 执行编址指令 */ private void showEditTextDialog() { final QMUIDialog.EditTextDialogBuilder builder = new QMUIDialog.EditTextDialogBuilder(this); builder.setTitle("提示") .setPlaceholder("请输入编址号码(1-16)") .setInputType(InputType.TYPE_CLASS_TEXT) .addAction("取消", new QMUIDialogAction.ActionListener() { @Override public void onClick(QMUIDialog dialog, int index) { dialog.dismiss(); } }) .addAction("确定", new QMUIDialogAction.ActionListener() { @Override public void onClick(QMUIDialog dialog, int index) { String text = builder.getEditText().getText().toString(); Integer res = -1; try { res = Integer.parseInt(text); } catch (Exception e) { e.printStackTrace(); } if (res == null || res < 0 || res > 16) { Toast("请输入1-16数字"); } else { item3.setDetailText(text); curCmd = 3; item6.setText(cmdName[2]); item6.setDetailText(text); dialog.dismiss(); } } }) .create(com.qmuiteam.qmui.R.style.QMUI_Dialog).show(); } /** * 输入编址序号后 一键执行所有指令 */ private void showQuickDialog() { final QMUIDialog.EditTextDialogBuilder builder = new QMUIDialog.EditTextDialogBuilder(this); builder.setTitle("提示") .setPlaceholder("请输入编址号码(1-16)") .setInputType(InputType.TYPE_CLASS_TEXT) .addAction("取消", new QMUIDialogAction.ActionListener() { @Override public void onClick(QMUIDialog dialog, int index) { dialog.dismiss(); } }) .addAction("确定", new QMUIDialogAction.ActionListener() { @Override public void onClick(QMUIDialog dialog, int index) { String text = builder.getEditText().getText().toString(); Integer addrrNo = -1; try { addrrNo = Integer.parseInt(text); } catch (Exception e) { e.printStackTrace(); } if (addrrNo == null || addrrNo < 0 || addrrNo > 16) { Toast("请输入1-16数字"); } else { curCmd = 5; item5.setDetailText(text); item6.setText(cmdName[4]); item6.setDetailText(text); dialog.dismiss(); } } }) .create(com.qmuiteam.qmui.R.style.QMUI_Dialog).show(); } public void initTitlebar() { iv_right.setVisibility(View.VISIBLE); iv_left.setImageDrawable(getResources().getDrawable(R.mipmap.icon_back)); iv_right.setImageDrawable(getResources().getDrawable(R.mipmap.icon_topbar_overflow)); } /** * 发送一键命令 * @param no2 */ private void sendYJCmd(int no2){ if (no2 > 16|| no2<1 ) { Toast("地址数据异常"); return; } ThreadUtils.executeBySingle(new ThreadUtils.SimpleTask() { @Override public Object doInBackground() throws Throwable { writeCmd(CMD.GETINTO); Thread.sleep(200); writeCmd(CMD.CLEAN); Thread.sleep(200); String sNo2 = Integer.toHexString(no2); // if (sNo2.length() < 2) { sNo2 = "0" + sNo2; } String cmd = CMD.ADDR_PREFIX + sNo2 + CMD.ADDR_SUFFIX; byte[] bytes = invertStringToBytes(cmd); String crc = CRCutil.getCRC(bytes); String zl = cmd + crc; LogUtils.e("reszl", zl); Thread.sleep(200); writeCmd(zl); return null; } @Override public void onSuccess(Object result) { } }); Toast("编址指令已发送!"); } }