Send Google Protocol Buffer With ZeroMQ Across NetWork to Raspberry Pi

Send Google Protocol Buffer With ZeroMQ Across NetWork to Raspberry Pi.md

Send Google Protocol Buffer With ZeroMQ Across NetWork to Raspberry Pi

1. Overview

When we want to send message across network with fast respond, We know ZeroMQ is one of the best choices. While sending across network and taking care of your message can be a big headache. Our own message can be hard to maintain with little flexibility. That’s where you need to consider a protocol to handler your growing messages. So now we use Google Protocol Buffer which is free and efficient to handle our protocol.

Ubuntu PC ----ZeroMQ Message With Protocol Buffer----> Raspberry Pi

You can check out the entire project from my GitHub.

2. Installation

We need

  1. Qt Creator at Ubuntu PC
  2. Python at Raspberry Pi
  3. Both Ubuntu PC and Raspberry Pi are in same network
  4. Protocol Buffer Library at both Ubuntu PC and Raspberry Pi
  • You can refer to this link for installation of Protocol Buffer
  • You can refer to this link to install Python version of ZeroMQ
  • You can refer to this link to install C++ version of ZeroMQ

Note: Installation instructions can be applied to both Ubuntu and Raspberry Pi. They are basically same since they are both *nix system.

3. Implementation

Since the project is hosted on GitHub, I will just explain necessary implementation.

3.1 Both System

In order to exchange message between Ubuntu and Raspberry, Both system must have protocol message file (.proto) in their own system.

We will decipher the following message protocol as followed. We will be sending as message as addressBook. In the adressBook, there can be many Person as signified by repeated keyword. Similarly, Person must have name as indicated by required and email is optional for a Person since the keyword is optional. The " = 1", " = 2" markers on each element identify the unique tag that field uses in the binary encoding.

package message;
message Person {
    required string name = 1;
    optional string email = 2;
}
message AddressBook{
    repeated Person person = 1;
}

Note: .proto file must be compiled before it can be used in the program. You can looked how it can be compiled at .pro file and python in the project.

You can manually compile the .proto file also. Just use

For Python

protoc message.proto --python_out='.' 

For C++

protoc message.proto --cpp_out='.' 

3.2 Raspberry Pi

We need to make sure Python, ZeroMQ Python and Protocol Buffer are already installed. Writing program in Python can be very short so it’s good to test in server first.

Here we will compile message.proto file and generate message_pb2.py file. We need to import this ‘message_pb2.py’ file in the program

<...omitted...>
    if (os.path.exists("message_pb2.py") == False):
        subprocess.call("protoc message.proto --python_out='.'", shell=True)
<...omitted...>

Then we will setup ZeroMQ and bind to the Raspberry Pi localhost IP address.

<...omitted...>
    context = zmq.Context()
    socket = context.socket(zmq.REP)
    socket.bind("tcp://*:5556")
<...omitted...>

Now we will parse String from the message that sent from client.

<...omitted...>
    message = socket.recv()
    addressBook = message_pb2.AddressBook()
    addressBook.ParseFromString(message)
<...omitted...>

The complete program of this file can be read from here.

3.3 Ubuntu

In Ubuntu system, we will be using Qt, ZeroMQ and Protocol Buffer so make sure they are already installed. Since we will be using C++, there are more setup required to make it works.

In order to compile *.proto file, we use *.pri file in Qt to compile and generate message.pb.h. Honestly I don’t write the ‘.pri’ file so I can’t explain it. Basically, it generates ‘.ph.h’ and ‘.ph.cc’ files at its own directory. You can read more detail from here.

At Client.cpp, we will setup ZeroMQ and register the ZeroMQ slot.

<...omitted...>
    socket = mContext->createSocket(ZMQSocket::TYP_REQ, this);
    QObject::connect(socket, SIGNAL(messageReceived(QList<QByteArray>)), SLOT(onReceivedFromZqmlToConsumeData(QList<QByteArray>)));
    mContext->start();
<...omitted...>

Still in Client.cpp, we will setup network and connect to Raspberry Pi Server.

<...omitted...>
    QString raspberryPiAddress = "192.168.1.104";
    _initilizeConnection();

    const int portNumber = 5556;
    QString stringPortNumber = QString::number(portNumber);

    QString ipAddressString = "tcp://" + raspberryPiAddress.toLocal8Bit() + ":" +stringPortNumber.toLocal8Bit();
    QByteArray qByteArray = ipAddressString.toLatin1();
    const char *charIpAddress = qByteArray.data();

    socket->connectTo(charIpAddress);
<...omitted...>

While still Client.cpp, we add two Person to Address Book, serialize the data and send to Raspberry Pi server.

<...omitted...>
    message::AddressBook addressBook;

    message::Person *john = addressBook.add_person();
    john->set_name("John ");
    john->set_email("john@abc.com");
    
    message::Person *drake = addressBook.add_person();
    drake->set_name("Drake");
    drake->set_email("drake@abc.com");

    qDebug() << "Number of Person in Address Book: " << addressBook.person_size();
    std::string msg_str;
    addressBook.SerializeToString(&msg_str);
    _sendStringToServer(msg_str.c_str());
<...omitted...>

The complete program of this file can be read from here.

4. Testing Result

We should first run the server program at Raspberry Pi. After that, we will run Qt program. Both of program will generate necessary compiled files from *.proto file.

The output result at Qt client will be like this.

Number of Person in Address Book:  2
Hello  John 
Your email will be  john@abc.com
Hello  Drake
Your email will be  drake@abc.com
Received Msg from Server is  "Hello Client"

And the server side will be displayed like the following.

Number of Person in Address Book:  2
Hello  John 
Your email will be  john@abc.com
Hello  Drake
Your email will be  drake@abc.com
Received Msg from Server is  "Hello Client"

5. Reference

  1. Protocol Buffer Developer Guide
  2. Using Google Protocol Buffers With qmake

No comments:

Post a Comment