微信小程序是
一種新的應用,用戶不須要下載應用只用經過掃二維碼或者打開連接就能使用,使用完後不須要卸載,直接關閉就好了。微信在2017年初推出微信小程序開發環境。任何企業,媒體,我的均可以註冊開發。是一種全新的 開發模式。微信也所以受到許多程序員的一致好評,尤爲是微信小程序的雲開發,提供大量數據處理接口,讓初學者也能夠很快入手。不須要後端數據庫的支持,本身一我的就能夠開發前端和後臺。javascript
微信小程序爲藍牙模塊提供了18個API。其中低功率藍牙9個,傳統藍牙9個。本次設計使用了其中的9個接口:html
(1) openBluetoothAdapter,這個API用來初始化藍牙適配器;前端
(2) startBluetoothDevicesDiscovery,開始搜索藍牙設備;java
(3) onBluetoothDeviceFound,判斷搜索到的藍牙設備的信號強度;android
(4) createBLEConnection,鏈接搜索到的藍牙設備;程序員
(5) stopBluetoothDevicesDiscovery,關閉搜索藍牙設備;數據庫
(6) getBLEDeviceServices,獲取藍牙的deviceId;編程
(7) getBLEDeviceCharacteristics,獲取藍牙設備服務的全部特徵值;小程序
(8) notycharacteristicsId,啓用低功耗藍牙特徵值的notify功能;後端
(9) writeBLECharacteristicValue,經過微信小程序向藍牙模塊發送命令。
js源代碼
Page({ /** * 頁面的初始數據 */ data: { connect: false, send_hex: false, send_string: true, send_string_val: 'Hex', recv_string: true, recv_string_val: 'Hex', recv_value: '', send_number: 0, recv_number: 0, recv_hex: true, wendu: 30, yanwu: 60 }, /*** 生命週期函數--監聽頁面加載 */ onLoad: function (options) { wx.stopBluetoothDevicesDiscovery({ success: function (res) { console.log('中止搜索設備', res) } }) console.log(options); this.setData({ deviceId: options.id, deviceName: options.name }); console.log('設備的ID', this.data.deviceId); }, /*** 生命週期函數--監聽頁面顯示 */ onShow: function () { wx.stopBluetoothDevicesDiscovery({ success: function (res) { console.log('中止搜索設備', res) } }) var that = this; /* 鏈接中動畫 */ wx.showLoading({ title: '鏈接中...', }); /* 開始鏈接藍牙設備 */ wx.createBLEConnection({ deviceId: that.data.deviceId, success: function (res) { console.log('鏈接成功', res); wx.hideLoading(); /* 獲取設備的服務UUID */ wx.getBLEDeviceServices({ deviceId: that.data.deviceId, success: function (service) { that.setData({ serviceId: "0000FFE0-0000-1000-8000-00805F9B34FB" //肯定須要的服務UUID }); console.log('須要的服務UUID', that.data.serviceId) that.Characteristics(); //調用獲取特徵值函數 }, }); that.setData({ connect: true }) }, }) }, Characteristics: function () { var that = this; var device_characteristics = []; var characteristics_uuid = {}; wx.getBLEDeviceCharacteristics({ deviceId: that.data.deviceId, serviceId: that.data.serviceId, success: function (res) { var characteristics = res.characteristics; //獲取到全部特徵值 var characteristics_length = characteristics.length; //獲取到特徵值數組的長度 console.log('獲取到特徵值', characteristics); console.log('獲取到特徵值數組長度', characteristics_length); that.setData({ notycharacteristicsId: "0000FFE1-0000-1000-8000-00805F9B34FB", //需肯定要的使能UUID characteristicsId: "0000FFE1-0000-1000-8000-00805F9B34FB" //暫時肯定的寫入UUID }); console.log('使能characteristicsId', that.data.notycharacteristicsId); console.log('寫入characteristicsId', that.data.characteristicsId); that.notycharacteristicsId(); //使能事件 }, }) }, /* 使能函數 */ notycharacteristicsId: function () { var that = this; var recv_value_ascii = ""; var string_value = ""; var recve_value = ""; wx.notifyBLECharacteristicValueChange({ deviceId: that.data.deviceId, serviceId: that.data.serviceId, characteristicId: that.data.notycharacteristicsId, state: true, success: function (res) { console.log('使能成功', res); /* 設備返回值 */ wx.onBLECharacteristicValueChange(function (res) { var length_hex = []; var turn_back = ""; var result = res.value; var hex = that.buf2hex(result); console.log('返回的值', hex); if (that.data.recv_string == true) { /* 成功接收到的值的展現 */ that.setData({ recv_value: that.data.recv_value + hex }); /* 接收成功的值的字節 */ var recv_number_1 = that.data.recv_number + hex.length / 2; var recv_number = Math.round(recv_number_1); that.setData({ recv_number: recv_number }); } else { console.log('設備返回來的值', hex); var f_hex = hex; var length_soy = f_hex.length / 2; var length = Math.round(length_soy); for (var i = 0; i < length; i++) { var hex_spalit = f_hex.slice(0, 2); length_hex.push(hex_spalit); f_hex = f_hex.substring(2); } console.log('length_hex', length_hex); for (var j = 0; j < length_hex.length; j++) { var integar = length_hex[j]; //十六進制 recve_value = parseInt(integar, 16); //十進制 console.log('recve_value', recve_value); turn_back = turn_back + String.fromCharCode(recve_value); console.log('turn_back', turn_back); } console.log('最終轉回來的值', turn_back) var recv_number_1 = that.data.recv_number + turn_back.length; var recv_number = Math.round(recv_number_1); that.setData({ recv_number: recv_number, recv_value: that.data.recv_value + turn_back }) } }); }, fail: function (res) { console.log('使能失敗', res); } }) }, /* 斷開鏈接 */ DisConnectTap: function () { var that = this; wx.closeBLEConnection({ deviceId: that.data.deviceId, success: function (res) { console.log('斷開設備鏈接', res); wx.reLaunch({ url: '../index/index', }) } }); }, /*** 生命週期函數--監聽頁面卸載 */ onUnload: function () { var that = this; wx.closeBLEConnection({ deviceId: that.data.deviceId, success: function (res) { console.log('斷開設備鏈接', res); } }); }, /* 清除Recv Bytes */ CleanNumberRecv: function () { this.setData({ recv_number: 0 }) }, /* ArrayBuffer類型數據轉爲16進制字符串 */ buf2hex: function (buffer) { // buffer is an ArrayBuffer var hexArr = Array.prototype.map.call( new Uint8Array(buffer), function (bit) { return ('00' + bit.toString(16)).slice(-2) } ) return hexArr.join(''); }, switch1Change: function (e) { var that = this; let buffer = new ArrayBuffer(1) let dataView = new DataView(buffer) if (e.detail.value) { dataView.setUint8(0, 0) } else { dataView.setUint8(0, 1) } wx.writeBLECharacteristicValue({ deviceId: that.data.deviceId, serviceId: that.data.serviceId, characteristicId: that.data.characteristicsId, value: buffer, success: function (res) { console.log('數據發送成功', res); console.log(buffer); }, fail: function (res) { console.log('調用失敗', res); /* 調用失敗時,再次調用 */ wx.writeBLECharacteristicValue({ deviceId: that.data.deviceId, serviceId: that.data.serviceId, characteristicId: that.data.characteristicsId, value: buffer, success: function (res) { console.log('第2次數據發送成功', res); } }) } }) }, switch1Change1: function (e) { var that = this; let buffer = new ArrayBuffer(1) let dataView = new DataView(buffer) if (e.detail.value) { dataView.setUint8(0, 2) } else { dataView.setUint8(0, 3) } wx.writeBLECharacteristicValue({ deviceId: that.data.deviceId, serviceId: that.data.serviceId, characteristicId: that.data.characteristicsId, value: buffer, success: function (res) { console.log('數據發送成功', res); console.log(buffer); }, fail: function (res) { console.log('調用失敗', res); /* 調用失敗時,再次調用 */ wx.writeBLECharacteristicValue({ deviceId: that.data.deviceId, serviceId: that.data.serviceId, characteristicId: that.data.characteristicsId, value: buffer, success: function (res) { console.log('第2次數據發送成功', res); } }) } }) }, add: function (e) { var id = e.target.id; if (this.data[id] > 98) { wx.showToast({ title: '已超過最大數值', icon: 'loading', duration: 2000 }) return; } this.setData({ [id]: +this.data[id] + 1 }); this.numbers(id) }, lessen: function (e) { var id = e.target.id; if (this.data[id] < 1) { wx.showToast({ title: '已小於最小數值', icon: 'loading', duration: 2000 }) return; } this.setData({ [id]: +this.data[id] - 1 }); this.numbers(id) }, changeVal: function (e) { var id = e.target.id; if (e.detail.value < 1 || e.detail.value > 100) { wx.showToast({ title: '請輸入有效數值', icon: 'loading', duration: 2000 }) return; } this.setData({ [id]: e.detail.value }); this.numbers(id) }, numbers: function (id) { var that = this; var number = '9'; let buffer = new ArrayBuffer(1) let dataView = new DataView(buffer) console.log(id) if (id == 'wendu') { number = '8' + that.data[id]; dataView.setUint8(0, 8) } else { number = number + that.data[id]; dataView.setUint8(0, number) } wx.writeBLECharacteristicValue({ deviceId: that.data.deviceId, serviceId: that.data.serviceId, characteristicId: that.data.characteristicsId, value: buffer, success: function (res) { console.log('數據發送成功', res); console.log(buffer); } }) } })
wxss源代碼
.connect_box { width: 100%; height: 30px; line-height: 30px; font-size: 32rpx; color: #666; font-family: "Microsoft YaHei"; } .connect_device_name{ float: left; padding-left: 10px; color: #39beff; } .connect_state { float: right; padding-right: 10px; text-decoration: underline; color: #39beff; } .fan{ width: 2rem; height: 2rem; vertical-align: middle; margin-left: 2.25rem; margin-right: 0.25rem; } .water{ width: 2.5rem; height: 2rem; vertical-align: middle; margin-left: 2rem; } .name{ display: inline-block; width: 22%; margin-left: 1.5rem; font-size: 0.9rem; } .key{ float: right; margin-right: 2rem; margin-top: 0.2rem; } .detail_box{ padding: 1.5rem 0; border-bottom: 1px solid #ccc; } .num { display: inline-block; width: 45%; text-align: right; vertical-align: middle; } .num input { display: inline-block; width: 2rem; text-align: center; border: 1px solid #f2f2f2; border-left: none; border-right: none; color: #a2a2a2; } .num text { display: inline-block; width: 1.4rem; height: 1.4rem; line-height: 1.4rem; text-align: center; border: 1px solid #f2f2f2; vertical-align: top; color: #dcdcdc; } .wendu{ width:1.9rem; height:2rem; vertical-align:middle; margin-left:2.3rem; margin-right:.3rem; }
wxml源代碼
<view class="connect_box"> <text class='connect_device_name'>{{deviceName}}</text> <text wx:if="{{connect}}" class="connect_state" catchtap="DisConnectTap">已鏈接</text> <text wx:else class="connect_state">未鏈接</text> </view> <view > <view class="detail_box"> <image src='../../images/airFan.png' class="fan"></image> <view class='name'>風扇</view> <switch bindchange="switch1Change" class='key' /> </view> <view class="detail_box"> <image src='../../images/waterPump.png' class="water"></image> <view class='name'>水泵</view> <switch bindchange="switch1Change1" class='key' /> </view> <view class="detail_box"> <image src='../../images/temperature.png' class="wendu"></image> <view class='name'>溫度閥值</view> <view class='num'> <text style='border-radius: 3px 0 0 3px;' id='wendu' bindtap='lessen'>-</text> <input type='number' value='{{wendu}}' name='piece' id='wendu' bindblur="changeVal" /> <text style='border-radius: 0 3px 3px 0;' id='wendu' bindtap='add'>+</text> </view> </view> <view class="detail_box"> <image src='../../images/smog.png' class="water"></image> <view class='name'>煙霧閥值</view> <view class='num'> <text style='border-radius: 3px 0 0 3px;' id='yanwu' bindtap='lessen'>-</text> <input type='number' value='{{yanwu}}' name='piece' id='yanwu' bindblur="changeVal" /> <text style='border-radius: 0 3px 3px 0;' id='yanwu' bindtap='add'>+</text> </view> </view> </view>
微信小程序展現頁面
微信小程序不能在電腦上模擬,智能用手機操做,咱們須要用手機打開咱們的微信小程序。首先若是手機藍牙沒有打開回提醒打開藍牙從新加載。若是手機藍牙打開了就會去搜索附近的藍牙模塊,搜索到本身的低功率藍牙,點擊就能夠鏈接到本身的藍牙。咱們就到了控制頁面。
咱們能夠經過微信小程序風扇和水泵。點擊開關時會調用writeBLECharacteristicValue接口經過藍牙模塊給單片機發送指令,控制單片機上的風扇和水泵等硬件設備。
2.硬件設備介紹
硬件部分主要介紹單片機、低功率藍牙、風扇和水泵。單片機用什麼型號的都行,都能與藍牙模塊正常通訊,收發數據。低功率藍牙主要優勢是功率低,壽命長,價格便宜。多用於硬件鏈接上位機軟件。風扇和水泵是外接設備,由單片機控制。
1.單片機
單片機的型號是stc89c52rc,STC89C52RC是STC公司生產的一種低功耗、高性能CMOS8位微控制器,具備8K字節系統可編程Flash存儲器。STC89C52使用經典的MCS-51內核,可是作了不少的改進使得芯片具備傳統的方法51單片機不具有的功能。在單芯片上,擁有靈巧的8 位CPU 和在系統可編程Flash,使得STC89C52爲衆多嵌入式控制應用系統提供高靈活、超有效的解決方案。
2.藍牙模塊
我用的是藍牙型號是HC-06,給HC-06上電以後,HC-06的指示燈會不停地閃爍,這個時候就標誌着進入AT模式了,配置的時候,HC-06的Rx和Tx 接到 51單片機的 Rx和 Tx,通常是P3.0,和P3.1,正常工做時,HC-06的Rx和Tx 接到 51單片機的 Tx和 Rx,8位數據位,1位結束位,無奇偶校驗。通常HC-06模塊的默認名稱就是hc-06,默認配對密碼是1234或0000。咱們若是鏈接微信小程序,咱們要把密碼取消,這樣微信小程序才能直接來鏈接。
3.風扇和水泵
風扇和水泵是直接供電就可使用,咱們只須要一個繼電器就能夠控制這兩個設備,我選擇了P3.5,P3.4這兩個引腳來控制,高電平驅動,低電平關閉,這兩個外接設備主要是測試數據有沒有接受成功。
單片機程序主程序
void ctrl(unsigned char a) //單字節數據接收 { //注意:若單片機TXD(P3.1)無上拉能力,必須在P3.1端接上拉電阻。本次測試須要接上拉電阻 TI=0; SBUF=a; while(TI==0); TI=0; Mode=1; if(SBUF==0){ LED_yanwu=0; baojing=0; fs=0; led1=0; led2=0; }else if(SBUF==1){ LED_yanwu=1; baojing=1; fs=1; Mode=0; }else if(SBUF==2){ baojing=0; LED_wendu=0; fs1=0; }else if(SBUF==3){ baojing=1; LED_wendu=1; fs1=1; led1=0; led2=0; Mode=0; } } void main() { check_wendu(); check_wendu(); Init1602(); ES=0; //關中斷 SCON = 0x50; // REN=1容許串行接受狀態,串口工做模式1, //10位UART(1位起始位,8位數據位,1位中止位,無奇偶校驗),波特率可變 TMOD = 0x20; // 定時器1工做於方式2,8位自動重載模式, 用於產生波特率 TH1=TL1=0xFD; // 波特率9600 (本次測試採用晶振爲11.0592) PCON &= 0x7f; // 波特率不倍增 TR1 = 1; //定時器1開始工做,產生波特率 TI=0; //接收標誌位置0 RI=0; ES=1; while(1) { temp=ADC0809(); check_wendu(); Key(); if(RI==1) // 是否有數據到來 { RI = 0; ctrl(SBUF); } Display_1602(yushe_wendu,yushe_yanwu,c,temp); //c溫度值,temp煙霧值 if(Mode==0) { if(temp>=yushe_yanwu) { LED_yanwu=0; baojing=0; fs=0; } else { LED_yanwu=1; } if(c>800){ c = 0; } if(c>=(yushe_wendu*10)) { baojing=0; LED_wendu=0; fs1=0; } else { LED_wendu=1; } if((temp<yushe_yanwu)&&(c<(yushe_wendu*10))) { baojing=1; fs=1; fs1=1; } } } }
硬件實物圖
數據採集顯示正常,微信小程序能夠正常控制單片機的水泵和風扇,通訊正常無異常。硬件部分我就簡單的拿出來講了一下,所涉及到的知識確定比我展現到的多,軟件部分主要是對低功率藍牙的搜索,鏈接,發送數據比較麻煩。