698 views|5 replies

13

Posts

0

Resources
The OP
 

[NUCLEO-WB09KE Review] 5. WeChat applet BLE adjusts LD3 brightness [Copy link]

Target

Develop a WeChat applet to establish a Bluetooth host to access the WB09KE Bluetooth slave, and send adjustment parameters PWM to adjust the brightness of LD3 (PB2)

1. WB09KE terminal

1. Regarding PWM to adjust LED brightness, please refer to: https://en.eeworld.com/bbs/thread-1294722-1-1.html

2.

Only one GATT service and characteristic value are created, and the characteristic value can be written, 1 BYTE

3. BLE adjusts LD3 brightness

After receiving LED_SERVICE_LED_TOGGLE_WRITE_EVT, get the write characteristic value through *p_Notification->DataTransfered.p_Payload, and give this value to PWM to adjust the duty cycle.

    case LED_SERVICE_LED_TOGGLE_WRITE_EVT:
      /* USER CODE BEGIN Service1Char1_WRITE_EVT */
		TIM_SetTIM2Compare3(*p_Notification->DataTransfered.p_Payload);
		APP_DBG_MSG("LED_SERVICE_LED_TOGGLE_WRITE_EVT\r\n");
      /* USER CODE END Service1Char1_WRITE_EVT */
      break;
//设置 TIM 通道 3 的占空比
//compare:比较值
void TIM_SetTIM2Compare3(uint32_t compare)
{
	//TIM2->CCR3=compare;
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, compare); // compare为新的占空比值

}

2. WeChat Mini Program

1. Create a custom component for BLE functions

index.js
The main idea is 1. Scan Bluetooth; 2. Connect to the self-built Bluetooth slave. After the connection is successful, all connection parameters can be directly used in the next step; 3. Send a number of 0-255 through writeBLECharacteristicValue1().
// components/bluetooth-comp/index.js

function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}

// 将字符串转为 ArrayBuffer
function str2ab(str) {
  let buf = new ArrayBuffer(str.length);
  let bufView = new Uint8Array(buf);
  for (var i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}


function intToArrayBuffer(int) {
  // 将整数转换为十六进制字符串
  let hexStr = int.toString(16);
  
  // 计算需要的字节数,如果十六进制字符串长度为奇数,需要补0以确保字节对齐
  let byteLength = (hexStr.length + (hexStr.length % 2 === 0 ? 0 : 2)) / 2;
  
  // 创建一个与计算出的字节长度相同的新的ArrayBuffer对象
  let buffer = new ArrayBuffer(byteLength);
  let dataView = new DataView(buffer);
  
  // 将十六进制字符串中的每个字节转换为无符号8位整数,并写入到ArrayBuffer中
  for (let i = 0; i < hexStr.length; i += 2) {
    let byte = parseInt(hexStr.substr(i, 2), 16); // 将每两个字符转换为一个字节的整数
    dataView.setUint8(i / 2, byte); // 将整数写入ArrayBuffer的适当位置(注意这里假设了整数是按大端序排列的)
  }
  
  return buffer; // 返回生成的ArrayBuffer对象
}


Component({

  behaviors: ['wx://component-export'],

  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  // bluetooth-comp/index.js
  data:{
    devices: [],
    connected: false,
    chs: []
  },

  /**
   * 组件的方法列表
   */
// bluetooth-comp/index.js
methods: {
  /* 初始化蓝牙模块 */
  openBluetoothAdapter() {
    // 先关闭蓝牙模块再开启 防止断开后点连接连接不上
    this.closeBluetoothAdapter();

    wx.openBluetoothAdapter({
      success: response => {
        console.log("初始化蓝牙模块成功:openBluetoothAdapter", response);
        this.startBluetoothDevicesDiscovery();
      },
      fail: err => {
        if (err.errCode === 10001) {
          /* 监听蓝牙适配器状态变化事件 */
          wx.onBluetoothAdapterStateChange(res => {
            console.log("监听蓝牙适配器状态变化事件:onBluetoothAdapterStateChange", res);
            res.available && this.startBluetoothDevicesDiscovery();
          });
        }
      },
    });
  },
  /* 获取本机蓝牙适配器状态 */
  getBluetoothAdapterState() {
    wx.getBluetoothAdapterState({
      success: res => {
        console.log("getBluetoothAdapterState", res);
        if (res.discovering) {
          // 是否正在搜索设备
          this.onBluetoothDeviceFound();
        } else if (res.available) {
          // 蓝牙适配器是否可用
          this.startBluetoothDevicesDiscovery();
        }
      },
    });
  },
  /* 开始搜寻附近的蓝牙外围设备 */
  startBluetoothDevicesDiscovery() {
    // 开始扫描参数
    if (this._discoveryStarted) return;

    this._discoveryStarted = true;
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: true,
      success: response => {
        console.log("开始搜寻附近的蓝牙外围设备:startBluetoothDevicesDiscovery", response);
        this.onBluetoothDeviceFound();
      },
      fail: err => {
        console.log("搜索设备失败", err);
        wx.showToast({ title: "搜索设备失败", icon: "none" });
      },
    });
  },
  /* 停止搜寻附近的蓝牙外围设备。*/
  stopBluetoothDevicesDiscovery() {
    console.log("停止搜寻附近的蓝牙外围设备");
    wx.stopBluetoothDevicesDiscovery();
  },
  /* 监听搜索到新设备的事件 */
  onBluetoothDeviceFound() {
    wx.onBluetoothDeviceFound(res => {
      res.devices.forEach(device => {
        if (!device.name && !device.localName) {
          return;
        }

        const foundDevices = this.data.devices;
        const idx = inArray(foundDevices, "deviceId", device.deviceId);
        const data = {};
        if (idx === -1) {
          data[`devices[${foundDevices.length}]`] = device;
        } else {
          data[`devices[${idx}]`] = device;
        }
        this.setData(data);
      });
    });
  },
  /* 连接蓝牙低功耗设备。*/
  createBLEConnection(e) {
    const ds = e.currentTarget.dataset;
    const deviceId = ds.deviceId;
    const name = ds.name;
    wx.createBLEConnection({
      deviceId,
      success: () => {
        this.setData({ connected: true, name, deviceId });
        wx.showToast({ title: "连接蓝牙设备成功", icon: "none" });
        this.getBLEDeviceServices(deviceId);
      },
      fail: e => {
        console.log("连接失败", e.errMsg);
        wx.showToast({ title: "连接失败,错误信息: " + e.errMsg, icon: "none" });
      },
    });
    // 停止搜寻蓝牙设备
    this.stopBluetoothDevicesDiscovery();
  },
  /* 断开与蓝牙低功耗设备的连接。 */
  closeBLEConnection() {
    console.log("断开与蓝牙低功耗设备的连接");
    wx.showToast({ title: "已断开和蓝牙设备的连接", icon: "none" });
    wx.closeBLEConnection({ deviceId: this.data.deviceId });
    this.setData({ connected: false, chs: [], canWrite: false });
  },
  /* 获取蓝牙低功耗设备所有服务 (service) */
  getBLEDeviceServices(deviceId) {
    wx.getBLEDeviceServices({
      deviceId,
      success: res => {
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary) {
            this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);
            return;
          }
        }
      },
    });
  },
  /* 获取蓝牙低功耗设备某个服务中所有特征 (characteristic)。 */
  getBLEDeviceCharacteristics(deviceId, serviceId) {
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: res => {
        console.log("获取蓝牙低功耗设备某个服务中所有特征:getBLEDeviceCharacteristics");

        for (let i = 0; i < res.characteristics.length; i++) {
          let item = res.characteristics[i];
          if (item.properties.read) {
            wx.readBLECharacteristicValue({ deviceId, serviceId, characteristicId: item.uuid });
          }
          if (item.properties.write) {
            this.setData({ canWrite: true });
            this._deviceId = deviceId;
            this._serviceId = serviceId;
            this._characteristicId = item.uuid;
            //   this.writeBLECharacteristicValue();
          }
          if (item.properties.notify || item.properties.indicate) {
            wx.notifyBLECharacteristicValueChange({
              deviceId,
              serviceId,
              characteristicId: item.uuid,
              state: true,
              success(res) {
                console.log("notifyBLECharacteristicValueChange success", res);
              },
            });
          }
        }
      },
      fail(res) {
        console.error("getBLEDeviceCharacteristics", res);
      },
    });

    // 操作之前先监听,保证第一时间获取数据
    wx.onBLECharacteristicValueChange(characteristic => {
      // TODO 收到的信息为ArrayBuffer类型,可根据自己的需要转换 可发送给父组件用来回显
      console.log("收到原始的数据", characteristic, characteristic.value);
      // 测试向设备发送数据
      // this.writeBLECharacteristicValue(JSON.stringify({"FAN":"OFF"}))
    });
  },
  /* 向蓝牙低功耗设备特征值中写入二进制数据 */
  writeBLECharacteristicValue(jsonStr) {
    let arrayBufferValue = str2ab(jsonStr);
    console.log("发送数据给蓝牙", "原始字符串", jsonStr, "转换arrayBuffer", arrayBufferValue);

    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId, // 微信文档上是错误的
      characteristicId: this._characteristicId,
      value: arrayBufferValue, // 只能发送arrayBuffer类型数据
      success(res) {
        console.log("消息发送成功", res.errMsg);
        wx.showToast({ title: "消息发送成功", icon: "none" });
      },
      fail(e) {i
        console.log("发送消息失败", e);i
        wx.showToast({ title: "发送消息失败,错误信息: " + e.errMsg, icon: "none" });
      },
    });
  },

    /* 向蓝牙低功耗设备特征值中写入十进制数据 */
    writeBLECharacteristicValue1(i) {
      let arrayBufferValue = intToArrayBuffer(i);
      console.log("发送数据给蓝牙", "原始字符串", i, "转换arrayBuffer", arrayBufferValue);
  
      wx.writeBLECharacteristicValue({
        deviceId: this._deviceId,
        serviceId: this._serviceId, // 微信文档上是错误的
        characteristicId: this._characteristicId,
        value: arrayBufferValue, // 只能发送arrayBuffer类型数据
        success(res) {
          console.log("消息发送成功", res.errMsg);
          wx.showToast({ title: "消息发送成功", icon: "none" });
        },
        fail(e) {
          console.log("发送消息失败", e);
          wx.showToast({ title: "发送消息失败,错误信息: " + e.errMsg, icon: "none" });
        },
      });
    },

  closeBluetoothAdapter() {
    console.log("关闭蓝牙模块");
    wx.closeBluetoothAdapter();
    this._discoveryStarted = false;
  },
}
})

index.json:

{
  "component": true,
  "usingComponents": {}

}

index.wxml

createBLEConnection<!-- bluetooth-comp/index.wxml -->
<view style="margin: 26rpx">
  <button wx:if="{{!connected}}" bindtap="openBluetoothAdapter">开始扫描</button>
  <button wx:else bindtap="closeBLEConnection">断开连接 - {{name}}</button>

  <view class="devices_summary">已发现 {{devices.length}} 个外围设备:</view>
  <view
    wx:for="{{devices}}"
    wx:key="index"
    data-device-id="{{item.deviceId}}"
    data-name="{{item.name || item.localName}}"
    bindtap="createBLEConnection"
    class="device_item"
    hover-class="device_item_hover">
    <view style="font-size: 16px; color: #333">{{item.name}}</view>
    <view style="font-size: 10px">信号强度: {{item.RSSI}}dBm</view>
    <view style="font-size: 10px">UUID: {{item.deviceId}}</view>
    <view style="font-size: 10px">localName: {{item.localName}}</view>
  </view>
</view>

index.wxss:

/* bluetooth-comp/index.wxss */
.devices_summary {
  /* margin-top: 30px; */
  padding: 10px;
  font-size: 16px;
}

.device_item {
  border-bottom: 1px solid #eee;
  padding: 10px;
  color: #666;
}
.device_item_hover {
  background-color: rgba(0, 0, 0, 0.1);
}

2. Main program

Introduce components in *.json

{
  "usingComponents": {

    "bluetoothcomp":"/components/bluetooth-comp/index"
  }
}

*.wxml appearance

<!--pages/wifi.wxml-->
<!--
<view style="position: inherit; width: 100%; background: #d3d3d3; height: auto; left: 0rpx; top: inherit">
  <icon type="success" size="40" style="position: relative; left: 31rpx; top: 6rpx"></icon>
  <text style="position: relative; left: 85rpx; top: -14rpx">蓝牙</text>
  <switch style="position: relative; left: 449rpx; top: -19rpx" checked="{{isBlueTooth}}" bindchange="openDialogBluetooth" />
  </view>
-->
<!--bind:close="onCloseBlueTooth"-->
<view>
<bluetoothcomp id="bluetoothid"></bluetoothcomp>
</view>

<view>
<slider bindchange="slider1change" min="0" max="255" show-value="true" left-icon="cancel" right-icon="success_no_circle"/>

<text style="position: relative; left: 303rpx; top: 20rpx" >{{slidervalue}}</text>
</view>
<image style="position: relative; left: 47rpx; top: 354rpx" src="/images/wb09.jpg"/>


*.js control part

// pages/wifi.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    isBlueTooth:false,
    bluetoothDialog:false,
    slidervalue:0,
    

  },


  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    this.bluetoothcomp = this.selectComponent("#bluetoothid");
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  },

  bluetoothChange(){


  },

  openDialogBluetooth(){
    this.setData({bluetoothDialog:true});
  },
  onCloseBlueTooth(){
    this.setData({bluetoothDialog:false});
  },

  slider1change: function(e) {
    // e.detail.value 包含了当前slider的value值
    this.setData({slidervalue:e.detail.value});

    console.log('Slider value changed to:', this.data.slidervalue);
    // 在这里你可以对获取到的value值进行进一步的处理或更新数据模型中的值
    this.bluetoothcomp.writeBLECharacteristicValue1(this.data.slidervalue);
  },

})

3. Effect

1. Mini Program Appearance

2. Run the demo

VID_20240927_142533

This post is from RF/Wirelessly

Latest reply

Can you share your source code, please?  Details Published on 2024-11-2 21:57
 

5998

Posts

6

Resources
2
 

Can WeChat Mini Programs connect directly via Bluetooth? Isn't it through WiFi?

This post is from RF/Wirelessly
Personal signature

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 

8

Posts

0

Resources
3
 
Qintianqintian0303 posted on 2024-9-28 13:44 Can WeChat applet connect directly via Bluetooth? Isn't it through WiFi?

It seems to be possible. One of my customers connected to the Bluetooth terminal in this way.

This post is from RF/Wirelessly
 
 
 

118

Posts

1

Resources
4
 

Niu's brother, mini program 666

This post is from RF/Wirelessly
 
 
 

6818

Posts

11

Resources
5
 
Can you share your source code, please?
This post is from RF/Wirelessly
 
 
 

13

Posts

0

Resources
6
 
This post is from RF/Wirelessly
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

快速回复 返回顶部 Return list