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 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 WriteActivity2 extends BaseActivity {
|
|
QMUIGroupListView mGroupListView;
|
|
QMUIRoundButton send;
|
|
private BluetoothConnectManager connectManager;
|
private BluetoothGatt gatt;
|
|
private BluetoothGattCharacteristic characteristic;
|
|
|
@Override
|
protected void contentView() {
|
setContentView(R.layout.activity_write);
|
|
}
|
|
@Override
|
protected void initView() {
|
super.initHead();
|
mGroupListView = findViewById(R.id.groupListView);
|
send = findViewById(R.id.send);
|
initTitlebar();
|
tv_center.setText("编址");
|
initGroupListView();
|
|
}
|
|
@Override
|
protected void initData() {
|
String uuid = Singletion.getInstance().uuid;
|
initWrite(uuid);
|
|
|
}
|
|
@Override
|
protected void initEvent() {
|
send.setOnClickListener(this);
|
|
}
|
|
|
@Override
|
public void onClick(View v) {
|
int id = v.getId();
|
if (id == R.id.iv_left) {
|
finish();
|
} else if (id == R.id.iv_right) {
|
} else if (id == R.id.send) {
|
switch (curCmd){
|
case -1:
|
Toast("请选择指令!");
|
break;
|
case 1:
|
//进入编址
|
writeCmd(CMD.GETINTO);
|
break;
|
case 2:
|
//清除地址
|
writeCmd(CMD.CLEAN);
|
break;
|
case 3:
|
String addrNos = item3.getDetailText().toString();
|
Integer addrNo = -1;
|
try {
|
addrNo = Integer.parseInt(addrNos);
|
}catch (Exception e){
|
e.printStackTrace();
|
}
|
if(addrNo == -1 ){
|
Toast("地址数据异常");
|
return;
|
|
}
|
String sNo = Integer.toHexString(addrNo);
|
if(sNo.length()<2){
|
sNo = "0" + sNo;
|
}
|
|
String cmd = CMD.ADDR_PREFIX + sNo + CMD.ADDR_SUFFIX;
|
byte[] bytes = invertStringToBytes(cmd);
|
String crc = CRCutil.getCRC(bytes);
|
String zl = cmd + crc;
|
LogUtils.e("reszl", zl);
|
writeCmd(zl);
|
Toast("编址指令已发送!");
|
break;
|
case 4:
|
//退出编址
|
writeCmd(CMD.EXIT);
|
break;
|
case 5:
|
String addrNos2 = item5.getDetailText().toString();
|
Integer addrNo2 = -1;
|
try {
|
addrNo2 = Integer.parseInt(addrNos2);
|
}catch (Exception e){
|
e.printStackTrace();
|
}
|
final Integer no2 = addrNo2;
|
if(no2 == -1 ){
|
Toast("地址数据异常");
|
return;
|
|
}
|
|
ThreadUtils.executeBySingle(new ThreadUtils.SimpleTask<Object>() {
|
@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("编址指令已发送!");
|
break;
|
}
|
}
|
}
|
|
|
@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<BluetoothGattService> 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<Map<String, Object>> getWriteData() {
|
List<Map<String, Object>> res = new ArrayList<>();
|
Map<String, Object> map1 = new HashMap<>();
|
map1.put("name", "进入编址状态");
|
map1.put("flag", "0");
|
map1.put("value", "A55A060100000000002F35");
|
res.add(map1);
|
Map<String, Object> map2 = new HashMap<>();
|
map2.put("name", "退出编址状态");
|
map2.put("flag", "0");
|
map2.put("value", "A55A060400000000002F60");
|
res.add(map2);
|
Map<String, Object> map3 = new HashMap<>();
|
map3.put("name", "编址");
|
map3.put("flag", "0");
|
map3.put("value", "A55A060300020000002F6F");
|
res.add(map3);
|
Map<String, Object> 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));
|
}
|
}
|