Werte erkennen Virtueller HTTP Eingang

Einklappen
X
 
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge
  • ToB204
    Smart Home'r
    • 26.08.2015
    • 54

    #1

    Werte erkennen Virtueller HTTP Eingang

    Hallo Forum brauch mal die Unterstützung bei dem einstellen der Befehlskennung des HTTP Eingangs.
    Es ist so das ich mir ein IR-Blaster zum senden und empfangen von IR Signalen nach gebaut habe. Mit dem kann ich nun IR-Signale senden. Nur beim einstellen der Befehlskennung des Eingangs, kommt bei mir einfach kein Wert raus. Jetzt hoffe ich, auf ein bisschen Untersützung von euch!
    Dazu habe ich mal ein Screenshot der Ausgangsseite gemacht.

    Am allerliebsten würde ich gerne den Wert aus Bereich 1 auslesen da dies eine kurze Zusammenfassung des Signals ist. Aber im Bereich 2 die "Data" Ausgabe würde auch gehen.

    Hier der Code der Seite.
    HTML-Code:
    <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
    <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
      <head>
        <meta name='viewport' content='width=device-width, initial-scale=.75' />
        <link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' />
        <style>@media (max-width: 991px) {.nav-pills>li {float: none; margin-left: 0; margin-top: 5px; text-align: center;}}</style>
        <title>ESP8266 IR Controller (IrBlaster)</title>
      </head>
      <body>
        <div class='container'>
          <h1><a href='https://github.com/mdhiggins/ESP8266-HTTP-IR-Blaster'>ESP8266 IR Controller</a></h1>
          <div class='row'>
            <div class='col-md-12'>
              <ul class='nav nav-pills'>
                <li class='active'>
                  <a href='http://IrBlaster.local:80'>Hostname <span class='badge'>IrBlaster.local:80</span></a></li>
                <li class='active'>
                  <a href='http://192.168.2.148:80'>Local <span class='badge'>192.168.2.148:80</span></a></li>
                <li class='active'>
                  <a href='http://87.143.64.47:80'>External <span class='badge'>87.143.64.47:80</span></a></li>
                <li class='active'>
                  <a href='#'>MAC <span class='badge'>5C:CF:7F:23:A0:5C</span></a></li>
              </ul>
            </div>
          </div><hr />
          <div class='row'>
            <div class='col-md-12'>
              <h2><span class='label label-success'>AA20A7CB:UNKNOWN:27</span></h2><br/>
              <dl class='dl-horizontal'>
                <dt>Data</dt>
                <dd><code>AA20A7CB</code></dd></dl>
              <dl class='dl-horizontal'>
                <dt>Type</dt>
                <dd><code>UNKNOWN</code></dd></dl>
              <dl class='dl-horizontal'>
                <dt>Length</dt>
                <dd><code>27</code></dd></dl>
              <dl class='dl-horizontal'>
                <dt>Address</dt>
                <dd><code>0x</code></dd></dl>
              <dl class='dl-horizontal'>
                <dt>Raw</dt>
                <dd><code>600,550, 550,600, 550,1750, 600,1700, 600,550, 550,1750, 600,550, 550,600, 600,1700, 550,1750, 550,1750, 600,1700, 600,550, 550,600, 550,600, 550,600, 600,550, 600,550, 550,600, 550,600, 600,1700, 550,1750, 600,1700, 550,1750, 600,1700, 550,1750, 550</code></dd></dl>
            </div></div>
          <div class='row'>
            <div class='col-md-12'>
              <div class='alert alert-warning'>Don't forget to add your passcode to the URLs below if you set one</div>
          </div></div>
          <div class='row'>
            <div class='col-md-12'>
              <ul class='list-unstyled'>
                <li>Hostname <span class='label label-default'>JSON</span></li>
                <li><pre>http://IrBlaster.local:80/json?plain=[{'data':[600,550, 550,600, 550,1750, 600,1700, 600,550, 550,1750, 600,550, 550,600, 600,1700, 550,1750, 550,1750, 600,1700, 600,550, 550,600, 550,600, 550,600, 600,550, 600,550, 550,600, 550,600, 600,1700, 550,1750, 600,1700, 550,1750, 600,1700, 550,1750, 550], 'type':'raw', 'khz':38}]</pre></li>
                <li>Local IP <span class='label label-default'>JSON</span></li>
                <li><pre>http://192.168.2.148:80/json?plain=[{'data':[600,550, 550,600, 550,1750, 600,1700, 600,550, 550,1750, 600,550, 550,600, 600,1700, 550,1750, 550,1750, 600,1700, 600,550, 550,600, 550,600, 550,600, 600,550, 600,550, 550,600, 550,600, 600,1700, 550,1750, 600,1700, 550,1750, 600,1700, 550,1750, 550], 'type':'raw', 'khz':38}]</pre></li>
                <li>External IP <span class='label label-default'>JSON</span></li>
                <li><pre>http://87.143.64.47:80/json?plain=[{'data':[600,550, 550,600, 550,1750, 600,1700, 600,550, 550,1750, 600,550, 550,600, 600,1700, 550,1750, 550,1750, 600,1700, 600,550, 550,600, 550,600, 550,600, 600,550, 600,550, 550,600, 550,600, 600,1700, 550,1750, 600,1700, 550,1750, 600,1700, 550,1750, 550], 'type':'raw', 'khz':38}]</pre></li></ul>
            </div>
         </div>
          <div class='row'><div class='col-md-12'><em>2711917ms uptime</em></div></div>
        </div>
      </body>
    </html>
    Danke für eure Hilfe!
  • romildo
    Lebende Foren Legende
    • 25.08.2015
    • 5161

    #2
    Hallo,

    Sofern ich Dich richtig verstanden habe, geht das nicht, da der Virtuellen HTTP Eingang keinen Text einlesen kann.
    Er kann Dir nur einen Wert anzeigen.
    Beispiel:
    Befehlserkennung: ESP\v
    würde 8266
    anzeigen.

    lg Romildo

    Kommentar

    • Christian Fenzl
      Lebende Foren Legende
      • 31.08.2015
      • 11238

      #3
      Direkt können keine Strings gelesen werden, lediglich ASCII-Werte von einzelnen Chars (\1).

      Du kannst das HTML anderwärtig parsen (z.B. Raspberry) und per Webservice oder UDP an den MS pushen.
      Hilfe für die Menschen der Ukraine: https://www.loxforum.com/forum/proje...Cr-die-ukraine

      Kommentar

      • romildo
        Lebende Foren Legende
        • 25.08.2015
        • 5161

        #4
        Ich weiss nicht was da genau gemacht werden soll, würde dies aber direkt vom ESP8266 an den MS pushen.
        lg Romildo

        Kommentar

        • ToB204
          Smart Home'r
          • 26.08.2015
          • 54

          #5
          Das hab ich befürchtet.
          werde jetzt wahrscheinlich den esp code umprogrammieren (wenn ich es hinbekomme), so das er die Befehle per UDP an den Miniserver schickt.
          Danke für eure Hilfe!

          Kommentar

          • Maruu
            LoxBus Spammer
            • 07.03.2017
            • 489

            #6
            Wenn ich es richtig verstanden habe dann erkennt die Platine per IR gesendete Codes und stellt den letzten empfangenen Code als Website per WLAN zur Verfügung. Diesen Code will er abrufen. Der Code besteht aus 3 Teilen:

            AA20A7CB:UNKNOWN:27

            Also aus dem eigentlich gesendeten Hexwert: AA20A7CB, dem Format: UNKNOWN (oder Sony, ...) und der Länge.

            Wenn er nun stets den gleichen Sender abfragt (hier also das Format UNKNOWN) müsste Ihm der Hexwert reichen. Er müsste also den Hexwert rausfiltern:

            <h2><span class='label label-success'>AA20A7CB:UNKNOWN:27</span></h2><br/>

            Vielleicht kann jemand sagen ob das mit der Befehlserkennung geht, davon hab ich keine Ahnung.

            Kommentar


            • Maruu
              Maruu kommentierte
              Kommentar bearbeiten
              Ups etwas zu spät
          • romildo
            Lebende Foren Legende
            • 25.08.2015
            • 5161

            #7
            Maruu
            Man könnte die Werte schon einzeln einlesen, das heisst für jeden einen Virtuellen Eingangsbefehl anlegen. Es würde dann der jeweilige ASCII Wert angezeigt.
            Beispiel für <h2><span class='label label-success'>AA20A7CB:UNKNOWN:27</span></h2><br/>:
            Eingang 1 Befehlserkennung:success'>\1 -für A käme dann 65
            Eingang 2 Befehlserkennung:success'>\s1\1 -für A käme dann 65
            Eingang 3 Befehlserkennung:success'>\s2\1 -für 2 käme dann 50
            Eingang 4 Befehlserkennung:success'>\s3\1 -für 0 käme dann 48
            Eingang 5 Befehlserkennung:success'>\s4\1 -für A käme dann 65
            Eingang 6 Befehlserkennung:success'>\s5\1 -für 7 käme dann 55
            Eingang 7 Befehlserkennung:success'>\s6\1 -für C käme dann 67
            Eingang 8 Befehlserkennung:success'>\s7\1 -für B käme dann 66

            Diese Zahlen könnte man in drei Statusbausteinen zusammenfügen und mittels 4. Statusbaustein auswerten.
            Wäre bei nur wenigen Signalen denkbar, bei vielen hingegen sehr aufwändig. PicoC wäre da schon eher richtig.

            Da die Abfragezeit von HTTP mit 10s begrenzt ist und zudem laufend abgefragt werden muss, wüede ich dafür UDP nehmen.

            Nachtrag:
            Hier noch das Beispiel als Bild:
            Klicke auf die Grafik für eine vergrößerte Ansicht

Name: 8ByteHEXStringHTTPEingang.png
Ansichten: 2042
Größe: 203,5 KB
ID: 105615
            Zuletzt geändert von romildo; 04.07.2017, 20:05.
            lg Romildo

            Kommentar

            • Maruu
              LoxBus Spammer
              • 07.03.2017
              • 489

              #8
              Super Arbeit, so in die Richtung hatte ich es mir auch gedacht!

              Kommentar

              • ToB204
                Smart Home'r
                • 26.08.2015
                • 54

                #9
                Super vielen Dank! Ihr seid die Besten!
                Das mit den 10 s ist wirklich blöde, da es da durch leider beim Zapping zu Verzögerungen kommt. Werd mal versuchen, das senden von UDP beim ESP Code hinzuzufügen. Bin da aber leider totaler Anfänger, werd mich da erst rein arbeiten müssen. Also wer Lust hat mir zu helfen kann sich gerne bei mir melden.

                Kommentar


                • romildo
                  romildo kommentierte
                  Kommentar bearbeiten
                  Vielleicht sagst Du uns, was Du damit machen möchtest.
                  Hast Du eine Fernsteuerung und möchtest damit Befehle in der Loxone auslösen, oder hast Du unterschiedliche Fernsteuerungen.......

                • ToB204
                  ToB204 kommentierte
                  Kommentar bearbeiten
                  Ich möchte mit dem IR-Blaster und dem Miniserver eine selbst gebaute IR CONTROL AIR bauen. Ich hab keine Air-Extension und so ist mir das Teil einfach zu teuer. Den Esp und die restlichen Teile (außer den IR Empfänger)hatte ich noch. Bis her hatte ich den Harmony Hub, der ist mir aber einfach zu unflexibel.
              • romildo
                Lebende Foren Legende
                • 25.08.2015
                • 5161

                #10
                Ich habe mir jetzt mal den IR-Blaster auf einen ESP8266 geladen.
                Bei mir ist es so, dass bei gleicher Tastenbetätigung auf der Fernsteuerung nicht immer der gleiche Code kommt.
                Manchmal weisst er den Typ UNKNOWN zu und manchmal erkennt er einen Typ.
                Macht er das bei Dir auch?

                UDP senden sollte aber kein Problem sein.
                lg Romildo

                Kommentar

                • ToB204
                  Smart Home'r
                  • 26.08.2015
                  • 54

                  #11
                  "Eigentlich" empfängt er immer die gleiche Signale. Bei einer Fernbedienung wird aber immer pro Taste abwechselnd zwei Signale gesendet und bei der Sony wird manchmal (jedes 10 mal oder so) der Tastencode nicht richtig erkannt. Hab hier mal mein veränderten Code das senden per UDP funktioniert schon nur leider hab ich keine Ahnung was ich bei UDP.write eintragen muss um den Code zu erhalten
                  HTML-Code:
                  #include <FS.h>                                               // This needs to be first, or it all crashes and burns
                  
                  #include <IRremoteESP8266.h>
                  #include <IRsend.h>
                  #include <IRrecv.h>
                  #include <IRutils.h>
                  #include <ESP8266WiFi.h>
                  #include <WiFiManager.h>                                      // https://github.com/tzapu/WiFiManager WiFi Configuration Magic
                  #include <ESP8266mDNS.h>                                      // Useful to access to ESP by hostname.local
                  
                  #include <ArduinoJson.h>
                  #include <ESP8266WebServer.h>
                  #include <ESP8266HTTPClient.h>
                  
                  #include <Ticker.h>                                           // For LED status
                  #include <NTPClient.h>
                  #include <WiFiUDP.h>
                  
                  const int configpin = 13;                                     // GPIO13 (D7 on D1 Mini) to enable configuration (connect to ground)
                  const int ledpin = BUILTIN_LED;                               // Built in LED defined for WEMOS people
                  const char *wifi_config_name = "IRBlaster Configuration";
                  const char serverName[] = "checkip.dyndns.org";
                  int port = 80;
                  char passcode[40] = "";
                  char host_name[40] = "";
                  char port_str[20] = "80";
                  DynamicJsonBuffer jsonBuffer;
                  JsonObject& last_code = jsonBuffer.createObject();            // Stores last code
                  JsonObject& last_code_2 = jsonBuffer.createObject();          // Stores 2nd to last code
                  JsonObject& last_code_3 = jsonBuffer.createObject();          // Stores 3rd to last code
                  JsonObject& last_code_4 = jsonBuffer.createObject();          // Stores 4th to last code
                  JsonObject& last_code_5 = jsonBuffer.createObject();          // Stores 5th to last code
                  JsonObject& last_send = jsonBuffer.createObject();            // Stores last sent
                  JsonObject& last_send_2 = jsonBuffer.createObject();          // Stores 2nd last sent
                  JsonObject& last_send_3 = jsonBuffer.createObject();          // Stores 3rd last sent
                  JsonObject& last_send_4 = jsonBuffer.createObject();          // Stores 4th last sent
                  JsonObject& last_send_5 = jsonBuffer.createObject();          // Stores 5th last sent
                  
                  ESP8266WebServer server(port);
                  HTTPClient http;
                  Ticker ticker;
                  
                  bool shouldSaveConfig = false;                                // Flag for saving data
                  bool holdReceive = false;                                     // Flag to prevent IR receiving while transmitting
                  
                  int pinr1 = 5;                                                // Receiving pin (GPIO5 = D1)
                  int pins1 = 4;                                                // Transmitting preset 1
                  int pins2 = 12;                                               // Transmitting preset 2
                  int pins3 = 16;                                               // Transmitting preset 3
                  int pins4 = 15;                                               // Transmitting preset 4
                  
                  IRrecv irrecv(pinr1);
                  IRsend irsend1(pins1);
                  IRsend irsend2(pins2);
                  IRsend irsend3(pins3);
                  IRsend irsend4(pins4);
                  
                  const unsigned long resetfrequency = 259200000;                // 72 hours in milliseconds
                  const int timeOffset = -14400;                                 // Timezone offset in seconds
                  const char* poolServerName = "time.nist.gov";
                  IPAddress IP_Remote(192, 168, 2, 4);                           // IP address for Miniserver
                  unsigned int Port_Remote = 5001;                               // Miniserver remote port
                  const bool getTime = true;                                     // Set to false to disable querying for the time
                  
                  // A UDP instance to let us send and receive packets over UDP
                  WiFiUDP Udp;
                  
                  WiFiUDP ntpUDP;
                  NTPClient timeClient(ntpUDP, poolServerName, timeOffset, (int)resetfrequency);
                  
                  const bool getExternalIP = true;                               // Set to false to disable querying external IP
                  String _ip = "";
                  unsigned long lastupdate = 0;
                  
                  //+=============================================================================
                  // Callback notifying us of the need to save config
                  //
                  void saveConfigCallback () {
                    Serial.println("Should save config");
                    shouldSaveConfig = true;
                  }
                  
                  
                  //+=============================================================================
                  // Reenable IR receiving
                  //
                  void resetReceive() {
                    if (holdReceive) {
                      Serial.println("Reenabling receiving");
                      irrecv.resume();
                      holdReceive = false;
                    }
                  }
                  
                  
                  //+=============================================================================
                  // Toggle state
                  //
                  void tick()
                  {
                    int state = digitalRead(ledpin);  // get the current state of GPIO1 pin
                    digitalWrite(ledpin, !state);     // set pin to the opposite state
                  }
                  
                  
                  //+=============================================================================
                  // Get External IP Address
                  //
                  String externalIP()
                  {
                    if (!getExternalIP) {
                      return "0.0.0.0"; // User doesn't want the external IP
                    }
                  
                    if (_ip != "") {
                      if (millis() - lastupdate > resetfrequency || lastupdate > millis()) {
                        Serial.println("Reseting cached external IP address");
                        _ip = ""; // Reset the cached external IP every 72 hours
                      } else {
                        return _ip;
                      }
                    }
                    unsigned long start = millis();
                    http.setTimeout(5000);
                    http.begin(serverName, 8245);
                    int httpCode = http.GET();
                  
                    if (httpCode > 0 && httpCode == HTTP_CODE_OK) {
                      String payload = http.getString();
                      int pos_start = payload.indexOf("IP Address") + 12; // add 10 for "IP Address" and 2 for ":" + "space"
                      int pos_end = payload.indexOf("</body>", pos_start); // add nothing
                      _ip = payload.substring(pos_start, pos_end);
                      Serial.print(F("External IP: "));
                      Serial.println(_ip);
                      http.end();
                    } else {
                      Serial.println("Error retrieving external IP");
                    }
                  
                    Serial.print("External IP address request took ");
                    Serial.print(millis() - start);
                    Serial.println(" ms");
                  
                    return _ip;
                  }
                  
                  
                  //+=============================================================================
                  // Turn off the Led after timeout
                  //
                  void disableLed()
                  {
                    Serial.println("Turning off the LED to save power.");
                    digitalWrite(ledpin, HIGH);                           // Shut down the LED
                    ticker.detach();                                      // Stopping the ticker
                  }
                  
                  
                  //+=============================================================================
                  // Gets called when WiFiManager enters configuration mode
                  //
                  void configModeCallback (WiFiManager *myWiFiManager) {
                    Serial.println("Entered config mode");
                    Serial.println(WiFi.softAPIP());
                    //if you used auto generated SSID, print it
                    Serial.println(myWiFiManager->getConfigPortalSSID());
                    //entered config mode, make led toggle faster
                    ticker.attach(0.2, tick);
                  }
                  
                  
                  //+=============================================================================
                  // First setup of the Wifi.
                  // If return true, the Wifi is well connected.
                  // Should not return false if Wifi cannot be connected, it will loop
                  //
                  bool setupWifi(bool resetConf) {
                    // set led pin as output
                    pinMode(ledpin, OUTPUT);
                    // start ticker with 0.5 because we start in AP mode and try to connect
                    ticker.attach(0.6, tick);
                  
                    // WiFiManager
                    // Local intialization. Once its business is done, there is no need to keep it around
                    WiFiManager wifiManager;
                    // reset settings - for testing
                    if (resetConf)
                      wifiManager.resetSettings();
                  
                    // set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
                    wifiManager.setAPCallback(configModeCallback);
                    // set config save notify callback
                    wifiManager.setSaveConfigCallback(saveConfigCallback);
                  
                    if (SPIFFS.begin()) {
                      Serial.println("mounted file system");
                      if (SPIFFS.exists("/config.json")) {
                        //file exists, reading and loading
                        Serial.println("reading config file");
                        File configFile = SPIFFS.open("/config.json", "r");
                        if (configFile) {
                          Serial.println("opened config file");
                          size_t size = configFile.size();
                          // Allocate a buffer to store contents of the file.
                          std::unique_ptr<char[]> buf(new char[size]);
                  
                          configFile.readBytes(buf.get(), size);
                          DynamicJsonBuffer jsonBuffer;
                          JsonObject& json = jsonBuffer.parseObject(buf.get());
                          json.printTo(Serial);
                          if (json.success()) {
                            Serial.println("\nparsed json");
                  
                            if (json.containsKey("hostname")) strncpy(host_name, json["hostname"], 40);
                            if (json.containsKey("passcode")) strncpy(passcode, json["passcode"], 40);
                            if (json.containsKey("port_str")) {
                              strncpy(port_str, json["port_str"], 20);
                              port = atoi(json["port_str"]);
                            }
                          } else {
                            Serial.println("failed to load json config");
                          }
                        }
                      }
                    } else {
                      Serial.println("failed to mount FS");
                    }
                    // end read
                  
                    WiFiManagerParameter custom_hostname("hostname", "Choose a hostname to this IRBlaster", host_name, 40);
                    wifiManager.addParameter(&custom_hostname);
                    WiFiManagerParameter custom_passcode("passcode", "Choose a passcode", passcode, 40);
                    wifiManager.addParameter(&custom_passcode);
                    WiFiManagerParameter custom_port("port_str", "Choose a port", port_str, 40);
                    wifiManager.addParameter(&custom_port);
                  
                    // fetches ssid and pass and tries to connect
                    // if it does not connect it starts an access point with the specified name
                    // and goes into a blocking loop awaiting configuration
                    if (!wifiManager.autoConnect(wifi_config_name)) {
                      Serial.println("failed to connect and hit timeout");
                      // reset and try again, or maybe put it to deep sleep
                      ESP.reset();
                      delay(1000);
                    }
                  
                    // if you get here you have connected to the WiFi
                    strncpy(host_name, custom_hostname.getValue(), 40);
                    strncpy(passcode, custom_passcode.getValue(), 40);
                    strncpy(port_str, custom_port.getValue(), 20);
                    port = atoi(port_str);
                  
                    if (port != 80) {
                      Serial.println("Default port changed");
                      server = ESP8266WebServer(port);
                    }
                  
                    Serial.println("WiFi connected! User chose hostname '" + String(host_name) + String("' passcode '") + String(passcode) + "' and port '" + String(port_str) + "'");
                  
                    // save the custom parameters to FS
                    if (shouldSaveConfig) {
                      Serial.println(" config...");
                      DynamicJsonBuffer jsonBuffer;
                      JsonObject& json = jsonBuffer.createObject();
                      json["hostname"] = host_name;
                      json["passcode"] = passcode;
                      json["port_str"] = port_str;
                  
                      File configFile = SPIFFS.open("/config.json", "w");
                      if (!configFile) {
                        Serial.println("failed to open config file for writing");
                      }
                  
                      json.printTo(Serial);
                      Serial.println("");
                      json.printTo(configFile);
                      configFile.close();
                      //e nd save
                    }
                    ticker.detach();
                  
                    // keep LED on
                    digitalWrite(ledpin, LOW);
                    return true;
                  }
                  
                  
                  //+=============================================================================
                  // Setup web server and IR receiver/blaster
                  //
                  void setup() {
                  
                    // Initialize serial
                    Serial.begin(115200);
                    Serial.println("");
                    Serial.println("ESP8266 IR Controller");
                    pinMode(configpin, INPUT_PULLUP);
                    if (!setupWifi(digitalRead(configpin) == LOW))
                      return;
                  
                    WiFi.hostname(host_name);
                    while (WiFi.status() != WL_CONNECTED) {
                      delay(500);
                      Serial.print(".");
                    }
                  
                    wifi_set_sleep_type(LIGHT_SLEEP_T);
                    digitalWrite(ledpin, LOW);
                    // Turn off the led in 2s
                    ticker.attach(2, disableLed);
                  
                    // Configure mDNS
                    if (MDNS.begin(host_name)) {
                      Serial.println("mDNS started. Hostname is set to " + String(host_name) + ".local");
                    }
                    MDNS.addService("http", "tcp", port); // Announce the ESP as an HTTP service
                    Serial.println("URL to send commands: http://" + String(host_name) + ".local:" + port_str);
                  
                    if (getTime) timeClient.begin(); // Get the time
                  
                    // Configure the server
                    server.on("/json", []() { // JSON handler for more complicated IR blaster routines
                      Serial.println("Connection received - JSON");
                  
                      DynamicJsonBuffer jsonBuffer;
                      JsonArray& root = jsonBuffer.parseArray(server.arg("plain"));
                  
                      if (!root.success()) {
                        Serial.println("JSON parsing failed");
                        sendHomePage("JSON parsing failed", "Error", 3, 400); // 400
                      } else if (server.arg("pass") != passcode) {
                        Serial.println("Unauthorized access");
                        sendHomePage("Invalid passcode", "Unauthorized", 3, 401); // 401
                      } else {
                        for (int x = 0; x < root.size(); x++) {
                          String type = root[x]["type"];
                          String ip = root[x]["ip"];
                          int rdelay = root[x]["rdelay"];
                          int pulse = root[x]["pulse"];
                          int pdelay = root[x]["pdelay"];
                          int repeat = root[x]["repeat"];
                          int out = root[x]["out"];
                  
                          if (pulse <= 0) pulse = 1; // Make sure pulse isn't 0
                          if (repeat <= 0) repeat = 1; // Make sure repeat isn't 0
                          if (pdelay <= 0) pdelay = 100; // Default pdelay
                          if (rdelay <= 0) rdelay = 1000; // Default rdelay
                  
                          if (type == "delay") {
                            delay(rdelay);
                          } else if (type == "raw") {
                            JsonArray &raw = root[x]["data"]; // Array of unsigned int values for the raw signal
                            int khz = root[x]["khz"];
                            if (khz <= 0) khz = 38; // Default to 38khz if not set
                            rawblast(raw, khz, rdelay, pulse, pdelay, repeat, pickIRsend(out));
                          } else if (type == "roku") {
                            String data = root[x]["data"];
                            rokuCommand(ip, data);
                          } else {
                            String data = root[x]["data"];
                            long address = root[x]["address"];
                            int len = root[x]["length"];
                            irblast(type, data, len, rdelay, pulse, pdelay, repeat, address, pickIRsend(out));
                          }
                        }
                        digitalWrite(ledpin, LOW);
                        ticker.attach(0.5, disableLed);
                        sendHomePage("Code sent", "Success", 1); // 200
                      }
                    });
                  
                    // Setup simple msg server to mirror version 1.0 functionality
                    server.on("/msg", []() {
                      Serial.println("Connection received - MSG");
                      if (server.arg("pass") != passcode) {
                        Serial.println("Unauthorized access");
                        sendHomePage("Invalid passcode", "Unauthorized", 3, 401); // 401
                      } else {
                        String type = server.arg("type");
                        String data = server.arg("data");
                        String ip = server.arg("ip");
                        int len = server.arg("length").toInt();
                        long address = (server.hasArg("address")) ? server.arg("address").toInt() : 0;
                        int rdelay = (server.hasArg("rdelay")) ? server.arg("rdelay").toInt() : 1000;
                        int pulse = (server.hasArg("pulse")) ? server.arg("pulse").toInt() : 1;
                        int pdelay = (server.hasArg("pdelay")) ? server.arg("pdelay").toInt() : 100;
                        int repeat = (server.hasArg("repeat")) ? server.arg("repeat").toInt() : 1;
                        int out = (server.hasArg("out")) ? server.arg("out").toInt() : 0;
                        if (server.hasArg("code")) {
                          String code = server.arg("code");
                          char separator = ':';
                          data = getValue(code, separator, 0);
                          type = getValue(code, separator, 1);
                          len = getValue(code, separator, 2).toInt();
                        }
                  
                        if (type == "roku") {
                          rokuCommand(ip, data);
                        } else {
                          irblast(type, data, len, rdelay, pulse, pdelay, repeat, address, pickIRsend(out));
                        }
                        digitalWrite(ledpin, LOW);
                        ticker.attach(0.5, disableLed);
                        sendHomePage("Code Sent", "Success", 1); // 200
                      }
                    });
                  
                    server.on("/received", []() {
                      Serial.println("Connection received");
                      int id = server.arg("id").toInt();
                      String output;
                      if (id == 1 && last_code.containsKey("time")) {
                        sendCodePage(last_code);
                      } else if (id == 2 && last_code_2.containsKey("time")) {
                        sendCodePage(last_code_2);
                      } else if (id == 3 && last_code_3.containsKey("time")) {
                        sendCodePage(last_code_3);
                      } else if (id == 4 && last_code_4.containsKey("time")) {
                        sendCodePage(last_code_4);
                      } else if (id == 5 && last_code_5.containsKey("time")) {
                        sendCodePage(last_code_5);
                      } else {
                        sendHomePage("Code does not exist", "Alert", 2, 404); // 404
                      }
                    });
                  
                    server.on("/", []() {
                      Serial.println("Connection received");
                      sendHomePage(); // 200
                    });
                  
                    server.begin();
                    Serial.println("HTTP Server started on port " + String(port));
                  
                    externalIP();
                  
                    irsend1.begin();
                    irsend2.begin();
                    irsend3.begin();
                    irsend4.begin();
                    irrecv.enableIRIn();
                    Serial.println("Ready to send and receive IR signals");
                  }
                  
                  
                  //+=============================================================================
                  // IP Address to String
                  //
                  String ipToString(IPAddress ip)
                  {
                    String s="";
                    for (int i=0; i<4; i++)
                      s += i  ? "." + String(ip[i]) : String(ip[i]);
                    return s;
                  }
                  
                  
                  //+=============================================================================
                  // Send command to local roku
                  //
                  int rokuCommand(String ip, String data) {
                    String url = "http://" + ip + ":8060/" + data;
                    http.begin(url);
                    Serial.println(url);
                    Serial.println("Sending roku command");
                  
                    copyJsonSend(last_send_4, last_send_5);
                    copyJsonSend(last_send_3, last_send_4);
                    copyJsonSend(last_send_2, last_send_3);
                    copyJsonSend(last_send, last_send_2);
                  
                    last_send["data"] = data;
                    last_send["len"] = 1;
                    last_send["type"] = "roku";
                    last_send["address"] = ip;
                    last_send["time"] = String(timeClient.getFormattedTime());
                    return http.POST("");
                    http.end();
                  }
                  
                  
                  //+=============================================================================
                  // Split string by character
                  //
                  String getValue(String data, char separator, int index)
                  {
                    int found = 0;
                    int strIndex[] = {0, -1};
                    int maxIndex = data.length() - 1;
                  
                    for (int i = 0; i <= maxIndex && found <= index; i++) {
                      if (data.charAt(i) == separator || i == maxIndex) {
                        found++;
                        strIndex[0] = strIndex[1] + 1;
                        strIndex[1] = (i == maxIndex) ? i + 1 : i;
                      }
                    }
                  
                    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
                  }
                  
                  
                  //+=============================================================================
                  // Return which IRsend object to act on
                  //
                  IRsend pickIRsend (int out) {
                    switch (out) {
                      case 1: return irsend1;
                      case 2: return irsend2;
                      case 3: return irsend3;
                      case 4: return irsend4;
                      default: return irsend1;
                    }
                  }
                  
                  
                  //+=============================================================================
                  // Display encoding type
                  //
                  // Display encoding type
                  //
                  String encoding(decode_results *results) {
                    String output;
                    switch (results->decode_type) {
                      default:
                      case UNKNOWN:      output = "UNKNOWN";            break;
                      case NEC:          output = "NEC";                break;
                      case SONY:         output = "SONY";               break;
                      case RC5:          output = "RC5";                break;
                      case RC6:          output = "RC6";                break;
                      case DISH:         output = "DISH";               break;
                      case SHARP:        output = "SHARP";              break;
                      case JVC:          output = "JVC";                break;
                      case SANYO:        output = "SANYO";              break;
                      case SANYO_LC7461: output = "SANYO_LC7461";       break;
                      case MITSUBISHI:   output = "MITSUBISHI";         break;
                      case SAMSUNG:      output = "SAMSUNG";            break;
                      case LG:           output = "LG";                 break;
                      case WHYNTER:      output = "WHYNTER";            break;
                      case AIWA_RC_T501: output = "AIWA_RC_T501";       break;
                      case PANASONIC:    output = "PANASONIC";          break;
                      case DENON:        output = "DENON";              break;
                      case COOLIX:       output = "COOLIX";             break;
                    }
                    return output;
                    if (results->repeat) Serial.print(" (Repeat)");
                  }
                  
                  //+=============================================================================
                  // Uint64 to String
                  //
                  String Uint64toString(uint64_t input, uint8_t base) {
                    char buf[8 * sizeof(input) + 1];  // Assumes 8-bit chars plus zero byte.
                    char *str = &buf[sizeof(buf) - 1];
                  
                    *str = '\0';
                  
                    // prevent crash if called with base == 1
                    if (base < 2) base = 10;
                  
                    do {
                      char c = input % base;
                      input /= base;
                  
                      *--str = c < 10 ? c + '0' : c + 'A' - 10;
                    } while (input);
                  
                    std::string s(str);
                    return s.c_str();
                  }
                  
                  //+=============================================================================
                  // Code to string
                  //
                  void fullCode (decode_results *results)
                  {
                    Serial.print("One line: ");
                    serialPrintUint64(results->value, 16);
                    Serial.print(":");
                    Serial.print(encoding(results));
                    Serial.print(":");
                    Serial.print(results->bits, DEC);
                    if (results->overflow)
                      Serial.println("WARNING: IR code too long."
                                     "Edit IRrecv.h and increase RAWBUF");
                    Serial.println("");
                  }
                  
                  //+=============================================================================
                  // Send header HTML
                  //
                  void sendHeader() {
                    sendHeader(200);
                  }
                  
                  void sendHeader(int httpcode) {
                    server.setContentLength(CONTENT_LENGTH_UNKNOWN);
                    server.send(httpcode, "text/html; charset=utf-8", "");
                    server.sendContent("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n");
                    server.sendContent("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>\n");
                    server.sendContent("  <head>\n");
                    server.sendContent("    <meta name='viewport' content='width=device-width, initial-scale=.75' />\n");
                    server.sendContent("    <link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' />\n");
                    server.sendContent("    <style>@media (max-width: 991px) {.nav-pills>li {float: none; margin-left: 0; margin-top: 5px; text-align: center;}}</style>\n");
                    server.sendContent("    <title>ESP8266 IR Controller (" + String(host_name) + ")</title>\n");
                    server.sendContent("  </head>\n");
                    server.sendContent("  <body>\n");
                    server.sendContent("    <div class='container'>\n");
                    server.sendContent("      <h1><a href='https://github.com/mdhiggins/ESP8266-HTTP-IR-Blaster'>ESP8266 IR Controller</a></h1>\n");
                    server.sendContent("      <div class='row'>\n");
                    server.sendContent("        <div class='col-md-12'>\n");
                    server.sendContent("          <ul class='nav nav-pills'>\n");
                    server.sendContent("            <li class='active'>\n");
                    server.sendContent("              <a href='http://" + String(host_name) + ".local" + ":" + String(port) + "'>Hostname <span class='badge'>" + String(host_name) + ".local" + ":" + String(port) + "</span></a></li>\n");
                    server.sendContent("            <li class='active'>\n");
                    server.sendContent("              <a href='http://" + ipToString(WiFi.localIP()) + ":" + String(port) + "'>Local <span class='badge'>" + ipToString(WiFi.localIP()) + ":" + String(port) + "</span></a></li>\n");
                    server.sendContent("            <li class='active'>\n");
                    server.sendContent("              <a href='http://" + externalIP() + ":" + String(port) + "'>External <span class='badge'>" + externalIP() + ":" + String(port) + "</span></a></li>\n");
                    server.sendContent("            <li class='active'>\n");
                    server.sendContent("              <a href='#'>MAC <span class='badge'>" + String(WiFi.macAddress()) + "</span></a></li>\n");
                    server.sendContent("          </ul>\n");
                    server.sendContent("        </div>\n");
                    server.sendContent("      </div><hr />\n");
                  }
                  
                  //+=============================================================================
                  // Send footer HTML
                  //
                  void sendFooter() {
                    server.sendContent("      <div class='row'><div class='col-md-12'><em>" + String(millis()) + "ms uptime</em></div></div>\n");
                    server.sendContent("    </div>\n");
                    server.sendContent("  </body>\n");
                    server.sendContent("</html>\n");
                    server.client().stop();
                  }
                  
                  //+=============================================================================
                  // Stream home page HTML
                  //
                  void sendHomePage() {
                    sendHomePage("", "");
                  }
                  
                  void sendHomePage(String message, String header) {
                    sendHomePage(message, header, 0);
                  }
                  
                  void sendHomePage(String message, String header, int type) {
                    sendHomePage(message, header, type, 200);
                  }
                  
                  void sendHomePage(String message, String header, int type, int httpcode) {
                    sendHeader(httpcode);
                    if (type == 1)
                    server.sendContent("      <div class='row'><div class='col-md-12'><div class='alert alert-success'><strong>" + header + "!</strong> " + message + "</div></div></div>\n");
                    if (type == 2)
                    server.sendContent("      <div class='row'><div class='col-md-12'><div class='alert alert-warning'><strong>" + header + "!</strong> " + message + "</div></div></div>\n");
                    if (type == 3)
                    server.sendContent("      <div class='row'><div class='col-md-12'><div class='alert alert-danger'><strong>" + header + "!</strong> " + message + "</div></div></div>\n");
                    server.sendContent("      <div class='row'>\n");
                    server.sendContent("        <div class='col-md-12'>\n");
                    server.sendContent("          <h3>Codes Transmitted</h3>\n");
                    server.sendContent("          <table class='table table-striped' style='table-layout: fixed;'>\n");
                    server.sendContent("            <thead><tr><th>Sent</th><th>Command</th><th>Type</th><th>Length</th><th>Address</th></tr></thead>\n"); //Title
                    server.sendContent("            <tbody>\n");
                    if (last_send.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td>" + last_send["time"].as<String>() + "</td><td><code>" + last_send["data"].as<String>() + "</code></td><td><code>" + last_send["type"].as<String>() + "</code></td><td><code>" + last_send["len"].as<String>() + "</code></td><td><code>" + last_send["address"].as<String>() + "</code></td></tr>\n");
                    if (last_send_2.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td>" + last_send_2["time"].as<String>() + "</td><td><code>" + last_send_2["data"].as<String>() + "</code></td><td><code>" + last_send_2["type"].as<String>() + "</code></td><td><code>" + last_send_2["len"].as<String>() + "</code></td><td><code>" + last_send_2["address"].as<String>() + "</code></td></tr>\n");
                    if (last_send_3.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td>" + last_send_3["time"].as<String>() + "</td><td><code>" + last_send_3["data"].as<String>() + "</code></td><td><code>" + last_send_3["type"].as<String>() + "</code></td><td><code>" + last_send_3["len"].as<String>() + "</code></td><td><code>" + last_send_3["address"].as<String>() + "</code></td></tr>\n");
                    if (last_send_4.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td>" + last_send_4["time"].as<String>() + "</td><td><code>" + last_send_4["data"].as<String>() + "</code></td><td><code>" + last_send_4["type"].as<String>() + "</code></td><td><code>" + last_send_4["len"].as<String>() + "</code></td><td><code>" + last_send_4["address"].as<String>() + "</code></td></tr>\n");
                    if (last_send_5.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td>" + last_send_5["time"].as<String>() + "</td><td><code>" + last_send_5["data"].as<String>() + "</code></td><td><code>" + last_send_5["type"].as<String>() + "</code></td><td><code>" + last_send_5["len"].as<String>() + "</code></td><td><code>" + last_send_5["address"].as<String>() + "</code></td></tr>\n");
                    if (!last_send.containsKey("time") && !last_send_2.containsKey("time") && !last_send_3.containsKey("time") && !last_send_4.containsKey("time") && !last_send_5.containsKey("time"))
                    server.sendContent("              <tr><td colspan='5' class='text-center'><em>No codes sent</em></td></tr>");
                    server.sendContent("            </tbody></table>\n");
                    server.sendContent("          </div></div>\n");
                    server.sendContent("      <div class='row'>\n");
                    server.sendContent("        <div class='col-md-12'>\n");
                    server.sendContent("          <h3>Codes Received</h3>\n");
                    server.sendContent("          <table class='table table-striped' style='table-layout: fixed;'>\n");
                    server.sendContent("            <thead><tr><th>Time Sent</th><th>Command</th><th>Type</th><th>Length</th><th>Address</th></tr></thead>\n"); //Title
                    server.sendContent("            <tbody>\n");
                    if (last_code.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=1'>" + last_code["time"].as<String>() + "</a></td><td><code>" + last_code["data"].as<String>() + "</code></td><td><code>" + last_code["encoding"].as<String>() + "</code></td><td><code>" + last_code["bits"].as<String>() + "</code></td><td><code>" + last_code["address"].as<String>() + "</code></td></tr>\n");
                    if (last_code_2.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=2'>" + last_code_2["time"].as<String>() + "</a></td><td><code>" + last_code_2["data"].as<String>() + "</code></td><td><code>" + last_code_2["encoding"].as<String>() + "</code></td><td><code>" + last_code_2["bits"].as<String>() + "</code></td><td><code>" + last_code_2["address"].as<String>() + "</code></td></tr>\n");
                    if (last_code_3.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=3'>" + last_code_3["time"].as<String>() + "</a></td><td><code>" + last_code_3["data"].as<String>() + "</code></td><td><code>" + last_code_3["encoding"].as<String>() + "</code></td><td><code>" + last_code_3["bits"].as<String>() + "</code></td><td><code>" + last_code_3["address"].as<String>() + "</code></td></tr>\n");
                    if (last_code_4.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=4'>" + last_code_4["time"].as<String>() + "</a></td><td><code>" + last_code_4["data"].as<String>() + "</code></td><td><code>" + last_code_4["encoding"].as<String>() + "</code></td><td><code>" + last_code_4["bits"].as<String>() + "</code></td><td><code>" + last_code_4["address"].as<String>() + "</code></td></tr>\n");
                    if (last_code_5.containsKey("time"))
                    server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=5'>" + last_code_5["time"].as<String>() + "</a></td><td><code>" + last_code_5["data"].as<String>() + "</code></td><td><code>" + last_code_5["encoding"].as<String>() + "</code></td><td><code>" + last_code_5["bits"].as<String>() + "</code></td><td><code>" + last_code_5["address"].as<String>() + "</code></td></tr>\n");
                    if (!last_code.containsKey("time") && !last_code_2.containsKey("time") && !last_code_3.containsKey("time") && !last_code_4.containsKey("time") && !last_code_5.containsKey("time"))
                    server.sendContent("              <tr><td colspan='5' class='text-center'><em>No codes received</em></td></tr>");
                    server.sendContent("            </tbody></table>\n");
                    server.sendContent("          </div></div>\n");
                    server.sendContent("      <div class='row'>\n");
                    server.sendContent("        <div class='col-md-12'>\n");
                    server.sendContent("          <ul class='list-unstyled'>\n");
                    server.sendContent("            <li><span class='badge'>GPIO " + String(pinr1) + "</span> Receiving </li>\n");
                    server.sendContent("            <li><span class='badge'>GPIO " + String(pins1) + "</span> Transmitter 1 </li>\n");
                    server.sendContent("            <li><span class='badge'>GPIO " + String(pins2) + "</span> Transmitter 2 </li>\n");
                    server.sendContent("            <li><span class='badge'>GPIO " + String(pins3) + "</span> Transmitter 3 </li>\n");
                    server.sendContent("            <li><span class='badge'>GPIO " + String(pins4) + "</span> Transmitter 4 </li></ul>\n");
                    server.sendContent("        </div>\n");
                    server.sendContent("      </div>\n");
                    sendFooter();
                  }
                  
                  //+=============================================================================
                  // Stream code page HTML
                  //
                  void sendCodePage(JsonObject& selCode) {
                    sendCodePage(selCode, 200);
                  }
                  
                  void sendCodePage(JsonObject& selCode, int httpcode){
                    sendHeader(httpcode);
                    server.sendContent("      <div class='row'>\n");
                    server.sendContent("        <div class='col-md-12'>\n");
                    server.sendContent("          <h2><span class='label label-success'>" + selCode["data"].as<String>() + ":" + selCode["encoding"].as<String>() + ":" + selCode["bits"].as<String>() + "</span></h2><br/>\n");
                    server.sendContent("          <dl class='dl-horizontal'>\n");
                    server.sendContent("            <dt>Data</dt>\n");
                    server.sendContent("            <dd><code>" + selCode["data"].as<String>()  + "</code></dd></dl>\n");
                    server.sendContent("          <dl class='dl-horizontal'>\n");
                    server.sendContent("            <dt>Type</dt>\n");
                    server.sendContent("            <dd><code>" + selCode["encoding"].as<String>()  + "</code></dd></dl>\n");
                    server.sendContent("          <dl class='dl-horizontal'>\n");
                    server.sendContent("            <dt>Length</dt>\n");
                    server.sendContent("            <dd><code>" + selCode["bits"].as<String>()  + "</code></dd></dl>\n");
                    server.sendContent("          <dl class='dl-horizontal'>\n");
                    server.sendContent("            <dt>Address</dt>\n");
                    server.sendContent("            <dd><code>" + selCode["address"].as<String>()  + "</code></dd></dl>\n");
                    server.sendContent("          <dl class='dl-horizontal'>\n");
                    server.sendContent("            <dt>Raw</dt>\n");
                    server.sendContent("            <dd><code>" + selCode["uint16_t"].as<String>()  + "</code></dd></dl>\n");
                    server.sendContent("        </div></div>\n");
                    server.sendContent("      <div class='row'>\n");
                    server.sendContent("        <div class='col-md-12'>\n");
                    server.sendContent("          <div class='alert alert-warning'>Don't forget to add your passcode to the URLs below if you set one</div>\n");
                    server.sendContent("      </div></div>\n");
                    if (selCode["encoding"] == "UNKNOWN") {
                    server.sendContent("      <div class='row'>\n");
                    server.sendContent("        <div class='col-md-12'>\n");
                    server.sendContent("          <ul class='list-unstyled'>\n");
                    server.sendContent("            <li>Hostname <span class='label label-default'>JSON</span></li>\n");
                    server.sendContent("            <li><pre>http://" + String(host_name) + ".local:" + String(port) + "/json?plain=[{'data':[" + selCode["uint16_t"].as<String>() + "], 'type':'raw', 'khz':38}]</pre></li>\n");
                    server.sendContent("            <li>Local IP <span class='label label-default'>JSON</span></li>\n");
                    server.sendContent("            <li><pre>http://" + ipToString(WiFi.localIP()) + ":" + String(port) + "/json?plain=[{'data':[" + selCode["uint16_t"].as<String>() + "], 'type':'raw', 'khz':38}]</pre></li>\n");
                    server.sendContent("            <li>External IP <span class='label label-default'>JSON</span></li>\n");
                    server.sendContent("            <li><pre>http://" + externalIP() + ":" + String(port) + "/json?plain=[{'data':[" + selCode["uint16_t"].as<String>() + "], 'type':'raw', 'khz':38}]</pre></li></ul>\n");
                    } else {
                    server.sendContent("      <div class='row'>\n");
                    server.sendContent("        <div class='col-md-12'>\n");
                    server.sendContent("          <ul class='list-unstyled'>\n");
                    server.sendContent("            <li>Hostname <span class='label label-default'>MSG</span></li>\n");
                    server.sendContent("            <li><pre>http://" + String(host_name) + ".local:" + String(port) + "/msg?code=" + selCode["data"].as<String>() + ":" + selCode["encoding"].as<String>() + ":" + selCode["bits"].as<String>() + "</pre></li>\n");
                    server.sendContent("            <li>Local IP <span class='label label-default'>MSG</span></li>\n");
                    server.sendContent("            <li><pre>http://" + ipToString(WiFi.localIP()) + ":" + String(port) + "/msg?code=" + selCode["data"].as<String>() + ":" + selCode["encoding"].as<String>() + ":" + selCode["bits"].as<String>() + "</pre></li>\n");
                    server.sendContent("            <li>External IP <span class='label label-default'>MSG</span></li>\n");
                    server.sendContent("            <li><pre>http://" + externalIP() + ":" + String(port) + "/msg?code=" + selCode["data"].as<String>() + ":" + selCode["encoding"].as<String>() + ":" + selCode["bits"].as<String>() + "</pre></li></ul>\n");
                    server.sendContent("          <ul class='list-unstyled'>\n");
                    server.sendContent("            <li>Hostname <span class='label label-default'>JSON</span></li>\n");
                    server.sendContent("            <li><pre>http://" + String(host_name) + ".local:" + String(port) + "/json?plain=[{'data':'" + selCode["data"].as<String>() + "', 'type':'" + selCode["encoding"].as<String>() + "', 'length':" + selCode["bits"].as<String>() + "}]</pre></li>\n");
                    server.sendContent("            <li>Local IP <span class='label label-default'>JSON</span></li>\n");
                    server.sendContent("            <li><pre>http://" + ipToString(WiFi.localIP()) + ":" + String(port) + "/json?plain=[{'data':'" + selCode["data"].as<String>() + "', 'type':'" + selCode["encoding"].as<String>() + "', 'length':" + selCode["bits"].as<String>() + "}]</pre></li>\n");
                    server.sendContent("            <li>External IP <span class='label label-default'>JSON</span></li>\n");
                    server.sendContent("            <li><pre>http://" + externalIP() + ":" + String(port) + "/json?plain=[{'data':'" + selCode["data"].as<String>() + "', 'type':'" + selCode["encoding"].as<String>() + "', 'length':" + selCode["bits"].as<String>() + "}]</pre></li></ul>\n");
                    }
                    server.sendContent("        </div>\n");
                    server.sendContent("     </div>\n");
                    sendFooter();
                  }
                  
                  //+=============================================================================
                  // Code to JsonObject
                  //
                  void codeJson(JsonObject &codeData, decode_results *results)
                  {
                    codeData["data"] = Uint64toString(results->value, 16);
                    codeData["encoding"] = encoding(results);
                    codeData["bits"] = results->bits;
                    String r = "";
                        for (uint16_t i = 1; i < results->rawlen; i++) {
                        r += results->rawbuf[i] * USECPERTICK;
                        if (i < results->rawlen - 1)
                          r += ",";                           // ',' not needed on last one
                        if (!(i & 1)) r += " ";
                      }
                    codeData["uint16_t"] = r;
                    if (results->decode_type != UNKNOWN) {
                      codeData["address"] = "0x" + String(results->address, HEX);
                      codeData["command"] = "0x" + String(results->command, HEX);
                    } else {
                      codeData["address"] = "0x";
                      codeData["command"] = "0x";
                    }
                  }
                  
                  //+=============================================================================
                  // Dump out the decode_results structure.
                  //
                  void dumpInfo(decode_results *results) {
                    if (results->overflow)
                      Serial.println("WARNING: IR code too long."
                                     "Edit IRrecv.h and increase RAWBUF");
                  
                    // Show Encoding standard
                    Serial.print("Encoding  : ");
                    Serial.print(encoding(results));
                    Serial.println("");
                  
                    // Show Code & length
                    Serial.print("Code      : ");
                    serialPrintUint64(results->value, 16);
                    Serial.print(" (");
                    Serial.print(results->bits, DEC);
                    Serial.println(" bits)");
                  }
                  
                  
                  //+=============================================================================
                  // Dump out the decode_results structure.
                  //
                  void dumpRaw(decode_results *results) {
                    // Print Raw data
                    Serial.print("Timing[");
                    Serial.print(results->rawlen - 1, DEC);
                    Serial.println("]: ");
                  
                    for (uint16_t i = 1;  i < results->rawlen;  i++) {
                      if (i % 100 == 0)
                        yield();  // Preemptive yield every 100th entry to feed the WDT.
                      uint32_t x = results->rawbuf[i] * USECPERTICK;
                      if (!(i & 1)) {  // even
                        Serial.print("-");
                        if (x < 1000) Serial.print(" ");
                        if (x < 100) Serial.print(" ");
                        Serial.print(x, DEC);
                      } else {  // odd
                        Serial.print("     ");
                        Serial.print("+");
                        if (x < 1000) Serial.print(" ");
                        if (x < 100) Serial.print(" ");
                        Serial.print(x, DEC);
                        if (i < results->rawlen - 1)
                          Serial.print(", ");  // ',' not needed for last one
                      }
                      if (!(i % 8)) Serial.println("");
                    }
                    Serial.println("");  // Newline
                  }
                  
                  
                  //+=============================================================================
                  // Dump out the decode_results structure.
                  //
                  void dumpCode(decode_results *results) {
                    // Start declaration
                    Serial.print("uint16_t  ");              // variable type
                    Serial.print("rawData[");                // array name
                    Serial.print(results->rawlen - 1, DEC);  // array size
                    Serial.print("] = {");                   // Start declaration
                  
                    // Dump data
                    for (uint16_t i = 1; i < results->rawlen; i++) {
                      Serial.print(results->rawbuf[i] * USECPERTICK, DEC);
                      if (i < results->rawlen - 1)
                        Serial.print(",");  // ',' not needed on last one
                      if (!(i & 1)) Serial.print(" ");
                    }
                  
                    // End declaration
                    Serial.print("};");  //
                  
                    // Comment
                    Serial.print("  // ");
                    Serial.print(encoding(results));
                    Serial.print(" ");
                    serialPrintUint64(results->value, 16);
                  
                    // Newline
                    Serial.println("");
                  
                    // Now dump "known" codes
                    if (results->decode_type != UNKNOWN) {
                      // Some protocols have an address &/or command.
                      // NOTE: It will ignore the atypical case when a message has been decoded
                      // but the address & the command are both 0.
                      if (results->address > 0 || results->command > 0) {
                        Serial.print("uint32_t  address = 0x");
                        Serial.print(results->address, HEX);
                        Serial.println(";");
                        Serial.print("uint32_t  command = 0x");
                        Serial.print(results->command, HEX);
                        Serial.println(";");
                      }
                  
                      // All protocols have data
                      Serial.print("uint64_t  data = 0x");
                      serialPrintUint64(results->value, 16);
                      Serial.println(";");
                    }
                  }
                  
                  
                  //+=============================================================================
                  // Convert string to hex, borrowed from ESPBasic
                  //
                  unsigned long HexToLongInt(String h)
                  {
                    // this function replace the strtol as this function is not able to handle hex numbers greather than 7fffffff
                    // I'll take char by char converting from hex to char then shifting 4 bits at the time
                    int i;
                    unsigned long tmp = 0;
                    unsigned char c;
                    int s = 0;
                    h.toUpperCase();
                    for (i = h.length() - 1; i >= 0 ; i--)
                    {
                      // take the char starting from the right
                      c = h[i];
                      // convert from hex to int
                      c = c - '0';
                      if (c > 9)
                        c = c - 7;
                      // add and shift of 4 bits per each char
                      tmp += c << s;
                      s += 4;
                    }
                    return tmp;
                  }
                  
                  
                  //+=============================================================================
                  // Send IR codes to variety of sources
                  //
                  void irblast(String type, String dataStr, unsigned int len, int rdelay, int pulse, int pdelay, int repeat, long address, IRsend irsend) {
                    Serial.println("Blasting off");
                    type.toLowerCase();
                    unsigned long data = HexToLongInt(dataStr);
                    holdReceive = true;
                    Serial.println("Blocking incoming IR signals");
                    // Repeat Loop
                    for (int r = 0; r < repeat; r++) {
                      // Pulse Loop
                      for (int p = 0; p < pulse; p++) {
                        Serial.print(data, HEX);
                        Serial.print(":");
                        Serial.print(type);
                        Serial.print(":");
                        Serial.println(len);
                        if (type == "nec") {
                          irsend.sendNEC(data, len);
                        } else if (type == "sony") {
                          irsend.sendSony(data, len);
                        } else if (type == "coolix") {
                          irsend.sendCOOLIX(data, len);
                        } else if (type == "whynter") {
                          irsend.sendWhynter(data, len);
                        } else if (type == "panasonic") {
                          Serial.println(address);
                          irsend.sendPanasonic(address, data);
                        } else if (type == "jvc") {
                          irsend.sendJVC(data, len, 0);
                        } else if (type == "samsung") {
                          irsend.sendSAMSUNG(data, len);
                        } else if (type == "sharp") {
                          irsend.sendSharpRaw(data, len);
                        } else if (type == "dish") {
                          irsend.sendDISH(data, len);
                        } else if (type == "rc5") {
                          irsend.sendRC5(data, len);
                        } else if (type == "rc6") {
                          irsend.sendRC6(data, len);
                        } else if (type == "roomba") {
                          roomba_send(atoi(dataStr.c_str()), pulse, pdelay, irsend);
                        }
                        delay(pdelay);
                      }
                      delay(rdelay);
                    }
                  
                    copyJsonSend(last_send_4, last_send_5);
                    copyJsonSend(last_send_3, last_send_4);
                    copyJsonSend(last_send_2, last_send_3);
                    copyJsonSend(last_send, last_send_2);
                  
                    last_send["data"] = dataStr;
                    last_send["len"] = len;
                    last_send["type"] = type;
                    last_send["address"] = address;
                    last_send["time"] = String(timeClient.getFormattedTime());
                  
                    resetReceive();
                  }
                  
                  
                  void rawblast(JsonArray &raw, int khz, int rdelay, int pulse, int pdelay, int repeat, IRsend irsend) {
                    Serial.println("Raw transmit");
                    holdReceive = true;
                    Serial.println("Blocking incoming IR signals");
                    // Repeat Loop
                    for (int r = 0; r < repeat; r++) {
                      // Pulse Loop
                      for (int p = 0; p < pulse; p++) {
                        Serial.println("Sending code");
                        irsend.enableIROut(khz);
                        int first = raw[0];
                        for (unsigned int i = 0; i < raw.size(); i++) {
                          unsigned int val = raw[i];
                          if (i & 1) irsend.space(val);
                          else       irsend.mark(val);
                        }
                        irsend.space(0);
                        delay(pdelay);
                      }
                      delay(rdelay);
                    }
                  
                    resetReceive();
                  }
                  
                  
                  void roomba_send(int code, int pulse, int pdelay, IRsend irsend)
                  {
                    Serial.print("Sending Roomba code ");
                    Serial.println(code);
                    holdReceive = true;
                    Serial.println("Blocking incoming IR signals");
                  
                    int length = 8;
                    uint16_t raw[length * 2];
                    unsigned int one_pulse = 3000;
                    unsigned int one_break = 1000;
                    unsigned int zero_pulse = one_break;
                    unsigned int zero_break = one_pulse;
                    uint16_t len = 15;
                    uint16_t hz = 38;
                  
                    int arrayposition = 0;
                    for (int counter = length - 1; counter >= 0; --counter) {
                      if (code & (1 << counter)) {
                        raw[arrayposition] = one_pulse;
                        raw[arrayposition + 1] = one_break;
                      }
                      else {
                        raw[arrayposition] = zero_pulse;
                        raw[arrayposition + 1] = zero_break;
                      }
                      arrayposition = arrayposition + 2;
                    }
                    for (int i = 0; i < pulse; i++) {
                      irsend.sendRaw(raw, len, hz);
                      delay(pdelay);
                    }
                  
                    resetReceive();
                  }
                  
                  void copyJson(JsonObject& j1, JsonObject& j2) {
                    if (j1.containsKey("data"))     j2["data"] = j1["data"];
                    if (j1.containsKey("encoding")) j2["encoding"] = j1["encoding"];
                    if (j1.containsKey("bits"))     j2["bits"] = j1["bits"];
                    if (j1.containsKey("address"))  j2["address"] = j1["address"];
                    if (j1.containsKey("command"))  j2["command"] = j1["command"];
                    if (j1.containsKey("time"))     j2["time"] = j1["time"];
                    if (j1.containsKey("uint16_t")) j2["uint16_t"] = j1["uint16_t"];
                  }
                  
                  void copyJsonSend(JsonObject& j1, JsonObject& j2) {
                    if (j1.containsKey("data"))    j2["data"] = j1["data"];
                    if (j1.containsKey("type"))    j2["type"] = j1["type"];
                    if (j1.containsKey("len"))     j2["len"] = j1["len"];
                    if (j1.containsKey("address")) j2["address"] = j1["address"];
                    if (j1.containsKey("time"))    j2["time"] = j1["time"];
                  }
                  
                  void loop() {
                    server.handleClient();
                    decode_results  results;                                        // Somewhere to store the results
                    if (getTime) timeClient.update();                               // Update the time
                  
                    if (irrecv.decode(&results) && !holdReceive) {                  // Grab an IR code
                      Serial.println("Signal received:");
                      fullCode(&results);                                           // Print the singleline value
                      dumpCode(&results);                                           // Output the results as source code
                      copyJson(last_code_4, last_code_5);                           // Pass
                      copyJson(last_code_3, last_code_4);                           // Pass
                      copyJson(last_code_2, last_code_3);                           // Pass
                      copyJson(last_code, last_code_2);                             // Pass
                      codeJson(last_code, &results);                                // Store the results
                      last_code["time"] = String(timeClient.getFormattedTime());    // Set the new update time
                      Serial.println("start Resault sending to Miniserver");                                           
                      Udp.beginPacket(IP_Remote, Port_Remote);
                      Udp.write(last_code);
                      Udp.endPacket();
                      Serial.println("");                                           // Blank line between entries
                      irrecv.resume();                                              // Prepare for the next value
                      digitalWrite(ledpin, LOW);                                    // Turn on the LED for 0.5 seconds
                      ticker.attach(0.5, disableLed);
                    }
                    delay(200);
                  }
                  
                  

                  Kommentar

                  • romildo
                    Lebende Foren Legende
                    • 25.08.2015
                    • 5161

                    #12
                    Ich habe den unter Code to String eingebunden.
                    Die UDP-Adresse generiere ich anhand der Wifi-Adresse und gebe diese für den gesamten Bereich (255) frei.
                    Die UDP-Daten zeige ich auch im Fenster an.
                    Timezone timeOffset habe ich auf 7200 gestellt

                    Daher ist mein Beispiel etwas anders wie Deins. Es ist sicher noch nicht fertig, aber fürs erste sollte es reichen.
                    Hoffe es hilft Dir etwas weiter.

                    HTML-Code:
                    #include <FS.h>                                               // This needs to be first, or it all crashes and burns
                    
                    #include <IRremoteESP8266.h>
                    #include <IRsend.h>
                    #include <IRrecv.h>
                    #include <IRutils.h>
                    #include <ESP8266WiFi.h>
                    #include <WiFiManager.h>                                      // https://github.com/tzapu/WiFiManager WiFi Configuration Magic
                    #include <ESP8266mDNS.h>                                      // Useful to access to ESP by hostname.local
                    
                    #include <ArduinoJson.h>
                    #include <ESP8266WebServer.h>
                    #include <ESP8266HTTPClient.h>
                    
                    #include <Ticker.h>                                           // For LED status
                    #include <NTPClient.h>
                    #include <WiFiUDP.h>                                          // UDP
                    
                    const int configpin = 13;                                     // GPIO13 (D7 on D1 Mini) to enable configuration (connect to ground)
                    const int ledpin = BUILTIN_LED;                               // Built in LED defined for WEMOS people
                    const char *wifi_config_name = "IRBlaster Configuration";
                    const char serverName[] = "checkip.dyndns.org";
                    int port = 80;
                    char passcode[40] = "";
                    char host_name[40] = "";
                    char port_str[20] = "80";
                    DynamicJsonBuffer jsonBuffer;
                    JsonObject& last_code = jsonBuffer.createObject();            // Stores last code
                    JsonObject& last_code_2 = jsonBuffer.createObject();          // Stores 2nd to last code
                    JsonObject& last_code_3 = jsonBuffer.createObject();          // Stores 3rd to last code
                    JsonObject& last_code_4 = jsonBuffer.createObject();          // Stores 4th to last code
                    JsonObject& last_code_5 = jsonBuffer.createObject();          // Stores 5th to last code
                    JsonObject& last_send = jsonBuffer.createObject();            // Stores last sent
                    JsonObject& last_send_2 = jsonBuffer.createObject();          // Stores 2nd last sent
                    JsonObject& last_send_3 = jsonBuffer.createObject();          // Stores 3rd last sent
                    JsonObject& last_send_4 = jsonBuffer.createObject();          // Stores 4th last sent
                    JsonObject& last_send_5 = jsonBuffer.createObject();          // Stores 5th last sent
                    
                    ESP8266WebServer server(port);
                    HTTPClient http;
                    Ticker ticker;
                    
                    bool shouldSaveConfig = false;                                // Flag for saving data
                    bool holdReceive = false;                                     // Flag to prevent IR receiving while transmitting
                    
                    int pinr1 = 5;                                                // Receiving pin (GPIO5 = D1)
                    int pins1 = 4;                                                // Transmitting preset 1
                    int pins2 = 12;                                               // Transmitting preset 2
                    int pins3 = 16;                                               // Transmitting preset 3
                    int pins4 = 15;                                               // Transmitting preset 4
                    
                    IRrecv irrecv(pinr1);
                    IRsend irsend1(pins1);
                    IRsend irsend2(pins2);
                    IRsend irsend3(pins3);
                    IRsend irsend4(pins4);
                    
                    const unsigned long resetfrequency = 259200000;                // 72 hours in milliseconds
                    const int timeOffset = 7200;                                 // Timezone offset in seconds alt -14400
                    const char* poolServerName = "time.nist.gov";
                    
                    const bool getTime = true;                                     // Set to false to disable querying for the time
                    WiFiUDP ntpUDP;
                    NTPClient timeClient(ntpUDP, poolServerName, timeOffset, (int)resetfrequency);
                    
                    const bool getExternalIP = true;                               // Set to false to disable querying external IP
                    String _ip = "";
                    unsigned long lastupdate = 0;
                    
                    //+=============================================================================
                    // UDP variables
                    int PortUDP = 5001;
                    String sIPUDP;
                    char* cIPUDP;
                    String sSignalCodeUDP;
                    char* cSignalCodeUDP;
                    WiFiUDP UDP;
                    
                    void udpSend( char * msg){
                    
                      sIPUDP = udpToString(WiFi.localIP());
                      sIPUDP += ".255";
                      cIPUDP = const_cast<char*>(sIPUDP.c_str());
                      UDP.beginPacket(cIPUDP, PortUDP);
                      UDP.write(msg);
                      UDP.endPacket();
                      Serial.println ("UDP gesendet");
                    }
                    
                    //+=============================================================================
                    // Callback notifying us of the need to save config
                    //
                    void saveConfigCallback () {
                      Serial.println("Should save config");
                      shouldSaveConfig = true;
                    }
                    
                    
                    //+=============================================================================
                    // Reenable IR receiving
                    //
                    void resetReceive() {
                      if (holdReceive) {
                        Serial.println("Reenabling receiving");
                        irrecv.resume();
                        holdReceive = false;
                      }
                    }
                    
                    
                    //+=============================================================================
                    // Toggle state
                    //
                    void tick()
                    {
                      int state = digitalRead(ledpin);  // get the current state of GPIO1 pin
                      digitalWrite(ledpin, !state);     // set pin to the opposite state
                    }
                    
                    
                    //+=============================================================================
                    // Get External IP Address
                    //
                    String externalIP()
                    {
                      if (!getExternalIP) {
                        return "0.0.0.0"; // User doesn't want the external IP
                      }
                    
                      if (_ip != "") {
                        if (millis() - lastupdate > resetfrequency || lastupdate > millis()) {
                          Serial.println("Reseting cached external IP address");
                          _ip = ""; // Reset the cached external IP every 72 hours
                        } else {
                          return _ip;
                        }
                      }
                      unsigned long start = millis();
                      http.setTimeout(5000);
                      http.begin(serverName, 8245);
                      int httpCode = http.GET();
                    
                      if (httpCode > 0 && httpCode == HTTP_CODE_OK) {
                        String payload = http.getString();
                        int pos_start = payload.indexOf("IP Address") + 12; // add 10 for "IP Address" and 2 for ":" + "space"
                        int pos_end = payload.indexOf("</body>", pos_start); // add nothing
                        _ip = payload.substring(pos_start, pos_end);
                        Serial.print(F("External IP: "));
                        Serial.println(_ip);
                        http.end();
                      } else {
                        Serial.println("Error retrieving external IP");
                      }
                    
                      Serial.print("External IP address request took ");
                      Serial.print(millis() - start);
                      Serial.println(" ms");
                    
                      return _ip;
                    }
                    
                    
                    //+=============================================================================
                    // Turn off the Led after timeout
                    //
                    void disableLed()
                    {
                      Serial.println("Turning off the LED to save power.");
                      digitalWrite(ledpin, HIGH);                           // Shut down the LED
                      ticker.detach();                                      // Stopping the ticker
                    }
                    
                    
                    //+=============================================================================
                    // Gets called when WiFiManager enters configuration mode
                    //
                    void configModeCallback (WiFiManager *myWiFiManager) {
                      Serial.println("Entered config mode");
                      Serial.println(WiFi.softAPIP());
                      //if you used auto generated SSID, print it
                      Serial.println(myWiFiManager->getConfigPortalSSID());
                      //entered config mode, make led toggle faster
                      ticker.attach(0.2, tick);
                    }
                    
                    
                    //+=============================================================================
                    // First setup of the Wifi.
                    // If return true, the Wifi is well connected.
                    // Should not return false if Wifi cannot be connected, it will loop
                    //
                    bool setupWifi(bool resetConf) {
                      // set led pin as output
                      pinMode(ledpin, OUTPUT);
                      // start ticker with 0.5 because we start in AP mode and try to connect
                      ticker.attach(0.6, tick);
                    
                      // WiFiManager
                      // Local intialization. Once its business is done, there is no need to keep it around
                      WiFiManager wifiManager;
                      // reset settings - for testing
                      if (resetConf)
                        wifiManager.resetSettings();
                    
                      // set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
                      wifiManager.setAPCallback(configModeCallback);
                      // set config save notify callback
                      wifiManager.setSaveConfigCallback(saveConfigCallback);
                    
                      if (SPIFFS.begin()) {
                        Serial.println("mounted file system");
                        if (SPIFFS.exists("/config.json")) {
                          //file exists, reading and loading
                          Serial.println("reading config file");
                          File configFile = SPIFFS.open("/config.json", "r");
                          if (configFile) {
                            Serial.println("opened config file");
                            size_t size = configFile.size();
                            // Allocate a buffer to store contents of the file.
                            std::unique_ptr<char[]> buf(new char[size]);
                    
                            configFile.readBytes(buf.get(), size);
                            DynamicJsonBuffer jsonBuffer;
                            JsonObject& json = jsonBuffer.parseObject(buf.get());
                            json.printTo(Serial);
                            if (json.success()) {
                              Serial.println("\nparsed json");
                    
                              if (json.containsKey("hostname")) strncpy(host_name, json["hostname"], 40);
                              if (json.containsKey("passcode")) strncpy(passcode, json["passcode"], 40);
                              if (json.containsKey("port_str")) {
                                strncpy(port_str, json["port_str"], 20);
                                port = atoi(json["port_str"]);
                              }
                            } else {
                              Serial.println("failed to load json config");
                            }
                          }
                        }
                      } else {
                        Serial.println("failed to mount FS");
                      }
                      // end read
                    
                      WiFiManagerParameter custom_hostname("hostname", "Choose a hostname to this IRBlaster", host_name, 40);
                      wifiManager.addParameter(&custom_hostname);
                      WiFiManagerParameter custom_passcode("passcode", "Choose a passcode", passcode, 40);
                      wifiManager.addParameter(&custom_passcode);
                      WiFiManagerParameter custom_port("port_str", "Choose a port", port_str, 40);
                      wifiManager.addParameter(&custom_port);
                    
                      // fetches ssid and pass and tries to connect
                      // if it does not connect it starts an access point with the specified name
                      // and goes into a blocking loop awaiting configuration
                      if (!wifiManager.autoConnect(wifi_config_name)) {
                        Serial.println("failed to connect and hit timeout");
                        // reset and try again, or maybe put it to deep sleep
                        ESP.reset();
                        delay(1000);
                      }
                    
                      // if you get here you have connected to the WiFi
                      strncpy(host_name, custom_hostname.getValue(), 40);
                      strncpy(passcode, custom_passcode.getValue(), 40);
                      strncpy(port_str, custom_port.getValue(), 20);
                      port = atoi(port_str);
                    
                      if (port != 80) {
                        Serial.println("Default port changed");
                        server = ESP8266WebServer(port);
                      }
                    
                      Serial.println("WiFi connected! User chose hostname '" + String(host_name) + String("' passcode '") + String(passcode) + "' and port '" + String(port_str) + "'");
                    
                      // save the custom parameters to FS
                      if (shouldSaveConfig) {
                        Serial.println(" config...");
                        DynamicJsonBuffer jsonBuffer;
                        JsonObject& json = jsonBuffer.createObject();
                        json["hostname"] = host_name;
                        json["passcode"] = passcode;
                        json["port_str"] = port_str;
                    
                        File configFile = SPIFFS.open("/config.json", "w");
                        if (!configFile) {
                          Serial.println("failed to open config file for writing");
                        }
                    
                        json.printTo(Serial);
                        Serial.println("");
                        json.printTo(configFile);
                        configFile.close();
                        //e nd save
                      }
                      ticker.detach();
                    
                      // keep LED on
                      digitalWrite(ledpin, LOW);
                      return true;
                    }
                    
                    
                    //+=============================================================================
                    // Setup web server and IR receiver/blaster
                    //
                    void setup() {
                    
                      // Initialize serial
                      Serial.begin(115200);
                      Serial.println("");
                      Serial.println("ESP8266 IR Controller");
                      pinMode(configpin, INPUT_PULLUP);
                      if (!setupWifi(digitalRead(configpin) == LOW))
                        return;
                    
                      WiFi.hostname(host_name);
                      while (WiFi.status() != WL_CONNECTED) {
                        delay(500);
                        Serial.print(".");
                      }
                    
                      wifi_set_sleep_type(LIGHT_SLEEP_T);
                      digitalWrite(ledpin, LOW);
                      // Turn off the led in 2s
                      ticker.attach(2, disableLed);
                    
                      // Configure mDNS
                      if (MDNS.begin(host_name)) {
                        Serial.println("mDNS started. Hostname is set to " + String(host_name) + ".local");
                      }
                      MDNS.addService("http", "tcp", port); // Announce the ESP as an HTTP service
                      Serial.println("URL to send commands: http://" + String(host_name) + ".local:" + port_str);
                    
                      if (getTime) timeClient.begin(); // Get the time
                    
                      // Configure the server
                      server.on("/json", []() { // JSON handler for more complicated IR blaster routines
                        Serial.println("Connection received - JSON");
                    
                        DynamicJsonBuffer jsonBuffer;
                        JsonArray& root = jsonBuffer.parseArray(server.arg("plain"));
                    
                        if (!root.success()) {
                          Serial.println("JSON parsing failed");
                          sendHomePage("JSON parsing failed", "Error", 3, 400); // 400
                        } else if (server.arg("pass") != passcode) {
                          Serial.println("Unauthorized access");
                          sendHomePage("Invalid passcode", "Unauthorized", 3, 401); // 401
                        } else {
                          for (int x = 0; x < root.size(); x++) {
                            String type = root[x]["type"];
                            String ip = root[x]["ip"];
                            int rdelay = root[x]["rdelay"];
                            int pulse = root[x]["pulse"];
                            int pdelay = root[x]["pdelay"];
                            int repeat = root[x]["repeat"];
                            int out = root[x]["out"];
                    
                            if (pulse <= 0) pulse = 1; // Make sure pulse isn't 0
                            if (repeat <= 0) repeat = 1; // Make sure repeat isn't 0
                            if (pdelay <= 0) pdelay = 100; // Default pdelay
                            if (rdelay <= 0) rdelay = 1000; // Default rdelay
                    
                            if (type == "delay") {
                              delay(rdelay);
                            } else if (type == "raw") {
                              JsonArray &raw = root[x]["data"]; // Array of unsigned int values for the raw signal
                              int khz = root[x]["khz"];
                              if (khz <= 0) khz = 38; // Default to 38khz if not set
                              rawblast(raw, khz, rdelay, pulse, pdelay, repeat, pickIRsend(out));
                            } else if (type == "roku") {
                              String data = root[x]["data"];
                              rokuCommand(ip, data);
                            } else {
                              String data = root[x]["data"];
                              long address = root[x]["address"];
                              int len = root[x]["length"];
                              irblast(type, data, len, rdelay, pulse, pdelay, repeat, address, pickIRsend(out));
                            }
                          }
                          digitalWrite(ledpin, LOW);
                          ticker.attach(0.5, disableLed);
                          sendHomePage("Code sent", "Success", 1); // 200
                        }
                      });
                    
                      // Setup simple msg server to mirror version 1.0 functionality
                      server.on("/msg", []() {
                        Serial.println("Connection received - MSG");
                        if (server.arg("pass") != passcode) {
                          Serial.println("Unauthorized access");
                          sendHomePage("Invalid passcode", "Unauthorized", 3, 401); // 401
                        } else {
                          String type = server.arg("type");
                          String data = server.arg("data");
                          String ip = server.arg("ip");
                          int len = server.arg("length").toInt();
                          long address = (server.hasArg("address")) ? server.arg("address").toInt() : 0;
                          int rdelay = (server.hasArg("rdelay")) ? server.arg("rdelay").toInt() : 1000;
                          int pulse = (server.hasArg("pulse")) ? server.arg("pulse").toInt() : 1;
                          int pdelay = (server.hasArg("pdelay")) ? server.arg("pdelay").toInt() : 100;
                          int repeat = (server.hasArg("repeat")) ? server.arg("repeat").toInt() : 1;
                          int out = (server.hasArg("out")) ? server.arg("out").toInt() : 0;
                          if (server.hasArg("code")) {
                            String code = server.arg("code");
                            char separator = ':';
                            data = getValue(code, separator, 0);
                            type = getValue(code, separator, 1);
                            len = getValue(code, separator, 2).toInt();
                          }
                    
                          if (type == "roku") {
                            rokuCommand(ip, data);
                          } else {
                            irblast(type, data, len, rdelay, pulse, pdelay, repeat, address, pickIRsend(out));
                          }
                          digitalWrite(ledpin, LOW);
                          ticker.attach(0.5, disableLed);
                          sendHomePage("Code Sent", "Success", 1); // 200
                        }
                      });
                    
                      server.on("/received", []() {
                        Serial.println("Connection received");
                        int id = server.arg("id").toInt();
                        String output;
                        if (id == 1 && last_code.containsKey("time")) {
                          sendCodePage(last_code);
                        } else if (id == 2 && last_code_2.containsKey("time")) {
                          sendCodePage(last_code_2);
                        } else if (id == 3 && last_code_3.containsKey("time")) {
                          sendCodePage(last_code_3);
                        } else if (id == 4 && last_code_4.containsKey("time")) {
                          sendCodePage(last_code_4);
                        } else if (id == 5 && last_code_5.containsKey("time")) {
                          sendCodePage(last_code_5);
                        } else {
                          sendHomePage("Code does not exist", "Alert", 2, 404); // 404
                        }
                      });
                    
                      server.on("/", []() {
                        Serial.println("Connection received");
                        sendHomePage(); // 200
                      });
                    
                      server.begin();
                      Serial.println("HTTP Server started on port " + String(port));
                    
                      externalIP();
                    
                      irsend1.begin();
                      irsend2.begin();
                      irsend3.begin();
                      irsend4.begin();
                      irrecv.enableIRIn();
                      Serial.println("Ready to send and receive IR signals");
                    }
                    
                    
                    //+=============================================================================
                    // IP Address to String
                    //
                    String ipToString(IPAddress ip)
                    {
                      String s="";
                      for (int i=0; i<4; i++)
                        s += i  ? "." + String(ip[i]) : String(ip[i]);
                      return s;
                    }
                    
                    //+=============================================================================
                    // UDP Address to String
                    //
                    String udpToString(IPAddress ip)
                    {
                      String s="";
                      for (int i=0; i<3; i++)
                        s += i  ? "." + String(ip[i]) : String(ip[i]);
                      return s;
                    }
                    //+=============================================================================
                    // Send command to local roku
                    //
                    int rokuCommand(String ip, String data) {
                      String url = "http://" + ip + ":8060/" + data;
                      http.begin(url);
                      Serial.println(url);
                      Serial.println("Sending roku command");
                    
                      copyJsonSend(last_send_4, last_send_5);
                      copyJsonSend(last_send_3, last_send_4);
                      copyJsonSend(last_send_2, last_send_3);
                      copyJsonSend(last_send, last_send_2);
                    
                      last_send["data"] = data;
                      last_send["len"] = 1;
                      last_send["type"] = "roku";
                      last_send["address"] = ip;
                      last_send["time"] = String(timeClient.getFormattedTime());
                      return http.POST("");
                      http.end();
                    }
                    
                    
                    //+=============================================================================
                    // Split string by character
                    //
                    String getValue(String data, char separator, int index)
                    {
                      int found = 0;
                      int strIndex[] = {0, -1};
                      int maxIndex = data.length() - 1;
                    
                      for (int i = 0; i <= maxIndex && found <= index; i++) {
                        if (data.charAt(i) == separator || i == maxIndex) {
                          found++;
                          strIndex[0] = strIndex[1] + 1;
                          strIndex[1] = (i == maxIndex) ? i + 1 : i;
                        }
                      }
                    
                      return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
                    }
                    
                    
                    //+=============================================================================
                    // Return which IRsend object to act on
                    //
                    IRsend pickIRsend (int out) {
                      switch (out) {
                        case 1: return irsend1;
                        case 2: return irsend2;
                        case 3: return irsend3;
                        case 4: return irsend4;
                        default: return irsend1;
                      }
                    }
                    
                    
                    //+=============================================================================
                    // Display encoding type
                    //
                    // Display encoding type
                    //
                    String encoding(decode_results *results) {
                      String output;
                      switch (results->decode_type) {
                        default:
                        case UNKNOWN:      output = "UNKNOWN";            break;
                        case NEC:          output = "NEC";                break;
                        case SONY:         output = "SONY";               break;
                        case RC5:          output = "RC5";                break;
                        case RC6:          output = "RC6";                break;
                        case DISH:         output = "DISH";               break;
                        case SHARP:        output = "SHARP";              break;
                        case JVC:          output = "JVC";                break;
                        case SANYO:        output = "SANYO";              break;
                        case SANYO_LC7461: output = "SANYO_LC7461";       break;
                        case MITSUBISHI:   output = "MITSUBISHI";         break;
                        case SAMSUNG:      output = "SAMSUNG";            break;
                        case LG:           output = "LG";                 break;
                        case WHYNTER:      output = "WHYNTER";            break;
                        case AIWA_RC_T501: output = "AIWA_RC_T501";       break;
                        case PANASONIC:    output = "PANASONIC";          break;
                        case DENON:        output = "DENON";              break;
                        case COOLIX:       output = "COOLIX";             break;
                      }
                      return output;
                      if (results->repeat) Serial.print(" (Repeat)");
                    }
                    
                    //+=============================================================================
                    // Uint64 to String
                    //
                    String Uint64toString(uint64_t input, uint8_t base) {
                      char buf[8 * sizeof(input) + 1];  // Assumes 8-bit chars plus zero byte.
                      char *str = &buf[sizeof(buf) - 1];
                    
                      *str = '\0';
                    
                      // prevent crash if called with base == 1
                      if (base < 2) base = 10;
                    
                      do {
                        char c = input % base;
                        input /= base;
                    
                        *--str = c < 10 ? c + '0' : c + 'A' - 10;
                      } while (input);
                    
                      std::string s(str);
                      return s.c_str();
                    }
                    
                    //+=============================================================================
                    // Code to string
                    //
                    void fullCode (decode_results *results)
                    {
                      Serial.print("One line: ");
                      serialPrintUint64(results->value, 16);
                      Serial.print(":");
                      Serial.print(encoding(results));
                      Serial.print(":");
                      Serial.print(results->bits, DEC);
                      if (results->overflow)
                        Serial.println("WARNING: IR code too long."
                                       "Edit IRrecv.h and increase RAWBUF");
                      Serial.println("");
                    // Code an UDP senden
                      sSignalCodeUDP = Uint64toString(results->value, 16);
                      cSignalCodeUDP = const_cast<char*>(sSignalCodeUDP.c_str());
                      Serial.println(sSignalCodeUDP);
                      udpSend(cSignalCodeUDP);
                    //
                    }
                    
                    //+=============================================================================
                    // Send header HTML
                    //
                    void sendHeader() {
                      sendHeader(200);
                    }
                    
                    void sendHeader(int httpcode) {
                      server.setContentLength(CONTENT_LENGTH_UNKNOWN);
                      server.send(httpcode, "text/html; charset=utf-8", "");
                      server.sendContent("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n");
                      server.sendContent("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>\n");
                      server.sendContent("  <head>\n");
                      server.sendContent("    <meta name='viewport' content='width=device-width, initial-scale=.75' />\n");
                      server.sendContent("    <link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' />\n");
                      server.sendContent("    <style>@media (max-width: 991px) {.nav-pills>li {float: none; margin-left: 0; margin-top: 5px; text-align: center;}}</style>\n");
                      server.sendContent("    <title>ESP8266 IR Controller (" + String(host_name) + ")</title>\n");
                      server.sendContent("  </head>\n");
                      server.sendContent("  <body>\n");
                      server.sendContent("    <div class='container'>\n");
                      server.sendContent("      <h1><a href='https://github.com/mdhiggins/ESP8266-HTTP-IR-Blaster'>ESP8266 IR Controller</a></h1>\n");
                      server.sendContent("      <div class='row'>\n");
                      server.sendContent("        <div class='col-md-12'>\n");
                      server.sendContent("          <ul class='nav nav-pills'>\n");
                      server.sendContent("            <li class='active'>\n");
                      server.sendContent("              <a href='http://" + String(host_name) + ".local" + ":" + String(port) + "'>Hostname <span class='badge'>" + String(host_name) + ".local" + ":" + String(port) + "</span></a></li>\n");
                      server.sendContent("            <li class='active'>\n");
                      server.sendContent("              <a href='http://" + ipToString(WiFi.localIP()) + ":" + String(port) + "'>Local <span class='badge'>" + ipToString(WiFi.localIP()) + ":" + String(port) + "</span></a></li>\n");
                      server.sendContent("            <li class='active'>\n");
                      server.sendContent("              <a href='http://" + externalIP() + ":" + String(port) + "'>External <span class='badge'>" + externalIP() + ":" + String(port) + "</span></a></li>\n");
                      server.sendContent("            <li class='active'>\n");
                      server.sendContent("              <a href='#'>MAC <span class='badge'>" + String(WiFi.macAddress()) + "</span></a></li>\n");
                    // UDP Adresse und Port anzeigen
                      server.sendContent("            <li class='active'>\n");
                      server.sendContent("              <a href='#'>UDP IP <span class='badge'>" + String(sIPUDP) + "</span></a></li>\n");
                      server.sendContent("            <li class='active'>\n");
                      server.sendContent("              <a href='#'>UDP Port <span class='badge'>" + String(PortUDP) + "</span></a></li>\n");
                    //
                      server.sendContent("          </ul>\n");
                      server.sendContent("        </div>\n");
                      server.sendContent("      </div><hr />\n");
                    }
                    
                    //+=============================================================================
                    // Send footer HTML
                    //
                    void sendFooter() {
                      server.sendContent("      <div class='row'><div class='col-md-12'><em>" + String(millis()) + "ms uptime</em></div></div>\n");
                      server.sendContent("    </div>\n");
                      server.sendContent("  </body>\n");
                      server.sendContent("</html>\n");
                      server.client().stop();
                    }
                    
                    //+=============================================================================
                    // Stream home page HTML
                    //
                    void sendHomePage() {
                      sendHomePage("", "");
                    }
                    
                    void sendHomePage(String message, String header) {
                      sendHomePage(message, header, 0);
                    }
                    
                    void sendHomePage(String message, String header, int type) {
                      sendHomePage(message, header, type, 200);
                    }
                    
                    void sendHomePage(String message, String header, int type, int httpcode) {
                      sendHeader(httpcode);
                      if (type == 1)
                      server.sendContent("      <div class='row'><div class='col-md-12'><div class='alert alert-success'><strong>" + header + "!</strong> " + message + "</div></div></div>\n");
                      if (type == 2)
                      server.sendContent("      <div class='row'><div class='col-md-12'><div class='alert alert-warning'><strong>" + header + "!</strong> " + message + "</div></div></div>\n");
                      if (type == 3)
                      server.sendContent("      <div class='row'><div class='col-md-12'><div class='alert alert-danger'><strong>" + header + "!</strong> " + message + "</div></div></div>\n");
                      server.sendContent("      <div class='row'>\n");
                      server.sendContent("        <div class='col-md-12'>\n");
                      server.sendContent("          <h3>Codes Transmitted</h3>\n");
                      server.sendContent("          <table class='table table-striped' style='table-layout: fixed;'>\n");
                      server.sendContent("            <thead><tr><th>Sent</th><th>Command</th><th>Type</th><th>Length</th><th>Address</th></tr></thead>\n"); //Title
                      server.sendContent("            <tbody>\n");
                      if (last_send.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td>" + last_send["time"].as<String>() + "</td><td><code>" + last_send["data"].as<String>() + "</code></td><td><code>" + last_send["type"].as<String>() + "</code></td><td><code>" + last_send["len"].as<String>() + "</code></td><td><code>" + last_send["address"].as<String>() + "</code></td></tr>\n");
                      if (last_send_2.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td>" + last_send_2["time"].as<String>() + "</td><td><code>" + last_send_2["data"].as<String>() + "</code></td><td><code>" + last_send_2["type"].as<String>() + "</code></td><td><code>" + last_send_2["len"].as<String>() + "</code></td><td><code>" + last_send_2["address"].as<String>() + "</code></td></tr>\n");
                      if (last_send_3.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td>" + last_send_3["time"].as<String>() + "</td><td><code>" + last_send_3["data"].as<String>() + "</code></td><td><code>" + last_send_3["type"].as<String>() + "</code></td><td><code>" + last_send_3["len"].as<String>() + "</code></td><td><code>" + last_send_3["address"].as<String>() + "</code></td></tr>\n");
                      if (last_send_4.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td>" + last_send_4["time"].as<String>() + "</td><td><code>" + last_send_4["data"].as<String>() + "</code></td><td><code>" + last_send_4["type"].as<String>() + "</code></td><td><code>" + last_send_4["len"].as<String>() + "</code></td><td><code>" + last_send_4["address"].as<String>() + "</code></td></tr>\n");
                      if (last_send_5.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td>" + last_send_5["time"].as<String>() + "</td><td><code>" + last_send_5["data"].as<String>() + "</code></td><td><code>" + last_send_5["type"].as<String>() + "</code></td><td><code>" + last_send_5["len"].as<String>() + "</code></td><td><code>" + last_send_5["address"].as<String>() + "</code></td></tr>\n");
                      if (!last_send.containsKey("time") && !last_send_2.containsKey("time") && !last_send_3.containsKey("time") && !last_send_4.containsKey("time") && !last_send_5.containsKey("time"))
                      server.sendContent("              <tr><td colspan='5' class='text-center'><em>No codes sent</em></td></tr>");
                      server.sendContent("            </tbody></table>\n");
                      server.sendContent("          </div></div>\n");
                      server.sendContent("      <div class='row'>\n");
                      server.sendContent("        <div class='col-md-12'>\n");
                      server.sendContent("          <h3>Codes Received</h3>\n");
                      server.sendContent("          <table class='table table-striped' style='table-layout: fixed;'>\n");
                      server.sendContent("            <thead><tr><th>Time Sent</th><th>Command</th><th>Type</th><th>Length</th><th>Address</th></tr></thead>\n"); //Title
                      server.sendContent("            <tbody>\n");
                      if (last_code.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=1'>" + last_code["time"].as<String>() + "</a></td><td><code>" + last_code["data"].as<String>() + "</code></td><td><code>" + last_code["encoding"].as<String>() + "</code></td><td><code>" + last_code["bits"].as<String>() + "</code></td><td><code>" + last_code["address"].as<String>() + "</code></td></tr>\n");
                      if (last_code_2.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=2'>" + last_code_2["time"].as<String>() + "</a></td><td><code>" + last_code_2["data"].as<String>() + "</code></td><td><code>" + last_code_2["encoding"].as<String>() + "</code></td><td><code>" + last_code_2["bits"].as<String>() + "</code></td><td><code>" + last_code_2["address"].as<String>() + "</code></td></tr>\n");
                      if (last_code_3.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=3'>" + last_code_3["time"].as<String>() + "</a></td><td><code>" + last_code_3["data"].as<String>() + "</code></td><td><code>" + last_code_3["encoding"].as<String>() + "</code></td><td><code>" + last_code_3["bits"].as<String>() + "</code></td><td><code>" + last_code_3["address"].as<String>() + "</code></td></tr>\n");
                      if (last_code_4.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=4'>" + last_code_4["time"].as<String>() + "</a></td><td><code>" + last_code_4["data"].as<String>() + "</code></td><td><code>" + last_code_4["encoding"].as<String>() + "</code></td><td><code>" + last_code_4["bits"].as<String>() + "</code></td><td><code>" + last_code_4["address"].as<String>() + "</code></td></tr>\n");
                      if (last_code_5.containsKey("time"))
                      server.sendContent("              <tr class='text-uppercase'><td><a href='/received?id=5'>" + last_code_5["time"].as<String>() + "</a></td><td><code>" + last_code_5["data"].as<String>() + "</code></td><td><code>" + last_code_5["encoding"].as<String>() + "</code></td><td><code>" + last_code_5["bits"].as<String>() + "</code></td><td><code>" + last_code_5["address"].as<String>() + "</code></td></tr>\n");
                      if (!last_code.containsKey("time") && !last_code_2.containsKey("time") && !last_code_3.containsKey("time") && !last_code_4.containsKey("time") && !last_code_5.containsKey("time"))
                      server.sendContent("              <tr><td colspan='5' class='text-center'><em>No codes received</em></td></tr>");
                      server.sendContent("            </tbody></table>\n");
                      server.sendContent("          </div></div>\n");
                      server.sendContent("      <div class='row'>\n");
                      server.sendContent("        <div class='col-md-12'>\n");
                      server.sendContent("          <ul class='list-unstyled'>\n");
                      server.sendContent("            <li><span class='badge'>GPIO " + String(pinr1) + "</span> Receiving </li>\n");
                      server.sendContent("            <li><span class='badge'>GPIO " + String(pins1) + "</span> Transmitter 1 </li>\n");
                      server.sendContent("            <li><span class='badge'>GPIO " + String(pins2) + "</span> Transmitter 2 </li>\n");
                      server.sendContent("            <li><span class='badge'>GPIO " + String(pins3) + "</span> Transmitter 3 </li>\n");
                      server.sendContent("            <li><span class='badge'>GPIO " + String(pins4) + "</span> Transmitter 4 </li></ul>\n");
                      server.sendContent("        </div>\n");
                      server.sendContent("      </div>\n");
                      sendFooter();
                    }
                    
                    //+=============================================================================
                    // Stream code page HTML
                    //
                    void sendCodePage(JsonObject& selCode) {
                      sendCodePage(selCode, 200);
                    }
                    
                    void sendCodePage(JsonObject& selCode, int httpcode){
                      sendHeader(httpcode);
                      server.sendContent("      <div class='row'>\n");
                      server.sendContent("        <div class='col-md-12'>\n");
                      server.sendContent("          <h2><span class='label label-success'>" + selCode["data"].as<String>() + ":" + selCode["encoding"].as<String>() + ":" + selCode["bits"].as<String>() + "</span></h2><br/>\n");
                      server.sendContent("          <dl class='dl-horizontal'>\n");
                      server.sendContent("            <dt>Data</dt>\n");
                      server.sendContent("            <dd><code>" + selCode["data"].as<String>()  + "</code></dd></dl>\n");
                      server.sendContent("          <dl class='dl-horizontal'>\n");
                      server.sendContent("            <dt>Type</dt>\n");
                      server.sendContent("            <dd><code>" + selCode["encoding"].as<String>()  + "</code></dd></dl>\n");
                      server.sendContent("          <dl class='dl-horizontal'>\n");
                      server.sendContent("            <dt>Length</dt>\n");
                      server.sendContent("            <dd><code>" + selCode["bits"].as<String>()  + "</code></dd></dl>\n");
                      server.sendContent("          <dl class='dl-horizontal'>\n");
                      server.sendContent("            <dt>Address</dt>\n");
                      server.sendContent("            <dd><code>" + selCode["address"].as<String>()  + "</code></dd></dl>\n");
                      server.sendContent("          <dl class='dl-horizontal'>\n");
                      server.sendContent("            <dt>Raw</dt>\n");
                      server.sendContent("            <dd><code>" + selCode["uint16_t"].as<String>()  + "</code></dd></dl>\n");
                      server.sendContent("        </div></div>\n");
                      server.sendContent("      <div class='row'>\n");
                      server.sendContent("        <div class='col-md-12'>\n");
                      server.sendContent("          <div class='alert alert-warning'>Don't forget to add your passcode to the URLs below if you set one</div>\n");
                      server.sendContent("      </div></div>\n");
                      if (selCode["encoding"] == "UNKNOWN") {
                      server.sendContent("      <div class='row'>\n");
                      server.sendContent("        <div class='col-md-12'>\n");
                      server.sendContent("          <ul class='list-unstyled'>\n");
                      server.sendContent("            <li>Hostname <span class='label label-default'>JSON</span></li>\n");
                      server.sendContent("            <li><pre>http://" + String(host_name) + ".local:" + String(port) + "/json?plain=[{'data':[" + selCode["uint16_t"].as<String>() + "], 'type':'raw', 'khz':38}]</pre></li>\n");
                      server.sendContent("            <li>Local IP <span class='label label-default'>JSON</span></li>\n");
                      server.sendContent("            <li><pre>http://" + ipToString(WiFi.localIP()) + ":" + String(port) + "/json?plain=[{'data':[" + selCode["uint16_t"].as<String>() + "], 'type':'raw', 'khz':38}]</pre></li>\n");
                      server.sendContent("            <li>External IP <span class='label label-default'>JSON</span></li>\n");
                      server.sendContent("            <li><pre>http://" + externalIP() + ":" + String(port) + "/json?plain=[{'data':[" + selCode["uint16_t"].as<String>() + "], 'type':'raw', 'khz':38}]</pre></li></ul>\n");
                      } else {
                      server.sendContent("      <div class='row'>\n");
                      server.sendContent("        <div class='col-md-12'>\n");
                      server.sendContent("          <ul class='list-unstyled'>\n");
                      server.sendContent("            <li>Hostname <span class='label label-default'>MSG</span></li>\n");
                      server.sendContent("            <li><pre>http://" + String(host_name) + ".local:" + String(port) + "/msg?code=" + selCode["data"].as<String>() + ":" + selCode["encoding"].as<String>() + ":" + selCode["bits"].as<String>() + "</pre></li>\n");
                      server.sendContent("            <li>Local IP <span class='label label-default'>MSG</span></li>\n");
                      server.sendContent("            <li><pre>http://" + ipToString(WiFi.localIP()) + ":" + String(port) + "/msg?code=" + selCode["data"].as<String>() + ":" + selCode["encoding"].as<String>() + ":" + selCode["bits"].as<String>() + "</pre></li>\n");
                      server.sendContent("            <li>External IP <span class='label label-default'>MSG</span></li>\n");
                      server.sendContent("            <li><pre>http://" + externalIP() + ":" + String(port) + "/msg?code=" + selCode["data"].as<String>() + ":" + selCode["encoding"].as<String>() + ":" + selCode["bits"].as<String>() + "</pre></li></ul>\n");
                      server.sendContent("          <ul class='list-unstyled'>\n");
                      server.sendContent("            <li>Hostname <span class='label label-default'>JSON</span></li>\n");
                      server.sendContent("            <li><pre>http://" + String(host_name) + ".local:" + String(port) + "/json?plain=[{'data':'" + selCode["data"].as<String>() + "', 'type':'" + selCode["encoding"].as<String>() + "', 'length':" + selCode["bits"].as<String>() + "}]</pre></li>\n");
                      server.sendContent("            <li>Local IP <span class='label label-default'>JSON</span></li>\n");
                      server.sendContent("            <li><pre>http://" + ipToString(WiFi.localIP()) + ":" + String(port) + "/json?plain=[{'data':'" + selCode["data"].as<String>() + "', 'type':'" + selCode["encoding"].as<String>() + "', 'length':" + selCode["bits"].as<String>() + "}]</pre></li>\n");
                      server.sendContent("            <li>External IP <span class='label label-default'>JSON</span></li>\n");
                      server.sendContent("            <li><pre>http://" + externalIP() + ":" + String(port) + "/json?plain=[{'data':'" + selCode["data"].as<String>() + "', 'type':'" + selCode["encoding"].as<String>() + "', 'length':" + selCode["bits"].as<String>() + "}]</pre></li></ul>\n");
                      }
                      server.sendContent("        </div>\n");
                      server.sendContent("     </div>\n");
                      sendFooter();
                    }
                    
                    //+=============================================================================
                    // Code to JsonObject
                    //
                    void codeJson(JsonObject &codeData, decode_results *results)
                    {
                      codeData["data"] = Uint64toString(results->value, 16);
                      codeData["encoding"] = encoding(results);
                      codeData["bits"] = results->bits;
                      String r = "";
                          for (uint16_t i = 1; i < results->rawlen; i++) {
                          r += results->rawbuf[i] * USECPERTICK;
                          if (i < results->rawlen - 1)
                            r += ",";                           // ',' not needed on last one
                          if (!(i & 1)) r += " ";
                        }
                      codeData["uint16_t"] = r;
                      if (results->decode_type != UNKNOWN) {
                        codeData["address"] = "0x" + String(results->address, HEX);
                        codeData["command"] = "0x" + String(results->command, HEX);
                      } else {
                        codeData["address"] = "0x";
                        codeData["command"] = "0x";
                      }
                    }
                    
                    //+=============================================================================
                    // Dump out the decode_results structure.
                    //
                    void dumpInfo(decode_results *results) {
                      if (results->overflow)
                        Serial.println("WARNING: IR code too long."
                                       "Edit IRrecv.h and increase RAWBUF");
                    
                      // Show Encoding standard
                      Serial.print("Encoding  : ");
                      Serial.print(encoding(results));
                      Serial.println("");
                    
                      // Show Code & length
                      Serial.print("Code      : ");
                      serialPrintUint64(results->value, 16);
                      Serial.print(" (");
                      Serial.print(results->bits, DEC);
                      Serial.println(" bits)");
                    }
                    
                    
                    //+=============================================================================
                    // Dump out the decode_results structure.
                    //
                    void dumpRaw(decode_results *results) {
                      // Print Raw data
                      Serial.print("Timing[");
                      Serial.print(results->rawlen - 1, DEC);
                      Serial.println("]: ");
                    
                      for (uint16_t i = 1;  i < results->rawlen;  i++) {
                        if (i % 100 == 0)
                          yield();  // Preemptive yield every 100th entry to feed the WDT.
                        uint32_t x = results->rawbuf[i] * USECPERTICK;
                        if (!(i & 1)) {  // even
                          Serial.print("-");
                          if (x < 1000) Serial.print(" ");
                          if (x < 100) Serial.print(" ");
                          Serial.print(x, DEC);
                        } else {  // odd
                          Serial.print("     ");
                          Serial.print("+");
                          if (x < 1000) Serial.print(" ");
                          if (x < 100) Serial.print(" ");
                          Serial.print(x, DEC);
                          if (i < results->rawlen - 1)
                            Serial.print(", ");  // ',' not needed for last one
                        }
                        if (!(i % 8)) Serial.println("");
                      }
                      Serial.println("");  // Newline
                    }
                    
                    
                    //+=============================================================================
                    // Dump out the decode_results structure.
                    //
                    void dumpCode(decode_results *results) {
                      // Start declaration
                      Serial.print("uint16_t  ");              // variable type
                      Serial.print("rawData[");                // array name
                      Serial.print(results->rawlen - 1, DEC);  // array size
                      Serial.print("] = {");                   // Start declaration
                    
                      // Dump data
                      for (uint16_t i = 1; i < results->rawlen; i++) {
                        Serial.print(results->rawbuf[i] * USECPERTICK, DEC);
                        if (i < results->rawlen - 1)
                          Serial.print(",");  // ',' not needed on last one
                        if (!(i & 1)) Serial.print(" ");
                      }
                    
                      // End declaration
                      Serial.print("};");  //
                    
                      // Comment
                      Serial.print("  // ");
                      Serial.print(encoding(results));
                      Serial.print(" ");
                      serialPrintUint64(results->value, 16);
                    
                      // Newline
                      Serial.println("");
                    
                      // Now dump "known" codes
                      if (results->decode_type != UNKNOWN) {
                        // Some protocols have an address &/or command.
                        // NOTE: It will ignore the atypical case when a message has been decoded
                        // but the address & the command are both 0.
                        if (results->address > 0 || results->command > 0) {
                          Serial.print("uint32_t  address = 0x");
                          Serial.print(results->address, HEX);
                          Serial.println(";");
                          Serial.print("uint32_t  command = 0x");
                          Serial.print(results->command, HEX);
                          Serial.println(";");
                        }
                    
                        // All protocols have data
                        Serial.print("uint64_t  data = 0x");
                        serialPrintUint64(results->value, 16);
                        Serial.println(";");
                      }
                    }
                    
                    
                    //+=============================================================================
                    // Convert string to hex, borrowed from ESPBasic
                    //
                    unsigned long HexToLongInt(String h)
                    {
                      // this function replace the strtol as this function is not able to handle hex numbers greather than 7fffffff
                      // I'll take char by char converting from hex to char then shifting 4 bits at the time
                      int i;
                      unsigned long tmp = 0;
                      unsigned char c;
                      int s = 0;
                      h.toUpperCase();
                      for (i = h.length() - 1; i >= 0 ; i--)
                      {
                        // take the char starting from the right
                        c = h[i];
                        // convert from hex to int
                        c = c - '0';
                        if (c > 9)
                          c = c - 7;
                        // add and shift of 4 bits per each char
                        tmp += c << s;
                        s += 4;
                      }
                      return tmp;
                    }
                    
                    
                    //+=============================================================================
                    // Send IR codes to variety of sources
                    //
                    void irblast(String type, String dataStr, unsigned int len, int rdelay, int pulse, int pdelay, int repeat, long address, IRsend irsend) {
                      Serial.println("Blasting off");
                      type.toLowerCase();
                      unsigned long data = HexToLongInt(dataStr);
                      holdReceive = true;
                      Serial.println("Blocking incoming IR signals");
                      // Repeat Loop
                      for (int r = 0; r < repeat; r++) {
                        // Pulse Loop
                        for (int p = 0; p < pulse; p++) {
                          Serial.print(data, HEX);
                          Serial.print(":");
                          Serial.print(type);
                          Serial.print(":");
                          Serial.println(len);
                          if (type == "nec") {
                            irsend.sendNEC(data, len);
                          } else if (type == "sony") {
                            irsend.sendSony(data, len);
                          } else if (type == "coolix") {
                            irsend.sendCOOLIX(data, len);
                          } else if (type == "whynter") {
                            irsend.sendWhynter(data, len);
                          } else if (type == "panasonic") {
                            Serial.println(address);
                            irsend.sendPanasonic(address, data);
                          } else if (type == "jvc") {
                            irsend.sendJVC(data, len, 0);
                          } else if (type == "samsung") {
                            irsend.sendSAMSUNG(data, len);
                          } else if (type == "sharp") {
                            irsend.sendSharpRaw(data, len);
                          } else if (type == "dish") {
                            irsend.sendDISH(data, len);
                          } else if (type == "rc5") {
                            irsend.sendRC5(data, len);
                          } else if (type == "rc6") {
                            irsend.sendRC6(data, len);
                          } else if (type == "roomba") {
                            roomba_send(atoi(dataStr.c_str()), pulse, pdelay, irsend);
                          }
                          delay(pdelay);
                        }
                        delay(rdelay);
                      }
                    
                      copyJsonSend(last_send_4, last_send_5);
                      copyJsonSend(last_send_3, last_send_4);
                      copyJsonSend(last_send_2, last_send_3);
                      copyJsonSend(last_send, last_send_2);
                    
                      last_send["data"] = dataStr;
                      last_send["len"] = len;
                      last_send["type"] = type;
                      last_send["address"] = address;
                      last_send["time"] = String(timeClient.getFormattedTime());
                    
                      resetReceive();
                    }
                    
                    
                    void rawblast(JsonArray &raw, int khz, int rdelay, int pulse, int pdelay, int repeat, IRsend irsend) {
                      Serial.println("Raw transmit");
                      holdReceive = true;
                      Serial.println("Blocking incoming IR signals");
                      // Repeat Loop
                      for (int r = 0; r < repeat; r++) {
                        // Pulse Loop
                        for (int p = 0; p < pulse; p++) {
                          Serial.println("Sending code");
                          irsend.enableIROut(khz);
                          int first = raw[0];
                          for (unsigned int i = 0; i < raw.size(); i++) {
                            unsigned int val = raw[i];
                            if (i & 1) irsend.space(val);
                            else       irsend.mark(val);
                          }
                          irsend.space(0);
                          delay(pdelay);
                        }
                        delay(rdelay);
                      }
                    
                      resetReceive();
                    }
                    
                    
                    void roomba_send(int code, int pulse, int pdelay, IRsend irsend)
                    {
                      Serial.print("Sending Roomba code ");
                      Serial.println(code);
                      holdReceive = true;
                      Serial.println("Blocking incoming IR signals");
                    
                      int length = 8;
                      uint16_t raw[length * 2];
                      unsigned int one_pulse = 3000;
                      unsigned int one_break = 1000;
                      unsigned int zero_pulse = one_break;
                      unsigned int zero_break = one_pulse;
                      uint16_t len = 15;
                      uint16_t hz = 38;
                    
                      int arrayposition = 0;
                      for (int counter = length - 1; counter >= 0; --counter) {
                        if (code & (1 << counter)) {
                          raw[arrayposition] = one_pulse;
                          raw[arrayposition + 1] = one_break;
                        }
                        else {
                          raw[arrayposition] = zero_pulse;
                          raw[arrayposition + 1] = zero_break;
                        }
                        arrayposition = arrayposition + 2;
                      }
                      for (int i = 0; i < pulse; i++) {
                        irsend.sendRaw(raw, len, hz);
                        delay(pdelay);
                      }
                    
                      resetReceive();
                    }
                    
                    void copyJson(JsonObject& j1, JsonObject& j2) {
                      if (j1.containsKey("data"))     j2["data"] = j1["data"];
                      if (j1.containsKey("encoding")) j2["encoding"] = j1["encoding"];
                      if (j1.containsKey("bits"))     j2["bits"] = j1["bits"];
                      if (j1.containsKey("address"))  j2["address"] = j1["address"];
                      if (j1.containsKey("command"))  j2["command"] = j1["command"];
                      if (j1.containsKey("time"))     j2["time"] = j1["time"];
                      if (j1.containsKey("uint16_t")) j2["uint16_t"] = j1["uint16_t"];
                    }
                    
                    void copyJsonSend(JsonObject& j1, JsonObject& j2) {
                      if (j1.containsKey("data"))    j2["data"] = j1["data"];
                      if (j1.containsKey("type"))    j2["type"] = j1["type"];
                      if (j1.containsKey("len"))     j2["len"] = j1["len"];
                      if (j1.containsKey("address")) j2["address"] = j1["address"];
                      if (j1.containsKey("time"))    j2["time"] = j1["time"];
                    }
                    
                    void loop() {
                      server.handleClient();
                      decode_results  results;                                        // Somewhere to store the results
                      if (getTime) timeClient.update();                               // Update the time
                    
                      if (irrecv.decode(&results) && !holdReceive) {                  // Grab an IR code
                        Serial.println("Signal received:");
                        fullCode(&results);                                           // Print the singleline value
                        dumpCode(&results);                                           // Output the results as source code
                        copyJson(last_code_4, last_code_5);                           // Pass
                        copyJson(last_code_3, last_code_4);                           // Pass
                        copyJson(last_code_2, last_code_3);                           // Pass
                        copyJson(last_code, last_code_2);                             // Pass
                        codeJson(last_code, &results);                                // Store the results
                        last_code["time"] = String(timeClient.getFormattedTime());    // Set the new update time
                        Serial.println("");                                           // Blank line between entries
                        irrecv.resume();                                              // Prepare for the next value
                        digitalWrite(ledpin, LOW);                                    // Turn on the LED for 0.5 seconds
                        ticker.attach(0.5, disableLed);
                      }
                      delay(200);
                    }
                    Zuletzt geändert von romildo; 07.07.2017, 10:27.
                    lg Romildo

                    Kommentar

                    • ToB204
                      Smart Home'r
                      • 26.08.2015
                      • 54

                      #13
                      Hallo romildo,
                      hab dein Code getestet und die UDP Kommunikation funktioniert super!
                      Nur du hast Recht, es gibt sehr viele Falschmeldungen des IR Codes. Ist mir leider zuvor nicht aufgefallen. Ich nehme an das nicht jedesmal alles vom vollen Code ankommt und das dies dem normalen Empfänger nichts aus ( nur für uns zur Verarbeitung ist es natürlich blöde).
                      Hab daher schon überlegt ob man ne bluetooth Fernbedienung mimt z.B. Die hier http://www.emtec-international.com/de-eu/gem-motion und die irgendwie dazu bringt über den ESP Befehle an den Miniserver zusenden. Das senden der Befehle an die Geräte ( Amp, Sat Reseiver...) dann allerdings wieder ganz normal mit den LED's zu machen.

                      Kommentar


                      • romildo
                        romildo kommentierte
                        Kommentar bearbeiten
                        Oder man schreibt/sucht sich ein anderes Programm welches die Codes dann richtig weitergibt

                        Ich könnte mir schon vorstellen, dass man das Senden an den Miniserver hinkriegen sollte, auch die Weitergabe an andere Geräte mit nur einer Fernsteuerung müsste dann einfach möglich sein, hingegen wird es vermutlich etwas schwieriger, wenn mehrere Fernsteuerungen erkannt werden sollen.

                        Einfacher wär's dann doch den IR CONTROL AIR von Loxone zu nehmen.
                    Lädt...