diff --git a/.gitignore b/.gitignore index 69bc38b..0ba4a66 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,6 @@ ubuntu-xenial-16.04-cloudimg-console.log lib/ConfigJson lib/ESPAL lib/OpenEVSE + +# gui static files +src/web_static/ diff --git a/.gitmodules b/.gitmodules index 0528578..cc8da48 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "gui"] path = gui - url = https://github.com/openevse/openevse_wifi_gui + url = https://github.com/chaseadam/openevse_wifi_gui diff --git a/gui b/gui index bb089a9..ae95ac6 160000 --- a/gui +++ b/gui @@ -1 +1 @@ -Subproject commit bb089a95d336ee369337a0dd8a4ee05ad35eca90 +Subproject commit ae95ac6898ecf8b7b4d9830a746eea6e48dd4be5 diff --git a/platformio.ini b/platformio.ini index 0c9a421..09f8c4a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -32,11 +32,12 @@ default_envs = openevse [common] version = -DBUILD_TAG=2.9.1 monitor_speed=115200 +# AsyncWebServer 3.3.18+ does not enter static file handler lib_deps = - PubSubClient@2.6 - ESP Async WebServer@1.2.3 - ESPAsyncTCP@1.2.2 - ArduinoJson@6.15.1 + PubSubClient@2.8 + mathieucarbou/ESPAsyncWebServer @ 3.3.23 + ESP32Async/ESPAsyncTCP@2.0.0 + ArduinoJson@6.21.5 Micro Debug@0.0.3 ConfigJson@0.0.6 OpenEVSE@0.0.14 @@ -48,9 +49,15 @@ debug_flags = # -DENABLE_DEBUG_RAPI -DENABLE_PROFILE -DDEBUG_PORT=Serial1 +# -DDEBUG_ESP_PORT=Serial +# -DDEBUG_ESP_MDNS_RESPONDER +# -DDEBUG_ESP_WIFI +# -DDEBUG_ESP_CORE ota_flags = -DENABLE_OTA -DWIFI_LED=0 +# TODO switch ota password to env variable +# -DOTA_PASSWORD="123" src_build_flags = # -DENABLE_ASYNC_WIFI_SCAN @@ -59,7 +66,7 @@ build_flags = # specify exact Arduino ESP SDK version, requires platformio 3.5+ (curently dev version) # http://docs.platformio.org/en/latest/projectconf/section_env_general.html#platform #platform = https://github.com/platformio/platform-espressif8266.git#release/v1.6.0 -platform = espressif8266@2.5.2 +platform = espressif8266@4.2.1 platform_stage = https://github.com/platformio/platform-espressif8266.git#develop [env:openevse] @@ -91,8 +98,11 @@ framework = arduino lib_deps = ${common.lib_deps} build_flags = ${common.build_flags} ${common.debug_flags} src_build_flags = ${common.version}.dev ${common.src_build_flags} ${common.ota_flags} ${common.debug_flags} -#upload_protocol = espota -#upload_port = openevse.local +# uncomment speed and comment ota lines for initial upload via serial +#upload_speed = 921600 +upload_protocol = espota +upload_port = openevse.local +upload_flags = --auth="123" monitor_speed = ${common.monitor_speed} extra_scripts = ${common.extra_scripts} @@ -130,8 +140,6 @@ board = esp12e framework = arduino lib_deps = https://github.com/knolleary/pubsubclient - https://github.com/me-no-dev/ESPAsyncWebServer.git - https://github.com/me-no-dev/ESPAsyncTCP.git https://github.com/bblanchon/ArduinoJson.git https://github.com/jeremypoulter/MicroDebug.git https://github.com/jeremypoulter/ConfigJson.git diff --git a/src/divert.cpp b/src/divert.cpp index be9dd76..5304238 100644 --- a/src/divert.cpp +++ b/src/divert.cpp @@ -70,8 +70,8 @@ void divertmode_update(byte newmode) { case DIVERT_MODE_NORMAL: // Restore the max charge current - rapiSender.sendCmdSync(String(F("$SC ")) + String(max_charge_current)); - DBUGF("Restore max I: %d", max_charge_current); + //rapiSender.sendCmdSync(String(F("$SC ")) + String(max_charge_current)); + //DBUGF("Restore max I: %d", max_charge_current); break; case DIVERT_MODE_ECO: @@ -208,12 +208,12 @@ void divert_update_state() // Set charge rate via RAPI bool chargeRateSet = false; // Try and set current with new API with volatile flag (don't save the current rate to EEPROM) - if(0 == rapiSender.sendCmdSync(String(F("$SC ")) + String(charge_rate) + String(F(" V")))) { - chargeRateSet = true; - } else if(0 == rapiSender.sendCmdSync(String(F("$SC ")) + String(charge_rate))) { - // Fallback to old API - chargeRateSet = true; - } + //if(0 == rapiSender.sendCmdSync(String(F("$SC ")) + String(charge_rate) + String(F(" V")))) { + // chargeRateSet = true; + //} else if(0 == rapiSender.sendCmdSync(String(F("$SC ")) + String(charge_rate))) { + // // Fallback to old API + // chargeRateSet = true; + //} if(true == chargeRateSet) { @@ -269,9 +269,9 @@ void divert_update_state() DBUGLN(F("Charge Stopped")); event["divert_active"] = divert_active = false; - if(0 == rapiSender.sendCmdSync(String(F("$SC ")) + String(max_charge_current))) { - DBUGF("Restore max I: %d", max_charge_current); - } + //if(0 == rapiSender.sendCmdSync(String(F("$SC ")) + String(max_charge_current))) { + // DBUGF("Restore max I: %d", max_charge_current); + //} } } } diff --git a/src/http.cpp b/src/http.cpp index ebecff9..a1c2c22 100644 --- a/src/http.cpp +++ b/src/http.cpp @@ -5,6 +5,7 @@ #include WiFiClientSecure client; // Create class for HTTPS TCP connections get_https() +WiFiClient client_insecure; HTTPClient http; // Create class for HTTP TCP connections get_http() // ------------------------------------------------------------------- @@ -20,7 +21,7 @@ get_https(const char *fingerprint, const char *host, String url, DEBUG.print(host + httpsPort); //debug return ("Connection error"); } - if (client.verify(fingerprint, host)) { + //if (client.verify(fingerprint, host)) { client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); // Handle wait for reply and timeout @@ -39,9 +40,9 @@ get_https(const char *fingerprint, const char *host, String url, return ("ok"); } } - } else { - return ("HTTPS fingerprint no match"); - } + //} else { + // return ("HTTPS fingerprint no match"); + //} return ("error " + String(host)); } @@ -51,7 +52,7 @@ get_https(const char *fingerprint, const char *host, String url, // ------------------------------------------------------------------- String get_http(const char *host, String url) { - http.begin(String("http://") + host + String(url)); + http.begin(client_insecure,String("http://") + host + String(url)); int httpCode = http.GET(); if ((httpCode > 0) && (httpCode == HTTP_CODE_OK)) { String payload = http.getString(); diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 0abbc14..d79090e 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -81,7 +81,7 @@ void mqttmsg_callback(char *topic, byte * payload, unsigned int length) { // Print RAPI command from mqtt-sub topic e.g $SC // ASSUME RAPI COMMANDS ARE ALWAYS PREFIX BY $ AND TWO CHARACTERS LONG) String cmd = String(topic + rapi_character_index); - if (payload[0] != 0); { // If MQTT msg contains a payload e.g $SC 13. Not all rapi commands have a payload e.g. $GC + if (payload[0] != 0) { // If MQTT msg contains a payload e.g $SC 13. Not all rapi commands have a payload e.g. $GC cmd += " "; // print RAPI value received via MQTT serial for (unsigned int i = 0; i < length; i++) { diff --git a/src/ohm.cpp b/src/ohm.cpp index ab9e78b..72e9fa5 100644 --- a/src/ohm.cpp +++ b/src/ohm.cpp @@ -41,8 +41,8 @@ void ohm_loop() DBUGLN(F("ERROR Ohm Connect - connection failed")); return; } - if (client.verify(ohm_fingerprint, ohm_host)) - { + //if (client.verify(ohm_fingerprint, ohm_host)) + //{ client.print(String("GET ") + ohm_url + ohm + " HTTP/1.1\r\n" + "Host: " + ohm_host + "\r\n" + "User-Agent: OpenEVSE\r\n" + "Connection: close\r\n\r\n"); @@ -93,9 +93,9 @@ void ohm_loop() } } } - } else { - DBUGLN(F("ERROR Ohm Connect - Certificate Invalid")); - } + //} else { + // DBUGLN(F("ERROR Ohm Connect - Certificate Invalid")); + //} } Profile_End(ohm_loop, 5); diff --git a/src/ota.cpp b/src/ota.cpp index 2e7a421..d8cc418 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -14,6 +14,7 @@ void ota_setup() { // Start local OTA update server ArduinoOTA.setHostname(esp_hostname.c_str()); + ArduinoOTA.setPassword("123"); ArduinoOTA.begin(); ArduinoOTA.onStart([]() { diff --git a/src/urlencode.cpp b/src/urlencode.cpp index 0da3470..82139fa 100644 --- a/src/urlencode.cpp +++ b/src/urlencode.cpp @@ -54,7 +54,7 @@ String urlencode(String str) char c; char code0; char code1; - char code2; + //char code2; for (unsigned int i =0; i < str.length(); i++){ c=str.charAt(i); if (c == ' '){ @@ -71,7 +71,7 @@ String urlencode(String str) if (c > 9){ code0=c - 10 + 'A'; } - code2='\0'; + //code2='\0'; encodedString+='%'; encodedString+=code0; encodedString+=code1; diff --git a/src/web_server.cpp b/src/web_server.cpp index 63b2e0b..8c15225 100644 --- a/src/web_server.cpp +++ b/src/web_server.cpp @@ -75,13 +75,13 @@ void dumpRequest(AsyncWebServerRequest *request) { int headers = request->headers(); int i; for(i=0; igetHeader(i); + const AsyncWebHeader* h = request->getHeader(i); DBUGF("_HEADER[%s]: %s", h->name().c_str(), h->value().c_str()); } int params = request->params(); for(i = 0; i < params; i++) { - AsyncWebParameter* p = request->getParam(i); + const AsyncWebParameter* p = request->getParam(i); if(p->isFile()){ DBUGF("_FILE[%s]: %s, size: %u", p->name().c_str(), p->value().c_str(), p->size()); } else if(p->isPost()){ @@ -292,7 +292,7 @@ handleSaveMqtt(AsyncWebServerRequest *request) { String pass = request->arg("pass"); int port = 1883; - AsyncWebParameter *portParm = request->getParam("port"); + const AsyncWebParameter *portParm = request->getParam("port"); if(nullptr != portParm) { port = portParm->value().toInt(); } @@ -926,15 +926,11 @@ void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient *client, AwsEventTy void web_server_setup() { -// SPIFFS.begin(); // mount the fs - - // Setup the static files -// server.serveStatic("/", SPIFFS, "/") -// .setDefaultFile("index.html"); - // Add the Web Socket server ws.onEvent(onWsEvent); server.addHandler(&ws); + + // static file handler server.addHandler(&staticFile); // Start server & server root html / diff --git a/src/web_server_static.cpp b/src/web_server_static.cpp index de5ee2c..d000cdb 100644 --- a/src/web_server_static.cpp +++ b/src/web_server_static.cpp @@ -28,8 +28,9 @@ StaticFileWebHandler::StaticFileWebHandler() { } -bool StaticFileWebHandler::_getFile(AsyncWebServerRequest *request, StaticFile **file) +bool StaticFileWebHandler::_getFile(AsyncWebServerRequest *request, StaticFile **file) const { + DBUGF("[StaticFileWebHandler::_getFile] entry"); // Remove the found uri String path = request->url(); if(path == "/") { @@ -53,11 +54,15 @@ bool StaticFileWebHandler::_getFile(AsyncWebServerRequest *request, StaticFile * return false; } -bool StaticFileWebHandler::canHandle(AsyncWebServerRequest *request) +bool StaticFileWebHandler::canHandle(AsyncWebServerRequest *request) const { StaticFile *file = NULL; - if (request->method() == HTTP_GET && - _getFile(request, &file)) + DBUGF("[StaticFileWebHandler::canHandle] entry"); + if (request->isHTTP() && + request->method() == HTTP_GET && + //request->url().startsWith(_uri) && + _getFile(request, &file) + ) { request->_tempObject = file; DBUGF("[StaticFileWebHandler::canHandle] TRUE"); @@ -73,8 +78,8 @@ void StaticFileWebHandler::handleRequest(AsyncWebServerRequest *request) // Are we authenticated if(wifi_mode_is_sta() && - _username != "" && _password != "" && - false == request->authenticate(_username.c_str(), _password.c_str())) + www_username != "" && www_password != "" && + false == request->authenticate(www_username.c_str(), www_password.c_str())) { request->requestAuthentication(esp_hostname.c_str()); return; @@ -82,6 +87,7 @@ void StaticFileWebHandler::handleRequest(AsyncWebServerRequest *request) // Get the filename from request->_tempObject and free it StaticFile *file = (StaticFile *)request->_tempObject; + DBUGF("[StaticFileWebHandler::handleRequest] checking if file set"); if (file) { request->_tempObject = NULL; @@ -89,6 +95,7 @@ void StaticFileWebHandler::handleRequest(AsyncWebServerRequest *request) request->send(response); } else { request->send(404); + DBUGF("[StaticFileWebHandler::handleRequest] returning 404"); } } @@ -119,6 +126,7 @@ size_t StaticFileResponse::write(AsyncWebServerRequest *request) // How should failures to send be handled? request->client()->send(); } + return 0; } size_t StaticFileResponse::writeData(AsyncWebServerRequest *request) diff --git a/src/web_server_static.h b/src/web_server_static.h index 3847f28..3ae2c94 100644 --- a/src/web_server_static.h +++ b/src/web_server_static.h @@ -16,11 +16,11 @@ struct StaticFile class StaticFileWebHandler: public AsyncWebHandler { private: - bool _getFile(AsyncWebServerRequest *request, StaticFile **file = NULL); + bool _getFile(AsyncWebServerRequest *request, StaticFile **file = NULL) const; protected: public: StaticFileWebHandler(); - virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual bool canHandle(AsyncWebServerRequest *request) const override final; virtual void handleRequest(AsyncWebServerRequest *request) override final; }; diff --git a/src/web_static/readme.md b/src/web_static/readme.md index f8fb01c..84e3056 100644 --- a/src/web_static/readme.md +++ b/src/web_static/readme.md @@ -2,21 +2,6 @@ Do not edit these files, these are all auto generated from the files in `gui`. -To update do the following: - 1. Make sure the content of `gui` is up-to-date - - ```shell - cd gui - git checkout master - git pull - ``` - 2. 'Build' the UI - - ```shell - npm install - npm run build - ``` - 3. Build/Upload the project as normal diff --git a/src/web_static/web_server.favicon-32x32.png.h b/src/web_static/web_server.favicon-32x32.png.h deleted file mode 100644 index fa87976..0000000 --- a/src/web_static/web_server.favicon-32x32.png.h +++ /dev/null @@ -1,88 +0,0 @@ -static const char CONTENT_FAVICON_32X32_PNG[] PROGMEM = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, - 0xf4, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, - 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, - 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, - 0x07, 0xe1, 0x08, 0x01, 0x16, 0x37, 0x3a, 0xd7, 0xa0, 0xe8, 0x67, 0x00, 0x00, 0x04, 0xee, 0x49, - 0x44, 0x41, 0x54, 0x58, 0xc3, 0xe5, 0x97, 0x5b, 0x6c, 0x14, 0x75, 0x14, 0xc6, 0x7f, 0x67, 0x76, - 0x67, 0xaf, 0x1d, 0x7b, 0xb3, 0x6c, 0x77, 0xb7, 0xa5, 0x2d, 0x16, 0xa1, 0x50, 0x04, 0x24, 0x55, - 0x0a, 0x21, 0x44, 0x0d, 0x4a, 0x7c, 0xf4, 0xc9, 0x07, 0xaf, 0x0f, 0x0a, 0x06, 0x9b, 0x68, 0x88, - 0x04, 0x95, 0xc8, 0x12, 0x13, 0x43, 0x8a, 0x46, 0x03, 0x0f, 0x24, 0xc6, 0xa0, 0x26, 0x4a, 0x14, - 0x34, 0x31, 0x18, 0x88, 0x21, 0xde, 0x9e, 0x14, 0x14, 0xe3, 0x25, 0x06, 0x8d, 0x26, 0xb4, 0xb0, - 0x08, 0xc5, 0x50, 0xba, 0xf6, 0xb2, 0xec, 0xce, 0xce, 0xcc, 0xf1, 0xa1, 0xe5, 0xd2, 0xee, 0x94, - 0x56, 0x24, 0xf2, 0xe0, 0x24, 0xdf, 0xcb, 0xec, 0xf9, 0xff, 0xe7, 0x3b, 0xe7, 0x7c, 0xe7, 0xb2, - 0xa2, 0xaa, 0x5c, 0xcf, 0xc7, 0xe0, 0x3a, 0x3f, 0xc1, 0xab, 0x39, 0x24, 0x0d, 0x0d, 0x9d, 0x24, - 0x12, 0x1b, 0x68, 0x6a, 0x29, 0x8d, 0xba, 0x60, 0xfc, 0xcc, 0x87, 0x7b, 0x5f, 0xd4, 0xab, 0x08, - 0xe7, 0x55, 0x11, 0xc0, 0xf3, 0x56, 0x92, 0x48, 0xac, 0xa4, 0x75, 0xd6, 0xf9, 0xb1, 0x37, 0xb3, - 0x81, 0x17, 0xff, 0xbb, 0x14, 0x48, 0xa0, 0x9d, 0xca, 0x4a, 0x1b, 0x31, 0x9c, 0x31, 0xd4, 0xb0, - 0x7e, 0x7d, 0xed, 0x35, 0x23, 0x20, 0x22, 0x22, 0x33, 0x67, 0x3e, 0x22, 0xcb, 0x96, 0x6d, 0x94, - 0x35, 0x6b, 0xcc, 0x89, 0xbf, 0x11, 0x36, 0xdb, 0xb1, 0x6e, 0x28, 0x02, 0xa5, 0x4b, 0x08, 0xce, - 0x2d, 0xbb, 0xa3, 0xa1, 0x61, 0xa9, 0x2c, 0x5e, 0xfc, 0xba, 0x3c, 0xf4, 0x50, 0x7c, 0x52, 0x5f, - 0x26, 0xa6, 0x4d, 0x44, 0x84, 0x74, 0xfa, 0x01, 0xd2, 0xe9, 0x57, 0xb8, 0x7d, 0x69, 0x8e, 0x48, - 0xf4, 0x27, 0x1c, 0x7b, 0x03, 0xaf, 0xbe, 0xda, 0x43, 0x43, 0x43, 0x0a, 0xcb, 0x7a, 0x84, 0x1b, - 0xeb, 0x9e, 0xa4, 0xa3, 0x63, 0x90, 0x50, 0xf8, 0xb2, 0xc3, 0x7a, 0x84, 0xdc, 0xc0, 0x4e, 0xea, - 0xeb, 0xbf, 0x66, 0xcf, 0x9e, 0x20, 0xf9, 0xfc, 0x46, 0x1a, 0x1b, 0x9f, 0xa0, 0xfd, 0x96, 0x11, - 0x2c, 0xeb, 0x2b, 0xa2, 0xe1, 0xb5, 0x9a, 0xc9, 0xe4, 0xa7, 0x26, 0x90, 0x4e, 0xdf, 0x4f, 0xba, - 0xe1, 0x35, 0x96, 0x75, 0x9e, 0x23, 0x1e, 0x77, 0x47, 0xef, 0xd6, 0x02, 0xe7, 0xce, 0xfd, 0xc8, - 0xc9, 0x93, 0x77, 0x92, 0x4a, 0x97, 0xa8, 0xa9, 0x2e, 0x11, 0x08, 0xa8, 0x8f, 0x36, 0xa0, 0x68, - 0x9f, 0x20, 0x7b, 0x42, 0x10, 0x99, 0x4b, 0x73, 0x4b, 0x1e, 0x33, 0xa8, 0x63, 0x77, 0x1c, 0x66, - 0x78, 0x78, 0x9d, 0x6e, 0xdf, 0x5e, 0xbc, 0xb2, 0x08, 0x03, 0x81, 0x5a, 0x52, 0xa9, 0x3c, 0x96, - 0x55, 0x40, 0xe4, 0xe2, 0x5b, 0xea, 0x66, 0xdc, 0x4a, 0xdd, 0x8c, 0x1c, 0x72, 0x85, 0x84, 0x06, - 0x02, 0x60, 0x9a, 0x49, 0xe6, 0xb6, 0x01, 0x4c, 0xb4, 0xad, 0x9a, 0x5e, 0x15, 0x64, 0xb3, 0x3b, - 0xa9, 0xaa, 0xba, 0x9b, 0xc6, 0x99, 0x8d, 0xd4, 0xd6, 0xda, 0xd7, 0xa6, 0xda, 0xd5, 0x05, 0x7d, - 0x61, 0xa2, 0xf7, 0xbe, 0x22, 0x54, 0x55, 0x8f, 0xc1, 0xc1, 0xa7, 0xf8, 0xe1, 0xfb, 0x10, 0x25, - 0xc7, 0x46, 0xa4, 0xf0, 0xaf, 0x61, 0xc8, 0x2e, 0xcd, 0x64, 0x8e, 0x4e, 0xbb, 0x0f, 0x68, 0x6f, - 0x6f, 0x8f, 0x34, 0x37, 0xff, 0xc2, 0x40, 0x7f, 0x3d, 0xc9, 0x54, 0xe1, 0x1a, 0xf4, 0xdb, 0x83, - 0xff, 0xa8, 0x11, 0x49, 0x2a, 0xd5, 0x44, 0x55, 0xf5, 0x6d, 0x54, 0x56, 0xfe, 0x8a, 0x21, 0x05, - 0x04, 0x1f, 0xc1, 0x51, 0xc0, 0x75, 0x4f, 0x61, 0x17, 0xaa, 0x40, 0x12, 0x44, 0xa2, 0x0e, 0x01, - 0xf1, 0xef, 0x84, 0xaa, 0x77, 0x02, 0x6f, 0x4f, 0x8b, 0x80, 0x88, 0x08, 0xa9, 0xd4, 0xa3, 0xcc, - 0x6a, 0x39, 0x4b, 0x3c, 0x66, 0x8f, 0xa6, 0x49, 0x4a, 0x88, 0x61, 0x5f, 0xfc, 0xb4, 0xa7, 0x1f, - 0xe0, 0x16, 0xf7, 0x93, 0xc9, 0x94, 0x00, 0x58, 0xbd, 0x7a, 0x01, 0xa1, 0xd0, 0xb3, 0xb4, 0x2f, - 0x30, 0xa9, 0xb0, 0x4a, 0xe5, 0x1e, 0xb1, 0x5c, 0x76, 0xec, 0x78, 0x4f, 0xbb, 0xba, 0x8a, 0xbe, - 0x65, 0x28, 0x89, 0xc4, 0x2c, 0x6a, 0x6b, 0x3b, 0xa8, 0xae, 0x6e, 0x25, 0x1e, 0xbf, 0x89, 0x68, - 0x7c, 0x36, 0xf3, 0xda, 0x72, 0x58, 0x96, 0x7d, 0xb9, 0x29, 0x22, 0x45, 0x0c, 0x76, 0xb3, 0x71, - 0xe3, 0x81, 0x89, 0x7d, 0x5f, 0x9a, 0x9b, 0x93, 0xa4, 0x52, 0xef, 0x70, 0xcf, 0x3d, 0x27, 0x89, - 0xc4, 0x9c, 0x32, 0x12, 0x6e, 0xa9, 0x9f, 0x6c, 0xf6, 0x34, 0x43, 0x43, 0x59, 0x86, 0x86, 0x7a, - 0xd9, 0xb7, 0xef, 0x3b, 0x55, 0xd5, 0xe0, 0x58, 0xf9, 0x3c, 0x49, 0xdb, 0xbc, 0xdb, 0x68, 0x5f, - 0xf0, 0x27, 0x21, 0xd3, 0xc3, 0x90, 0x3e, 0x9f, 0x38, 0x82, 0x60, 0x53, 0x5d, 0x73, 0xd0, 0x6f, - 0xe8, 0x68, 0x6f, 0xef, 0x69, 0x49, 0xa7, 0x0f, 0xf2, 0xdb, 0xef, 0x9d, 0x2c, 0x5a, 0x7c, 0xba, - 0x5c, 0x07, 0x61, 0x8b, 0x96, 0x56, 0x0b, 0xcf, 0xbd, 0x19, 0xa7, 0x14, 0xa0, 0xbe, 0x7e, 0x1d, - 0x50, 0xba, 0x54, 0x05, 0xb1, 0xa8, 0x12, 0x32, 0x0d, 0x20, 0x88, 0xa7, 0xa6, 0x2f, 0x1c, 0x2f, - 0xcb, 0xe3, 0x6b, 0x9c, 0x49, 0xc5, 0x76, 0xbe, 0xf4, 0x13, 0x7f, 0x9c, 0xac, 0xc5, 0x75, 0x41, - 0xbd, 0x72, 0xe0, 0x81, 0x21, 0x10, 0x0a, 0xb9, 0x2c, 0x59, 0x32, 0x4e, 0x03, 0x82, 0x6a, 0x10, - 0xf5, 0xcc, 0x29, 0xf4, 0x5c, 0x81, 0x8c, 0x06, 0x63, 0x12, 0x49, 0xc7, 0xf1, 0x3c, 0x41, 0x0c, - 0x81, 0xe9, 0x8d, 0xe6, 0x0b, 0x11, 0xe8, 0xc7, 0x76, 0x82, 0xd8, 0x4e, 0x04, 0x57, 0x43, 0x28, - 0x93, 0xa1, 0x8d, 0x4c, 0xa6, 0x76, 0xb2, 0x01, 0x86, 0x69, 0xae, 0x26, 0x99, 0x8e, 0x60, 0xdb, - 0x29, 0x1c, 0xaf, 0x06, 0xcf, 0x8b, 0x8d, 0x3a, 0x69, 0x70, 0x11, 0x2a, 0x82, 0x32, 0xcc, 0xa7, - 0x9f, 0x7a, 0xe3, 0x66, 0x81, 0xdc, 0x71, 0x47, 0x84, 0x44, 0x63, 0x2b, 0x55, 0xb1, 0x9b, 0x19, - 0x1a, 0x59, 0xcb, 0xcc, 0xa6, 0x28, 0x91, 0x88, 0xe7, 0xa3, 0x85, 0x43, 0x7c, 0xf9, 0xf9, 0xf3, - 0xfa, 0xc5, 0x17, 0xe3, 0x52, 0x21, 0xc9, 0xe4, 0xbd, 0xa4, 0x1b, 0x76, 0xb2, 0x6a, 0x55, 0x96, - 0x48, 0xcc, 0x2d, 0x2b, 0x5a, 0x43, 0xf6, 0xe2, 0x39, 0x87, 0x28, 0x14, 0x7a, 0xd8, 0xba, 0x35, - 0x77, 0x41, 0x47, 0xe2, 0xb7, 0xc4, 0x48, 0x53, 0xd3, 0x06, 0x3a, 0x97, 0x3f, 0x4c, 0xdb, 0xdc, - 0xbf, 0x7c, 0xe3, 0xe6, 0xb8, 0x3f, 0x53, 0xc8, 0x3f, 0xad, 0xdb, 0xb6, 0x8d, 0x8c, 0xf5, 0x8d, - 0xc7, 0x68, 0x6a, 0x7e, 0x8e, 0xce, 0xce, 0x7e, 0x2a, 0x2b, 0xfd, 0xda, 0xf7, 0x59, 0xd0, 0xfb, - 0x74, 0xf3, 0x66, 0x67, 0x7a, 0x0b, 0xc9, 0xc8, 0xc8, 0xbb, 0xf4, 0x1c, 0xab, 0xc4, 0xb6, 0xc3, - 0x78, 0xae, 0x59, 0x06, 0x91, 0x3a, 0x2a, 0x2a, 0xce, 0x5f, 0x16, 0xff, 0x10, 0xf5, 0x49, 0x07, - 0xab, 0x42, 0x7d, 0xed, 0x5d, 0xe7, 0x13, 0xbf, 0x8f, 0x4f, 0x4e, 0xa0, 0xbf, 0xff, 0x14, 0xe7, - 0xfa, 0x8f, 0x33, 0xf8, 0x57, 0x18, 0xcf, 0x0b, 0x96, 0xc3, 0xf9, 0x48, 0x37, 0x6f, 0xf6, 0x2e, - 0x23, 0xbc, 0x9b, 0xec, 0xf1, 0x30, 0x05, 0x3b, 0xe4, 0x6b, 0x0f, 0x87, 0xff, 0xd9, 0x4a, 0x96, - 0x4c, 0xde, 0x47, 0xcd, 0x8d, 0xb3, 0x89, 0xc6, 0x0c, 0x54, 0xcc, 0x09, 0x50, 0x5c, 0x77, 0xdf, - 0x38, 0x55, 0xe4, 0x72, 0x03, 0x0c, 0x0c, 0x1c, 0xe0, 0xcf, 0x33, 0x71, 0x1f, 0x7b, 0x13, 0x47, - 0xbb, 0x64, 0xcb, 0x16, 0x63, 0x5a, 0x04, 0x24, 0x91, 0x48, 0x60, 0x59, 0x2f, 0xb3, 0x78, 0xe1, - 0x30, 0x66, 0xd0, 0x40, 0xdd, 0xe0, 0x38, 0x78, 0xce, 0x67, 0x6c, 0xdd, 0x9a, 0x2b, 0xbb, 0x29, - 0x9f, 0xdf, 0x45, 0xcf, 0xb1, 0x1b, 0x70, 0x1d, 0xb3, 0xec, 0x8c, 0x78, 0x4b, 0x29, 0x16, 0x1f, - 0x14, 0x11, 0x99, 0x3a, 0x02, 0xc1, 0xe0, 0x26, 0xe6, 0xcc, 0x89, 0x52, 0x55, 0xad, 0xbe, 0xcd, - 0xc8, 0x75, 0xdf, 0xf7, 0x5d, 0xbf, 0xfb, 0xfa, 0xbe, 0xa5, 0xef, 0xcc, 0xef, 0x0c, 0x0e, 0x86, - 0x7d, 0xcf, 0x29, 0xcf, 0xd0, 0xd5, 0x65, 0x4d, 0x4d, 0x20, 0x12, 0xd9, 0x46, 0x6e, 0xb0, 0x8f, - 0x42, 0x21, 0x84, 0x6a, 0x10, 0x34, 0x88, 0xf2, 0x0d, 0xc3, 0x43, 0xfb, 0xe9, 0x3f, 0x7b, 0x8c, - 0xee, 0xee, 0xef, 0xfc, 0x07, 0x9e, 0x2a, 0x23, 0xc3, 0x6f, 0x72, 0xfc, 0x78, 0x1f, 0x76, 0xf1, - 0x2d, 0xce, 0x9c, 0x31, 0x70, 0x9c, 0xd1, 0xf3, 0x68, 0x00, 0xf5, 0xba, 0xd9, 0xb1, 0x63, 0x68, - 0xca, 0x9d, 0x10, 0x40, 0xda, 0xda, 0x9a, 0x49, 0xd4, 0x7f, 0xcc, 0xc2, 0x45, 0x16, 0x91, 0xd0, - 0x4b, 0xc4, 0x62, 0x6f, 0x90, 0xc9, 0x28, 0x4b, 0x96, 0x44, 0xf5, 0xc8, 0x91, 0xfc, 0xa4, 0x1b, - 0xee, 0xfc, 0xf9, 0x21, 0x8e, 0x1e, 0x55, 0x55, 0x2d, 0x49, 0x47, 0x47, 0x3b, 0x75, 0x89, 0x9d, - 0xdc, 0xd4, 0xd2, 0x4a, 0x2c, 0xb6, 0x89, 0xee, 0xee, 0x5d, 0xbe, 0x91, 0x53, 0x55, 0x5f, 0x30, - 0x67, 0x4e, 0x0b, 0x2b, 0x56, 0xcc, 0xbb, 0x40, 0xf2, 0x6a, 0x40, 0x6b, 0x6b, 0x98, 0x15, 0x2b, - 0xee, 0xba, 0xd2, 0x1d, 0xf2, 0xbf, 0xff, 0x73, 0x7a, 0xdd, 0x09, 0xfc, 0x0d, 0x51, 0xed, 0xba, - 0xcd, 0x65, 0x83, 0x02, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82, 0x00 }; diff --git a/src/web_static/web_server.home.html.h b/src/web_static/web_server.home.html.h deleted file mode 100644 index c0b592f..0000000 --- a/src/web_static/web_server.home.html.h +++ /dev/null @@ -1,48 +0,0 @@ -static const char CONTENT_HOME_HTML[] PROGMEM = - " OpenEVSE

OpenEVSE

WiFi

Loading, please wait... (/)

WiFi Setup

Mode:

IP Address:

Successful packets:
of

OpenEVSE

RAPI packets:
of

Network RSSI dBm

IP Address:

Successful packets:
of

OpenEVSE

RAPI packets:
of

Connect to network:

Scanning...

SSID:

Passkey:

Connecting to WIFI Network...

Administration

Username:
15 characters max

Password:


15 characters max
Web interface HTTP authentication.

WiFi Firmware

Version:

Error:

Updating...
Firmware update completed ok

Advanced Settings

Hostname:
31 characters max

NTP Server:

Developer Mode

Enabled:

  Energy Monitoring

Emoncms Server*:
0 }\">

Emoncms Node*:

Emoncms write-apikey*:

Emoncms SSL SHA-1 Fingerprint (optional):


HTTPS will be enabled if present e.g: 7D:82:15:BE:D7:BC:72:58:87:7D:8E:40:D4:80:BA:1A:9F:8B:8D:DA

  Connected:    Successful posts: 

MQTT

Status published to:
{base-topic}/{status} value
e.g. /amp 16

RAPI control subscribes to:
{base-topic}/rapi/in/{command} value
e.g. /rapi/in/$SC 16
e.g. /rapi/in/$GC

RAPI response published to:
{base-topic}/rapi/out response
e.g. /rapi/out $OK 6 32

Host*:
0 }\">
e.g 'emonpi', 'test.mosquitto.org', '192.168.1.4'

Port*:

Reject self-signed certificates:

Warning!!

Certificate validation is disabled, although the connection to MQTT server will be encrypted the connection is still vulnerable to man-in-the-middle attacks.

Username: blank - no authentication

Password: blank - no authentication

Base-topic*:

e.g 'openevse'

Voltage topic:
Voltage MQTT topic to improve power calculations

  Connected: 

  OhmConnect

Click Here to Join

OhmConnect monitors real-time conditions on the electricity grid. When dirty and unsustainable power plants turn on, our users receive a notification to save energy.

Ohm Hour:

Ohm key:

USA - California only

Ohm Key can be obtained by logging in to OhmConnect, enter Settings and locate the link in \"Open Source Projects\"
Example: https://login.ohmconnect.com/verify-ohm-hour/OpnEoVse
Key: OpnEoVse

Solar PV divert

MQTT not enabled.

Solar PV Divert requires an SolarPV-gen or Grid (+I/-E) feed to be delivered via MQTT.
Dynamically adjust charge rate based on solar PV generation or excess power (grid export).

  • If only solar PV feed available: charge rate is modulated based on solar PV generation.
  • If grid +I/-E (positive Import / negative Export) feed is available: charge rate will be modulated by available excess power.
  • If EVSE is sleeping: charging will begin when solar PV / excess power > min charge rate.
  • Charging will pause if the excess power drops below the nim charge rate for a period of time.
Note: It's assumed that EVSE power is included in the grid feed


Solar: Grid Import/Export: W - | Charge rate: A

Feed*:

Solar PV MQTT topic to modulate charge rate based on solar Grid (+I/-E) MQTT topic to modulate charge rate based on excess power

Divert smoothing attack:

The amount of the new feed value to add to the divert available power rolling average

Divert smoothing decay:

The amount of the new feed value to remove to the divert available power rolling average

Minimum charge time:

The minimum amount of time (seconds) to charge the car once enabled via the Solar PV divert. This can help minimise wear and tear on the EVSE.

EVSE Error

EVSE Error

OpenEVSE not responding or not connected

Session Status

Current Energy Temp Elapsed

Solar: Grid Import/Export: W - | Vehicle not connected Waiting for solar Charging from solar | Charge rate: A
Voltage: V | Available Current: A | Smoothed Current: A

Charge Options

Normal (fast) Eco (PV divert)


Time limit:

Energy limit:



Timer:
Start:    Stop:

Energy

Energy
This Session:
Total:

Sensor Values

Sensor Value
Pilot:
Current Now:
Voltage:
Temp1:
Temp2:
Temp3:

Setup

Time: No RTC detected

Time:

Time zone:

Set time from

Service Level:

Max Current:

Current

Name
Service Level:
Level Minimum:
Level Maximum:
Sensor Scale:
Sensor Offset:

Safety

Hardware safety checks. Enable dev mode (System > Developer Mode) to enable/disable or use the physical LCD + menu button.

Warning!!

Not all the safety tests are enabled, please take extra care before charging your vehicle.
Test Status
GFI Self Test:
Ground Monitoring:
Stuck Contact Detection:
Temperature Monitoring:
Diode Check:
Vent Required:
Error Count
GFCI:
No Ground:
Stuck Contact:

Hardware

OpenEVSE
Firmware:
Protocol:
OpenEVSE WiFi
Firmware:
Flash Size:
Free RAM:

Display

Simple Advanced

RAPI Command:

RAPI System Functions

Function Description
$FB LCD Backlight Color (0-7)
$FD Disable EVSE
$FE Enable EVSE
$FP Output text at x y position text to LCD (x y text)
$FR Reset EVSE
$FS Put EVSE to sleep

RAPI Get Commands

Get Description
$G3 Get Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$GA Get Ammeter Scale/Offset, scale offset
$GC Get current capacity range, integers
$GD Get delay timer, starthr startmin endhr endmin
$GE Get settings, amps flags
$GF Get fault counters, gfi ground stuck (in hex)
$GG Get charge current and voltage, milliamps millivolts
$GH Get charge limit in kWh, integer
$GM Get Voltmeter Scale/Offset, scale offset
$GO Get Overtemperature thresholds, ambient infrared
$GP Get Temperatures, LCD mcp9808 infrared (all integers, Celsius * 10)
$GS Get EVSE State, state elapsed_seconds
$GT Get time, year month day hour minute second
$GU Get Energy usage, wattseconds watt_hour_accumulated
$GV Get Versions, evse_firmware protocol_version

RAPI Set Commands

Set Description
$S0 Set LCD Type, Monochrome (0), Color (1)
$S1 Set RTC Year Month Day Hour Minute Second (all 2-digit max)
$S2 Enable (1)/ Disable (0) Ammeter Calibration Mode
$S3 Set Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$SA Set Ammeter Scale/Offset, scale offset
$SC Set current capacity, integer
$SDEnable (1) / Disable (0) Diode self-check
$SF Enable (1) / Disable (0) GFI self-check
$SG Enable (1) / Disable (0) Ground check
$SH Set charge limit in kWh, integer
$SK Set accumulated Wh, integer
$SLSet service level (1/2/A)
$SM Set Voltmeter Scale/Offset, scale offset
$SO Set Overtemperature thresholds, ambient infrared
$SR Enable (1) / Disable (0) Stuck-relay check
$SS Enable (1) / Disable (0) GFI self-check
$ST Set timer, start_hour start_min end_hour end_min
$SV Enable (1) / Disable (0) vent required check

Powered by OpenEVSE and OpenEnergyMonitor
Version: V
\n"; diff --git a/src/web_static/web_server.home.js.h b/src/web_static/web_server.home.js.h deleted file mode 100644 index 6d5e6f4..0000000 --- a/src/web_static/web_server.home.js.h +++ /dev/null @@ -1,3 +0,0 @@ -static const char CONTENT_HOME_JS[] PROGMEM = - "\"use strict\";function OpenEVSEError(e){var t=1\"+e.ret),t.cmd(e.cmd)},\"json\").always(function(){t.rapiSend(!1)})}}function TimeViewModel(n){var o=this;function r(e){return(e<10?\"0\":\"\")+e}o.evseTimedate=ko.observable(new Date),o.localTimedate=ko.observable(new Date),o.nowTimedate=ko.observable(null),o.hasRTC=ko.observable(!0),o.elapsedNow=ko.observable(new Date(0)),o.elapsedLocal=ko.observable(new Date),o.divertUpdateNow=ko.observable(new Date(0)),o.divertUpdateLocal=ko.observable(new Date),o.date=ko.pureComputed({read:function(){if(null===o.nowTimedate())return\"\";var e=o.nowTimedate();return e.getFullYear()+\"-\"+r(e.getMonth()+1)+\"-\"+r(e.getDate())},write:function(e){var t=o.evseTimedate();e+=\" \"+r(t.getHours())+\":\"+r(t.getMinutes())+\":\"+r(t.getSeconds()),o.evseTimedate(new Date(e)),o.localTimedate(new Date)}}),o.time=ko.pureComputed({read:function(){if(null===o.nowTimedate())return\"--:--:--\";var e=o.nowTimedate();return r(e.getHours())+\":\"+r(e.getMinutes())+\":\"+r(e.getSeconds())},write:function(e){var t=e.split(\":\"),n=o.evseTimedate();n.setHours(parseInt(t[0])),n.setMinutes(parseInt(t[1])),o.evseTimedate(n),o.localTimedate(new Date)}}),o.elapsed=ko.pureComputed(function(){if(null===o.nowTimedate())return\"0:00:00\";var e=o.elapsedNow().getTime(),t=(e=Math.floor(e/1e3))%60,n=(e=Math.floor(e/60))%60;return Math.floor(e/60)+\":\"+r(n)+\":\"+r(t)}),n.status.elapsed.subscribe(function(e){o.elapsedNow(new Date(1e3*e)),o.elapsedLocal(new Date)}),o.divert_update=ko.pureComputed(function(){if(null===o.nowTimedate())return!1;var e=o.divertUpdateNow().getTime();return Math.floor(e/1e3)}),n.status.divert_update.subscribe(function(e){o.divertUpdateNow(new Date(1e3*e)),o.divertUpdateLocal(new Date)});var a=null;o.automaticTime=ko.observable(!0),o.timeUpdate=function(e){var t=!(1=e){r.timeLimit(n.value);break}}},r.selectChargeLimit=function(e){if(r.chargeLimit()!==e)for(var t=0;t=e){r.chargeLimit(n.value);break}}};var o=[function(){return!1===r.status.time()?r.openevse.time(r.time.timeUpdate):new DummyRequest},function(){return r.openevse.service_level(function(e,t){r.serviceLevel(e),r.actualServiceLevel(t)})},function(){return r.updateCurrentCapacity()},function(){return r.openevse.current_capacity(function(e){r.currentCapacity(e)})},function(){return r.openevse.time_limit(function(e){r.selectTimeLimit(e)})},function(){return r.openevse.charge_limit(function(e){r.selectChargeLimit(e)})},function(){return r.openevse.gfi_self_test(function(e){r.gfiSelfTestEnabled(e)})},function(){return r.openevse.ground_check(function(e){r.groundCheckEnabled(e)})},function(){return r.openevse.stuck_relay_check(function(e){r.stuckRelayEnabled(e)})},function(){return r.openevse.temp_check(function(e){r.tempCheckEnabled(e)})},function(){return r.openevse.diode_check(function(e){r.diodeCheckEnabled(e)})},function(){return r.openevse.vent_required(function(e){r.ventRequiredEnabled(e)})},function(){return r.openevse.temp_check(function(){r.tempCheckSupported(!0)},r.tempCheckEnabled()).error(function(){r.tempCheckSupported(!1)})},function(){return r.openevse.timer(function(e,t,n){r.delayTimerEnabled(e),r.delayTimerStart(t),r.delayTimerStop(n)})}];r.updateCount=ko.observable(0),r.updateTotal=ko.observable(o.length),r.updateCurrentCapacity=function(){return r.openevse.current_capacity_range(function(e,t){r.minCurrentLevel(e),r.maxCurrentLevel(t);var n=r.currentCapacity();r.currentLevels.removeAll();for(var o=r.minCurrentLevel();o<=r.maxCurrentLevel();o++)r.currentLevels.push({name:o+\" A\",value:o});r.currentCapacity(n)})},r.updatingServiceLevel=ko.observable(!1),r.savedServiceLevel=ko.observable(!1),r.updatingCurrentCapacity=ko.observable(!1),r.savedCurrentCapacity=ko.observable(!1),r.updatingTimeLimit=ko.observable(!1),r.savedTimeLimit=ko.observable(!1),r.updatingChargeLimit=ko.observable(!1),r.savedChargeLimit=ko.observable(!1),r.updatingDelayTimer=ko.observable(!1),r.savedDelayTimer=ko.observable(!1),r.updatingStatus=ko.observable(!1),r.savedStatus=ko.observable(!1),r.updatingGfiSelfTestEnabled=ko.observable(!1),r.savedGfiSelfTestEnabled=ko.observable(!1),r.updatingGroundCheckEnabled=ko.observable(!1),r.savedGroundCheckEnabled=ko.observable(!1),r.updatingStuckRelayEnabled=ko.observable(!1),r.savedStuckRelayEnabled=ko.observable(!1),r.updatingTempCheckEnabled=ko.observable(!1),r.savedTempCheckEnabled=ko.observable(!1),r.updatingDiodeCheckEnabled=ko.observable(!1),r.savedDiodeCheckEnabled=ko.observable(!1),r.updatingVentRequiredEnabled=ko.observable(!1),r.savedVentRequiredEnabled=ko.observable(!1);var a=!(r.setForTime=function(e,t){e(!0),setTimeout(function(){e(!1)},t)});function i(e){return/([01]\\d|2[0-3]):([0-5]\\d)/.test(e)}r.subscribe=function(){a||(r.serviceLevel.subscribe(function(e){r.updatingServiceLevel(!0),r.openevse.service_level(function(e,t){r.setForTime(r.savedServiceLevel,2e3),r.actualServiceLevel(t),r.updateCurrentCapacity().always(function(){})},e).always(function(){r.updatingServiceLevel(!1)})}),r.currentCapacity.subscribe(function(t){!0!==r.updatingServiceLevel()&&(r.updatingCurrentCapacity(!0),r.openevse.current_capacity(function(e){r.setForTime(r.savedCurrentCapacity,2e3),t!==e&&r.currentCapacity(e)},t).always(function(){r.updatingCurrentCapacity(!1)}))}),r.timeLimit.subscribe(function(t){r.updatingTimeLimit(!0),r.openevse.time_limit(function(e){r.setForTime(r.savedTimeLimit,2e3),t!==e&&r.selectTimeLimit(e)},t).always(function(){r.updatingTimeLimit(!1)})}),r.chargeLimit.subscribe(function(t){r.updatingChargeLimit(!0),r.openevse.charge_limit(function(e){r.setForTime(r.savedChargeLimit,2e3),t!==e&&r.selectChargeLimit(e)},t).always(function(){r.updatingChargeLimit(!1)})}),r.gfiSelfTestEnabled.subscribe(function(t){r.updatingGfiSelfTestEnabled(!0),r.openevse.gfi_self_test(function(e){r.setForTime(r.savedGfiSelfTestEnabled,2e3),t!==e&&r.gfiSelfTestEnabled(e)},t).always(function(){r.updatingGfiSelfTestEnabled(!1)})}),r.groundCheckEnabled.subscribe(function(t){r.updatingGroundCheckEnabled(!0),r.openevse.ground_check(function(e){r.setForTime(r.savedGroundCheckEnabled,2e3),t!==e&&r.groundCheckEnabled(e)},t).always(function(){r.updatingGroundCheckEnabled(!1)})}),r.stuckRelayEnabled.subscribe(function(t){r.updatingStuckRelayEnabled(!0),r.savedStuckRelayEnabled(!1),r.openevse.stuck_relay_check(function(e){r.savedStuckRelayEnabled(!0),setTimeout(function(){r.savedStuckRelayEnabled(!1)},2e3),t!==e&&r.stuckRelayEnabled(e)},t).always(function(){r.updatingStuckRelayEnabled(!1)})}),r.tempCheckEnabled.subscribe(function(t){r.updatingTempCheckEnabled(!0),r.openevse.temp_check(function(e){r.setForTime(r.savedTempCheckEnabled,2e3),t!==e&&r.tempCheckEnabled(e)},t).always(function(){r.updatingTempCheckEnabled(!1)})}),r.diodeCheckEnabled.subscribe(function(t){r.updatingDiodeCheckEnabled(!0),r.openevse.diode_check(function(e){r.setForTime(r.savedDiodeCheckEnabled,2e3),t!==e&&r.diodeCheckEnabled(e)},t).always(function(){r.updatingDiodeCheckEnabled(!1)})}),r.ventRequiredEnabled.subscribe(function(t){r.updatingVentRequiredEnabled(!0),r.openevse.vent_required(function(e){r.setForTime(r.savedVentRequiredEnabled,2e3),t!==e&&r.ventRequiredEnabled(e)},t).always(function(){r.updatingVentRequiredEnabled(!1)})}),a=!0)},r.update=function(){var e=0>10|55296,1023&n|56320))}function i(){C()}var e,p,w,o,a,h,d,v,x,u,c,C,T,s,k,g,l,m,b,E=\"sizzle\"+1*new Date,y=n.document,S=0,r=0,N=ue(),_=ue(),A=ue(),D=ue(),O=function(e,t){return e===t&&(c=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,M=t.push,L=t.push,P=t.slice,R=function(e,t){for(var n=0,r=e.length;n+~]|\"+I+\")\"+I+\"*\"),z=new RegExp(I+\"|>\"),G=new RegExp($),X=new RegExp(\"^\"+H+\"$\"),Y={ID:new RegExp(\"^#(\"+H+\")\"),CLASS:new RegExp(\"^\\\\.(\"+H+\")\"),TAG:new RegExp(\"^(\"+H+\"|[*])\"),ATTR:new RegExp(\"^\"+F),PSEUDO:new RegExp(\"^\"+$),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+I+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+I+\"*(?:([+-]|)\"+I+\"*(\\\\d+)|))\"+I+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+B+\")$\",\"i\"),needsContext:new RegExp(\"^\"+I+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+I+\"*((?:-\\\\d)?\\\\d*)\"+I+\"*\\\\)|)(?=[^-]|$)\",\"i\")},K=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,Z=/^h\\d$/i,ee=/^[^{]+\\{\\s*\\[native \\w/,te=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ne=/[+~]/,re=new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\"+I+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),ie=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,oe=function(e,t){return t?\"\\0\"===e?\"�\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},ae=we(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{L.apply(t=P.call(y.childNodes),y.childNodes),t[y.childNodes.length].nodeType}catch(e){L={apply:t.length?function(e,t){M.apply(e,P.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,c,l,f=e&&e.ownerDocument,d=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==d&&9!==d&&11!==d)return n;if(!r&&(C(e),e=e||T,k)){if(11!==d&&(u=te.exec(t)))if(i=u[1]){if(9===d){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&b(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return L.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&p.getElementsByClassName&&e.getElementsByClassName)return L.apply(n,e.getElementsByClassName(i)),n}if(p.qsa&&!D[t+\" \"]&&(!g||!g.test(t))&&(1!==d||\"object\"!==e.nodeName.toLowerCase())){if(l=t,f=e,1===d&&(z.test(t)||J.test(t))){for((f=ne.test(t)&&me(e.parentNode)||e)===e&&p.scope||((s=e.getAttribute(\"id\"))?s=s.replace(ie,oe):e.setAttribute(\"id\",s=E)),o=(c=h(t)).length;o--;)c[o]=(s?\"#\"+s:\":scope\")+\" \"+ye(c[o]);l=c.join(\",\")}try{return L.apply(n,f.querySelectorAll(l)),n}catch(e){D(t,!0)}finally{s===E&&e.removeAttribute(\"id\")}}}return v(t.replace(V,\"$1\"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+\" \")>w.cacheLength&&delete e[r.shift()],e[t+\" \"]=n}}function ce(e){return e[E]=!0,e}function le(e){var t=T.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)w.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function pe(t){return function(e){return\"input\"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return(\"input\"===t||\"button\"===t)&&e.type===n}}function ve(t){return function(e){return\"form\"in e?e.parentNode&&!1===e.disabled?\"label\"in e?\"label\"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:\"label\"in e&&e.disabled===t}}function ge(a){return ce(function(o){return o=+o,ce(function(e,t){for(var n,r=a([],e.length,o),i=r.length;i--;)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function me(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in p=se.support={},a=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!K.test(t||n&&n.nodeName||\"HTML\")},C=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:y;return r!=T&&9===r.nodeType&&r.documentElement&&(s=(T=r).documentElement,k=!a(T),y!=T&&(n=T.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",i,!1):n.attachEvent&&n.attachEvent(\"onunload\",i)),p.scope=le(function(e){return s.appendChild(e).appendChild(T.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),p.attributes=le(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),p.getElementsByTagName=le(function(e){return e.appendChild(T.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),p.getElementsByClassName=ee.test(T.getElementsByClassName),p.getById=le(function(e){return s.appendChild(e).id=E,!T.getElementsByName||!T.getElementsByName(E).length}),p.getById?(w.filter.ID=function(e){var t=e.replace(re,f);return function(e){return e.getAttribute(\"id\")===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&k){var n=t.getElementById(e);return n?[n]:[]}}):(w.filter.ID=function(e){var n=e.replace(re,f);return function(e){var t=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return t&&t.value===n}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&k){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode(\"id\"))&&n.value===e)return[o];for(i=t.getElementsByName(e),r=0;o=i[r++];)if((n=o.getAttributeNode(\"id\"))&&n.value===e)return[o]}return[]}}),w.find.TAG=p.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"!==e)return o;for(;n=o[i++];)1===n.nodeType&&r.push(n);return r},w.find.CLASS=p.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&k)return t.getElementsByClassName(e)},l=[],g=[],(p.qsa=ee.test(T.querySelectorAll))&&(le(function(e){var t;s.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&g.push(\"[*^$]=\"+I+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||g.push(\"\\\\[\"+I+\"*(?:value|\"+B+\")\"),e.querySelectorAll(\"[id~=\"+E+\"-]\").length||g.push(\"~=\"),(t=T.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||g.push(\"\\\\[\"+I+\"*name\"+I+\"*=\"+I+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||g.push(\":checked\"),e.querySelectorAll(\"a#\"+E+\"+*\").length||g.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),g.push(\"[\\\\r\\\\n\\\\f]\")}),le(function(e){e.innerHTML=\"\";var t=T.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&g.push(\"name\"+I+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&g.push(\":enabled\",\":disabled\"),s.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&g.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),g.push(\",.*:\")})),(p.matchesSelector=ee.test(m=s.matches||s.webkitMatchesSelector||s.mozMatchesSelector||s.oMatchesSelector||s.msMatchesSelector))&&le(function(e){p.disconnectedMatch=m.call(e,\"*\"),m.call(e,\"[s!='']:x\"),l.push(\"!=\",$)}),g=g.length&&new RegExp(g.join(\"|\")),l=l.length&&new RegExp(l.join(\"|\")),t=ee.test(s.compareDocumentPosition),b=t||ee.test(s.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},O=t?function(e,t){if(e===t)return c=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e==T||e.ownerDocument==y&&b(y,e)?-1:t==T||t.ownerDocument==y&&b(y,t)?1:u?R(u,e)-R(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==T?-1:t==T?1:i?-1:o?1:u?R(u,e)-R(u,t):0;if(i===o)return de(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?de(a[r],s[r]):a[r]==y?-1:s[r]==y?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(C(e),p.matchesSelector&&k&&!D[t+\" \"]&&(!l||!l.test(t))&&(!g||!g.test(t)))try{var n=m.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){D(t,!0)}return 0\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(re,f),e[3]=(e[3]||e[4]||e[5]||\"\").replace(re,f),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Y.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&G.test(n)&&(t=h(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(re,f).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+\" \"];return t||(t=new RegExp(\"(^|\"+I+\")\"+e+\"(\"+I+\"|$)\"))&&N(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?\"!=\"===r:!r||(t+=\"\",\"=\"===r?t===i:\"!=\"===r?t!==i:\"^=\"===r?i&&0===t.indexOf(i):\"*=\"===r?i&&-1\",\"#\"===e.firstChild.getAttribute(\"href\")})||fe(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),p.attributes&&le(function(e){return e.innerHTML=\"\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||fe(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),le(function(e){return null==e.getAttribute(\"disabled\")})||fe(B,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(T);E.find=p,E.expr=p.selectors,E.expr[\":\"]=E.expr.pseudos,E.uniqueSort=E.unique=p.uniqueSort,E.text=p.getText,E.isXMLDoc=p.isXML,E.contains=p.contains,E.escapeSelector=p.escape;function h(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&E(e).is(n))break;r.push(e)}return r}function C(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var S=E.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var _=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function A(e,n,r){return y(n)?E.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?E.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?E.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(E.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):y(e)?void 0!==n.ready?n.ready(e):e(E):E.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:O.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof E?t[0]:t,E.merge(this,E.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:k,!0)),_.test(r[1])&&E.isPlainObject(t))for(r in t)y(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=k.getElementById(r[2]))&&(this[0]=i,this.length=1),this}).prototype=E.fn,D=E(k);var j=/^(?:parents|prev(?:Until|All))/,q={children:!0,contents:!0,next:!0,prev:!0};function M(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}E.fn.extend({has:function(e){var t=E(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,he=/^$|^module$|\\/(?:java|ecma)script/i;le=k.createDocumentFragment().appendChild(k.createElement(\"div\")),(fe=k.createElement(\"input\")).setAttribute(\"type\",\"radio\"),fe.setAttribute(\"checked\",\"checked\"),fe.setAttribute(\"name\",\"t\"),le.appendChild(fe),b.checkClone=le.cloneNode(!0).cloneNode(!0).lastChild.checked,le.innerHTML=\"\",b.noCloneChecked=!!le.cloneNode(!0).lastChild.defaultValue,le.innerHTML=\"\",b.option=!!le.lastChild;var ve={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function ge(e,t){var n;return n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[],void 0===t||t&&N(e,t)?E.merge([e],n):n}function me(e,t){for(var n=0,r=e.length;n\",\"\"]);var be=/<|&#?\\w+;/;function ye(e,t,n,r,i){for(var o,a,s,u,c,l,f=t.createDocumentFragment(),d=[],p=0,h=e.length;p\\s*$/g;function Oe(e,t){return N(e,\"table\")&&N(11!==t.nodeType?t:t.firstChild,\"tr\")&&E(e).children(\"tbody\")[0]||e}function je(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function qe(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Me(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(X.hasData(e)&&(s=X.get(e).events))for(i in X.remove(t,\"handle events\"),s)for(n=0,r=s[i].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",i=function(e){r.remove(),i=null,e&&t(\"error\"===e.type?404:200,e.type)}),k.head.appendChild(r[0])},abort:function(){i&&i()}}});var tn,nn=[],rn=/(=)\\?(?=&|$)|\\?\\?/;E.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=nn.pop()||E.expando+\"_\"+qt.guid++;return this[e]=!0,e}}),E.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(rn.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&rn.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=y(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(rn,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Mt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return o||E.error(r+\" was not called\"),o[0]},e.dataTypes[0]=\"json\",i=T[r],T[r]=function(){o=arguments},n.always(function(){void 0===i?E(T).removeProp(r):T[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,nn.push(r)),o&&y(i)&&i(o[0]),o=i=void 0}),\"script\"}),b.createHTMLDocument=((tn=k.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===tn.childNodes.length),E.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(b.createHTMLDocument?((r=(t=k.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=k.location.href,t.head.appendChild(r)):t=k),o=!n&&[],(i=_.exec(e))?[t.createElement(i[1])]:(i=ye([e],t,o),o&&o.length&&E(o).remove(),E.merge([],i.childNodes)));var r,i,o},E.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(\" \");return-1\").append(E.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},E.expr.pseudos.animated=function(t){return E.grep(E.timers,function(e){return t===e.elem}).length},E.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,c=E.css(e,\"position\"),l=E(e),f={};\"static\"===c&&(e.style.position=\"relative\"),s=l.offset(),o=E.css(e,\"top\"),u=E.css(e,\"left\"),i=(\"absolute\"===c||\"fixed\"===c)&&-1<(o+u).indexOf(\"auto\")?(a=(r=l.position()).top,r.left):(a=parseFloat(o)||0,parseFloat(u)||0),y(t)&&(t=t.call(e,n,E.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),\"using\"in t?t.using.call(e,f):(\"number\"==typeof f.top&&(f.top+=\"px\"),\"number\"==typeof f.left&&(f.left+=\"px\"),l.css(f))}},E.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){E.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if(\"fixed\"===E.css(r,\"position\"))t=r.getBoundingClientRect();else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&\"static\"===E.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=E(e).offset()).top+=E.css(e,\"borderTopWidth\",!0),i.left+=E.css(e,\"borderLeftWidth\",!0))}return{top:t.top-i.top-E.css(r,\"marginTop\",!0),left:t.left-i.left-E.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===E.css(e,\"position\");)e=e.offsetParent;return e||re})}}),E.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,i){var o=\"pageYOffset\"===i;E.fn[t]=function(e){return $(this,function(e,t,n){var r;if(v(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),E.each([\"top\",\"left\"],function(e,n){E.cssHooks[n]=Qe(b.pixelPosition,function(e,t){if(t)return t=Ke(e,n),Je.test(t)?E(e).position()[n]+\"px\":t})}),E.each({Height:\"height\",Width:\"width\"},function(a,s){E.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,o){E.fn[o]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),i=r||(!0===e||!0===t?\"margin\":\"border\");return $(this,function(e,t,n){var r;return v(e)?0===o.indexOf(\"outer\")?e[\"inner\"+a]:e.document.documentElement[\"client\"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body[\"scroll\"+a],r[\"scroll\"+a],e.body[\"offset\"+a],r[\"offset\"+a],r[\"client\"+a])):void 0===n?E.css(e,t,i):E.style(e,t,n,i)},s,n?e:void 0,n)}})}),E.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){E.fn[t]=function(e){return this.on(t,e)}}),E.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),E.each(\"blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu\".split(\" \"),function(e,n){E.fn[n]=function(e,t){return 0e.length)&&e.substring(0,t.length)===t},ud:function(e,t){if(e===t)return!0;if(11===e.nodeType)return!1;if(t.contains)return t.contains(1!==e.nodeType?e.parentNode:e);if(t.compareDocumentPosition)return 16==(16&t.compareDocumentPosition(e));for(;e&&e!=t;)e=e.parentNode;return!!e},Rb:function(e){return _.a.ud(e,e.ownerDocument.documentElement)},jd:function(e){return!!_.a.Lb(e,_.a.Rb)},P:function(e){return e&&e.tagName&&e.tagName.toLowerCase()},zc:function(e){return _.onError?function(){try{return e.apply(this,arguments)}catch(e){throw _.onError&&_.onError(e),e}}:e},setTimeout:(c=function(e,t){return setTimeout(_.a.zc(e),t)},h.toString=function(){return c.toString()},h),Fc:function(e){setTimeout(function(){throw _.onError&&_.onError(e),e},0)},H:function(t,e,n){var r=_.a.zc(n);if(n=l[e],_.options.useOnlyNativeEvents||n||!Te)if(n||\"function\"!=typeof t.addEventListener){if(void 0===t.attachEvent)throw Error(\"Browser doesn't support addEventListener or attachEvent\");var i=function(e){r.call(t,e)},o=\"on\"+e;t.attachEvent(o,i),_.a.I.za(t,function(){t.detachEvent(o,i)})}else t.addEventListener(e,r,!1);else u=u||(\"function\"==typeof Te(t).on?\"on\":\"bind\"),Te(t)[u](e,r)},Fb:function(e,t){if(!e||!e.nodeType)throw Error(\"element must be a DOM node when calling triggerEvent\");var n;if(n=!(\"input\"!==_.a.P(e)||!e.type||\"click\"!=t.toLowerCase()||\"checkbox\"!=(n=e.type)&&\"radio\"!=n),_.options.useOnlyNativeEvents||!Te||n)if(\"function\"==typeof xe.createEvent){if(\"function\"!=typeof e.dispatchEvent)throw Error(\"The supplied element doesn't support dispatchEvent\");(n=xe.createEvent(s[t]||\"HTMLEvents\")).initEvent(t,!0,!0,we,0,0,0,0,0,!1,!1,!1,!1,0,e),e.dispatchEvent(n)}else if(n&&e.click)e.click();else{if(void 0===e.fireEvent)throw Error(\"Browser doesn't support triggering events\");e.fireEvent(\"on\"+t)}else Te(e).trigger(t)},c:function(e){return _.N(e)?e():e},$b:function(e){return _.N(e)?e.w():e},Eb:function(t,e,n){var r;e&&(\"object\"===_typeof(t.classList)?(r=t.classList[n?\"add\":\"remove\"],_.a.C(e.match(p),function(e){r.call(t.classList,e)})):\"string\"==typeof t.className.baseVal?i(t.className,\"baseVal\",e,n):i(t,\"className\",e,n))},Ab:function(e,t){var n=_.a.c(t);null!==n&&n!==ye||(n=\"\");var r=_.h.firstChild(e);!r||3!=r.nodeType||_.h.nextSibling(r)?_.h.ua(e,[e.ownerDocument.createTextNode(n)]):r.data=n,_.a.zd(e)},Xc:function(e,t){if(e.name=t,d<=7)try{var n=e.name.replace(/[&<>'\"]/g,function(e){return\"&#\"+e.charCodeAt(0)+\";\"});e.mergeAttributes(xe.createElement(\"\"),!1)}catch(e){}},zd:function(e){9<=d&&(e=1==e.nodeType?e:e.parentNode).style&&(e.style.zoom=e.style.zoom)},vd:function(e){if(d){var t=e.style.width;e.style.width=0,e.style.width=t}},Od:function(e,t){e=_.a.c(e),t=_.a.c(t);for(var n=[],r=e;r<=t;r++)n.push(r);return n},la:function(e){for(var t=[],n=0,r=e.length;n\",\"\"],tbody:t,tfoot:t,tr:[2,\"\",\"
\"],td:l=[3,\"\",\"
\"],th:l,option:f=[1,\"\"],optgroup:f},p=_.a.W<=8,_.a.ta=function(e,t){var n;if(Te){if(Te.parseHTML)n=Te.parseHTML(e,t)||[];else if((n=Te.clean([e],t))&&n[0]){for(var r=n[0];r.parentNode&&11!==r.parentNode.nodeType;)r=r.parentNode;r.parentNode&&r.parentNode.removeChild(r)}}else{(n=t)||(n=xe),r=n.parentWindow||n.defaultView||we;var i,o=_.a.Cb(e).toLowerCase(),a=n.createElement(\"div\");for(o=(i=(o=o.match(/^(?:\\x3c!--.*?--\\x3e\\s*?)*?<([a-z]+)[\\s>]/))&&d[o[1]]||u)[0],i=\"ignored
\"+i[1]+e+i[2]+\"
\",\"function\"==typeof r.innerShiv?a.appendChild(r.innerShiv(i)):(p&&n.body.appendChild(a),a.innerHTML=i,p&&a.parentNode.removeChild(a));o--;)a=a.lastChild;n=_.a.la(a.lastChild.childNodes)}return n},_.a.Ld=function(e,t){var n=_.a.ta(e,t);return n.length&&n[0].parentElement||_.a.Xb(n)},_.a.dc=function(e,t){if(_.a.Sb(e),null!==(t=_.a.c(t))&&t!==ye)if(\"string\"!=typeof t&&(t=t.toString()),Te)Te(e).html(t);else for(var n=_.a.ta(t,e.ownerDocument),r=0;r]*))?)*\\s+)data-bind\\s*=\\s*([\"'])([\\s\\S]*?)\\3/gi,de=/\\x3c!--\\s*ko\\b\\s*([\\s\\S]*?)\\s*--\\x3e/g,{wd:function(e,t,n){t.isTemplateRewritten(e,n)||t.rewriteTemplate(e,function(e){return _.ic.Kd(e,t)},n)},Kd:function(e,o){return e.replace(fe,function(e,t,n,r,i){return ge(i,t,n,o)}).replace(de,function(e,t){return ge(t,\"\\x3c!-- ko --\\x3e\",\"#comment\",o)})},ld:function(r,i){return _.aa.Wb(function(e,t){var n=e.nextSibling;n&&n.nodeName.toLowerCase()===i&&_.eb(n,r,t)})}}),_.b(\"__tr_ambtns\",_.ic.ld),function(){_.B={},_.B.D=function(e){if(this.D=e){var t=_.a.P(e);this.Db=\"script\"===t?1:\"textarea\"===t?2:\"template\"==t&&e.content&&11===e.content.nodeType?3:4}},_.B.D.prototype.text=function(){var e=1===this.Db?\"text\":2===this.Db?\"value\":\"innerHTML\";if(0==arguments.length)return this.D[e];var t=arguments[0];\"innerHTML\"==e?_.a.dc(this.D,t):this.D[e]=t};var t=_.a.g.Z()+\"_\";_.B.D.prototype.data=function(e){if(1===arguments.length)return _.a.g.get(this.D,t+e);_.a.g.set(this.D,t+e,arguments[1])};var r=_.a.g.Z();_.B.D.prototype.nodes=function(){var e=this.D;if(0==arguments.length){var t=_.a.g.get(e,r)||{},n=t.jb||(3===this.Db?e.content:4===this.Db?e:ye);return n&&!t.hd||(t=this.text())&&(n=_.a.Ld(t,e.ownerDocument),this.text(\"\"),_.a.g.set(e,r,{jb:n,hd:!0})),n}_.a.g.set(e,r,{jb:arguments[0]})},_.B.ia=function(e){this.D=e},_.B.ia.prototype=new _.B.D,_.B.ia.prototype.constructor=_.B.ia,_.B.ia.prototype.text=function(){if(0==arguments.length){var e=_.a.g.get(this.D,r)||{};return e.jc===ye&&e.jb&&(e.jc=e.jb.innerHTML),e.jc}_.a.g.set(this.D,r,{jc:arguments[0]})},_.b(\"templateSources\",_.B),_.b(\"templateSources.domElement\",_.B.D),_.b(\"templateSources.anonymousTemplate\",_.B.ia)}(),function(){function r(e,t,n){var r;for(t=_.h.nextSibling(t);e&&(r=e)!==t;)n(r,e=_.h.nextSibling(r))}function d(e,t){if(e.length){var i=e[0],o=e[e.length-1],n=i.parentNode,a=_.ga.instance,s=a.preprocessNode;if(s){if(r(i,o,function(e,t){var n=e.previousSibling,r=s.call(a,e);r&&(e===i&&(i=r[0]||t),e===o&&(o=r[r.length-1]||n))}),e.length=0,!i)return;i===o?e.push(i):(e.push(i,o),_.a.Ua(e,n))}r(i,o,function(e){1!==e.nodeType&&8!==e.nodeType||_.uc(t,e)}),r(i,o,function(e){1!==e.nodeType&&8!==e.nodeType||_.aa.bd(e,[t])}),_.a.Ua(e,n)}}function u(e){return e.nodeType?e:0\"+t+\"<\\/script>\")},0\n" - "\n" - " \n" - " \n" - " \n" - " image/svg+xml\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; diff --git a/src/web_static/web_server.wifi_signal_2.svg.h b/src/web_static/web_server.wifi_signal_2.svg.h deleted file mode 100644 index a20670e..0000000 --- a/src/web_static/web_server.wifi_signal_2.svg.h +++ /dev/null @@ -1,67 +0,0 @@ -static const char CONTENT_WIFI_SIGNAL_2_SVG[] PROGMEM = - "\n" - "\n" - " \n" - " \n" - " \n" - " image/svg+xml\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; diff --git a/src/web_static/web_server.wifi_signal_3.svg.h b/src/web_static/web_server.wifi_signal_3.svg.h deleted file mode 100644 index 0970954..0000000 --- a/src/web_static/web_server.wifi_signal_3.svg.h +++ /dev/null @@ -1,66 +0,0 @@ -static const char CONTENT_WIFI_SIGNAL_3_SVG[] PROGMEM = - "\n" - "\n" - " \n" - " \n" - " \n" - " image/svg+xml\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; diff --git a/src/web_static/web_server.wifi_signal_4.svg.h b/src/web_static/web_server.wifi_signal_4.svg.h deleted file mode 100644 index 0132e92..0000000 --- a/src/web_static/web_server.wifi_signal_4.svg.h +++ /dev/null @@ -1,65 +0,0 @@ -static const char CONTENT_WIFI_SIGNAL_4_SVG[] PROGMEM = - "\n" - "\n" - " \n" - " \n" - " \n" - " image/svg+xml\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; diff --git a/src/web_static/web_server.wifi_signal_5.svg.h b/src/web_static/web_server.wifi_signal_5.svg.h deleted file mode 100644 index 8405c9a..0000000 --- a/src/web_static/web_server.wifi_signal_5.svg.h +++ /dev/null @@ -1,55 +0,0 @@ -static const char CONTENT_WIFI_SIGNAL_5_SVG[] PROGMEM = - "\n" - "\n" - " \n" - " \n" - " \n" - " image/svg+xml\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; diff --git a/src/web_static/web_server_static_files.h b/src/web_static/web_server_static_files.h index bba8449..eba578a 100644 --- a/src/web_static/web_server_static_files.h +++ b/src/web_static/web_server_static_files.h @@ -7,6 +7,8 @@ #include "web_server.lib.js.h" #include "web_server.ohm.jpg.h" #include "web_server.style.css.h" +#include "web_server.term.html.h" +#include "web_server.term.js.h" #include "web_server.wifi_portal.html.h" #include "web_server.wifi_portal.js.h" #include "web_server.wifi_signal_1.svg.h" @@ -14,6 +16,7 @@ #include "web_server.wifi_signal_3.svg.h" #include "web_server.wifi_signal_4.svg.h" #include "web_server.wifi_signal_5.svg.h" +#include "web_server.zones.json.h" StaticFile staticFiles[] = { { "/assets.js", CONTENT_ASSETS_JS, sizeof(CONTENT_ASSETS_JS) - 1, _CONTENT_TYPE_JS }, { "/emoncms.jpg", CONTENT_EMONCMS_JPG, sizeof(CONTENT_EMONCMS_JPG) - 1, _CONTENT_TYPE_JPEG }, @@ -24,6 +27,8 @@ StaticFile staticFiles[] = { { "/lib.js", CONTENT_LIB_JS, sizeof(CONTENT_LIB_JS) - 1, _CONTENT_TYPE_JS }, { "/ohm.jpg", CONTENT_OHM_JPG, sizeof(CONTENT_OHM_JPG) - 1, _CONTENT_TYPE_JPEG }, { "/style.css", CONTENT_STYLE_CSS, sizeof(CONTENT_STYLE_CSS) - 1, _CONTENT_TYPE_CSS }, + { "/term.html", CONTENT_TERM_HTML, sizeof(CONTENT_TERM_HTML) - 1, _CONTENT_TYPE_HTML }, + { "/term.js", CONTENT_TERM_JS, sizeof(CONTENT_TERM_JS) - 1, _CONTENT_TYPE_JS }, { "/wifi_portal.html", CONTENT_WIFI_PORTAL_HTML, sizeof(CONTENT_WIFI_PORTAL_HTML) - 1, _CONTENT_TYPE_HTML }, { "/wifi_portal.js", CONTENT_WIFI_PORTAL_JS, sizeof(CONTENT_WIFI_PORTAL_JS) - 1, _CONTENT_TYPE_JS }, { "/wifi_signal_1.svg", CONTENT_WIFI_SIGNAL_1_SVG, sizeof(CONTENT_WIFI_SIGNAL_1_SVG) - 1, _CONTENT_TYPE_SVG }, @@ -31,4 +36,5 @@ StaticFile staticFiles[] = { { "/wifi_signal_3.svg", CONTENT_WIFI_SIGNAL_3_SVG, sizeof(CONTENT_WIFI_SIGNAL_3_SVG) - 1, _CONTENT_TYPE_SVG }, { "/wifi_signal_4.svg", CONTENT_WIFI_SIGNAL_4_SVG, sizeof(CONTENT_WIFI_SIGNAL_4_SVG) - 1, _CONTENT_TYPE_SVG }, { "/wifi_signal_5.svg", CONTENT_WIFI_SIGNAL_5_SVG, sizeof(CONTENT_WIFI_SIGNAL_5_SVG) - 1, _CONTENT_TYPE_SVG }, + { "/zones.json", CONTENT_ZONES_JSON, sizeof(CONTENT_ZONES_JSON) - 1, _CONTENT_TYPE_TEXT }, }; diff --git a/src/wifi.cpp b/src/wifi.cpp index f0a7b56..c6a8f96 100644 --- a/src/wifi.cpp +++ b/src/wifi.cpp @@ -233,6 +233,13 @@ wifi_setup() { wifi_start(); + // pulled this status check from example: https://github.com/arduino/esp8266/blob/master/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino + // without this we get no mDNS and error: "standard interfaces are not up, please specify one in ::begin()" + // mDNS restarts after onStationModeGotIP and onStationModeDisconnected WiFiEventHandlers, but I guess requires connected status before the .begin() + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } if (MDNS.begin(esp_hostname.c_str())) { MDNS.addService("http", "tcp", 80); }