A while back, a friend of mine created a script called Buddy List. Running the script showed you a list of other nodes that are online at the same time as you are. This was before the Meshtastic apps had an “Online” filter.
I have a node mounted on a pegboard next to my desk that I leave there all the time. When I come home, I often grab my phone to see if any new nodes have appeared since the last time I checked. It occurred to me that a Buddy List on an ePaper display next to the node on my pegboard could highlight new nodes as well as show me which ones are currently active, without needing to take the time to connect my phone.
I'm using a Heltec V3 for this project, because it's what I had on hand. It should with any device flashed with Meshtastic firmware.
I used whatever ePaper displays I had on hand for this project, which is probably more than the average person. I initially used an InkyPHAT display from Pimoroni, which is 2.13” and, due to its aspect ratio, able to display just one column of node names. I could only fit about 12 lines on this display with the default font, which meant room for only nine nodes after the headers were included. The refresh rate of the InkyPHAT was incredible – blink and you’d miss it – but ultimately I wanted to show more than nine nodes so I couldn’t keep using it.
I upgraded to the next smallest display I had laying around: a Waveshare 2.7 inch ePaper display with four buttons. Using smaller font, I’m able to fit two columns of 14 node names each. This allows for 23 node names (when you subtract the headers and a space after each headers) which is more nodes than I currently have in my database! The refresh rate of the 2.7 inch display is slightly worse, a second or two, but it’s bearable.
Comparing the two now, I can also see that the Waveshare display has a higher pixel density than the InkyPHAT display, allowing me to fit more information into the same amount of space.
My ePaper screen is connected to a Pi 5, which is connected to a Heltec v3. I previously used a Pi Zero and found that it works, but the commands take about twice as long to complete than the Pi 5. The upgrade to the 5 was definitely overkill, but it will likely serve double duty and run some other scripts too.
You can find all of the code I used for this project in my Github repo.
The Pi runs three scripts. The first script is called update-node-list.py
. It runs meshtastic --nodes
and formats the output into a database on my Pi. It keeps information like the long and short names of the node, and the ID, plus some other data that was interesting to me like the hardware. I don’t save the data that constantly changes like the channel utilization, to try to reduce the amount of reading and writing to my SD card. Each node entry also has an array of “last seen” times. Every time the last seen time updates, an updated entry is appended to the array.
The second script is called update-buddy-list.py
. It pulls the node database and formats it into a buddy list. Based on the last seen times array, the nodes are divided up into one of three lists: active, last active less than 24 hours ago, and last active less than a week ago.
It also uses the last seen times array to mark new devices. Devices that were first seen less than a week ago get a *
before their name, devices that were first seen less than 24 hours ago get a **
to emphasize them further.
The nodes within each list are alphabetized, keeping the nodes that start with a *
at the beginning. I opted to display the long name of the node, but if I had more space on the display, I’d probably add the short name as well. The lists are displayed on the ePaper screen.
The update-node-list.py
script runs every three minutes in a cron job. The update-buddy-list.py
script also runs every three minutes, but I added a 60 second delay to it doesn’t pull the node list until after it has been updated.
The third script is called node-list-cleanup.py
. This one runs every third day. This script archives the active node database into a file with that day’s date on it. Then it replaces the active file with a version that is identical, except the only times in the least seen array are the first value and the last value. This keeps the active node database file from getting too big.
On many versions of the Meshtastic firmware, if you are connected to the node with Bluetooth and try to run a CLI command at the same time, the CLI command will time out or fail. For this reason, it’s recommended that you turn off Bluetooth on the node that will serve as your base station. This unfortunately means that you won’t be able to see any messages that happen while you’re away unless they appear on the screen or you SSH into your Pi and check via the CLI.
To get an accurate list of the times that your node was last seen, your node must know what time it is. This proves more difficult than you’d expect. The nodes do not apparently get time from your phone being connected to them, and as I mentioned previously, you can’t have your phone connected at the same time as you are using the buddy list anyway.
According to someone on the Meshtastic Discord, each CLI command is supposed to update your node’s current time from your computer’s clock, but that doesn’t seem to be the case with either the Pi Zero or the Pi 5. Another contributor on the Discord says this only works properly in versions 2.5+. I’m still on 2.3.13, so I can’t say whether this is the case, but it doesn’t work with my firmware and I’m not willing to upgrade to (what is at the time of writing) an unstable version of the firmware.
A work around for this is GPS. If one node on your mesh has a GPS module, that node will give all the other nodes the time. It must be an actual hardware GPS module; it can’t be your phone giving it position data with the app. That node also can’t be connected only sometimes: the moment your GPS node goes offline your base station node will immediately forget the time.
You can have your base station node be the one with the GPS module, but if it’s not near a window or oriented so that the GPS module is facing up, you may not get a satellite lock. I opted to have a second node on my network, and that second node is the one that I can connect to via Bluetooth to see any messages I missed when I was away.
You will need to make sure that your time zone is properly set on your base station node. I found (at least with my combo of FW version and iOS application version) that I couldn’t set the time zone using the iOS app. Using Android I was able to set the time zone without issue.
The time zones aren’t the usual “America/New_York” strings you might expect. Look up your time zone from this list.
I’m not currently using the buttons on my display, but eventually I’d like to incorporate them so that pressing the button would switch the display from the formal long names to the short name and maybe a description that I’ve written about the node (“Joe’s node”). When people leave the default Meshtastic ABCD names, it’s hard to remember who’s who!
I also have plenty of extremely large (7”+) ePaper displays laying around, and while being able to display more information about each node is tempting, the long refresh rates make this undesirable. The 7.5” displays can take 30-45 seconds to refresh, and from experience I can say that a large screen flashing to refresh on my desk is very distracting. I generally don’t use the 7.5” screens for anything that refreshes more often than once every 12 hours if it’s somewhere that I will see it when it is refreshing. Maybe once I am in range of a more consistent mesh network I’ll create a buddy list that only updates once a day.
My node database allowed me to answer a few questions I had about my Meshtastic set-up.
My first question was how often does the “Last seen” metric get updated? You would think that two nodes that are six inches apart and on the same mesh would be constantly connected to each other and thus the time that one had “Last seen” the other would be zero seconds. This didn’t prove to be the case: I found that the “Last seen” time gets updated pretty much exactly every 15 minutes.
This 15-minute value is determined by a setting in the firmware that determines how often nodes broadcast to each other that they are on the network. It was recently increased to 15 minutes to improve performance on congested networks.
This wasn’t ideal for me because I have a nearby mesh that I can often connect to when the wind blows the right way. I wanted to be able to see right away when I’m connected to this nearby mesh so that I can send messages; knowing that I was connected 15 minutes ago isn’t really that helpful to me.
Doing a little research, I found there are a few ways to force my base station node to check if a second node is still online: I can run a telemetry request, a position request, or a trace route to the second node and if the node is still in range, it’s last seen value will be updated. The telemetry request was recommended as the least “expensive” (in terms of how much bandwidth the request utilizes).
It takes up about 3% channel utilization, but, more importantly to me, it takes around 5-10 seconds to complete. And, for whatever reason, if I run two of these commands to two different nodes back-to-back, the second one takes twice as long to complete. This means that quickly polling every node in my database to see if they’re still online isn’t feasible, even on a small mesh such as mine. Upgrading my Pi from a Pi Zero to a Pi 5 decreased the time the commands took to run, but the node itself still takes about five seconds to return a result from the first command, and longer for the second.
I moved on to the second question: how often do I connect to that nearby mesh? By looking at the database, the answer turns out to be very often. Approximately every 15 minutes I see at least one of the nodes on the nearby mesh. However, I’m rarely connected long enough to send or receive any messages from the mesh.
What I took away from this data is investing in a marginally better antenna set-up would likely get me a constant connection to the nearby local mesh. Once I’m constantly connected to that nearby mesh it won’t matter too much if my “Active” list is 15 minutes out of date, those nodes will likely still be online.
All the code for this project is available at this Github repository.
Please be kind when evaluating my coding skills. This seems to work without bugs for now (who knows how it will work with future updates of Meshtastic firmware), but it's certainly not written the best it could be. ChatGPT is responsible for quite a bit of it, purely because in this case I preferred getting it done quickly to getting it done well :)