Building a Laravel / MQTT App on Laravel Forge

4 minute read
February 15, 2020

TLDR: Using a simple node script you can subscribe to an MQTT broker and forward messages to a Laravel application. See the demo repository here.

A friend of mine has taken an interest in programming simple sensors for things like controlling light switches or reading temperature. There are a number of different kinds of units on the market, but he's focused on Arduino and Sonoff. Ever heard of Rasberry Pi? Very similar.

An organization that we are both connected with has several walk-in freezers and coolers used to store merchandise like ice cream and groceries. Because these units contain a fair amount it would not be an insignificant financial loss if the contents thawed.

While there are commercial offerings for cold-storage monitoring, Larry and I wanted to combine our interests and build a system that would track the temperatures over time, but more importantly, alert the maintenance staff if the cooling systems fail and the temps rise too far. The goal was to give enough time to either fix the condensers or move the merchandise to avoid spoilage.

I had never heard of MQTT before this but after Larry gave me an intro I was pretty convinced there had to be some kind of a bridge to get the data into a Laravel application. At the time we built this (about a year ago) there were only a couple articles I could find that gave bits and pieces of info relating Laravel to MQTT. 

After collecting as much info as we could find the approach we landed on was using a simple node script to subscribe to the MQTT broker and forward messages on to Laravel for storage and processing. 

The Core Script

This script is responsible for subscribing to a topic on the MQTT broker and forwarding the message to an endpoint, which in our case is the Laravel application.

Take note of the first line, which manually assigns a title to the process responsible for running the script. This would normally be done automatically but we need to know which process is handling the script so we can kill it later.

Laravel Forge

There are a few other things that need to be in place for this to work correctly. 

First off, the script always needs to be running and must be restarted if it stops, so we used Laravel Forge's daemon feature:

Second, every time we deploy an update to the application we kill the node script so that it will be restarted and automatically pick up any new sensors.

On line 11 we are killing the process responsible for running the subscriber. Remember, the daemon will restart the process any time it is killed. 

Artisan Command

Another item that took some time to figure out was how to get the PHP application to communicate with the node process. Utilizing the Symfony Process component allowed me to bridge that gap.

This command is used when we register a new sensor in the Laravel application and need to reset the subscriber to pick up the new topic.

What Can We Do Now?

Now that we have our node script subscribed to the MQTT broker and forwarding messages to our Laravel application we can do whatever we want! 

Our system has customizable rules to define temperature breakpoints and send alerts or warnings to users if necessary. We are tracking the performance of the freezers/coolers to see when the defrost cycles occur, how far the temperatures vary over the day, and we can also publish messages back to the sensors and control the interval upon which they report back. 

We've dreamed about other implementations such as electrical draw sensing to see where electricity is used, water flow meters to see if toilets or sinks are left running, or logging when lights are on.

The majority of my work as a web programmer doesn't interface with the physical world. This project has been a fun exploration into IOT and I'm excited to see where else it may go!