Skip to content

Blog

Converting a QByteArray into an Unsigned Integer

My program received messages from a network as an array of bytes. The sender of the messages encoded integers in Big Endian format. So, the hex number 0x1540 arrived in the sequence [0x15, 0x40]. I wrote the following function, which converts such a byte array of at most four bytes into a 32-bit unsigned integer. The function converts the sequence [0x15, 0x40] into the hex number 0x1540.

quint32 byteArrayToUint32(const QByteArray &bytes)
{
    auto count = bytes.size();
    if (count == 0 || count > 4) {
        return 0;
    }
    quint32 number = 0U;
    for (int i = 0; i < count; ++i) {
        auto b = static_cast<quint32>(bytes[count - 1 - i]);
        number += static_cast<quint32>(b << (8 * i));
    }
    return number;
}

Of course, I also wrote a unit test.

void TestByteArrayToUint32::testByteArrayToUint32()
{
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("9020562f")), 0x9020562fU);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("314922")), 0x314922U);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("1540")), 0x1540U);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("38")), 0x38U);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("")), 0x0U);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("559020562f")), 0x0U);
}

All QCOMPARE checks passed. All seemed fine. After using my function for a (short) while, a test didn't want to pass. I tracked the problem down to my function. Converting the byte array [0x01, 0x80] yielded the result 0x80.

Can you spot the bug in my code - and in my test?
Read More »Converting a QByteArray into an Unsigned Integer

Connectivity Solutions Will Not Help with Autonomous Farming

Over the last two years, agricultural OEMs have been in a rush to get data from their machines to their cloud servers. Claas uses Proemion’s connectivity solution. Agco, Grimme, Krone and a few others bet on AgriRouter running on SAP’s cloud servers. Holmer seems to favour Bosch’s IoT suite. All these solutions have one thing in common: They transfer little data, typically less than 50 data points per second. They top out at 100 data points. They are good for task or order management, asset tracking, fleet management, monitoring of machine health and remote diagnosis.

At least some of these companies seem to think that these connectivity solutions will help them with driver-less or autonomous farming like harvesting, seeding, spraying or fertilising. The wishful thinking would go like this.

The farm machines transfer data to the cloud. The data is used to train machine learning algorithms on extremely powerful compute servers. The model, the result of the learning process, automagically detects whether grains are dirty, maize leaves are dry or the heads of sugar beets are chopped off. Typically, this model runs in the cloud as well, because it requires more compute power than is available on the farm machine or because it adapts to new conditions and self-optimises by continuous learning. This is the way how voice assistants like Alexa and Siri understand spoken language or how medical software recognises cancer cells in MRT scans.

This approach does not work for farm machines. Here is why and what we can do about it.
Read More »Connectivity Solutions Will Not Help with Autonomous Farming

Agritechnica 2017: What’s New for Terminals?

Agritechnica 2017 was my third visit after 2013 and 2015. My focus was on terminals (display computers) as usual.

The standard terminal of 2017 is powered by a quad-core NXP i.MX6 processor (32-bit ARM Cortex-A9 with ARMv7a architecture) and has an HD 12-inch multi-touch display (resolution: 1280×800, format: 16:10). The new ISOBUS terminal CCI 1200 manufactured by CrossControl is the prime example.

In 2013, there were only terminals with single-core Cortex-A8 processors (NXP i.MX53). In 2015, there was only the odd prototype terminal with a quad-core i.MX6 in 2015 (from Grammer Belgium) but no production-quality ones. In 2017, most terminals sport a quad-core i.MX6 (Cortex-A9) processor. The processing power of terminals increases very, very slowly.

Compare this to a typical processor used in today’s in-vehicle infotainment systems. For example, the Renesas R-Car M3 sports two Cortex-A57 and four Cortex-A53 cores (all 64-bit), which has the performance of low-end to mid-range desktop PCs. Agricultural terminals need this procesing power as well, if the agricultural industry is serious about autonomous seeding, spraying and harvesting.

CLAAS demonstrated a first step into this direction. A camera is trained on the crop flow. An image recognition software (most likely using machine learning) detects whether the grains are too dirty and whether there are foreign particles between the grains. The future will see more and more such software to deduce actions from sensor data.

These expensive computations must be performed onboard the machine, because the Internet connection is not good enough on the field to send the data to powerful servers and to perform the computations there. The most powerful computer on the machine is typically the terminal. Current terminals are not powerful enough for these computations.

One terminal stands out from the uniform, slightly boring bulk of 12-inch, 1280×800 and quad-core i.MX6 terminals: the PowerView 1200 from Murphy by Enovation Controls. It is powered by a dual-core Cortex-A15 and has a 12.3-inch multi-touch display with a resolution of 1280×480 (format: 8:3). The PowerView 1200 is well-suited for dashboards and can double up as a rearview mirror.

I’ll take a more detailed look at some terminals in the rest of this post. I will ignore quite a few terminals, because they don’t stand out in any way from the rest or I simply overlooked them.
Read More »Agritechnica 2017: What’s New for Terminals?

New in Qt 5.10: Dynamic Language Change in QML

My favourite new feature in Qt 5.10 is the inconspicuous function QmlEngine::retranslate(). Finally, seven years after QML’s birth, there is a Qt way to change the language of your application at runtime. There is no need for workarounds any more (see How to do dynamic translation in QML for the standard workaround).

I wrote a simple application demonstrating the new feature. If we click the British (German) flag on the right-hand side, the language of the labels on the left-hand side is changed accordingly.

How does the dynamic language change work?
Read More »New in Qt 5.10: Dynamic Language Change in QML

Pretty-Printing Output for QCOMPARE

We have created a custom class, say Person, and use it in a unit test.

void TestPerson::testEquality()
{
    Person p1("Alice", 42);
    Person p2("Bob", 37);
    QCOMPARE(p1, p2);
}

The unit test fails with this message.

FAIL!  : TestPerson::testEquality() Compared values are not the same
   Loc: [../QComparePrint/TestPerson.cpp(8)]

This message does not tell us how the two Person objects differ. We would like to see this message as we would see it for any type known to QCOMPARE.

FAIL!  : TestPerson::testEquality() Compared values are not the same
   Actual   (p1): "Person(Alice, 42)"
   Expected (p2): "Person(Bob, 37)"
   Loc: [../QComparePrint/TestPerson.cpp(16)]

How do we achieve such a pretty-printed output for QCOMPARE?
Read More »Pretty-Printing Output for QCOMPARE

Passing Enum Properties between C++ and QML

We have defined a Qt property warningLevel in the C++ class MainModel:

    Q_PROPERTY(WarningLevel::Enum warningLevel READ warningLevel
               WRITE setWarningLevel NOTIFY warningLevelChanged)

We want to use this property in QML. For example, we want to colour a rectangle according to the warningLevel:

    import com.embeddeduse.models 1.0
    // ...

    property MainModel mainModel : MainModel {}

    Rectangle {
        color: toColor(mainModel.warningLevel)
        // ...
    }

    function toColor(level) {
        switch (level) {
        case WarningLevel.Error:
            return "red"
        case WarningLevel.Warning:
            return "orange"
        case WarningLevel.Info:
            return "green"
        case WarningLevel.Debug:
            return "purple"
        default:
            return "magenta"
        }
    }

Note how we access the C++ property mainModel.warningLevel from QML to set the color of the rectangle and how we use symbolic enum constants like WarningLevel.Info in the function toColor().

It is similarly easy to use a list of the symbolic enum constants as the model of a Repeater and to assign the warning level by the user to the property mainModel.warningLevel in the onReleased handler of a MouseArea.

    Repeater {
        model: [WarningLevel.Error, WarningLevel.Warning, WarningLevel.Info,
            WarningLevel.Debug]
        Rectangle {
            color: toColor(modelData)
            // ...
            MouseArea {
                anchors.fill: parent
                onReleased: mainModel.warningLevel = modelData
            }
        }
    }

I’ll show you in the rest of this post how to write your C++ code so that you can use a C++ property of enum type easily in QML.
Read More »Passing Enum Properties between C++ and QML