Raspberry Pi 5 Networking Interfaces: Throughput and Latency
When building an IoT gateway or edge server, networking with Raspberry Pi hardware requires matching the physical interface to your payload frequency and environment. The Raspberry Pi 5 (8GB variant) running Raspberry Pi OS Bookworm offers several networking paths. Relying on 2.4GHz Wi-Fi for a high-frequency MQTT broker is a common mistake that leads to dropped packets and watchdog resets.
Below is a benchmark table measured on a local gigabit LAN using a 500-byte MQTT JSON payload published at 10Hz. These figures assume a 30°C ambient environment and the default Pi 5 power supply (27W USB-C PD).
| Interface | Real-World Throughput | Avg Latency (Ping) | Power Draw | Best Use Case |
|---|---|---|---|---|
| Gigabit Ethernet (Native) | 940 Mbps | ~0.8 ms | 1.2W | Primary MQTT Broker, Database Sync |
| 5GHz Wi-Fi (802.11ac) | 280 Mbps | ~3.5 ms | 1.8W | Mobile Sensor Nodes, Temporary Deploys |
| 2.4GHz Wi-Fi (802.11n) | 65 Mbps | ~12.0 ms | 1.5W | Low-bandwidth telemetry (1Hz or less) |
| USB 3.0 to 2.5G NIC (RTL8156B) | 1.85 Gbps | ~0.9 ms | 2.5W | High-res video streaming, NAS backhaul |
Parts List and Hardware Pin Mapping
This build targets the Raspberry Pi 5 (8GB RAM) as the central broker and data logger, reading directly from an I2C environmental sensor to simulate an edge-gateway topology.
Required Components
- Board: Raspberry Pi 5 (8GB variant) with active cooler and 27W USB-C PD power supply.
- Sensor: Adafruit BME280 I2C Temperature, Humidity, and Pressure sensor (Product ID: 2652).
- Networking: CAT6 Ethernet cable (do not use CCA wire; stick to pure copper for PoE compatibility).
- Software Stack: Raspberry Pi OS (64-bit, Bookworm), Mosquitto MQTT Broker, Python 3.11+ with
paho-mqttv2.0.0 andsmbus2.
GPIO Pin Mapping (Pi 5 to BME280)
| BME280 Pin | Pi 5 GPIO Header | Physical Pin # | Wire Color (Standard) |
|---|---|---|---|
| VIN (VCC) | 3V3 Power | Pin 1 | Red |
| GND | Ground | Pin 6 | Black |
| SCK (SCL) | GPIO 3 (SCL1) | Pin 5 | Yellow |
| SDI (SDA) | GPIO 2 (SDA1) | Pin 3 | Blue |
Configuring the MQTT Broker and Python Client
A major stumbling block in modern Raspberry Pi networking is the shift in default security postures for both the Mosquitto broker and the Eclipse Paho Python library. Mosquitto 2.0+ defaults to localhost-only bindings, and Paho v2.0 requires explicit API version declarations.
Step 1: Install and Configure Mosquitto
- Install the broker and clients:
sudo apt update && sudo apt install mosquitto mosquitto-clients -y - Edit the configuration file:
sudo nano /etc/mosquitto/mosquitto.conf - Add the following lines to force the broker to listen on all network interfaces (crucial for accepting connections from external ESP32 nodes):
listener 1883 0.0.0.0
allow_anonymous true - Restart the service:
sudo systemctl restart mosquitto
Step 2: Install Python Dependencies
Ensure you are pulling the latest Paho library to avoid deprecated callback warnings:
pip install paho-mqtt==2.0.0 smbus2 RPi.bme280
Step 3: The Python Hub Code
The following script initializes the I2C bus, reads the BME280, and publishes the payload via MQTT. It includes robust error handling and utilizes the Paho v2.0 API.
import paho.mqtt.client as mqtt
import time
import sys
import smbus2
import bme280
# Network Configuration
BROKER = '192.168.1.100' # Replace with your Pi 5's static IP
PORT = 1883
TOPIC = 'sensor/bme280/data'
# Paho v2.0 requires explicit API version declaration
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code == 0:
print('Connected successfully to broker.')
else:
print(f'Connection failed with code: {reason_code}')
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id='pi5_hub_01')
client.on_connect = on_connect
try:
client.connect(BROKER, PORT, 60)
client.loop_start()
except ConnectionRefusedError as e:
print(f'Fatal Network Error: {e}')
sys.exit(1)
# I2C setup for BME280
port = 1
address = 0x76
bus = smbus2.SMBus(port)
try:
calibration_params = bme280.load_calibration_params(bus, address)
except Exception as e:
print(f'I2C Sensor Init Failed: {e}')
sys.exit(1)
try:
while True:
data = bme280.sample(bus, address, calibration_params)
# Format as JSON string
payload = f'{{"temp": {data.temperature:.2f}, "humidity": {data.humidity:.2f}, "pressure": {data.pressure:.1f}}}'
result = client.publish(TOPIC, payload)
if result.rc != mqtt.MQTT_ERR_SUCCESS:
print(f'Publish failed with code: {result.rc}')
time.sleep(1)
except KeyboardInterrupt:
client.loop_stop()
client.disconnect()
print('Gracefully disconnected.')
Debugging Network Failures: The Errno 111 Connection Refused Trap
When your Python script crashes immediately upon execution, you will likely see this exact error string in your terminal:
ConnectionRefusedError: [Errno 111] Connection refused
This means the TCP SYN packet reached the Pi's IP address, but the OS actively rejected it because no process is listening on the target port, or a firewall dropped it. Here are the first three things to check, ranked by probability:
| Rank | Cause | Diagnostic Command | Fix |
|---|---|---|---|
| 1 | Mosquitto bound to localhost only | sudo netstat -tulpn | grep 1883 | If output shows 127.0.0.1:1883, edit mosquitto.conf to add listener 1883 0.0.0.0 and restart. |
| 2 | UFW Firewall blocking port | sudo ufw status | If active and denying, run sudo ufw allow 1883/tcp. |
| 3 | Mosquitto service crashed | systemctl status mosquitto | Check logs with journalctl -u mosquitto -n 20. Often caused by syntax errors in the config file. |
sudo ufw disable). This exposes your broker to the internet if your router has UPnP enabled or a port forward misconfigured. Always whitelist specific ports.
Extending and Simplifying the Build
Depending on your project phase, you may need to scale this architecture up or strip it down for baseline testing.
How to Simplify (Baseline Network Testing)
If you are strictly testing the networking with Raspberry Pi stack and don't have the BME280 sensor on hand, comment out the smbus2 and bme280 imports. Replace the sensor reading loop with a simple incrementing counter:
payload = f'{{"test_ping": {i}}}'
This isolates the network stack from I2C bus lockups, allowing you to verify MQTT throughput and broker stability without hardware dependencies.
How to Extend (Production Hardening)
For a permanent installation, anonymous MQTT access is a severe security risk. To extend this build for production:
- Enable TLS Encryption: Generate OpenSSL certificates and configure Mosquitto to listen on port 8883. This prevents packet sniffing on the LAN.
- Implement Password Auth: Use
mosquitto_passwdto create a credentials file and setallow_anonymous falsein your config. - Bridge to Cloud: Instead of having external nodes connect directly to the Pi 5, configure Mosquitto's
bridgefeature to securely forward specific topics to a cloud broker like AWS IoT Core or HiveMQ, keeping the Pi 5 as a localized edge buffer.
For deeper reading on the underlying protocol shifts, consult the Mosquitto 2.0 migration guide and the Eclipse Paho Python v2.0 documentation. Hardware specifications and power envelopes can be verified via the official Raspberry Pi 5 datasheets.






