树莓派与Android设备的连接建立及传感器数据传输、执行器控制方案问询
Hey there! Let's walk through how to connect your Raspberry Pi with an Android device, stream sensor data from the Pi to your phone, and control actuators on the Pi right from Android. I've built a few projects like this, so here's a straightforward, actionable plan:
Two reliable options here—Wi-Fi is great for long-range, real-time data, while Bluetooth works well if you don't have a Wi-Fi network nearby.
Wi-Fi (Local Network)
First, make sure both your Pi and Android are on the same Wi-Fi network. Find your Pi's local IP address by runninghostname -Iin the Pi's terminal (it'll look like192.168.x.x). That's the address you'll use to communicate between devices.
If you don't have a Wi-Fi network, you can turn your Pi into a Wi-Fi hotspot usinghostapdanddnsmasq—it's quick to set up with basic guides.Bluetooth
On the Pi, install BlueZ tools withsudo apt-get install bluetooth bluez-tools. Pair your Android device with the Pi via system settings, then use RFCOMM to establish a serial connection. This is lower-power but better for short-range use cases.
Let's cover two popular approaches: HTTP (super simple for beginners) and MQTT (ideal for real-time, low-latency data).
Option 1: HTTP API with Flask
On the Pi, we'll create a lightweight web server to serve sensor data.
- Install Flask:
pip install flask - Create a script
sensor_server.py:
from flask import Flask import Adafruit_DHT # Example for DHT11/DHT22 sensor app = Flask(__name__) sensor = Adafruit_DHT.DHT11 pin = 4 # GPIO pin connected to sensor @app.route('/sensor/data') def get_sensor_data(): humidity, temperature = Adafruit_DHT.read_retry(sensor, pin) if humidity is not None and temperature is not None: return {'temperature': temperature, 'humidity': humidity} else: return {'error': 'Failed to read sensor data'} if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
- Run it:
python sensor_server.py
On Android, use OkHttp to fetch the data:
val client = OkHttpClient() val request = Request.Builder() .url("http://<PI_LOCAL_IP>:5000/sensor/data") .build() client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // Handle connection errors here } override fun onResponse(call: Call, response: Response) { val responseData = response.body?.string() // Parse the JSON response and update your app's UI with temperature/humidity } })
Don't forget to add <uses-permission android:name="android.permission.INTERNET" /> to your AndroidManifest.xml.
Option 2: MQTT (Real-Time Streaming)
MQTT is perfect if you need continuous, low-delay data. We'll use Eclipse Mosquitto as the broker—running it locally on the Pi is fastest.
- Install Mosquitto on Pi:
sudo apt-get install mosquitto mosquitto-clients - Install paho-mqtt for Python:
pip install paho-mqtt - Pi script to publish sensor data:
import paho.mqtt.client as mqtt import Adafruit_DHT import time sensor = Adafruit_DHT.DHT11 pin = 4 client = mqtt.Client() client.connect("localhost", 1883, 60) # Connect to local broker while True: humidity, temperature = Adafruit_DHT.read_retry(sensor, pin) if humidity and temperature: client.publish("pi/sensor/temperature", str(temperature)) client.publish("pi/sensor/humidity", str(humidity)) time.sleep(2)
On Android, use the Paho MQTT client:
- Add dependency to build.gradle:
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5' - Subscribe to the topics:
val client = MqttClient("tcp://<PI_LOCAL_IP>:1883", MqttClient.generateClientId()) client.connect() client.subscribe("pi/sensor/temperature") { topic, message -> val temp = String(message.payload) // Update UI with the latest temperature } client.subscribe("pi/sensor/humidity") { topic, message -> val humidity = String(message.payload) // Update UI with the latest humidity }
Again, we'll use HTTP or MQTT to send commands from Android to the Pi.
Option 1: HTTP Control
Extend the Flask server to handle actuator commands (e.g., turning an LED on/off):
from flask import Flask, request import RPi.GPIO as GPIO app = Flask(__name__) led_pin = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(led_pin, GPIO.OUT) @app.route('/actuator/led', methods=['POST']) def control_led(): state = request.json.get('state') if state == 'on': GPIO.output(led_pin, GPIO.HIGH) return {'status': 'LED turned on'} elif state == 'off': GPIO.output(led_pin, GPIO.LOW) return {'status': 'LED turned off'} else: return {'error': 'Invalid state'} if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
On Android, send a POST request to control the LED:
val client = OkHttpClient() val json = JSONObject().apply { put("state", "on") } val body = RequestBody.create(MediaType.parse("application/json"), json.toString()) val request = Request.Builder() .url("http://<PI_LOCAL_IP>:5000/actuator/led") .post(body) .build() client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // Handle error } override fun onResponse(call: Call, response: Response) { // Confirm the command was successful in your app } })
Option 2: MQTT Control
Set up the Pi to subscribe to a control topic and act on messages:
import paho.mqtt.client as mqtt import RPi.GPIO as GPIO led_pin = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(led_pin, GPIO.OUT) def on_message(client, userdata, msg): command = msg.payload.decode() if command == "led_on": GPIO.output(led_pin, GPIO.HIGH) elif command == "led_off": GPIO.output(led_pin, GPIO.LOW) client = mqtt.Client() client.on_message = on_message client.connect("localhost", 1883, 60) client.subscribe("pi/actuator/control") client.loop_forever()
On Android, publish commands to the topic:
val client = MqttClient("tcp://<PI_LOCAL_IP>:1883", MqttClient.generateClientId()) client.connect() // To turn LED on client.publish("pi/actuator/control", "led_on".toByteArray()) // To turn LED off client.publish("pi/actuator/control", "led_off".toByteArray())
- Network Issues: Double-check that both devices are on the same network, and the Pi's firewall isn't blocking ports (use
sudo ufw allow 5000for HTTP,sudo ufw allow 1883for MQTT if needed). - GPIO Permissions: Run your Pi scripts with
sudoor add your user to thegpiogroup (sudo usermod -aG gpio pi) to avoid permission errors. - Android Permissions: For Android 10+, you might need
ACCESS_NETWORK_STATEpermission in addition toINTERNET.
内容的提问来源于stack exchange,提问作者user9691492

