Powering the real food revolution with IoT, MQTT, and Heroku: an Interview with Freight Farms

Kyle Seaman is Director of Farm Technology for Freight Farms, producer of pre-assembled, IoT-enabled, hydroponic farms inside repurposed freight containers. Read the Freight Farms customer story to learn more about how Heroku has helped the company scale their business.

What is Freight Farms?

Our flagship product, The Leafy Green Machine (LGM), is a complete, commercial-ready, hydroponic growing system assembled inside a repurposed shipping container. Each of our 100+ farms is connected to an IoT network built on Heroku.

Tell us about your stack.

We’re running the open source version of the Parse server on Heroku. Our stack is mostly JavaScript: MongoDB along with a Node.js API. We also use Heroku Postgres.

Xively is a core component of our stack. We use the Xively add-on to sync our Heroku apps with their IoT cloud platform enabling us to connect the physical sensors and gateway devices located in our individual farm units to our software system running on Heroku.

Our favorite Heroku Add-on is Papertrail, which has been great with helping us monitor our apps. Heroku Connect has also made it really easy to sync data with our Salesforce CRM instance.

Our customer-facing app, Farmhand, is a native iOS and React web app. Farmhand's Connect features enable farmers to track, monitor, and control the climate and growing conditions of their farm remotely. Farmhand’s Shop is an e-commerce app where farmers can buy supplies.

How does data flow through your hardware and software systems?

Every farm is provisioned with a gateway device that’s running a Xively MQTT client locally. It’s connected to the other hardware devices, such as IP security cameras, wireless sensors, and the farm’s automation controller. Xively serves as our MQTT communication gateway and broker.

Freight Farm architectural diagram

Every minute, the gateway is collecting 100+ data points that give us information about the farm environment. This ranges from simple data, such as whether the lights are on or off, to more complex readings of nutrient levels, CO2, and temperature.

The local MQTT client running in each shipping container is a Lua application. It connects each farm to Xively’s cloud MQTT broker. This means that any other client can subscribe to listen in. As data is being passed up to the MQTT cloud broker, our server on Heroku is listening so it can process that data in real-time.

The IoT communication gateway and time series tracking is provided by Xively, and the logic is happening on Heroku. As a farm sends out data, Xively can respond to time series queries and Heroku filters the data to check for issues.

Do you communicate the other way, from your server to the farm?

Yes, we do. Our Heroku app has a range of workflows and monitoring triggers, that when triggered, sends a command via MQTT down to the farm. The local client is also listening for messages from the Heroku side.

There are also endpoints that allow our farmers to control the farm remotely. When farmers sign in to the Farmhand app and want to do something like turn the lights on, a Heroku app handles that request. It sends a message to the farm over MQTT, which then routes it to the farm’s automation controller to initiate the action.

What is the advantage to using MQTT?

In general, this MQTT architecture has worked really well for us. We were originally using HTTPS and a Raspberry Pi for sending data from the farm, but we’ve upgraded to a proper gateway, which gives us better security and enables sending data to the farm. Because MQTT is such a strong IoT standard now, it was very straightforward to configure our one-way HTTPS infrastructure for two way TLS MQTT.

With MQTT, you have one broker and n number of clients. Each new message only needs to be sent over the wire from the farm once, but will end up on all connected clients and our server instantly. This both saves on bandwidth and scales well as we bring more farms and client apps online.

MQTT is built around the concept of channels (ex. /sensors), and each client can subscribe to and extend channels (ex. /sensors/{farmId}). Xively has extended MQTT in an interesting way with the concept of templates. They don’t just have a /sensor channel that every device or client can subscribe to. Instead, every farm has its own set of channels built from the template, e.g. /{farmId}/sensors. As new channels are created, they are propagated to all devices. This adds a nice layer of security and separation, ensuring that messages only get to the intended device. From a development standpoint, it makes it that much easier to work with the protocol as each device shares the same properties.

Xively also adds the concept of organizations, allowing only clients and devices in the same organization to actually send messages to each other. This added logic on the broker means there is nothing extra for us to do to get full ACL out of the box.

Our message volume is very high. Each new request, such as “calibrate sensors,” initiates a specific session that subscribes to a farm channel. So if I create a new channel for a calibration, it will propagate to every device on every farm, making it a lot easier for us.

MQTT can be challenging in a multi-dyno setup, how are you using it?

Generically subscribing to a topic on Heroku is challenging, as each dyno will receive the message at the same time. However, sending messages from a running process over MQTT using WebSockets works really well, and that’s how we are using it.

We have a number of workflows and monitoring triggers that start up a process on Heroku, this could be a farmer hitting “start calibration” on their mobile app, or the server automatically stopping a pump once the tank is full. For user workflows, when one is started, the Farmhand app is listening to our server on Heroku, and the server uses MQTT to start a session subscribing to that farm’s specific channel for the workflow. This actually allows us to do less filtering on all inbound message because the server process and app subscribe to the actual topic URL associated with that farm.

Interestingly, we’ve found it faster to do tasks such as calibration through our cloud-based system rather than locally using a PLC (Programmable Logic Controller) for the farm.

Can you tell us more about the hardware and sensors?

Each farm has 40 pieces of environmental equipment that are controlled by an automation controller that uses the modbus protocol. These pieces of equipment are for anything climate-related or mechanical, such as lights, pumps, and fans. Every time a piece of equipment changes state, (e.g. “the pump turned off?”), we send this info up through the gateway to our server. At any point, Heroku or a client app can send the appropriate command down to the hardware, (e.g. “lights turn off”).

Each farm has 10 sensors. Some track climate-related conditions, such as humidity, CO2, and temperature. Others track conditions in our growing tanks, such as nutrients or pH levels in the water.

Do you push firmware updates?

Our very first farm that started 4 years ago is still running the same automation controller, which didn’t ship with OTA firmware updates. So a big consideration as we deployed our Heroku / Xively infrastructure was backwards compatibility. Our gateway has solved this issue, it augments the existing controller and it’s able to update itself with all our newer features through server-side logic. That’s a big evolution for our company—extending functionality to push firmware updates remotely, without requiring the user to do them manually onsite.

So, instead of having to go onsite to a farm to update firmware or fine-tune hardware, we can optimize the farm from anywhere through our app. We can also learn from optimizing a single farm and apply it to other farms and crops.

How are you applying what you’ve learned?

Because we can access any or all of our farms on demand, we’re building out new workflows that help us optimize farm operations based on real usage data.

We’ve written monitoring logic on Heroku to handle scenario and location-specific conditions. For example, if a farm is located in a cool climate region, we control the farm’s internal temperature by cooling it via the intake fans rather than AC in order to save energy.

Our next area of opportunity is crop optimization. For example, if you’re growing basil, what are the right conditions that will produce the best crop in your area? We’re starting to analyze yield data, but it’s still a very manual process. The new Track feature in Farmhand just launched a couple of weeks ago, which will help aggregate and analyze data from all our farms. Once we have historical data and algorithms in place, we’ll be able to strengthen our growing parameters for specific crops, as well as trigger alerts to farmers if conditions are suboptimal.

We’re finally hitting scale with 100 farms deployed. Many of these farms are just coming online, so we’re just getting the data now to validate some of these ideal “growing recipes.”

What’s next for Freight Farms?

We’re in a “consume and learn” phase. The next big project will be exposing this data through Farmhand analysis tools to help our farmers continue to grow the best product possible. We’ve also just launched our newest product, the LGC, which is our most connected farm yet, and ¼ the size of the LGM. As we continue down the connected path, we’ll continue to discover new and exciting use cases for our farms that weren’t possible before.

Browse the blog archives, subscribe to the full-text feed, or visit the engineering blog.