简体   繁体   English

Xamarin iOS低功耗蓝牙-CBPeripheral.UpdatedCharacteristicValue读取TX特性显示意外数据

[英]Xamarin iOS Bluetooth Low Energy - CBPeripheral.UpdatedCharacteristicValue reading TX characteristic shows unexpected data

I recently received a BLE device for Bluetooth to Serial. 我最近收到了一个用于蓝牙到串行的BLE设备。 It uses TruConnect and I'm trying to get it to communicate with my serial device. 它使用TruConnect,我正在尝试使其与串行设备通信。 The serial device receives communication over a serial cable and echoes back anything that is sent to it as well as any results from a command that is sent. 串行设备通过串行电缆接收通信,并回显发送给它的所有内容以及所发送命令的任何结果。

Right now I'm simply trying to send TruConnect commands to the BLE device to check the current baud rate that the BLE device is set for. 现在,我只是试图将TruConnect命令发送到BLE设备,以检查BLE设备的当前波特率。

I wrote some code based on this TruConnect guide that I found: https://truconnect.ack.me/1.5/apps/communicating_via_ble#reading_from_a_truconnect_device_serial_interface . 我根据发现的TruConnect指南编写了一些代码: https : //truconnect.ack.me/1.5/apps/communicating_via_ble#reading_from_a_truconnect_device_serial_interface

The problem seems to be that whenever I try to read anything from the tx characteristic when there should be data, the data is not right. 问题似乎是,每当我尝试从tx特性中读取任何东西时,应该有数据,数据就不正确。

Setting up CBPeripheral events: 设置CBP外围事件:

private void setupPerif(CBPeripheral perf)
{
    selectedPeripheral = perf;

    selectedPeripheral.UpdatedCharacterteristicValue += (sender, e) =>
    {
        var c = e.Characteristic;
        if (c != null)
        {
            var uuid = c.UUID.ToString(true).ToLower();
            if (uuid == UUID_RX)
            {
                //
            }
            else if (uuid == UUID_TX)
            {
                // expecting bytes to contain valid response data
                // it almost always contains twenty 0s.
                byte[] bytes = c.Value.Where(i => i != 13).ToArray();
                var invalidBytes = c.Value.Where(i => i > 127).ToArray();
                var nonZeros = c.Value.Where(i => i != 0).ToArray();
                if (nonZeros.Length < 1)
                {
                    return;
                }
                else
                {
                    foreach (byte b in bytes)
                        handler.handleByteReceived((char)b);
                }
            }
            else if (uuid == UUID_MODE)
            {
                //
            }
        }
    };

    selectedPeripheral.DiscoveredService += (sender, e) =>
    {
        var services = selectedPeripheral.Services;
        if (services != null)
        {
            foreach (CBService service in services)
            {
                if (service.UUID.ToString(true).ToLower() == UUID_TRUCONNECT)
                {
                    truConnect = service;
                    selectedPeripheral.DiscoverCharacteristics(truConnect);
                }
            }
        }
    };

    selectedPeripheral.DiscoveredCharacteristic += (sender, e) =>
    {
        if (truConnect != null && truConnect.Characteristics != null)
        {
            foreach (CBCharacteristic c in truConnect.Characteristics)
            {
                var uuidString = c.UUID.ToString(true).ToLower();
                if (uuidString == UUID_RX)
                {
                    rx = c;

                }
                else if (uuidString == UUID_TX)
                {
                    tx = c;
                }
                else if (uuidString == UUID_MODE)
                {
                    mode = c;
                    // set to stream mode
                    selectedPeripheral.WriteValue(NSData.FromArray(new byte[] { MODE_COMMAND }), mode, CBCharacteristicWriteType.WithResponse);
                }
            }
        }
    };
    selectedPeripheral.WroteCharacteristicValue += (sender, e) =>
    {
        // if UUID is for RX, we just wrote to RX. Drill down to
        // TX characteristic and read it. This will trigger
        // the UpdatedCharacteristicValue event.
        string uuid = e.Characteristic.UUID.ToString(true).ToLower();
        if (uuid == UUID_RX)
        {
            var services = selectedPeripheral.Services;
            if (services != null)
            {
                foreach (CBService s in services)
                {
                    if (s.UUID.ToString(true).ToLower() == UUID_TRUCONNECT)
                    {
                        var charachteristics = s.Characteristics;
                        if (charachteristics != null && charachteristics.Length > 0)
                        {
                            foreach (CBCharacteristic c in charachteristics)
                            {
                                if (c.UUID.ToString(true).ToLower() == UUID_TX)
                                {
                                    Timer t = new Timer(new TimerCallback(delegate(object o)
                                    {
                                        selectedPeripheral.ReadValue(c);
                                    }), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(-1));
                                }
                            }
                        }
                    }
                }
            }
        }
    };
    manager.ConnectPeripheral(selectedPeripheral);
}

Writes to rx. 写入rx。 This is what should be used to actually send commands. 这是实际用于发送命令的方式。

public void sendCommand(string command)
{
    command += endString + "\n";
    if (rx != null)
    {
        NSData d = NSData.FromString(command);

        foreach (CBService s in selectedPeripheral.Services)
        {
            if (s.UUID.ToString(true).ToLower() == UUID_TRUCONNECT)
                foreach (CBCharacteristic c in s.Characteristics)
                {
                    if (c.UUID.ToString(true).ToLower() == UUID_RX)
                        selectedPeripheral.WriteValue(NSData.FromString(command), c, CBCharacteristicWriteType.WithResponse);
                }
        }
    }
}

So my question is, why am I not getting the expected data when the CBPeripheral.UpdatedCharacteristicValue event is called? 所以我的问题是,为什么在调用CBPeripheral.UpdatedCharacteristicValue事件时没有得到期望的数据? Occasionally I will get the expected data, but it is quite rare, and I can't seem to find any logical reason or pattern that would explain why this is happening. 有时我会获得预期的数据,但这是非常罕见的,而且我似乎找不到任何逻辑原因或模式可以解释为什么会发生这种情况。

AHA! AHA! I figured it out! 我想到了!

The problem was that I need to set the notify value for the appropriate characteristics. 问题是我需要为适当的特征设置通知值。 After doing that, I didn't need to call CBPeripheral.ReadValue(CBCharacteristic) . 完成之后,我不需要调用CBPeripheral.ReadValue(CBCharacteristic)

    selectedPeripheral.DiscoveredCharacteristic += (sender, e) =>
    {
        if (truConnect != null && truConnect.Characteristics != null)
        {
            foreach (CBCharacteristic c in truConnect.Characteristics)
            {
                var uuidString = c.UUID.ToString(true).ToLower();
                if (uuidString == UUID_RX)
                {
                    rx = c;
                }
                else if (uuidString == UUID_TX)
                {
                    tx = c;
                    // set the notify value to true and poof!
                    // now CBPeripheral.UpdatedCharacteristicValue
                    // event will be triggered at the appropriate time.
                    selectedPeripheral.SetNotifyValue(true, tx);
                }
                else if (uuidString == UUID_MODE)
                {
                    mode = c;
                    // set to remote command mode
                    selectedPeripheral.WriteValue(NSData.FromArray(new byte[] { MODE_COMMAND }), mode, CBCharacteristicWriteType.WithResponse);
                }
            }
        }
    };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM