如何从BLE服务器发送和接收数据?

时间:2020-02-26 15:13:42

标签: java android bluetooth bluetooth-lowenergy

上次我发布了有关BLE的问题。我对BLE和经典蓝牙感到困惑。现在,我编写这段代码,从Internet上获得了很多帮助,但是现在,我陷入了如何将数据发送到BLE服务器以及如何从BLE服务器读取数据的问题。此数据以逗号分隔。其次是宪章。我用的是UTF-8

define SERVICE_UUID   "ab0828b1-198e-4351-b779-901fa0e0371e"
define CHARACTERISTIC_UUID_RX  "4ac8a682-9736-4e5d-932b-e9b31405049c"
define CHARACTERISTIC_UUID_TX  "0972EF8C-7613-4075-AD52-756F33D4DA91"

UUI是RX的可读性和TX的可写性。

import android.Manifest;
import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.ficat.easyble.BleDevice;
import com.ficat.easyble.BleManager;
import com.ficat.easyble.gatt.bean.CharacteristicInfo;
import com.ficat.easyble.gatt.bean.ServiceInfo;
import com.ficat.easyble.gatt.callback.BleConnectCallback;
import com.ficat.easyble.gatt.callback.BleWriteCallback;
import com.ficat.easyble.scan.BleScanCallback;
import com.ficat.easypermissions.EasyPermissions;
import com.ficat.easypermissions.RequestExecutor;
import com.ficat.easypermissions.bean.Permission;
import com.ficat.sample.adapter.ScanDeviceAdapter;
import com.ficat.sample.adapter.common.CommonRecyclerViewAdapter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private final static String CHARACTERISTIC_READABLE = "4ac8a682-9736-4e5d-932b-e9b31405049c";
    private final static String CHARACTERISTIC_WRITABLE =  "0972EF8C-7613-4075-AD52-756F33D4DA91";
    private final static int CHARACTERISTIC_NOTIFICATION = 103;

    private RecyclerView rv;
    private BleManager manager;
    private List<BleDevice> deviceList = new ArrayList<>();
    private ScanDeviceAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initBleManager();
        showDevicesByRv();
    }

    private void initView() {
        Button btnScan = findViewById(R.id.btn_scan);
        Button btnDisconnect = findViewById(R.id.btn_disconnect);
        Button btnNotify = findViewById(R.id.btn_notify);
        Button btnWrite = findViewById(R.id.btn_write);
        rv = findViewById(R.id.rv);

        btnScan.setOnClickListener(this);
        btnDisconnect.setOnClickListener(this);
        btnNotify.setOnClickListener(this);
        btnWrite.setOnClickListener(this);
    }

    private void initBleManager() {
        //check if this android device supports ble
        if (!BleManager.supportBle(this)) {
            return;
        }
        //open bluetooth without a request dialog
        BleManager.toggleBluetooth(true);

        BleManager.Options options = new BleManager.Options();
        options.loggable = true;
        options.scanPeriod = 10000;
        options.connectTimeout = 10000;
        manager = BleManager.getInstance(getApplication());
        manager.option(options);
    }

    private void showDevicesByRv() {
        rv.setLayoutManager(new LinearLayoutManager(this));
        rv.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                super.getItemOffsets(outRect, view, parent, state);
                outRect.top = 3;
            }
        });
        SparseArray<int[]> res = new SparseArray<>();
        res.put(R.layout.item_rv_scan_devices, new int[]{R.id.tv_name, R.id.tv_address, R.id.tv_connection_state});
        adapter = new ScanDeviceAdapter(this, deviceList, res);
        adapter.setOnItemClickListener(new CommonRecyclerViewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View itemView, int position) {
                manager.stopScan();
                manager.connect(deviceList.get(position), new BleConnectCallback() {
                    @Override
                    public void onStart(boolean startConnectSuccess, String info, BleDevice device) {
                        Log.e(TAG, "start connecting = " + startConnectSuccess + "     info: " + info);
                    }

                    @Override
                    public void onTimeout(BleDevice device) {
                        Toast.makeText(MainActivity.this, "connect timeout!", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onConnected(BleDevice device) {
                        adapter.notifyDataSetChanged();
                    }

                    @Override
                    public void onDisconnected(BleDevice device) {
                        adapter.notifyDataSetChanged();
                    }
                });
            }
        });
        rv.setAdapter(adapter);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_scan:
                if (!BleManager.isBluetoothOn()) {
                    BleManager.toggleBluetooth(true);
                }
                EasyPermissions
                        .with(this)
                        .request(Manifest.permission.ACCESS_COARSE_LOCATION)
                        .autoRetryWhenUserRefuse(true, null)
                        .result(new RequestExecutor.ResultReceiver() {
                            @Override
                            public void onPermissionsRequestResult(boolean grantAll, List<Permission> results) {
                                if (grantAll) {
                                    if (!manager.isScanning()) {
                                        startScan();
                                    }
                                } else {
                                    Toast.makeText(MainActivity.this,
                                            "Please go to settings to grant location permission manually",
                                            Toast.LENGTH_LONG).show();
                                    EasyPermissions.goToSettingsActivity(MainActivity.this);
                                }
                            }
                        });
                break;
            case R.id.btn_disconnect:
                manager.disconnectAll();
                break;
            case R.id.btn_notify:
                testNotify();
                break;
            case R.id.btn_write:
                testWrite();
                break;
            default:
                break;
        }
    }

    private void startScan() {
        manager.startScan(new BleScanCallback() {
            @Override
            public void onLeScan(BleDevice device, int rssi, byte[] scanRecord) {
                for (BleDevice d : deviceList) {
                    if (device.address.equals(d.address)) {
                        return;
                    }
                }
                deviceList.add(device);
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onStart(boolean startScanSuccess, String info) {
                Log.e(TAG, "start scan = " + startScanSuccess + "   info: " + info);
                if (startScanSuccess) {
                    deviceList.clear();
                    adapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onFinish() {
                Log.e(TAG, "scan finish");
            }
        });
    }




    private void testWrite() {
        if (manager.getConnectedDevices().size() <= 0) {
            Toast.makeText(MainActivity.this, "No connected devices", Toast.LENGTH_SHORT).show();
            return;
        }
        //we use the first connected device to test
        BleDevice device1 = manager.getConnectedDevices().get(0);
        //randomly finding a writable characteristic to test
        Map<String, String> notificationInfo1 = getSpecificServiceInfo(device1, CHARACTERISTIC_WRITABLE);
        for (Map.Entry<String, String> e : notificationInfo1.entrySet()) {
            manager.write(device1, e.getKey(), e.getValue(), "TestWriteData001".getBytes(), new BleWriteCallback() {
                @Override
                public void onWrite(byte[] data, BleDevice device) {
                    Toast.makeText(MainActivity.this, "write success!   data:  " + new String(data), Toast.LENGTH_LONG).show();
                }

                @Override
                public void onFail(int failCode, String info, BleDevice device) {
                    Toast.makeText(MainActivity.this, "write fail: " + info, Toast.LENGTH_SHORT).show();
                }
            });
            return;
        }
    }

    private void testNotify() {
        if (manager.getConnectedDevices().size() <= 0) {
            Toast.makeText(MainActivity.this, "No connected devices", Toast.LENGTH_SHORT).show();
            return;
        }
        //we use the first connected device to test
        BleDevice device = manager.getConnectedDevices().get(0);

    }


    private Map<String, String> getSpecificServiceInfo(BleDevice device, String characteristicProperty) {
        Map<String, String> map = new HashMap<>();
        Map<ServiceInfo, List<CharacteristicInfo>> serviceInfo = manager.getDeviceServices(device);
        for (Map.Entry<ServiceInfo, List<CharacteristicInfo>> entry : serviceInfo.entrySet()) {
            String serviceUuid = entry.getKey().uuid;
            for (CharacteristicInfo charInfo : entry.getValue()) {
                boolean specificReadable = characteristicProperty.equals(CHARACTERISTIC_READABLE) && charInfo.readable;
                boolean specificWritable = characteristicProperty.equals(CHARACTERISTIC_WRITABLE) && charInfo.writable;

            }
        }
        return map;
    }
}

0 个答案:

没有答案