Skip to content

Commit 1651c13

Browse files
committed
Adds Protobuf + ZeroMQ Networking Example
See #12, #13. References: - http://api.zeromq.org/2-1:zmq-cpp
1 parent 4af23e5 commit 1651c13

File tree

4 files changed

+154
-5
lines changed

4 files changed

+154
-5
lines changed

libsweep/examples/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,17 @@ if (LIBSFML_FOUND)
2828
else()
2929
message(STATUS "SFML2 required for real-time viewer (libsfml-dev)")
3030
endif()
31+
32+
33+
# Optional Protobuf + ZeroMQ networking example
34+
find_package(Protobuf 2.4.1)
35+
pkg_check_modules(LIBZMQ libzmq)
36+
37+
if (Protobuf_FOUND AND LIBZMQ_FOUND)
38+
protobuf_generate_cpp(ProtoSources ProtoHeaders net.proto)
39+
add_executable(example-net net.cc ${ProtoSources} ${ProtoHeaders})
40+
target_link_libraries(example-net PRIVATE ${LIBSWEEP_LIBRARY} ${Protobuf_LITE_LIBRARIES} ${LIBZMQ_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
41+
target_include_directories(example-net SYSTEM PRIVATE ${LIBSWEEP_INCLUDE_DIR} ${Protobuf_INCLUDE_DIRS} ${LIBZMQ_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
42+
else()
43+
message(STATUS "Protobuf2 and ZeroMQ required for networking example (libprotobuf-dev protobuf-compiler libzmq-dev)")
44+
endif()

libsweep/examples/README.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,29 @@ To build:
1717
cmake --build .
1818
```
1919

20-
**Note:** the viewer requires SFML2 to be installed.
20+
**Note:**
21+
- The viewer requires SFML2 to be installed.
22+
- The pub-sub networking example requires Protobuf and ZeroMQ to be installed.
2123

2224

2325
```bash
24-
# run the examples
25-
./example-c
26-
./example-c++
27-
./example-viewer
26+
./example-c
27+
./example-c++
28+
```
29+
30+
Real-time viewer:
31+
32+
```bash
33+
./example-viewer
34+
```
35+
36+
Pub-Sub networking example.
37+
Start a publisher sending out full 360 degree scans via the network (localhost).
38+
Then start some subscribers connecting to the publisher.
39+
40+
```bash
41+
./example-net publisher
42+
./example-net subscriber
2843
```
2944

3045
### License

libsweep/examples/net.cc

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#include <cstdlib>
2+
#include <cstring>
3+
4+
#include <iostream>
5+
#include <iterator>
6+
#include <string>
7+
#include <vector>
8+
9+
#include <google/protobuf/stubs/common.h>
10+
#include <sweep/sweep.hpp>
11+
#include <zmq.hpp>
12+
13+
#include "net.pb.h"
14+
15+
static void usage() {
16+
std::cout << "Usage: example-net [ publisher | subscriber ]\n";
17+
std::exit(EXIT_SUCCESS);
18+
}
19+
20+
void subscriber() {
21+
zmq::context_t ctx{/*io_threads=*/1};
22+
zmq::socket_t sub{ctx, ZMQ_SUB};
23+
24+
sub.connect("tcp://127.0.0.1:5555");
25+
sub.setsockopt(ZMQ_SUBSCRIBE, "", 0);
26+
27+
std::cout << "Subscribing." << std::endl;
28+
29+
for (;;) {
30+
zmq::message_t msg;
31+
32+
if (!sub.recv(&msg))
33+
continue;
34+
35+
sweep::proto::scan in;
36+
in.ParseFromArray(msg.data(), msg.size());
37+
38+
const auto n = in.angle_size();
39+
40+
for (auto i = 0; i < n; ++i) {
41+
std::cout << "Angle: " << in.angle(i) //
42+
<< " Distance: " << in.distance(i) //
43+
<< " Signal strength: " << in.signal_strength(i) //
44+
<< std::endl;
45+
}
46+
}
47+
}
48+
49+
void publisher() try {
50+
zmq::context_t ctx{/*io_threads=*/1};
51+
zmq::socket_t pub{ctx, ZMQ_PUB};
52+
53+
pub.bind("tcp://127.0.0.1:5555");
54+
55+
sweep::sweep device;
56+
device.start_scanning();
57+
58+
std::cout << "Publishing. Each dot is a full 360 degree scan." << std::endl;
59+
60+
for (;;) {
61+
const sweep::scan scan = device.get_scan();
62+
63+
sweep::proto::scan out;
64+
65+
for (const sweep::sample& sample : scan.samples) {
66+
out.add_angle(sample.angle);
67+
out.add_distance(sample.distance);
68+
out.add_signal_strength(sample.signal_strength);
69+
}
70+
71+
auto encoded = out.SerializeAsString();
72+
73+
zmq::message_t msg{encoded.size()};
74+
std::memcpy(msg.data(), encoded.data(), encoded.size());
75+
76+
const auto ok = pub.send(msg);
77+
78+
if (ok)
79+
std::cout << "." << std::flush;
80+
}
81+
82+
device.stop_scanning();
83+
84+
} catch (const sweep::device_error& e) {
85+
std::cerr << "Error: " << e.what() << '\n';
86+
}
87+
88+
int main(int argc, char** argv) {
89+
std::vector<std::string> args{argv, argv + argc};
90+
91+
if (args.size() != 2)
92+
usage();
93+
94+
const auto isPublisher = args[1] == "publisher";
95+
const auto isSubscriber = args[1] == "subscriber";
96+
97+
if (!isPublisher && !isSubscriber)
98+
usage();
99+
100+
GOOGLE_PROTOBUF_VERIFY_VERSION;
101+
102+
struct AtExit {
103+
~AtExit() { ::google::protobuf::ShutdownProtobufLibrary(); }
104+
} sentry;
105+
106+
if (isPublisher)
107+
publisher();
108+
109+
if (isSubscriber)
110+
subscriber();
111+
}

libsweep/examples/net.proto

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package sweep.proto;
2+
3+
option optimize_for = LITE_RUNTIME;
4+
5+
message scan {
6+
repeated int32 angle = 1 [packed=true];
7+
repeated int32 distance = 2 [packed=true];
8+
repeated int32 signal_strength = 3 [packed=true];
9+
}

0 commit comments

Comments
 (0)