示例:传感器

Sensors

The Sensors example shows how two applications can communicate by sending protobuf messages using UDP sockets.

Sensors示例显示了两个应用程序如何通过使用UDP套接字发送protobuf消息进行通信。

The Sensors example consists of the following components:

传感器示例由以下组件组成:

  • protobuf_sensors library that you generate from the protobuf schema using the qt_add_protobuf call.
  • ​使用qt_add_protobuf调用从protobuf模式生成的protobufsensors库。​
  • protobuf_sensor_emulator application that emulates simple sensor behavior.
  • protobuf_sensor_emulator应用程序,用于模拟简单的传感器行为。
  • protobuf_sensors_client application that displays the sensor data from the UDP socket.
  • protobuf_sensors_client应用程序,用于显示UDP套接字中的传感器数据。

The client application binds on the localhost UDP port 65500 and waits for data from the emulator application.

客户端应用程序绑定在本地主机UDP端口65500上,并等待来自模拟器应用程序的数据。

Use the emulator application to change the values of sensor data and send the data to the client's UDP port.

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

The applications use the generated messages from the protobuf_sensors library to communicate. The library is generated from the protobuf schema described in .proto files.

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

qt_add_protobuf(protobuf_sensors
    PROTO_FILES
        sensors.proto
        tlv.proto
)

The first file describes the Type-Length-Value message, that wraps the sensor data:

第一个文件描述了“类型长度值”消息,该消息封装传感器数据:

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;
}

The second .proto file contains a description of the sensor messages:

第二个.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;
}

Messages are serialized using QProtobufSerializer that you instantiate in the client:

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

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

And the emulator:

以及模拟器:

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

After you click the Send button in the emulator application, the data from QLineEdit fields is converted from string format to the message field-specific format, for example, double for the fields of the Coordinates message:

​在模拟器应用程序中单击“发送”按钮后,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);
    });

Then the message with all the fields is serialized and wrapped with the Type-Length-Value message:

然后,带有所有字段的消息被序列化,并用Type-Length-Value消息包装:

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

The client applies the reverse operations on the received datagrams. First the Type-Length-Value message is deserialized from the datagram data:

客户端对接收到的数据报应用反向操作。首先,从数据报数据中反序列化类型长度值消息:

        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;
        }

Then the Type-Length-Value message is deserialized into the sensor message:

然后,类型长度值消息被反序列化为传感器消息:

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

Finally, it is converted and displayed to the user:

最后,它被转换并显示给用户:

    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));

Note: Before running the example, make sure that your operating system allows binding on UDP port 65500 and sending the data over UDP.

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值