import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.lsw.mvpframe.utils.Constant;
import com.lsw.mvpframe.utils.LogUtil;
import com.lsw.mvpframe.utils.SharedPreferencesUtils;
import org.greenrobot.eventbus.EventBus;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Set;
import java.util.UUID;
import utils.ToastUtil;
/**
* @description: 连接蓝牙服务
* @author: Created by lsw
* @date: 2018/9/17 17:45
*/
@SuppressLint("MissingPermission")
public class BlueService extends Service {
private ServerOrCilent serviceOrCilent;
private String BlueToothAddress;
private BluetoothAdapter mBtAdapter;
private BluetoothDevice device;
private clientThread clientConnectThread;
private BluetoothSocket socket;
private readThread mreadThread;
int linkCout = 0;
private static int parseFlag = 999; // 判断使用何种解析方式进行解析数据, 默认999不以任何方式进行解析
/* ==================================================================== */
/* ====================== 耀华仪表盘串口解析 start ====================== */
/* ==================================================================== */
private static final int startByTF0 = 2; // TF0, 起始位
private static final int endByTF0 = 3; // TF0, 结束位
private static byte[] dataByTF0 = new byte[12]; // 存储的数据, 总共读取12位字节, 第一位和最后一位分别为开始和结束位 (对应十六进制2, 3), TF0
private static final int startAndEndByTF1 = 0; // 暂时不解析该种方式
private static byte[] dataByTF1 = new byte[0]; // 暂时不解析该种方式
private static final int startAndEndByTF2 = 61; // TF2, 起始位和结束位
private static byte[] dataByTF2 = new byte[8]; // 存储的数据, 总共读取8位字节, 开始位和结束位均为等号 (对应十六进制3D), TF2
private static final int startAndEndByTF3 = 61; // TF3, 起始位和结束位
private static byte[] dataByTF3 = new byte[9]; // 存储的数据, 总共读取9位字节, 开始位和结束位均为等号 (对应十六进制3D), TF3
private static final int startByP52 = 119; // P52, 起始位
private static final int endByP52 = 10; // P52, 结束位
private static byte[] dataByP52 = new byte[14]; // 存储的数据, 总共读取14位字节, 第一位和最后一位分别为开始和结束位 (对应十进制119, 10), P52
private boolean isOpen;
private SharedPreferencesUtils spUtils;
private boolean linked = false;
/* ==================================================================== */
/* ====================== 耀华仪表盘串口解析 end ======================== */
/* ==================================================================== */
enum ServerOrCilent {
NONE,
SERVICE,
CILENT
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private boolean showWeightLog = false;
@SuppressLint("HandlerLeak")
private Handler LinkDetectedHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//Toast.makeText(mContext, (String)msg.obj, Toast.LENGTH_SHORT).show();
switch (msg.what) {
case 1:
String str = (String) msg.obj;
//Toast.makeText(BlueToothActivity.this,"获取到的数据为:"+str,Toast.LENGTH_SHORT).show();
char[] arr = str.toCharArray();
for (int i = 0; i < arr.length; i++) {
if ('0' != str.charAt(i)) {
str = str.substring(i, str.length());
break;
}
}
// if (showWeightLog) {
// LogUtil.e("重量-- " + str);
// }
if(!TextUtils.isEmpty(str)){
EventBus.getDefault().post(str);
}
break;
case 0:
// Toast.makeText(BlueService.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
LogUtil.w("BlueService -->"+ (String) msg.obj);
break;
case -1:
if(linkCout <5){
sendEmptyMessageDelayed(66, 10000);
}else{
if(!linked){
LogUtil.e("多次连接蓝牙失败!");
ToastUtil.show("多次连接蓝牙失败!停止连接!请检查蓝牙设备!");
}
postDelayed(new Runnable() {
@Override
public void run() {
linkCout = 0;
if(!linked){
sendEmptyMessage(66);
}
}
},1000 * 60);
}
// Toast.makeText(BlueService.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
LogUtil.w("BlueService -->"+ (String) msg.obj);
break;
case 66:
linkCout++;
startLinkBlue(spUtils.get(Constant.BLUE_NAME).toUpperCase());
break;
}
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
spUtils = SharedPreferencesUtils.getInstance(getApplicationContext());
startLinkBlue(spUtils.get(Constant.BLUE_NAME).toUpperCase());
return START_STICKY;
}
//yaohua
private void startLinkBlue(String blueName) {
LogUtil.e("blue_name -- "+ blueName);
Set pairedDevices = mBtAdapter.getBondedDevices();
for (BluetoothDevice pairedDevice : pairedDevices) {
if (pairedDevice.getName().contains(blueName)) {
connection(pairedDevice);
LogUtil.e(pairedDevice.getAddress()+"-- 地磅地址");
break;
}
}
}
/**
* 连接蓝牙设备
*/
private void connection(BluetoothDevice device) {
if (device.getName() == null) {
ToastUtil.show("获取蓝牙设备名称失败!");
return;
}
BlueToothAddress = device.getAddress();
mBtAdapter.cancelDiscovery();
serviceOrCilent = ServerOrCilent.CILENT;
next();
}
//下一步
private void next() {
if (serviceOrCilent == ServerOrCilent.CILENT) {
String address = BlueToothAddress;
if (!address.equals("null")) {
Log.e("Tag", "开始连接Blue");
device = mBtAdapter.getRemoteDevice(address);
clientConnectThread = new clientThread();
clientConnectThread.start();
} else {
Toast.makeText(this, "blue address is null !", Toast.LENGTH_SHORT).show();
}
} else {
}
}
//开启客户端
private class clientThread extends Thread {
public void run() {
try {
//创建一个Socket连接:只需要服务器在注册时的UUID号
// socket = device.createRfcommSocketToServiceRecord(BluetoothProtocols.OBEX_OBJECT_PUSH_PROTOCOL_UUID);
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
// socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001102-0000-1000-8000-00805F9B34FB"));
//连接
Message msg2 = new Message();
msg2.obj = "请稍候,正在连接蓝牙服务:" + BlueToothAddress;
msg2.what = 0;
LinkDetectedHandler.sendMessage(msg2);
// try {
socket.connect();
// }catch (Exception e){
// e.printStackTrace();
// }
linked = true;
Message msg = new Message();
msg.obj = "已经连接上服务端!可以发送信息。";
msg.what = 0;
LinkDetectedHandler.sendMessage(msg);
//启动接受数据
mreadThread = new readThread();
mreadThread.start();
} catch (IOException e) {
Log.e("connect", "--连接服务端异常!稍后自动进行重试--", e);
Message msg = new Message();
msg.obj = "连接服务端异常!稍后自动进行重试!";
msg.what = -1;
LinkDetectedHandler.sendMessage(msg);
}
}
}
//读取数据
private class readThread extends Thread {
public void run() {
byte[] buffer = new byte[1024];
int bytes;
InputStream mmInStream = null;
try {
mmInStream = socket.getInputStream();
} catch (IOException e1) {
e1.printStackTrace();
}
while (true) {
try {
// Read from the InputStream
if ((bytes = mmInStream.read(buffer)) > 0) {
byte[] buf_data = new byte[bytes];
for (int i = 0; i < bytes; i++) {
// Log.e("Tag", "接收到的数据:" + buffer[i]);
buf_data[i] = buffer[i];
}
try {
String st = readData(buf_data);
if(showWeightLog){
Log.e("Tag", "解析数据:" + st);
}
if (st.length() > 1) {
String ss = st.substring(0, 1);
//s=st.substring(1,st.length());
if ("+".equals(ss)) {
s = st.substring(1, st.length());
} else {
s = "0";
}
}
} catch (Exception e) {
e.printStackTrace();
Log.e("Tag", "异常数据:");
dataByTF0 = new byte[12];
dataByP52 = new byte[14];
}
Message msg = new Message();
msg.obj = s;
msg.what = 1;
LinkDetectedHandler.sendMessage(msg);
}
} catch (IOException e) {
try {
mmInStream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
break;
}
}
}
private String s = "";
}
/**
* 解析耀华仪表盘串口数据
*
* @param buffer
* @throws Exception
*/
private String readData(byte[] buffer) throws Exception {
String data = "";
if (parseFlag != startByTF0 && parseFlag != startByP52) { // 如果当前没有选中解析方式则根据从串口读入得数据进行判断解析方式
for (int i = 0; i < buffer.length; i++) {
parseFlag = buffer[i];
if (parseFlag == startByTF0 || parseFlag == startByP52) {
break;
}
}
}
switch (parseFlag) {
case startByTF0: {
data = readDataByTF0(buffer);
}
break;
case startByP52: {
data = readDataByP52(buffer);
}
default: {
// placeholder
}
}
return data;
}
/**
* 解析耀华仪表盘TF0连续发送方式
*
* @param buffer
* @throws Exception
*/
private String readDataByTF0(byte[] buffer) throws Exception {
String dataStr = "";
if (dataByTF0[0] == 0) { // 如果当前接收数据为空
if (buffer[0] == startByTF0) { // 如果当前数据处于一个完整数据的开始部分则进行接收
for (int i = 0; i < buffer.length; i++) {
dataByTF0[i] = buffer[i]; // 将从串口读取到的数据存入data中
}
}
} else if (dataByTF0[dataByTF0.length - 1] == 0) {
int dataIndex = 0; // 当前数据应该存入的下标位
for (int i = 0; i < dataByTF0.length; i++) {
if (dataByTF0[i] == 0) {
dataIndex = i;
break;
}
}
for (int i = 0; i < buffer.length; i++) {
dataByTF0[dataIndex++] = buffer[i];
if (buffer[i] == endByTF0) { // 如果已经达到结束部分则退出循环
break;
}
}
}
if (dataByTF0.length == 12 && dataByTF0[11] != 0) { // 一个完整的数据已经接收完成, 处理数据并进行结果展示
String symbol = Integer.toHexString(dataByTF0[1]).toUpperCase().equals("2B") ? "+" : "-"; // 正负符号
byte[] dotIndexByte = new byte[]{dataByTF0[8]};
int dotIndex = Integer.parseInt(new String(dotIndexByte)); // 小数点位数, 从右向左
byte[] dataNum = Arrays.copyOfRange(dataByTF0, 2, 8); // 数据位
dataStr = symbol + new String(dataNum);
if (dotIndex > 0) { // 如果有小数位则做相应的处理
dataStr = dataStr.substring(0, dataStr.length() - 1 - dotIndex) + "." + dataStr.substring(dataStr.length() - dotIndex, dataStr.length());
}
System.out.println("Bytes to string start !!!");
System.out.println("Bytes to String : " + dataStr);
System.out.println("Bytes to string end !!!");
dataByTF0 = new byte[12]; // 重置接收数据容器
}
return dataStr;
}
/**
* 解析耀华仪表盘P52连续发送方式
*
* @param buffer
* @throws Exception
*/
private String readDataByP52(byte[] buffer) throws Exception {
String dataStr = "";
if (dataByP52[0] == 0) { // 如果当前接收数据为空
if (buffer[0] == startByP52) { // 如果当前数据处于一个完整数据的开始部分则进行接收
for (int i = 0; i < buffer.length; i++) {
dataByP52[i] = buffer[i]; // 将从串口读取到的数据存入data中
}
}
} else if (dataByP52[dataByP52.length - 1] == 0) {
int dataIndex = 0; // 当前数据应该存入的下标位
for (int i = 0; i < dataByP52.length; i++) {
if (dataByP52[i] == 0) {
dataIndex = i;
break;
}
}
for (int i = 0; i < buffer.length; i++) {
dataByP52[dataIndex++] = buffer[i];
if (buffer[i] == endByP52) { // 如果已经达到结束部分则退出循环
break;
}
}
}
if (dataByP52.length == 14 && dataByP52[13] != 0) { // 一个完整的数据已经接收完成, 处理数据并进行结果展示
String symbol = "+";
if (dataByP52[2] == 45) {
symbol = "-";
} else {
symbol = "+";
}
String unit = new String(Arrays.copyOfRange(dataByP52, 10, 12)).toUpperCase(); // 单位数据
byte[] dataNum = Arrays.copyOfRange(dataByP52, 3, 10); // 数据位
if (unit.toUpperCase().equals("KG")) { // 公斤
dataStr = new String(dataNum);
} else if (unit.toUpperCase().equals("LB")) { // 磅,1磅(lb)=0.4535924千克(kg)
dataStr = new BigDecimal(new String(dataNum)).multiply(new BigDecimal(0.4535924)).setScale(2, BigDecimal.ROUND_HALF_UP).toString(); // 计算出kg的数值保留两位小数
} else {
// Placeholder
}
dataStr = symbol + dataStr;
System.out.println("Bytes to string start !!!");
System.out.println("Bytes to String : " + dataStr);
System.out.println("Bytes to string end !!!");
dataByP52 = new byte[14]; // 重置接收数据容器
}
return dataStr;
}
@Override
public void onDestroy() {
super.onDestroy();
isOpen = false;
// Make sure we're not doing discovery anymore
if (mBtAdapter != null) {
mBtAdapter.cancelDiscovery();
}
new Thread() {
public void run() {
if (clientConnectThread != null) {
clientConnectThread.interrupt();
clientConnectThread = null;
}
if (mreadThread != null) {
mreadThread.interrupt();
mreadThread = null;
}
if (socket != null) {
try {
socket.close();
LogUtil.e("-- 蓝牙连接 close");
} catch (IOException e) {
e.printStackTrace();
}
socket = null;
}
}
}.start();
}
}