Contrôle ESP8266 via Raspberry Pi via MQTT

9

Je travaille sur un projet domotique. L'objectif de base de mon projet est de contrôler les relais et autres capteurs situés à différents endroits. J'ai configuré mon Raspberry Pi en tant que courtier MQTT. Le moustique fonctionne bien. Pour l'instant, ce que j'essaie de faire est de déclencher un relais câblé avec esp8266 (GPIO2). Voici mon code de serveur Web Python:

import paho.mqtt.client as mqtt
from flask import Flask, render_template, request
app = Flask(__name__)

mqttc=mqtt.Client()
mqttc.connect("localhost",1883,60)
mqttc.loop_start()

# Create a dictionary called pins to store the pin number, name, and pin state:
pins = {
   2 : {'name' : 'GPIO 2', 'board' : 'esp8266', 'topic' : 'esp8266/2', 'state' : 'False'}
}

# Put the pin dictionary into the template data dictionary:
templateData = {
'pins' : pins
}

@app.route("/")
def main():
# Pass the template data into the template main.html and return it to the user
return render_template('main.html', **templateData)

# The function below is executed when someone requests a URL with the pin number and action in it:
@app.route("/<board>/<changePin>/<action>")

def action(board, changePin, action):
# Convert the pin from the URL into an integer:
changePin = int(changePin)
# Get the device name for the pin being changed:
devicePin = pins[changePin]['name']
# If the action part of the URL is "on," execute the code indented below:
  if action == "1" and board == 'esp8266':
  mqttc.publish(pins[changePin]['topic'],"1")
  pins[changePin]['state'] = 'True'

if action == "0" and board == 'esp8266':
  mqttc.publish(pins[changePin]['topic'],"0")
  pins[changePin]['state'] = 'False'

# Along with the pin dictionary, put the message into the template data dictionary:
templateData = {
  'pins' : pins
}

return render_template('main.html', **templateData)

if __name__ == "__main__":
app.run(host='0.0.0.0', port=8181, debug=True)

Voici mon code HTML:

<!DOCTYPE html>
<head>
   <title>RPi Web Server</title>
   <!-- Latest compiled and minified CSS -->
   <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
   <!-- Optional theme -->
   <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
   <!-- Latest compiled and minified JavaScript -->
   <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
   <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
   <h1>RPi Web Server - ESP8266 MQTT</h1>
   {% for pin in pins %}
   <h2>{{ pins[pin].name }}
   {% if pins[pin].state == 'True' %}
  is currently <strong>on</strong></h2><div class="row"><div class="col-md-2">
  <a href="/esp8266/{{pin}}/0" class="btn btn-block btn-lg btn-default" role="button">Turn off</a></div></div>
   {% else %}
  is currently <strong>off</strong></h2><div class="row"><div class="col-md-2">
  <a href="/esp8266/{{pin}}/1" class="btn btn-block btn-lg btn-primary" role="button">Turn on</a></div></div>
   {% endif %}
   {% endfor %}
</body>
</html>

Voici mon code ESP8266:

#include <ESP8266WiFi.h>
#include <PubSubClient.h

const char* ssid = "Godfather";
const char* password = "idontknow";

const char* mqtt_server = "192.168.137.100";

WiFiClient espClient;
PubSubClient client(espClient);

const int ledGPIO2 = 2;

void setup_wifi() {
  delay(10);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;

  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();

  if(topic=="esp8266/2"){
      Serial.print("Changing GPIO 2 to ");
      if(messageTemp == "1"){
        digitalWrite(ledGPIO2, HIGH);
        Serial.print("On");
      }
      else if(messageTemp == "0"){
        digitalWrite(ledGPIO4, LOW);
        Serial.print("Off");
      }
  }
  Serial.println();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");  

      client.subscribe("esp8266/2");

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
  // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(ledGPIO2, OUTPUT);

  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);    
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  if(!client.loop())
    client.connect("ESP8266Client");
}

Résultats: tout semble bien fonctionner mais le relais n'est pas déclenché quand je clique sur le bouton du serveur web. Je pense que l'ESP n'est pas souscrit correctement. Lorsque j'exécute le script Python sur le terminal, pour le premier clic, je reçois HTTP / 1.1 "404 sur le terminal, et à chaque autre clic, je reçois HTTP / 1.1" 200

Mon Pi travaille actuellement sur IP dynamique. Mais je me suis assuré que l'ESP8266 est configuré avec l'adresse IP Pi actuelle.

Rohit Mathur
la source
1
Cette chaîne de commentaires devient assez longue maintenant; cette conversation a été déplacée vers le chat . Vous pouvez y poursuivre votre discussion dans un environnement plus convivial pour les conversations prolongées. Pensez également à modifier votre question avec des mises à jour ou à poser de nouvelles questions si vous rencontrez des problèmes que vous ne pouvez pas résoudre.
Aurora0001
1
que dois-je ajouter dans mon code si j'ai plusieurs clients?
Rohit Mathur

Réponses:

3

Je vous suggère de décomposer le problème.

Essayez de tester le relais en publiant des messages directement sur le courtier MQTT (c'est-à-dire en utilisant le client mosquito_pub).

Essayez de vérifier si l'application Web publie des sujets et des messages corrects au courtier (c'est-à-dire en utilisant le client mosquito_sub).

Vous pouvez également surveiller le comportement de vos appareils en vous abonnant à la rubrique SYS (c'est-à-dire le nombre total de clients connectés ou d'abonnements).

Ziolek
la source
1
Et ajoutez un ping (publication) à partir de l'ESP8266 afin de pouvoir confirmer qu'il fonctionne et qu'il peut atteindre le serveur MQTT.
MatsK