locked
Equivalent c# code of this C++ code RRS feed

  • Question

  • Hi everyone,

    I have to create a desktop application in C# that gets connected to a Bluetooth low energy device and send values to the device using Set characteristic value function. For this I need get Characteristic buffer using get characteristics function. (http://msdn.microsoft.com/en-us/library/windows/hardware/hh450795(v=vs.85).aspx). 

    I have C++ equivalent code to do this:

    USHORT charBufferSize = 0; HRESULT hres = BluetoothGATTGetCharacteristics( BLE_Service,NULL, 0,NULL,

    &charBufferSize,BLUETOOTH_GATT_FLAG_NONE);

    if(hres==HRESULT_FROM_WIN32(ERROR_MORE_DATA)) // if 5 { Characteristic_Buffer = new BTH_LE_GATT_CHARACTERISTIC [charBufferSize ]; } // end of if 5 USHORT val = 0;

    // get characteristics after allocating required size hres = BluetoothGATTGetCharacteristics(BLE_Service,NULL,charBufferSize,

    Characteristic_Buffer,&val,BLUETOOTH_GATT_FLAG_NONE);

    I have to do this same thing in C#

    So, I tried something like this

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct BTH_LE_GATT_CHARACTERISTIC { public UInt16 ServiceHandle; public BTH_LE_UUID CharacteristicUuid; public UInt16 AttributeHandle; public UInt16 CharacteristicValueHandle; public Boolean IsBroadcastable; public Boolean IsReadable; public Boolean IsWritable; public Boolean IsWritableWithoutResponse; public Boolean IsSignedWritable; public Boolean IsNotifiable; public Boolean IsIndicatable; public Boolean HasExtendedProperties; } [DllImport(@"BluetoothApis.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern Boolean BluetoothGATTGetCharacteristics( IntPtr Device_Handle, IntPtr Service, UInt16 Char_Buffer_Count, ref BTH_LE_GATT_CHARACTERISTIC CharBuffer, out UInt16 RequiredSize, uint Flags ); UInt16 Size_Required = 0; UInt16 NBytes = 0; BTH_LE_GATT_CHARACTERISTIC gattChar = new BTH_LE_GATT_CHARACTERISTIC(); Success = BluetoothGATTGetCharacteristics(Ble_Device, IntPtr.Zero, 0, IntPtr.Zero,

    out Size_Required, (uint)BTH_LE_FLAGS.BLUETOOTH_GATT_FLAG_NONE);


    I am stuck here. Now, to make second call to the function, I should allocate memory to the characteristic buffer as done in c++. 

    Any suggestions as how to allocate memory of required size to the characteristic structure??

    Or is there any other way to use bluetooth low energy functions in C#?

    Thanks in advance

    phanitk23


    • Edited by phanitk Thursday, March 21, 2013 9:15 AM
    Thursday, March 21, 2013 8:53 AM

Answers

  • The equivalent C# code is shown below

    C++

        byte Characteristic_Buffer[] = new BTH_LE_GATT_CHARACTERISTIC [charBufferSize ];               

               or

        byte *Characteristic_Buffer = new BTH_LE_GATT_CHARACTERISTIC [charBufferSize ];               


    C#

        byte[] Characteristic_Buffer = new BTH_LE_GATT_CHARACTERISTIC [charBufferSize ];               



    jdweng

    • Proposed as answer by Mike Feng Sunday, March 24, 2013 7:58 AM
    • Marked as answer by Mike Feng Wednesday, April 3, 2013 4:44 PM
    Saturday, March 23, 2013 11:23 PM
  • Don't laugh when you see the solution.  I don't understand why you need to use 'new' with a char[] and don't need to use 'new' it with a byte[].

            static void Main(string[] args)
            {
                byte[] bytearray = { 0x31, 0x32, 0x33 };
                char[] chararrray = Encoding.UTF8.GetChars(bytearray);
                chararrray = new char[]{'A','B','B'};
                bytearray = Encoding.UTF8.GetBytes(chararrray);
            }


    jdweng

    • Marked as answer by Mike Feng Wednesday, April 3, 2013 4:44 PM
    Monday, March 25, 2013 9:35 AM

All replies

  • In the C++ code, it looks like the fourth parameter of BluetoothGATTGetCharacteristics is a pointer to an array of BTH_LE_GATT_CHARACTERISTICs. (You are allocating Characteristic_Buffer so that it can hold charBufferSize items.)

    In the C# code, however, you have declared the fourth parameter of the function to be a single item, and you are also allocating a single item.

    Try changing the function declaration to

    [DllImport(@"BluetoothApis.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern Boolean BluetoothGATTGetCharacteristics(
        IntPtr Device_Handle,
        IntPtr Service,
        UInt16 Char_Buffer_Count,
        BTH_LE_GATT_CHARACTERISTIC[] CharBuffer,
        out UInt16 RequiredSize,
        uint Flags
    );

    and the allocation to

    BTH_LE_GATT_CHARACTERISTIC[] gattChar = new BTH_LE_GATT_CHARACTERISTIC[Size_Required]();

    You also need to put the allocation of gattChar after the initial call to BluetoothGATTGetCharacteristics.

    Then hopefully you will be able to make your second call to BluetoothGATTGetCharacteristics like this:

    BluetoothGATTGetCharacteristics(Ble_Device, 
        IntPtr.Zero, Size_Required, gattChar, 
        out Size_Required,
        (uint)BTH_LE_FLAGS.BLUETOOTH_GATT_FLAG_NONE);
    

    • Edited by mbj79 Saturday, March 23, 2013 5:36 PM Noticed some more differences
    • Proposed as answer by Mike Feng Sunday, March 24, 2013 7:59 AM
    Saturday, March 23, 2013 5:21 PM
  • The equivalent C# code is shown below

    C++

        byte Characteristic_Buffer[] = new BTH_LE_GATT_CHARACTERISTIC [charBufferSize ];               

               or

        byte *Characteristic_Buffer = new BTH_LE_GATT_CHARACTERISTIC [charBufferSize ];               


    C#

        byte[] Characteristic_Buffer = new BTH_LE_GATT_CHARACTERISTIC [charBufferSize ];               



    jdweng

    • Proposed as answer by Mike Feng Sunday, March 24, 2013 7:58 AM
    • Marked as answer by Mike Feng Wednesday, April 3, 2013 4:44 PM
    Saturday, March 23, 2013 11:23 PM
  • Hey 

    Thanks for the answers.. I ll try them and get back to you..

    Monday, March 25, 2013 4:23 AM
  • Hey mbj79,

    I tried what you suggested.

    It is getting executed well without any errors, but the structure is null after the second call also..

    And the GetlastWin32error() gives 234 i.e, more data is available..

    Any suggestions??

    Thanks


    • Edited by phanitk Monday, March 25, 2013 9:52 AM
    Monday, March 25, 2013 4:41 AM
  • Hi joel,

    How can i give byte array as characteristic stucture?? do i need to typecast it??

    Monday, March 25, 2013 4:44 AM
  • Don't laugh when you see the solution.  I don't understand why you need to use 'new' with a char[] and don't need to use 'new' it with a byte[].

            static void Main(string[] args)
            {
                byte[] bytearray = { 0x31, 0x32, 0x33 };
                char[] chararrray = Encoding.UTF8.GetChars(bytearray);
                chararrray = new char[]{'A','B','B'};
                bytearray = Encoding.UTF8.GetBytes(chararrray);
            }


    jdweng

    • Marked as answer by Mike Feng Wednesday, April 3, 2013 4:44 PM
    Monday, March 25, 2013 9:35 AM
  • Any chance you could share the whole code?

    Also you should know that there already is a c# api for this, but in my case i need CharacteristicValueHandle and that isen't exposed in the c# api.

    Example usage of the C# api https://github.com/AnderssonPeter/Home-Assistant-Windows-Tools/blob/master/gatttool/Program.cs


    • Edited by Petoj87 Thursday, April 13, 2017 6:57 AM
    Thursday, April 13, 2017 6:53 AM