Recently, I am working on car-to-X communication and using two On-Board-Units (OBU). It's possible to read and monitor the GPS data on both modules with gpsd, gpsd clients and also I'm able to measure the network performance with iPerf. To do that one device act as a server and other one act as client. Now, I would like to connect those two devices with two different laptops and measure the network performance as well as read the GPS data outside of the OBUs. Also I need to synchronize between GPS data and iPerf output so that I can detect TPV (time, position, velocity) wise throughput, latency etc. Now I need to synchronize GPS and iPerf data together so that I can store them as a log-file and process the data later. Is there anyone can help me with the idea how to do that. I have already tried one solution which is - Time stamp both GPS & iperf data, and store to logs. I have 2nd solution which is to send GPS data as iperf payload, using the -f option. I would like to try the 2nd one but not exactly sure how to do that. Help from anyone is truly appreciated.
1 Answers
You don't mention which scripting languages or programming languages you are familiar with. There are many ways to do it, from a simple python or bash script, to more complex C++ programs.
I didn't want to write an entire demo software for you not knowing specifically what you were looking for, but I was able to take parts of this sample c++ gpsd client and modify it so it also runs iperf and output as csv (which you can then pipe to a logger or however you want to do it).
#include <iostream>
#include <iomanip>
#include <ctime>
#include <sstream>
#include <memory>
#include <libgpsmm.h>
std::string exec(const char *cmd) {
std::array<char, 128> buffer;
std::string result;
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
if (!pipe) throw std::runtime_error("popen() failed!");
while (!feof(pipe.get())) {
if (fgets(buffer.data(), 128, pipe.get()) != NULL) result += buffer.data();
}
return result;
}
int main(int argc, char **argv)
{
if (argc < 2) {
std::cout << "Please execute command with a remote iperf server. Exiting." <<
"\n";
return 1;
}
gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT);
if (gps_rec.stream(WATCH_ENABLE | WATCH_JSON) == NULL) {
std::cerr << "No GPSD running.\n";
return 1;
}
for (;;) {
// run iperf and get output in a string (note: needs error checking!)
// the cut portion is there to remove the first column from the csv output
// which is time, as we'll take the gps time instead.
std::stringstream iperfCmd;
iperfCmd << "iperf -c " << argv[1] << " -ey C | cut -d , -f 2-9";
const std::string& tmp = iperfCmd.str();
const char *iperfCmdArr = tmp.c_str();
std::string iperfOutput = exec(iperfCmdArr);
struct gps_data_t *newdata;
if (!gps_rec.waiting(50000000)) continue;
if ((newdata = gps_rec.read()) == NULL) {
std::cerr << "Read error.\n";
return 1;
} else {
while (((newdata = gps_rec.read()) == NULL) ||
(newdata->fix.mode < 1)) {
// Do nothing; don't want to output wrong initial time
}
timestamp_t ts = newdata->fix.time;
double latitude = newdata->fix.latitude;
double longitude = newdata->fix.longitude;
// convert GPSD's timestamp_t into time_t
time_t seconds;
seconds = (time_t)ts;
auto tm = *std::localtime(&seconds);
std::ostringstream oss;
oss << std::put_time(&tm, "%d-%m-%Y %H:%M:%S");
auto time_str = oss.str();
// set decimal precision
std::cout.precision(6);
std::cout.setf(std::ios::fixed, std::ios::floatfield);
std::cout << time_str << "," <<
latitude << "," <<
longitude << "," << iperfOutput;
// uncomment below to break out of for loop (will only output 1 iteration)
// return 0;
}
}
return 0;
}
You can modify the iperfCmd variable to change the iperf command. For example, you can change it to "-rey C" if you want to run a bidirectional test. Look at iperf --help for what you need, but you'll have to keep the "-y C" flag for CSV output. If you have gpsd (and sometimes the necessary libgps-dev libraries), you can compile the code as such:
g++ -Wall -std=c++14 -pedantic $(pkg-config --cflags --libs libgps) gpsd-iperf-example.cpp -o gpsd-iperf-example
Then just run (Press CTRL-C to stop):
gpsd-iperf-example servername
Assuming gpsd is working properly, and you are using iperf v2, the output should look like this:
07-05-2017 19:05:10,45.3XXXXX,-75.8XXXXX,192.168.2.36,40466,192.168.2.28,5001,4,0.0-10.0,286785536,228615722
07-05-2017 19:05:11,45.3XXXXX,-75.8XXXXX,192.168.2.36,40468,192.168.2.28,5001,4,0.0-10.0,328859648,261792317
07-05-2017 19:05:12,45.3XXXXX,-75.8XXXXX,192.168.2.36,40470,192.168.2.28,5001,4,0.0-10.0,293601280,234307789
Which you can further parse or simply adjust the c++ program. Not sure if this was what you were looking for, but again, many ways to do it, just look around for snippets of code and adjust to your needs.

- 193
- 3
- 13