在本文中,我想告诉您如何制作一个非常简单的蓝牙气象站(没有它的地方:)),并在Flutter上编写一个移动应用程序。
首先,请考虑传感器本身
要重复,您将需要一个Arduino nano 33 BLE感应板。该评估板基于nrf52840构建。我们通过arduino中的董事会经理安装它。
立即安装必要的库:这些库对于已经焊接在电路板上的传感器来说是必需的。有点理论,然后考虑实际实现
主要思想不是制造插件设备,而是实现广播消息,其中包含所有必需的信息。使用了常规的蓝牙标签模式,但对ManufacturerData进行了修改。该包可以在每个广告包中传输。广告包的总大小为31个字节。其中包括所有必要的信息:设备名称,系统数据,用户数据。以纯格式,ManufacturerData中的用户约为20个字节。这足以传输气象站数据。这种数据传输方法的优点是功耗较低,无需与广播设备保持恒定连接。这样的消息可以在接收半径内捕获无限数量的接收者。在开始投放广告之前已安装了ManufacturerData。现在是实际部分
在arduino代码中,我们指示BLE部件的工作类型并设置开始的ManufacturerData,此外,为了方便起见,我指定了设备的名称,因此在应用程序中更容易找到。BLE.setLocalName("nrf52840.ru");
BLE.setConnectable(false);
byte data[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
BLE.setManufacturerData(data, 8);
BLE.advertise();
初始数据以一组字节填充数组的形式给出。现在,在主要代码中,我们停止广播,停止广播,测量必要的数据,并用实际数据填充ManufacturerData,然后开始广播。该操作每2秒执行一次。BLE.stopAdvertise();
---------------------
---------------------
byte data[8] = { 0x00, 0x01, t1, t2, h1, h2, p1, p2};
BLE.setManufacturerData(data, 8);
BLE.advertise();
delay(2000);
这样就完成了传感器的工作。传感器每100毫秒广播一次,每2秒钟将数据更新到当前一次。结果是一个非常简单的天气代码和实施传感器。现在考虑移动应用
我将立即预订:我不是移动应用程序开发人员。为了工作,我将VSCode与Flutter插件一起使用。我认为,这种环境似乎比Android Studio简单。为了使用BLE,使用Flutter_blue库,该库大大简化了设备的连接。应用程序的逻辑也很简单。我们的传感器以常规信标模式广播,因此您只需要执行以下几项操作:- 扫描广播-查找具有给定名称的设备,
- 解析ManufacturerData以在屏幕上显示数据。
让我们看看这是如何完成的。启动应用程序后,将定期启动计时器,该计时器每10秒钟扫描一次蓝牙设备,持续2秒钟。扫描得更多,更长的时间是没有意义的,电池消耗会增加,并且传感器通常每100ms广播一次。DeviceScanner() {
_subscribeToScanEvents();
_timer = new Timer.periodic(const Duration(seconds: 10), startScan);
}
void startScan(Timer timer) {
FlutterBlue.instance.startScan(timeout: Duration(seconds: 2));
}
接下来,我们开始分析扫描结果,检查扫描列表中是否存在具有给定名称的设备,如果是,我们将分析其程序包并将结果显示给用户。
void _subscribeToScanEvents() {
FlutterBlue.instance.scanResults.listen((scanResults) {
for (ScanResult scanResult in scanResults) {
if (scanResult.device.name.toString() == "nrf52840.ru") {
final int rssi = scanResult.rssi;
final String name = scanResult.device.name;
final String mac = scanResult.device.id.toString();
final double temp = scanResult.advertisementData.manufacturerData[256]
[0] +
scanResult.advertisementData.manufacturerData[256][1] * 0.01;
final double humm = scanResult.advertisementData.manufacturerData[256]
[2] +
scanResult.advertisementData.manufacturerData[256][3] * 0.01;
final double press =
scanResult.advertisementData.manufacturerData[256][4] +
scanResult.advertisementData.manufacturerData[256][5] * 0.01;
final SensorData sensorData = new SensorData(
name: name,
rssi: rssi,
mac: mac,
temperature: temp,
humidity: humm,
pressure: press);
_streamController.add(sensorData);
print(
'Manufacturer data ${scanResult.advertisementData.manufacturerData}');
FlutterBlue.instance.stopScan();
}
print(
'${scanResult.device.name} found! mac: ${scanResult.device.id} rssi: ${scanResult.rssi}');
}
});
}
有点细微差别。Flutter的蓝牙库可能看起来很奇怪,它以int数组的形式接收数据,在arduino中,我们从字节组成一个包,因此我在传感器中形成了一个包以简化其分析。25.85度的温度分为两个值25和85,它们作为单独的字节值发送,并以相同的方式收集。最终的结果就是这样一个应用程序。
可以从Github下载项目源代码。