泰凌微ble mesh蓝牙模组天猫精灵学习之旅④如何在Android开发低功耗蓝牙ble控制 TB-02 模块,代码工程全部开源!(附带Demo)
- 本<泰凌微ble mesh藍(lán)牙模組天貓精靈學(xué)習(xí)之旅>系列博客學(xué)習(xí)由半顆心臟 潛心所力所寫,僅僅做個(gè)人技術(shù)交流分享,不做任何商業(yè)用途。如有不對之處,請留言,本人及時(shí)更改。
1、小白也癡迷,如何在 Linux環(huán)境搭建編譯燒錄 安信可TB02,點(diǎn)亮一盞LED燈;
2、如何實(shí)現(xiàn) 微信小程序藍(lán)牙控制 Ble Mesh模組 安信可TB02,全部開源!
3、簡單入門安信可TB-02開發(fā)開發(fā)板輕松接入天貓精靈,語音控制冷暖燈so easy!
4、如何在Android開發(fā)低功耗藍(lán)牙ble控制 TB-02 模塊,代碼工程全部開源!
5、 初認(rèn)識(shí)阿里天貓精靈官方Genie BT mesh Stack框架, windows平臺(tái)搭建打印Hello World!
文章目錄
- 前言
- 一、材料準(zhǔn)備
- 二、藍(lán)牙模塊初始化
- 三、App開發(fā)過程
- 4.1 搜索設(shè)備
- 4.2 連接設(shè)備
- 4.3 獲取服務(wù)列表和其特征列表
- 4.4 主動(dòng)訂閱通知
- 4.5 如何接受設(shè)備發(fā)來的數(shù)據(jù)
- 4.6 如何發(fā)送數(shù)據(jù)到設(shè)備
- 另外,不要把我的博客作為學(xué)習(xí)標(biāo)準(zhǔn),我的只是筆記,難有疏忽之處,如果有,請指出來,也歡迎留言哈!
前言
????工作了三年,職業(yè)之路不能偏離方向,當(dāng)海浪掀起,周圍會(huì)有一些美麗的風(fēng)景在吸引著你,抑或有誘惑在向你招手,請不要沉迷,請不要迷戀,走走停停,每一段旅程都應(yīng)該有它的歸屬;
????一直在從事智能家居領(lǐng)域,對無線對接語音平臺(tái),微信控制什么的,小家電很熟,但是對 Linux 驅(qū)動(dòng)等一些工業(yè)級的應(yīng)用開發(fā),一竅不通;這是我這個(gè)月的反思,等做好這個(gè)Ble Mesh的熟悉之后,會(huì)逐漸地轉(zhuǎn) Linux 和 服務(wù)器開發(fā),因?yàn)槲覀€(gè)人是喜歡敲代碼的,即使老去了,看著曾經(jīng)敲過的代碼,無比喜悅!
????好了,今天就給大家我最近做的一個(gè)《安信可Android藍(lán)牙APP控制TB02》的過程分享吧!
????最后共勉大家一句話: 生命意義在于折騰,生命價(jià)值在于奉獻(xiàn);
一、材料準(zhǔn)備
????這里務(wù)必聲明一下,硬件對接需要一點(diǎn)成本請自行出資,并不像純軟件就可以搞的!下面推薦的藍(lán)牙模塊自行某寶購買哈!
????這里不涉及到單片機(jī)編程,直接用串口助手模擬單片機(jī);
???? 注意:一個(gè)ble藍(lán)牙設(shè)備可擁有多個(gè)服務(wù)和特征,涉及到讀取設(shè)備的服務(wù)和特征,都是需要需要設(shè)備廠商指定的!如果未能列出,那么此特征的權(quán)限是 可讀可寫可通知,一般為一個(gè)特征擁有此三個(gè)權(quán)限;如果不是,那需要具體問設(shè)備廠商啦!!
二、藍(lán)牙模塊初始化
???? 如果您的板子并沒燒錄AT固件,請按照第一篇文章,編譯 example/at 工程,燒錄到板子即可!
???? 默認(rèn)波特率等設(shè)置,上電后會(huì)有信息打印,如下圖所示:
???? 本人不玩AT指令開發(fā),因做微信小程序,所以需了解此設(shè)備的AT指令,如需了解具體的AT指令集,點(diǎn)我:
???? 下面為大家列下主要指令:
| 1 | AT | 測試 AT |
| 2 | ATE | 開關(guān)回顯 |
| 3 | AT+GMR | 查詢固件版本 |
| 4 | AT+RST | 重啟模組 |
| 5 | AT+SLEEP | 深度睡眠 |
| 6 | AT+ RESTORE | 恢復(fù)出廠設(shè)置 恢復(fù)后將重啟 |
| 7 | AT+BAUD | 查詢或設(shè)置波特率 重啟后生效 |
| 8 | AT+NAME | 查詢或設(shè)置藍(lán)牙廣播名稱 重啟后生效 |
| 9 | AT+MAC | 設(shè)置或查詢模組 MAC 地址 重啟后生效 |
| 10 | AT+STATE | 查詢藍(lán)牙連接狀態(tài) |
| 11 | AT+SEND | AT 模式下發(fā)送數(shù)據(jù) |
| 12 | +DATA | AT 模式下收到數(shù)據(jù) |
三、App開發(fā)過程
???? Android開發(fā)的藍(lán)牙ble API文檔還是很齊全的!為了減少開發(fā)工作量,我使用了第三方庫,實(shí)現(xiàn) 動(dòng)態(tài)授權(quán)和 ble連接發(fā)現(xiàn)以及設(shè)備通訊;
???? APP源碼已經(jīng)在底部貼出,請知悉!
4.1 搜索設(shè)備
???? 搜索前務(wù)必要開啟 藍(lán)牙權(quán)限,而在安卓 6.0(包括6.0) 系統(tǒng)以上,務(wù)必開啟定位權(quán)限,否則也是無法搜索到藍(lán)牙設(shè)備的呢!
//動(dòng)態(tài)授權(quán) PermissonUtil.checkPermission(this, new PermissionListener() {@Overridepublic void havePermission() {initBleScan();}@Overridepublic void requestPermissionFail() {Toast.makeText(mContext, "您拒絕了開啟權(quán)限", Toast.LENGTH_SHORT).show();finish();}}, Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_FINE_LOCATION);???? 第一步肯定是搜索設(shè)備,通過 調(diào)用 object.scanBle() 來發(fā)現(xiàn)設(shè)備,入?yún)⒖梢灾付?UUID,注意設(shè)備列表的回調(diào)是通過 onSuccess() 方法回調(diào)。
mBleController.scanBle(0, new ScanCallback() {@Overridepublic void onSuccess() {//判斷獲取到的設(shè)備藍(lán)牙列表是否大于0if (bluetoothDevices.size() > 0) {mDeviceList.setAdapter(new DeviceListAdapter(MainActivity.this, bluetoothDevices));mDeviceList.setOnItemClickListener(MainActivity.this);} else {Toast.makeText(MainActivity.this, "Search Device Lists empty!", Toast.LENGTH_SHORT).show();}}@Overridepublic void onScanning(BluetoothDevice device, int rssi, byte[] scanRecord) {//過濾是否含有 Ai-Thinker 名字的藍(lán)牙設(shè)備if (device.getName() != null && device.getName().contains("Ai-Thinker"))if (!bluetoothDevices.contains(device)) {bluetoothDevices.add(device);}}});4.2 連接設(shè)備
????上步我們已經(jīng)拿到了周圍的藍(lán)牙設(shè)備列表,那么如何判斷哪個(gè)是我們想要的呢?一般為名字,TB02的廣播名字一般為 Ai-Thinker,于是乎,調(diào)用 connect() ,入?yún)樗阉鞯降脑O(shè)備的 mac地址!
//連接設(shè)備mBleController.connect(0, address, new ConnectCallback() {@Overridepublic void onConnSuccess() {Toast.makeText(MainActivity.this, "connected!", Toast.LENGTH_SHORT).show();}@Overridepublic void onConnFailed() {Toast.makeText(MainActivity.this, "connect fail!", Toast.LENGTH_SHORT).show();}});4.3 獲取服務(wù)列表和其特征列表
????上面說了,一個(gè)設(shè)備可擁有多個(gè)服務(wù)service,我們在獲取時(shí)候,是在已連接成功的情況下再獲取哦!
????下面獲取到了服務(wù)列表,并通過判斷其 uuid 是否和我們一致,從而判斷是否Tb01設(shè)備,否則,就是連接了其他設(shè)備。
????也許你會(huì)問,如何獲取這個(gè)uuid是否一致。參考uuid一般是廠商提供的,如下:
//TODO 這里是TB02開發(fā)板提供的各種UUID,請勿修改private static final String BLUETOOTH_S = "00010203-0405-0607-0809-0a0b0c0d1910";private static final String BLUETOOTH_NOTIFY_C = "00010203-0405-0607-0809-0a0b0c0d2b10";private static final String BLUETOOTH_WRITE_C = "00010203-0405-0607-0809-0a0b0c0d2b10";????如果獲取了服務(wù),那么我們下一步就是要獲此這個(gè)服務(wù)下的特征列表;
????同樣道理,也是要獲取到其特征的uuid,在 TB01模塊里面的這個(gè)服務(wù),只有一個(gè)特征好吧。所以只取元素第一個(gè)即可!
????下面是代碼,其實(shí)這些早已經(jīng)封裝在另外一個(gè)庫了,如有興趣可以去翻閱看看品讀;
//服務(wù)被發(fā)現(xiàn)了@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {if (null != mBluetoothGatt && status == BluetoothGatt.GATT_SUCCESS) {List<BluetoothGattService> services = mBluetoothGatt.getServices();int serviceSize = services.size();for (int i = 0; i < serviceSize; i++) {HashMap<String, BluetoothGattCharacteristic> charMap = new HashMap<>();BluetoothGattService bluetoothGattService = services.get(i);String serviceUuid = bluetoothGattService.getUuid().toString();List<BluetoothGattCharacteristic> characteristics = bluetoothGattService.getCharacteristics();int characteristicSize = characteristics.size();for (int j = 0; j < characteristicSize; j++) {charMap.put(characteristics.get(j).getUuid().toString(), characteristics.get(j));if (characteristics.get(j).getUuid().toString().equals(BLUETOOTH_NOTIFY_C)) {if (enableNotification(true, characteristics.get(j))) {isConnectResponse = true;connSuccess();} else {reConnect();}}}servicesMap.put(serviceUuid, charMap);}}}4.4 主動(dòng)訂閱通知
????下面程序中的調(diào)用 wx.notifyBLECharacteristicValueChange()方法目的是 主動(dòng)監(jiān)聽此通道的數(shù)值變化,通俗來說就是:設(shè)備一旦發(fā)送數(shù)據(jù)在此通道,就會(huì)立刻收到通知;
if (!mBluetoothGatt.setCharacteristicNotification(characteristic, enable))return false;4.5 如何接受設(shè)備發(fā)來的數(shù)據(jù)
????上一點(diǎn)已經(jīng)主動(dòng)監(jiān)聽到了某通道的數(shù)值變化,這點(diǎn)必須要做的;
????然后,就可以調(diào)用下面方法,接收到數(shù)據(jù)打印出來。注意:接收到的是十六進(jìn)制格式,還需要轉(zhuǎn)下!
// TODO 接收數(shù)據(jù)的監(jiān)聽mBleController.registReciveListener(REQUESTKEY_SENDANDRECIVEACTIVITY, new OnReceiverCallback() {@Overridepublic void onRecive(byte[] value) {// 這里為了演示方便,把 byte數(shù)組轉(zhuǎn)字符串顯示String string = new String(value);mReciveString.append(string + "\r\n");mReciveText.setText(mReciveString.toString());}});4.6 如何發(fā)送數(shù)據(jù)到設(shè)備
????發(fā)送數(shù)據(jù)時(shí)候,必須確定所在的通道是否可寫 write ;發(fā)送數(shù)據(jù)時(shí)候,務(wù)必把字符串轉(zhuǎn)為byte數(shù)組,再傳進(jìn)去;
String sendText = mSendEdit.getText().toString().trim();if (TextUtils.isEmpty(sendText)) {Toast.makeText(this, "send text cannot be null" , Toast.LENGTH_SHORT).show();return;} else {//這里把字符串格式轉(zhuǎn)byte數(shù)組byte[] bytes = sendText.getBytes();mBleController.writeBuffer(bytes, new OnWriteCallback() {@Overridepublic void onSuccess() {Toast.makeText(SendAndReciveActivity.this, "send OK!", Toast.LENGTH_SHORT).show();}@Overridepublic void onFailed(int state) {Toast.makeText(SendAndReciveActivity.this, "send Fail!", Toast.LENGTH_SHORT).show();}});}- 最后共勉,源碼地址:https://github.com/Ai-Thinker-Open/AiTBxxForWeChat
- 編譯后可直接安裝的APK:https://docs.ai-thinker.com/_media/ble/spec/ai-thinker_ble_tool.rar
另外,不要把我的博客作為學(xué)習(xí)標(biāo)準(zhǔn),我的只是筆記,難有疏忽之處,如果有,請指出來,也歡迎留言哈!
- 玩轉(zhuǎn)esp8266帶你飛、加群QQ群,不喜的朋友勿噴勿加:434878850
- 個(gè)人郵箱:xuhongv@yeah.net 24小時(shí)在線,有發(fā)必回復(fù)!
- esp8266源代碼學(xué)習(xí)匯總(持續(xù)更新,歡迎star):https://github.com/xuhongv/StudyInEsp8266
- esp32源代碼學(xué)習(xí)匯總(持續(xù)更新,歡迎star):https://github.com/xuhongv/StudyInEsp32
- 關(guān)注下面微信公眾號二維碼,干貨多多,第一時(shí)間推送!
總結(jié)
以上是生活随笔為你收集整理的泰凌微ble mesh蓝牙模组天猫精灵学习之旅④如何在Android开发低功耗蓝牙ble控制 TB-02 模块,代码工程全部开源!(附带Demo)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 泰克Tektronix示波器软件TDS2
- 下一篇: 桌面的计算机怎么打开,电脑如何开启桌面整