Building My Own Telemetry System for F1 2017 (Game) Using Golang, InfluxDB and Grafana.
Some day ago, I discovered a feature in my F1 2017 Game(PS4), navigating in a menu I sow an option called UDP Telemetry Settings with many network configurations, as shown below.
After, I searched at Google about that and I found a blog post at Codemasters Blog with the specification about that UDP package. Yes, that is a great example of poor documentation, only a Struct scheme with wrong information's fixed in commentaries below of the post. The struct is shown below.
// Packet size – 1289 bytes
float m_x; // World space position
float m_y; // World space position
float m_z; // World space position
float m_speed; // Speed of car in MPH //First mistake, the speed is measured in m/s
See the full struct at the blog post : http://forums.codemasters.com/discussion/53139/f1-2017-d-box-and-udp-output-specification
After I knew how to work that feature I created a simple go program for reading the packages and printing the speed of the car. In my program I had to read some bytes from the UDP payload, Obs: all Floats fields have 4 bytes and Int’s values have a byte.
Yes, Only seeing speed in a terminal is not useful, I needed find a good way to see those information's and I thought in a good tool used for monitoring servers and applications, If you thought about Grafana you are right.
Grafana can make Beautiful dashboards with a lot of graphs, It can manipulate data and it’s perfect to monitoring things in real time like software applications but now a will test with a Formula 1 car ;).
The first thing that I did was to understand how I can send data to Grafana. In my search I found many Data Sources but only 10 oficial Data Sources, In those Data Sources I chose the InfluxDB because it’s fast, easy and I don’t need use a collector for sending my data to DB.
With those 3 tools I did my own telemetry system.
First Step: Make a Collector
First, I need write a collector who will collect data in UDP packages and after will send to InfluxDB, Is easy speak this but I found same issues for building that.
The first problem we need solve is how to read UDP packages, It’s simple in Go, we can use the package net, in this package have the function ListUDP witch open a UDP connection, after that we need build a loop and use the Read function of the connection for reading the bytes of UDP payload. Obs: I created a buffer with 1289 bytes because is the size described in F1 documentation.
After read the UDP package we need converter to a struct witch describe the information's about the car or race, So the next step is write structs, we have 2 struct, the first describe you and the second describe other players.
Now with the complete structs We need decode the binary package in a TelemetryPack, It’s easy too. We can use the ‘encode/binary’ package of Go. In that have a function named Read who transform the binary in a struct. We can just write a New function in telemetry.go file.
After that we need write a simple client for sending the struct in InfluxDB, believe It’s easy too.
I need give a few explications about that code, first I created a UDPClient who will send the data to InfluxDB, after I initialized a loop with channel and created a BatchPoints, BatchPoints is an interface into a batched grouping of points to write into InfluxDB together but in this exemple we will write one per one because we need more speed in the graph view.
After created a BatchPoints I created Point who represents a single data point, Lastly I sent the BatchPoints to server with write function.
At this moment we have three different parts of our collector, an UDP receiver, the Struct and an InfluxDB client. Now we need to make it all work together, first we will do the receiver to transform a UDP pack to a TelemetryPack and make a Point with that.
For that, We need convert the struct to a map of strings, I wrote a special function using the package reflect for that.
Now miss simple things, We need call that function in client.NewPoint
And for finish, we need send the struct for our client, for that I initialized 5 go routines with influxDBSender and in loop I created and sent a Point struct to channel.
For seeing all code go to my github project.
Second Step: Install The InfluxDB
Now we need install a InfluxDB server in a host, In this post I’am using a Raspberry pi 3 b+ as host for my Grafana and InfluxDB. It’s very easy install that Raspbian, We need add the InfluxData repository at apt and after run a apt-get , we can do this with these commands:
If you want know more about that follow the oficial documentation at https://docs.influxdata.com/influxdb/v1.5/introduction/installation .
After that we have a InfluxDB server running in our host, but it don’t allow UDP packages yet, for configure that we need make some changes at influxdb.conf, only change the UDP enabled for true, uncomment bind-address and put database line with name of our database (“f1”).
enabled = true
bind-address = ":8089"
database = "f1"
Now Enough restart the server and create the f1 database with these commands.
>> CREATE DATABASE f1
Third Step: Install The Grafana
Simple, follow that page http://docs.grafana.org/installation/debian/ .
I installed with these commands:
sudo dpkg -i grafana_5.2.1_armhf.deb
sudo service grafana-server start
Is it, if you try access the port 3000 with user admin/admin you can acesse the Grafana.
First thing to do is configure the data source.
Fourth Step: Configure Our First Dashboard
The InfluxDB only create the schema after receive the first message, we need try all for that, play the F1 game and run our Golang program.
Now we have all done to make our first dashbord.
It’s simple, click in create a new dashboard -> add panel-> graph -> edit, after just add that configuration:
And now, we have our first dash with a speed graph. Enjoy it.
Now just study about Grafana and make you dashboad.
In that post I showed to you how I can make my own telemetry system, it’s the basic, if you want more see my github repo.
If you think it ‘s useless. You are correct. But I improve my english writing this post, I learned about Grafana and Influxdb and It’s first time I use UDP and Reflect in Go. All of it in a cool project(for me).