Die neue NanoESP-Library mit MQTT, HTTP und Blynk-Support

Im Kontext des neues IoT Adventskalenders 2016 wurde die Library zum NanoESP um einige Funktionen erweitert. Neben den klassischen Befehlen zum Steuern des Moduls, gibt es in dieser Version auch zwei Sub-Libraries, die das Übermitteln von Webseiten erleichtern oder die Verwendung des beliebten MQTT(http://mqtt.org/) IoT-Protokolls ermöglichen.

download-151556_640

Download

 

Link auf Github: https://github.com/FKainka/NanoESP

Unter den Beispielen befindet sich außerdem ein Programm, welches Blynk-Projekte (http://www.blynk.cc/) ermöglicht. Damit Sie das Programm verwenden können, benötigen Sie eine zusätzliche Library:

https://github.com/blynkkk/blynk-library/releases/tag/v0.3.4

Auf dieser Seite möchte ich die einzelnen Funktionen und Methoden etwas detaillierter erläutern sowie auf etwaige Neuerungen eingehen. Die Basis der Library bildet die SoftwareSerial-Library, die bereits in Arduino integriert ist. Aufgrund dessen können Befehle wie find() und findUntil() auch mit dieser Library genutzt werden.

Inhalt

Basics (NanoESP)
Webserver (NanoESP_HTTP)
MQTT (NanoESP_MQTT)
 – Datentyp mqtt_msg.
 – Abonnieren mit Funktions-Verknüpfung:

Basics (NanoESP)

FunktionErläuterung
boolean init(boolean vDebug=false);Initialisiert das Board und stellt default Werte ein (Transfermode = 0, Multiple Connections = 1)
Wenn der Debug-Parameter true ist, wird bei einem fehlerhaften Befehl Zusatzinformationen über den Seriellen Monitor ausgegeben
 String sendCom(String command);

 

Sendet ein AT-Kommando an das ESP-Modul
boolean sendCom(String command, char respond[]);s.o.; Zusätzlich wird überprüft, ob das Modul eine Antwort sendet, die dem Respond-Parameter entspricht.
boolean setMultipleConnections();Erlaubt Mehrfachverbindungen (AT+CIPMUX=1)
boolean setTransferMode() ;Setzt den Transfermodus auf transparent (AT+CIPMODE=0)
boolean reset();Resetet das Board und wartet, bis es wieder bereit ist
boolean configWifiMode(int modus);Stellt den WLAN Modus ein (STATION, ACCESSPOINT, DUAL)
boolean configWifi(int modus, String ssid, String password);Stellt das WLAN ein mit Modus, SSID und Password
boolean configWifiStation(String ssid, String password);Stellt eine Verbindung zu einem WLAN-Router her
boolean configWifiAP(String ssid, String password);Stellt einen eignen AccesPoint zur Verfügung (Password darf leer sein, sonst min sechs Zeichen)
boolean configWifiAP(String ssid, String password, int channel, int crypt);

 

S.o.

Zusätzliche Parameter: WLAN-Kanal, Verschlüsselungsmodus

boolean disconnectWifi();Trennt die WLAN-Verbindung
bool wifiConnected();Überprüft, ob automatisch eine WLAN-Verbindung zu einer Station hergestellt wurde (Zeitersparnis gegenüber neue Verbindung bei bekannter Station)
bool getIpMac(String &ip, String &mac);Liefert IP und MAC-Adresse des Boards. Parameter werden als Referenz übergeben
String getIp();Ermittelt die IP/IPs des Boards (AT+CIFSR)
boolean newConnection(int id, String type, String ip , unsigned int port);Baut eine neue Verbindung (TCP oder UDP) auf.

Parameter: Verbindungs-ID (0-4), Typ (TCP/UDP), IP (Ziel IP oder Adresse), Port

boolean closeConnection(int id) ;Trennt die Verbindung mit der angegebenen Verbindungs-ID
boolean startUdpServer(int id, String ip , unsigned int port, unsigned int recvport, int mode=0);

 

Öffnet eine UDP-Verbindung

Der Empfangs-Port kann ein anderer sein als der Sende-Port. Modus 0: Die Ziel IP ändert sich nicht; Modus 1: die Ziel IP ändert sich einmal, wenn das Board eine Nachricht von einer anderen IP erhält; Modus 2: Das Board ändert die Ziel IP immer, wenn es eine neue Nachricht von einer anderen IP erhalten hat.

boolean endUdpServer(int id);

 

Beendet die UDP-Verbindung mit der angegeben ID
boolean startTcpServer(unsigned int port) ;Startet einen TCP-Server unter dem angegeben Port. Es kann nur ein TCP-Server aktiviert sein
boolean endTcpServer();

 

Beendet den TCP-Server
boolean sendData(int id, String msg);Sendet Text über die angegebene Verbindung
boolean sendDataClose(int id, String msg);Sendet Text und schließt danach die Verbindung
bool sendRaw(int id, unsigned char data[], int LenChar);Sendet binäre Daten (kein String)
int getId();Gibt die Verbindungs-ID bei Datenempfang an. Wenn keine Daten empfangen wurden ist der Wert -1
bool recvData(int &id,int &len);Wird true, wenn Daten empfangen wurden. ID und Länge werden per Referenz zurückgegeben
int ping(String adress);Pingt den Server unter der angegebenen Adresse an. Die Antwort-Zeit in ms wird zurückgegeben. Ist die Zeit 0 wurde keine Antwort empfangen.
void serialDebug();

 

Stellt eine direkte Verbindung zwischen Software und Hardware Serieller Schnittstelle her. Kann zum Testen von AT-Kommandos verwendet werden.

 

Webserver (NanoESP_HTTP)

FunktionErläuterung
bool recvRequest(int &id, String &method, String &ressource, String &parameter);Gibt true zurück, wenn ein http-Request empfangen wurde. ID, Methode (POST oder GET) sowie angeforderte URL und etwaige Befehle werden per Referenz zurückgegeben.
bool recvHTTP(int id, int len, String &method, String &ressource, String &parameter);s.o.
bool sendFromFlash(int client, const char *website, int len);Sendet eine als Progmem-Variable gespeicherte Webseite direkt an den angeben Client (Verbindungs-ID)
bool sendStreamHeader(int connectionId);

 

 

Sendet die Antwort auf einen Event-Stream-Request. Server-Send-Events können zum schnellen Datenaustausch vom Server zum Client genutzt werden (http://www.html5rocks.com/en/tutorials/eventsource/basics/)
bool sendRequest(int id, char method[5], String address);Sendet einen http-Request an einen Server
(ID, Methode (GET/POST), URL)
bool sendRequest(int id, char method[5], String address, String parameter);Sendet einen http-Request an einen Server inklusive Sub-Parameter

 

MQTT (NanoESP_MQTT)

FunktionErläuterung
bool connect(int id, String brooker, unsigned int port, String deviceId);Baut eine Verbindung zu einem MQTT-Server auf. Minimale Parameter: Verbindungs-ID, Broker-Adresse und Geräte-ID (darf nur einmal auf dem Broker vorhanden sein)

(Defaultwerte: Clean Session = true, keepAliveTime = 120s)

bool connect( [s.o], mqtt_msg * lastWill);Erweitere Parameter der Connect-Funktion:

Parameter: lastWill-Nachricht

bool connect( [s.o] , bool cleanSession, byte keepAliveTime);Erweitere Parameter der Connect-Funktion:

Parameter: cleanSession, keepAliveTime

bool connect( [s.o] , bool cleanSession, byte keepAliveTime, mqtt_msg * lastWill);Erweitere Parameter der Connect-Funktion:

Parameter: cleanSession, keepAliveTime, lastWill-Nachricht

bool connect([s.o], String userName , String password);

 

Erweitere Parameter der Connect-Funktion:

Parameter: Nutzername und Passwort für Broker mit Benutzerverwaltung

bool connect([s.o],  bool cleanSession, byte keepAliveTime, mqtt_msg * lastWill , String userName , String password);

 

Erweitere Parameter der Connect-Funktion

 

bool disconnect(int id);Trennt Verbindung zum MQTT-Broker
bool subscribe(int id, String topic) ;Abonniert ein Topic
bool subscribe(int id, String topic, byte qos);Abonniert ein Topic mit Qos
bool subscribe(int id, String topic, byte qos, void (*g)(String value));Abonniert ein Topic und weißt dem Topic eine Funktion zu, die aufgerufen wird, wenn eine Nachricht unter dem Topic empfangen wird (s.u. für weitere Erklärungen)
bool unsubscribe(int id, String topic) ;Deabonniert ein Topic
bool publish(int id, String topic, String value);Veröffentlicht Nachricht unter dem angeben Topic
bool publish(int id, String topic, String value, byte qos, bool retain);Veröffentlicht Nachricht unter dem angeben Topic

Zusätzliche Parameter: Quality of Service, Retain

bool publish(int id, mqtt_msg *msg);Veröffentlicht Nachricht unter dem angeben Topic (Datentyp mqtt_msg s.u.)
bool recvMQTT(int id, int len, String &topic, String &value);Gibt True zurück wenn eine MQTT-Nachricht empfangen wurde. Topic und Nachricht per Referenz
bool recvMQTT(int &id, String &topic, String &value) ;Gibt True zurück wenn eine MQTT-Nachricht empfangen wurde. ID, Topic und Nachricht per Referenz
void stayConnected(int id);Hält die Verbindung zum Broker aktiv, indem in regelmäßigen Abständen (i.d.R. StayConnected-Zeit/2) ein Ping gesendet wird
bool ping(int id);Pingt den MQTT-Broker an (damit Verbindung bestehen bleibt)

 

Datentyp mqtt_msg

Mqtt_msg ist eine Struktur, über die eine MQTT-Nachricht definiert werden kann.

  typedef struct{

               String topic;

               String value;

               byte qos;

               bool retain;

  } mqtt_msg;

 

Beispiel:

mqtt_msg msgMode = {„NanoESP/test/rgb/mode“,“1“, 0, true}; 

Es können auch einzelne Werte der Nachricht verändert werden:

msgMode.value = „0“;

 

Abonnieren mit Funktions-Verknüpfung:

In dem Befehl

bool subscribe(int id, String topic, byte qos, void (*g)(String value));

kann als letzter Parameter eine Funktion angeben werden, die dann aufgerufen wird, wenn zu diesem Topic eine Nachricht empfangen wurde (Wildcards erlaubt). Die Funktion muss einen Parameter vom Typ String haben, der die Nachricht des Topics enthält. Es können maximal 5 dieser Funktions-Verknüpfungen definiert werden.

Beispiel:

mqtt.subscribe(0, „test/song“, 2, gotnewSong)

 

void gotnewSong(String value) {

Serial.println(„New Song: “ + value);

}

26 Kommentare

  1. Björn Starkimarm

    Ich habe mir aus einem NanoESP mit einem DHT22-Sensor ein Munin-Thermometer/Hygrometer gebaut und mußte dafür die NanoESP-Library anpassen. Ist vielleicht auch noch für den einen oder anderen interessant. Der Code funktioniert für mich, ist aber höchstwahrscheinlich unelegant und/oder fehleranfällig:

    NanoESP.h:

    String getStatus();
    bool recvData(int &id,int &len,String &msg);

    NanoESP.cpp:

    //new
    String NanoESP::getStatus()
    {
    return sendCom(at+“CIPSTATUS“);
    }

    // +msg
    bool NanoESP::recvData(int &id,int &len,String &msg)
    {
    if (this->available()) {
    if (this->findUntil(„+IPD,“, „\n“) ) {
    id = this->parseInt();
    if (id >= 0) {
    this->find(„,“);
    len = this->parseInt();
    // new
    if (len >= 0) {
    char rcvmsg[len];
    this->readBytes(rcvmsg,len);
    msg = rcvmsg[1];
    for(int i=2;ifind(„:“); DONT!
    return true;
    }
    }
    }
    }
    return false;
    }

    1. Björn Starkimarm

      Hmpf, WordPress oder was auch immer drunter ist interpretiert spitze Klammern…

      bool NanoESPtw::recvData(int &id,int &len,String &msg)
      {
      if (this->available()) {
      if (this->findUntil(„+IPD,“, „\n“) ) {
      id = this->parseInt();
      if (id >= 0) {
      this->find(„,“);
      len = this->parseInt();
      // tw 2016-12-26
      if (len >= 0) {
      char rcvmsg[len];
      this->readBytes(rcvmsg,len);
      msg = rcvmsg[1];
      for(int i=2;ifind(„:“); DONT!
      return true;
      }
      }
      }
      }
      return false;
      }

      1. Björn Starkimarm

        Nächster Versuch:

        bool NanoESPtw::recvData(int &id,int &len,String &msg)
        {
        if (this->available()) {
        if (this->findUntil(„+IPD,“, „\n“) ) {
        id = this->parseInt();
        if (id >= 0) {
        this->find(„,“);
        len = this->parseInt();
        // tw 2016-12-26
        if (len >= 0) {
        char rcvmsg[len];
        this->readBytes(rcvmsg,len);
        msg = rcvmsg[1];
        for(int i=2;i<len;i++)
        {
        msg.concat(rcvmsg[i]);
        }
        //this->find(„:“); DONT!
        return true;
        }
        }
        }
        }
        return false;
        }

  2. Niklas Kappel

    Ich verstehe den Befehl nanoesp.recvData nicht. Ich möchte gern mit einem NanoESP per UDP ein Paket an einen anderen senden. Der Sender NanoESP sendet vermutlich auch, ich finde jedoch keinen Code, mit dem ich empfangen könnte…

  3. Bertram Kaufmann

    Das ESP8266 lässt sich mit der Arduino IDE direkt Programmieren, wozu dann noch ein Arduino NANO ?
    Den einzigen Vorteil den ich sehe sind die Verfügbarkeit Analoger I/O und mehr I/O durch den Nano.
    Der ESP8266 hat nur 1 Analogen Input, aber er kann I2C.
    Dort wo ich dieses Teil Einsetze braucht es nicht viel,
    und mit der ESP8266 Bibliothek hab ich alles was ich brauche.
    Wozu also ein NANO, der ESP ist kleiner und bringt alles mit was man für IOT braucht. AT-Kommandos war gestern, Petzel war gestern…

  4. Luca

    Ich hab ein wenig mit dem tcp server beispiel gespielt und hab ein paar pakete an den Nano esp geschickt. Was auch sehr gut funktioniert hat. Der Inhalt der Pakete scheint als method gespeichert zu werden? Dahinter wird aber immer ein +IPD,0,2: gehängt (Zumindest wenn ich mir über den seriellen Monitor die Variable anzeigen lasse). Wenn ich versuche das Nano Esp per TCP anzusteuern, also denn Inhalt der Pakete mit Strings zu vergleichen komme ich in Schwierigkeiten. Mit was muss ich vergleichen wenn LED zum beispiel das code wort für das einschalten einer LED seien soll? Einfach mit method funktioniert nicht, auch das anhängen des +IPD,0,2:
    bringt nichts.

  5. H.-P. Mayer

    ich habe die Library
    https://github.com/FKainka/NanoESP/archive/v1.1.zip
    erfolgreich eingebunden –
    darin befindet sich aber kein Wifi_Scanner,
    wie im Adventskalender-Manual versprochen.
    Wo ist den die Library mit dem Wifi_Scanner ?
    Würde ich gerne ausprobieren.
    Vielen Dank

    1. Terence

      Hallo,
      du musst unter Datei -> Beispiele -> ganz unten in dem Abschnitt: Beispiele aus eigenen Bibliotheken -> NanoESP-master-> Basics suchen. Dort ist der Wlan scanner zu finden.

      Schöne Grüße
      Terence

      1. H.-P. Mayer

        Hallo Terence,
        ich habe es jetzt gerafft, bei mir war die Ordnerstruktur nicht richtig angelegt.
        Aber jetzt ist alles da !
        Vielen Dank und Gruß
        HP

  6. bernd

    Habe auch probleme mit der Bibliotek:
    siehe Bild. Und wenn ich versuche die umbenannte (ohne 1.1) hinzuzulegen kriege ich nur: the library is already present.
    Wie werde ich die los um es nochmal zu machen?
    Unter den Arduino biblioteken ist weder die eine noch die andere

    1. sumero

      Schau mal in dein Userverzeichnis unter:
      C:\Users\\Documents\Arduino\libraries
      dort ist vermutlich noch das Verzeichnis NanoESP verzeichnis

      1. sumero

        Schau mal in dein Userverzeichnis unter:
        C:\Users\deinUsername\Documents\Arduino\libraries
        dort ist vermutlich noch das NanoESP Verzeichnis

        1. Bernd

          ja, gefunden danke Sumero. Suchte unter programs/arduino/libraries da war’s nicht.
          jetzt tut sich was, aber der com3 ausdruck ist total unleslich:

          siehe bild.
          legt vielleicht daran dass mein Windows Schwedisch ist.
          wo kann ich die richtige Sprache für den Ausdruck einstellen?
          alles andere ist kein problem.

          1. Bernd

            problem gelöst, falsche Bautrate

  7. M

    Cool. Ich versuche die Library zu laden:

    „Die Library „NanoESP-1.1″ kann nicht verwendet werden.Librarynamen dürfen nur normale Buchstaben und Zahlen(ausschließlich ASCII ohne Leerzeichen und ohne Zahl als erstes Zeichen enthalten.“

    1. fk (Beitrag Autor)

      Hallo,
      Github fügt leider automatisch die Versionsnummer mit an. D.h. die Zip-Datei muss umbennant werden, z.B. in NanoESP.zip

      1. hans r.

        Nun hab‘ ich auch endlich Zeit gefunden für den Adventskalender, allerdings bekomme ich folgende Fehler nach dem Umbenennen:

        Der Sketch „AT-Commands“ kann nicht verwendet werden. Sketchnamen dürfen nur normale Buchstaben und Zahlen […] Bitte löschen Sie diesen Sketch von …, um diese Meldung loszuwerden.

        Der Sketch „TCP-Server“ kann nicht …

        Der Sketch „WiFi-Connect“ kann nicht …

        und so weiter. Insgesamt fünf Meldungen. Klar könnte ich die Dinger jetzt umbenennen, aber irgendwas muss ich doch falsch machen, oder?

    2. sumero

      Bei mir hat das laden problemlos funktioniert. Arduino IDE 1.6.13

  8. Tobias Studiger

    Hallo,
    Wir versuchen die Bibliothek des Tages 2 einzubinden und bekommen die Fehlermeldung „ZIP enthält keine Bibliothek“. Woran liegt das? Danke für die Unterstützung.

    1. Andi Hippauf

      Windows oder Mac? Auf meinem Mac hat Safari die Bibliothek gleich entpackt, musste sie als erst wieder in ein ZIP Zurückpacken.

    2. el_Caro

      Das Einbinden des Zipfiles hat bei mir auch nicht funktioniert (Kleinweich 10). Nachdem ich den entpackten Ordner nach Programme-x86/Arduino/libraries kopiert habe, konnte ich die Beispiele ansteuern.

  9. Dietmar

    Hallo Zusammen

    Ich versuche eine MQTT Verbindung zu einem Mosquitto 3.1.1 unter Linux herzustellen.

    Ohne Userid/Password bekomme ich den RC=1. Mit Userid/Password bekomme ich RC=5.

    Andere Client (Linux) können sich mit Userid/Password problemlos verbinden.

    Hat jemand eine Idee?

    1. Andi

      HI,

      habe das selbe Problem, kann es an dem connect liegen?

      mqtt.connect(0, „IP“, 1883, mqttId, „User“, „passwd“))

      Danke schon mal

      1. Florian

        hi, ich habe das gleiche problem , konntest du es lösen?

  10. Kwi

    Hallo,

    Thx auch lot for this libraries.

  11. Leo de Blaauw

    Hello,

    Just onto day 6 and everything mostly works great here ! A lot of fun figuring things out but this library is a great addition instead of having all these AT commands directly into the code it makes it much cleaner. I will give this a go in reprogramming some examples ;-)

    Thank you!

    Greetings,
    Leo

Schreiben Sie einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.