【沁恒RISC-V内核 CH582】微信小程序控制点灯
[复制链接]
【前言】
【沁恒RISC-V内核 CH582】BLE 点灯 https://bbs.eeworld.com.cn/thread-1195457-1-1.html
原先我用E4A做了一个点灯的小程序,但是那个小程序是单向控制LED灯,没反馈到灯的状态。最近公司做了一个BLE连接佳博蓝牙打印机的项目,本来是想用E4A来做的,但是没有支持的库,所以改用微信小程来做。周未,刚好把前面手机控制LED的程序移植到CH582的评测项目里来。其实微信小程序如果上手了的话,相比E4A,可以实现苹果、安卓以及华为的三个平台的通用,很是方便的。
【具体的思路】
CH582:1、上面接收微信小程序的接口还是用原来的接口。在回调函数simpleProfileChangeCB里的SIMPLEPROFILE_CHAR1接收上面判断开关标志,然后控制LED的IO发送高低电平。
2、在函数performPeriodicTask里每500ms读取LED的IO状态,生成上报数据用peripheralChar4Notify上报灯的状态。
微信小程序:1、搜索BLE设备,搜索到设备后将设备展示在APP的界面。
2、连接CH582的BLE设备,读取serviceId、characteristicId。
3、连接成功并获取到notifyServiceId的可读为真,开启notify的数据监听。
4、notify收到数据后,判断数据,来更改微信小程上的图标,显示灯的状态。
【主要函数】
CH582:工程是在“\CH583EVT\EVT\EXAM\BLE\Peripheral”这个DEMO上面修改而来:
1、simpleProfileChangeCB 这个是接收的回调函数,接收微信小程序数据,判断后对LED进行电平的转换。
static void simpleProfileChangeCB(uint8_t paramID, uint8_t *pValue, uint16_t len)
{
switch(paramID)
{
case SIMPLEPROFILE_CHAR1:
{
uint8_t newValue[SIMPLEPROFILE_CHAR1_LEN];
tmos_memcpy(newValue, pValue, len);
PRINT("profile ChangeCB CHAR1.. %s\n",newValue);
//这里用于判断接收到的数据是否为1,因为上位机是发的字符为1.
if(pValue[0] == 48)
{
GPIOB_SetBits(GPIO_Pin_19);
}
else {
GPIOB_ResetBits(GPIO_Pin_19);
}
break;
}
case SIMPLEPROFILE_CHAR3:
{
uint8_t newValue[SIMPLEPROFILE_CHAR3_LEN];
tmos_memcpy(newValue, pValue, len);
PRINT("profile ChangeCB CHAR3..\n");
break;
}
default:
// should not reach here!
break;
}
}
2、performPeriodicTask 这个函数主要是定时的读取LED灯的电平 ,然后发送给微信小程序,用于反馈给APP显示灯的状态。
static void performPeriodicTask(void)
{
uint8_t notiData[SIMPLEPROFILE_CHAR4_LEN] = {0x88,0x01};
//PRINT("LED STATUS..%x\n", GPIOB_ReadPortPin(GPIO_Pin_19)); ////GPIOB_ReadPortPin的返回值并不是bool值,而是对应的port&pin的值
if (GPIOB_ReadPortPin(GPIO_Pin_19) != 0) {
notiData[1] = 0x00;
}else {
notiData[1] = 0x01;
}
peripheralChar4Notify(notiData, SIMPLEPROFILE_CHAR4_LEN);
}
3、初始化LED 的GPIO,我这里用的是GPIOB19:GPIOB_ModeCfg(GPIO_Pin_19, GPIO_ModeOut_PP_5mA);
编译好后下载给CH582就OK了。
微信小程:
1、新建一个js模板的微信小程:
在pages图标上右键新建一个image文件夹,用于存放关、开灯的图片。
首先去网上下载两张灯的图片,一个是亮灯的、一个是灭灯的。他这两张图片放到image文件夹下。
修改app.js:
//app.js
App({
onLaunch: function () {
this.globalData.sysinfo = wx.getSystemInfoSync()
},
getModel: function () { //获取手机型号
return this.globalData.sysinfo["model"]
},
getVersion: function () { //获取微信版本号
return this.globalData.sysinfo["version"]
},
getSystem: function () { //获取操作系统版本
return this.globalData.sysinfo["system"]
},
getPlatform: function () { //获取客户端平台
return this.globalData.sysinfo["platform"]
},
getSDKVersion: function () { //获取客户端基础库版本
return this.globalData.sysinfo["SDKVersion"]
},
globalData: {
userInfo: null,
platform:"",
screenWidth:wx.getSystemInfoSync().screenWidth,
screenHeight:wx.getSystemInfoSync().screenHeight,
},
BLEInformation:{
platform: "",
deviceId:"",
writeCharaterId: "",
writeServiceId: "",
notifyCharaterId: "",
notifyServiceId: "",
readCharaterId: "",
readServiceId: "",
}
})
然后修改index.wxml
<button class='button' hover-class="hover" bindtap="startSearch" loading='{{isScanning}}'> 搜索蓝牙设备 </button>
<scroll-view class="device_list" scroll-y scroll-with-animation >
<view wx:for="{{list}}" wx:for-item="item"
data-title="{{item.deviceId}}"
data-name="{{item.name}}"
data-advertisData="{{item.advertisServiceUUIDs}}"
wx:key="{{item.deviceId}}"
bindtap="bindViewTap"
class="item" hover-class="item_hover">
<view style="font-size: 16px; color: #333;">{{item.name}}</view>
<view style="font-size: 16px; color: #333;" >{{item.deviceId}}</view>
<view style="font-size: 10px">信号强度: {{item.RSSI}}dBm ({{utils.max(0, item.RSSI + 100)}}%)</view>
</view>
</scroll-view>
<image src="{{imageUrl}}" mode="aspectFit">
</image>
<button class='button' bindtap="offLED" > 关灯 </button>
<button class='button' bindtap="onLED" > 开灯 </button>
修改index.wxss
.button {
margin-top: 20px;
width: 90%;
background-color: #54bec2;
color: white;
border-radius: 98rpx;
background: bg_red;
}
/* 按下变颜色 */
.hover {
background: #DCDCDC;
}
.device_list {
height: auto;
margin-left: 20px;
margin-right: 20px;
margin-top: 10px;
margin-bottom: 20px;
border: 1px solid #EEE;
border-radius: 5px;
width: auto;
}
.td {
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
}
/* .item {
padding-top: 10px;
padding-bottom: 10px;
height: 130rpx;
width: 100%;
} */
.item{
display: block;
/* font-family: Arial, Helvetica, sans-serif;
font-size:14px;
margin: 0 10px;
margin-top:10px;
margin-bottom: 10px;
background-color:#FFA850;
border-radius: 5px;
border-bottom: 2px solid #68BAEA; */
border-bottom: 1px solid #EEE;
padding: 4px;
color: #666;
}
.item_hover {
background-color: rgba(0, 0, 0, .1);
}
.block{
display: block;
color:#ffffff;
padding: 5px;
}/* pages/bleConnect/bleConnect.wxss */
修改index.js:
// pages/blueconn/blueconn.js
var app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
list: [],
services: [],
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false,
isScanning:false,
imageUrl:"../image/0.jpg"
},
//搜索设备
startSearch: function () {
var that = this
wx.openBluetoothAdapter({
success: function (res) {
wx.getBluetoothAdapterState({
success: function (res) {
console.log('openBluetoothAdapter success', res)
if (res.available) {
if (res.discovering) {
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log(res)
}
})
}else{
// that.startBluetoothDevicesDiscovery()
that.getBluetoothDevices()
}
// that.checkPemission()
} else {
wx.showModal({
title: '提示',
content: '本机蓝牙不可用',
showCancel: false
})
}
},
})
}, fail: function () {
// if (res.errCode === 10001) {
// wx.onBluetoothAdapterStateChange(function (res) {
// console.log('onBluetoothAdapterStateChange', res)
// if (res.available) {
// this.startBluetoothDevicesDiscovery()
// }
// })
// }
wx.showModal({
title: '提示',
content: '蓝牙初始化失败,请到设置打开蓝牙',
showCancel: false
})
}
})
},
checkPemission: function () { //android 6.0以上需授权地理位置权限
var that = this
var platform = app.BLEInformation.platform
if (platform == "ios") {
app.globalData.platform = "ios"
that.getBluetoothDevices()
} else if (platform == "android") {
app.globalData.platform = "android"
console.log(app.getSystem().substring(app.getSystem().length - (app.getSystem().length - 8), app.getSystem().length - (app.getSystem().length - 8) + 1))
if (app.getSystem().substring(app.getSystem().length - (app.getSystem().length - 8), app.getSystem().length - (app.getSystem().length - 8) + 1) > 5) {
wx.getSetting({
success: function (res) {
console.log(res)
if (!res.authSetting['scope.userLocation']) {
wx.authorize({
scope: 'scope.userLocation',
complete: function (res) {
that.getBluetoothDevices()
}
})
} else {
that.getBluetoothDevices()
}
}
})
}
}
},
getBluetoothDevices: function () { //获取蓝牙设备信息
var that = this
console.log("start search")
wx.showLoading({
title: '正在加载',
icon: 'loading',
})
that.setData({
isScanning:true
})
wx.startBluetoothDevicesDiscovery({
success: function (res) {
console.log(res)
setTimeout(function () {
wx.getBluetoothDevices({
success: function (res) {
var devices = []
var num = 0
for (var i = 0; i < res.devices.length; ++i) {
if (res.devices[i].name != "未知设备") {
devices[num] = res.devices[i]
num++
}
}
that.setData({
list: devices,
isScanning:false
})
wx.hideLoading()
wx.stopPullDownRefresh()
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log("停止搜索蓝牙")
}
})
},
})
}, 5000)
},
})
},
bindViewTap: function (e) {
var that = this
wx.stopBluetoothDevicesDiscovery({
success: function (res) { console.log(res) },
})
that.setData({
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false
})
console.log(e.currentTarget.dataset.title)
wx.showLoading({
title: '正在连接',
})
wx.createBLEConnection({
deviceId: e.currentTarget.dataset.title,
success: function (res) {
console.log(res)
app.BLEInformation.deviceId = e.currentTarget.dataset.title
that.getSeviceId()
}, fail: function (e) {
wx.showModal({
title: '提示',
content: '连接失败',
showCancel: false
})
console.log(e)
wx.hideLoading()
}, complete: function (e) {
console.log(e)
}
})
},
getSeviceId: function () {
var that = this
var platform = app.BLEInformation.platform
console.log(app.BLEInformation.deviceId)
wx.getBLEDeviceServices({
deviceId: app.BLEInformation.deviceId,
success: function (res) {
console.log(res)
// var realId = ''
// if (platform == 'android') {
// // for(var i=0;i<res.services.length;++i){
// // var item = res.services[i].uuid
// // if (item == "0000FEE7-0000-1000-8000-00805F9B34FB"){
// realId = "0000FEE7-0000-1000-8000-00805F9B34FB"
// // break;
// // }
// // }
// } else if (platform == 'ios') {
// // for(var i=0;i<res.services.length;++i){
// // var item = res.services[i].uuid
// // if (item == "49535343-FE7D-4AE5-8FA9-9FAFD205E455"){
// realId = "49535343-FE7D-4AE5-8FA9-9FAFD205E455"
// // break
// // }
// // }
// }
// app.BLEInformation.serviceId = realId
that.setData({
services: res.services
})
that.getCharacteristics()
}, fail: function (e) {
console.log(e)
}, complete: function (e) {
console.log(e)
}
})
},
getCharacteristics: function () {
var that = this
var list = that.data.services
var num = that.data.serviceId
var write = that.data.writeCharacter
var read = that.data.readCharacter
var notify = that.data.notifyCharacter
wx.getBLEDeviceCharacteristics({
deviceId: app.BLEInformation.deviceId,
serviceId: list[num].uuid,
success: function (res) {
console.log(res)
for (var i = 0; i < res.characteristics.length; ++i) {
var properties = res.characteristics[i].properties
var item = res.characteristics[i].uuid
if (!notify) {
if (properties.notify) {
app.BLEInformation.notifyCharaterId = item
app.BLEInformation.notifyServiceId = list[num].uuid
notify = true
}
}
if (!write) {
if (properties.write) {
app.BLEInformation.writeCharaterId = item
app.BLEInformation.writeServiceId = list[num].uuid
write = true
}
}
if (!read) {
if (properties.read) {
app.BLEInformation.readCharaterId = item
app.BLEInformation.readServiceId = list[num].uuid
read = true
}
}
}
if (!write || !notify || !read) {
num++
that.setData({
writeCharacter: write,
readCharacter: read,
notifyCharacter: notify,
serviceId: num
})
if (num == list.length) {
wx.showModal({
title: '提示',
content: '找不到该读写的特征值',
showCancel: false
})
} else {
that.getCharacteristics()
}
} else {
wx.showToast({
title: '连接成功',
})
that.openControl()
}
}, fail: function (e) {
console.log(e)
}, complete: function (e) {
console.log("write:" + app.BLEInformation.writeCharaterId)
console.log("read:" + app.BLEInformation.readCharaterId)
console.log("notify:" + app.BLEInformation.notifyCharaterId)
}
})
},
openControl: function () {//连接成功返回主页
// wx.navigateTo({
// url: '../home/home',
// })
var that = this
wx.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId:app.BLEInformation.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId:"0000FFE0-0000-1000-8000-00805F9B34FB",
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId:"0000FFE4-0000-1000-8000-00805F9B34FB",
success (res) {
console.log('notifyBLECharacteristicValueChange success', res.errMsg)
}
})
// ArrayBuffer转16进制字符串示例
function ab2hex(buffer) {
let hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
}
wx.onBLECharacteristicValueChange(function(res) {
console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
console.log(ab2hex(res.value))
if(ab2hex(res.value) == 8801){
console.log("开灯")
that.setData({
imageUrl: "../image/1.jpg"
})
}
else
{
console.log("关灯")
that.setData({
imageUrl: "../image/0.jpg"
})
}
})
},
offLED: function (e) {
console.log("发送关灯程序")
var senddata = "0";
var that = this
let buffer = new ArrayBuffer(senddata.length)
let dataView = new DataView(buffer)
for (var i = 0; i < senddata.length; i++) {
dataView.setUint8(i, senddata.charAt(i).charCodeAt())
}
wx.writeBLECharacteristicValue({
deviceId: app.BLEInformation.deviceId,
serviceId: "0000FFE0-0000-1000-8000-00805F9B34FB",
characteristicId: "0000FFE1-0000-1000-8000-00805F9B34FB",
value: buffer,
success: function (res) {
wx.showToast({
title: '发送成功',
icon: 'success',
duration: 2000
})
}
})
},
onLED: function (e) {
console.log("发送开灯灯程序")
console.log("发送关灯程序")
var senddata = "1";
var that = this
let buffer = new ArrayBuffer(senddata.length)
let dataView = new DataView(buffer)
for (var i = 0; i < senddata.length; i++) {
dataView.setUint8(i, senddata.charAt(i).charCodeAt())
}
wx.writeBLECharacteristicValue({
deviceId: app.BLEInformation.deviceId,
serviceId: "0000FFE0-0000-1000-8000-00805F9B34FB",
characteristicId: "0000FFE1-0000-1000-8000-00805F9B34FB",
value: buffer,
success: function (res) {
wx.showToast({
title: '发送成功',
icon: 'success',
duration: 2000
})
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
app.BLEInformation.platform = app.getPlatform()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
// /**
// * 页面相关事件处理函数--监听用户下拉动作
// */
// onPullDownRefresh: function () {
// // var that = this
// // wx.startPullDownRefresh({})
// // that.startSearch()
// },
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
编译以后就是这样的:
然后进行真机调试:
手机扫码后弹出调试界面:
手机的调试界面:
然后点搜索蓝牙设备:
搜索到CH582以后就会出现
到这里就成功了。
微信小程序具体的实现大家去看看官方文档就行,如果大家遇到什么问题,可以给私信我,大家互相学习讨论。
【讨论】
这里还只是实现了基本的数据收发功能,相对于前一编用E4A来实现点灯,这次有了反馈的,显得更加合理。当然程序还有很多的地方要完善修改,这里我反馈标志是500ms,手机APP有点延时。微信小程序的UID我这里都是写死的,后面还要考虑适配的东西。
相比第一次的点灯,这次的程序改写思路清晰多了,这里要感谢@manhuami2007。我从他的评测报告中学到了notify的定时上报数据。他的贴子写得非常好,大家有时间可以去看看他的两篇贴子,对于BLE的数据交换很有益:【沁恒RISC-V内核 CH582】 4-手机对 CH582 的数据进行读操作和写操作 https://bbs.eeworld.com.cn/thread-1195658-1-1.html、【沁恒RISC-V内核 CH582】 7- 使用CH582蓝牙的notify主动上传数据 https://bbs.eeworld.com.cn/thread-1196861-1-1.html。
这几天公司的项目忙得头昏眼花,评测的报告也出得比较慢。静下来想想,其实做评测项目很是花时间,因为我是第一次接触沁恒的芯片,蓝牙也是第一次,很是有些吃力,但是通过对这个板子的学习,我接触到了蓝牙,并且刚好用在公司的接入蓝牙打印机的项目上,并且正试上线了。可以说是有很大的收获。
这里要感谢EEWORLD给机会,在这个网站学习到了很多东西,结识了很多优秀的朋友。
【下一步】
根据我的评测进度,下一步用IO控制继电器,来控制取暖器的开关。
|