传感器

传感器示例演示了两个应用程序如何通过使用UDP套接字发送protobuf消息来通信。

传感器示例包含以下组件

  • 从protobuf模式生成,使用qt_add_protobuf调用生成的protobuf_sensors库。
  • 模拟简单传感器行为的protobuf_sensor_emulator应用程序。
  • 显示UDP套接字中传感器数据的protobuf_sensors_client应用程序。

客户端应用程序绑定到本地的UDP端口65500,等待来自仿真应用程序的数据。

使用仿真应用程序更改传感器数据的值,并将数据发送到客户端的UDP端口。

应用程序使用从protobuf_sensors库生成的消息进行通信。该库从.proto文件中描述的protobuf模式生成。

qt_add_protobuf(protobuf_sensors
    PROTO_FILES
        sensors.proto
        tlv.proto
)

第一个文件描述了包装传感器数据的类型-长度-值的消息

package qt.examples.sensors.tlv;

enum MessageType {
    Coordinates = 0;
    Temperature = 1;
    WarningNotification = 2;
}

// Protobuf messages imply inline data size.
message TlvMessage {
    MessageType type = 1;
    bytes value = 2;
}

第二个.proto文件包含传感器消息的描述

package qt.examples.sensors;

message Coordinates {
    double longitude = 1;
    double latitude = 2;
    double altitude = 3;
}

message Temperature {
    enum Unit {
        Farenheit = 0;
        Celsius = 1;
    }
    sint32 value = 1;
    Unit units = 2;
}

message WarningNotification {
    string text = 1;
}

消息使用您在客户端中实例化的QProtobufSerializer进行序列化

class SensorClient : public QObject
{
    Q_OBJECT
...
private:
    QUdpSocket m_client;
    QProtobufSerializer m_serializer;
};

和仿真器

class SensorEmulator : public QObject
{
    Q_OBJECT
...
    QUdpSocket m_socket;
    QProtobufSerializer m_serializer;
};

在仿真应用程序中点击发送按钮后,从QLineEdit域转换的数据从字符串格式转换为消息字段特定的格式,例如,双精度对于坐标消息的字段

    QObject::connect(ui->sendCoordinates, &QPushButton::clicked, this, [this]() {
        qt::examples::sensors::Coordinates coord;
        coord.setLatitude(ui->latitudeValue->text().toDouble());
        coord.setLongitude(ui->longitudeValue->text().toDouble());
        coord.setAltitude(ui->altitudeValue->text().toDouble());
        emit coordinatesUpdated(coord);
    });

然后,具有所有字段的消息被序列化并包装在类型-长度-值消息中

    Q_ASSERT(serializer != nullptr);
    qt::examples::sensors::tlv::TlvMessage msg;
    msg.setType(type);
    msg.setValue(data);
    return msg.serialize(serializer);

客户端对接收到的数据报执行相反的操作。首先将类型-长度-值消息从数据报数据反序列化

        const auto datagram = m_client.receiveDatagram();
        qt::examples::sensors::tlv::TlvMessage msg;
        msg.deserialize(&m_serializer, datagram.data());
        if (m_serializer.deserializationError()
                != QAbstractProtobufSerializer::NoError) {
            qWarning().nospace() << "Unable to deserialize datagram ("
                       << m_serializer.deserializationError() << ")"
                       << m_serializer.deserializationErrorString();
            continue;
        }

然后将类型-长度-值消息反序列化到传感器消息

            qt::examples::sensors::Coordinates coord;
            coord.deserialize(&m_serializer, msg.value());
            emit coordinatesUpdated(coord);
            break;

最后,将其转换为显示给用户

    ui->latitudeValue->setText(QString::number(coord.latitude(), 'f', 7));
    ui->longitudeValue->setText(QString::number(coord.longitude(), 'f', 7));
    ui->altitudeValue->setText(QString::number(coord.altitude(), 'f', 7));

注意:在运行示例之前,请确保您的操作系统允许在UDP端口65500上绑定并发送数据。

示例项目 @ code.qt.io

© 2024 Qt公司有限公司。此处包含的文档贡献是各自所有者的版权。此处提供的文档是根据自由软件基金会发布的GNU自由文档许可协议版本1.3的条款提供的。Qt及其相关商标是芬兰的Qt公司及其在全球的子公司和关联公司的注册商标。所有其他商标均为其各自所有者的财产。