Very recently (today, in fact) my ISP - Verizon - had a somewhat widespread service-effecting issue which definitely effected me, my house, and our service.
Internet outages are certainly not new; I've had my share of issues with both Verizon/Fios and Comcast in the past. In my personal experience, Verizon has edged out Comcast in terms of stability and availability, and so it is with them that I stay. I have been a work-from-home professional for years before the pandemic started, and internet availability is cruicial for me. Any longstanding issues - particularly of the intermittent kind that cannot be easily identified ("Well, I don't see a problem right now, so there must not be a problem.") - were what infuriated me with Comcast.
What was a "hmmmm" moment about this particular Verizon issue, however, was that it came just one day after I "cut the cord" with Verizon and dropped both voice and tv services, opting instead for straight up Internet. I kept the Gigabit service (though it is most likely overkill for what I need) because I can, and now I'll find myself with a few extra dollars left over every month.
It turns out that the issue of the day was, in fact, Verizon snubbing me and throttling my service, but it still got me thinking that it'd be neat to set up my home internet monitoring system that I had originally set up with Comcast to prove to them I was having availability issues. I don't have any great, huge needs, so to do this I decided that a Node-Red dashboard would be perfect.
To accomplish what I'm aiming to do, I realised that I would need two unique functions: a speed-test node, to monitor the speed of the service, as well as a simple "ping" to monitor for availability. I'm not monitoring packet loss in this solution; I'm only sending out a few pings every minute, and that's a poor indicator of packet loss.
The nodes I decided to use are "node-red-contrib-speedtest-updated" for testing the speed of the service, and "node-red-configurable-ping" to monitor availability. The solution will look like this:
At 5 minute intervals, perform a speedtest to calculate latency, upload and download speeds.
At 1 minute intervals, perform a ping test to determine availability.
The Dashboard
This entire project is going to be focused on a dashboard, so I created a new one named, appropriately, Home Internet Monitoring. It is comprised of three columns; one to present Upload speed, one to present Download speed, and one to present Availability and Latency.
The Ping Test
The first test to perform, the simple ping test, is very straightfoward:
- The "timestamp" modules kicks off the entire flow. It runs once at deployment, and then repeats every 1 minute.
- The "ping" module performs the actual ping.
- The "function" module simply takes the output from the ping module and formats it into a 0 or 100.
- Finally, the Availability chart presents the data.
First, the timestamp module is crucial. It is required to actually kick off the entire flow. It will run at system start, and when configured to repeat will do just that.
The ping module performs the data gathering. At it's heart, Node-Red is all about data manipulation, and that is really all the ping module does: it performs a ping, gathers the results, and sends it in the message payload to the next module.
I want to monitor my internet availability, so I need to ping something that I know should be available at all times. There are a number of destinations available, but I ultimately decided on pinging my own internet-facing IP Address. It is a DHCP address assigned by Verizon, but with the use of a Dynamic DHCP service I can use my DNS name easily.
The result from the Ping module is a latency measurement. Being that I am pinging my own IP address, the measurement is typically less than half a second, which is rather meaningless. I use the 'function' module here to use a straight forward "if/then" to convert the value into an Availability-centric 100 or 0: If latency is greater than 0, then Availability is 100, otherwise, Availability is 0.
if (msg.payload > 0) {
msg.payload = 100
} else {
msg.payload = 0
}
return msg;
Finally, the chart simply presents the data.
I have the X-Axis configured to show the most recent two hours of data. Data older than that is ignored.
Truests will argue that I am not really monitoring "internet availability," and they're correct; I'm not pinging outside of the house, so this does not have external visibility. What it does do, however, is let me know that Verizon is, in fact, supplying me with a DHCP address. When I was having my host of issues with Comcast previously I had noticed that my address kept cycling and I would often not have an IP Address.
Upload and Download Speeds
These sets of flows may look overbearing, but they're really not. This flow starts off just like the Ping flow, with the Timestamp injection module; unlike the Ping flow, however, I've configured this one to run only once every five minutes.
The speedtest module is equivalent to the ping module; it performs the speedtest. This is a predefined module that utilises speedtest.net from Ookla. One of the really nice things about the Node-Red environment is the openness and re-usability of so much knowledge.
What occurs after the speedtest is complete is that the flow splits off into three simultaneous flows. It's worth repeating that a Node-Red flow is simply data manipulation. The output from the speedtest node contains only key pieces of information:
- Upload speed
- Download speed
- Latency
- A few other configuration parameters
The connection between each flow passes that data along it, so what I am doing here is passing the same output from the results of the speedtest to three different flows, each of which takes that information as input and performs it's own calculations on it.
The Upload Speed function parses out the upload speed:
upload = msg.payload["speeds"]["upload"] * 8
msg.payload = upload
return msg
Likewise, the Download Speed and Latency functions parse out the Download Speed and Latency results, respectively.
Finally, the results of each of those modules are then passed into dashboard widgets for presentation. The result looks remarkably like this:
The charts - particularly the gauges - have some colour coordination for them, and the line charts have firm Y-Axis labels. What is really interesting to me is to see what I often have higher upload speeds than I do download speeds.
Ways to Improve
This small project is not meant to replace a network monitoring solution, nor is the dashboard meant to be a reporting front end. It's primarily a way for me to be a nerd and appease my inner-geek. But if I did want to expand this I would do the following:
Store the results of each test in a backend database, probably sqlite.
Add to the dashboard the ability to perform a test on-demand.
Add to the dashboard the ability to configure the tests (particularly Ping)
Add a packet loss measurement
Install and configure MQTT to perform some action when a threshold is breached, such as low internet speed, or unavailability
You know, the more I'm thinking about this, the more I think I could turn this into a complete "Home Internet Monitoring" solution hosted on a raspberry pi. Hrrm.