           " value='190B8050000000E0190B8070000010F0'>"
       " <input type='submit' value='Send A/C State'>"
     "</form>"
-    "<br><hr>"
-#if FIRMWARE_OTA_ENABLE
-    "<h3>Update IR Server firmware</h3><p>"
-    "<b><mark>Warning:</mark></b><br> "
-    "<i>Updating your firmware may screw up your access to the device. "
-    "If you are going to use this, know what you are doing first "
-    "(and you probably do).</i><br>"
-    "<form method='POST' action='/update' enctype='multipart/form-data'>"
-      "Firmware to upload: <input type='file' name='update'>"
-      "<input type='submit' value='Update'>"
-    "</form>"
-#endif  // FIRMWARE_OTA_ENABLE
-    "</body></html>");
+    "<br>";
+#if FIRMWARE_OTA
+  html += "<hr><h3>Update IR Server firmware</h3><p>"
+          "<b><mark>Warning:</mark></b><br> ";
+  if (!strcmp(kHtmlPassword, kDefaultPassword))  // Deny if password unchanged
+    html += "<i>OTA firmware is disabled until you change the password. "
+            "(See 'kHtmlPassword' in the source code.)</i><br>";
+  else  // default password has been changed, so allow it.
+    html +=
+        "<i>Updating your firmware may screw up your access to the device. "
+        "If you are going to use this, know what you are doing first "
+        "(and you probably do).</i><br>"
+        "<form method='POST' action='/update' enctype='multipart/form-data'>"
+          "Firmware to upload: <input type='file' name='update'>"
+          "<input type='submit' value='Update'>"
+        "</form>";
+
+#endif  // FIRMWARE_OTA
+  html += "</body></html>";
+  server.send(200, "text/html", html);
 }
 
 // Reset web page

  // Setup a reset page to cause WiFiManager information to be reset.
  server.on("/reset", handleReset);

#if FIRMWARE_OTA_ENABLE
  // Setup the URL to allow Over-The-Air (OTA) firmware updates.
  server.on("/update", HTTP_POST, [](){
      server.sendHeader("Connection", "close");
      server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
      ESP.restart();
    }, [](){
#if (HTML_PASSWORD_ENABLE || FIRMWARE_OTA_PASSWORD_ENABLE)
      if (!server.authenticate(kHtmlUsername, kHtmlPassword)) {
        debug("Basic HTTP authentication failure for /update.");
        return server.requestAuthentication();
      }
#endif  // (HTML_PASSWORD_ENABLE || FIRMWARE_OTA_PASSWORD_ENABLE)
      HTTPUpload& upload = server.upload();
      if (upload.status == UPLOAD_FILE_START) {
        WiFiUDP::stopAll();
        debug("Update: " + upload.filename);
        uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) &
            0xFFFFF000;
        if (!Update.begin(maxSketchSpace)) {  // start with max available size
#ifdef DEBUG
          Update.printError(Serial);
#endif  // DEBUG
        }
      } else if (upload.status == UPLOAD_FILE_WRITE) {
        if (Update.write(upload.buf, upload.currentSize) !=
            upload.currentSize) {
#ifdef DEBUG
          Update.printError(Serial);
#endif  // DEBUG
        }
      } else if (upload.status == UPLOAD_FILE_END) {
        if (Update.end(true)) {  // true to set the size to the current progress
          debug("Update Success: " + (String) upload.totalSize +
                "\nRebooting...");
        }
      }
      yield();
    });
#endif  // FIRMWARE_OTA_ENABLE

  // Set up an error page.
  server.onNotFound(handleNotFound);

  irrecv.enableIRIn();  // Start the receiver
#endif  // IR_RX

#if DEBUG
  // Use SERIAL_TX_ONLY so that the RX pin can be freed up for GPIO/IR use.
  Serial.begin(BAUD_RATE, SERIAL_8N1, SERIAL_TX_ONLY);
  while (!Serial)  // Wait for the serial connection to be establised.
    delay(50);
  Serial.println();
  debug("IRMQTTServer " _MY_VERSION_" has booted.");
#endif  // DEBUG

  setup_wifi();

