If you want to skip directly to the code, take a look at the Github repository for Internal Resource Monitor.
Recently I noticed my home automation setup wasn't reliable. I am using Home Assistant which works well, I have a feeling this instability has more to do with the fact that it is running on a two year old first generation Raspberry Pi. While upgrading the Raspberry Pi would more than likely fix this issue, I think it would be more interesting to try to develop my own solution.
I don't directly interact with my automation setup through the UI very often. This resulted in me not noticing that it had gone down for a long period of time. To address this issue I built a service to monitor Home Assistant and let me know if it ever becomes unavailable. There are many services out there that will ping a site for you and notify you if that site doesn't respond. Unfortunately, I couldn't use any of those because the Raspberry Pi hosting Home Assistant is not open to the internet. While I could open the Raspberry Pi to the internet, this problem was an interesting one to solve.
At this point I decided that I needed to write my own solution. For things like this I tend to default to Node because the turnaround time is usually quick. While it might seem obvious to just run the monitor on the Rasberry Pi, due to some instability in my Rasbian install, sometimes the entire device will stop communicating with the network. This means I needed something outside the Pi to monitor both it and the Home Assistant service.
Ultimately, I needed to have a single endpoint available to update the last seen time for various services in the database. A scheduled task was also required to notify me if any objects in the database hadn't been seen for a specified amount of time. While Lambda isn't the only solution that would work, I felt it was perfectly suited for these tasks and it allowed me to implement these things with minimal complexity.
The application is written in NodeJS that is executed using lambda functions in AWS. Persistence is handled using DocumentDB. Notifications are sent using Pushover, due to the fact that my Home Assistant instance already uses Pushover for notifications.
This application consists of two lambda functions and a set of supporting library modules.
updateTimestamp
updateTimestamp is accessible through an HTTP GET
request to the route /{stage}/update/{name}
. The database is checked for a resource with the name specified in the url. If a resource with that name does not exist, one is created. If a resource already exists the record is retrieved. The lastSeen
property is updated to the current time. If that resource was previously unavailable a notification is sent stating that the resource is now available.
checkAvailability
checkAvailability is executed every 15 minutes. Each execution it compiles a list of all resources where the lastSeen
time was longer than 15 minutes ago. For each of these resources, if a notification hasn't already been sent a notification is sent and the notified
flag is changed to true
.
If you want to use the Internal Resource Monitor I created for your own services, here are some getting started instructions. This is a standard serverless framework application, so there shouldn't be too many surprises with getting this up and running.
Install the serverless framework using npm
npm install -g serverless
Clone this repository
git clone https://github.com/tawehn/internal-resource-monitor.git
Install the project dependencies
npm install
Setup pushover environment variables
For right now, the pushover API configuration uses environment variables (One of those "temporary" solutions). I plan on updating this to use a more maintainable method in the future, but here is how you configure it right now.
export PUSHOVER_IRM_APP_KEY=YOUR_APP_KEY_HERE
export PUSHOVER_USER_KEY=YOUR_USER_KEY_HERE
Either execute the above lines directly in your shell or place them in your .bashrc
or .zshrc
.
Deploy to AWS
sls deploy -s dev
For more information please refer to the serverless framework documentation.