一、前言
宿舍关灯神器应该是一个已经被玩烂了的项目了,我也废话不多说。本篇文章就如标题所说,教大家如何开发一个鸿蒙NEXT版的APP来对单片机举行蓝牙通信。本文的关灯器将采用ESP32作为控制器。
二、材料准备
设备组装
舵机上赤色的线是接vin(也就是esp32上的5v引脚,不同的板子叫法不同),黑色的接GND,另外一个是信号线,任意接一个GPIO引脚即可,我这里接的是12,这个要记着反面要用。
三、单片机代码
- #include <BluetoothSerial.h>
- #include <string>
- #include <ESP32Servo.h>
- using namespace std;
-
- BluetoothSerial SerialBT;
- Servo myservo;
- int servoPin = 12;
- int ini_pos = 90;
- bool is_on = false;
- void turn_mid_light()
- {
- myservo.write(90);
- }
- void turn_light()
- {
- myservo.write(90 + 45);
- delay(500);
- turn_mid_light();
- }
- void turn_off_light()
- {
- myservo.write(90 - 45);
- delay(500);
- turn_mid_light();
- }
-
- void setup() {
- myservo.attach(servoPin);
- Serial.begin(115200);
- SerialBT.begin("ESP32_Server"); // 设定蓝牙服务器名称
- int init_angle = myservo.read(); // 读取初始角度
- if (init_angle != ini_pos)
- {
- myservo.write(ini_pos);
- };
- }
-
- void loop() {
- if(SerialBT.available()){
- String cmd = SerialBT.readString();
- Serial.print(cmd);
- if(cmd == "switch"){
- if(is_on){
- turn_off_light();
- is_on = false;
- }else{
- turn_light();
- is_on = true;
- }
- }
- }
- }
复制代码 下面我来解释一下这段代码:
起首引入了三个头文件<BluetoothSerial.h>(蓝牙库)、和<ESP32Servo.h>(控制舵机的库)。定义了蓝牙串口对象SerialBT和舵机对象myservo,以及servoPin(舵机引脚,就是组装时信号线接的位置)、ini_pos(初始位置角度)、is_on(表现灯是否开启的标志)。
接着定义了三个函数turn_mid_light(将舵机转到中心位置,避免影响人手正常开关灯)、turn_light(将舵机转到特定角度开启灯光,然后再转到中心位置)、turn_off_light(将舵机转到特定角度关闭灯光,然后再转到中心位置)。
在setup函数中,将舵机毗连到指定引脚,初始化串口通信,设置蓝牙服务器名称,读取舵机初始角度,假如初始角度不是设定的初始位置角度,则将舵机转到初始位置。
在loop函数中,假如蓝牙串口有数据可读,就读取数据并存储在cmd字符串中。假如cmd等于 “switch”,根据is_on的状态来决定是开启灯光还是关闭灯光。
四、鸿蒙APP代码
1.蓝牙接口
我先不直接放代码,这里要先着重说一下鸿蒙蓝牙开发的方式,由于授之以鱼不如授之以渔,我解释了这一点以后,你在开发其他蓝牙应用的时间你就知道该怎么做了。
由于鸿蒙版本迭代快,api之间差别也不小,你在网上任意搜的教程指不定是哪个api的,而且写教程的人也没说,这就会造成许多误解。以是我会告诉大家我用的api版本,起首Dev eco studio版本是5.0.9.300,compatibleSdkVersion是 5.0.0(12)。
(由于这个项目是24年写的,如今整理的时间发现当前最新的api版本是16,但是主要的用法没有什么大变化。)
在华为官方文档中搜刮的时间注意要选上你如今用的api版本
假如直接搜刮蓝牙,会找到一些过时的文档,请注意看上边标注了从某某api后不再支持,假如用错了版本就会影响反面的开发。
经过我的查找,我发现了这个接口@ohos.bluetooth.connection (蓝牙connection模块),这个就是标准蓝牙通信的接口,当然你在左侧的栏目中也会发现有蓝牙ble模块,这个对应的是低功耗蓝牙,不过我这个项目用的是经典蓝牙,假如想试试ble肯定也可以,只不过固件代码也得相应的更改,有爱好的读者可以研究一下。
2.部分代码
先引入一些须要的库,此中connection和socket是蓝牙毗连和通信须要的组件。
- import { router } from '@kit.ArkUI';
- import { connection } from '@kit.ConnectivityKit';
- import { socket } from '@kit.ConnectivityKit';
- import { BusinessError } from '@kit.BasicServicesKit';
- import { buffer } from '@kit.ArkTS';
- import { promptAction } from '@kit.ArkUI';
复制代码 下面来讲几个紧张的函数:
- connection.getPairedDevices()
这个是用于获取已配对设备的mac地点,返回是Array
- connection.getRemoteDeviceName()
当我们拿到了mac地点后,我们想知道设备名称就要用这个函数,这个函数对于已配对设备和未配对都是一样的,只要传入地点就能返回设备名称。在api16中好像又新加进去了一个参数alias,不过是可选,我们不消管这个。
- connection.on(‘bluetoothDeviceFind’, Callback<Array>)
这里可以看到有几个不同的on函数,此中第一个参数传入不同的字符串表现订阅不同的消息,这里我们当然要订阅发现设备的消息,也就是开启蓝牙扫描后只要发现了设备,就执行回调函数。
- connection.startBluetoothDiscovery();
这个就不消多说了,就是开启扫描。
- socket.sppConnect(deviceId: string, options: SppOptions, callback: AsyncCallback): void
毗连指定地点的设备
- socket.sppWrite(clientSocket: number, data: ArrayBuffer): void
发送字节数据
以是有了上面的代码,我们就可以分别写出以下功能:
检查已配对设备有无关灯器
- getDevice = (): boolean=>{
- try{
- let devices: Array<string> = connection.getPairedDevices()
- for(let i=0; i<devices.length; i++){
- if(connection.getRemoteDeviceName(devices[i])=="ESP32_Server"){
- this.address = devices[i]
- return true
- }
- }
- } catch (err) {
- console.error("errCode:" + err.code + ",errMessage:" + err.message)
- }
- return false
- }
复制代码 这里的设备名称是你自己设定的,根据你的固件代码举行现实调整。
扫描并配对
- scanAndPair = ()=>{
- try {
- connection.on('bluetoothDeviceFind', (data)=>{
- for(let i=0;i<data.length;i++){
- let adrr = data[i]
- if(adrr!=""){
- let name = connection.getRemoteDeviceName(adrr)
- if(name == "ESP32_Server"){
- connection.pairDevice(adrr)
- }
- }
- }
- });
- connection.startBluetoothDiscovery();
- } catch (err) {
- console.error("errCode:" + err.code + ",errMessage:" + err.message);
- }
- }
复制代码 毗连设备
- connect = ()=>{
- try{
- socket.sppConnect(this.address, {uuid: '00001101-0000-1000-8000-00805f9b34fb', secure: false, type: 0},
- (code: BusinessError, number: number)=>{
- if (code) {
- console.error('sppListen error, code is ' + code)
- promptAction.showToast({message: '连接失败', duration: 2000})
- return;
- }
- this.client_num = number
- promptAction.showToast({message: '连接成功', duration: 2000})
- this.state = "在线"
- this.color = Color.Green
- // this.sendCmd()
- })
- } catch (err) {
- console.error("errCode:" + err.code + ",errMessage:" + err.message);
- promptAction.showToast({message: '连接失败', duration: 2000})
- }
- }
复制代码 发送消息
- sendCmd = ()=>{
- try{
- socket.sppWrite(this.client_num, this.strToBuffer("switch"))
- this.light_color==Color.Gray ? this.light_color = Color.Green : this.light_color = Color.Gray
- socket.sppCloseClientSocket(this.client_num)
- } catch (err) {
- console.error("errCode:" + err.code + ",errMessage:" + err.message);
- if(err.code == 2901054){
- promptAction.showToast({message: '连接已丢失请重试', duration: 2000})
- this.client_num = -1
- this.state = "离线"
- this.color = Color.Red
- }
- }
- }
复制代码 完整代码在此
https://github.com/1wpc/autolight_HMOS.git
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |