App Inventor 2 蓝牙遥控教程 - 经典蓝牙与BLE控制智能硬件

« 返回首页

一、蓝牙遥控概述

蓝牙(Bluetooth)是智能硬件遥控中最常用的无线通信方式之一。在 App Inventor 2 中,你可以通过内置的 BluetoothClient 组件(经典蓝牙)或 BluetoothLE 扩展(低功耗蓝牙 BLE)与各种硬件设备通信,实现遥控小车、LED 灯控、传感器数据采集等功能。

本教程涵盖:

  • 经典蓝牙 vs BLE 方案对比
  • 经典蓝牙连接与通信(适配 HC-05/HC-06、JDY-34 等模块)
  • BLE 连接与通信(适配 ESP32、Arduino BLE 等设备)
  • 发送控制命令与接收传感器数据
  • 实战案例:蓝牙遥控小车、LED 控制
  • Android 12+ 蓝牙权限处理

二、蓝牙方案对比:经典蓝牙 vs BLE

对比项 经典蓝牙(Classic Bluetooth) 低功耗蓝牙(BLE)
蓝牙版本 Bluetooth 2.0/3.0 Bluetooth 4.0+
App Inventor 组件 内置 BluetoothClient 需导入 BluetoothLE 扩展
典型模块 HC-05、HC-06、JDY-34(经典模式) HM-10、JDY-34(BLE模式)、ESP32
通信方式 串口模拟(SPP 协议) GATT 服务/特征值读写
功耗 较高(适合持续供电场景) 极低(适合电池供电设备)
传输速率 较高(1-3 Mbps) 较低(125Kbps-2Mbps)
连接复杂度 简单(配对后即用) 较复杂(需了解 Service/Characteristic)
适用场景 遥控小车、简单数据传输 传感器采集、穿戴设备、智能家居
Android 兼容性 广泛支持 Android 4.3+

选择建议:

  • 初学者 / 简单遥控场景 → 经典蓝牙(HC-05/HC-06,简单直接)
  • 低功耗 / 传感器采集 → BLE(ESP32,更省电)
  • 双模需求 → JDY-34 等双模模块(同时支持经典蓝牙和 BLE)

三、经典蓝牙连接与通信

3.1 组件准备

在 App Inventor 2 设计视图中:

  1. Connectivity(连接) 分类中拖入 BluetoothClient 组件
  2. User Interface(用户界面) 中拖入 ListPicker 组件(用于选择蓝牙设备)
  3. User Interface 中拖入 Button 组件(用于发送命令)

3.2 蓝牙设备选择与连接

ListPicker 填充已配对设备列表

当 ListPicker1.BeforePicking 执行:
  设置 ListPicker1.Elements 为 BluetoothClient1.AddressesAndNames

用户选择设备后建立连接

当 ListPicker1.AfterPicking 执行:
  如果 BluetoothClient1.Connect(ListPicker1.Selection) 成功:
    设置 Label_Status.Text 为 "已连接:" + ListPicker1.Selection
    设置 BluetoothClient1.Secure 为 true
  否则:
    设置 Label_Status.Text 为 "连接失败,请重试"

说明:

  • BluetoothClient1.AddressesAndNames 返回已配对设备的名称和地址列表
  • 使用前需先在 Android 系统蓝牙设置中完成配对
  • Secure = true 表示使用安全连接(推荐)

3.3 发送控制命令

经典蓝牙通过 SPP(Serial Port Profile)串口通信,数据以文本或字节流形式发送:

发送文本命令

当 Button_Forward.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.SendText(文本: "F\n")
当 Button_Stop.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.SendText(文本: "S\n")

发送字节数据(更精确)

当 Button_Left.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.SendBytes(字节数据: [0x4C, 0x0A])

说明:

  • 文本命令简单直观,适合初学者:用 "F" 表示前进,"B" 表示后退,"L" 表示左转,"R" 表示右转,"S" 表示停止
  • 字节命令更灵活,适合需要精确控制协议的场景
  • 建议每条命令后加换行符 \n,方便硬件端解析

3.4 接收数据

当 Clock1.Timer 执行(计时间隔:100ms):
  如果 BluetoothClient1.IsConnected 那么:
    如果 BluetoothClient1.BytesAvailable > 0 那么:
      设置 Label_Data.Text 为 BluetoothClient1.ReceiveText(字节数: -1)

说明:

  • 使用 Clock 组件定时轮询接收数据
  • ReceiveText(-1) 表示读取所有可用数据
  • 也可使用 ReceiveSignedBytes / ReceiveUnsignedBytes 接收二进制数据

3.5 断开连接

当 Button_Disconnect.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.Disconnect()
    设置 Label_Status.Text 为 "已断开连接"

四、BLE 连接与通信

4.1 安装 BLE 扩展

  1. 从 MIT IoT 站点下载 edu.mit.appinventor.ble.aix 扩展文件
  2. 在 App Inventor 设计视图中,点击左下角 Extension(扩展)Import extension → 上传 .aix 文件
  3. 导入后会出现 BluetoothLE 组件

4.2 BLE 核心概念

使用 BLE 通信需理解以下概念:

概念 说明
Service(服务) 设备提供的一组功能的集合,用 UUID 标识
Characteristic(特征值) 服务中的具体数据项,用 UUID 标识,可读/写/通知
Descriptor(描述符) 特征值的配置信息
UUID 128位唯一标识符,如 "0000ffe0-0000-1000-8000-00805f9b34fb"

4.3 扫描与连接 BLE 设备

当 Button_Scan.Click 执行:
  调用 BluetoothLE1.StartScanning()
  设置 Label_Status.Text 为 "正在扫描..."
当 BluetoothLE1.DeviceFound 执行:
  设置 Label_Device.Text 为 deviceName + " (" + deviceAddress + ")"
  调用 BluetoothLE1.StopScanning()
  调用 BluetoothLE1.Connect(deviceAddress)
当 BluetoothLE1.Connected 执行:
  设置 Label_Status.Text 为 "BLE 已连接"

4.4 通过 GATT 读写数据

写入控制命令

当 Button_LED_On.Click 执行:
  如果 BluetoothLE1.IsConnected 那么:
    调用 BluetoothLE1.WriteBytes(
      serviceUuid: "0000ffe0-0000-1000-8000-00805f9b34fb",
      characteristicUuid: "0000ffe1-0000-1000-8000-00805f9b34fb",
      写入值: [0x01]
    )
当 Button_LED_Off.Click 执行:
  如果 BluetoothLE1.IsConnected 那么:
    调用 BluetoothLE1.WriteBytes(
      serviceUuid: "0000ffe0-0000-1000-8000-00805f9b34fb",
      characteristicUuid: "0000ffe1-0000-1000-8000-00805f9b34fb",
      写入值: [0x00]
    )

接收通知数据(传感器)

当 BluetoothLE1.Connected 执行:
  调用 BluetoothLE1.RegisterForBytes(
    serviceUuid: "0000ffe0-0000-1000-8000-00805f9b34fb",
    characteristicUuid: "0000ffe1-0000-1000-8000-00805f9b34fb"
  )
当 BluetoothLE1.BytesReceived 执行:
  设置 Label_Sensor.Text 为 "传感器值:" + byteValues

注意事项:

  • WriteBytesWriteStrings 更可靠(WriteStrings 存在 23 字节硬编码限制)
  • UUID 需要与硬件端 GATT 服务的 UUID 一致
  • 常见 BLE 模块的默认 UUID:
    • HM-10:FFE0 / FFE1
    • ESP32(NimBLE 默认):6E400001-B5A3-F393-E0A9-E50E24DCCA9E

五、实战案例:蓝牙遥控小车

5.1 硬件准备

组件 说明
Arduino UNO / Nano 主控板
HC-05 / HC-06 蓝牙模块 经典蓝牙串口模块
L298N 电机驱动模块 驱动直流电机
直流电机 × 2 小车左右轮驱动
电池组 7.4V 锂电池或 4 节 AA 电池
小车底盘 带轮子的亚克力底盘

硬件连接:

HC-05 模块:
  VCC → Arduino 5V
  GND → Arduino GND
  TXD → Arduino RX (Pin 0)
  RXD → Arduino TX (Pin 1)(注意:需通过分压电路降至 3.3V)

L298N 电机驱动:
  IN1 → Arduino Pin 5
  IN2 → Arduino Pin 6
  IN3 → Arduino Pin 9
  IN4 → Arduino Pin 10
  ENA → Arduino Pin 3(PWM 调速)
  ENB → Arduino Pin 11(PWM 调速)

5.2 Arduino 端代码

// 蓝牙遥控小车 - Arduino 端代码
#include <SoftwareSerial.h>

SoftwareSerial bluetooth(0, 1); // RX, TX

// 电机引脚定义
int IN1 = 5, IN2 = 6, IN3 = 9, IN4 = 10;
int ENA = 3, ENB = 11;  // PWM 调速

int speed = 200;  // 默认速度 0-255

void setup() {
  Serial.begin(9600);
  bluetooth.begin(9600);
  
  pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT); pinMode(ENB, OUTPUT);
  
  stop();
}

void loop() {
  if (bluetooth.available()) {
    char cmd = bluetooth.read();
    
    switch(cmd) {
      case 'F': forward(); break;   // 前进
      case 'B': backward(); break;  // 后退
      case 'L': left(); break;      // 左转
      case 'R': right(); break;     // 右转
      case 'S': stop(); break;      // 停止
      case '1': speed = 150; break; // 低速
      case '2': speed = 200; break; // 中速
      case '3': speed = 255; break; // 高速
    }
  }
}

void forward() {
  analogWrite(ENA, speed); analogWrite(ENB, speed);
  digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW);
}

void backward() {
  analogWrite(ENA, speed); analogWrite(ENB, speed);
  digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH);
}

void left() {
  analogWrite(ENA, speed); analogWrite(ENB, speed);
  digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW);
}

void right() {
  analogWrite(ENA, speed); analogWrite(ENB, speed);
  digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH);
}

void stop() {
  analogWrite(ENA, 0); analogWrite(ENB, 0);
  digitalWrite(IN1, LOW); digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
}

5.3 App Inventor 积木块设计

UI 设计

布局结构:
├── HorizontalArrangement(状态栏)
│   ├── Label:"蓝牙状态:"
│   └── Label_Status:"未连接"
├── HorizontalArrangement(连接栏)
│   ├── ListPicker_Bluetooth:"选择蓝牙设备"
│   └── Button_Disconnect:"断开"
├── TableArrangement(方向控制 3×3)
│   ├── (空)        Button_Forward:"↑"    (空)
│   ├── Button_Left:"←"  Button_Stop:"■"  Button_Right:"→"
│   └── (空)        Button_Backward:"↓"   (空)
├── HorizontalArrangement(速度栏)
│   ├── Button_SpeedLow:"低速"
│   ├── Button_SpeedMid:"中速"
│   └── Button_SpeedHigh:"高速"
└── HorizontalArrangement(数据栏)
    ├── Label:"传感器数据:"
    └── Label_Data:"--"

核心积木块(伪代码)

1. 初始化与权限请求

当 Screen1.Initialize 执行:
  如果 Android 版本 >= 12 那么:
    请求运行时权限(BLUETOOTH_CONNECT, BLUETOOTH_SCAN)

2. 连接设备

当 ListPicker_Bluetooth.BeforePicking 执行:
  设置 ListPicker_Bluetooth.Elements 为 BluetoothClient1.AddressesAndNames

当 ListPicker_Bluetooth.AfterPicking 执行:
  如果 BluetoothClient1.Connect(ListPicker_Bluetooth.Selection) 那么:
    设置 Label_Status.Text 为 "已连接"
  否则:
    设置 Label_Status.Text 为 "连接失败"

3. 方向控制

当 Button_Forward.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.SendText(文本: "F")

当 Button_Backward.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.SendText(文本: "B")

当 Button_Left.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.SendText(文本: "L")

当 Button_Right.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.SendText(文本: "R")

当 Button_Stop.Click 执行:
  如果 BluetoothClient1.IsConnected 那么:
    调用 BluetoothClient1.SendText(文本: "S")

4. 速度控制

当 Button_SpeedLow.Click 执行:
  调用 BluetoothClient1.SendText(文本: "1")

当 Button_SpeedMid.Click 执行:
  调用 BluetoothClient1.SendText(文本: "2")

当 Button_SpeedHigh.Click 执行:
  调用 BluetoothClient1.SendText(文本: "3")

5. 接收传感器数据

当 Clock_Receive.Timer 执行(间隔 200ms):
  如果 BluetoothClient1.IsConnected 那么:
    如果 BluetoothClient1.BytesAvailable > 0 那么:
      设置 Label_Data.Text 为 BluetoothClient1.ReceiveText(字节数: -1)

六、实战案例:BLE LED 控制

6.1 硬件准备

使用 ESP32 开发板作为 BLE 外设:

// ESP32 BLE LED 控制 - Arduino 端代码
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#define LED_PIN 2  // ESP32 内置 LED

// 自定义 Service 和 Characteristic UUID
#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

BLEServer *pServer = NULL;
BLECharacteristic *pCharacteristic = NULL;
bool deviceConnected = false;

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer) {
    deviceConnected = true;
  }
  void onDisconnect(BLEServer *pServer) {
    deviceConnected = false;
    // 重新开始广播
    BLEDevice::startAdvertising();
  }
};

class MyCharacteristicCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    std::string value = pCharacteristic->getValue();
    if (value.length() > 0) {
      if (value[0] == 0x01) {
        digitalWrite(LED_PIN, HIGH);  // 开灯
      } else if (value[0] == 0x00) {
        digitalWrite(LED_PIN, LOW);   // 关灯
      }
    }
  }
};

void setup() {
  pinMode(LED_PIN, OUTPUT);
  
  BLEDevice::init("ESP32_LED");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
    CHARACTERISTIC_UUID,
    BLECharacteristic::PROPERTY_READ |
    BLECharacteristic::PROPERTY_WRITE |
    BLECharacteristic::PROPERTY_NOTIFY
  );
  pCharacteristic->addDescriptor(new BLE2902());
  pCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
  
  pCharacteristic->setValue("Hello");
  pService->start();
  BLEDevice::startAdvertising();
}

void loop() {
  if (deviceConnected) {
    // 可在此处发送传感器通知
    pCharacteristic->setValue((uint8_t*)"OK", 2);
    pCharacteristic->notify();
    delay(2000);
  }
  delay(100);
}

6.2 App Inventor BLE 积木块

当 Button_Scan.Click 执行:
  调用 BluetoothLE1.StartScanning()

当 BluetoothLE1.DeviceFound 执行:
  如果 deviceName = "ESP32_LED" 那么:
    调用 BluetoothLE1.StopScanning()
    调用 BluetoothLE1.Connect(deviceAddress)

当 BluetoothLE1.Connected 执行:
  设置 Label_Status.Text 为 "已连接 ESP32_LED"

当 Button_LED_On.Click 执行:
  调用 BluetoothLE1.WriteBytes(
    serviceUuid: "4fafc201-1fb5-459e-8fcc-c5c9c331914b",
    characteristicUuid: "beb5483e-36e1-4688-b7f5-ea07361b26a8",
    写入值: [1]
  )

当 Button_LED_Off.Click 执行:
  调用 BluetoothLE1.WriteBytes(
    serviceUuid: "4fafc201-1fb5-459e-8fcc-c5c9c331914b",
    characteristicUuid: "beb5483e-36e1-4688-b7f5-ea07361b26a8",
    写入值: [0]
  )

当 Button_Disconnect.Click 执行:
  调用 BluetoothLE1.Disconnect()

七、Android 12+ 蓝牙权限处理

7.1 权限变化背景

从 Android 12(API 31)开始,Google 对蓝牙权限进行了重大调整:

Android 版本 所需权限
Android 11 及以下 BLUETOOTHBLUETOOTH_ADMINACCESS_FINE_LOCATION
Android 12+ BLUETOOTH_SCANBLUETOOTH_CONNECTBLUETOOTH_ADVERTISE

关键变化:

  1. 旧权限被弃用BLUETOOTHBLUETOOTH_ADMIN 在 Android 12+ 中不再生效
  2. 新增运行时权限BLUETOOTH_SCAN(扫描)、BLUETOOTH_CONNECT(连接)、BLUETOOTH_ADVERTISE(广播)需要在运行时动态请求
  3. 位置权限仍需要:在某些设备上,ACCESS_FINE_LOCATION 仍然是蓝牙扫描所必需的

7.2 App Inventor 中的权限处理

App Inventor 2 从 nb197 及更高版本开始,已在编译时自动添加了 Android 12+ 所需的蓝牙权限声明。但在运行时,仍需请求用户授权。

使用内置组件处理权限

当 Screen1.Initialize 执行:
  调用 BluetoothClient1.RequestBluetoothPermission()

使用 TaifunBluetooth 扩展处理权限

如果使用 Taifun 的 Bluetooth 扩展(支持 Android 12+),可使用内置的权限请求方法:

当 Screen1.Initialize 执行:
  调用 TaifunBluetooth1.RequestBluetoothPermission()

说明:

  • 此方法会自动判断 Android 版本,在 Android 12+ 上请求 BLUETOOTH_CONNECTBLUETOOTH_SCANBLUETOOTH_ADVERTISEACCESS_FINE_LOCATION
  • 在 Android 11 及以下只请求 ACCESS_FINE_LOCATION

7.3 常见问题与解决

问题 1:Error 908 ACCESS_FINE_LOCATION

原因:Android 10+ 要求精确定位权限才能扫描蓝牙设备。

解决

当 Screen1.Initialize 执行:
  如果 未获得 ACCESS_FINE_LOCATION 权限 那么:
    请求权限(ACCESS_FINE_LOCATION)

在 App Inventor 中,可以使用 Screen1.AskForPermission 方法:

当 Screen1.Initialize 执行:
  调用 Screen1.AskForPermission(Manifest.permission.ACCESS_FINE_LOCATION)

问题 2:Android 12+ 扫描不到设备

原因:缺少 BLUETOOTH_SCAN 运行时权限。

解决:确保使用最新版本的 App Inventor(nb197+),并在连接前请求权限。

问题 3:JDY-34 双模蓝牙模块连接问题

JDY-34 是一款同时支持经典蓝牙(SPP)和 BLE 的双模模块:

  • 经典蓝牙模式:使用 BluetoothClient 组件,波特率默认 9600
  • BLE 模式:使用 BluetoothLE 扩展,Service UUID 为 FFF0,Characteristic UUID 为 FFF1(透传)和 FFF2(通知)

JDY-34 BLE 模式 AT 指令设置:

AT+DEFAULTSP      // 恢复出厂设置
AT+BLEMODE1       // 设置为 BLE 模式(0=经典, 1=BLE, 2=双模)
AT+BAUD4          // 设置波特率 9600
AT+NAMEJDY-34     // 设置设备名称

八、进阶技巧

8.1 使用滑动条控制速度

当 Slider_Speed.PositionChanged 执行:
  如果 BluetoothClient1.IsConnected 那么:
    设置 speedValue 为 向下取整(Slider_Speed.ThumbPosition)
    调用 BluetoothClient1.SendText(文本: "V" + speedValue + "\n")

Arduino 端解析:

if (bluetooth.available()) {
  String data = bluetooth.readStringUntil('\n');
  if (data.startsWith("V")) {
    speed = data.substring(1).toInt();
    speed = constrain(speed, 0, 255);
  }
}

8.2 使用加速度传感器遥控

当 AccelerometerSensor1.AccelerationChanged 执行:
  如果 BluetoothClient1.IsConnected 那么:
    如果 Y轴加速度 > 2 那么:        // 手机前倾
      调用 BluetoothClient1.SendText(文本: "F")
    否则如果 Y轴加速度 < -2 那么:   // 手机后仰
      调用 BluetoothClient1.SendText(文本: "B")
    否则如果 X轴加速度 > 2 那么:    // 手机左倾
      调用 BluetoothClient1.SendText(文本: "L")
    否则如果 X轴加速度 < -2 那么:   // 手机右倾
      调用 BluetoothClient1.SendText(文本: "R")
    否则:
      调用 BluetoothClient1.SendText(文本: "S")

8.3 数据可视化(传感器图表)

使用 App Inventor 的 Chart 组件实时显示蓝牙传感器数据:

当 Clock_Chart.Timer 执行(间隔 500ms):
  如果 BluetoothClient1.IsConnected 那么:
    如果 BluetoothClient1.BytesAvailable > 0 那么:
      设置 dataText 为 BluetoothClient1.ReceiveText(字节数: -1)
      设置 dataValue 为 转换为数字(dataText)
      调用 ChartData1.AddEntry(时间戳, dataValue)

8.4 多设备控制

通过创建多个 BluetoothClient 实例,可以同时连接并控制多个蓝牙设备:

当 Button_Sync.Click 执行:
  如果 BluetoothClient1.IsConnected 且 BluetoothClient2.IsConnected 那么:
    调用 BluetoothClient1.SendText(文本: "SYNC")
    调用 BluetoothClient2.SendText(文本: "SYNC")

九、调试技巧

9.1 常见问题排查

问题 可能原因 解决方案
扫描不到设备 权限未授予、蓝牙未开启、位置服务未开 检查权限、确保蓝牙和位置服务已开启
连接后立即断开 UUID 不匹配、模块未就绪 检查 UUID 配置、重试连接
发送命令无响应 波特率不匹配、TX/RX 接反 确认波特率一致、检查接线
数据乱码 编码方式不一致 确保两端使用相同编码(UTF-8)
Android 12+ 权限报错 缺少运行时权限 使用最新版 App Inventor,添加权限请求

9.2 调试建议

  1. 先在串口调试器测试硬件:使用 USB 串口或蓝牙串口调试 App 确认硬件端正常
  2. 逐步调试:先确保能连接,再测试发送,最后测试接收
  3. 使用 Label 显示状态:在 App 界面上显示连接状态、发送/接收的数据
  4. Do It 实时调试:使用 AI 伴侣的 “Do It” 功能实时查看变量值

十、完整项目清单

经典蓝牙遥控小车

项目 说明
组件 BluetoothClient、ListPicker、Button × 6、Clock、Label × 2
通信协议 单字符命令:F/B/L/R/S + 速度 1/2/3
硬件 Arduino + HC-05/HC-06 + L298N + 直流电机

BLE LED 控制

项目 说明
组件 BluetoothLE 扩展、Button × 3、Label × 2
通信协议 BLE GATT WriteBytes:0x01=开灯,0x00=关灯
硬件 ESP32 开发板 + LED

BLE 传感器数据采集

项目 说明
组件 BluetoothLE 扩展、Button × 2、Label、Chart、Clock
通信协议 BLE GATT Notify + ReadBytes
硬件 ESP32 + 温湿度/光照传感器

参考资料


*文档版本:2026.05 更新日期:2026-05-18 作者:App Inventor 2 中文网 www.fun123.cn*

参考资料与版权声明

原文来源

版权声明

本文档基于 MIT App Inventor 开源项目整理编写,遵循 Apache 2.0 授权。 本文档由 ai2claw 🐝 编写整理,仅供学习参考。

文档反馈