TTN Mapper Integration (TTN console)

After watching the keynote by @jpmeijers during the TTN Conference, I started playing with the new TTN Mapper integration for TTN nodes.
I started with the setup that I used a while back using a LoPy with an external GPS receiver. I had to update the code (will update the github code today) so that not just the longitude and latitude but also the elevation and the HDOP are being transmitted and turned into the appropriate JSON object by the payload format function.

After that, it was just a matter of adding the integration (it just needed my mail address) and the tracker was displayed on the map:

That was last night, so I haven’t taken the node out for a ride yet, but I thought I’d post some first questions / remarks here both for @jpmeijers and the team at TTN to get things going.

First of all: Nice work! This makes mapping easier if you just want to take along a single node to do the mapping without the additional need of a smartphone, running an app, using GPS and a data connection. If you’re on the road in a car a lot, you could simply take the node with you every day and forget about it.

Flooding risk of servers?
The automatic nature of it also worried me a bit. I’m still optimizing my own code to only send valid data, so for example not when the GPS doesn’t have a fix yet (the external GPS takes a lot longer than my smartphone to get a fix), but this node will send data to the TTN mapper service whenever it has power, it is less of a deliberate action then with the app. I hope the TTN mapper servers can handle that.

Interval of measurements
I didn’t really know what is considered a advised interval for measurements. The TTN network has FUP policies, not enforced at the moment and with allowance for higher use during tests/experiments, but is a fixed TTN Mapper node in a car still an experiment?

Instant feedback
One thing that I do like about the smartphone app approach is that you get instant feedback. Many of us have probably been walking around the sound switched on and can remember the thrill of hearing the sound of a package being received and mapped. (or am I just the only one?)
With this direct integration, I no longer get that instant feedback and distance measurement.
I know I could create my own MQTT integration, could probably figure out the distance measurements also, but that would mean a lot of individual work. Maybe (just thinking out loud) the app could have a feature where I subscribe to a node just like now, but in a purely “listening” mode, where I get the feedback without the GPS of my smartphone being used?

ON/OFF switch
I think the integration could do with an “enable/disable” option in the console allowing someone to switch it off temporarily during testing without having tot remove the integration completely. I know the setup is quick and easy (just add mail address), but deleting feels much more final then disabling it.

How to choose a different FPORT?
I haven’t been able to figure out how to set the FPORT in microPython yet, being able to filter out which packages get sent to TTN Mapper would enable me to use the node for more than just mapping while sending only the mapping data. Maybe @jmarcelino knows?

Other implementations?
I’m using microPython and an external GPS on the LoPy, I’ll document the setup once I’m sort of sure I haven’t done really stupid things. I’d be interested to hear/read about other implementations. I might be useful to get some sort of default code base in particular with regard to filtering out bad data before it is being sent to the TTN mapper servers.


Very nice! Thanks so much for posting this, I’m still processing everything from the TTN conference :slight_smile:

To set FPORT on the LoPy you bind the socket to the port you need, like:



Hi Pierre. Nice to hear someone appreciates the work we are doing!

Q: Flooding risk of servers?
A: As long as you keep to the 1% duty cycle, and keep the FUP in mind, you won’t hurt the servers at all. Regarding the validity of data - TTN Mapper has some validation and filtering it applies to all received measurement point. That is also the reason why the HDOP value is requested (not required).

Q: Interval of measurements
A: I think the best approach here would to to use “smart beaconing”, where the interval of packets is determined by the speed you are moving at. I map at just slower than 1% duty cycle, but normally I don’t map for more than an hour at a time. So just a trade off. If the gateway is run by you, and there isn’t much other LoRa traffic in the air, I don’t see why you can’t just map at 1% duty cycle. I would however recommend sticking to SF7 then.

Q: Instant feedback
A: You can still use the app as well. Using the app together with a gps based node that has the integration switched on will mean we have double the amount of data, which is not a problem. The two systems will provide slightly different coordinates - the gps node will send the location where you were when you started sending the packet, and the phone will use the location you are at after the packet was successfully sent. This is sometimes useful to see how far you moved while the packet was sent. You can also disable uploading packets to the TTN Mapper server in the settings of the phone app.

Q: ON/OFF switch
A: I think for consistency with other integrations this shouldn’t be done. Perhaps log to an experiment if you don’t want the data appearing on the main map.

Q: Different FPort
A: Not sure how this is done on the LoPy.

Q: Other implementations.
A: Some examples I wrote a while back can be found at:
Sodaq One:
Things Uno with GPS shield:


Thanks for the responses, good to hear that using app + node together is no problem.

Ok, had to look up what that means, if I use the spreadsheet linked here and given that I only need 9 bytes for the data in the package, I could send 22 messages per hour (or one every 6 seconds)

I’ll have a look at the other examples to see if my microPython code is consistent with them.

Just checking if I am reading the code correctly:

For the code using the Sodaq One, in the loop() I don’t see anything that makes the node wait between two transmissions. Isn’t this node sending data to TTN as often as possible?

The code using the Things Uno with GPS shield tries to send every 1 second?

if (gps.location.age() < 1000 && (millis() - last_update) >= 1000)

So, no “smart beaconing” in those two implementations yet? (or am I missing something?)

Yes you are right. Those two are really basic ones that just send as often as is allowed by the LoRaWAN protocol stack inside the RN2483 radio. Fine for a “quick test”, but not fine for long running devices.

Strangely enough I don’t seem to be able to find any smarter code than tyours. All the examples I can find on github either choose to send as often as possible, or at a fixed rate of 1-5 seconds per update.

What intelligence are you considering? I can think of distance triggering and corner pegging.

I was now thinking at different update frequencies. Something like:
0 = stationary = every 30 seconds update
1 = walking = speed <= 6 km/hour = every 20 seconds update
2 = cycling = speed > 6 and <= 30 km/hour = every 10 seconds update
3 = car / train = speed > 30 km/hour = every 5 seconds update

options selection in code (0-3), option “auto” (decide based on GPS speed) or maybe even with option to set via LoRaWAN download.

1 Like

If stationary, I don’t see a reason to send an update at all. You have one ?

One issue to be aware of when transmitting whilst mobile is signal coherency. LoRa is good when mobile and if i recall from past I think its good for up to aro 100mph/160kph (even higher?) at SF6/7 but at SF12 its much lower (combination of symbol on air time and frequency/bandwidth) at around 25mph/40kph…dont take my values as gospel please check yourselves.! :wink: The impact of this is increased BER/PER though symbols should still be captured there is a risk of drops which increases as you go beyond any coherency limit. Remember also ‘speed’ is wrt tx/rx line of propagation hence need to consider the derived/vectored portion rather than actual ground speed on a bearing. So something to bear in mind (pun intended!) when mapping at a distance (hence higher SF) or at speed :slight_smile:

One little question, in what format must be the GPS data? I have a old Garmin Geko 201 which has a RS-232 Interface and supports NMEA 0183 as output. So my idea is to combine it with a Heltec V2 ESP32 Lora Modul to have a tracker with GPS Modul. But i need to know in which format the GPS data is accepted by the TTNMapper.

Also if mapping for more than a few mins/hours of so have regard for duty cycle & FUP as both easily breached at higher SF and with these update rates…

I know from my own V1 LoRaMotes (SMTC/iMST) that the 29byte payload they generate has on air time of ~>1.6sec @ SF12…

TTN mapper expects a json object, see details at

TTNMapper recommends to use SF7, for moving nodes that is the best option. See this reply for calculations related to duty cycle and FUP.

Yes, you would ideally send the data in a as small as possible package to TTN. 9 bytes is doable for latitude + longitude + altitude + hdop
On the TTN backend side you then translate it into JSON using a Payload format function.
don’t send JSON of LoRaWAN! :slight_smile:

Appreciate that is the case, and it helps establish ‘worst case’ coverage of any given gateway but I’m also interested in deriving minimum number of economically viable gateways to cover a given area or region hence looking at any usable coverage out at SF 10, 11 & even 12. Hence using LoRaMotes vs TTN mapper for now… will likely add to the TTN Mapper community once baseline for wider coverage established in my case… :slight_smile: Meantime am following TTN Mapper progress with interest, ready…

  1. It could be that the first package is not received, then having another go after 30 seconds makes sense.
  2. No GPS data is perfect, so having multiple GPS measurements even while not physically moving gave @jpmeijers more data to work with
  3. can’t think of a real number 3, just that while debugging I’m usually not moving, so I like to be able to account for that state also. :slight_smile:

Fair enough. I’m focusing on SF7 for now, but using SF11 or SF12 would just mean changing the intervals in the code. I was planning on using variables for them also, so they could easily be changed.

Great. That sounds like a plan :slight_smile:
Besides the LoRaMotes have just taken delivery of some RAK 811 Tracker boards & sensor boards and have some RAK813/Trackers in transit so hope to start using all of them from early next month… also that’s when I will likely start contributing data to TTN Mapper. :+1: