连接蓝牙模块后丢失数据 toggleScanDevices toggleConnectDevicedevice.name connectDevice名称 findDeviceWhereNameContainsname连接之前的日志连接后的日志

问题描述

客观

我试图在连接后从蓝牙设备返回数据,因为要使用读写功能,需要一些数据。 示例数据name,overflowServiceUUIDs,solicitedServiceUUIDs,mtu,RSSi...等。因为如果我想读写,我需要一些属性。我正在使用图书馆react-native-ble-plx

发生了什么事?

连接设备后,我丢失了一些值。

重要

type DeviceState = {
  connected: boolean;
  services: Service[];
  device: Device | null;
  characteristics: Record<string,Characteristic[]>;
};

const INITIAL_DEVICE_STATE = {
  connected: false,services: [],device: null,characteristics: {},};
const [adapterState,setAdapterState] = useState(false);
const [bleDevices,setBleDevices] = useState<Device[]>([]);
const [isScanning,setIsScanning] = useState(false);
const [connectedDevice,setConnectedDevice] = useState<DeviceState>(
    INITIAL_DEVICE_STATE,);

# The state isScaning is used to be if we are scanning devices.
# The connectedDevice state will be the connected device.

序列功能

toggleScanDevices()

将所有设备推到bleDevices状态。

  const toggleScanDevices = () => {
    setIsScanning(true);
    setBleDevices([]);

    bleManager.startDeviceScan(null,{},(bleError,device) => {
      if (device && _.findindex(bleDevices,{ id: device.id }) < 0) {
        bleDevices.push(device);
        setBleDevices(bleDevices);
      }
    });

    setTimeout(() => {
      setIsScanning(false);
      bleManager.stopDeviceScan();
    },5000);
  };

toggleConnectDevice(device.name)

  const toggleConnectDevice = (name: string) => async () => {
    if (!connectedDevice.device) {
      await connectDevice(name);
    } else {
      const { device } = connectedDevice;

      if (!device) return;

      await device.cancelConnection();

      if (!(await device.isConnected())) {
        setConnectedDevice(INITIAL_DEVICE_STATE);
      }
    }
  };

connectDevice(名称

  const connectDevice = async (name: string) => {
    let device = findDeviceWhereNameContains(name);

    if (device === null) {
      setConnectedDevice(INITIAL_DEVICE_STATE);
      return false;
    }

    let isConnected = await device.isConnected();

    if (!isConnected) {
      /* Testar aqui */
      device = await bleManager.connectToDevice(device.id);
      isConnected = await device.isConnected();
    }
    device = await device.discoverAllServicesAndcharacteristics();

    device.ondisconnected((error,device) => {
      setConnectedDevice(INITIAL_DEVICE_STATE);
    });

    const services = await device.services();
    const characteristics: Record<string,Characteristic[]> = {};
    const descriptors = {};

    _.forEach(services,async service => {
      const devicecharacteristics = await device?.characteristicsForService(
        service.uuid,);
      characteristics[service.uuid] = devicecharacteristics || [];
    });

    setConnectedDevice(state => ({
      ...state,services,characteristics,device,}));

    const newDevice = { ...connectedDevice,device };
    setConnectedDevice(newDevice);
    console.log('não atualizado',connectedDevice);
    console.log('novo valor',newDevice);
  };

findDeviceWhereNameContains(name)

  const findDeviceWhereNameContains = (name: string) => {
    const device = bleDevices.find(item => String(item.name).includes(name));
    if (device !== undefined) {
      return device;
    }
    return null;
  };

connectDevice函数中,我有一个let device接收有关findDeviceWhereNameContains的值,如果我记录此变量device,我会收到很多非常重要的数据,但是我还没有连接。因此,当我在此处验证if (!isConnected)时,我将进行连接,此后,如果再次登录device时,将丢失一些值。

连接之前的日志

The data before the connection

连接后的日志

Device {overflowServiceUUIDs: null,solicitedServiceUUIDs: null,localName: null,isConnectable: null,txPowerLevel: null,…}
overflowServiceUUIDs: null
solicitedServiceUUIDs: null
localName: null
isConnectable: null
txPowerLevel: null
serviceUUIDs: null
serviceData: null
mtu: null
name: "MLT-BT05"
manufacturerData: null
RSSi: null
id: "88:25:83:F0:30:BC"

解决方法

从调用本机模块时得到的响应中检查您正在使用的库creates another device object,这可能是因为新对象在这些字段上带有空值,而replaces您需要的价值观。由于它现在就可以正常工作,因此您可以copy将这些值pick删除之前先将其保存到另一个对象

import pick from 'lodash/pick';

const connectDevice = async (name: string) => {
    let device = findDeviceWhereNameContains(name);
    // according to the screenshot,the object still have the
    // information you want at this point
    
    // taking advantage taht you have lodash already you can use pick
    const valuesYouNeed = pick(device,['serviceUUIDs',...]);

    ...

    // here you merge them back with other device's attr that are present at this point
    const newDevice = { ...pick(device,['connected',...]),...valuesYouNeed };
    setConnectedDevice(newDevice);
    console.log('não atualizado',connectedDevice);
    console.log('novo valor',newDevice);
  };

但是您要小心,它们不会再次被替换。

如果您认为这是react-native-ble-plx的错误行为,则可以使用Device构造函数中的更改来打开PR,以免发生这种情况。

由于您使用的是打字稿,因此您会对打字感到有些不满,您可以使用react-native-ble-plx设备类型创建类型,而enter image description here仅使用其属性部分来省略方法并避免存储处于您状态的复杂对象。

import { Device } from 'react-native-ble-plx`;

type DeviceState = Pick<
    Device,| 'id'
    | 'name'
    | 'rssi'
    | 'mtu'
    | 'manufacturerData'
    | 'serviceData'
    | 'serviceUUIDs'
    | 'localName'
    | 'txPowerLevel'
    | 'solicitedServiceUUIDs'
    | 'isConnectable'
    | 'overflowServiceUUIDs'
  >

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...