java - 如何在 Xamarin 表单中为 BLE 拆分和发送 >20 字节的数据?

标签 java c# android xamarin.forms bluetooth-lowenergy

我正在尝试实现 Xamarin 中的 BLE 表单 .我要发送数据大于 20 个字节。我已经看到使用 java 在 native android 中的实现。它看起来像下面

private void sendMessage(BluetoothGattCharacteristic characteristic, String CHARACTERS){
        byte[] initial_packet = new byte[3];
        /**
         * Indicate byte
         */
        initial_packet[0] = BLE.INITIAL_MESSAGE_PACKET;
        if (Long.valueOf(
                String.valueOf(CHARACTERS.length() + initial_packet.length))
                > BLE.DEFAULT_BYTES_VIA_BLE) {
            sendingContinuePacket(characteristic, initial_packet, CHARACTERS);
        } else {
            sendingLastPacket(characteristic, initial_packet, CHARACTERS);
        }
    }

private void sendingContinuePacket(BluetoothGattCharacteristic characteristic,
            byte[] initial_packet, String CHARACTERS){
        /**
         * TODO If data length > Default data can sent via BLE : 20 bytes
         */
        // Check the data length is large how many times with Default Data (BLE)
        int times = Byte.valueOf(String.valueOf(
                CHARACTERS.length() / BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET));

        Log.i(TAG, "CHARACTERS.length() " + CHARACTERS.length());
        Log.i(TAG, "times " + times);

        // TODO
        // 100 : Success
        // 101 : Error
        byte[] sending_continue_hex = new byte[BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET];
        for (int time = 0; time <= times; time++) {
            /**
             * Wait second before sending continue packet 
             */
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (time == times) {
                Log.i(TAG, "LAST PACKET ");

                /**
                 * If you do not have enough characters to send continue packet,
                 * This is the last packet that will be sent to the band
                 */

                /**
                 * Packet length byte :
                 */
                /**
                 * Length of last packet
                 */
                int character_length = CHARACTERS.length()
                        - BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET*times;

                initial_packet[1] = Byte.valueOf(String.valueOf(character_length
                        + BLE.INITIAL_MESSAGE_PACKET_LENGTH));
                initial_packet[2] = BLE.SENDING_LAST_PACKET;

                Log.i(TAG, "character_length " + character_length);

                /**
                 * Message
                 */
                // Hex file
                byte[] sending_last_hex = new byte[character_length];

                // Hex file : Get next bytes
                for (int i = 0; i < sending_last_hex.length; i++) {
                    sending_last_hex[i] = 
                            CHARACTERS.getBytes()[sending_continue_hex.length*time + i];
                }

                // Merge byte[]
                byte[] last_packet = 
                        new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH];
                System.arraycopy(initial_packet, 0, last_packet,
                        0, initial_packet.length);
                System.arraycopy(sending_last_hex, 0, last_packet, 
                        initial_packet.length, sending_last_hex.length);

                // Set value for characteristic
                characteristic.setValue(last_packet);
            } else {
                Log.i(TAG, "CONTINUE PACKET ");
                /**
                 * If you have enough characters to send continue packet,
                 * This is the continue packet that will be sent to the band
                 */
                /**
                 * Packet length byte
                 */
                int character_length = sending_continue_hex.length;

                /**
                 * TODO Default Length : 20 Bytes
                 */
                initial_packet[1] = Byte.valueOf(String.valueOf(
                        character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH));

                /**
                 * If sent data length > 20 bytes (Default : BLE allow send 20 bytes one time)
                 * -> set 01 : continue sending next packet
                 * else or if after sent until data length < 20 bytes
                 * -> set 00 : last packet
                 */
                initial_packet[2] = BLE.SENDING_CONTINUE_PACKET;
                /**
                 * Message
                 */
                // Hex file : Get first 17 bytes
                for (int i = 0; i < sending_continue_hex.length; i++) {
                    Log.i(TAG, "Send stt : " 
                            + (sending_continue_hex.length*time + i));

                    // Get next bytes
                    sending_continue_hex[i] = 
                            CHARACTERS.getBytes()[sending_continue_hex.length*time + i];
                }

                // Merge byte[]
                byte[] sending_continue_packet = 
                        new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH];
                System.arraycopy(initial_packet, 0, sending_continue_packet, 
                        0, initial_packet.length);
                System.arraycopy(sending_continue_hex, 0, sending_continue_packet, 
                        initial_packet.length, sending_continue_hex.length);

                // Set value for characteristic
                characteristic.setValue(sending_continue_packet);
            }

            // Write characteristic via BLE
            mBluetoothGatt.writeCharacteristic(characteristic);
        }
    }

public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic,
            String data) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return false;
        }

        if (ActivityBLEController.IS_FIRST_TIME) {
            /**
             * In the first time, 
             * should send the Title
             */
            byte[] merge_title = sendTitle(data);

            // Set value for characteristic
            characteristic.setValue(merge_title);

            // Write characteristic via BLE
            mBluetoothGatt.writeCharacteristic(characteristic);

            // Reset
            ActivityBLEController.IS_FIRST_TIME = false;

            return true;
        } else {
            /**
             * In the second time, 
             * should send the Message
             */
            if (data.length() <= BLE.LIMIT_CHARACTERS) {
                sendMessage(characteristic, data);

                // Reset
                ActivityBLEController.IS_FIRST_TIME = true; 

                return true;
            } else {
                // Typed character
                typed_character = data.length();

                return false;
            }
        }
    }
这是我的 Xamarin 代码 我在哪里写操作
 private async Task<string> ReadAndWriteCharacterisicsValue(ICharacteristic _characteristics)
        {
            if (_characteristics != null)
            {
                var sbnew = new StringBuilder("BLE Characteristics\n");
                byte[] senddata = Encoding.UTF8.GetBytes(string.IsNullOrEmpty("") ? "Hi1290004847846767627723676" : "");

                if (MainThread.IsMainThread)
                {
                    string writeTypes = _characteristics.WriteType.ToString();
                    await _characteristics.WriteAsync(senddata);

                }

                //_characteristics.ReadAsync();


                var charVal = _characteristics.Value;

                var str = Encoding.UTF8.GetString(charVal);
                sbnew.AppendLine($"Characteristics found on this device: {string.Join(", ", str.ToString())}");

                return sbnew.ToString();


            }
            return null;
        }
当我尝试发送字符串 Hi1290004847846767627723676(27 字节)但我得到 Hi129000484784676762(20 字节)在外围不会崩溃 .我正在使用 plugin.ble 最新版本和我的蓝牙设备版本是 5.0 . 我什至尝试请求 Mtu .正如您在以下代码中看到的
 if (_characteristics != null)
            {
                try
                {

                    var sbnew = new StringBuilder("BLE Characteristics\n");
                     byte[] senddata = Encoding.UTF8.GetBytes(string.IsNullOrEmpty("") ? "Start{'command':'UnSelectEnhancement','data':[{'UnSelectEnhancement':'VitaminC'},{'UnSelectEnhancement':'CitricAcid'},  {'UnSelectEnhancement':'Electolytes'},{'UnSelectEnhancement':'Sweetener'}]}End":"");
                   
                    await _device.RequestMtuAsync(2000);
                  

                    
                    if (MainThread.IsMainThread)
                    {
                        string writeTypes = _characteristics.WriteType.ToString();
                         await _characteristics.WriteAsync(senddata);

                    }
我要发送的数据最大值为 200 字节 .我也试过分割字符串 使用此代码。
IEnumerable<string> s = str.Split();
                    IEnumerable<string> Split( )
                    {
                        while (!string.IsNullOrWhiteSpace(str))
                        {
                            var chunk = str.Take(size).ToArray();
                           str = str.Substring(chunk.Length);
                           yield return new string(chunk);

                       }

                    }

                    
                    Console.WriteLine("Error of split");
                    
                    Console.WriteLine(String.Join(Environment.NewLine, str));
                    Console.WriteLine(String.Join(Environment.NewLine, str));
但它没有用。它看起来对我来说很复杂。 有什么简单的方法对大于 的数据执行写操作20 字节在 xamarin 形式中使用 c# ?

最佳答案

您可以尝试以多个 block 的形式发送数据,每个 block 的最大大小为 20。
此示例发送第一个 20 字节 block ,然后发送另一个带有剩余 7 个字节的 block 。

            byte[] senddata = Encoding.ASCII.GetBytes("Hi1290004847846767627723676");
            int start = 0;
            while (start < senddata.Length)
            {
                int chunkLength = Math.Min(20, senddata.Length - start);
                byte[] chunk = new byte[chunkLength];
                Array.Copy(senddata, start, chunk, 0, chunkLength);
                await writeBuf.WriteAsync(chunk);
                start += 20;
            }
编辑:
  • 删除了复制粘贴的评论
  • 关于java - 如何在 Xamarin 表单中为 BLE 拆分和发送 >20 字节的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65246453/

    相关文章:

    android - 在Android中设置RatingBar星级选择颜色

    java - Android 中的套接字异常

    c# - 重置数据表中的自动增量

    c# - Release 文件夹中的 vshost.exe 文件?

    c# - XDocument防止无效字符

    java - react native 错误 : 'Permission Denial: starting Intent"

    java - 使用java库信号量的有界缓冲区

    java - 将 Groovy 集成到现有的 Web 应用程序中

    java - 在电话上运行 tess-two

    java - 无法在 Android 11 上以编程方式拍照 - Intent 返回已取消状态