HTTP 1.1 Webserver für ESP8266 als Accesspoint

Ich hatte vor einiger Zeit ein Codebeispiel für einen stabilen HTTP 1.1 Webserver für den ESP8266 gepostet (klick). Dieser Code ist in der Arduino IDE verwendbar, wenn man diese mit dem Boardmanager für den ESP8266 erweitert (klick). Mit dem bestehenden Codebeispiel loggt sich der ESP8266 in ein bestehendes WLAN ein und bezieht von dort per DHCP eine IP Adresse.

In einigen Fragen/Kommentaren haben Leser ein Codebeispiel für einen Accesspoint gewünscht. Dabei loggt sich der ESP8266 nicht in ein bestehendes WLAN ein, sondern erzeugt einen eigenen Accesspoint. Nicht ganz sauber aber allgemeinverständlicher formuliert: Der ESP8266 macht sein eigenes WLAN mit eigenem Namen und man kann sich per PC, Tablet oder Mobiltelefon damit verbinden.

Der Code ist an dem bereits geposteten Beispiel orientiert. Die Codeänderungen sind:
1. Am Anfang wird nun nicht mehr die SSID und das Passwort des Ziel WLANs eingetragen, sondern die Werte für das vom ESP zu erzeugende WLAN.
2. Der Reconnect Counter entfällt – macht keinen Sinn.
3. Das WLAN wird mit dem Modus WIFI_AP erzeugt. ssid und Passwort werden per API übergeben.
4. Die Wifi Startroutine entfällt. Ebenso der Check, ob noch eine Verbindung zum WLAN besteht. Brauchen wir nicht mehr. Wir machen jetzt unser eigenes WLAN.
Geprüft habe ich den Code mit der ESP8266 Erweiterung mit SDK Version 1.20 auf einer Arduino IDE 1.6.5.

In dem Beispiel wird ein WLAN namens ESP-Accesspoint erzeugt. Das WLAN Passwort ist auf 12345678 eingestellt. Wenn man einen Windows PC oder ein Android Gerät verbindet, kann das einen Augenblick dauern. Dies liegt nicht am ESP oder am Beispielcode. Beide Betriebssysteme prüfen zunächst für einige Sekunden, ob das WLAN auf das Internet zugreifen kann. Das geht natürlich nicht, da der ESP in diesem Beispiel sein eigenes WLAN erzeugt und keinerlei Verbindung zum Internet hat.
Android reagiert darauf mit der Meldung „Internet event. nicht verfügbar“. Diese bitte mit OK bestätigen. Windows 10 zeigt in der Netzwerkanzeige an, dass es sich um eine eingeschränkte Netzwerkverbindung handelt.
WebServerAP_Networks
Wenn man dann in einem Browser http://192.168.4.1 eingibt, sollte die vom ESP erzeugte Webseite erscheinen.
WebServerAP
Im seriellen Monitor kann man die Ausgaben überprüfen, wenn man die Knöpfe auf der Seite klickt. GPIO2 kann auch geschaltet werden.
WebServerAP_Serial

Hier gibt es den Code: ESP_WebServerAP

Viel Erfolg!

P.S.: password = "" –> WLAN ist offen und ohne Passwort.

79 Gedanken zu „HTTP 1.1 Webserver für ESP8266 als Accesspoint

  1. Peter

    Hallo, ich habe mir Deine zip-Datei heruntergeladen und wollte diese gleich ausprobieren. Main Arduino-Programm meckert dass er die nicht findet. Welche Datei hast Du hier includiert?

    Danke schon mal für Deine Antwort!

    Gruß, Peter

    Antworten
    1. ST Beitragsautor

      Hi Suat,

      die ESP8266WiFi.h gibt es, wenn Du die Arduino IDE für den ESP8266 erweitert hast (kick) und das Board auf „Generic ESP8266“ stellst.
      Viel Erfolg!

      Gruss Stefan

      Antworten
  2. Werner

    Hallo,
    erstmal möchte ich mich für diesen Beitrag bedanken. Ich denke er könnte mein Problem lösen.
    Ich möchte 4 Arduino-Boards mit einem 5 Arduino-Board seriell (möglichst schnell) per WLAN kommunizieren lassen. Ich dachte mit das Master Modul (1) als Accesspoint mit Webserver aufzusetzen und die 4 anderen Module (2-5) als Webserver. Alle Module sind gleich aufgebaut: 3,3v Versorgung für den ESP8266, 5V für den Arduino Uno und GND für beide. Der RX (Arduino) ist mit dem TXD (ESP 12E) direkt verbunden. Der TX (Arduino) mit einer Pegelanpassung (5V-3,3V) mit dem RXD (ESP 12E).
    Da ich keine Erfahrung mit dem ESP8266 habe ergeben sich für mich folgende Fragen:
    Würde das im Prinzip mit den von dir bereitgestellten Softwaremodulen funktionieren?
    Noch eine Nebenfrage: Welche Beschaltung hat der ESP8266. Vieleich kannst du mir eine Skizze deiner Schaltung zusenden.
    Schon mal vielen Dank im voraus.
    Werner

    Antworten
    1. ST Beitragsautor

      Hallo Werner,

      zur generellen Beschaltung schau bitte mal hier rein (klick); da ist eine kleine Programmierplatine beschrieben. Und hier (klick) habe ich einen Arduino und einen ESP für eine Markisensteuerung verbunden und die Kommunikation per serieller Schnittstelle gelöst. Das sollte zu Deiner Fragestellung passen. Der ESP8266 12E hat ein leicht anderes Layout ist aber elektisch identisch.

      Zur der Kommunikation: Die SW hier baut einen kleinen Webserver auf. Natürlich kannst Du einen solchen Webserver nehmen und dann mit Hilfe der Client ESPs Daten übertragen, in dem Du geeignete URLs auf dem Webserver ansprichst (die Daten kommen dann als Parameter). Zu der Clientseite ist hier kein Code hinterlegt. Es gibt aber Beispiele im Netz.
      Alternativ könntest Du auf dem Server mehrere Ports aufmachen und da drauf von der Client Seite aus schreiben. Dann nimmst Du den http Overhead weg.

      Gruss Stefan

      Antworten
  3. ST

    Es sollte möglich sein, Dateien wie html, jpg oder css mit draufzuflashen. Ich habe beides bisher nicht getan. Spontan fallen mir zwei Möglichkeiten ein.

    Möglichkeit 1: Datei in eine Header Datei konvertieren. Dazu gibt es Tools im Netz; z.B. hier http://sourceforge.net/projects/bin2header/

    Möglichkeit 2: Google mal nach der ESPFS Bibliothek und den Kommandos espFsOpen, espFsRead etc. Damit kann man sich Dateien in einer Art Dateisystem ablegen.

    Gruss Stefan

    Antworten
  4. ST

    Woher die 192.168.4.1 kommt? – Hat sich vermutlich irgend ein Programmierer bei Espressif so ausgedacht 🙂

    Du kannst das aber auch nach Gusto einstellen; ergänze den Code einfach um jeweils die zweite Zeile (die erste ist mit drin, damit Du die Stelle findest):

    WiFiServer server(80);
    IPAddress apIP(192, 168, 1, 1);

    und

    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));

    Antworten
  5. Bastelfreund

    Servus,

    erstmal ein großes Dankeschön für das super Tutorial. Ich habe bei der AP-Variante das Problem, das unabhängig der eingestellten SSID und PW immer das gleiche Wlan Netz ohne erforderliches PW angezeigt wird. Hat jemand eine Idee an was das liegen könnte. Ich hab zuvor einmal per original FW und AT Kommano einen AP konfiguriert, dann aber auf die Arduino IDE umgestiegen.

    Vielen Dank & Grüße
    ~Bastelfreund~

    Antworten
  6. Bernd Günther

    Hi,

    vielen Dank für den tollen Artikel, der hat mir sehr geholfen. Aus irgendeinem Grund klappt die WLAN-Verdindung bei Windows 10 nicht, wohl aber mit dem Handy und auch mit Windows 7.

    Du hattest Dich doch erfolgreich mit Windows 10 conneten können, oder?

    Viele Grüße

    Bernd

    Antworten
    1. ST Beitragsautor

      Hi Bernd,

      Ich kann mich Windows 10 verbinden. Ich vermute, dass die Ursache irgendwo in den unzähligen Netzwerkeinstellungen liegt. Windows 10 prüft immer die Internetkonnektivität eines WLANs. Der Accesspoint hat natürlich keine. Irgendwo kann man einstellen, dass Windows solche Access Points nicht nimmt.

      Gruß Stefan

      Antworten
  7. Hackan

    Bin in diesem Bereich ein Anfänger.
    behelfe mir meist mit google.
    Habe mir den Code auch nicht im Detail angeschaut. Meist sieht man Codes, in dem man Relais toglen (ein und ausschalten kann, aber ich bräuchte etwas, wo ich einen Button anklicke und dies einen Taster simuliert und der Relais eine bestimmte Zeit geschaltet wird und wieder sich löst.
    Natürlich schaue ich mir den Code noch genauer an, vielleicht verstehe ich ja etwas raus und kann es etwas umschreiben.
    Danke noch im Voraus

    Antworten
  8. snafu

    Hallo Stefan! Vielen Dank für deine Mühe! Ich habe dein vorletztes Beispiel „ESP8266 im bestehenden WLAN, DHCP“ nachvollzogen und damit eine schicke Funksteckdose gebaut.

    Jetzt möchte ich ein bestehendes Schließsystem umbauen (derzeit öffnen wir per SMS unsere Tür vom Space). Dazu wäre dein letztes Beispiel ideal.

    Siehst du eine Möglichkeit, dass man den ESP so konfigurieren kann, dass er Anfragen an *beliebige* IP-Adressen und URLs beantwortet? So wie man es von Wlan Accesspoints in Hotels kenn, wo man erstmal auf einer Anmeldeseite landet…

    Dann muss man den Nutzern eine Handlung weniger beibringen 😉

    Antworten
    1. ST Beitragsautor

      Schau Dir mal das Beispiel Captive Portal an, welches bei der ESP Erweiterung mitkommt. Ich habe es selbst nie genutzt. Der Code erzeugt einen Accesspoint und lenkt die alle Anfragen auf eine Defaultseite um.
      Die Alternative wäre es, den ESP ins Heimnetz zu hängen und das Öffnen der Türe darüber zu steuern. Das hätte den Vorteil, dass Du nicht zwei konkurrierende WLAN Accesspoints zu Hause hast und die Handys ggf im „Tür WLAN“ sind und dann keinen Internetkontakt haben. Ob Dir das alles sicher genug ist, wäre die andere Diskussion.

      Viel Erfolg
      Stefan

      Antworten
  9. Marcus

    Hallo Stefan,

    vielen Dank für den schönen Code, den Du hier veröffentlicht hast.
    Ich habe damit ein kleine Problem. Die Buttons sind mir zu klein. Auf einem Tablet ist das kritisch. Man muss genau den Text im Button treffen, damit eine Reaktion erfolgt.
    Gibt es dafür eine einfache Lösung?

    Viele Grüße
    von
    Marcus

    Antworten
  10. ST

    Hallo Marcus,

    eigentlich ist der html Code so gemacht, dass er die Breite des Tablets/Telefons ausnutzen soll. Ich bin nicht der Super-html-Experte. Die Lösung sollte in dieser Zeile liegen:
    content=\“width=device-width, initial-scale=1.0, user-scalable=yes\“

    Dreh ggf mal die inital-scale hoch.

    Gruss Stefan

    Antworten
  11. Softsolution

    Hallo,
    gibt es eigentlich eine Möglichkeit, dass die Verbindung zu Webserver (ESP8266) nicht nach jedem Request beendet wird ? Das führt dazu, dass ein Client erst wieder die Verbindung herstellen muss, was relativ lange dauert.

    Antworten
    1. ST Beitragsautor

      Man kann das prinzipiell machen. Der Code würde natürlich deutlich komplexer:
      wenn ein neuer Client verbindet, muss man sich diesen in einem array des Typs WiFiClient merken. Dann im Code immer alle Clienten versorgen; und das je nach Zustand. Und natürlich am Ende des loop() nicht immer client.stop() aufrufen. Irgendwann muss man die Verbindung dann schließen, sonst geht das RAM aus. Schau mal in den Seriel2Telnet Code. Dieser Code kann mehrere Clienten parallel betreiben und lässt die Verbindung stehen.
      Letztlich ist das eine Menge Aufwand und man muss das RAM sehr gut im Auge behalten. Bisher hatte ich nicht die Notwendigkeit dafür.

      Gruss Stefan

      Antworten
      1. Softsolution

        Hallo Srefan,
        Vielen Dank für deine Antwort. Im Netz habe ich schon versucht, das Problem zu googlen. Bisher leider ohne Erfolg. Das Projekt, das du nanntest kannte ich noch nicht und werde es mal näher anschauen…

        Gruß Softsolution

        Antworten
  12. Phil

    Hallo,

    ich hab mir den code geladen und nach meinen ansprüchen angepasst.
    Ich habe jedoch ein Problem, immer wenn ich die Zeilen
    — Serial.println(„new client“);
    — Serial.println(„Client disonnected“);
    raus nehme, dann bekomme ich immer einen Fehler beim uploaden.

    Wie kann ich das umgehen?

    Hintergrund ist diese das ich die Seriellen Signale abgreife und nur den Text An bzw Aus übermitteln will um diese mittels µC zu lesen.

    Antworten
    1. ST Beitragsautor

      Hallo Phil,

      Ich kann das bei mir nicht nachvollziehen. Du kommentierst die beiden Zeilen raus und dann kommt was für ein Fehler?

      Gruss Stefan

      Antworten
      1. Phil

        warning: espcomm_send_command: didn’t receive command response
        warning: espcomm_send_command(FLASH_DOWNLOAD_DATA) failed
        warning: espcomm_send_command: wrong direction/command: 0x01 0x03, expected 0x01 0x04
        error: espcomm_upload_mem failed
        error: espcomm_upload_mem failed

        Antworten
        1. ST Beitragsautor

          Kann es sein, dass Du eine veraltete ESP Erweiterung installiert hast? – Versuche mal über den Boardmanager upzugraden. Alternativ einfach mal hier das esp8266 Unterverzeichnis killen und die ESP Erweiterung neu installieren:
          C:\Users\—DEIN BENUTZERNAME—\AppData\Local\Arduino15\packages\esp8266

          Gruss Stefan

          Antworten
  13. Purehunter

    Hallo,
    Ich habe den Code noch nicht eingesetzt, sollte aber als Basis für meine Anwendung gut sein. Es soll ein AP einen Webserver bereitstellen, auf dessen Homepage man einen Log eintragen kann, mehr nicht.
    Habe aber eine Frage zu dem Beispiel. Im Browser Fenster ganz oben wird auf die IP 192.168.4.1 zugegriffen. Wo kommt diese IP her? Und wo die für die Clients? Im Code kann ich nichts dazu finden.

    Antworten
    1. ST Beitragsautor

      Die IP ist ein Standardwert aus dem Esp Framework. Kannst Du auch anders setzen. Evtl ist für Dich auch das Beispiel CaptivePortal interessant. Das Beispiel wird mit der Esp Erweiterung mitgeliefert.

      Gruss Stefan

      Antworten
  14. Jürgen Pirker

    Guten Tag Herr Thesen!
    Vielen Dank für Ihr Wissen und Können, dass Sie zur Verfügung stellen.
    Sowohl „ESP-WLAN-Microcontroller“ so wie „HTTP 1.1 Accesspoint“ als auch „WLAN Lufttemeratur -Logger mit Grafik“ laufen problemlos.
    Gescheitert bin ich beim Versuch das Programm: „WLAN Lufttemperatur und Feuchte-logger+grafik“ so umzubuen, dass es als Accesspoint funktioniert. Das läuft zwar aber mir der NTP-Zeit gibt es Probleme.
    Meine Frage (Bitte): Kann der ESP8266 als Accesspoint die NTP_zeit beziehen?
    Vielen Dank

    Antworten
  15. ST

    Hallo Herr Pirker,
    als Accesspoint kann der ESP keine Zeit aus dem Internet beziehen. Der ESP kann in einem Modus laufen, in dem er Client eines Wifi ist und gleichzeitig einen Accesspoint erzeugt. Damit könnte man über die Internet Verbindung als Wifi Client die NTP Zeit beziehen und hätte die richtige Zeit im Accesspoint.
    Ich habe den Mix-Modus selbst noch nie verwendet, weil ich dazu nie einen Einsatzzweck hatte. Es sollte aber analog der Beispiele für Accesspoint und Wifi Client laufen. WiFi.mode(WIFI_AP_STA) sollte den Modus setzen.

    Viel Erfolg
    Gruss Stefan

    Antworten
  16. Manuel

    Sehr schönes Tutorial. Hat mir sehr weiter geholfen.
    Ist es auch möglich eine Art Slider zu programmieren, der dann seinen Wert an den ESP8266 übermittelt und diesen dann von dort aus via serieller Schnittstelle ausgibt?
    Gruß Manuel

    Antworten
  17. Jürgen

    Guten Tag Herr Thesen!
    Es ist mir erfolgreich gelungen „ESP als Accesspoint“ in “ ESP_TH_LOGGER_V2″ einzubauen.
    Der Luxus wäre: über den Schalter
    „(neue) WIFI Zugangsdaten speichern“ dem ESP eine fixe IP zuzuweisen, bevor er dann der „_LOGGER_V2“ starttet.
    Leider gelint mir das nicht.
    Vielen Dank für einen Hinweis.
    Jürgen

    PS
    Ich bin Pensionist. Es ist mein geistiges Fitnestraining Ihre Programme so oft zu lesen, bis ich sie verstehe, ändern und anpassen kann.

    Antworten
  18. Peter

    Hallo,
    ich Versuche über den Webserver ein Ferngesteuertes Auto zu steuern, statt der Led soll dann halt der Motor an und ausgehen.
    Gibt es eine Möglichkeit die Sendeverzögerung zu Verringern?
    Sodass nicht nach drücken einer Taste auf dem Server erst einmal 2s vergehen?
    MFG

    Antworten
    1. ST Beitragsautor

      Hallo Peter,

      in dem Beispiel wird nach einem Knopfdruck eine http Verbindung aufgebaut und eine Seite gesendet. Das dauert ein wenig.
      Ein Möglichkeit für Deine Problemstellung wäre per Javascript im Browser auf die Knöpfe zu reagieren und dann direkt Strings auf einen offenen Port am ESP zu senden.

      Gruss Stefan

      Antworten
      1. Peter

        Hallo Stefen,

        kennst du eine gute Anleitung um so etwas zu schreiben?
        Lässt sich eine Javascript Bibliothek beim Arduino einbinden?

        MFG

        Antworten
        1. ST Beitragsautor

          Hallo Peter,

          eine exemplarische Einbindung von Javascript gibt es in diesem Beispiel hier:
          https://blog.thesen.eu/wlan-lufttemperatur-und-feuchte-logger-mit-grafischer-darstellung-fuer-esp8266/

          Der Javascript Code wird vom ESP im Rahmen der Webseite an den Browser gesendet. Die Arduino IDE sieht dabei html & Javascript nur als Strings an. Deshalb braucht sie dafür keine lib o.ä. Wenn Du so etwas lernen möchtest, schaue nach Infos zur Webprogrammierung. Ich bin diesbezüglich nur sehr amateurhaft unterwegs 🙂

          Gruss Stefan

          Antworten
          1. Peter

            War zwar etwas schwierig aber ich habe es jetzt mit Javascript hinbekommen 🙂

            Nun frage ich mich ob es eine Möglickeit gibt festzustellen ob ein Gerät mit dem ACcespoint des Esp verbunden.
            Man könnte so z.b wenn man das Wlan an seinem Handy ausschaltet die lichter des Ferngesteuerten Autos ausgehen lassen.

            Nur ist die Frage wie? Client Diconnected kommt ja immer schon nach jeder Information die ich Erfolgreich Empfangen und verarbeitet habe.

            Wie könnte man dies umsetzten?
            Gruß Peter

          2. ST Beitragsautor

            Hallo Peter,

            die Sache mit den in einen AP eingeloggten Clients habe ich noch nicht probiert. Google mal nach wifi_softap_get_station_num(). Evtl. kommst Du damit weiter.

            Gruss Stefan

  19. Jürgen

    Guten Tag Herr Thesen!
    Jedesmal wenn die Seite neu geladen wird, zB durch refresh, wird die letzte Eingabe mitgesendet. Wenn also ein Button „AUF“ gedrückt wird, wird bei jedem Neuaufbau der Seite der Soll Wert erhöht. (siehe Schnipsel unten)
    Wie kann man erreichen, dass EINE Eingabe NUR EINMAL gesendet wird?
    Vielen Dank
    Jürgen

    if(sPath==“/“) // format the html page for /
    {
    // react on parameters
    if (sCmd.length()>0)
    {
    // SOLL TEMPERATUR. AUF/AB
    if(sCmd.indexOf(„AUF“)>=0)
    {
    t_soll = t_soll + 0.5;
    }

    Antworten
    1. ST Beitragsautor

      Hallo Jürgen,

      wenn Du die Seite neu lädst, dann sind in der URL die Parameter enthalten (siehe Adresszeile in Browser). Wenn die Parameter wiederholt gesendet werden, dann werden sie auch wiederholt verarbeitet.
      Lösung a: (Ich habe das nie umgesetzt). Den Parametern einen Zähler mitgeben. Diesen bei jedem Aufruf inkrementieren. Einen bestimmten Zählerstand nur einmal umsetzen und danach ignorieren.
      Lösung b: von http get auf post wechseln.
      Lösung c: Falls Parameter bei der URL dabei sind, eine andere minimale http Seite anzeigen:

       sResponse  = F("<html><head><meta http-equiv=\"refresh\" content=\"1;url=/\" /></head><body><h1>Verarbeite Kommando...</h1></body></html>"); 

      Damit wird nach einem Tastendruck kurz „Verarbeite Kommando…“ angezeigt und dann die Seite neu und ohne Paramter in der URL geladen.

      Gruss Stefan

      Antworten
  20. Jürgen

    Servus Stefan,
    vielen Dank für Deine Antwort! Jetzt funktioniert’s.
    Ich verwende Lösung C . Als letzte Zeile von:
    if (sCmd.length()>0)
    {
    }
    Mit Dank und lieben Grüßen
    Jürgen

    PS.
    Die Sommerzeit wäre noch was schönes.

    Antworten
  21. Jürgen

    Guten Tag Herr Thesen!
    Ich bin auf der Suche nach einem BUTTON, der die Farbe ändert. Die folgenden zwei Teile habe ich in den ESP_Websurfer eingebaut.
    Aber: Entweder der Schalter wechselt auf click die Farbe oder
    sCmd wird übertragen. Beides sollte sein.
    Haben Sie eine Lösung?
    Vielen Dank
    Jürgen

        sResponse += "Funktion 1 <a href="?pin=FUNCTION1ON" rel="nofollow">einschalten</a>&nbsp;<a href="?pin=FUNCTION1OFF" rel="nofollow">ausschalten</a>";
        sResponse += "Funktion 2 <a href="?pin=FUNCTION2ON" rel="nofollow">einschalten</a>&nbsp;<a href="?pin=FUNCTION2OFF" rel="nofollow">ausschalten</a>";
        sResponse += "     ";
        sResponse += "        Press "; 
        sResponse += "          <a href="?pin=FUNCTION1ON" rel="nofollow">Press</a>  "; 
        sResponse += "         ";
        sResponse += "         ";
        sResponse += "            $(() =&gt; { ";
        sResponse += "                'use strict'; ";
        sResponse += "                $('button').click(function() { ";
        sResponse += "                    $(this).toggleClass('pressed'); ";
        sResponse += "                }); ";
        sResponse += "            }); ";
        sResponse += "         ";  
    
    und 
    //    sHeader  = "HTTP/1.1 200 OK\r\n";
        sHeader = " ";
        sHeader += " ";    
        sHeader += "     ";
        sHeader += "         ";
        sHeader += "        Button Fun ";
        sHeader += "         ";
        sHeader += "            button { ";
        sHeader += "                background-color: blue; ";
        sHeader += "                height: 40px; ";
        sHeader += "                width: 120px; ";
        sHeader += "            } ";
        sHeader += "           button.pressed { ";
        sHeader += "                background-color: red; ";
        sHeader += "            } ";
        sHeader += "         ";
        sHeader += "     ";         
        sHeader += "Content-Length: ";
    
    Antworten
    1. ST Beitragsautor

      Keine Ahnung – WordPress hat mit den Beitrag mit Code zur Moderation gesendet. Ich habe ihn freigegeben und den Code als Codesektion markiert.
      Kann jeder machen: Eckige Klammer auf, dann „cpp“ und eckige Klammer wieder zu. Danach der Code. Am Ende des Codes wieder die eckigen Klammern. Dazwischen /cpp

      Gruss Stefan

      Antworten
  22. Jürgen

    Sehr geehrter Herr Thesen,
    vorweg Vielen Dank für Ihre Mühen.
    Vielleicht bin ich so verständlicher. Ich habe zwei button-Lösungen gefunden die mir gefallen:
    Ein FlipFlop-Schalter (mit Text) auf:
    https://wiki.selfhtml.org/wiki/HTML/Tutorials/Buttons_und_Schalter
    sowie:
    https://codereview.stackexchange.com/questions/134106/changing-color-on-button-click
    Beide funktionieren auf dem Bilschirm. Ich möchte aber einen pin HIGH/LOW schalten. So wie in Ihrem Webserver „href=\“?pin=PUMPE_EIN“ . Aber das gelingt mir nicht.
    Dank
    Jürgen

    Antworten
  23. ST Beitragsautor

    Hallo Jürgen,

    ich bin kein html Profi. Generell musst Du schauen, ob der html Code oder der Code im Backend auf dem ESP das Statehandling macht. Das hier klappt mit dem Code zusammen:

    <!DOCTYPE html>
    <html>
    <head>
    <style>
    .button1 {
        background-color: #FF00FF;
        padding: 15px 32px;
        text-align: center;
        text-decoration: none;
        display: inline-block;
        font-size: 16px;
        margin: 4px 2px;
    }
    </style>
    </head>
    <body>
    
    <h2>Farbiger Knopf</h2>
    
    <a href="/blablabla" class="button1">Drück mich</a>
    
    </body>
    </html>
    

    Gruss Stefan

    Antworten
  24. Jürgen

    Guten Morgen Stefan!
    Vielen Dank für Deine Mühen. Es ist noch nicht ganz das, wonach ich suche.
    Beim mitgeschickten Code schicken deine buttons ein sCmd der andere Schalter wechselt die Farbe. Schön wäre beides.
    Nochmals vielen Dank.
    Jürgen

     
        sResponse += "<head> ";
        sResponse += "<script> ";
        sResponse += "    var count=1;    "; 
        sResponse += "function setColor(btn, color){ ";
        sResponse += "    var property = document.getElementById(btn); ";
        sResponse += "    if (count == 0){ ";
        sResponse += "        property.style.backgroundColor =  \"green \"; ";
        sResponse += "        count=1;    ";   
        sResponse += "    } ";
        sResponse += "    else{ ";
        sResponse += "        property.style.backgroundColor = \"red \"; ";
        sResponse += "        count=0; ";     
        sResponse += "    } ";
        sResponse += "} ";
        sResponse += "</script> ";
        sResponse += "<body> ";
        sResponse += "<input type= \"button\" id=\"button\" value = \"button\" style= \"color:white\" onclick=\"setColor('button', '#101010')\";/> "; 
        sResponse += "<p>Funktion 1 <a href=\"?pin=LED_EIN\"><id=Schalter_LED><button>EIN</button></a>&nbsp;<a href=\"?pin=LED_AUS\"><button>AUS</button></a></p>";
    
    Antworten
    1. ST Beitragsautor

      Hallo Jürgen,

      ich verstehe das Problem nicht. Über die Parameter, die mit der URL übertragen werden und dem Zustand auf dem ESP (z.B. Relais ist an) hast Du alle Information auf dem ESP. Beim Drücken auf einen Button wird ein Neuladen der http Seite vom ESP ausgelöst. Du kannst dann die Seite inklusive Button-Farben so aufbauen, wie es der akutelle Zustand und die URL Parameter definieren.

      Gruss Stefan

      Antworten
      1. Jürgen

        Servus Stefan!
        Es funktioniert!!
        Warum ist mir diese einfache Lösung nicht selber eingefallen?
        (Bitte auf diese Frage nicht antworten).

        Vielen, vielen Dank.
        Jürgen

        Antworten
  25. Björn

    Moin Moin

    Ich frage mich aktuell, ob es möglich ist, dem Modul gleich eine andere IP zuzuordnen, die sich von der Standardadresse 192.168.4.1 unterscheidet, um eventuell mehrere Geräte nebeneinander laufen zu lassen?

    Haben Sie da bereits etwas probiert oder eine Idee?
    Gibt es dazu eine einfache Anweisung?

    Vielen Dank!

    Antworten
    1. ST Beitragsautor

      Hallo Björn,

      wenn Du einen Accesspoint mit einem ESP aufmachst, dann erzeugt er ein eigenes Netzwerk. Du kannst keine zwei Accesspoints mit dem ESP machen (also zwei Netze) und dann ein Netzwerk haben wollen 🙂
      Es ist vermutlich sinnvoller, wenn Du die Variante nimmst, die ein Client in einem WLAN Netzwerk ist. Davon kannst Du viel ESPs parallel betreiben. Die IP wird dann vom Router zugewiesen.

      Gruss Stefan

      P.S.: Und ja, die 192.168.1.4 kann man auch ändern.

      Antworten
      1. Björn

        Hallo Stefan,

        vielen Dank für die Antwort!

        Ich meine natürlich zwei Netze mit zwei ESP8266, die gleichzeitig bestehen.
        Nur wenn alle den 192.168.4.1 als Standard haben, dann muss ja zumindest einer geändert werden. Lässt sich das gleich mit einbauen in Deinen Sketch?

        Das Programm läuft bei mir ganz gut. Allerdings verstehe ich nicht ganz, weshalb sich der GPIO unter Funktion eins bei mir etwas anderes verhält als vermutlich beabsichtigt.
        Die LED leuchtet, wenn ich ausschalten auswähle. Habe jedoch noch nicht nachgemessen, ob der Port dann genauso schaltet. Mag vielleicht an der Hardware liegen. Von den Boards gibt es ja etliche.

        Gruß

        Björn

        Antworten
        1. ST Beitragsautor

          Hallo Björn,

          wenn Du unterschiedliche Netze hast, brauchst Du keine unterschiedliche IP. Wenn Du es unbedingt ändern willst, dann schau mal in den Kommentaren hier weiter oben. Das Kommando heißt softAPConfig().

          Gruss Stefan

          P.S.: Wenn Du eine gedrehte Logik hast (an macht aus), dann liegt das vermutlich daran, dass Du ein Relaisboard drangeklemmt hast. Die meisten Relaisboards schalten auf LOW – steht aber auch in der Doku…

          Antworten
  26. kristina

    Hi und Hallo

    klasse Beispiel..hat mir sehr geholfen…ich war genau auf der such nach dieser kombi zw AP u wifiClient.
    Da ich zuvor scon einen reinen WifiClient mit AJAX hatte, habe ich jetzt deinen Code mit meinem „gekreuzt“ 😉

    Hier ein lauffähiges Beispiel mit AJAX ( rest ist original vom Code oben ):

    /*--------------------------------------------------
    HTTP 1.1 Webserver as AccessPoint for ESP8266
    for ESP8266 adapted Arduino IDE
    
    by Stefan Thesen 08/2015 - free for anyone &amp; AJAX from Kristina
    Funktioniert SUPER!!
    upload
    auf com3..kommt die ip 192.168.4.1
    browser: site aufrufen
    AJAX function CALL
    gebacken in ECLIPSE / SLOEBER
    --------------------------------------------------*/
    
    #include 
    const char * ssid = "ESPA";
    const char * password = ""; // set to "" for open access point w/o passwortd
    
    unsigned long ulReqcount;
    String HTTP_req;
    
    // Create an instance of the server on Port 80
    WiFiServer server(80);
    
    /*
     * IP adresse kann auch geändert werden!!
     * WiFiServer server(80);
     * IPAddress apIP(192, 168, 1, 1);
     * und
     * WiFi.mode(WIFI_AP);
     * WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
     * https://blog.thesen.eu/http-1-1-webserver-fuer-esp8266-als-accesspoint/
     * 
     */
    
    int i = 0;
    void clearLogList(WiFiClient cl) {
        cl.print("");
    }
    
    void fillLogWithSomeData(WiFiClient cl) {
        //Serial.println("fillLogWithSomeData(WiFiClient cl): start");
        cl.print("Jetzt kommen Werte aus einer Funktion: ");
        cl.print(++i);
        cl.print("\n");
        //Serial.println("fillLogWithSomeData(WiFiClient cl): end");
    }
    
    void setup() {
        // setup globals
        ulReqcount = 0;
    
        // prepare GPIO2
        pinMode(2, OUTPUT);
        digitalWrite(2, 0);
    
        // start serial
        Serial.begin(115200);
        delay(10);
    
        // AP mode
        WiFi.mode(WIFI_AP);
        WiFi.softAP(ssid, password);
        server.begin();
    
        IPAddress myIP = WiFi.softAPIP();
        Serial.print("AP IP address: ");
        Serial.println(myIP);
        Serial.println("HTTP server started");
    }
    
    void loop() {
        WiFiClient client = server.available();
        if (client) {
            boolean currentLineIsBlank = true;
            while (client.connected()) {
                if (client.available()) {
                    char c = client.read();
                    HTTP_req += c;
                    if (c == '\n' &amp;&amp; currentLineIsBlank) {
                        client.println("HTTP/1.1 200 OK");
                        client.println("Content-Type: text/html");
                        client.println("Connection: keep-alive");
                        client.println();
                        //Serial.println("Connection: keep-alive");
    
                        if (HTTP_req.indexOf("ajax_switch") &gt; -1) {
                            clearLogList(client);
                            fillLogWithSomeData(client);
                            Serial.println("ajax_switch");
                        } else {
                            //client.println("");
                            client.println("");
                            client.println("");
                            client.println("");
                            client.println("Kristinas first AJAX example");
                            client.println("");
                            client.println("");
                            // function 1
                            client.println("function clearLogList() {");
                            client.println("nocache = \"&amp;nocache=\"+ Math.random() * 1000000;");
                            client.println("var request = new XMLHttpRequest();");
                            client.println("request.onreadystatechange = function() {");
                            client.println("if (this.readyState == 4) {");
                            client.println("if (this.status == 200) {");
                            client.println("if (this.responseText != null) {");
                            client.println("document.getElementById(\"txtAreaLog\").innerHTML = '';");
                            client.println("}}}}");
                            client.println("request.open(\"GET\", \"ajax_switch\" + nocache, true);");
                            client.println("request.send(null);");
                            client.println("}");
                            //function2
                            //Serial.println("call of function 2 / fillLogWithSomeData(): start");
                            client.println("function fillLogWithSomeData() {");
                            client.println("nocache = \"&amp;nocache=\"+ Math.random() * 1000000;");
                            client.println("var request = new XMLHttpRequest();");
                            client.println("request.onreadystatechange = function() {");
                            client.println("if (this.readyState == 4) {");
                            client.println("if (this.status == 200) {");
                            client.println("if (this.responseText != null) {");
                            client.println("document.getElementById(\"txtAreaLog\").innerHTML += this.responseText;");
                            client.println("}}}}");
                            client.println("request.open(\"GET\", \"ajax_switch\" + nocache, true);");
                            client.println("request.send(null);");
                            client.println("}");
                            client.println("");
                            // style block in html code - start
                            client.println("");
                            client.println("h1 { color: red; font-size: 20px;}");
                            client.println("button { background-color: #555555; border: none; color: white; padding: 15px 32px;  text-align: center; text-decoration: none;  display: inline-block; font-size: 18px; margin: 4px 2px; cursor: pointer;}");
                            client.println("textarea {color: black;	font-size: 12px;}");
                            client.println("");
                            // style block in html code - End
                            client.println("");
                            client.println("");
                            client.println("");
                            client.println("Kristinas first AJAX example");
                            client.println("..");
                            //client.println("");
                            client.println("");
                            client.println("Fill Log Data");
                            client.println("&nbsp;&nbsp;;&nbsp;");
                            client.println("CLEAR List");
                            client.println("");
                            client.println("");
                            client.println("");
                            //Serial.println("ajax actualization block!");
                        }
                        //Serial.print(HTTP_req);
                        HTTP_req = "";
                        break;
                    }
                }
            }
            delay(1);
            client.stop();
        }
    }
    
    Antworten
  27. Marcus

    Hallo Kristina,

    sowas habe ich gesucht 🙂

    Einiges wurde Zer-HTML-Hackstückelt,
    nur einige Sonderzeichen konnte ich korrigieren, aber die Ausgabe ist nicht richtig.
    Hast du eine vollständige Version (pastebin oder so etwas?)
    Danke 🙂

    Antworten
  28. bitboy

    Hi,

    Wenn ich die NodeMCU mit der Arduino IDE im flashe funktioniert der AP Modus nur sehr unstabil bzw ich kann mich erst gar nicht verbinden, bekomme das Netzwerk aber angezeigt. Mit dem Android Phone geht’s manchmal, mit dem Laptop nie.

    Antworten
    1. ST Beitragsautor

      Das liegt erfahrungsgemäß weder an der NodeMCU Hardware noch am Sketch. Leider haben die Betriebssystemhersteller angefangen für ihre meisten technisch wenig versierten Kunden mitzudenken. Also probieren die Betriebssysteme in der „dummy“ Einstellung aus, ob sie nach der Verbindung mit einem Wifi das Internet erreichen können. Das geht natürlich bei einem ESP8266 im AP Modus nicht. Das ganze Netzwerk besteht ja nur aus Laptop/Handy und ESP. Android moppelt dann normalerweise nach ~ 1 Minute, dass das Internet nicht erreichbar ist und fragt, ob man das Netz trotzdem nehmen will. Bei Win10 gibt es irgendwo eine Einstellung für das Verhalten; wenn die an ist, wird das WiFi sofort wieder getrennt.

      Gruss Stefan

      Antworten
  29. Jan

    Hallo und danke für den Code.
    Wie ich finder sehr schön geschrieben.
    Habe allerdings das Problem, dass die Website nur zum Teil dargestellt wird. Ab „Funktion 2“ hört sie auf( Taster fehlen ).
    Bei meinem „Mit-Azubi“ wird zwar etwas mehr dargestellt aber auch bei weitem nicht alles.
    Benutzen beide Google Chrome.
    Habe aber auch schon andere Browser mit unterschliedlichen Einsetllungen getestet.

    Hoffe mir kann jemand weiter helfen / bzw. einen Denkanstoß geben 🙂

    Antworten
    1. ST Beitragsautor

      Klingt danach, als ob die Länge im http Header nicht stimmt. Evtl. habt ihr die Länge nicht richtig aufsummiert.

      Gruss Stefan

      Antworten
  30. ottelo

    Hi,
    dein Code ging mal auf meinem ESP8266. Irgendwie scheint er nun nicht mehr zu funzen. Habe alles nochmal neu heruntergeladen. Wenn die ich Homepage aufrufen will kommt sofort: Seite kann nicht geöffnet werden. Auf dem UART Output steht dann immer

    new client
    Client disonnected

    Irgendeine Idee?

    Antworten
  31. Jens

    Hallo Stefan,
    Danke für Deinen sehr verständlichen Sketch. Ich habe ihn als Grundlage für eine Datenweiterleitung genommen. (Daten von einem Gerät an den (1.)ESP8266-12E-AP senden. AP schaltet sich nach Empfang ab. Wifi-Client schaltet sich an. Daten werden zu Server weiterübertragen. Wifi-Client schaltet sich nach der Übertragung ab. AP schaltet sich wieder an und wartet auf den nächsten Connect.)
    Das obige Szenario funktioniert wunderbar … wenn ich die ursprünglichen Daten z. B. von einem Smartphone zum AP sende.
    Nutze ich einen anderen (2.)ESP8266-12E für die Verbindung zum AP, wird korrekt zum AP verbunden, aber die Daten werden nicht übertragen.
    Sende ich vom 2.ESP direkt im Ziel-WLAN an den Ziel-Server, gehen die Daten korrekt rüber. Insofern kann ich einen Fehler im Sketch ausschließen.

    Bei der Verbindung von-ESP-zu-ESP-AP konnte ich folgende Schritte nachvollziehen:
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(„.“);
    }
    Serial.println(WiFi.localIP());
    // hier wird korrekt mit dem AP verbunden und die zugeteilte Client-IP angezeigt

    if (!client.connect(host,80)) {
    Serial.println(„Fehler“);
    delay(500);
    }
    else {
    Serial.println(„- succesfully connected“);
    }
    // hier bekomme ich immer NUR zur Fehleranzeige

    Da kann man doch nichts verkehrt machen, oder?
    Gibt es bekannte Probleme bei der Verbindung zwischen zwei ESP8266-12E? Ich konnte diesbzgl. noch nichts finden.

    Danke vorab für Dein Brainstorming
    Gruß
    Jens

    Antworten
  32. Simon

    Deine Anleitung ist genau dass wonach ich gesucht habe. Leider habe ich ein Probelm beim laden der Seite. aufm Handy sehe ich sie kurz und danach kommt die meldung „laden der Seite nicht möglcih.“ Am PC kommt die meldung Sofort ohne kurzes aufblinken der Seite. Weißt du woran es liegen könnte? Vielen Dank für deine Antwort

    Antworten
    1. ST Beitragsautor

      Hallo Simon,

      schau bitte mal die Kommentare über Deinem an. Da steht schon die Lösung. Entwicklungsumgebung Version 2.4.1 hat Probleme. Downgrade auf unter 2.4 und alles geht.

      Gruss Stefan

      Antworten
  33. Karsten Schulz

    Sehr gut, vor dem beenden muss aber nach dem Senden ein delay(1000);
    folgen sonnst ist je nach dem die Verbindung weg und der Bildschirm weiß.

    Sehr gut.
    Grüße aus Berlin

    Antworten
    1. ST Beitragsautor

      Was hast Du denn für ein Board genommen? – Mich wundert die Formulierung „das Relais“. Hast Du einen GPIO mit einem Relaisboard verbunden oder irgendwas fertiges genommen?

      Antworten
  34. Tim Zenker

    Vielen Dank für diese gute Beschreibung des AP-Modes. Ich möchte dieses Sketch zur Grundlage eines Programms nehmen, mit dem ich Folgendes machen kann:
    Anschluss eines LED-Matrixdisplasys an das Board als „Zähltafel“. Über das aufgespannte WLAN des Boards kann sich dann ein Handy verbinden. Bei Aufruf der Seite 192.168.4.1 soll man dann per Klick auf einem Button die Zahlen von 0 bis 30 hochzählen können und auf dem Handydisplay ebenfalls verfolgen können.
    Wie kann ich eine solche Seite für den Server generieren?
    Danke für eure Hilfe.

    Antworten
  35. volker

    Super AP mode lauft sehr stabiel Danke dafür.
    Jetzt fehlt nur noch das man im AP die SSID und das Passwort eingeben muss und
    von dort aus sofort in den STA mode kommt.
    Wäre nicht schlecht wenn das jemand programiert und hier veröffendlicht.
    Ich kann leider nicht so gut programieren.
    Habe im Inet schon sehr viel ausprobiert aber kein Server lauft so stabiel wie dieser.

    MKG Volker

    Antworten
  36. Christoph

    Hallo,

    vielen Dank für dieses Beispiel, welches soweit wunderbar funktioniert 🙂
    Ich würde das ganze allerdings gerne etwas erweitern – und zwar abgeschaut von vielen anderen Geräten…

    1. Einschalten: Ein eigenes WLan wird aufgebaut und man kann sich damit verbinden (siehe dein Beispiel)
    2. Nun kann man die Daten seines eigenen WLans eingeben – SSID, Kennwort, ob DHCP oder Statische IP, etc….
    3. diese Daten sollen auf dem Gerät gespeichert werden, damit man künftig über sein eigenes Wlan mit dem Gerät kommunizieren kann.

    Leider fehlen mir infos darüber, wie ich diese Daten direkt auf dem Gerät speichern kann, bzw. wie ich es erreiche, dass er nur beim erstmaligen Starten das eigene, vorkonfigurierte Wlan aufbaut…
    Hast du hierfür vielleicht Beispiele?

    Danke und Grüße,
    Christoph

    Antworten

Schreibe einen Kommentar

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