Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to solve the problem of garbled characters in characteristic names for lowenergyscanner on the Windows platform?
Forum Updated to NodeBB v4.3 + New Features

How to solve the problem of garbled characters in characteristic names for lowenergyscanner on the Windows platform?

Scheduled Pinned Locked Moved Unsolved General and Desktop
19 Posts 5 Posters 1.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • hskoglundH Offline
    hskoglundH Offline
    hskoglund
    wrote on last edited by
    #8

    Hi, the conversion only supports texts with an even number of characters, "Enter Sleep Mode" is 16 chars but "Data Size" is 9 and "Data Transmission State" is 23.

    So for both "Data Size" and "Data Transmission State" there is a missing "65" at the end, for example to fix "Data Siz" to "Data Size" change "e68584e685b4e58ca0e7a9a9" to "e68584e685b4e58ca0e7a9a965".

    S 1 Reply Last reply
    0
    • B Offline
      B Offline
      Bonnie
      wrote on last edited by Bonnie
      #9

      I've got a more simple way to do this conversion:

      // QStringEncoder for Qt6, QTextCodec+QTextEncoder for Qt5
      QStringEncoder utf16LE(QStringEncoder::Utf16LE);
      QString wrongText = QString::fromUtf8(value);
      QByteArray restoredBytes = utf16LE(wrongText);
      QString correctText = QString::fromUtf8(restoredBytes);
      

      But this won't help about the missing character. It just has the same effect as your code.

      1 Reply Last reply
      0
      • hskoglundH hskoglund

        Hi, the conversion only supports texts with an even number of characters, "Enter Sleep Mode" is 16 chars but "Data Size" is 9 and "Data Transmission State" is 23.

        So for both "Data Size" and "Data Transmission State" there is a missing "65" at the end, for example to fix "Data Siz" to "Data Size" change "e68584e685b4e58ca0e7a9a9" to "e68584e685b4e58ca0e7a9a965".

        S Offline
        S Offline
        swjqq
        wrote on last edited by
        #10

        @hskoglund Thank you for your reply. However, I am unable to determine what is missing at the end of the text with an odd number of characters, as it is not necessarily 65. These data are read from descriptor values, such as "e68584e685b4e590a0e685b2e78daee6a5ade78db3e6bda9", which should correspond to "Data Transmission".

        1 Reply Last reply
        0
        • hskoglundH Offline
          hskoglundH Offline
          hskoglund
          wrote on last edited by
          #11

          That descriptor value "e68584e685b4e590a0e685b2e78daee6a5ade78db3e6bda9" is missing the a final "6e" and that's why you only get "Data Transmissio".
          The function that gives you those descriptor values has a bug: there is a 50% chance it will throw away the last character :-(
          If you do not have access to that function so you can fix the bug, maybe you can use a spelling checker to complete the sentence.

          S 1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #12

            You should create a bug report about this. Looks like the decoding within qlowenergycontroller_winrt.cpp is wrong / buggy. But I can't see where exactly.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            0
            • hskoglundH Offline
              hskoglundH Offline
              hskoglund
              wrote on last edited by
              #13

              (Didn't know the bug was in Qt)

              Inside qlowenergycontroller_winrt.cpp there is special case for handling buffers of the type QBluetoothUuid::DescriptorType::CharacteristicUserDescription, by setting the boolean isWCharString to true, which enables this "easy to understand :-)" code:

                  if (isWCharString) {
                      QString valueString = QString::fromUtf16(reinterpret_cast<char16_t *>(data)).left(size / 2);
                      return valueString.toUtf8();
                  }
              

              however Microsoft's documentation says
              ..
              CharacteristicUserDescription:
              The characteristic value contains a UTF-8 string of variable size that is a user textual description
              ...

              So probably the bug is that there is no WCharString in there to reinterpret_cast on..
              .

              1 Reply Last reply
              0
              • hskoglundH Offline
                hskoglundH Offline
                hskoglund
                wrote on last edited by
                #14

                Aha, I think I just spotted the bug, at the end of this line (from prev. post):
                QString valueString = QString::fromUtf16(reinterpret_cast<char16_t *>(data)).left(size / 2);
                size / 2 ---> this is what causes the loss of the last character when the text has an odd number of characters

                S 1 Reply Last reply
                1
                • hskoglundH hskoglund

                  Aha, I think I just spotted the bug, at the end of this line (from prev. post):
                  QString valueString = QString::fromUtf16(reinterpret_cast<char16_t *>(data)).left(size / 2);
                  size / 2 ---> this is what causes the loss of the last character when the text has an odd number of characters

                  S Offline
                  S Offline
                  swjqq
                  wrote on last edited by swjqq
                  #15

                  @hskoglund Thank you for your reply. I think what you said is correct. I tried making the following modifications to the byteArrayFromBuffer function and found that I could correctly retrieve the value of CharacteristicUserDescription without needing to use the getUserDescriptionOnWindows function.

                      if (isWCharString) {
                          // QString valueString = QString::fromUtf16(reinterpret_cast<char16_t *>(data)).left(size / 2);
                          // return valueString.toUtf8();
                          return QByteArray(data, size);
                      }
                  

                  The new getName function in the characteristicinfo.cpp:

                  QString CharacteristicInfo::getName() const
                  {
                      //! [les-get-descriptors]
                      QString name = m_characteristic.name();
                      if (!name.isEmpty())
                          return name;
                  
                      // find descriptor with CharacteristicUserDescription
                      const QList<QLowEnergyDescriptor> descriptors = m_characteristic.descriptors();
                      for (const QLowEnergyDescriptor &descriptor : descriptors) {
                          if (descriptor.type() == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) {
                              name = descriptor.value();
                              // qDebug() << "original: " <<descriptor.value();
                              // name = getUserDescriptionOnWindows(descriptor.value());
                              // qDebug() << descriptor.value().toHex('-');
                              // qDebug() << "converted: "  << name;
                              break;
                          }
                      }
                      //! [les-get-descriptors]
                  
                      if (name.isEmpty())
                          name = u"Unknown"_s;
                  
                      return name;
                  }
                  

                  20cf1ae1-9f79-4146-8e44-8224cb82135e-image.png

                  S 1 Reply Last reply
                  0
                  • hskoglundH Offline
                    hskoglundH Offline
                    hskoglund
                    wrote on last edited by
                    #16

                    Glad to hear it worked out for you.
                    Maybe if you have time you could try what @Christian-Ehrlicher suggested: file a Qt bug report, something like this:
                    "Qt bluetooth qlowenergycontroller_winrt.cpp incorrectly assumes CharacteristicUserDescription returns UTF16 when it actually returns UTF8"

                    S 1 Reply Last reply
                    0
                    • hskoglundH hskoglund

                      That descriptor value "e68584e685b4e590a0e685b2e78daee6a5ade78db3e6bda9" is missing the a final "6e" and that's why you only get "Data Transmissio".
                      The function that gives you those descriptor values has a bug: there is a 50% chance it will throw away the last character :-(
                      If you do not have access to that function so you can fix the bug, maybe you can use a spelling checker to complete the sentence.

                      S Offline
                      S Offline
                      swjqq
                      wrote on last edited by
                      #17

                      @hskoglund Regarding the spelling checker, could you provide a simple example or reference link?

                      @hskoglund said in How to solve the problem of garbled characters in characteristic names for lowenergyscanner on the Windows platform?:

                      maybe you can use a spelling checker to complete the sentence.

                      1 Reply Last reply
                      0
                      • hskoglundH hskoglund

                        Glad to hear it worked out for you.
                        Maybe if you have time you could try what @Christian-Ehrlicher suggested: file a Qt bug report, something like this:
                        "Qt bluetooth qlowenergycontroller_winrt.cpp incorrectly assumes CharacteristicUserDescription returns UTF16 when it actually returns UTF8"

                        S Offline
                        S Offline
                        swjqq
                        wrote on last edited by
                        #18

                        @hskoglund Thank you again for your help. I have created a bug report for this issue: https://bugreports.qt.io/browse/QTBUG-132202.

                        1 Reply Last reply
                        0
                        • S swjqq

                          @hskoglund Thank you for your reply. I think what you said is correct. I tried making the following modifications to the byteArrayFromBuffer function and found that I could correctly retrieve the value of CharacteristicUserDescription without needing to use the getUserDescriptionOnWindows function.

                              if (isWCharString) {
                                  // QString valueString = QString::fromUtf16(reinterpret_cast<char16_t *>(data)).left(size / 2);
                                  // return valueString.toUtf8();
                                  return QByteArray(data, size);
                              }
                          

                          The new getName function in the characteristicinfo.cpp:

                          QString CharacteristicInfo::getName() const
                          {
                              //! [les-get-descriptors]
                              QString name = m_characteristic.name();
                              if (!name.isEmpty())
                                  return name;
                          
                              // find descriptor with CharacteristicUserDescription
                              const QList<QLowEnergyDescriptor> descriptors = m_characteristic.descriptors();
                              for (const QLowEnergyDescriptor &descriptor : descriptors) {
                                  if (descriptor.type() == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) {
                                      name = descriptor.value();
                                      // qDebug() << "original: " <<descriptor.value();
                                      // name = getUserDescriptionOnWindows(descriptor.value());
                                      // qDebug() << descriptor.value().toHex('-');
                                      // qDebug() << "converted: "  << name;
                                      break;
                                  }
                              }
                              //! [les-get-descriptors]
                          
                              if (name.isEmpty())
                                  name = u"Unknown"_s;
                          
                              return name;
                          }
                          

                          20cf1ae1-9f79-4146-8e44-8224cb82135e-image.png

                          S Offline
                          S Offline
                          swjqq
                          wrote on last edited by
                          #19

                          @swjqq To clarify, there's no need to modify the byteArrayFromBuffer function directly. Instead, the following changes should be made to the QWinRTLowEnergyServiceHandler::obtainCharList function and the QLowEnergyControllerPrivateWinRT::readDescriptorHelper function in the qlowenergycontroller_winrt.cpp file (both of which call byteArrayFromGattResult, which in turn calls byteArrayFromBuffer):

                                  if (descData.uuid == QBluetoothUuid::DescriptorType::CharacteristicUserDescription)
                                      // descData.value = byteArrayFromGattResult(descriptorValue, true);
                                      descData.value = byteArrayFromGattResult(descriptorValue, false);
                                  else
                                      descData.value = byteArrayFromGattResult(descriptorValue);
                          
                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved