41 MQTT in project greenhouse

41.1 MQTT in the greenhouse (how control & sensing works)
In the greenhouse we use MQTT as a lightweight “message bus” that lets devices publish sensor data and receive control commands.
Why MQTT?
- One broker, many devices: sensors and controllers don’t need to know about each other directly—everything goes through the broker.
- Safer control: students don’t need to wire high-voltage loads or power electronics. The high-voltage / high-current parts (e.g., irrigation solenoids, pumps, fans) are already installed and protected (relays, fuses, enclosures, labeling).
- Faster labs: you focus on data + logic + automation, not on dangerous wiring.
41.2 Broker + login details
Use these details:
- Wi-Fi SSID:
agrotech - Wi-Fi password:
1Afuna2gezer - MQTT broker:
192.168.0.102 - MQTT port:
1883 - MQTT username:
mqtt-user - MQTT password:
1234
41.3 MQTT basics you need for this course
41.3.1 Topics
A topic is a string path (like folders). Devices publish messages to topics; other devices subscribe to topics.
Example control topic:
/greenhouse/outside/irrigation/solenoid5
41.3.2 Payloads
For most greenhouse actuators we use a simple convention:
0→ OFF / closed1→ ON / open
So publishing 1 to a solenoid topic opens that valve; publishing 0 closes it.
41.4 What is available in the greenhouse
Below is the current set of available MQTT endpoints. Each endpoint has:
- topic
- direction: control (subscribe) or telemetry (publish)
- expected payload format
- notes / safety constraints
41.4.1 Actuators (control topics)
All actuator topics expect a binary payload:
0→ OFF / closed1→ ON / open
These devices are already wired through protected relays. You should only control them via MQTT.
41.4.1.1 Outside irrigation & fertigation
| Device | Topic | Payload | Meaning |
|---|---|---|---|
| Solenoid 1 (outside irrigation) | /greenhouse/outside/irrigation/solenoid1 |
0 / 1 |
0=closed, 1=open |
| Solenoid 2 (outside irrigation) | /greenhouse/outside/irrigation/solenoid2 |
0 / 1 |
0=closed, 1=open |
| Solenoid 3 (outside irrigation) | /greenhouse/outside/irrigation/solenoid3 |
0 / 1 |
0=closed, 1=open |
| Solenoid 4 (outside irrigation) | /greenhouse/outside/irrigation/solenoid4 |
0 / 1 |
0=closed, 1=open |
| Solenoid 5 (outside irrigation) | /greenhouse/outside/irrigation/solenoid5 |
0 / 1 |
0=closed, 1=open |
| Solenoid 6 (outside irrigation) | /greenhouse/outside/irrigation/solenoid6 |
0 / 1 |
0=closed, 1=open |
| Solenoid 7 (outside irrigation) | /greenhouse/outside/irrigation/solenoid7 |
0 / 1 |
0=closed, 1=open |
| Solenoid 8 (outside irrigation) | /greenhouse/outside/irrigation/solenoid8 |
0 / 1 |
0=closed, 1=open |
| Fertigation pump | /greenhouse/outside/irrigation/fertigation |
0 / 1 |
0=off, 1=on |
⚠️ Note: Do not leave solenoids or the fertigation pump ON unattended. Always send
0when finished testing.
41.4.1.2 220 V sockets (inside greenhouse)
These topics control mains-voltage sockets inside the greenhouse. Each one corresponds to the top socket in its socket array.
| Device | Topic | Payload | Meaning |
|---|---|---|---|
| Socket 1 (220 V) | /greenhouse/sockets/socket1 |
0 / 1 |
0=off, 1=on |
| Socket 5 (220 V) | /greenhouse/sockets/socket5 |
0 / 1 |
0=off, 1=on |
| Socket 6 (220 V) | /greenhouse/sockets/socket6 |
0 / 1 |
0=off, 1=on |
⚠️ Safety: These are high-voltage outputs. Never connect or disconnect loads while powered. Use MQTT only.
41.4.2 Sensors (telemetry topics)
Sensors in the greenhouse publish data to MQTT topics. You do not send commands to these topics — you only subscribe to read values.
All sensor messages use plain numeric payloads (no JSON).
41.4.2.1 Outside irrigation flow sensor
These topics report the pulse output of the outside flow meter connected to the irrigation system.
| Sensor | Topic | Payload | Meaning |
|---|---|---|---|
| Flow pulses per second | /greenhouse/sensors/outside_flow/pulse_per_sec |
number | instantaneous pulse rate (pulses·s⁻¹) |
| Total flow pulses | /greenhouse/sensors/outside_flow/pulse_total |
integer | cumulative pulse count since last reset |
Notes:
pulse_per_secis updated continuously and reflects current flow activitypulse_totalis retained on the broker, so new subscribers immediately receive the last value- Conversion from pulses to volume (e.g. liters) depends on the flow meter calibration and is done client-side
41.4.2.2 Typical usage
- Subscribe to
pulse_per_secto detect whether irrigation is currently flowing - Subscribe to
pulse_totalto compute total water usage over time - Combine flow data with solenoid control topics to verify that irrigation commands worked as expected
41.5 How to test MQTT without writing code
You can test control and telemetry immediately using an MQTT client.
41.5.1 Phone apps
- Android: MQTT Client Lite (works well)
- iPhone: search “MQTT client” in the App Store (common options include clients like MQTTAnalyzer / MQTT Client—availability changes)
What to do:
Add a new connection:
- Host:
192.168.0.102 - Port:
1883 - Username/password: (provided privately)
- Host:
Subscribe to a telemetry topic to watch values (e.g., flow).
Publish to a control topic:
- Topic:
/greenhouse/outside/irrigation/solenoid5 - Message:
1to open,0to close
- Topic:
41.5.2 Desktop apps (recommended)
- MQTT Explorer (very friendly UI)
- MQTTX (clean UI, cross-platform)
These make it easy to:
- browse topics
- publish test payloads
- subscribe and watch live values
- debug retained messages
41.6 Safety + good practice rules
Always send
0when you’re done testing a solenoid/relay.Don’t leave actuators ON unattended.
If something behaves unexpectedly, check:
- retained messages
- topic spelling (leading
/matters) - whether your payload is exactly
0or1
Never publish credentials in notebooks, screenshots, or repos.
41.7 Where this fits in the code below
In the Arduino/ESP code, you’ll see:
- Wi-Fi connect → join
agrotech - MQTT connect → broker
192.168.0.102:1883 - subscribe (optional) to control topics
- publish telemetry (optional) to sensor topics
- publish
0/1commands to control relays/solenoids
41.8 Control irrigation solenoid in the greenhouse
Use the code below to control the irrigation solenoid outside the greenhouse.
Code usage: connect a jumper to A4. Whenever you touch the jumper, the solenoid will be open, otherwise it will be closed.
Download code#include <WiFi.h>
#include <PubSubClient.h>
// WiFi credentials
const char* ssid = "agrotech"; // Replace with your WiFi SSID
const char* password = "1Afuna2gezer"; // Replace with your WiFi Password
// MQTT broker details
const char* mqtt_server = "192.168.0.102"; // IP address of Home Assistant
const int mqtt_port = 1883; // Default MQTT port
const char* mqtt_user = "mqtt-user"; // MQTT username
const char* mqtt_password = "1234"; // MQTT password
const char* mqtt_topic = "/greenhouse/outside/irrigation/solenoid5"; // MQTT topic
// Touch pin configuration
#define TOUCH_PIN A4 // Use GPIO 4 as touch pin (T0 on ESP32)
// MQTT client and WiFi client
WiFiClient espClient;
PubSubClient client(espClient);
// State variable to track touch pin state
bool send_message = false;
void setup_wifi() {
Serial.print("Connecting to WiFi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
// Attempt to reconnect to the MQTT broker
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" Retrying in 5 seconds...");
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
// Initialize WiFi
setup_wifi();
// Set up MQTT
client.setServer(mqtt_server, mqtt_port);
// Ensure the ESP32 starts connected to the MQTT broker
reconnect();
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// Read the state of the touch pin
bool is_touched = touchRead(TOUCH_PIN) < 40; // If the value is less than 40, the pin is being touched
// Send "1" if the pin is being touched
if (is_touched) {
if (!send_message) {
client.publish(mqtt_topic, "1");
Serial.println("Sent: 1");
send_message = true; // Set flag to avoid sending multiple times while touching
}
}
// Send "0" if the pin is not being touched
else {
if (send_message) {
client.publish(mqtt_topic, "0");
Serial.println("Sent: 0");
send_message = false; // Reset the flag when pin is no longer touched
}
}
// Optional: Small delay to avoid flooding the MQTT server with messages
delay(100); // Adjust the delay if necessary
}