From 2fc1b8f87a3cc56ab063a5795bd30894271c6d85 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sat, 3 Jul 2021 21:31:07 +0100 Subject: [PATCH 01/20] Initial update to latest ESP32 Platform IO package/ESP-IDF --- CMakeLists.txt | 3 ++ platformio.ini | 93 ++++++++++++---------------------------------- sdkconfig.defaults | 18 +++++++++ src/CMakeLists.txt | 6 +++ src/ota.cpp | 2 +- src/scheduler.cpp | 2 +- 6 files changed, 52 insertions(+), 72 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 sdkconfig.defaults create mode 100644 src/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..00a24c59 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16.0) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(OpenEVSE_WiFi) diff --git a/platformio.ini b/platformio.ini index d2561f74..54877a8e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -54,10 +54,13 @@ debug_flags = #-DENABLE_DEBUG_LCD #-DENABLE_DEBUG_MQTT #-DENABLE_DEBUG_EMONCMS + -DENABLE_DEBUG_WEB #-DENABLE_PROFILE src_build_flags = # -DENABLE_ASYNC_WIFI_SCAN build_flags = + -DARDUINO=250 + -DESP32 -DCS_PLATFORM=CS_P_ESP32 -DMG_ENABLE_SSL=1 -DMG_ENABLE_HTTP_STREAMING_MULTIPART=1 @@ -71,24 +74,38 @@ build_flags = #-DCS_ENABLE_DEBUG #-DMBEDTLS_DEBUG_C -DMG_ENABLE_SNTP=1 - -DCS_PLATFORM=CS_P_ESP32 + -DENABLE_DEBUG_MICROTASKS build_partitions = min_spiffs.csv -monitor_flags = --filter=esp32_exception_decoder neopixel_lib = adafruit/Adafruit NeoPixel@1.7.0 + +[env] # 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-espressif32.git#feature/stage #platform = https://github.com/platformio/platform-espressif32.git#develop -platform = espressif32@1.11.1 -#platform = espressif32 +#platform = espressif32@1.11.1 +platform = espressif32 +framework = arduino, espidf +lib_deps = ${common.lib_deps} +build_flags = + ${common.build_flags} +#upload_port = openevse.local +upload_speed = 921600 +monitor_speed = 115200 +extra_scripts = ${common.extra_scripts} +board_build.partitions = ${common.build_partitions} +platform_packages = + ; use a special branch + framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 +monitor_flags = + --filter=esp32_exception_decoder + --raw [env:openevse_nodemcu-32s] -platform = ${common.platform} board = nodemcu-32s framework = arduino, espidf -lib_deps = ${common.lib_deps} src_build_flags = ${common.version}.dev ${common.src_build_flags} @@ -96,18 +113,9 @@ src_build_flags = -DWIFI_LED=LED_BUILTIN -DWIFI_LED_ON_STATE=LOW -DRAPI_PORT=Serial2 -build_flags = - ${common.build_flags} -#upload_port = openevse.local -upload_speed = 921600 -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions} [env:openevse_esp-wrover-kit] -platform = ${common.platform} board = esp-wrover-kit -framework = arduino, espidf lib_deps = ${common.lib_deps} ${common.neopixel_lib} @@ -130,18 +138,12 @@ build_flags = #upload_port = openevse.local #upload_speed = 921600 upload_protocol = ftdi -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions} lib_extra_dirs = lib # export PLATFORMIO_UPLOAD_PORT=172.16.0.157 # export PLATFORMIO_UPLOAD_FLAGS="-p 3232" [env:openevse_huzzah32_dev] -platform = ${common.platform} board = featheresp32 -framework = arduino, espidf -lib_deps = ${common.lib_deps} src_build_flags = ${common.version}.dev ${common.src_build_flags} @@ -153,18 +155,9 @@ src_build_flags = -DRAPI_PORT=Serial -DDEBUG_PORT=Serial2 -DSERIAL_RX_PULLUP_PIN=3 -build_flags = - ${common.build_flags} -upload_speed = 921600 -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions} [env:openevse_huzzah32] -platform = ${common.platform} board = featheresp32 -framework = arduino, espidf -lib_deps = ${common.lib_deps} src_build_flags = ${common.version} ${common.src_build_flags} @@ -175,18 +168,9 @@ src_build_flags = -DRAPI_PORT=Serial -DDEBUG_PORT=Serial2 -DSERIAL_RX_PULLUP_PIN=3 -build_flags = - ${common.build_flags} -upload_speed = 921600 -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions} [env:openevse_featheresp32] -platform = ${common.platform} board = featheresp32 -framework = arduino, espidf -lib_deps = ${common.lib_deps} src_build_flags = ${common.version}.dev ${common.src_build_flags} @@ -195,18 +179,9 @@ src_build_flags = -DWIFI_BUTTON=LED_BUILTIN -DRAPI_PORT=Serial2 -DENABLE_DEBUG_LED -build_flags = - ${common.build_flags} -#upload_port = openevse.local -upload_speed = 921600 -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions} [env:openevse_wifi_v1] -platform = ${common.platform} board = esp32dev -framework = arduino, espidf lib_deps = ${common.lib_deps} ${common.neopixel_lib} @@ -228,17 +203,10 @@ src_build_flags = build_flags = ${common.build_flags} -DTX1=16 -upload_speed = 921600 -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions} [env:openevse_esp32-gateway] #For hardware older than RevE -platform = ${common.platform} board = esp32-gateway -framework = arduino, espidf -lib_deps = ${common.lib_deps} src_build_flags = ${common.version} ${common.src_build_flags} @@ -250,13 +218,7 @@ src_build_flags = -DRAPI_PORT=Serial2 -DENABLE_WIRED_ETHERNET -DRANDOM_SEED_CHANNEL=1 -build_flags = - ${common.build_flags} -upload_speed = 115200 -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} # https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/examples/ETH_LAN8720/ETH_LAN8720.ino -board_build.partitions = ${common.build_partitions} [env:openevse_esp32-gateway-e] # Tested working with hardware RevE and RevF @@ -270,10 +232,7 @@ build_flags = board_build.extra_flags = "-DARDUINO_ESP32_GATEWAY=\'E\'" [env:openevse_esp32-heltec-wifi-lora-v2] -platform = ${common.platform} board = heltec_wifi_lora_32_V2 -framework = arduino, espidf -lib_deps = ${common.lib_deps} src_build_flags = ${common.version}.dev ${common.src_build_flags} @@ -285,9 +244,3 @@ build_flags = ${common.build_flags} -DRX1=25 -DTX1=27 -#upload_port = openevse.local -#upload_speed = 921600 -upload_protocol = esptool -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions} diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 00000000..90e65ab3 --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,18 @@ +# Override some defaults to enable Arduino framework +CONFIG_ENABLE_ARDUINO_DEPENDS=y +CONFIG_AUTOSTART_ARDUINO=y +CONFIG_ARDUINO_RUN_CORE1=y +CONFIG_ARDUINO_RUNNING_CORE=1 +CONFIG_ARDUINO_EVENT_RUN_CORE1=y +CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 +CONFIG_ARDUINO_UDP_RUN_CORE1=y +CONFIG_ARDUINO_UDP_RUNNING_CORE=1 +CONFIG_DISABLE_HAL_LOCKS=y +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 +CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y +CONFIG_ARDUHAL_PARTITION_SCHEME="default" +CONFIG_AUTOCONNECT_WIFI=y +CONFIG_ARDUINO_SELECTIVE_WiFi=y +CONFIG_MBEDTLS_PSK_MODES=y +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..483bc0cf --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,6 @@ +# This file was automatically generated for projects +# without default 'CMakeLists.txt' file. + +FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*) + +idf_component_register(SRCS ${app_sources}) diff --git a/src/ota.cpp b/src/ota.cpp index 08e3be76..28191d6d 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -20,7 +20,7 @@ void ota_setup() // Clean SPIFFS //SPIFFS.end(); DBUGF("Starting ArduinoOTA update"); - lcd.display(F("Updating WiFi"), 0, 0, 0, LCD_CLEAR_LINE); + lcd.display(F("Updating WiFi"), 0, 0, 10, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); lcd.display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); }); diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 8fe43049..82513439 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -59,7 +59,7 @@ void Scheduler::Event::setId(uint32_t id) { String Scheduler::Event::getTime() { - char time[9]; + char time[14]; snprintf(time, sizeof(time), "%02d:%02d:%02d", getHours(), getMinutes(), getSeconds()); String timeString(time); return timeString; From 8d7f8fd0f7245501bca5ef0c720af7631ad517c0 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 4 Jul 2021 21:45:06 +0100 Subject: [PATCH 02/20] Fixed issues with profiling --- src/main.cpp | 3 +++ src/net_manager.cpp | 2 +- src/profile.h | 3 +-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 21212216..9aab4b16 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -148,7 +148,10 @@ loop() { ota_loop(); rapiSender.loop(); divert_current_loop(); + + Profile_Start(MicroTask); MicroTask.update(); + Profile_End(MicroTask, 10); if(OpenEVSE.isConnected()) { diff --git a/src/net_manager.cpp b/src/net_manager.cpp index 6de0cdaa..bb8ae33f 100644 --- a/src/net_manager.cpp +++ b/src/net_manager.cpp @@ -486,7 +486,7 @@ net_loop() dnsServer.processNextRequest(); // Captive portal DNS re-dierct } - Profile_End(net_wifi_loop, 5); + Profile_End(net_loop, 5); } void diff --git a/src/profile.h b/src/profile.h index d02df132..2c8bd232 100644 --- a/src/profile.h +++ b/src/profile.h @@ -1,10 +1,9 @@ #ifndef __PROFILE_H #define __PROFILE_H -#if defined(ENABLE_PROFILE) && defined(ENABLE_DEBUG) +#if defined(ENABLE_PROFILE) #if defined(ENABLE_NOISY_PROFILE) - #define Profile_Start(x) \ unsigned long profile ## x = millis(); \ DBUGLN(">> Start " #x) From e3fa04d0632eb17d697e73190831aa103d8d5b9d Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 4 Jul 2021 21:45:24 +0100 Subject: [PATCH 03/20] Removed old IDF 3 files --- src/sdkconfig | 939 ------------------------------------------------ src/sdkconfig.h | 397 -------------------- 2 files changed, 1336 deletions(-) delete mode 100644 src/sdkconfig delete mode 100644 src/sdkconfig.h diff --git a/src/sdkconfig b/src/sdkconfig deleted file mode 100644 index 18fe7ab8..00000000 --- a/src/sdkconfig +++ /dev/null @@ -1,939 +0,0 @@ -# -# Automatically generated file; DO NOT EDIT. -# Espressif IoT Development Framework Configuration -# -CONFIG_IDF_TARGET="esp32" -CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 - -# -# SDK tool configuration -# -CONFIG_TOOLPREFIX="xtensa-esp32-elf-" -CONFIG_PYTHON="python" -CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y - -# -# Application manager -# -CONFIG_APP_COMPILE_TIME_DATE=y -CONFIG_APP_EXCLUDE_PROJECT_VER_VAR= -CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR= - -# -# Arduino Configuration -# -CONFIG_ENABLE_ARDUINO_DEPENDS=y -CONFIG_AUTOSTART_ARDUINO=y -CONFIG_ARDUINO_RUN_CORE0= -CONFIG_ARDUINO_RUN_CORE1=y -CONFIG_ARDUINO_RUN_NO_AFFINITY= -CONFIG_ARDUINO_RUNNING_CORE=1 -CONFIG_ARDUINO_EVENT_RUN_CORE0= -CONFIG_ARDUINO_EVENT_RUN_CORE1=y -CONFIG_ARDUINO_EVENT_RUN_NO_AFFINITY= -CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 -CONFIG_ARDUINO_UDP_RUN_CORE0= -CONFIG_ARDUINO_UDP_RUN_CORE1=y -CONFIG_ARDUINO_UDP_RUN_NO_AFFINITY= -CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_DISABLE_HAL_LOCKS= - -# -# Debug Log Configuration -# -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_NONE= -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_WARN= -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO= -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_DEBUG= -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE= -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 -CONFIG_ARDUHAL_LOG_COLORS= -CONFIG_ARDUHAL_ESP_LOG=y -CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y -CONFIG_ARDUHAL_PARTITION_SCHEME_MINIMAL= -CONFIG_ARDUHAL_PARTITION_SCHEME_NO_OTA= -CONFIG_ARDUHAL_PARTITION_SCHEME_HUGE_APP= -CONFIG_ARDUHAL_PARTITION_SCHEME_MIN_SPIFFS= -CONFIG_ARDUHAL_PARTITION_SCHEME="default" -CONFIG_AUTOCONNECT_WIFI= -CONFIG_ARDUINO_SELECTIVE_COMPILATION= - -# -# Bootloader config -# -CONFIG_LOG_BOOTLOADER_LEVEL_NONE=y -CONFIG_LOG_BOOTLOADER_LEVEL_ERROR= -CONFIG_LOG_BOOTLOADER_LEVEL_WARN= -CONFIG_LOG_BOOTLOADER_LEVEL_INFO= -CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= -CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= -CONFIG_LOG_BOOTLOADER_LEVEL=0 -CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= -CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y -CONFIG_BOOTLOADER_FACTORY_RESET= -CONFIG_BOOTLOADER_APP_TEST= -CONFIG_BOOTLOADER_WDT_ENABLE=y -CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE= -CONFIG_BOOTLOADER_WDT_TIME_MS=9000 -CONFIG_APP_ROLLBACK_ENABLE= - -# -# Security features -# -CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT= -CONFIG_SECURE_BOOT_ENABLED= -CONFIG_FLASH_ENCRYPTION_ENABLED= - -# -# Serial flasher config -# -CONFIG_ESPTOOLPY_PORT="/dev/cu.usbserial-DO00EAB0" -CONFIG_ESPTOOLPY_BAUD_115200B= -CONFIG_ESPTOOLPY_BAUD_230400B= -CONFIG_ESPTOOLPY_BAUD_921600B=y -CONFIG_ESPTOOLPY_BAUD_2MB= -CONFIG_ESPTOOLPY_BAUD_OTHER= -CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 -CONFIG_ESPTOOLPY_BAUD=921600 -CONFIG_ESPTOOLPY_COMPRESSED=y -CONFIG_FLASHMODE_QIO= -CONFIG_FLASHMODE_QOUT= -CONFIG_FLASHMODE_DIO=y -CONFIG_FLASHMODE_DOUT= -CONFIG_ESPTOOLPY_FLASHMODE="dio" -CONFIG_ESPTOOLPY_FLASHFREQ_80M= -CONFIG_ESPTOOLPY_FLASHFREQ_40M=y -CONFIG_ESPTOOLPY_FLASHFREQ_26M= -CONFIG_ESPTOOLPY_FLASHFREQ_20M= -CONFIG_ESPTOOLPY_FLASHFREQ="40m" -CONFIG_ESPTOOLPY_FLASHSIZE_1MB= -CONFIG_ESPTOOLPY_FLASHSIZE_2MB= -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_ESPTOOLPY_FLASHSIZE_8MB= -CONFIG_ESPTOOLPY_FLASHSIZE_16MB= -CONFIG_ESPTOOLPY_FLASHSIZE="4MB" -CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y -CONFIG_ESPTOOLPY_BEFORE_RESET=y -CONFIG_ESPTOOLPY_BEFORE_NORESET= -CONFIG_ESPTOOLPY_BEFORE="default_reset" -CONFIG_ESPTOOLPY_AFTER_RESET=y -CONFIG_ESPTOOLPY_AFTER_NORESET= -CONFIG_ESPTOOLPY_AFTER="hard_reset" -CONFIG_MONITOR_BAUD_9600B= -CONFIG_MONITOR_BAUD_57600B= -CONFIG_MONITOR_BAUD_115200B=y -CONFIG_MONITOR_BAUD_230400B= -CONFIG_MONITOR_BAUD_921600B= -CONFIG_MONITOR_BAUD_2MB= -CONFIG_MONITOR_BAUD_OTHER= -CONFIG_MONITOR_BAUD_OTHER_VAL=115200 -CONFIG_MONITOR_BAUD=115200 - -# -# Partition Table -# -CONFIG_PARTITION_TABLE_SINGLE_APP=y -CONFIG_PARTITION_TABLE_TWO_OTA= -CONFIG_PARTITION_TABLE_CUSTOM= -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" -CONFIG_PARTITION_TABLE_OFFSET=0x8000 -CONFIG_PARTITION_TABLE_MD5=y - -# -# Compiler options -# -CONFIG_OPTIMIZATION_LEVEL_DEBUG=y -CONFIG_OPTIMIZATION_LEVEL_RELEASE= -CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y -CONFIG_OPTIMIZATION_ASSERTIONS_SILENT= -CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED= -CONFIG_CXX_EXCEPTIONS=y -CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -CONFIG_STACK_CHECK_NONE= -CONFIG_STACK_CHECK_NORM=y -CONFIG_STACK_CHECK_STRONG= -CONFIG_STACK_CHECK_ALL= -CONFIG_STACK_CHECK=y -CONFIG_WARN_WRITE_STRINGS=y -CONFIG_DISABLE_GCC8_WARNINGS= - -# -# Component config -# - -# -# Application Level Tracing -# -CONFIG_ESP32_APPTRACE_DEST_TRAX= -CONFIG_ESP32_APPTRACE_DEST_NONE=y -CONFIG_ESP32_APPTRACE_ENABLE= -CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y -CONFIG_AWS_IOT_SDK=y -CONFIG_AWS_IOT_MQTT_HOST="" -CONFIG_AWS_IOT_MQTT_PORT=8883 -CONFIG_AWS_IOT_MQTT_TX_BUF_LEN=512 -CONFIG_AWS_IOT_MQTT_RX_BUF_LEN=512 -CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS=5 -CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL=1000 -CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL=128000 - -# -# Thing Shadow -# -CONFIG_AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER= -CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES=80 -CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS=10 -CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES=10 -CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED=120 -CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME=60 -CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME=20 - -# -# Bluetooth -# -CONFIG_BT_ENABLED=y - -# -# Bluetooth controller -# -CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY= -CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY= -CONFIG_BTDM_CONTROLLER_MODE_BTDM=y -CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 -CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN=2 -CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN=0 -CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 -CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 -CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=2 -CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 -CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y -CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= -CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 -CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y -CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= - -# -# MODEM SLEEP Options -# -CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=y -CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG=y -CONFIG_BTDM_MODEM_SLEEP_MODE_EVED= -CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL=y -CONFIG_BLE_SCAN_DUPLICATE=y -CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR=y -CONFIG_SCAN_DUPLICATE_BY_ADV_DATA= -CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR= -CONFIG_SCAN_DUPLICATE_TYPE=0 -CONFIG_DUPLICATE_SCAN_CACHE_SIZE=20 -CONFIG_BLE_MESH_SCAN_DUPLICATE_EN= -CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED=y -CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM=100 -CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 -CONFIG_BTDM_COEX_BT_OPTIONS= -CONFIG_BLUEDROID_ENABLED=y -CONFIG_BLUEDROID_PINNED_TO_CORE_0=y -CONFIG_BLUEDROID_PINNED_TO_CORE_1= -CONFIG_BLUEDROID_PINNED_TO_CORE=0 -CONFIG_BTC_TASK_STACK_SIZE=8192 -CONFIG_BTU_TASK_STACK_SIZE=4096 -CONFIG_BLUEDROID_MEM_DEBUG= -CONFIG_CLASSIC_BT_ENABLED=y -CONFIG_A2DP_ENABLE=y -CONFIG_A2DP_SINK_TASK_STACK_SIZE=2048 -CONFIG_A2DP_SOURCE_TASK_STACK_SIZE=2048 -CONFIG_BT_SPP_ENABLED=y -CONFIG_HFP_ENABLE=y -CONFIG_HFP_CLIENT_ENABLE=y -CONFIG_HFP_AUDIO_DATA_PATH_PCM=y -CONFIG_HFP_AUDIO_DATA_PATH_HCI= -CONFIG_BT_SSP_ENABLED=y -CONFIG_GATTS_ENABLE=y -CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL= -CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y -CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 -CONFIG_GATTC_ENABLE=y -CONFIG_GATTC_CACHE_NVS_FLASH= -CONFIG_BLE_SMP_ENABLE=y -CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE= -CONFIG_BT_STACK_NO_LOG=y -CONFIG_BT_ACL_CONNECTIONS=4 -CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y -CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=y -CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK= -CONFIG_SMP_ENABLE=y -CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY= -CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c - -# -# Driver configurations -# - -# -# ADC configuration -# -CONFIG_ADC_FORCE_XPD_FSM= -CONFIG_ADC2_DISABLE_DAC=y - -# -# SPI configuration -# -CONFIG_SPI_MASTER_IN_IRAM= -CONFIG_SPI_MASTER_ISR_IN_IRAM=y -CONFIG_SPI_SLAVE_IN_IRAM= -CONFIG_SPI_SLAVE_ISR_IN_IRAM=y - -# -# eFuse Bit Manager -# -CONFIG_EFUSE_CUSTOM_TABLE= -CONFIG_EFUSE_VIRTUAL= -CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE= -CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y -CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT= -CONFIG_EFUSE_MAX_BLK_LEN=192 -CONFIG_C_IMPL= -CONFIG_XTENSA_IMPL=y - -# -# ESP-FACE Configuration -# -CONFIG_MTMN_LITE_QUANT=y -CONFIG_MTMN_LITE_FLOAT= -CONFIG_MTMN_HEAVY_QUANT= -CONFIG_FRMN= -CONFIG_MFN56_1X=y -CONFIG_MFN56_2X= -CONFIG_MFN56_3X= -CONFIG_MFN56_4X= - -# -# Object Detection -# -CONFIG_LSSH_SPARSE_MN_5=y -CONFIG_LSSH_WITH_LANDMARK= - -# -# ESP32-specific -# -CONFIG_IDF_TARGET_ESP32=y -CONFIG_ESP32_REV_MIN_0=y -CONFIG_ESP32_REV_MIN_1= -CONFIG_ESP32_REV_MIN_2= -CONFIG_ESP32_REV_MIN_3= -CONFIG_ESP32_REV_MIN=0 -CONFIG_ESP32_DPORT_WORKAROUND=y -CONFIG_ESP32_DEFAULT_CPU_FREQ_80= -CONFIG_ESP32_DEFAULT_CPU_FREQ_160= -CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y -CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -CONFIG_SPIRAM_SUPPORT=y - -# -# SPI RAM config -# -CONFIG_SPIRAM_BOOT_INIT= -CONFIG_SPIRAM_USE_MEMMAP= -CONFIG_SPIRAM_USE_CAPS_ALLOC=y -CONFIG_SPIRAM_USE_MALLOC= -CONFIG_SPIRAM_TYPE_AUTO=y -CONFIG_SPIRAM_TYPE_ESPPSRAM32= -CONFIG_SPIRAM_TYPE_ESPPSRAM64= -CONFIG_SPIRAM_SIZE=-1 -CONFIG_SPIRAM_SPEED_40M=y -CONFIG_SPIRAM_CACHE_WORKAROUND=y -CONFIG_SPIRAM_BANKSWITCH_ENABLE=y -CONFIG_SPIRAM_BANKSWITCH_RESERVE=8 -CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST= -CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY= - -# -# PSRAM clock and cs IO for ESP32-DOWD -# -CONFIG_D0WD_PSRAM_CLK_IO=17 -CONFIG_D0WD_PSRAM_CS_IO=16 - -# -# PSRAM clock and cs IO for ESP32-D2WD -# -CONFIG_D2WD_PSRAM_CLK_IO=9 -CONFIG_D2WD_PSRAM_CS_IO=10 - -# -# PSRAM clock and cs IO for ESP32-PICO -# -CONFIG_PICO_PSRAM_CS_IO=10 -CONFIG_SPIRAM_SPIWP_SD3_PIN=7 -CONFIG_MEMMAP_TRACEMEM= -CONFIG_MEMMAP_TRACEMEM_TWOBANKS= -CONFIG_ESP32_TRAX= -CONFIG_TRACEMEM_RESERVE_DRAM=0x0 -CONFIG_TWO_UNIVERSAL_MAC_ADDRESS= -CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y -CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 -CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 -CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2048 -CONFIG_MAIN_TASK_STACK_SIZE=4096 -CONFIG_IPC_TASK_STACK_SIZE=1024 -CONFIG_TIMER_TASK_STACK_SIZE=4096 -CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y -CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF= -CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR= -CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF= -CONFIG_NEWLIB_STDIN_LINE_ENDING_LF= -CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y -CONFIG_NEWLIB_NANO_FORMAT= -CONFIG_CONSOLE_UART_DEFAULT=y -CONFIG_CONSOLE_UART_CUSTOM= -CONFIG_CONSOLE_UART_NONE= -CONFIG_CONSOLE_UART_NUM=0 -CONFIG_CONSOLE_UART_BAUDRATE=115200 -CONFIG_ULP_COPROC_ENABLED=y -CONFIG_ULP_COPROC_RESERVE_MEM=512 -CONFIG_ESP32_PANIC_PRINT_HALT= -CONFIG_ESP32_PANIC_PRINT_REBOOT=y -CONFIG_ESP32_PANIC_SILENT_REBOOT= -CONFIG_ESP32_PANIC_GDBSTUB= -CONFIG_ESP32_DEBUG_OCDAWARE=y -CONFIG_ESP32_DEBUG_STUBS_ENABLE=y -CONFIG_INT_WDT=y -CONFIG_INT_WDT_TIMEOUT_MS=300 -CONFIG_INT_WDT_CHECK_CPU1=y -CONFIG_TASK_WDT=y -CONFIG_TASK_WDT_PANIC=y -CONFIG_TASK_WDT_TIMEOUT_S=5 -CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y -CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1= -CONFIG_BROWNOUT_DET=y -CONFIG_BROWNOUT_DET_LVL_SEL_0=y -CONFIG_BROWNOUT_DET_LVL_SEL_1= -CONFIG_BROWNOUT_DET_LVL_SEL_2= -CONFIG_BROWNOUT_DET_LVL_SEL_3= -CONFIG_BROWNOUT_DET_LVL_SEL_4= -CONFIG_BROWNOUT_DET_LVL_SEL_5= -CONFIG_BROWNOUT_DET_LVL_SEL_6= -CONFIG_BROWNOUT_DET_LVL_SEL_7= -CONFIG_BROWNOUT_DET_LVL=0 -CONFIG_REDUCE_PHY_TX_POWER=y -CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y -CONFIG_ESP32_TIME_SYSCALL_USE_RTC= -CONFIG_ESP32_TIME_SYSCALL_USE_FRC1= -CONFIG_ESP32_TIME_SYSCALL_USE_NONE= -CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y -CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL= -CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC= -CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256= -CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 -CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 -CONFIG_ESP32_XTAL_FREQ_40= -CONFIG_ESP32_XTAL_FREQ_26= -CONFIG_ESP32_XTAL_FREQ_AUTO=y -CONFIG_ESP32_XTAL_FREQ=0 -CONFIG_DISABLE_BASIC_ROM_CONSOLE= -CONFIG_ESP_TIMER_PROFILING= -CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= -CONFIG_ESP_ERR_TO_NAME_LOOKUP=y -CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 - -# -# Wi-Fi -# -CONFIG_SW_COEXIST_ENABLE=y -CONFIG_SW_COEXIST_PREFERENCE_WIFI= -CONFIG_SW_COEXIST_PREFERENCE_BT= -CONFIG_SW_COEXIST_PREFERENCE_BALANCE=y -CONFIG_SW_COEXIST_PREFERENCE_VALUE=2 -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 -CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y -CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 -CONFIG_ESP32_WIFI_CSI_ENABLED= -CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y -CONFIG_ESP32_WIFI_TX_BA_WIN=6 -CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y -CONFIG_ESP32_WIFI_RX_BA_WIN=16 -CONFIG_ESP32_WIFI_NVS_ENABLED=y -CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y -CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= -CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 -CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 -CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE= -CONFIG_ESP32_WIFI_IRAM_OPT=y -CONFIG_ESP32_WIFI_RX_IRAM_OPT= - -# -# PHY -# -CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y -CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION= -CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 -CONFIG_ESP32_PHY_MAX_TX_POWER=20 - -# -# Power Management -# -CONFIG_PM_ENABLE= - -# -# Camera configuration -# -CONFIG_OV2640_SUPPORT=y -CONFIG_OV7725_SUPPORT=y -CONFIG_OV3660_SUPPORT=y -CONFIG_SCCB_HARDWARE_I2C=y -CONFIG_CAMERA_CORE0= -CONFIG_CAMERA_CORE1=y -CONFIG_CAMERA_NO_AFFINITY= - -# -# ADC-Calibration -# -CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y -CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y -CONFIG_ADC_CAL_LUT_ENABLE=y - -# -# Event Loop Library -# -CONFIG_EVENT_LOOP_PROFILING= - -# -# ESP HTTP client -# -CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y -CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH= - -# -# HTTP Server -# -CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 -CONFIG_HTTPD_MAX_URI_LEN=512 -CONFIG_HTTPD_ERR_RESP_NO_DELAY=y -CONFIG_HTTPD_PURGE_BUF_LEN=32 -CONFIG_HTTPD_LOG_PURGE_DATA= - -# -# ESP HTTPS OTA -# -CONFIG_OTA_ALLOW_HTTP= - -# -# Core dump -# -CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH= -CONFIG_ESP32_ENABLE_COREDUMP_TO_UART= -CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y -CONFIG_ESP32_ENABLE_COREDUMP= - -# -# Ethernet -# -CONFIG_DMA_RX_BUF_NUM=10 -CONFIG_DMA_TX_BUF_NUM=10 -CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE=y -CONFIG_EMAC_CHECK_LINK_PERIOD_MS=2000 -CONFIG_EMAC_TASK_PRIORITY=20 -CONFIG_EMAC_TASK_STACK_SIZE=3072 - -# -# FAT Filesystem support -# -CONFIG_FATFS_CODEPAGE_DYNAMIC= -CONFIG_FATFS_CODEPAGE_437= -CONFIG_FATFS_CODEPAGE_720= -CONFIG_FATFS_CODEPAGE_737= -CONFIG_FATFS_CODEPAGE_771= -CONFIG_FATFS_CODEPAGE_775= -CONFIG_FATFS_CODEPAGE_850=y -CONFIG_FATFS_CODEPAGE_852= -CONFIG_FATFS_CODEPAGE_855= -CONFIG_FATFS_CODEPAGE_857= -CONFIG_FATFS_CODEPAGE_860= -CONFIG_FATFS_CODEPAGE_861= -CONFIG_FATFS_CODEPAGE_862= -CONFIG_FATFS_CODEPAGE_863= -CONFIG_FATFS_CODEPAGE_864= -CONFIG_FATFS_CODEPAGE_865= -CONFIG_FATFS_CODEPAGE_866= -CONFIG_FATFS_CODEPAGE_869= -CONFIG_FATFS_CODEPAGE_932= -CONFIG_FATFS_CODEPAGE_936= -CONFIG_FATFS_CODEPAGE_949= -CONFIG_FATFS_CODEPAGE_950= -CONFIG_FATFS_CODEPAGE=850 -CONFIG_FATFS_LFN_NONE= -CONFIG_FATFS_LFN_HEAP= -CONFIG_FATFS_LFN_STACK=y -CONFIG_FATFS_MAX_LFN=255 -CONFIG_FATFS_API_ENCODING_ANSI_OEM=y -CONFIG_FATFS_API_ENCODING_UTF_16= -CONFIG_FATFS_API_ENCODING_UTF_8= -CONFIG_FATFS_FS_LOCK=0 -CONFIG_FATFS_TIMEOUT_MS=10000 -CONFIG_FATFS_PER_FILE_CACHE=y -CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y - -# -# Modbus configuration -# -CONFIG_MB_QUEUE_LENGTH=20 -CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 -CONFIG_MB_SERIAL_BUF_SIZE=256 -CONFIG_MB_SERIAL_TASK_PRIO=10 -CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT= -CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 -CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 -CONFIG_MB_CONTROLLER_STACK_SIZE=4096 -CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 -CONFIG_MB_TIMER_PORT_ENABLED=y -CONFIG_MB_TIMER_GROUP=0 -CONFIG_MB_TIMER_INDEX=0 - -# -# FreeRTOS -# -CONFIG_FREERTOS_UNICORE= -CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF -CONFIG_FREERTOS_CORETIMER_0=y -CONFIG_FREERTOS_CORETIMER_1= -CONFIG_FREERTOS_HZ=1000 -CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION= -CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE= -CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL= -CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y -CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y -CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y -CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 -CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y -CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE= -CONFIG_FREERTOS_ASSERT_DISABLE= -CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 -CONFIG_FREERTOS_ISR_STACKSIZE=1536 -CONFIG_FREERTOS_LEGACY_HOOKS= -CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 -CONFIG_SUPPORT_STATIC_ALLOCATION= -CONFIG_TIMER_TASK_PRIORITY=1 -CONFIG_TIMER_TASK_STACK_DEPTH=2048 -CONFIG_TIMER_QUEUE_LENGTH=10 -CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 -CONFIG_FREERTOS_USE_TRACE_FACILITY= -CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS= -CONFIG_FREERTOS_DEBUG_INTERNALS= -CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y -CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y -CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE= - -# -# Heap memory debugging -# -CONFIG_HEAP_POISONING_DISABLED= -CONFIG_HEAP_POISONING_LIGHT=y -CONFIG_HEAP_POISONING_COMPREHENSIVE= -CONFIG_HEAP_TRACING= -CONFIG_HEAP_TASK_TRACKING= - -# -# libsodium -# -CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y - -# -# Log output -# -CONFIG_LOG_DEFAULT_LEVEL_NONE= -CONFIG_LOG_DEFAULT_LEVEL_ERROR=y -CONFIG_LOG_DEFAULT_LEVEL_WARN= -CONFIG_LOG_DEFAULT_LEVEL_INFO= -CONFIG_LOG_DEFAULT_LEVEL_DEBUG= -CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= -CONFIG_LOG_DEFAULT_LEVEL=1 -CONFIG_LOG_COLORS= - -# -# LWIP -# -CONFIG_L2_TO_L3_COPY= -CONFIG_LWIP_IRAM_OPTIMIZATION= -CONFIG_LWIP_MAX_SOCKETS=10 -CONFIG_LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS=y -CONFIG_USE_ONLY_LWIP_SELECT= -CONFIG_LWIP_SO_REUSE=y -CONFIG_LWIP_SO_REUSE_RXTOALL=y -CONFIG_LWIP_SO_RCVBUF=y -CONFIG_LWIP_IP_FRAG= -CONFIG_LWIP_IP_REASSEMBLY= -CONFIG_LWIP_STATS= -CONFIG_LWIP_ETHARP_TRUST_IP_MAC=y -CONFIG_ESP_GRATUITOUS_ARP=y -CONFIG_GARP_TMR_INTERVAL=60 -CONFIG_TCPIP_RECVMBOX_SIZE=32 -CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y -CONFIG_LWIP_DHCP_RESTORE_LAST_IP= - -# -# DHCP server -# -CONFIG_LWIP_DHCPS_LEASE_UNIT=60 -CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 -CONFIG_LWIP_AUTOIP= -CONFIG_LWIP_NETIF_LOOPBACK=y -CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 - -# -# TCP -# -CONFIG_LWIP_MAX_ACTIVE_TCP=16 -CONFIG_LWIP_MAX_LISTENING_TCP=16 -CONFIG_TCP_MAXRTX=12 -CONFIG_TCP_SYNMAXRTX=6 -CONFIG_TCP_MSS=1436 -CONFIG_TCP_MSL=60000 -CONFIG_TCP_SND_BUF_DEFAULT=5744 -CONFIG_TCP_WND_DEFAULT=5744 -CONFIG_TCP_RECVMBOX_SIZE=6 -CONFIG_TCP_QUEUE_OOSEQ=y -CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= -CONFIG_TCP_OVERSIZE_MSS=y -CONFIG_TCP_OVERSIZE_QUARTER_MSS= -CONFIG_TCP_OVERSIZE_DISABLE= - -# -# UDP -# -CONFIG_LWIP_MAX_UDP_PCBS=16 -CONFIG_UDP_RECVMBOX_SIZE=6 -CONFIG_TCPIP_TASK_STACK_SIZE=2560 -CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY= -CONFIG_TCPIP_TASK_AFFINITY_CPU0=y -CONFIG_TCPIP_TASK_AFFINITY_CPU1= -CONFIG_TCPIP_TASK_AFFINITY=0x0 -CONFIG_PPP_SUPPORT=y -CONFIG_PPP_NOTIFY_PHASE_SUPPORT= -CONFIG_PPP_PAP_SUPPORT=y -CONFIG_PPP_CHAP_SUPPORT=y -CONFIG_PPP_MSCHAP_SUPPORT=y -CONFIG_PPP_MPPE_SUPPORT=y -CONFIG_PPP_DEBUG_ON= - -# -# ICMP -# -CONFIG_LWIP_MULTICAST_PING= -CONFIG_LWIP_BROADCAST_PING= - -# -# LWIP RAW API -# -CONFIG_LWIP_MAX_RAW_PCBS=16 - -# -# SNTP -# -CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 -CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 - -# -# mbedTLS -# -CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y -CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC= -CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC= -CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC= -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN= -CONFIG_MBEDTLS_DEBUG= -CONFIG_MBEDTLS_ECP_RESTARTABLE= -CONFIG_MBEDTLS_CMAC_C= -CONFIG_MBEDTLS_HARDWARE_AES=y -CONFIG_MBEDTLS_HARDWARE_MPI= -CONFIG_MBEDTLS_HARDWARE_SHA= -CONFIG_MBEDTLS_HAVE_TIME=y -CONFIG_MBEDTLS_HAVE_TIME_DATE= -CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y -CONFIG_MBEDTLS_TLS_SERVER_ONLY= -CONFIG_MBEDTLS_TLS_CLIENT_ONLY= -CONFIG_MBEDTLS_TLS_DISABLED= -CONFIG_MBEDTLS_TLS_SERVER=y -CONFIG_MBEDTLS_TLS_CLIENT=y -CONFIG_MBEDTLS_TLS_ENABLED=y - -# -# TLS Key Exchange Methods -# -CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y -CONFIG_MBEDTLS_SSL_RENEGOTIATION=y -CONFIG_MBEDTLS_SSL_PROTO_SSL3= -CONFIG_MBEDTLS_SSL_PROTO_TLS1=y -CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y -CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y -CONFIG_MBEDTLS_SSL_PROTO_DTLS= -CONFIG_MBEDTLS_SSL_ALPN=y -CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y - -# -# Symmetric Ciphers -# -CONFIG_MBEDTLS_AES_C=y -CONFIG_MBEDTLS_CAMELLIA_C= -CONFIG_MBEDTLS_DES_C= -CONFIG_MBEDTLS_RC4_DISABLED=y -CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT= -CONFIG_MBEDTLS_RC4_ENABLED= -CONFIG_MBEDTLS_BLOWFISH_C= -CONFIG_MBEDTLS_XTEA_C= -CONFIG_MBEDTLS_CCM_C=y -CONFIG_MBEDTLS_GCM_C=y -CONFIG_MBEDTLS_RIPEMD160_C= - -# -# Certificates -# -CONFIG_MBEDTLS_PEM_PARSE_C=y -CONFIG_MBEDTLS_PEM_WRITE_C=y -CONFIG_MBEDTLS_X509_CRL_PARSE_C=y -CONFIG_MBEDTLS_X509_CSR_PARSE_C=y -CONFIG_MBEDTLS_ECP_C=y -CONFIG_MBEDTLS_ECDH_C=y -CONFIG_MBEDTLS_ECDSA_C=y -CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y -CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y -CONFIG_MBEDTLS_ECP_NIST_OPTIM=y - -# -# mDNS -# -CONFIG_MDNS_MAX_SERVICES=10 - -# -# ESP-MQTT Configurations -# -CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_TRANSPORT_SSL=y -CONFIG_MQTT_TRANSPORT_WEBSOCKET=y -CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y -CONFIG_MQTT_USE_CUSTOM_CONFIG= -CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED= -CONFIG_MQTT_CUSTOM_OUTBOX= - -# -# NVS -# - -# -# OpenSSL -# -CONFIG_OPENSSL_DEBUG= -CONFIG_OPENSSL_ASSERT_DO_NOTHING=y -CONFIG_OPENSSL_ASSERT_EXIT= - -# -# PThreads -# -CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 -CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=2048 -CONFIG_PTHREAD_STACK_MIN=768 -CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y -CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0= -CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1= -CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 -CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" - -# -# SPI Flash driver -# -CONFIG_SPI_FLASH_VERIFY_WRITE= -CONFIG_SPI_FLASH_ENABLE_COUNTERS= -CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y -CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y -CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS= -CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED= -CONFIG_SPI_FLASH_YIELD_DURING_ERASE= - -# -# SPIFFS Configuration -# -CONFIG_SPIFFS_MAX_PARTITIONS=3 - -# -# SPIFFS Cache Configuration -# -CONFIG_SPIFFS_CACHE=y -CONFIG_SPIFFS_CACHE_WR=y -CONFIG_SPIFFS_CACHE_STATS= -CONFIG_SPIFFS_PAGE_CHECK=y -CONFIG_SPIFFS_GC_MAX_RUNS=10 -CONFIG_SPIFFS_GC_STATS= -CONFIG_SPIFFS_PAGE_SIZE=256 -CONFIG_SPIFFS_OBJ_NAME_LEN=32 -CONFIG_SPIFFS_USE_MAGIC=y -CONFIG_SPIFFS_USE_MAGIC_LENGTH=y -CONFIG_SPIFFS_META_LENGTH=4 -CONFIG_SPIFFS_USE_MTIME=y - -# -# Debug Configuration -# -CONFIG_SPIFFS_DBG= -CONFIG_SPIFFS_API_DBG= -CONFIG_SPIFFS_GC_DBG= -CONFIG_SPIFFS_CACHE_DBG= -CONFIG_SPIFFS_CHECK_DBG= -CONFIG_SPIFFS_TEST_VISUALISATION= - -# -# TCP/IP Adapter -# -CONFIG_IP_LOST_TIMER_INTERVAL=120 -CONFIG_TCPIP_LWIP=y - -# -# Unity unit testing library -# -CONFIG_UNITY_ENABLE_FLOAT=y -CONFIG_UNITY_ENABLE_DOUBLE=y -CONFIG_UNITY_ENABLE_COLOR= -CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y -CONFIG_UNITY_ENABLE_FIXTURE= - -# -# Virtual file system -# -CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y -CONFIG_SUPPORT_TERMIOS=y - -# -# Wear Levelling -# -CONFIG_WL_SECTOR_SIZE_512= -CONFIG_WL_SECTOR_SIZE_4096=y -CONFIG_WL_SECTOR_SIZE=4096 - -# -# Wi-Fi Provisioning Manager -# -CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 diff --git a/src/sdkconfig.h b/src/sdkconfig.h deleted file mode 100644 index 85a459f1..00000000 --- a/src/sdkconfig.h +++ /dev/null @@ -1,397 +0,0 @@ -/* - * - * Automatically generated file; DO NOT EDIT. - * Espressif IoT Development Framework Configuration - * - */ -#define CONFIG_GATTC_ENABLE 1 -#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 -#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0 -#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 -#define CONFIG_MQTT_TRANSPORT_SSL 1 -#define CONFIG_BLE_SMP_ENABLE 1 -#define CONFIG_SPIRAM_TYPE_AUTO 1 -#define CONFIG_STACK_CHECK 1 -#define CONFIG_MB_SERIAL_TASK_PRIO 10 -#define CONFIG_MQTT_PROTOCOL_311 1 -#define CONFIG_TCP_RECVMBOX_SIZE 6 -#define CONFIG_LWIP_ETHARP_TRUST_IP_MAC 1 -#define CONFIG_BLE_SCAN_DUPLICATE 1 -#define CONFIG_STACK_CHECK_NORM 1 -#define CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS 10 -#define CONFIG_TCP_WND_DEFAULT 5744 -#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 -#define CONFIG_SW_COEXIST_ENABLE 1 -#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 -#define CONFIG_ESPTOOLPY_FLASHSIZE_4MB 1 -#define CONFIG_IPC_TASK_STACK_SIZE 1024 -#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 -#define CONFIG_FATFS_PER_FILE_CACHE 1 -#define CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY 1 -#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" -#define CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME 20 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 -#define CONFIG_UDP_RECVMBOX_SIZE 6 -#define CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT 1 -#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 -#define CONFIG_MBEDTLS_AES_C 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 -#define CONFIG_A2DP_SINK_TASK_STACK_SIZE 2048 -#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 -#define CONFIG_MBEDTLS_GCM_C 1 -#define CONFIG_ESPTOOLPY_FLASHSIZE "4MB" -#define CONFIG_SPIFFS_CACHE_WR 1 -#define CONFIG_SPIRAM_CACHE_WORKAROUND 1 -#define CONFIG_BROWNOUT_DET_LVL_SEL_0 1 -#define CONFIG_D0WD_PSRAM_CS_IO 16 -#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 -#define CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE 1 -#define CONFIG_BTDM_CONTROLLER_MODEM_SLEEP 1 -#define CONFIG_SPIFFS_CACHE 1 -#define CONFIG_INT_WDT 1 -#define CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL 1 -#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN 3 -#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 -#define CONFIG_BT_STACK_NO_LOG 1 -#define CONFIG_ESP_GRATUITOUS_ARP 1 -#define CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 -#define CONFIG_MBEDTLS_ECDSA_C 1 -#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 -#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 -#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE 0 -#define CONFIG_AWS_IOT_MQTT_PORT 8883 -#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 -#define CONFIG_MBEDTLS_ECDH_C 1 -#define CONFIG_SPIRAM_USE_CAPS_ALLOC 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 -#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 16 -#define CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 -#define CONFIG_MBEDTLS_SSL_ALPN 1 -#define CONFIG_MBEDTLS_PEM_WRITE_C 1 -#define CONFIG_BT_SPP_ENABLED 1 -#define CONFIG_BT_RESERVE_DRAM 0xdb5c -#define CONFIG_APP_COMPILE_TIME_DATE 1 -#define CONFIG_CXX_EXCEPTIONS 1 -#define CONFIG_D2WD_PSRAM_CLK_IO 9 -#define CONFIG_FATFS_FS_LOCK 0 -#define CONFIG_IP_LOST_TIMER_INTERVAL 120 -#define CONFIG_SPIFFS_META_LENGTH 4 -#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1 -#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 -#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 -#define CONFIG_AWS_IOT_MQTT_RX_BUF_LEN 512 -#define CONFIG_CAMERA_CORE1 1 -#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 -#define CONFIG_MB_SERIAL_BUF_SIZE 256 -#define CONFIG_CONSOLE_UART_BAUDRATE 115200 -#define CONFIG_SPIRAM_SUPPORT 1 -#define CONFIG_MFN56_1X 1 -#define CONFIG_LWIP_MAX_SOCKETS 10 -#define CONFIG_LWIP_NETIF_LOOPBACK 1 -#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread" -#define CONFIG_EMAC_TASK_PRIORITY 20 -#define CONFIG_TIMER_TASK_STACK_DEPTH 2048 -#define CONFIG_TCP_MSS 1436 -#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 -#define CONFIG_BTDM_CONTROLLER_MODE_BTDM 1 -#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF 3 -#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 -#define CONFIG_TCPIP_TASK_AFFINITY_CPU0 1 -#define CONFIG_FATFS_CODEPAGE 850 -#define CONFIG_SPIRAM_SPIWP_SD3_PIN 7 -#define CONFIG_ULP_COPROC_RESERVE_MEM 512 -#define CONFIG_LWIP_MAX_UDP_PCBS 16 -#define CONFIG_ESPTOOLPY_BAUD 921600 -#define CONFIG_INT_WDT_CHECK_CPU1 1 -#define CONFIG_ADC_CAL_LUT_ENABLE 1 -#define CONFIG_AWS_IOT_MQTT_TX_BUF_LEN 512 -#define CONFIG_FLASHMODE_DIO 1 -#define CONFIG_ESPTOOLPY_AFTER_RESET 1 -#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED 1 -#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 -#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-" -#define CONFIG_MBEDTLS_ECP_C 1 -#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1024 -#define CONFIG_MBEDTLS_RC4_DISABLED 1 -#define CONFIG_FATFS_LFN_STACK 1 -#define CONFIG_CONSOLE_UART_NUM 0 -#define CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED 120 -#define CONFIG_ARDUINO_EVENT_RUNNING_CORE 1 -#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE 1 -#define CONFIG_PTHREAD_STACK_MIN 768 -#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1 -#define CONFIG_TCP_OVERSIZE_MSS 1 -#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1 -#define CONFIG_CONSOLE_UART_DEFAULT 1 -#define CONFIG_A2DP_SOURCE_TASK_STACK_SIZE 2048 -#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384 -#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4 -#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 -#define CONFIG_AUTOSTART_ARDUINO 1 -#define CONFIG_ARDUINO_RUNNING_CORE 1 -#define CONFIG_PPP_CHAP_SUPPORT 1 -#define CONFIG_LOG_DEFAULT_LEVEL_ERROR 1 -#define CONFIG_TIMER_TASK_STACK_SIZE 4096 -#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 -#define CONFIG_SPIRAM_BANKSWITCH_ENABLE 1 -#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 -#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 -#define CONFIG_HTTPD_PURGE_BUF_LEN 32 -#define CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR 1 -#define CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 -#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 -#define CONFIG_MB_SERIAL_TASK_STACK_SIZE 2048 -#define CONFIG_MBEDTLS_PSK_MODES 1 -#define CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO 1 -#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 -#define CONFIG_EFUSE_MAX_BLK_LEN 192 -#define CONFIG_SPIFFS_USE_MAGIC 1 -#define CONFIG_OV7725_SUPPORT 1 -#define CONFIG_TCPIP_TASK_STACK_SIZE 2560 -#define CONFIG_BLUEDROID_PINNED_TO_CORE_0 1 -#define CONFIG_FATFS_CODEPAGE_850 1 -#define CONFIG_TASK_WDT 1 -#define CONFIG_MTMN_LITE_QUANT 1 -#define CONFIG_MAIN_TASK_STACK_SIZE 4096 -#define CONFIG_SPIFFS_PAGE_CHECK 1 -#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 -#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 -#define CONFIG_TASK_WDT_TIMEOUT_S 5 -#define CONFIG_INT_WDT_TIMEOUT_MS 300 -#define CONFIG_SCCB_HARDWARE_I2C 1 -#define CONFIG_ARDUINO_EVENT_RUN_CORE1 1 -#define CONFIG_ESPTOOLPY_FLASHMODE "dio" -#define CONFIG_BTC_TASK_STACK_SIZE 8192 -#define CONFIG_BLUEDROID_ENABLED 1 -#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 -#define CONFIG_ESPTOOLPY_BEFORE "default_reset" -#define CONFIG_ADC2_DISABLE_DAC 1 -#define CONFIG_HFP_ENABLE 1 -#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM 100 -#define CONFIG_ESP32_REV_MIN_0 1 -#define CONFIG_LOG_DEFAULT_LEVEL 1 -#define CONFIG_TIMER_QUEUE_LENGTH 10 -#define CONFIG_ESP32_REV_MIN 0 -#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT 1 -#define CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE 0 -#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1 -#define CONFIG_FATFS_TIMEOUT_MS 10000 -#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 -#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 -#define CONFIG_MBEDTLS_CCM_C 1 -#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 -#define CONFIG_ARDUHAL_PARTITION_SCHEME "default" -#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 -#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 -#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 -#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 -#define CONFIG_MDNS_MAX_SERVICES 10 -#define CONFIG_ULP_COPROC_ENABLED 1 -#define CONFIG_LSSH_SPARSE_MN_5 1 -#define CONFIG_HFP_AUDIO_DATA_PATH_PCM 1 -#define CONFIG_IDF_TARGET_ESP32 1 -#define CONFIG_EMAC_CHECK_LINK_PERIOD_MS 2000 -#define CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 -#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 -#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1 -#define CONFIG_AWS_IOT_SDK 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK 1 -#define CONFIG_DMA_RX_BUF_NUM 10 -#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_PSK 1 -#define CONFIG_TCP_SYNMAXRTX 6 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 -#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF 0 -#define CONFIG_HEAP_POISONING_LIGHT 1 -#define CONFIG_PYTHON "python" -#define CONFIG_SPIRAM_BANKSWITCH_RESERVE 8 -#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 -#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 -#define CONFIG_ESPTOOLPY_COMPRESSED 1 -#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" -#define CONFIG_MB_CONTROLLER_STACK_SIZE 4096 -#define CONFIG_TCP_SND_BUF_DEFAULT 5744 -#define CONFIG_GARP_TMR_INTERVAL 60 -#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 -#define CONFIG_TCP_MSL 60000 -#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 -#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 -#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT 20 -#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 -#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 -#define CONFIG_XTENSA_IMPL 1 -#define CONFIG_UNITY_ENABLE_FLOAT 1 -#define CONFIG_ESP32_WIFI_RX_BA_WIN 16 -#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 -#define CONFIG_SPIFFS_USE_MTIME 1 -#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN 0 -#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN 2 -#define CONFIG_PICO_PSRAM_CS_IO 10 -#define CONFIG_EMAC_TASK_STACK_SIZE 3072 -#define CONFIG_MB_QUEUE_LENGTH 20 -#define CONFIG_SW_COEXIST_PREFERENCE_VALUE 2 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 -#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 -#define CONFIG_OV2640_SUPPORT 1 -#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK 1 -#define CONFIG_PPP_SUPPORT 1 -#define CONFIG_SPIRAM_SPEED_40M 1 -#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 2048 -#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 -#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 -#define CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 -#define CONFIG_BROWNOUT_DET_LVL 0 -#define CONFIG_MBEDTLS_PEM_PARSE_C 1 -#define CONFIG_SPIFFS_GC_MAX_RUNS 10 -#define CONFIG_ARDUINO_RUN_CORE1 1 -#define CONFIG_ESP32_APPTRACE_DEST_NONE 1 -#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 -#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 -#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 -#define CONFIG_HTTPD_MAX_URI_LEN 512 -#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 -#define CONFIG_ARDUHAL_ESP_LOG 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 -#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 240 -#define CONFIG_MBEDTLS_HARDWARE_AES 1 -#define CONFIG_FREERTOS_HZ 1000 -#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 -#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 -#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 -#define CONFIG_BROWNOUT_DET 1 -#define CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES 10 -#define CONFIG_ESP32_XTAL_FREQ 0 -#define CONFIG_MONITOR_BAUD_115200B 1 -#define CONFIG_LOG_BOOTLOADER_LEVEL 0 -#define CONFIG_D2WD_PSRAM_CS_IO 10 -#define CONFIG_MBEDTLS_TLS_ENABLED 1 -#define CONFIG_LWIP_MAX_RAW_PCBS 16 -#define CONFIG_BTU_TASK_STACK_SIZE 4096 -#define CONFIG_SMP_ENABLE 1 -#define CONFIG_SPIRAM_SIZE -1 -#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1 -#define CONFIG_SPIFFS_MAX_PARTITIONS 3 -#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 -#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0 1 -#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 -#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 -#define CONFIG_MB_EVENT_QUEUE_TIMEOUT 20 -#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 -#define CONFIG_PPP_MPPE_SUPPORT 1 -#define CONFIG_ENABLE_ARDUINO_DEPENDS 1 -#define CONFIG_WARN_WRITE_STRINGS 1 -#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 -#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT 5 -#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF 2 -#define CONFIG_LOG_BOOTLOADER_LEVEL_NONE 1 -#define CONFIG_PARTITION_TABLE_MD5 1 -#define CONFIG_TCPIP_RECVMBOX_SIZE 32 -#define CONFIG_ESP32_DEFAULT_CPU_FREQ_240 1 -#define CONFIG_ESP32_XTAL_FREQ_AUTO 1 -#define CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST 1 -#define CONFIG_TCP_MAXRTX 12 -#define CONFIG_ESPTOOLPY_AFTER "hard_reset" -#define CONFIG_TCPIP_TASK_AFFINITY 0x0 -#define CONFIG_LWIP_SO_REUSE 1 -#define CONFIG_ARDUINO_UDP_RUN_CORE1 1 -#define CONFIG_DMA_TX_BUF_NUM 10 -#define CONFIG_LWIP_MAX_LISTENING_TCP 16 -#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 -#define CONFIG_WL_SECTOR_SIZE 4096 -#define CONFIG_ESP32_DEBUG_OCDAWARE 1 -#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 -#define CONFIG_TIMER_TASK_PRIORITY 1 -#define CONFIG_PPP_PAP_SUPPORT 1 -#define CONFIG_MBEDTLS_TLS_CLIENT 1 -#define CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 -#define CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI 1 -#define CONFIG_BT_ENABLED 1 -#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY 1 -#define CONFIG_D0WD_PSRAM_CLK_IO 17 -#define CONFIG_BT_SSP_ENABLED 1 -#define CONFIG_SW_COEXIST_PREFERENCE_BALANCE 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 -#define CONFIG_MONITOR_BAUD 115200 -#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT -1 -#define CONFIG_ESP32_DEBUG_STUBS_ENABLE 1 -#define CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT 30 -#define CONFIG_TCPIP_LWIP 1 -#define CONFIG_REDUCE_PHY_TX_POWER 1 -#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 -#define CONFIG_FREERTOS_CORETIMER_0 1 -#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 -#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" -#define CONFIG_MBEDTLS_HAVE_TIME 1 -#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 -#define CONFIG_TCP_QUEUE_OOSEQ 1 -#define CONFIG_FATFS_ALLOC_PREFER_EXTRAM 1 -#define CONFIG_GATTS_ENABLE 1 -#define CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE 0 -#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 -#define CONFIG_MBEDTLS_TLS_SERVER 1 -#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 -#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED 1 -#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 -#define CONFIG_SUPPORT_TERMIOS 1 -#define CONFIG_CLASSIC_BT_ENABLED 1 -#define CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK 1 -#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1 -#define CONFIG_IDF_TARGET "esp32" -#define CONFIG_WL_SECTOR_SIZE_4096 1 -#define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 -#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF -#define CONFIG_AWS_IOT_MQTT_HOST "" -#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 -#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 -#define CONFIG_MB_TIMER_INDEX 0 -#define CONFIG_SCAN_DUPLICATE_TYPE 0 -#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 -#define CONFIG_HFP_CLIENT_ENABLE 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 -#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 -#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32 -#define CONFIG_BT_ACL_CONNECTIONS 4 -#define CONFIG_FATFS_MAX_LFN 255 -#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 -#define CONFIG_ESPTOOLPY_BAUD_921600B 1 -#define CONFIG_BOOTLOADER_WDT_ENABLE 1 -#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 -#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 -#define CONFIG_A2DP_ENABLE 1 -#define CONFIG_MB_TIMER_GROUP 0 -#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 -#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 -#define CONFIG_SPIFFS_PAGE_SIZE 256 -#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 -#define CONFIG_ESP32_DPORT_WORKAROUND 1 -#define CONFIG_PPP_MSCHAP_SUPPORT 1 -#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 -#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 2048 -#define CONFIG_LWIP_SO_RCVBUF 1 -#define CONFIG_MB_TIMER_PORT_ENABLED 1 -#define CONFIG_DUPLICATE_SCAN_CACHE_SIZE 20 -#define CONFIG_ARDUINO_UDP_RUNNING_CORE 1 -#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200 -#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 -#define CONFIG_ESPTOOLPY_PORT "/dev/cu.usbserial-DO00EAB0" -#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1 -#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 -#define CONFIG_LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 -#define CONFIG_TASK_WDT_PANIC 1 -#define CONFIG_OV3660_SUPPORT 1 -#define CONFIG_UNITY_ENABLE_DOUBLE 1 -#define CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD 20 -#define CONFIG_BLUEDROID_PINNED_TO_CORE 0 -#define CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG 1 -#define CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR 1 -#define CONFIG_ESP32_WIFI_IRAM_OPT 1 -#define CONFIG_FATFS_API_ENCODING_ANSI_OEM 1 -#define CONFIG_ARDUINO_IDF_COMMIT "367c3c09c" -#define CONFIG_ARDUINO_IDF_BRANCH "release/v3.3" From 7074b3c2996d5445fd570104d7b6db2b3a62a9fc Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 4 Jul 2021 21:45:35 +0100 Subject: [PATCH 04/20] Warning fixes --- src/evse_monitor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evse_monitor.cpp b/src/evse_monitor.cpp index 5888b952..d0ca2716 100644 --- a/src/evse_monitor.cpp +++ b/src/evse_monitor.cpp @@ -164,7 +164,8 @@ EvseMonitor::EvseMonitor(OpenEVSEClass &openevse) : _boot_ready(EVSE_MONITOR_BOOT_READY), _session_complete(EVSE_MONITOR_SESSION_COMPLETE_MASK, EVSE_MONITOR_SESSION_COMPLETE_TRIGGER), _count(0), - _heartbeat(false) + _heartbeat(false), + _firmware_version("") #ifdef ENABLE_MCP9808 , _mcp9808() #endif From 0ec4151067c5ffdd246f173fb07b79c5d6fe3f4f Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 4 Jul 2021 21:45:52 +0100 Subject: [PATCH 05/20] Ignore the generated sdkconfig file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a3edd7c2..e26565b0 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,4 @@ lib/MicroTasks *.bin +sdkconfig From 6ced27b72c983d22f6200322b98a06ac50b02995 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 4 Jul 2021 21:46:22 +0100 Subject: [PATCH 06/20] `src_build_flags` no longer work --- platformio.ini | 56 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/platformio.ini b/platformio.ini index 54877a8e..b7963304 100644 --- a/platformio.ini +++ b/platformio.ini @@ -54,7 +54,7 @@ debug_flags = #-DENABLE_DEBUG_LCD #-DENABLE_DEBUG_MQTT #-DENABLE_DEBUG_EMONCMS - -DENABLE_DEBUG_WEB + #-DENABLE_DEBUG_WEB #-DENABLE_PROFILE src_build_flags = # -DENABLE_ASYNC_WIFI_SCAN @@ -74,7 +74,7 @@ build_flags = #-DCS_ENABLE_DEBUG #-DMBEDTLS_DEBUG_C -DMG_ENABLE_SNTP=1 - -DENABLE_DEBUG_MICROTASKS + #-DENABLE_DEBUG_MICROTASKS build_partitions = min_spiffs.csv neopixel_lib = adafruit/Adafruit NeoPixel@1.7.0 @@ -101,7 +101,6 @@ platform_packages = framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 monitor_flags = --filter=esp32_exception_decoder - --raw [env:openevse_nodemcu-32s] board = nodemcu-32s @@ -119,7 +118,8 @@ board = esp-wrover-kit lib_deps = ${common.lib_deps} ${common.neopixel_lib} -src_build_flags = +build_flags = + ${common.build_flags} ${common.version}.dev ${common.src_build_flags} ${common.debug_flags} @@ -130,22 +130,21 @@ src_build_flags = -DRED_LED=0 -DGREEN_LED=2 -DBLUE_LED=4 -build_flags = - ${common.build_flags} -DRX1=25 -DTX1=27 - -ggdb #upload_port = openevse.local #upload_speed = 921600 upload_protocol = ftdi lib_extra_dirs = lib +build_type = debug # export PLATFORMIO_UPLOAD_PORT=172.16.0.157 # export PLATFORMIO_UPLOAD_FLAGS="-p 3232" + [env:openevse_huzzah32_dev] board = featheresp32 -src_build_flags = - ${common.version}.dev +build_flags = + ${common.build_flags} ${common.src_build_flags} ${common.debug_flags} -DWIFI_LED=13 @@ -158,7 +157,8 @@ src_build_flags = [env:openevse_huzzah32] board = featheresp32 -src_build_flags = +build_flags = + ${common.build_flags} ${common.version} ${common.src_build_flags} -DWIFI_LED=13 @@ -171,7 +171,8 @@ src_build_flags = [env:openevse_featheresp32] board = featheresp32 -src_build_flags = +build_flags = + ${common.build_flags} ${common.version}.dev ${common.src_build_flags} ${common.debug_flags} @@ -186,7 +187,8 @@ lib_deps = ${common.lib_deps} ${common.neopixel_lib} adafruit/Adafruit MCP9808 Library @ 1.1.2 -src_build_flags = +build_flags = + ${common.build_flags} ${common.version} ${common.src_build_flags} ${common.debug_flags} @@ -200,14 +202,13 @@ src_build_flags = -DI2C_SDA=21 -DI2C_SCL=22 -DENABLE_MCP9808 -build_flags = - ${common.build_flags} -DTX1=16 [env:openevse_esp32-gateway] #For hardware older than RevE board = esp32-gateway -src_build_flags = +build_flags = + ${common.build_flags} ${common.version} ${common.src_build_flags} -DWIFI_LED=33 @@ -227,20 +228,39 @@ extends = env:openevse_esp32-gateway framework = arduino, espidf build_flags = ${common.build_flags} + ${common.version} + ${common.src_build_flags} + -DWIFI_LED=33 + -DWIFI_LED_ON_STATE=HIGH + -DWIFI_BUTTON=34 + -DWIFI_BUTTON_PRESSED_STATE=LOW + -DDEBUG_PORT=Serial + -DRAPI_PORT=Serial2 + -DENABLE_WIRED_ETHERNET + -DRANDOM_SEED_CHANNEL=1 -DRX2=16 -DTX2=32 board_build.extra_flags = "-DARDUINO_ESP32_GATEWAY=\'E\'" [env:openevse_esp32-heltec-wifi-lora-v2] board = heltec_wifi_lora_32_V2 -src_build_flags = +build_flags = + ${common.build_flags} + ${common.version} + ${common.src_build_flags} + -DWIFI_LED=33 + -DWIFI_LED_ON_STATE=HIGH + -DWIFI_BUTTON=34 + -DWIFI_BUTTON_PRESSED_STATE=LOW + -DDEBUG_PORT=Serial + -DRAPI_PORT=Serial2 + -DENABLE_WIRED_ETHERNET + -DRANDOM_SEED_CHANNEL=1 ${common.version}.dev ${common.src_build_flags} -DWIFI_LED=25 -DWIFI_BUTTON=2 -DWIFI_LED_ON_STATE=HIGH -DRAPI_PORT=Serial1 -build_flags = - ${common.build_flags} -DRX1=25 -DTX1=27 From e9daaca43eb50e6a508a93c3b10d1e8eb6a5c408 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 4 Jul 2021 21:46:53 +0100 Subject: [PATCH 07/20] Don't automatically start the WiFi, we do that in the firmware --- sdkconfig.defaults | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 90e65ab3..ea87d468 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -7,12 +7,12 @@ CONFIG_ARDUINO_EVENT_RUN_CORE1=y CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 CONFIG_ARDUINO_UDP_RUN_CORE1=y CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_DISABLE_HAL_LOCKS=y +#CONFIG_DISABLE_HAL_LOCKS=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y CONFIG_ARDUHAL_PARTITION_SCHEME="default" -CONFIG_AUTOCONNECT_WIFI=y -CONFIG_ARDUINO_SELECTIVE_WiFi=y +#CONFIG_AUTOCONNECT_WIFI=y +#CONFIG_ARDUINO_SELECTIVE_WiFi=y CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y From 9634bbe656b3893845b39ddb82ec7a61a268dab5 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Thu, 7 Oct 2021 22:03:35 +0100 Subject: [PATCH 08/20] Adding a space after the -D to make it more readable --- platformio.ini | 206 ++++++++++++++++++++++++------------------------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/platformio.ini b/platformio.ini index b7963304..3b2fa91c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,7 +29,7 @@ data_dir = src/data default_envs = openevse_wifi_v1 [common] -version = -DBUILD_TAG=4.0.1 +version = -D BUILD_TAG=4.0.1 monitor_speed = 115200 lib_deps = ArduinoJson@6.15.1 @@ -45,36 +45,36 @@ lib_deps = extra_scripts = scripts/extra_script.py debug_flags = -ggdb - -DENABLE_DEBUG - #-DENABLE_DEBUG_SCHEDULER - #-DENABLE_DEBUG_EVSE_MAN - #-DENABLE_DEBUG_EVSE_MONITOR - #-DENABLE_DEBUG_DIVERT - #-DENABLE_DEBUG_LED - #-DENABLE_DEBUG_LCD - #-DENABLE_DEBUG_MQTT - #-DENABLE_DEBUG_EMONCMS - #-DENABLE_DEBUG_WEB - #-DENABLE_PROFILE + -D ENABLE_DEBUG + #-D ENABLE_DEBUG_SCHEDULER + #-D ENABLE_DEBUG_EVSE_MAN + #-D ENABLE_DEBUG_EVSE_MONITOR + #-D ENABLE_DEBUG_DIVERT + #-D ENABLE_DEBUG_LED + #-D ENABLE_DEBUG_LCD + #-D ENABLE_DEBUG_MQTT + #-D ENABLE_DEBUG_EMONCMS + #-D ENABLE_DEBUG_WEB + #-D ENABLE_PROFILE src_build_flags = -# -DENABLE_ASYNC_WIFI_SCAN +# -D ENABLE_ASYNC_WIFI_SCAN build_flags = - -DARDUINO=250 - -DESP32 - -DCS_PLATFORM=CS_P_ESP32 - -DMG_ENABLE_SSL=1 - -DMG_ENABLE_HTTP_STREAMING_MULTIPART=1 - -DMG_SSL_MBED_DUMMY_RANDOM=1 - -DMG_SSL_IF=MG_SSL_IF_MBEDTLS - -DMG_SSL_IF_MBEDTLS_FREE_CERTS=1 - #-DMG_SSL_IF_MBEDTLS_MAX_FRAG_LEN=2048 - #-DARDUINO_MONGOOSE_DEFAULT_STREAM_BUFFER=2048 - #-DARDUINO_MONGOOSE_SEND_BUFFER_SIZE=2048 - #-DENABLE_DEBUG - #-DCS_ENABLE_DEBUG - #-DMBEDTLS_DEBUG_C - -DMG_ENABLE_SNTP=1 - #-DENABLE_DEBUG_MICROTASKS + -D ARDUINO=250 + -D ESP32 + -D CS_PLATFORM=CS_P_ESP32 + -D MG_ENABLE_SSL=1 + -D MG_ENABLE_HTTP_STREAMING_MULTIPART=1 + -D MG_SSL_MBED_DUMMY_RANDOM=1 + -D MG_SSL_IF=MG_SSL_IF_MBEDTLS + -D MG_SSL_IF_MBEDTLS_FREE_CERTS=1 + #-D MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN=2048 + #-D ARDUINO_MONGOOSE_DEFAULT_STREAM_BUFFER=2048 + #-D ARDUINO_MONGOOSE_SEND_BUFFER_SIZE=2048 + #-D ENABLE_DEBUG + #-D CS_ENABLE_DEBUG + #-D MBEDTLS_DEBUG_C + -D MG_ENABLE_SNTP=1 + #-D ENABLE_DEBUG_MICROTASKS build_partitions = min_spiffs.csv neopixel_lib = adafruit/Adafruit NeoPixel@1.7.0 @@ -109,9 +109,9 @@ src_build_flags = ${common.version}.dev ${common.src_build_flags} ${common.debug_flags} - -DWIFI_LED=LED_BUILTIN - -DWIFI_LED_ON_STATE=LOW - -DRAPI_PORT=Serial2 + -D WIFI_LED=LED_BUILTIN + -D WIFI_LED_ON_STATE=LOW + -D RAPI_PORT=Serial2 [env:openevse_esp-wrover-kit] board = esp-wrover-kit @@ -123,15 +123,15 @@ build_flags = ${common.version}.dev ${common.src_build_flags} ${common.debug_flags} - -DWIFI_BUTTON=2 - -DRAPI_PORT=Serial1 - -DNEO_PIXEL_PIN=18 - -DNEO_PIXEL_LENGTH=2 - -DRED_LED=0 - -DGREEN_LED=2 - -DBLUE_LED=4 - -DRX1=25 - -DTX1=27 + -D WIFI_BUTTON=2 + -D RAPI_PORT=Serial1 + -D NEO_PIXEL_PIN=18 + -D NEO_PIXEL_LENGTH=2 + -D RED_LED=0 + -D GREEN_LED=2 + -D BLUE_LED=4 + -D RX1=25 + -D TX1=27 #upload_port = openevse.local #upload_speed = 921600 upload_protocol = ftdi @@ -147,13 +147,13 @@ build_flags = ${common.build_flags} ${common.src_build_flags} ${common.debug_flags} - -DWIFI_LED=13 - -DWIFI_LED_ON_STATE=HIGH - -DWIFI_BUTTON=0 - -DWIFI_BUTTON_PRESSED_STATE=LOW - -DRAPI_PORT=Serial - -DDEBUG_PORT=Serial2 - -DSERIAL_RX_PULLUP_PIN=3 + -D WIFI_LED=13 + -D WIFI_LED_ON_STATE=HIGH + -D WIFI_BUTTON=0 + -D WIFI_BUTTON_PRESSED_STATE=LOW + -D RAPI_PORT=Serial + -D DEBUG_PORT=Serial2 + -D SERIAL_RX_PULLUP_PIN=3 [env:openevse_huzzah32] board = featheresp32 @@ -161,13 +161,13 @@ build_flags = ${common.build_flags} ${common.version} ${common.src_build_flags} - -DWIFI_LED=13 - -DWIFI_LED_ON_STATE=HIGH - -DWIFI_BUTTON=0 - -DWIFI_BUTTON_PRESSED_STATE=LOW - -DRAPI_PORT=Serial - -DDEBUG_PORT=Serial2 - -DSERIAL_RX_PULLUP_PIN=3 + -D WIFI_LED=13 + -D WIFI_LED_ON_STATE=HIGH + -D WIFI_BUTTON=0 + -D WIFI_BUTTON_PRESSED_STATE=LOW + -D RAPI_PORT=Serial + -D DEBUG_PORT=Serial2 + -D SERIAL_RX_PULLUP_PIN=3 [env:openevse_featheresp32] board = featheresp32 @@ -176,10 +176,10 @@ build_flags = ${common.version}.dev ${common.src_build_flags} ${common.debug_flags} - -DWIFI_LED=LED_BUILTIN - -DWIFI_BUTTON=LED_BUILTIN - -DRAPI_PORT=Serial2 - -DENABLE_DEBUG_LED + -D WIFI_LED=LED_BUILTIN + -D WIFI_BUTTON=LED_BUILTIN + -D RAPI_PORT=Serial2 + -D ENABLE_DEBUG_LED [env:openevse_wifi_v1] board = esp32dev @@ -192,17 +192,17 @@ build_flags = ${common.version} ${common.src_build_flags} ${common.debug_flags} - -DNEO_PIXEL_PIN=17 - -DNEO_PIXEL_LENGTH=2 - -DWIFI_BUTTON=0 - -DWIFI_BUTTON_PRESSED_STATE=LOW - -DRAPI_PORT=Serial - -DDEBUG_PORT=Serial1 - -DSERIAL_RX_PULLUP_PIN=3 - -DI2C_SDA=21 - -DI2C_SCL=22 - -DENABLE_MCP9808 - -DTX1=16 + -D NEO_PIXEL_PIN=17 + -D NEO_PIXEL_LENGTH=2 + -D WIFI_BUTTON=0 + -D WIFI_BUTTON_PRESSED_STATE=LOW + -D RAPI_PORT=Serial + -D DEBUG_PORT=Serial1 + -D SERIAL_RX_PULLUP_PIN=3 + -D I2C_SDA=21 + -D I2C_SCL=22 + -D ENABLE_MCP9808 + -D TX1=16 [env:openevse_esp32-gateway] #For hardware older than RevE @@ -211,14 +211,14 @@ build_flags = ${common.build_flags} ${common.version} ${common.src_build_flags} - -DWIFI_LED=33 - -DWIFI_LED_ON_STATE=HIGH - -DWIFI_BUTTON=34 - -DWIFI_BUTTON_PRESSED_STATE=LOW - -DDEBUG_PORT=Serial - -DRAPI_PORT=Serial2 - -DENABLE_WIRED_ETHERNET - -DRANDOM_SEED_CHANNEL=1 + -D WIFI_LED=33 + -D WIFI_LED_ON_STATE=HIGH + -D WIFI_BUTTON=34 + -D WIFI_BUTTON_PRESSED_STATE=LOW + -D DEBUG_PORT=Serial + -D RAPI_PORT=Serial2 + -D ENABLE_WIRED_ETHERNET + -D RANDOM_SEED_CHANNEL=1 # https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/examples/ETH_LAN8720/ETH_LAN8720.ino [env:openevse_esp32-gateway-e] @@ -230,17 +230,17 @@ build_flags = ${common.build_flags} ${common.version} ${common.src_build_flags} - -DWIFI_LED=33 - -DWIFI_LED_ON_STATE=HIGH - -DWIFI_BUTTON=34 - -DWIFI_BUTTON_PRESSED_STATE=LOW - -DDEBUG_PORT=Serial - -DRAPI_PORT=Serial2 - -DENABLE_WIRED_ETHERNET - -DRANDOM_SEED_CHANNEL=1 - -DRX2=16 - -DTX2=32 -board_build.extra_flags = "-DARDUINO_ESP32_GATEWAY=\'E\'" + -D WIFI_LED=33 + -D WIFI_LED_ON_STATE=HIGH + -D WIFI_BUTTON=34 + -D WIFI_BUTTON_PRESSED_STATE=LOW + -D DEBUG_PORT=Serial + -D RAPI_PORT=Serial2 + -D ENABLE_WIRED_ETHERNET + -D RANDOM_SEED_CHANNEL=1 + -D RX2=16 + -D TX2=32 +board_build.extra_flags = "-D ARDUINO_ESP32_GATEWAY=\'E\'" [env:openevse_esp32-heltec-wifi-lora-v2] board = heltec_wifi_lora_32_V2 @@ -248,19 +248,19 @@ build_flags = ${common.build_flags} ${common.version} ${common.src_build_flags} - -DWIFI_LED=33 - -DWIFI_LED_ON_STATE=HIGH - -DWIFI_BUTTON=34 - -DWIFI_BUTTON_PRESSED_STATE=LOW - -DDEBUG_PORT=Serial - -DRAPI_PORT=Serial2 - -DENABLE_WIRED_ETHERNET - -DRANDOM_SEED_CHANNEL=1 + -D WIFI_LED=33 + -D WIFI_LED_ON_STATE=HIGH + -D WIFI_BUTTON=34 + -D WIFI_BUTTON_PRESSED_STATE=LOW + -D DEBUG_PORT=Serial + -D RAPI_PORT=Serial2 + -D ENABLE_WIRED_ETHERNET + -D RANDOM_SEED_CHANNEL=1 ${common.version}.dev ${common.src_build_flags} - -DWIFI_LED=25 - -DWIFI_BUTTON=2 - -DWIFI_LED_ON_STATE=HIGH - -DRAPI_PORT=Serial1 - -DRX1=25 - -DTX1=27 + -D WIFI_LED=25 + -D WIFI_BUTTON=2 + -D WIFI_LED_ON_STATE=HIGH + -D RAPI_PORT=Serial1 + -D RX1=25 + -D TX1=27 From 70a181214bda90bf7c8a9a41c1a3de68f3a0c523 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Thu, 17 Mar 2022 21:09:23 +0000 Subject: [PATCH 09/20] Merge of #325 as that is needed for the latest ArduinoOcpp library --- platformio.ini | 12 +- src/MongooseOcppSocketClient.cpp | 8 +- src/MongooseOcppSocketClient.h | 8 +- src/app_config.cpp | 22 + src/app_config.h | 13 + src/evse_man.h | 4 +- src/input.cpp | 4 + src/main.cpp | 5 +- src/ocpp.cpp | 389 +++++++++-------- src/ocpp.h | 25 +- src/rfid.cpp | 460 ++++++++++++++++++++ src/rfid.h | 79 ++++ src/web_server.cpp | 29 ++ src/web_static/web_server.arduinoocpp.png.h | 106 +++++ src/web_static/web_server.home.html.h | 6 +- src/web_static/web_server.home.js.h | 6 +- src/web_static/web_server.lib.js.h | 6 +- src/web_static/web_server.term.js.h | 2 +- src/web_static/web_server_static_files.h | 2 + 19 files changed, 969 insertions(+), 217 deletions(-) create mode 100644 src/rfid.cpp create mode 100644 src/rfid.h create mode 100644 src/web_static/web_server.arduinoocpp.png.h diff --git a/platformio.ini b/platformio.ini index a2b0cd3b..8c7703c5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -32,8 +32,8 @@ default_envs = openevse_wifi_v1 version = -D BUILD_TAG=4.1.2 monitor_speed = 115200 lib_deps = - bblanchon/ArduinoJson@6.15.1 - jeremypoulter/ArduinoMongoose@0.0.17 + bblanchon/ArduinoJson@6.19.1 + jeremypoulter/ArduinoMongoose@0.0.18 jeremypoulter/Micro Debug@0.0.5 jeremypoulter/ConfigJson@0.0.4 jeremypoulter/OpenEVSE@0.0.11 @@ -42,7 +42,8 @@ lib_deps = jeremypoulter/MicroTasks@0.0.2 erropix/ESP32 AnalogWrite@0.2 lorol/LittleFS_esp32@1.0.5 - matth-x/ArduinoOcpp@0.0.4 + ; matth-x/ArduinoOcpp@0.0.4 + https://github.com/matth-x/ArduinoOcpp.git#d4f705caf10bcdd1311512664a2d8c15c4a2db5d lib_ignore = WebSockets ; ArduinoOcpp: don't compile built-in WS library extra_scripts = scripts/extra_script.py debug_flags = @@ -82,7 +83,8 @@ build_flags = #-D ENABLE_DEBUG_MICROTASKS -D CS_PLATFORM=CS_P_ESP32 -D AO_CUSTOM_WS ; ArduinoOcpp: don't use built-in WS library - -D AO_CUSTOM_DIAGNOSTICS ; ArduinoOcpp: don't do internal logging + -D AO_CUSTOM_CONSOLE ; ArduinoOcpp: use custom debug out + -D AO_DBG_LEVEL=AO_DL_WARN #-D ENABLE_DEBUG #-D ENABLE_DEBUG_MONGOOSE_HTTP_CLIENT -D RAPI_MAX_COMMANDS=20 @@ -260,7 +262,7 @@ build_flags = -D RANDOM_SEED_CHANNEL=1 -D RX2=16 -D TX2=32 -board_build.extra_flags = "-D ARDUINO_ESP32_GATEWAY=\'E\'" +board_build.extra_flags = "-DARDUINO_ESP32_GATEWAY=\'E\'" upload_speed = 921600 [env:openevse_esp32-heltec-wifi-lora-v2] diff --git a/src/MongooseOcppSocketClient.cpp b/src/MongooseOcppSocketClient.cpp index 21f094eb..0e3b60ae 100644 --- a/src/MongooseOcppSocketClient.cpp +++ b/src/MongooseOcppSocketClient.cpp @@ -3,6 +3,10 @@ * Created: 2021-04-10 */ +#if defined(ENABLE_DEBUG) && !defined(ENABLE_DEBUG_OCPPSOCKET) +#undef ENABLE_DEBUG +#endif + #include "MongooseOcppSocketClient.h" #include "net_manager.h" #include "debug.h" @@ -203,7 +207,7 @@ void MongooseOcppSocketClient::reconnect(const String &ws_url) { maintainWsConn(); } -bool MongooseOcppSocketClient::sendTXT(String &out) { +bool MongooseOcppSocketClient::sendTXT(std::string &out) { /* * Check if the EVSE is able to send the data at the moment. This fuzzy check can be useful to * to diagnose connection problems at upper layers. It gives no guarantee that packages will @@ -243,7 +247,7 @@ bool MongooseOcppSocketClient::isValidUrl(const char *url) { if (url[1] != 'S' && url[1] != 's') return false; - if (url[2] == 'S' && url[2] == 's') { + if (url[2] == 'S' || url[2] == 's') { if (url[3] != ':') return false; //else: passed diff --git a/src/MongooseOcppSocketClient.h b/src/MongooseOcppSocketClient.h index c1662a00..f43056d2 100644 --- a/src/MongooseOcppSocketClient.h +++ b/src/MongooseOcppSocketClient.h @@ -32,17 +32,17 @@ class MongooseOcppSocketClient : public ArduinoOcpp::OcppSocket { MongooseOcppSocketClient(const String &ws_url); - ~MongooseOcppSocketClient(); + ~MongooseOcppSocketClient() override; - void loop(); + void loop() override; void maintainWsConn(); - bool sendTXT(String &out); + bool sendTXT(std::string &out) override; bool receiveTXT(const char* msg, size_t len); - void setReceiveTXTcallback(ArduinoOcpp::ReceiveTXTcallback &receiveTXT) { + void setReceiveTXTcallback(ArduinoOcpp::ReceiveTXTcallback &receiveTXT) override { this->receiveTXTcallback = receiveTXT; }; //ReceiveTXTcallback is defined in OcppServer.h diff --git a/src/app_config.cpp b/src/app_config.cpp index 7c2a8baf..ce5b9844 100644 --- a/src/app_config.cpp +++ b/src/app_config.cpp @@ -84,6 +84,11 @@ String tesla_vehicle_id; uint8_t led_brightness; #endif +// RFID storage +String rfid_storage; + +long max_current_soft; + String esp_hostname_default = "openevse-"+ESPAL.getShortId(); void config_changed(String name); @@ -149,10 +154,15 @@ ConfigOpt *opts[] = new ConfigOptDefenition(tesla_expires_in, -1, "tesla_expires_in", "tx"), new ConfigOptDefenition(tesla_vehicle_id, "", "tesla_vehicle_id", "ti"), +// RFID storage + new ConfigOptDefenition(rfid_storage, "", "rfid_storage", "rs"), + #if RGB_LED // LED brightness new ConfigOptDefenition(led_brightness, LED_DEFAULT_BRIGHTNESS, "led_brightness", "lb"), #endif +// RFID storage + new ConfigOptDefenition(rfid_storage, "", "rfid_storage", "rs"), // Flags &flagsOpt, @@ -170,6 +180,7 @@ ConfigOpt *opts[] = new ConfigOptVirtualBool(flagsOpt, CONFIG_SERVICE_OCPP, CONFIG_SERVICE_OCPP, "ocpp_enabled", "ope"), new ConfigOptVirtualBool(flagsOpt, CONFIG_OCPP_ACCESS_SUSPEND, CONFIG_OCPP_ACCESS_SUSPEND, "ocpp_suspend_evse", "ops"), new ConfigOptVirtualBool(flagsOpt, CONFIG_OCPP_ACCESS_ENERGIZE, CONFIG_OCPP_ACCESS_ENERGIZE, "ocpp_energize_plug", "opn"), + new ConfigOptVirtualBool(flagsOpt, CONFIG_RFID, CONFIG_RFID, "rfid_enabled", "rf"), new ConfigOptVirtualMqttProtocol(flagsOpt, "mqtt_protocol", "mprt"), new ConfigOptVirtualChargeMode(flagsOpt, "charge_mode", "chmd") }; @@ -384,6 +395,17 @@ config_save_ohm(bool enable, String qohm) config.commit(); } +void +config_save_rfid(bool enable, String storage){ + uint32_t newflags = flags & ~CONFIG_RFID; + if(enable) { + newflags |= CONFIG_RFID; + } + config.set("flags", newflags); + config.set("rfid_storage", rfid_storage); + config.commit(); +} + void config_save_flags(uint32_t newFlags) { config.set("flags", newFlags); diff --git a/src/app_config.h b/src/app_config.h index 32c60d36..d274663d 100644 --- a/src/app_config.h +++ b/src/app_config.h @@ -51,6 +51,9 @@ extern String ocpp_chargeBoxId; extern String ocpp_idTag; extern String tx_start_point; +// RFID storage +extern String rfid_storage; + // Time extern String time_zone; @@ -77,6 +80,7 @@ extern uint32_t flags; #define CONFIG_OCPP_ACCESS_SUSPEND (1 << 15) #define CONFIG_OCPP_ACCESS_ENERGIZE (1 << 16) #define CONFIG_VEHICLE_RANGE_MILES (1 << 17) +#define CONFIG_RFID (1 << 18) inline bool config_emoncms_enabled() { return CONFIG_SERVICE_EMONCMS == (flags & CONFIG_SERVICE_EMONCMS); @@ -133,6 +137,10 @@ inline bool config_pause_uses_disabled() { inline bool config_vehicle_range_miles() { return CONFIG_VEHICLE_RANGE_MILES == (flags & CONFIG_VEHICLE_RANGE_MILES); } + +inline bool config_rfid_enabled() { + return CONFIG_RFID == (flags & CONFIG_RFID); +} // Ohm Connect Settings extern String ohm; @@ -178,6 +186,11 @@ extern void config_save_wifi(String qsid, String qpass); // ------------------------------------------------------------------- extern void config_save_ohm(bool enable, String qohm); +// ------------------------------------------------------------------- +// Save RFID settings +// ------------------------------------------------------------------- +extern void config_save_rfid(bool enable, String storage); + // ------------------------------------------------------------------- // Save the flags // ------------------------------------------------------------------- diff --git a/src/evse_man.h b/src/evse_man.h index dba7bc1b..80e69607 100644 --- a/src/evse_man.h +++ b/src/evse_man.h @@ -32,6 +32,7 @@ typedef uint32_t EvseClient; #define EvseClient_OpenEVSE_Error EVC(EvseClient_Vendor_OpenEVSE, 0x0007) #define EvseClient_OpenEVSE_Ohm EVC(EvseClient_Vendor_OpenEVSE, 0x0008) #define EvseClient_OpenEVSE_Ocpp EVC(EvseClient_Vendor_OpenEVSE, 0x0009) +#define EvseClient_OpenEVSE_RFID EVC(EvseClient_Vendor_OpenEVSE, 0x000A) #define EvseClient_OpenEnergyMonitor_DemandShaper EVC(EvseClient_Vendor_OpenEnergyMonitor, 0x0001) @@ -44,6 +45,7 @@ typedef uint32_t EvseClient; #define EvseManager_Priority_API 500 #define EvseManager_Priority_Ohm 500 #define EvseManager_Priority_Manual 1000 +#define EvseManager_Priority_RFID 1030 #define EvseManager_Priority_Ocpp 1050 #define EvseManager_Priority_Limit 1100 #define EvseManager_Priority_Error 10000 @@ -53,7 +55,7 @@ typedef uint32_t EvseClient; #define EVSE_VEHICLE_ETA (1 << 2) #ifndef EVSE_MANAGER_MAX_CLIENT_CLAIMS -#define EVSE_MANAGER_MAX_CLIENT_CLAIMS 10 +#define EVSE_MANAGER_MAX_CLIENT_CLAIMS 11 #endif // !EVSE_MANAGER_MAX_CLIENT_CLAIMS class EvseProperties : virtual public JsonSerialize<512> diff --git a/src/input.cpp b/src/input.cpp index a97e387b..db756578 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -17,6 +17,7 @@ #include "emoncms.h" #include "tesla_client.h" #include "manual.h" +#include "rfid.h" #include "LedManagerTask.h" @@ -90,6 +91,9 @@ class InputTask : public MicroTasks::Task void create_rapi_json(JsonDocument &doc) { + if(config_rfid_enabled()) { + doc["authenticated"] = rfid.getAuthenticatedTag(); + } doc["amp"] = evse.getAmps() * AMPS_SCALE_FACTOR; doc["voltage"] = evse.getVoltage() * VOLTS_SCALE_FACTOR; doc["pilot"] = evse.getChargeCurrent(); diff --git a/src/main.cpp b/src/main.cpp index 8fb9c452..0e46d10d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include "emonesp.h" #include "app_config.h" @@ -50,6 +49,7 @@ #include "tesla_client.h" #include "event.h" #include "ocpp.h" +#include "rfid.h" #include "LedManagerTask.h" #include "event_log.h" @@ -117,6 +117,7 @@ void setup() scheduler.begin(); lcd.begin(evse, scheduler, manual); + rfid.begin(evse); ledManager.begin(evse); // Initialise the WiFi @@ -138,7 +139,7 @@ void setup() input_setup(); - ocpp.begin(evse, lcd, eventLog); + ocpp.begin(evse, lcd, eventLog, rfid); lcd.display(F("OpenEVSE WiFI"), 0, 0, 0, LCD_CLEAR_LINE); lcd.display(currentfirmware, 0, 1, 5 * 1000, LCD_CLEAR_LINE); diff --git a/src/ocpp.cpp b/src/ocpp.cpp index d8b84293..e8fb9589 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -5,23 +5,25 @@ #include "ocpp.h" -#include "app_config.h" - -#include // Facade for ArduinoOcpp -#include // define behavior for incoming req messages - -#include "http_update.h" - +#include +#include #include +#include -#include "emonesp.h" //for VOLTAGE_DEFAULT +#include "app_config.h" +#include "http_update.h" +#include "emonesp.h" #define LCD_DISPLAY(X) if (lcd) lcd->display((X), 0, 1, 5 * 1000, LCD_CLEAR_LINE); ArduinoOcppTask *ArduinoOcppTask::instance = NULL; -ArduinoOcppTask::ArduinoOcppTask() : MicroTasks::Task() /*, bootReadyCallback(MicroTasksCallback([](){})) */ { +void dbug_wrapper(const char *msg) { + DBUG(msg); +} + +ArduinoOcppTask::ArduinoOcppTask() : MicroTasks::Task() { } @@ -30,58 +32,94 @@ ArduinoOcppTask::~ArduinoOcppTask() { instance = NULL; } -void ArduinoOcppTask::begin(EvseManager &evse, LcdTask &lcd, EventLog &eventLog) { +void ArduinoOcppTask::begin(EvseManager &evse, LcdTask &lcd, EventLog &eventLog, RfidTask &rfid) { this->evse = &evse; this->lcd = &lcd; this->eventLog = &eventLog; + this->rfid = &rfid; - initializeArduinoOcpp(); - loadEvseBehavior(); + ao_set_console_out(dbug_wrapper); + + reconfigure(); instance = this; //cannot be in constructer because object is invalid before .begin() MicroTask.startTask(this); } -void ArduinoOcppTask::initializeArduinoOcpp() { +void ArduinoOcppTask::reconfigure() { - if (config_ocpp_enabled() && !arduinoOcppInitialized) { + if (arduinoOcppInitialized) { + arduinoOcppInitialized = false; + if (!config_ocpp_enabled() && ocppSocket) { + String emptyUrl = String(""); + ocppSocket->reconnect(emptyUrl); + } + OCPP_deinitialize(); + } + + if (config_ocpp_enabled()) { String url = getCentralSystemUrl(); - if (url.isEmpty()) { - return; + if (ocppSocket) { + ocppSocket->reconnect(url); + } else { + ocppSocket = new MongooseOcppSocketClient(url); } - ocppSocket = new MongooseOcppSocketClient(url); + initializeArduinoOcpp(); + + arduinoOcppInitialized = true; + } +} - ArduinoOcpp::OcppClock clockAdapter = [] () { - timeval time_now; - gettimeofday(&time_now, NULL); - return (ArduinoOcpp::otime_t) time_now.tv_sec; - }; +void ArduinoOcppTask::initializeArduinoOcpp() { - OCPP_initialize(ocppSocket, (float) VOLTAGE_DEFAULT, ArduinoOcpp::FilesystemOpt::Use, clockAdapter); + String url = getCentralSystemUrl(); - initializeDiagnosticsService(); - initializeFwService(); + if (url.isEmpty()) { + return; + } - DynamicJsonDocument *evseDetailsDoc = new DynamicJsonDocument(JSON_OBJECT_SIZE(6)); - JsonObject evseDetails = evseDetailsDoc->to(); - evseDetails["chargePointModel"] = "Advanced Series"; - //evseDetails["chargePointSerialNumber"] = "TODO"; //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/218 - evseDetails["chargePointVendor"] = "OpenEVSE"; - evseDetails["firmwareVersion"] = evse->getFirmwareVersion(); - //evseDetails["meterSerialNumber"] = "TODO"; - //evseDetails["meterType"] = "TODO"; - //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/219 + ocppSocket = new MongooseOcppSocketClient(url); - bootNotification(evseDetailsDoc, [this](JsonObject payload) { //ArduinoOcpp will delete evseDetailsDoc - LCD_DISPLAY("OCPP connected!"); - }); + ArduinoOcpp::OcppClock clockAdapter = [] () { + timeval time_now; + gettimeofday(&time_now, NULL); + return (ArduinoOcpp::otime_t) time_now.tv_sec; + }; - arduinoOcppInitialized = true; - } + OCPP_initialize(*ocppSocket, (float) VOLTAGE_DEFAULT, ArduinoOcpp::FilesystemOpt::Use, clockAdapter); + + loadEvseBehavior(); + initializeDiagnosticsService(); + initializeFwService(); + + /* + * BootNotification: provide the OCPP backend with relevant data about the OpenEVSE + * see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/219 + */ + String evseFirmwareVersion = String(evse->getFirmwareVersion()); + + DynamicJsonDocument *evseDetailsDoc = new DynamicJsonDocument( + JSON_OBJECT_SIZE(5) + + serial.length() + 1 + + currentfirmware.length() + 1 + + evseFirmwareVersion.length() + 1); + JsonObject evseDetails = evseDetailsDoc->to(); + evseDetails["chargePointModel"] = "Advanced Series"; + evseDetails["chargePointSerialNumber"] = serial; //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/218 + evseDetails["chargePointVendor"] = "OpenEVSE"; + evseDetails["firmwareVersion"] = currentfirmware; + evseDetails["meterSerialNumber"] = evseFirmwareVersion; + + bootNotification(evseDetailsDoc, [this](JsonObject payload) { //ArduinoOcpp will delete evseDetailsDoc + LCD_DISPLAY("OCPP connected!"); + }); + + ocppTxIdDisplay = getTransactionId(); + ocppSessionDisplay = getSessionIdTag(); } void ArduinoOcppTask::setup() { @@ -90,10 +128,6 @@ void ArduinoOcppTask::setup() { void ArduinoOcppTask::loadEvseBehavior() { - if (!arduinoOcppInitialized) { - return; - } - /* * Synchronize OpenEVSE data with OCPP-library data */ @@ -111,11 +145,10 @@ void ArduinoOcppTask::loadEvseBehavior() { setOnChargingRateLimitChange([this] (float limit) { //limit = maximum charge rate in Watts charging_limit = limit; - this->updateEvseClaim(); }); setConnectorPluggedSampler([this] () { - return (bool) evse->isConnected(); + return (bool) evse->isVehicleConnected(); }); setEvRequestsEnergySampler([this] () { @@ -132,6 +165,7 @@ void ArduinoOcppTask::loadEvseBehavior() { addConnectorErrorCodeSampler([this] () { if (evse->getEvseState() == OPENEVSE_STATE_GFI_FAULT || + evse->getEvseState() == OPENEVSE_STATE_GFI_SELF_TEST_FAILED || evse->getEvseState() == OPENEVSE_STATE_NO_EARTH_GROUND || evse->getEvseState() == OPENEVSE_STATE_DIODE_CHECK_FAILED) { return "GroundFailure"; @@ -154,79 +188,66 @@ void ArduinoOcppTask::loadEvseBehavior() { }); addConnectorErrorCodeSampler([this] () { - if (evse->getEvseState() == OPENEVSE_STATE_STUCK_RELAY || - evse->getEvseState() == OPENEVSE_STATE_GFI_SELF_TEST_FAILED) { - return "InternalError"; + if (evse->getEvseState() == OPENEVSE_STATE_STUCK_RELAY) { + return "PowerSwitchFailure"; } return (const char *) NULL; }); + addConnectorErrorCodeSampler([this] () { + if (rfid->communicationFails()) { + return "ReaderFailure"; + } + return (const char *) nullptr; + }); + /* * CP behavior definition: How will plugging and unplugging the EV start or stop OCPP transactions */ - onVehicleConnect = [this] () { - if (getTransactionId() < 0 && isAvailable()) { - if (!ocpp_idTag.isEmpty()) { - authorize(ocpp_idTag, [this] (JsonObject payload) { - if (idTagIsAccepted(payload)) { - startTransaction([this] (JsonObject payload) { - this->updateEvseClaim(); - }, [this] () { - LCD_DISPLAY("Central system error"); - }); - } else { - LCD_DISPLAY("ID card not recognized"); - } - }, [this] () { - LCD_DISPLAY("OCPP timeout"); - }); + onIdTagInput = [this] (const String& idInput) { + if (!config_ocpp_enabled()) { + return false; + } + if (idInput.isEmpty()) { + DBUGLN("[ocpp] empty idTag"); + return true; + } + if (!isAvailable() || !arduinoOcppInitialized) { + LCD_DISPLAY("OCPP inoperative"); + DBUGLN(F("[ocpp] present card but inoperative")); + return true; + } + const char *sessionIdTag = getSessionIdTag(); + if (sessionIdTag) { + //currently in an authorized session + if (idInput.equals(sessionIdTag)) { + //NFC card matches + endSession(); + LCD_DISPLAY("Card accepted"); } else { - startTransaction([this] (JsonObject payload) { - if (!idTagIsRejected(payload)) { - this->updateEvseClaim(); - } else { - LCD_DISPLAY("ID tag required"); - } - this->updateEvseClaim(); - }, [this] () { - LCD_DISPLAY("Central system error"); - }); + LCD_DISPLAY("Card not recognized"); } - - } - this->updateEvseClaim(); - }; - - setOnRemoteStartTransactionSendConf([this] (JsonObject payload) { - if (!operationIsAccepted(payload)){ - //RemoteStartTransaction rejected! Do nothing - return; + } else { + //idle mode + LCD_DISPLAY("Card read"); + String idInputCapture = idInput; + authorize(idInput.c_str(), [this, idInputCapture] (JsonObject payload) { + if (idTagIsAccepted(payload)) { + beginSession(idInputCapture.c_str()); + LCD_DISPLAY("Card accepted"); + } else { + LCD_DISPLAY("Card not recognized"); + } + }, [this] () { + LCD_DISPLAY("OCPP timeout"); + }); } - startTransaction([this] (JsonObject payload) { - this->updateEvseClaim(); - }, [this] () { - LCD_DISPLAY("Central system error"); - }); - }); - - onVehicleDisconnect = [this] () { - if (getTransactionId() >= 0) { - stopTransaction(); - } - this->updateEvseClaim(); + return true; }; - setOnRemoteStopTransactionSendConf([this](JsonObject payload) { - if (!operationIsAccepted(payload)){ - //RemoteStopTransaction rejected! There is no transaction with given ID. Do nothing - return; - } - - stopTransaction(); - this->updateEvseClaim(); - }); + rfid->setOnCardScanned(&onIdTagInput); setOnResetReceiveReq([this] (JsonObject payload) { const char *type = payload["type"] | "Soft"; @@ -245,42 +266,80 @@ void ArduinoOcppTask::loadEvseBehavior() { //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/230 return false; }); - - updateEvseClaim(); } unsigned long ArduinoOcppTask::loop(MicroTasks::WakeReason reason) { if (arduinoOcppInitialized) { - if (config_ocpp_enabled()) { - OCPP_loop(); - } else { - //The OCPP function has been activated and then deactivated again. - - ArduinoOcpp::ocppEngine_loop(); //There could be remaining operations in the OCPP-queue. I will add the OCPP_unitialize() soon as a better solution to this - return 0; - } - } else { - if (config_ocpp_enabled()) { - initializeArduinoOcpp(); - loadEvseBehavior(); - } + OCPP_loop(); + } + if (arduinoOcppInitialized != config_ocpp_enabled()) { + reconfigure(); return 50; } - if (evse->isVehicleConnected() && !vehicleConnected) { - vehicleConnected = evse->isVehicleConnected(); - - if (strcmp(tx_start_point.c_str(), "tx_only_remote")) { - //tx_start_point is different from tx_only_remote. Plugging an EV starts a transaction - onVehicleConnect(); + if (arduinoOcppInitialized) { + + if (evse->isVehicleConnected() && !vehicleConnected) { + //vehicle plugged + if (!getSessionIdTag()) { + //vehicle plugged before authorization + if (config_rfid_enabled()) { + LCD_DISPLAY("Need card"); + } else { + //no RFID reader --> Auto-Authorize or RemoteStartTransaction + if (!ocpp_idTag.isEmpty() && strcmp(tx_start_point.c_str(), "tx_only_remote")) { + //ID tag given in OpenEVSE dashboard & Auto-Authorize not disabled + String idTagCapture = ocpp_idTag; + authorize(idTagCapture.c_str(), [this, idTagCapture] (JsonObject payload) { + if (idTagIsAccepted(payload)) { + beginSession(idTagCapture.c_str()); + } else { + LCD_DISPLAY("ID tag not recognized"); + } + }, [this] () { + LCD_DISPLAY("OCPP timeout"); + }); + } else { + //OpenEVSE cannot authorize this session -> wait for RemoteStartTransaction + LCD_DISPLAY("Please authorize session"); + } + } + } } - } - - if (!evse->isVehicleConnected() && vehicleConnected) { vehicleConnected = evse->isVehicleConnected(); - onVehicleDisconnect(); + if (ocppSessionDisplay && !getSessionIdTag()) { + //Session unauthorized. Show if StartTransaction didn't succeed + if (ocppTxIdDisplay < 0) { + if (config_rfid_enabled()) { + LCD_DISPLAY("Card timeout"); + LCD_DISPLAY("Present card again"); + } else { + LCD_DISPLAY("Auth timeout"); + } + } + } else if (!ocppSessionDisplay && getSessionIdTag()) { + //Session recently authorized + if (!evse->isVehicleConnected()) { + LCD_DISPLAY("Plug in cable"); + } + } + ocppSessionDisplay = getSessionIdTag(); + + if (ocppTxIdDisplay <= 0 && getTransactionId() > 0) { + LCD_DISPLAY("OCPP start tx"); + String txIdMsg = "TxID "; + txIdMsg += String(getTransactionId()); + LCD_DISPLAY(txIdMsg); + } else if (ocppTxIdDisplay > 0 && getTransactionId() < 0) { + LCD_DISPLAY("OCPP Good bye!"); + String txIdMsg = "TxID "; + txIdMsg += String(ocppTxIdDisplay); + txIdMsg += " finished"; + LCD_DISPLAY(txIdMsg); + } + ocppTxIdDisplay = getTransactionId(); } if (resetTriggered) { @@ -296,7 +355,12 @@ unsigned long ArduinoOcppTask::loop(MicroTasks::WakeReason reason) { } } - return 0; + if (millis() - updateEvseClaimLast >= 1009) { + updateEvseClaimLast = millis(); + updateEvseClaim(); + } + + return arduinoOcppInitialized ? 0 : 1000; } void ArduinoOcppTask::updateEvseClaim() { @@ -304,24 +368,18 @@ void ArduinoOcppTask::updateEvseClaim() { EvseState evseState; EvseProperties evseProperties; - int transactionId = getTransactionId(); //ID of OCPP-transaction. transactionId < 0 means that no transaction runs on the EVSE at the moment - // transactionId > 0 means that the EVSE is in a charging transaction right now - // transactionId == 0 means that the initiation is pending + if (!arduinoOcppInitialized || !config_ocpp_enabled()) { + evse->release(EvseClient_OpenEVSE_Ocpp); + return; + } - //EVSE is in an OCPP-transaction? - if (transactionId < 0) { - //no transaction running. Forbid charging - evseState = EvseState::Disabled; - } else if (transactionId == 0) { + if (getTransactionId() == 0 && !strcmp(tx_start_point.c_str(), "tx_pending")) { //transaction initiated but neither accepted nor rejected - if (!strcmp(tx_start_point.c_str(), "tx_pending")) { - evseState = EvseState::Active; - } else { - evseState = EvseState::Disabled; - } - } else { - //transaction running. Allow charging evseState = EvseState::Active; + } else if (ocppPermitsCharge()) { + evseState = EvseState::Active; + } else { + evseState = EvseState::Disabled; } evseProperties = evseState; @@ -355,7 +413,7 @@ void ArduinoOcppTask::updateEvseClaim() { } //Apply inferred claim - if (evseState == EvseState::None || !config_ocpp_enabled()) { + if (evseState == EvseState::None) { //the claiming rules don't specify the EVSE state evse->release(EvseClient_OpenEVSE_Ocpp); } else { @@ -392,23 +450,8 @@ void ArduinoOcppTask::notifyConfigChanged() { } } -void ArduinoOcppTask::reconfigure() { - if (arduinoOcppInitialized) { - if (config_ocpp_enabled()) { - String mUrl = getCentralSystemUrl(); - ocppSocket->reconnect(mUrl); - } else { - String emptyUrl = String(""); - ocppSocket->reconnect(emptyUrl); - } - } else { - initializeArduinoOcpp(); - } - loadEvseBehavior(); -} - void ArduinoOcppTask::initializeDiagnosticsService() { - ArduinoOcpp::DiagnosticsService *diagService = ArduinoOcpp::getDiagnosticsService(); + ArduinoOcpp::DiagnosticsService *diagService = getDiagnosticsService(); if (diagService) { diagService->setOnUploadStatusSampler([this] () { if (diagFailure) { @@ -420,7 +463,7 @@ void ArduinoOcppTask::initializeDiagnosticsService() { } }); - diagService->setOnUpload([this] (String &location, ArduinoOcpp::OcppTimestamp &startTime, ArduinoOcpp::OcppTimestamp &stopTime) { + diagService->setOnUpload([this] (const std::string &location, ArduinoOcpp::OcppTimestamp &startTime, ArduinoOcpp::OcppTimestamp &stopTime) { //reset reported state diagSuccess = false; @@ -431,7 +474,7 @@ void ArduinoOcppTask::initializeDiagnosticsService() { struct mg_str scheme, query, fragment; if (mg_parse_uri(mg_mk_str(location.c_str()), &scheme, NULL, NULL, &port_i, NULL, &query, &fragment)) { DBUG(F("[ocpp] Diagnostics upload, invalid URL: ")); - DBUGLN(location); + DBUGLN(location.c_str()); diagFailure = true; return false; } @@ -500,7 +543,7 @@ void ArduinoOcppTask::initializeDiagnosticsService() { body += bodySuffix; DBUG(F("[ocpp] POST diagnostics file to ")); - DBUGLN(location); + DBUGLN(location.c_str()); MongooseHttpClientRequest *request = diagClient.beginRequest(location.c_str()); @@ -528,7 +571,7 @@ void ArduinoOcppTask::initializeDiagnosticsService() { } void ArduinoOcppTask::initializeFwService() { - ArduinoOcpp::FirmwareService *fwService = ArduinoOcpp::getFirmwareService(); + ArduinoOcpp::FirmwareService *fwService = getFirmwareService(); if (fwService) { fwService->setBuildNumber(evse->getFirmwareVersion()); @@ -542,7 +585,7 @@ void ArduinoOcppTask::initializeFwService() { } }); - fwService->setOnInstall([this](String &location) { + fwService->setOnInstall([this](const std::string &location) { DBUGLN(F("[ocpp] Starting installation routine")); @@ -550,7 +593,7 @@ void ArduinoOcppTask::initializeFwService() { updateFailure = false; updateSuccess = false; - return http_update_from_url(location, [] (size_t complete, size_t total) { }, + return http_update_from_url(String(location.c_str()), [] (size_t complete, size_t total) { }, [this] (int status_code) { //onSuccess updateSuccess = true; @@ -565,17 +608,7 @@ void ArduinoOcppTask::initializeFwService() { } } -bool ArduinoOcppTask::operationIsAccepted(JsonObject payload) { - const char *status = payload["status"] | "Invalid"; - return !strcmp(status, "Accepted"); -} - bool ArduinoOcppTask::idTagIsAccepted(JsonObject payload) { const char *status = payload["idTagInfo"]["status"] | "Invalid"; return !strcmp(status, "Accepted"); } - -bool ArduinoOcppTask::idTagIsRejected(JsonObject payload) { - const char *status = payload["idTagInfo"]["status"] | "Accepted"; - return strcmp(status, "Accepted"); -} diff --git a/src/ocpp.h b/src/ocpp.h index 54b61f0f..f89ce5ac 100644 --- a/src/ocpp.h +++ b/src/ocpp.h @@ -10,6 +10,7 @@ #include "evse_man.h" #include "lcd.h" +#include "rfid.h" #include "MongooseOcppSocketClient.h" #include @@ -20,44 +21,39 @@ class ArduinoOcppTask: public MicroTasks::Task { EvseManager *evse; LcdTask *lcd; EventLog *eventLog; + RfidTask *rfid; - /* - * OCPP state - */ float charging_limit = -1.f; //in Watts. chargingLimit < 0 means that there is no Smart Charging (and no restrictions ) + int ocppTxIdDisplay {-1}; + bool ocppSessionDisplay {false}; - /* - * SAE J1772 state - */ bool vehicleConnected = false; - bool vehicleCharging = false; - std::function onVehicleConnect = [] () {}; - std::function onVehicleDisconnect = [] () {}; + std::function onIdTagInput {nullptr}; bool resetTriggered = false; bool resetHard = false; //default to soft reset ulong resetTime; MongooseHttpClient diagClient = MongooseHttpClient(); - bool diagSuccess, diagFailure = false; + bool diagSuccess = false, diagFailure = false; void initializeDiagnosticsService(); - bool updateSuccess, updateFailure = false; + bool updateSuccess = false, updateFailure = false; void initializeFwService(); void initializeArduinoOcpp(); bool arduinoOcppInitialized = false; void loadEvseBehavior(); + ulong updateEvseClaimLast {0}; + String getCentralSystemUrl(); static ArduinoOcppTask *instance; //helper functions - static bool operationIsAccepted(JsonObject payload); static bool idTagIsAccepted(JsonObject payload); - static bool idTagIsRejected(JsonObject payload); protected: //hook method of MicroTask::Task @@ -70,13 +66,12 @@ class ArduinoOcppTask: public MicroTasks::Task { ArduinoOcppTask(); ~ArduinoOcppTask(); - void begin(EvseManager &evse, LcdTask &lcd, EventLog &eventLog); + void begin(EvseManager &evse, LcdTask &lcd, EventLog &eventLog, RfidTask &rfid); void updateEvseClaim(); static void notifyConfigChanged(); void reconfigure(); - }; #endif diff --git a/src/rfid.cpp b/src/rfid.cpp new file mode 100644 index 00000000..a9bb25df --- /dev/null +++ b/src/rfid.cpp @@ -0,0 +1,460 @@ +/* + * Author: Oliver Norin + * Matthias Akstaller + */ + +#if defined(ENABLE_DEBUG) && !defined(ENABLE_DEBUG_NFCREADER) +#undef ENABLE_DEBUG +#endif + +#include "rfid.h" + +#include "debug.h" +#include "mqtt.h" +#include "lcd.h" +#include "app_config.h" +#include "input.h" +#include "openevse.h" + +#include + +#ifndef I2C_SDA +#define I2C_SDA 21 +#endif + +#ifndef I2C_SCL +#define I2C_SCL 22 +#endif + +/* + * Documentation of the I2C messages: + * NXP PN532 manual, https://www.nxp.com/docs/en/user-guide/141520.pdf + * (accessed: 2022-01-14) + */ + +#define PN532_I2C_ADDRESS (0x48 >> 1) +#define PN532_RDY 0x01 +#define PN532_FRAME_HEADER_LEN 4 +#define PN532_FRAME_IDENTIFIER_LEN 1 +#define PN532_CMD_SAMCONFIGURATION_RESPONSE 0x15 +#define PN532_CMD_INAUTOPOLL_RESPONSE 0x61 + +#define I2C_READ_BUFFSIZE 35 //might increase later + +RfidTask::RfidTask() : + MicroTasks::Task() +{ +} + +void RfidTask::begin(EvseManager &evse){ + _evse = &evse; + Wire.begin(I2C_SDA, I2C_SCL); + MicroTask.startTask(this); +} + +void RfidTask::setup(){ + if (config_rfid_enabled()) { + pn532_initialize(); + } +} + +void RfidTask::scanCard(String& uid){ + if(waitingForTag > 0){ + waitingForTag = 0; + cardFound = true; + waitingForTagResult = uid; + lcd.display("Tag detected!", 0, 0, 0, LCD_CLEAR_LINE); + lcd.display(uid, 0, 1, 3000, LCD_CLEAR_LINE); + } else if (onCardScanned && (*onCardScanned) && (*onCardScanned)(uid)){ + //OCPP will process the card + }else{ + // Check if tag is stored locally + char storedTags[rfid_storage.length() + 1]; + rfid_storage.toCharArray(storedTags, rfid_storage.length()+1); + char* storedTag = strtok(storedTags, ","); + bool foundCard = false; + while(storedTag) + { + String storedTagStr = storedTag; + storedTagStr.replace(" ", ""); + if(storedTagStr.equals(uid)){ + foundCard = true; + if (!isAuthenticated()){ + setAuthentication(uid); + lcd.display("RFID: authenticated", 0, 1, 5 * 1000, LCD_CLEAR_LINE); + DBUGLN(F("[rfid] found card")); + } else if (uid == authenticatedTag) { + resetAuthentication(); + lcd.display("RFID: finished. See you next time!", 0, 1, 5 * 1000, LCD_CLEAR_LINE); + DBUGLN(F("[rfid] finished by presenting card")); + } else { + lcd.display("RFID: card does not match", 0, 1, 5 * 1000, LCD_CLEAR_LINE); + DBUGLN(F("[rfid] card does not match")); + } + break; + } + storedTag = strtok(NULL, ","); + } + + if (!foundCard) { + lcd.display("RFID: did not recognize card", 0, 1, 5 * 1000, LCD_CLEAR_LINE); + DBUGLN(F("[rfid] did not recognize card")); + } + + // Send to MQTT broker + DynamicJsonDocument data{JSON_OBJECT_SIZE(1) + uid.length() + 1}; + data["rfid"] = uid; + mqtt_publish(data); + } +} + +unsigned long RfidTask::loop(MicroTasks::WakeReason reason){ + + if (_evse->isVehicleConnected() && !vehicleConnected) { + vehicleConnected = _evse->isVehicleConnected(); + } + + if (!_evse->isVehicleConnected() && vehicleConnected) { + vehicleConnected = _evse->isVehicleConnected(); + + if (isAuthenticated()) { + lcd.display("RFID: finished. See you next time!", 0, 1, 5 * 1000, LCD_CLEAR_LINE); + DBUGLN(F("[rfid] finished by unplugging")); + } + resetAuthentication(); + } + + if (authenticationTimeoutExpired()) { + resetAuthentication(); + lcd.display("RFID: please present again", 0, 1, 20 * 1000, LCD_CLEAR_LINE); + } + + updateEvseClaim(); + + pn532_read(); + + if (!config_rfid_enabled()) { + pn532_status = PN532_DeviceStatus::NOT_ACTIVE; + resetAuthentication(); + return SCAN_FREQ; + } + + if (pn532_status == PN532_DeviceStatus::ACTIVE && millis() - pn532_lastResponse > MAXIMUM_UNRESPONSIVE_TIME) { + DBUGLN(F("[rfid] connection to PN532 lost")); + lcd.display("RFID chip not found", 0, 1, 5 * 1000, LCD_CLEAR_LINE); + pn532_status = PN532_DeviceStatus::FAILED; + } + + if (pn532_status != PN532_DeviceStatus::ACTIVE) { + pn532_initialize(); + return SCAN_FREQ; + } + + if(waitingForTag > 0){ + waitingForTag = (stopWaiting - millis()) / 1000; + String msg = "tag... "; + msg.concat(waitingForTag); + lcd.display("Waiting for RFID", 0, 0, 0, LCD_CLEAR_LINE); + lcd.display(msg, 0, 1, 1000, LCD_CLEAR_LINE); + } + + if (pn532_pollCount >= AUTO_REFRESH_CONNECTION) { + pn532_initialize(); + pn532_pollCount = 0; + } else { + pn532_poll(); + pn532_pollCount++; + } + + return SCAN_FREQ; +} + +bool RfidTask::authenticationTimeoutExpired(){ + return !authenticatedTag.isEmpty() && millis() - authentication_timestamp > AUTHENTICATION_TIMEOUT && !vehicleConnected; +} + +bool RfidTask::isAuthenticated(){ + if (authenticatedTag.isEmpty()) { + return false; + } else { + return vehicleConnected || millis() - authentication_timestamp <= AUTHENTICATION_TIMEOUT; + } +} + +String RfidTask::getAuthenticatedTag(){ + if (isAuthenticated()) + return authenticatedTag; + else + return String('\0'); +} + +void RfidTask::resetAuthentication(){ + authenticatedTag = String('\0'); +} + +void RfidTask::setAuthentication(String &idTag){ + authenticatedTag = idTag; + authentication_timestamp = millis(); +} + +void RfidTask::waitForTag(uint8_t seconds){ + if(!config_rfid_enabled()) + return; + waitingForTag = seconds; + stopWaiting = millis() + seconds * 1000; + cardFound = false; + lcd.display("Waiting for RFID", 0, 0, seconds * 1000, LCD_CLEAR_LINE); +} + +void RfidTask::updateEvseClaim() { + + if (!config_rfid_enabled()) { + _evse->release(EvseClient_OpenEVSE_RFID); + return; + } + + EvseState evseState = isAuthenticated() ? (EvseState::Active) : (EvseState::Disabled); + + EvseProperties evseProperties {evseState}; + + _evse->claim(EvseClient_OpenEVSE_RFID, EvseManager_Priority_RFID, evseProperties); +} + +DynamicJsonDocument RfidTask::rfidPoll() { + const size_t capacity = JSON_OBJECT_SIZE(2) + waitingForTagResult.length() + 1; + DynamicJsonDocument doc(capacity); + if(waitingForTag > 0){ + // respond with remainding time + doc["status"] = "waiting"; + doc["timeLeft"] = waitingForTag; + } + else if(cardFound){ + // respond with the scanned tags uid and reset + doc["status"] = "done"; + doc["scanned"] = waitingForTagResult; + cardFound = false; + waitingForTagResult.clear(); + } + else { + doc["status"] = "notStarted"; + } + return doc; +} + +void RfidTask::setOnCardScanned(std::function *onCardScanned) { + this->onCardScanned = onCardScanned; +} + +bool RfidTask::communicationFails() { + return config_rfid_enabled() && pn532_status == PN532_DeviceStatus::FAILED; +} + +void RfidTask::pn532_initialize() { + + /* + * Command hardcoded according to NXP manual, page 89 + */ + uint8_t SAMConfiguration [] = {0x00, 0xFF, 0x05, 0xFB, + 0xD4, 0x14, 0x01, 0x00, 0x00, + 0x17}; + Wire.beginTransmission(PN532_I2C_ADDRESS); + Wire.write(SAMConfiguration, sizeof(SAMConfiguration) / sizeof(*SAMConfiguration)); + Wire.endTransmission(); + + pn532_listen = true; + //"flush" ACK + delay(30); + pn532_read(); +} + +void RfidTask::pn532_poll() { + /* + * Command hardcoded according to NXP manual, page 144 + */ + uint8_t InAutoPoll [] = {0x00, 0xFF, 0x06, 0xFA, + 0xD4, 0x60, 0x01, 0x01, 0x10, 0x20, + 0x9A}; + Wire.beginTransmission(PN532_I2C_ADDRESS); + Wire.write(InAutoPoll, sizeof(InAutoPoll) / sizeof(*InAutoPoll)); + Wire.endTransmission(); + + pn532_listen = true; + //"flush" ACK + delay(30); + pn532_read(); +} + +void RfidTask::pn532_read() { + if (!pn532_listen) + return; + + Wire.requestFrom(PN532_I2C_ADDRESS, I2C_READ_BUFFSIZE + 1, 1); + if (Wire.read() != PN532_RDY) { + //no msg available + return; + } + + uint8_t response [I2C_READ_BUFFSIZE] = {0}; + uint8_t frame_len = 0; + while (Wire.available() && frame_len < I2C_READ_BUFFSIZE) { + response[frame_len] = Wire.read(); + frame_len++; + } + Wire.flush(); + + /* + * For frame layout, see NXP manual, page 28 + */ + + if (frame_len < PN532_FRAME_HEADER_LEN) { + //frame corrupt + pn532_listen = false; + return; + } + + uint8_t *header = nullptr; + uint8_t header_offs = 0; + while (header_offs < frame_len - PN532_FRAME_HEADER_LEN) { + if (response[header_offs] == 0x00 && response[header_offs + 1] == 0xFF) { //find frame preamble + header = response + header_offs; //header preamble found + break; + } + header_offs++; + } + + if (!header) { + //invalid packet + pn532_listen = false; + return; + } + + //check for ack frame + if (header[2] == 0x00 && header[3] == 0xFF) { + //ack detected + return; + } + + if (header[2] == 0x00 || header[2] == 0xFF) { + //ignore frame type + pn532_listen = false; + return; + } + + uint8_t data_len = header[2]; + uint8_t data_lcs = header[3]; + data_lcs += data_len; + + if (data_lcs) { + //checksum wrong + pn532_listen = false; + return; + } + + if (data_len <= PN532_FRAME_IDENTIFIER_LEN) { + //ingore frame type + pn532_listen = false; + return; + } + + //frame layout:
+ uint8_t *frame_identifier = header + PN532_FRAME_HEADER_LEN; + uint8_t *data = frame_identifier + PN532_FRAME_IDENTIFIER_LEN; + uint8_t *data_dcs = frame_identifier + data_len; + + if (data_dcs - response >= frame_len) { + DBUGLN(F("[rfid] Did not read sufficient bytes. Abort")); + pn532_listen = false; + return; + } + + uint8_t data_checksum = *data_dcs; + for (uint8_t *i = frame_identifier; i != data_dcs; i++) { + data_checksum += *i; + } + + if (data_checksum) { + //wrong checksum + pn532_listen = false; + return; + } + + if (frame_identifier[0] != 0xD5) { + //ignore frame type + pn532_listen = false; + return; + } + + uint8_t cmd_code = data[0]; + + if (cmd_code == PN532_CMD_SAMCONFIGURATION_RESPONSE) { + //success + DBUGLN(F("[rfid] connection to PN532 active")); + pn532_status = PN532_DeviceStatus::ACTIVE; + pn532_lastResponse = millis(); + + } else if (cmd_code == PN532_CMD_INAUTOPOLL_RESPONSE) { + + /* + * see NXP manual, page 145 + */ + + if (data_len < 3 || data[1] == 0) { + pn532_hasContact = false; + pn532_listen = false; + return; + } + + if (data_len < 10) { + pn532_listen = false; + return; + } + + uint8_t card_type = data[2]; + uint8_t targetDataLen = data[3]; + uint8_t uidLen = data[8]; + + if (data_len - 5 < targetDataLen || targetDataLen - 5 < uidLen) { + DBUGLN(F("[rfid] INAUTOPOLL format err")); + pn532_listen = false; + return; + } + + pn532_lastResponse = millis(); //successfully read + + if (pn532_hasContact) { + //valid card already scanned the last time; nothing to do + pn532_listen = false; + return; + } + + String uid = String('\0'); + uid.reserve(2*uidLen); + + for (uint8_t i = 0; i < uidLen; i++) { + uint8_t uid_i = data[9 + i]; + uint8_t lhw = uid_i / 0x10; + uint8_t rhw = uid_i % 0x10; + uid += (char) (lhw <= 9 ? lhw + '0' : lhw%10 + 'a'); + uid += (char) (rhw <= 9 ? rhw + '0' : rhw%10 + 'a'); + } + + DBUG(F("[rfid] found card! type = ")); + DBUG(card_type); + DBUG(F(", uid = ")); + DBUG(uid); + DBUGLN(F(" end")); + (void) card_type; + + scanCard(uid); + pn532_hasContact = true; + + } else { + DBUG(F("[rfid] unknown response; cmd_code = ")); + DBUGLN(cmd_code); + } + + pn532_listen = false; + return; +} + +RfidTask rfid; diff --git a/src/rfid.h b/src/rfid.h new file mode 100644 index 00000000..61ca53dc --- /dev/null +++ b/src/rfid.h @@ -0,0 +1,79 @@ +/* + * Author: Oliver Norin + * Matthias Akstaller + */ + +#ifndef RFIDTASK_H +#define RFIDTASK_H + +#include +#include + +#include "evse_man.h" + +#define SCAN_FREQ 1000 + +#define AUTHENTICATION_TIMEOUT 30000UL + +#define MAXIMUM_UNRESPONSIVE_TIME 60000UL //after this period the pn532 is considered offline +#define AUTO_REFRESH_CONNECTION 30 //after this number of polls, the connection to the PN532 will be refreshed + +class RfidTask : public MicroTasks::Task { + private: + EvseManager *_evse; + uint8_t waitingForTag = 0; + String waitingForTagResult {'\0'}; + unsigned long stopWaiting = 0; + boolean cardFound = false; + void scanCard(String& uid); + String authenticatedTag {'\0'}; + ulong authentication_timestamp {0}; + boolean isAuthenticated(); + bool authenticationTimeoutExpired(); + void resetAuthentication(); + void setAuthentication(String& tag); + + /* + * SAE J1772 state + */ + bool vehicleConnected = false; + + void updateEvseClaim(); + + std::function *onCardScanned {nullptr}; + + enum class PN532_DeviceStatus { + ACTIVE, + NOT_ACTIVE, + FAILED + }; + PN532_DeviceStatus pn532_status = PN532_DeviceStatus::NOT_ACTIVE; + + boolean pn532_hasContact = false; + bool pn532_listen = false; + void pn532_initialize(); + void pn532_poll(); + void pn532_read(); + + ulong pn532_lastResponse = 0; + uint pn532_pollCount = 0; + + protected: + void setup(); + unsigned long loop(MicroTasks::WakeReason reason); + + public: + RfidTask(); + void begin(EvseManager &evse); + void waitForTag(uint8_t seconds); + DynamicJsonDocument rfidPoll(); + + String getAuthenticatedTag(); + bool communicationFails(); + + void setOnCardScanned(std::function *onCardScanned); +}; + +extern RfidTask rfid; + +#endif diff --git a/src/web_server.cpp b/src/web_server.cpp index 3ce3cabe..526c1bfa 100644 --- a/src/web_server.cpp +++ b/src/web_server.cpp @@ -37,6 +37,7 @@ typedef const __FlashStringHelper *fstr_t; #include "time_man.h" #include "tesla_client.h" #include "scheduler.h" +#include "rfid.h" MongooseHttpServer server; // Create class for Web server @@ -894,6 +895,30 @@ void handleDescribe(MongooseHttpServerRequest *request) { request->send(response); } +void handleAddRFID(MongooseHttpServerRequest *request) { + MongooseHttpServerResponseStream *response; + if(false == requestPreProcess(request, response, CONTENT_TYPE_TEXT)) { + return; + } + response->setCode(200); + response->setContentType(CONTENT_TYPE_TEXT); + response->addHeader("Access-Control-Allow-Origin", "*"); + request->send(response); + rfid.waitForTag(60); +} + +void handlePollRFID(MongooseHttpServerRequest *request) { + MongooseHttpServerResponseStream *response; + if(false == requestPreProcess(request, response, CONTENT_TYPE_JSON)) { + return; + } + response->setCode(200); + response->setContentType(CONTENT_TYPE_JSON); + response->addHeader("Access-Control-Allow-Origin", "*"); + serializeJson(rfid.rfidPoll(), *response); + request->send(response); +} + String delayTimer = "0 0 0 0"; void @@ -1080,6 +1105,10 @@ web_server_setup() { server.on("/apoff$", handleAPOff); server.on("/divertmode$", handleDivertMode); server.on("/emoncms/describe$", handleDescribe); + server.on("/rfid/add$", handleAddRFID); + + // Check status of RFID scan + server.on("/rfid/poll$", handlePollRFID); server.on("/schedule/plan$", handleSchedulePlan); server.on("/schedule", handleSchedule); diff --git a/src/web_static/web_server.arduinoocpp.png.h b/src/web_static/web_server.arduinoocpp.png.h new file mode 100644 index 00000000..3e1bcd9c --- /dev/null +++ b/src/web_static/web_server.arduinoocpp.png.h @@ -0,0 +1,106 @@ +static const char CONTENT_ARDUINOOCPP_PNG[] PROGMEM = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x2a, 0x08, 0x06, 0x00, 0x00, 0x00, 0x13, 0x66, 0x13, + 0x3e, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x2e, 0x23, 0x00, 0x00, 0x2e, + 0x23, 0x01, 0x78, 0xa5, 0x3f, 0x76, 0x00, 0x00, 0x06, 0x22, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, + 0xed, 0x99, 0x69, 0x4c, 0x5c, 0x55, 0x14, 0xc7, 0xff, 0x6f, 0x16, 0x66, 0x67, 0x19, 0x60, 0x18, + 0x18, 0xb6, 0x81, 0xa1, 0x65, 0x87, 0x82, 0x50, 0x91, 0xb6, 0x92, 0x2e, 0x4a, 0x9b, 0x5a, 0x4d, + 0x97, 0x0f, 0xe2, 0xfe, 0xa1, 0x55, 0x93, 0x7e, 0xf0, 0x83, 0x1a, 0x35, 0x26, 0xb6, 0x46, 0x8d, + 0x69, 0x8c, 0x31, 0x31, 0x71, 0x49, 0xb5, 0x4d, 0x25, 0x51, 0x13, 0x9b, 0xb4, 0xb5, 0xa5, 0xc6, + 0x6a, 0x2b, 0x45, 0x84, 0x42, 0xa1, 0x02, 0x1d, 0x3a, 0x50, 0xd6, 0xc2, 0x0c, 0x0c, 0x03, 0xc3, + 0x0c, 0x03, 0xcc, 0x30, 0xeb, 0xf3, 0x53, 0x9b, 0xe2, 0xbb, 0x6f, 0x86, 0x59, 0x68, 0xa2, 0xe1, + 0x7c, 0x3c, 0xf7, 0xdc, 0x73, 0xef, 0xef, 0xbd, 0x73, 0xcf, 0x3d, 0xef, 0x3c, 0x8a, 0xa6, 0x69, + 0x1a, 0x41, 0xc8, 0xb0, 0xde, 0x88, 0xb1, 0x49, 0x33, 0xdc, 0x1e, 0x0f, 0x28, 0x50, 0x10, 0x09, + 0xa3, 0x50, 0x94, 0x93, 0x8e, 0x68, 0xa9, 0x98, 0x61, 0xdb, 0x3f, 0x62, 0x40, 0x43, 0xcb, 0x4d, + 0x0c, 0x4d, 0x59, 0x60, 0x5a, 0x70, 0x02, 0x00, 0x12, 0x24, 0x02, 0xa4, 0xc7, 0xcb, 0xa0, 0x56, + 0xca, 0x91, 0x9e, 0x24, 0x87, 0x5a, 0xa5, 0x80, 0x32, 0x31, 0x0e, 0x14, 0x45, 0x21, 0x52, 0x42, + 0x05, 0x03, 0x35, 0x3b, 0x37, 0x8f, 0x2d, 0x47, 0xbe, 0x83, 0xc3, 0xb7, 0x7c, 0xca, 0xf1, 0xba, + 0x47, 0xb1, 0x75, 0x63, 0x11, 0xc3, 0xfe, 0x83, 0x13, 0xe7, 0x71, 0xb2, 0xfb, 0x4e, 0x40, 0xbf, + 0xfb, 0xd7, 0x25, 0xa3, 0x6e, 0x7b, 0x39, 0xf2, 0xb3, 0xd3, 0xc0, 0xe7, 0x71, 0xc3, 0x86, 0xe2, + 0x04, 0x63, 0xac, 0x1d, 0x18, 0x67, 0x00, 0x01, 0x80, 0x4a, 0x21, 0x27, 0xda, 0xdb, 0x9d, 0xee, + 0x15, 0xf9, 0x3d, 0x7d, 0x7b, 0x12, 0x7b, 0xbf, 0xb8, 0x80, 0xa3, 0xdf, 0xfc, 0x8c, 0xa9, 0x19, + 0xeb, 0x83, 0x85, 0xea, 0xe8, 0x1f, 0x63, 0xe8, 0xb2, 0x24, 0x02, 0xa8, 0x53, 0x93, 0x88, 0xf6, + 0xbe, 0xe0, 0x22, 0x1b, 0x3f, 0xe8, 0x0c, 0x78, 0xe9, 0xb3, 0xd3, 0xd0, 0x0d, 0xeb, 0x1f, 0x0c, + 0xd4, 0xfc, 0xa2, 0x03, 0x3f, 0x75, 0x8d, 0x32, 0xf4, 0x07, 0x6b, 0x0a, 0x11, 0xc5, 0xe7, 0x11, + 0xe7, 0xf0, 0xb9, 0x9c, 0xa0, 0x37, 0xd4, 0x3f, 0xbf, 0x84, 0xc3, 0xc7, 0x2f, 0x62, 0x68, 0x6c, + 0x32, 0x64, 0x28, 0xde, 0x4a, 0x0d, 0xaf, 0x6b, 0x07, 0x61, 0x72, 0x79, 0x96, 0x6f, 0x9a, 0xa2, + 0x50, 0x96, 0x9b, 0xc9, 0x3a, 0xa7, 0xba, 0x50, 0x0d, 0x83, 0x75, 0x11, 0xe9, 0x72, 0x19, 0x78, + 0x5c, 0x0e, 0xa6, 0x6d, 0x76, 0xb4, 0xea, 0x67, 0x61, 0x76, 0x7b, 0xfd, 0xae, 0x35, 0x6a, 0x77, + 0xe1, 0xbd, 0xfa, 0xdf, 0xf0, 0xe5, 0x6b, 0x07, 0x20, 0x93, 0x88, 0x56, 0x07, 0xca, 0x47, 0xd3, + 0x68, 0xec, 0x1e, 0x62, 0xe8, 0x35, 0x32, 0x21, 0x52, 0x93, 0xe2, 0x59, 0xe7, 0xd5, 0x56, 0x97, + 0xa2, 0xb6, 0xba, 0x74, 0x99, 0xce, 0xe5, 0xf6, 0xc0, 0x30, 0x65, 0x46, 0x6b, 0xcf, 0x20, 0xde, + 0xbf, 0xd4, 0x05, 0x37, 0x4b, 0x88, 0xb6, 0x9a, 0x6c, 0x38, 0xfb, 0x47, 0x07, 0x9e, 0xdb, 0xbd, + 0x79, 0x75, 0xc2, 0x6f, 0xc6, 0x62, 0x43, 0x43, 0x3f, 0x33, 0x1c, 0xf6, 0x55, 0x68, 0x20, 0x14, + 0x44, 0x05, 0xb5, 0x60, 0x14, 0x9f, 0x07, 0x75, 0x6a, 0x12, 0xea, 0x76, 0x55, 0xe3, 0x97, 0xd7, + 0xf7, 0xa3, 0x4a, 0x11, 0xcd, 0x6a, 0xfb, 0x79, 0xa3, 0x16, 0x26, 0xb3, 0x75, 0x75, 0xa0, 0x9a, + 0x3a, 0xfb, 0x60, 0xf5, 0x2c, 0x0f, 0x19, 0x11, 0x87, 0xc2, 0xf6, 0x8a, 0xfc, 0xb0, 0x0e, 0xb4, + 0x3a, 0x35, 0x09, 0x9f, 0xbe, 0xb2, 0x07, 0x05, 0x31, 0xe4, 0x10, 0x33, 0xbb, 0xbd, 0xe8, 0xd4, + 0x8d, 0x44, 0x1e, 0xca, 0xe5, 0xf6, 0xe0, 0xe2, 0x8d, 0x01, 0xe6, 0x79, 0x49, 0x89, 0x83, 0x32, + 0x21, 0x2e, 0xec, 0xf4, 0xab, 0x88, 0x8f, 0xc5, 0xdb, 0xfb, 0x36, 0xb1, 0x8e, 0x7f, 0x7b, 0xb9, + 0x0b, 0x5e, 0xaf, 0x37, 0xb2, 0x50, 0xe3, 0xc6, 0x19, 0xb4, 0x4c, 0xce, 0x31, 0x43, 0xaf, 0xba, + 0x00, 0x7c, 0x3e, 0x0f, 0x91, 0x90, 0xca, 0x42, 0x0d, 0x76, 0xab, 0x13, 0x89, 0x63, 0x7f, 0xcf, + 0x2e, 0xc2, 0x18, 0xe4, 0xdd, 0x15, 0x10, 0xea, 0x4a, 0x87, 0x8e, 0x71, 0x98, 0x15, 0x51, 0x3c, + 0x54, 0x16, 0x69, 0xfc, 0xce, 0xa3, 0x69, 0x1a, 0x33, 0x16, 0x1b, 0xae, 0x75, 0xdf, 0x46, 0x6b, + 0x57, 0x3f, 0xcc, 0x56, 0x1b, 0xd8, 0x8a, 0x17, 0x2e, 0x97, 0x8b, 0xed, 0xa5, 0xd9, 0xac, 0xbe, + 0x0c, 0xa6, 0xd9, 0xc8, 0x65, 0xbf, 0xf9, 0x45, 0x07, 0x7e, 0x6c, 0x67, 0x86, 0xde, 0x53, 0x45, + 0x69, 0x88, 0x21, 0xd4, 0x7a, 0x77, 0xc5, 0xe9, 0x72, 0xe3, 0xc4, 0xb9, 0x26, 0x7c, 0xd5, 0xda, + 0x8f, 0x05, 0xaf, 0x0f, 0x00, 0x10, 0xcb, 0xe3, 0xe2, 0xd0, 0x23, 0xeb, 0xf0, 0xc2, 0xee, 0xcd, + 0xc4, 0xe4, 0xb2, 0x21, 0x37, 0x13, 0xc0, 0x35, 0xa2, 0x3f, 0xa3, 0x79, 0x2e, 0x72, 0x6f, 0x6a, + 0x70, 0x6c, 0x12, 0xa3, 0x76, 0x17, 0x43, 0xbf, 0xa5, 0x44, 0xc3, 0x5a, 0x80, 0xfa, 0x68, 0x1a, + 0xc7, 0xcf, 0x34, 0xe2, 0x93, 0x66, 0xdd, 0x3d, 0x20, 0x00, 0xb0, 0x7a, 0xbc, 0x38, 0xd6, 0xa4, + 0x43, 0x7d, 0x43, 0x33, 0x71, 0x5e, 0x8a, 0x42, 0x8e, 0x2c, 0x89, 0x80, 0xfc, 0xa6, 0xa6, 0x23, + 0x04, 0x45, 0xd3, 0x34, 0xce, 0xb7, 0x68, 0x19, 0xfa, 0x4c, 0x71, 0x14, 0x36, 0xe4, 0xaa, 0x59, + 0x1d, 0x9a, 0xcc, 0x56, 0x9c, 0x6c, 0x1f, 0x64, 0x1d, 0xff, 0xf8, 0xea, 0x2d, 0x4c, 0x98, 0xcc, + 0xcc, 0x8d, 0x70, 0x38, 0x28, 0x4d, 0x21, 0x27, 0x9e, 0x89, 0x59, 0x5b, 0x64, 0xa0, 0x4c, 0x66, + 0x2b, 0x4e, 0xf5, 0x30, 0x6b, 0xbd, 0x03, 0xe5, 0xd9, 0x7e, 0xef, 0xa6, 0xc1, 0x31, 0x23, 0x23, + 0xfd, 0xff, 0x5b, 0x46, 0x0c, 0xd3, 0x44, 0xbd, 0x32, 0x56, 0x42, 0xde, 0x8b, 0xcd, 0x11, 0x19, + 0xa8, 0x9e, 0x81, 0x31, 0xa2, 0xbe, 0x22, 0x3f, 0xd3, 0xaf, 0xc3, 0x95, 0xc4, 0xbf, 0xc5, 0xb6, + 0x48, 0xd4, 0x4b, 0x45, 0xe4, 0x87, 0x65, 0x5d, 0x72, 0x85, 0x0f, 0xe5, 0xf5, 0xf9, 0x70, 0xba, + 0xb9, 0x97, 0x18, 0x7a, 0x85, 0x9a, 0x74, 0xbf, 0x0e, 0x9d, 0x6e, 0x4f, 0xc0, 0x45, 0xdd, 0x2c, + 0x6f, 0x92, 0xc3, 0xe1, 0xb0, 0x9c, 0xd3, 0x08, 0x5c, 0xbe, 0x43, 0x63, 0x46, 0xfc, 0xae, 0x67, + 0xa6, 0xd1, 0x17, 0x37, 0xe5, 0x41, 0x10, 0xc5, 0xf7, 0xeb, 0x50, 0x1e, 0x2d, 0x09, 0xb8, 0xa8, + 0x54, 0x4c, 0x4e, 0x08, 0x3e, 0x9f, 0x8f, 0xa8, 0x8f, 0x15, 0xf2, 0xc3, 0x87, 0x6a, 0xeb, 0x1d, + 0x22, 0x1a, 0x97, 0xe7, 0x66, 0x06, 0x74, 0x98, 0x91, 0x9c, 0x10, 0xd0, 0x26, 0x39, 0x21, 0x96, + 0xa8, 0xb7, 0xd9, 0x9d, 0x44, 0x7d, 0xa2, 0x4c, 0x14, 0x1e, 0x94, 0xdb, 0xed, 0xc1, 0x99, 0xeb, + 0x03, 0xc4, 0xd0, 0xcb, 0x4e, 0x53, 0x06, 0x74, 0x98, 0xa9, 0x52, 0xa0, 0x2c, 0x5e, 0xca, 0x3a, + 0x9e, 0x17, 0x2d, 0x62, 0xf5, 0x33, 0x61, 0x59, 0x20, 0xa7, 0x7b, 0xb9, 0x2c, 0x3c, 0xa8, 0x8e, + 0x5b, 0x43, 0xe8, 0xb6, 0xd8, 0x19, 0x86, 0xaf, 0x6e, 0x2d, 0x09, 0x18, 0x7a, 0x00, 0x20, 0x16, + 0x0a, 0xf0, 0xe6, 0xde, 0x4d, 0x90, 0x12, 0x3e, 0x10, 0xa5, 0x5c, 0x0e, 0x3e, 0x7c, 0x76, 0x1b, + 0x44, 0x42, 0x66, 0xf8, 0x79, 0xbc, 0x5e, 0xb4, 0xeb, 0xc9, 0x95, 0x83, 0x2a, 0x31, 0x26, 0x74, + 0x28, 0x9a, 0xa6, 0xf1, 0x27, 0xe1, 0xbb, 0x89, 0x4f, 0x51, 0x28, 0xcb, 0xcb, 0x58, 0xb1, 0xd3, + 0x8a, 0x42, 0x0d, 0x4e, 0x1d, 0xdc, 0x89, 0x27, 0xb3, 0x93, 0xc0, 0xa7, 0x28, 0x88, 0x38, 0x14, + 0xf6, 0xe6, 0x28, 0x51, 0xff, 0xf2, 0x2e, 0x94, 0xac, 0x27, 0x87, 0xf0, 0x1d, 0x83, 0x09, 0x46, + 0x27, 0x39, 0xc9, 0x24, 0xc7, 0xc7, 0x86, 0x5e, 0x26, 0xcd, 0x2d, 0xd8, 0x71, 0x4e, 0x4b, 0xe8, + 0x43, 0x48, 0x05, 0x48, 0x49, 0x94, 0x07, 0xe5, 0xb8, 0x34, 0x4f, 0x8d, 0xe2, 0xdc, 0x4c, 0x1c, + 0xb5, 0x3b, 0xe0, 0xf3, 0xd1, 0x90, 0x49, 0xc5, 0xe0, 0xf8, 0x69, 0x83, 0x75, 0xf6, 0x8d, 0xb2, + 0x8e, 0xa5, 0x28, 0xe2, 0x42, 0x87, 0x6a, 0xeb, 0x19, 0x20, 0x3e, 0xad, 0x5d, 0xc5, 0x19, 0x41, + 0x7f, 0x0c, 0x02, 0x00, 0x87, 0xa2, 0x20, 0x93, 0x88, 0x03, 0xda, 0x39, 0x5d, 0x6e, 0x34, 0x74, + 0x92, 0xab, 0x90, 0x1c, 0xa9, 0x00, 0xc9, 0x41, 0x3e, 0x50, 0xce, 0xfd, 0x31, 0x7d, 0xa1, 0xbd, + 0x8f, 0x68, 0xb4, 0xed, 0xa1, 0x3c, 0xac, 0xa6, 0x5c, 0x69, 0xd7, 0xa2, 0xd9, 0x48, 0xbe, 0xb4, + 0x0f, 0x6d, 0x2d, 0x0e, 0xba, 0x17, 0x78, 0x0f, 0xca, 0x38, 0x6d, 0x41, 0xd3, 0x38, 0xf3, 0xa0, + 0xae, 0x97, 0x09, 0x91, 0xae, 0x4c, 0x58, 0x35, 0xa0, 0x11, 0xfd, 0x14, 0x8e, 0x5d, 0xb8, 0x4e, + 0xbe, 0xcf, 0xb8, 0x1c, 0x54, 0x16, 0x64, 0x87, 0xde, 0x78, 0x69, 0xee, 0xba, 0xbd, 0xac, 0xaa, + 0xbe, 0x2b, 0x8f, 0x17, 0xa4, 0x41, 0x2c, 0x12, 0xac, 0x0a, 0x90, 0x6e, 0x58, 0x8f, 0x37, 0x4e, + 0xfe, 0x8a, 0x31, 0x07, 0xb9, 0x0c, 0xaa, 0x2b, 0xcd, 0x40, 0x8a, 0x9f, 0xc6, 0x8e, 0x5f, 0x28, + 0xc7, 0x92, 0x13, 0xdf, 0xb7, 0xe8, 0x88, 0x06, 0x35, 0x65, 0xeb, 0x23, 0xda, 0xe7, 0xf6, 0xf9, + 0x7c, 0x30, 0x4c, 0x99, 0xd1, 0x78, 0xa3, 0x0f, 0x47, 0x2e, 0x75, 0xb3, 0xda, 0xa9, 0x84, 0x7c, + 0x3c, 0x5f, 0x5b, 0xe5, 0x37, 0xb9, 0xf8, 0x85, 0x1a, 0xd1, 0x9b, 0xd0, 0x3b, 0xc7, 0xac, 0x84, + 0x37, 0xc8, 0x25, 0xc8, 0x55, 0xab, 0x42, 0x06, 0xe8, 0xd2, 0x8d, 0xa0, 0xed, 0xd6, 0x30, 0x64, + 0x62, 0x21, 0x00, 0x60, 0xca, 0x32, 0x8f, 0xab, 0xfd, 0x13, 0xb8, 0x69, 0xb5, 0x07, 0x9c, 0xfb, + 0xce, 0x9e, 0x8d, 0x48, 0x56, 0xc8, 0x43, 0x5a, 0x97, 0x07, 0x00, 0x97, 0x3b, 0xc8, 0x6f, 0x69, + 0x47, 0x61, 0xfa, 0x8a, 0x2e, 0x5c, 0x36, 0x39, 0xdb, 0xdc, 0x83, 0x7a, 0xed, 0x78, 0xd0, 0xf3, + 0xde, 0xaa, 0x29, 0xc0, 0x63, 0x55, 0xc5, 0x21, 0xaf, 0xcb, 0x9b, 0x9d, 0x9b, 0xc7, 0xd7, 0x6d, + 0x03, 0xc4, 0xc1, 0xea, 0x62, 0x4d, 0x58, 0xa1, 0xe6, 0xf2, 0x04, 0xd7, 0x05, 0xe2, 0x53, 0x14, + 0xde, 0xdd, 0x51, 0x82, 0xa7, 0x6b, 0xab, 0x58, 0x2b, 0xf6, 0x15, 0x41, 0xf5, 0x0e, 0x92, 0xff, + 0x64, 0x54, 0x26, 0xca, 0x90, 0x97, 0x95, 0x8a, 0x07, 0x25, 0x39, 0x52, 0x01, 0x3e, 0x7a, 0x66, + 0x1b, 0x4a, 0xf3, 0xd4, 0x21, 0x9d, 0xa3, 0x65, 0x50, 0x7f, 0x69, 0xc9, 0xcd, 0xc2, 0x27, 0xca, + 0x34, 0xe0, 0x72, 0xc3, 0xfb, 0x57, 0x24, 0x8c, 0x0a, 0xdc, 0x42, 0x2b, 0x89, 0x13, 0xe3, 0xf0, + 0xce, 0x0a, 0x54, 0x14, 0x6a, 0x42, 0xea, 0x9b, 0x13, 0xa1, 0x76, 0x3e, 0x5c, 0x80, 0x84, 0x68, + 0x31, 0x16, 0x1c, 0x2e, 0xd0, 0xa0, 0xc1, 0xe7, 0x72, 0xa1, 0x4a, 0x8c, 0x41, 0x4d, 0x79, 0x7e, + 0xd8, 0xce, 0xf7, 0x54, 0x17, 0x61, 0xc9, 0xe5, 0xc1, 0xa8, 0x79, 0x1e, 0x2e, 0xaf, 0x0f, 0xd1, + 0x42, 0x3e, 0x54, 0xb1, 0x12, 0x64, 0x29, 0xe5, 0xc8, 0x50, 0xca, 0x91, 0x9e, 0x9c, 0x80, 0x8c, + 0x14, 0x45, 0x44, 0x7e, 0xb4, 0xdd, 0x2f, 0x54, 0xb0, 0xbf, 0x47, 0xff, 0x0b, 0xc2, 0xc1, 0xff, + 0x50, 0xd6, 0xa0, 0xd6, 0xa0, 0xd6, 0xa0, 0xd6, 0xa0, 0x02, 0xca, 0x3f, 0x64, 0xf7, 0x1a, 0xb6, + 0x98, 0xe1, 0x95, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, + 0x00 }; +static const char CONTENT_ARDUINOOCPP_PNG_ETAG[] PROGMEM = "dd36521eee5eca16ab06b14b0348309a964c5e1219adc69ea5f3c8c37d77f357"; diff --git a/src/web_static/web_server.home.html.h b/src/web_static/web_server.home.html.h index 162758e5..393aafec 100644 --- a/src/web_static/web_server.home.html.h +++ b/src/web_static/web_server.home.html.h @@ -1,5 +1,5 @@ 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:

Serial Consoles

Energy Monitoring

Emoncms Server*:
0 }\">

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:

RFID

Enabled:

Registered tags

Manage scanned tag

0\"> Place your RFID tag on the scanner...
Tag scanned successfully!

UID:


Developer Mode

Enabled:

Serial Consoles

Energy Monitoring

Emoncms Server*:
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 min 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

Required PV power ratio:

The fraction of PV current that suffices to start charging or increment current

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.

OCPP 1.6

Central System URL*:

e.g 'wss://ocpp.my-cpms.com/steve/websocket/CentralSystemService'

Charge box ID*:

ID Tag*:

Transaction start point:

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 min 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

Required PV power ratio:

The fraction of PV current that suffices to start charging or increment current

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.

OCPP 1.6

Central System URL*:

e.g 'wss://ocpp.my-cpms.com/steve/websocket/CentralSystemService'

Charge box ID*:

ID Tag*:

Transaction start point:
\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+H+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+H+\"*(?:value|\"+R+\")\"),e.querySelectorAll(\"[id~=\"+_+\"-]\").length||v.push(\"~=\"),(t=T.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+H+\"*name\"+H+\"*=\"+H+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+_+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.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&&v.push(\"name\"+H+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(d.matchesSelector=ee.test(l=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&le(function(e){d.disconnectedMatch=l.call(e,\"*\"),l.call(e,\"[s!='']:x\"),s.push(\"!=\",$)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),m=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}: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)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==T||e.ownerDocument==b&&m(b,e)?-1:t==T||t.ownerDocument==b&&m(b,t)?1:u?I(u,e)-I(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==T?-1:t==T?1:o?-1:i?1:u?I(u,e)-I(u,t):0;if(o===i)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]==b?-1:s[r]==b?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(C(e),d.matchesSelector&&k&&!A[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=l.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(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=p(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=S[e+\" \"];return t||(t=new RegExp(\"(^|\"+H+\")\"+e+\"(\"+H+\"|$)\"))&&S(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-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)}),d.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(R,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(C);k.find=p,k.expr=p.selectors,k.expr[\":\"]=k.expr.pseudos,k.uniqueSort=k.unique=p.uniqueSort,k.text=p.getText,k.isXMLDoc=p.isXML,k.contains=p.contains,k.escapeSelector=p.escape;function x(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&k(e).is(n))break;r.push(e)}return r}function _(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var E=k.expr.match.needsContext;function S(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function D(e,n,r){return y(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(k.fn.init=function(e,t,n){if(!e)return this;if(n=n||O,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):y(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:A.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:T,!0)),N.test(r[1])&&k.isPlainObject(t))for(var r in t)y(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=T.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=k.fn;var O=k(T),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}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,de=/^$|^module$|\\/(?:java|ecma)script/i;f=T.createDocumentFragment().appendChild(T.createElement(\"div\")),(p=T.createElement(\"input\")).setAttribute(\"type\",\"radio\"),p.setAttribute(\"checked\",\"checked\"),p.setAttribute(\"name\",\"t\"),f.appendChild(p),b.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",b.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",b.option=!!f.lastChild;var pe={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&S(e,t)?k.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var ve=/<|&#?\\w+;/;function me(e,t,n,r,o){for(var i,a,s,u,c,l=t.createDocumentFragment(),f=[],d=0,p=e.length;d\\s*$/g;function Se(e,t){return S(e,\"table\")&&S(11!==t.nodeType?t:t.firstChild,\"tr\")&&k(e).children(\"tbody\")[0]||e}function Ne(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function De(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Ae(e,t){var n,r,o,i;if(1===t.nodeType){if(X.hasData(e)&&(i=X.get(e).events))for(o in X.remove(t,\"handle events\"),i)for(n=0,r=i[o].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",o=function(e){r.remove(),o=null,e&&t(\"error\"===e.type?404:200,e.type)}),T.head.appendChild(r[0])},abort:function(){o&&o()}}});var Gt=[],Xt=/(=)\\?(?=&|$)|\\?\\?/;k.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Gt.pop()||k.expando+\"_\"+St.guid++;return this[e]=!0,e}}),k.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Xt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Xt.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(Xt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Nt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return i||k.error(r+\" was not called\"),i[0]},e.dataTypes[0]=\"json\",o=C[r],C[r]=function(){i=arguments},n.always(function(){void 0===o?k(C).removeProp(r):C[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),i&&y(o)&&o(i[0]),i=o=void 0}),\"script\"}),b.createHTMLDocument=((f=T.implementation.createHTMLDocument(\"\").body).innerHTML=\"

\",2===f.childNodes.length),k.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(b.createHTMLDocument?((r=(t=T.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=T.location.href,t.head.appendChild(r)):t=T),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=me([e],t,r),r&&r.length&&k(r).remove(),k.merge([],n.childNodes)));var r},k.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(\" \");return-1\").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,o,i,a,s=k.css(e,\"position\"),u=k(e),c={};\"static\"===s&&(e.style.position=\"relative\"),i=u.offset(),r=k.css(e,\"top\"),a=k.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(o=(s=u.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),null!=(t=y(t)?t.call(e,n,k.extend({},i)):t).top&&(c.top=t.top-i.top+o),null!=t.left&&(c.left=t.left-i.left+a),\"using\"in t?t.using.call(e,c):u.css(c)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.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],o={top:0,left:0};if(\"fixed\"===k.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\"===k.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=k(e).offset()).top+=k.css(e,\"borderTopWidth\",!0),o.left+=k.css(e,\"borderLeftWidth\",!0))}return{top:t.top-o.top-k.css(r,\"marginTop\",!0),left:t.left-o.left-k.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===k.css(e,\"position\");)e=e.offsetParent;return e||re})}}),k.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,o){var i=\"pageYOffset\"===o;k.fn[t]=function(e){return $(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[o]:e[t]:void(r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),k.each([\"top\",\"left\"],function(e,n){k.cssHooks[n]=Ge(b.pixelPosition,function(e,t){if(t)return t=ze(e,n),$e.test(t)?k(e).position()[n]+\"px\":t})}),k.each({Height:\"height\",Width:\"width\"},function(a,s){k.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,i){k.fn[i]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),o=r||(!0===e||!0===t?\"margin\":\"border\");return $(this,function(e,t,n){var r;return g(e)?0===i.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?k.css(e,t,o):k.style(e,t,n,o)},s,n?e:void 0,n)}})}),k.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.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)}}),k.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){k.fn[n]=function(e,t){return 0(e=e||\"\").length)&&e.substring(0,t.length)===t},vd: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},Sb:function(e){return N.a.vd(e,e.ownerDocument.documentElement)},kd:function(e){return!!N.a.Lb(e,N.a.Sb)},R:function(e){return e&&e.tagName&&e.tagName.toLowerCase()},Ac:function(e){return N.onError?function(){try{return e.apply(this,arguments)}catch(e){throw N.onError&&N.onError(e),e}}:e},setTimeout:(c=function(e,t){return setTimeout(N.a.Ac(e),t)},h.toString=function(){return c.toString()},h),Gc:function(e){setTimeout(function(){throw N.onError&&N.onError(e),e},0)},B:function(t,e,n){var r=N.a.Ac(n);if(n=l[e],N.options.useOnlyNativeEvents||n||!Ne)if(n||\"function\"!=typeof t.addEventListener){if(void 0===t.attachEvent)throw Error(\"Browser doesn't support addEventListener or attachEvent\");var o=function(e){r.call(t,e)},i=\"on\"+e;t.attachEvent(i,o),N.a.K.za(t,function(){t.detachEvent(i,o)})}else t.addEventListener(e,r,!1);else u=u||(\"function\"==typeof Ne(t).on?\"on\":\"bind\"),Ne(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=!(\"input\"!==N.a.R(e)||!e.type||\"click\"!=t.toLowerCase())&&(\"checkbox\"==(n=e.type)||\"radio\"==n);if(N.options.useOnlyNativeEvents||!Ne||n)if(\"function\"==typeof Ee.createEvent){if(\"function\"!=typeof e.dispatchEvent)throw Error(\"The supplied element doesn't support dispatchEvent\");(n=Ee.createEvent(s[t]||\"HTMLEvents\")).initEvent(t,!0,!0,_e,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 Ne(e).trigger(t)},f:function(e){return N.O(e)?e():e},bc:function(e){return N.O(e)?e.v():e},Eb:function(t,e,n){var r;e&&(\"object\"===_typeof(t.classList)?(r=t.classList[n?\"add\":\"remove\"],N.a.D(e.match(p),function(e){r.call(t.classList,e)})):\"string\"==typeof t.className.baseVal?o(t.className,\"baseVal\",e,n):o(t,\"className\",e,n))},Bb:function(e,t){var n=N.a.f(t);null!==n&&n!==ke||(n=\"\");t=N.h.firstChild(e);!t||3!=t.nodeType||N.h.nextSibling(t)?N.h.va(e,[e.ownerDocument.createTextNode(n)]):t.data=n,N.a.Ad(e)},Yc:function(e,t){if(e.name=t,d<=7)try{var n=e.name.replace(/[&<>'\"]/g,function(e){return\"&#\"+e.charCodeAt(0)+\";\"});e.mergeAttributes(Ee.createElement(\"\"),!1)}catch(e){}},Ad:function(e){9<=d&&((e=1==e.nodeType?e:e.parentNode).style&&(e.style.zoom=e.style.zoom))},wd:function(e){var t;d&&(t=e.style.width,e.style.width=0,e.style.width=t)},Pd:function(e,t){e=N.a.f(e),t=N.a.f(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:e,tfoot:e,tr:[2,\"\",\"
\"],td:e=[3,\"\",\"
\"],th:e,option:e=[1,\"\"],optgroup:e},f=N.a.W<=8,N.a.ua=function(e,t){var n;if(Ne){if(Ne.parseHTML)n=Ne.parseHTML(e,t)||[];else if((n=Ne.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{var r=(n=!(n=t)?Ee:n).parentWindow||n.defaultView||_e,o=N.a.Db(e).toLowerCase(),i=n.createElement(\"div\"),t=(o=o.match(/^(?:\\x3c!--.*?--\\x3e\\s*?)*?<([a-z]+)[\\s>]/))&&l[o[1]]||u,o=t[0];for(t=\"ignored
\"+t[1]+e+t[2]+\"
\",\"function\"==typeof r.innerShiv?i.appendChild(r.innerShiv(t)):(f&&n.body.appendChild(i),i.innerHTML=t,f&&i.parentNode.removeChild(i));o--;)i=i.lastChild;n=N.a.la(i.lastChild.childNodes)}return n},N.a.Md=function(e,t){t=N.a.ua(e,t);return t.length&&t[0].parentElement||N.a.Yb(t)},N.a.fc=function(e,t){if(N.a.Tb(e),null!==(t=N.a.f(t))&&t!==ke)if(\"string\"!=typeof t&&(t=t.toString()),Ne)Ne(e).html(t);else for(var n=N.a.ua(t,e.ownerDocument),r=0;r]*))?)*\\s+)data-bind\\s*=\\s*([\"'])([\\s\\S]*?)\\3/gi,be=/\\x3c!--\\s*ko\\b\\s*([\\s\\S]*?)\\s*--\\x3e/g,{xd:function(e,t,n){t.isTemplateRewritten(e,n)||t.rewriteTemplate(e,function(e){return N.kc.Ld(e,t)},n)},Ld:function(e,i){return e.replace(me,function(e,t,n,r,o){return Ce(o,t,n,i)}).replace(be,function(e,t){return Ce(t,\"\\x3c!-- ko --\\x3e\",\"#comment\",i)})},md:function(n,r){return N.aa.Xb(function(e,t){e=e.nextSibling;e&&e.nodeName.toLowerCase()===r&&N.ib(e,n,t)})}}),N.b(\"__tr_ambtns\",N.kc.md),function(){N.C={},N.C.F=function(e){var t;(this.F=e)&&(t=N.a.R(e),this.ab=\"script\"===t?1:\"textarea\"===t?2:\"template\"==t&&e.content&&11===e.content.nodeType?3:4)},N.C.F.prototype.text=function(){var e=1===this.ab?\"text\":2===this.ab?\"value\":\"innerHTML\";if(0==arguments.length)return this.F[e];var t=arguments[0];\"innerHTML\"==e?N.a.fc(this.F,t):this.F[e]=t};var t=N.a.g.Z()+\"_\";N.C.F.prototype.data=function(e){if(1===arguments.length)return N.a.g.get(this.F,t+e);N.a.g.set(this.F,t+e,arguments[1])};var o=N.a.g.Z();N.C.F.prototype.nodes=function(){var e=this.F;if(0==arguments.length){var t,n=N.a.g.get(e,o)||{},r=n.lb||(3===this.ab?e.content:4===this.ab?e:ke);return r&&!n.jd||(t=this.text())&&t!==n.bb&&(r=N.a.Md(t,e.ownerDocument),N.a.g.set(e,o,{lb:r,bb:t,jd:!0})),r}n=arguments[0],this.ab!==ke&&this.text(\"\"),N.a.g.set(e,o,{lb:n})},N.C.ia=function(e){this.F=e},N.C.ia.prototype=new N.C.F,N.C.ia.prototype.constructor=N.C.ia,N.C.ia.prototype.text=function(){if(0==arguments.length){var e=N.a.g.get(this.F,o)||{};return e.bb===ke&&e.lb&&(e.bb=e.lb.innerHTML),e.bb}N.a.g.set(this.F,o,{bb:arguments[0]})},N.b(\"templateSources\",N.C),N.b(\"templateSources.domElement\",N.C.F),N.b(\"templateSources.anonymousTemplate\",N.C.ia)}(),function(){function r(e,t,n){var r;for(t=N.h.nextSibling(t);e&&(r=e)!==t;)n(r,e=N.h.nextSibling(r))}function d(e,t){if(e.length){var o=e[0],i=e[e.length-1],n=o.parentNode,a=N.ga.instance,s=a.preprocessNode;if(s){if(r(o,i,function(e,t){var n=e.previousSibling,r=s.call(a,e);r&&(e===o&&(o=r[0]||t),e===i&&(i=r[r.length-1]||n))}),e.length=0,!o)return;o===i?e.push(o):(e.push(o,i),N.a.Ua(e,n))}r(o,i,function(e){1!==e.nodeType&&8!==e.nodeType||N.vc(t,e)}),r(o,i,function(e){1!==e.nodeType&&8!==e.nodeType||N.aa.cd(e,[t])}),N.a.Ua(e,n)}}function u(e){return e.nodeType?e:0\"+t+\"<\\/script>\")},0>10|55296,1023&e|56320))}function r(){C()}var e,d,w,o,i,p,h,g,x,u,c,C,k,a,_,v,s,l,m,T=\"sizzle\"+ +new Date,b=n.document,E=0,y=0,S=ue(),N=ue(),D=ue(),A=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+~]|\"+B+\")\"+B+\"*\"),z=new RegExp(B+\"|>\"),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)(?:\\\\(\"+B+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+B+\"*(?:([+-]|)\"+B+\"*(\\\\d+)|))\"+B+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+B+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+B+\"*((?:-\\\\d)?\\\\d*)\"+B+\"*\\\\)|)(?=[^-]|$)\",\"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}\"+B+\"?|\\\\\\\\([^\\\\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=be(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{L.apply(t=P.call(b.childNodes),b.childNodes),t[b.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=e&&e.ownerDocument,f=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==f&&9!==f&&11!==f)return n;if(!r&&(C(e),e=e||k,_)){if(11!==f&&(s=te.exec(t)))if(c=s[1]){if(9===f){if(!(o=e.getElementById(c)))return n;if(o.id===c)return n.push(o),n}else if(l&&(o=l.getElementById(c))&&m(e,o)&&o.id===c)return n.push(o),n}else{if(s[2])return L.apply(n,e.getElementsByTagName(t)),n;if((c=s[3])&&d.getElementsByClassName&&e.getElementsByClassName)return L.apply(n,e.getElementsByClassName(c)),n}if(d.qsa&&!A[t+\" \"]&&(!v||!v.test(t))&&(1!==f||\"object\"!==e.nodeName.toLowerCase())){if(c=t,l=e,1===f&&(z.test(t)||J.test(t))){for((l=ne.test(t)&&ge(e.parentNode)||e)===e&&d.scope||((a=e.getAttribute(\"id\"))?a=a.replace(ie,oe):e.setAttribute(\"id\",a=T)),i=(u=p(t)).length;i--;)u[i]=(a?\"#\"+a:\":scope\")+\" \"+me(u[i]);c=u.join(\",\")}try{return L.apply(n,l.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{a===T&&e.removeAttribute(\"id\")}}}return g(t.replace(V,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>w.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function ce(e){return e[T]=!0,e}function le(e){var t=k.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}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\"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 he(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 ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,e=e&&(e.ownerDocument||e).documentElement;return!K.test(t||e&&e.nodeName||\"HTML\")},C=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:b;return e!=k&&9===e.nodeType&&e.documentElement&&(a=(k=e).documentElement,_=!i(k),b!=k&&(t=k.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),d.scope=le(function(e){return a.appendChild(e).appendChild(k.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),d.attributes=le(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),d.getElementsByTagName=le(function(e){return e.appendChild(k.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),d.getElementsByClassName=ee.test(k.getElementsByClassName),d.getById=le(function(e){return a.appendChild(e).id=T,!k.getElementsByName||!k.getElementsByName(T).length}),d.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&&_){e=t.getElementById(e);return e?[e]:[]}}):(w.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&_){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=d.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):d.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=d.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&_)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=ee.test(k.querySelectorAll))&&(le(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+B+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+B+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+T+\"-]\").length||v.push(\"~=\"),(t=k.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+B+\"*name\"+B+\"*=\"+B+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+T+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.push(\"[\\\\r\\\\n\\\\f]\")}),le(function(e){e.innerHTML=\"\";var t=k.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&v.push(\"name\"+B+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(d.matchesSelector=ee.test(l=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&le(function(e){d.disconnectedMatch=l.call(e,\"*\"),l.call(e,\"[s!='']:x\"),s.push(\"!=\",$)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),m=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}: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)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==k||e.ownerDocument==b&&m(b,e)?-1:t==k||t.ownerDocument==b&&m(b,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==k?-1:t==k?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]==b?-1:s[r]==b?1:0}),k},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(C(e),d.matchesSelector&&_&&!A[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=l.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(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=p(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=S[e+\" \"];return t||(t=new RegExp(\"(^|\"+B+\")\"+e+\"(\"+B+\"|$)\"))&&S(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-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)}),d.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(I,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(C);_.find=p,_.expr=p.selectors,_.expr[\":\"]=_.expr.pseudos,_.uniqueSort=_.unique=p.uniqueSort,_.text=p.getText,_.isXMLDoc=p.isXML,_.contains=p.contains,_.escapeSelector=p.escape;function x(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&_(e).is(n))break;r.push(e)}return r}function T(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var E=_.expr.match.needsContext;function S(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function D(e,n,r){return y(n)?_.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?_.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?_.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(_.fn.init=function(e,t,n){if(!e)return this;if(n=n||O,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):y(e)?void 0!==n.ready?n.ready(e):e(_):_.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:A.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof _?t[0]:t,_.merge(this,_.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:k,!0)),N.test(r[1])&&_.isPlainObject(t))for(var r in t)y(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=k.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=_.fn;var O=_(k),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}_.fn.extend({has:function(e){var t=_(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,de=/^$|^module$|\\/(?:java|ecma)script/i;f=k.createDocumentFragment().appendChild(k.createElement(\"div\")),(p=k.createElement(\"input\")).setAttribute(\"type\",\"radio\"),p.setAttribute(\"checked\",\"checked\"),p.setAttribute(\"name\",\"t\"),f.appendChild(p),b.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",b.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",b.option=!!f.lastChild;var pe={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&S(e,t)?_.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var ve=/<|&#?\\w+;/;function me(e,t,n,r,i){for(var o,a,s,u,c,l=t.createDocumentFragment(),f=[],d=0,p=e.length;d\\s*$/g;function Se(e,t){return S(e,\"table\")&&S(11!==t.nodeType?t:t.firstChild,\"tr\")&&_(e).children(\"tbody\")[0]||e}function Ne(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function De(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Ae(e,t){var n,r,i,o;if(1===t.nodeType){if(X.hasData(e)&&(o=X.get(e).events))for(i in X.remove(t,\"handle events\"),o)for(n=0,r=o[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 Gt=[],Xt=/(=)\\?(?=&|$)|\\?\\?/;_.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Gt.pop()||_.expando+\"_\"+St.guid++;return this[e]=!0,e}}),_.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Xt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Xt.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(Xt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Nt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return o||_.error(r+\" was not called\"),o[0]},e.dataTypes[0]=\"json\",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?_(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&y(i)&&i(o[0]),o=i=void 0}),\"script\"}),b.createHTMLDocument=((f=k.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),_.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),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=me([e],t,r),r&&r.length&&_(r).remove(),_.merge([],n.childNodes)));var r},_.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(\" \");return-1\").append(_.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},_.expr.pseudos.animated=function(t){return _.grep(_.timers,function(e){return t===e.elem}).length},_.offset={setOffset:function(e,t,n){var r,i,o,a,s=_.css(e,\"position\"),u=_(e),c={};\"static\"===s&&(e.style.position=\"relative\"),o=u.offset(),r=_.css(e,\"top\"),a=_.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(i=(s=u.position()).top,s.left):(i=parseFloat(r)||0,parseFloat(a)||0),null!=(t=y(t)?t.call(e,n,_.extend({},o)):t).top&&(c.top=t.top-o.top+i),null!=t.left&&(c.left=t.left-o.left+a),\"using\"in t?t.using.call(e,c):u.css(c)}},_.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){_.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.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\"===_.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\"===_.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=_(e).offset()).top+=_.css(e,\"borderTopWidth\",!0),i.left+=_.css(e,\"borderLeftWidth\",!0))}return{top:t.top-i.top-_.css(r,\"marginTop\",!0),left:t.left-i.left-_.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===_.css(e,\"position\");)e=e.offsetParent;return e||re})}}),_.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,i){var o=\"pageYOffset\"===i;_.fn[t]=function(e){return $(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[i]:e[t]:void(r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),_.each([\"top\",\"left\"],function(e,n){_.cssHooks[n]=Ge(b.pixelPosition,function(e,t){if(t)return t=ze(e,n),$e.test(t)?_(e).position()[n]+\"px\":t})}),_.each({Height:\"height\",Width:\"width\"},function(a,s){_.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,o){_.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 g(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?_.css(e,t,i):_.style(e,t,n,i)},s,n?e:void 0,n)}})}),_.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){_.fn[t]=function(e){return this.on(t,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)}}),_.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){_.fn[n]=function(e,t){return 0(e=e||\"\").length)&&e.substring(0,t.length)===t},vd: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},Sb:function(e){return N.a.vd(e,e.ownerDocument.documentElement)},kd:function(e){return!!N.a.Lb(e,N.a.Sb)},R:function(e){return e&&e.tagName&&e.tagName.toLowerCase()},Ac:function(e){return N.onError?function(){try{return e.apply(this,arguments)}catch(e){throw N.onError&&N.onError(e),e}}:e},setTimeout:(c=function(e,t){return setTimeout(N.a.Ac(e),t)},h.toString=function(){return c.toString()},h),Gc:function(e){setTimeout(function(){throw N.onError&&N.onError(e),e},0)},B:function(t,e,n){var r=N.a.Ac(n);if(n=l[e],N.options.useOnlyNativeEvents||n||!Ne)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),N.a.K.za(t,function(){t.detachEvent(o,i)})}else t.addEventListener(e,r,!1);else u=u||(\"function\"==typeof Ne(t).on?\"on\":\"bind\"),Ne(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=!(\"input\"!==N.a.R(e)||!e.type||\"click\"!=t.toLowerCase())&&(\"checkbox\"==(n=e.type)||\"radio\"==n);if(N.options.useOnlyNativeEvents||!Ne||n)if(\"function\"==typeof Ee.createEvent){if(\"function\"!=typeof e.dispatchEvent)throw Error(\"The supplied element doesn't support dispatchEvent\");(n=Ee.createEvent(s[t]||\"HTMLEvents\")).initEvent(t,!0,!0,Te,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 Ne(e).trigger(t)},f:function(e){return N.O(e)?e():e},bc:function(e){return N.O(e)?e.v():e},Eb:function(t,e,n){var r;e&&(\"object\"===_typeof(t.classList)?(r=t.classList[n?\"add\":\"remove\"],N.a.D(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))},Bb:function(e,t){var n=N.a.f(t);null!==n&&n!==_e||(n=\"\");t=N.h.firstChild(e);!t||3!=t.nodeType||N.h.nextSibling(t)?N.h.va(e,[e.ownerDocument.createTextNode(n)]):t.data=n,N.a.Ad(e)},Yc:function(e,t){if(e.name=t,d<=7)try{var n=e.name.replace(/[&<>'\"]/g,function(e){return\"&#\"+e.charCodeAt(0)+\";\"});e.mergeAttributes(Ee.createElement(\"\"),!1)}catch(e){}},Ad:function(e){9<=d&&((e=1==e.nodeType?e:e.parentNode).style&&(e.style.zoom=e.style.zoom))},wd:function(e){var t;d&&(t=e.style.width,e.style.width=0,e.style.width=t)},Pd:function(e,t){e=N.a.f(e),t=N.a.f(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:e,tfoot:e,tr:[2,\"\",\"
\"],td:e=[3,\"\",\"
\"],th:e,option:e=[1,\"\"],optgroup:e},f=N.a.W<=8,N.a.ua=function(e,t){var n;if(Ne){if(Ne.parseHTML)n=Ne.parseHTML(e,t)||[];else if((n=Ne.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{var r=(n=!(n=t)?Ee:n).parentWindow||n.defaultView||Te,i=N.a.Db(e).toLowerCase(),o=n.createElement(\"div\"),t=(i=i.match(/^(?:\\x3c!--.*?--\\x3e\\s*?)*?<([a-z]+)[\\s>]/))&&l[i[1]]||u,i=t[0];for(t=\"ignored
\"+t[1]+e+t[2]+\"
\",\"function\"==typeof r.innerShiv?o.appendChild(r.innerShiv(t)):(f&&n.body.appendChild(o),o.innerHTML=t,f&&o.parentNode.removeChild(o));i--;)o=o.lastChild;n=N.a.la(o.lastChild.childNodes)}return n},N.a.Md=function(e,t){t=N.a.ua(e,t);return t.length&&t[0].parentElement||N.a.Yb(t)},N.a.fc=function(e,t){if(N.a.Tb(e),null!==(t=N.a.f(t))&&t!==_e)if(\"string\"!=typeof t&&(t=t.toString()),Ne)Ne(e).html(t);else for(var n=N.a.ua(t,e.ownerDocument),r=0;r]*))?)*\\s+)data-bind\\s*=\\s*([\"'])([\\s\\S]*?)\\3/gi,be=/\\x3c!--\\s*ko\\b\\s*([\\s\\S]*?)\\s*--\\x3e/g,{xd:function(e,t,n){t.isTemplateRewritten(e,n)||t.rewriteTemplate(e,function(e){return N.kc.Ld(e,t)},n)},Ld:function(e,o){return e.replace(me,function(e,t,n,r,i){return Ce(i,t,n,o)}).replace(be,function(e,t){return Ce(t,\"\\x3c!-- ko --\\x3e\",\"#comment\",o)})},md:function(n,r){return N.aa.Xb(function(e,t){e=e.nextSibling;e&&e.nodeName.toLowerCase()===r&&N.ib(e,n,t)})}}),N.b(\"__tr_ambtns\",N.kc.md),function(){N.C={},N.C.F=function(e){var t;(this.F=e)&&(t=N.a.R(e),this.ab=\"script\"===t?1:\"textarea\"===t?2:\"template\"==t&&e.content&&11===e.content.nodeType?3:4)},N.C.F.prototype.text=function(){var e=1===this.ab?\"text\":2===this.ab?\"value\":\"innerHTML\";if(0==arguments.length)return this.F[e];var t=arguments[0];\"innerHTML\"==e?N.a.fc(this.F,t):this.F[e]=t};var t=N.a.g.Z()+\"_\";N.C.F.prototype.data=function(e){if(1===arguments.length)return N.a.g.get(this.F,t+e);N.a.g.set(this.F,t+e,arguments[1])};var i=N.a.g.Z();N.C.F.prototype.nodes=function(){var e=this.F;if(0==arguments.length){var t,n=N.a.g.get(e,i)||{},r=n.lb||(3===this.ab?e.content:4===this.ab?e:_e);return r&&!n.jd||(t=this.text())&&t!==n.bb&&(r=N.a.Md(t,e.ownerDocument),N.a.g.set(e,i,{lb:r,bb:t,jd:!0})),r}n=arguments[0],this.ab!==_e&&this.text(\"\"),N.a.g.set(e,i,{lb:n})},N.C.ia=function(e){this.F=e},N.C.ia.prototype=new N.C.F,N.C.ia.prototype.constructor=N.C.ia,N.C.ia.prototype.text=function(){if(0==arguments.length){var e=N.a.g.get(this.F,i)||{};return e.bb===_e&&e.lb&&(e.bb=e.lb.innerHTML),e.bb}N.a.g.set(this.F,i,{bb:arguments[0]})},N.b(\"templateSources\",N.C),N.b(\"templateSources.domElement\",N.C.F),N.b(\"templateSources.anonymousTemplate\",N.C.ia)}(),function(){function r(e,t,n){var r;for(t=N.h.nextSibling(t);e&&(r=e)!==t;)n(r,e=N.h.nextSibling(r))}function d(e,t){if(e.length){var i=e[0],o=e[e.length-1],n=i.parentNode,a=N.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),N.a.Ua(e,n))}r(i,o,function(e){1!==e.nodeType&&8!==e.nodeType||N.vc(t,e)}),r(i,o,function(e){1!==e.nodeType&&8!==e.nodeType||N.aa.cd(e,[t])}),N.a.Ua(e,n)}}function u(e){return e.nodeType?e:0\"+t+\"<\\/script>\")},0>10|55296,1023&e|56320))}function r(){T()}var e,p,b,i,o,d,h,g,w,u,l,T,C,a,S,m,s,c,y,E=\"sizzle\"+ +new Date,v=n.document,k=0,x=0,A=ue(),N=ue(),j=ue(),D=ue(),q=function(e,t){return e===t&&(l=!0),0},L={}.hasOwnProperty,t=[],H=t.pop,O=t.push,P=t.push,R=t.slice,M=function(e,t){for(var n=0,r=e.length;n+~]|\"+W+\")\"+W+\"*\"),V=new RegExp(W+\"|>\"),G=new RegExp(F),Y=new RegExp(\"^\"+_+\"$\"),Q={ID:new RegExp(\"^#(\"+_+\")\"),CLASS:new RegExp(\"^\\\\.(\"+_+\")\"),TAG:new RegExp(\"^(\"+_+\"|[*])\"),ATTR:new RegExp(\"^\"+$),PSEUDO:new RegExp(\"^\"+F),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+W+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+W+\"*(?:([+-]|)\"+W+\"*(\\\\d+)|))\"+W+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+W+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+W+\"*((?:-\\\\d)?\\\\d*)\"+W+\"*\\\\)|)(?=[^-]|$)\",\"i\")},J=/HTML$/i,K=/^(?: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}\"+W+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),oe=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"�\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},ae=ve(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{P.apply(t=R.call(v.childNodes),v.childNodes),t[v.childNodes.length].nodeType}catch(e){P={apply:t.length?function(e,t){O.apply(e,R.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 o,i,a,s,u,l,c=e&&e.ownerDocument,f=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==f&&9!==f&&11!==f)return n;if(!r&&(T(e),e=e||C,S)){if(11!==f&&(s=te.exec(t)))if(l=s[1]){if(9===f){if(!(i=e.getElementById(l)))return n;if(i.id===l)return n.push(i),n}else if(c&&(i=c.getElementById(l))&&y(e,i)&&i.id===l)return n.push(i),n}else{if(s[2])return P.apply(n,e.getElementsByTagName(t)),n;if((l=s[3])&&p.getElementsByClassName&&e.getElementsByClassName)return P.apply(n,e.getElementsByClassName(l)),n}if(p.qsa&&!D[t+\" \"]&&(!m||!m.test(t))&&(1!==f||\"object\"!==e.nodeName.toLowerCase())){if(l=t,c=e,1===f&&(V.test(t)||X.test(t))){for((c=ne.test(t)&&ge(e.parentNode)||e)===e&&p.scope||((a=e.getAttribute(\"id\"))?a=a.replace(oe,ie):e.setAttribute(\"id\",a=E)),o=(u=d(t)).length;o--;)u[o]=(a?\"#\"+a:\":scope\")+\" \"+ye(u[o]);l=u.join(\",\")}try{return P.apply(n,c.querySelectorAll(l)),n}catch(e){D(t,!0)}finally{a===E&&e.removeAttribute(\"id\")}}}return g(t.replace(z,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>b.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function le(e){return e[E]=!0,e}function ce(e){var t=C.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}function fe(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)b.attrHandle[n[r]]=t}function pe(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 de(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 he(a){return le(function(i){return i=+i,le(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in p=se.support={},o=se.isXML=function(e){var t=e&&e.namespaceURI,e=e&&(e.ownerDocument||e).documentElement;return!J.test(t||e&&e.nodeName||\"HTML\")},T=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:v;return e!=C&&9===e.nodeType&&e.documentElement&&(a=(C=e).documentElement,S=!o(C),v!=C&&(t=C.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),p.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),p.attributes=ce(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),p.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),p.getElementsByClassName=ee.test(C.getElementsByClassName),p.getById=ce(function(e){return a.appendChild(e).id=E,!C.getElementsByName||!C.getElementsByName(E).length}),p.getById?(b.filter.ID=function(e){var t=e.replace(re,f);return function(e){return e.getAttribute(\"id\")===t}},b.find.ID=function(e,t){if(void 0!==t.getElementById&&S){e=t.getElementById(e);return e?[e]:[]}}):(b.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},b.find.ID=function(e,t){if(void 0!==t.getElementById&&S){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i]}return[]}}),b.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=[],o=0,i=t.getElementsByTagName(e);if(\"*\"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},b.find.CLASS=p.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&S)return t.getElementsByClassName(e)},s=[],m=[],(p.qsa=ee.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&m.push(\"[*^$]=\"+W+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||m.push(\"\\\\[\"+W+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+E+\"-]\").length||m.push(\"~=\"),(t=C.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||m.push(\"\\\\[\"+W+\"*name\"+W+\"*=\"+W+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||m.push(\":checked\"),e.querySelectorAll(\"a#\"+E+\"+*\").length||m.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),m.push(\"[\\\\r\\\\n\\\\f]\")}),ce(function(e){e.innerHTML=\"\";var t=C.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&m.push(\"name\"+W+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&m.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&m.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),m.push(\",.*:\")})),(p.matchesSelector=ee.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){p.disconnectedMatch=c.call(e,\"*\"),c.call(e,\"[s!='']:x\"),s.push(\"!=\",F)}),m=m.length&&new RegExp(m.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),y=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},q=t?function(e,t){if(e===t)return l=!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==C||e.ownerDocument==v&&y(v,e)?-1:t==C||t.ownerDocument==v&&y(v,t)?1:u?M(u,e)-M(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==C?-1:t==C?1:o?-1:i?1:u?M(u,e)-M(u,t):0;if(o===i)return pe(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?pe(a[r],s[r]):a[r]==v?-1:s[r]==v?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),p.matchesSelector&&S&&!D[t+\" \"]&&(!s||!s.test(t))&&(!m||!m.test(t)))try{var n=c.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 Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&G.test(n)&&(t=d(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=A[e+\" \"];return t||(t=new RegExp(\"(^|\"+W+\")\"+e+\"(\"+W+\"|$)\"))&&A(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-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&&ce(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}),ce(function(e){return null==e.getAttribute(\"disabled\")})||fe(I,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(T);S.find=d,S.expr=d.selectors,S.expr[\":\"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;function w(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&S(e).is(n))break;r.push(e)}return r}function E(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function j(e,n,r){return x(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(S.fn.init=function(e,t,n){if(!e)return this;if(n=n||q,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):x(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:D.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),N.test(r[1])&&S.isPlainObject(t))for(var r in t)x(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=C.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=S.fn;var q=S(C),L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,pe=/^$|^module$|\\/(?:java|ecma)script/i;f=C.createDocumentFragment().appendChild(C.createElement(\"div\")),(d=C.createElement(\"input\")).setAttribute(\"type\",\"radio\"),d.setAttribute(\"checked\",\"checked\"),d.setAttribute(\"name\",\"t\"),f.appendChild(d),v.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",v.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",v.option=!!f.lastChild;var de={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&A(e,t)?S.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var me=/<|&#?\\w+;/;function ye(e,t,n,r,o){for(var i,a,s,u,l,c=t.createDocumentFragment(),f=[],p=0,d=e.length;p\\s*$/g;function Ae(e,t){return A(e,\"table\")&&A(11!==t.nodeType?t:t.firstChild,\"tr\")&&S(e).children(\"tbody\")[0]||e}function Ne(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function je(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function De(e,t){var n,r,o,i;if(1===t.nodeType){if(Y.hasData(e)&&(i=Y.get(e).events))for(o in Y.remove(t,\"handle events\"),i)for(n=0,r=i[o].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",o=function(e){r.remove(),o=null,e&&t(\"error\"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){o&&o()}}});var Gt=[],Yt=/(=)\\?(?=&|$)|\\?\\?/;S.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Gt.pop()||S.expando+\"_\"+At.guid++;return this[e]=!0,e}}),S.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Yt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Yt.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=x(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Nt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return i||S.error(r+\" was not called\"),i[0]},e.dataTypes[0]=\"json\",o=T[r],T[r]=function(){i=arguments},n.always(function(){void 0===o?S(T).removeProp(r):T[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),i&&x(o)&&o(i[0]),i=o=void 0}),\"script\"}),v.createHTMLDocument=((f=C.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),S.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=C.location.href,t.head.appendChild(r)):t=C),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=ye([e],t,r),r&&r.length&&S(r).remove(),S.merge([],n.childNodes)));var r},S.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(\" \");return-1\").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,o,i,a,s=S.css(e,\"position\"),u=S(e),l={};\"static\"===s&&(e.style.position=\"relative\"),i=u.offset(),r=S.css(e,\"top\"),a=S.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(o=(s=u.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),null!=(t=x(t)?t.call(e,n,S.extend({},i)):t).top&&(l.top=t.top-i.top+o),null!=t.left&&(l.left=t.left-i.left+a),\"using\"in t?t.using.call(e,l):u.css(l)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.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],o={top:0,left:0};if(\"fixed\"===S.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\"===S.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=S(e).offset()).top+=S.css(e,\"borderTopWidth\",!0),o.left+=S.css(e,\"borderLeftWidth\",!0))}return{top:t.top-o.top-S.css(r,\"marginTop\",!0),left:t.left-o.left-S.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===S.css(e,\"position\");)e=e.offsetParent;return e||re})}}),S.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,o){var i=\"pageYOffset\"===o;S.fn[t]=function(e){return F(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[o]:e[t]:void(r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),S.each([\"top\",\"left\"],function(e,n){S.cssHooks[n]=Ge(v.pixelPosition,function(e,t){if(t)return t=Ve(e,n),Fe.test(t)?S(e).position()[n]+\"px\":t})}),S.each({Height:\"height\",Width:\"width\"},function(a,s){S.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,i){S.fn[i]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),o=r||(!0===e||!0===t?\"margin\":\"border\");return F(this,function(e,t,n){var r;return g(e)?0===i.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?S.css(e,t,o):S.style(e,t,n,o)},s,n?e:void 0,n)}})}),S.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.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)}}),S.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){S.fn[n]=function(e,t){return 0 Date: Sun, 20 Mar 2022 16:12:15 +0000 Subject: [PATCH 10/20] Changes to build with the latest ESP32 core --- .gitignore | 2 -- CMakeLists.txt | 3 --- platformio.ini | 24 +++++++++++++----------- sdkconfig.defaults | 18 ------------------ src/lcd.cpp | 2 +- 5 files changed, 14 insertions(+), 35 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 sdkconfig.defaults diff --git a/.gitignore b/.gitignore index 58169f85..f559f3e0 100644 --- a/.gitignore +++ b/.gitignore @@ -90,5 +90,3 @@ lib/StreamSpy lib/MicroTasks *.bin - -sdkconfig diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 00a24c59..00000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -cmake_minimum_required(VERSION 3.16.0) -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(OpenEVSE_WiFi) diff --git a/platformio.ini b/platformio.ini index 8c7703c5..65f32152 100644 --- a/platformio.ini +++ b/platformio.ini @@ -43,7 +43,8 @@ lib_deps = erropix/ESP32 AnalogWrite@0.2 lorol/LittleFS_esp32@1.0.5 ; matth-x/ArduinoOcpp@0.0.4 - https://github.com/matth-x/ArduinoOcpp.git#d4f705caf10bcdd1311512664a2d8c15c4a2db5d + ; https://github.com/matth-x/ArduinoOcpp.git#d4f705caf10bcdd1311512664a2d8c15c4a2db5d + https://github.com/jeremypoulter/ArduinoOcpp.git#72bbab2322362375c8d3c757e0fb650e028a02fd lib_ignore = WebSockets ; ArduinoOcpp: don't compile built-in WS library extra_scripts = scripts/extra_script.py debug_flags = @@ -65,7 +66,6 @@ src_build_flags = # -D ARDUINOJSON_USE_LONG_LONG # -D ENABLE_ASYNC_WIFI_SCAN build_flags = - -D ARDUINO=250 -D ESP32 -D CS_PLATFORM=CS_P_ESP32 -D MG_ENABLE_SSL=1 @@ -89,6 +89,9 @@ build_flags = #-D ENABLE_DEBUG_MONGOOSE_HTTP_CLIENT -D RAPI_MAX_COMMANDS=20 -D BUILD_ENV_NAME="$PIOENV" + -D ARDUINO_ARCH_ESP32 + -D USE_ESP32 + -D USE_ESP32_FRAMEWORK_ARDUINO build_partitions = min_spiffs.csv neopixel_lib = adafruit/Adafruit NeoPixel@1.7.0 @@ -100,8 +103,9 @@ neopixel_lib = adafruit/Adafruit NeoPixel@1.7.0 #platform = https://github.com/platformio/platform-espressif32.git#feature/stage #platform = https://github.com/platformio/platform-espressif32.git#develop #platform = espressif32@1.11.1 -platform = espressif32 -framework = arduino, espidf +platform = espressif32@3.5.0 +#framework = arduino, espidf +framework = arduino lib_deps = ${common.lib_deps} lib_ignore = ${common.lib_ignore} build_flags = @@ -112,8 +116,9 @@ monitor_speed = 115200 extra_scripts = ${common.extra_scripts} board_build.partitions = ${common.build_partitions} platform_packages = - ; use a special branch - framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 +# ; use a special branch +# framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 + platformio/framework-arduinoespressif32 @ ~3.10006.0 monitor_flags = --filter=esp32_exception_decoder @@ -224,7 +229,7 @@ build_flags = -D I2C_SDA=21 -D I2C_SCL=22 -D ENABLE_MCP9808 - -D TX1=16 + -D TX1=16 [env:openevse_esp32-gateway] #For hardware older than RevE @@ -247,7 +252,6 @@ build_flags = # Tested working with hardware RevE and RevF #https://github.com/OpenEVSE/ESP32_WiFi_V3.x/blob/master/docs/wired-ethernet.md extends = env:openevse_esp32-gateway -framework = arduino, espidf build_flags = ${common.build_flags} ${common.version} @@ -269,8 +273,8 @@ upload_speed = 921600 board = heltec_wifi_lora_32_V2 build_flags = ${common.build_flags} - ${common.version} ${common.src_build_flags} + ${common.version}.dev -D WIFI_LED=33 -D WIFI_LED_ON_STATE=HIGH -D WIFI_BUTTON=34 @@ -279,8 +283,6 @@ build_flags = -D RAPI_PORT=Serial2 -D ENABLE_WIRED_ETHERNET -D RANDOM_SEED_CHANNEL=1 - ${common.version}.dev - ${common.src_build_flags} -D WIFI_LED=25 -D WIFI_BUTTON=2 -D WIFI_LED_ON_STATE=HIGH diff --git a/sdkconfig.defaults b/sdkconfig.defaults deleted file mode 100644 index ea87d468..00000000 --- a/sdkconfig.defaults +++ /dev/null @@ -1,18 +0,0 @@ -# Override some defaults to enable Arduino framework -CONFIG_ENABLE_ARDUINO_DEPENDS=y -CONFIG_AUTOSTART_ARDUINO=y -CONFIG_ARDUINO_RUN_CORE1=y -CONFIG_ARDUINO_RUNNING_CORE=1 -CONFIG_ARDUINO_EVENT_RUN_CORE1=y -CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 -CONFIG_ARDUINO_UDP_RUN_CORE1=y -CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -#CONFIG_DISABLE_HAL_LOCKS=y -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 -CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y -CONFIG_ARDUHAL_PARTITION_SCHEME="default" -#CONFIG_AUTOCONNECT_WIFI=y -#CONFIG_ARDUINO_SELECTIVE_WiFi=y -CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y diff --git a/src/lcd.cpp b/src/lcd.cpp index 5b8ff114..606485f5 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -8,7 +8,7 @@ #include "openevse.h" #include "input.h" #include "app_config.h" -#include +#include static void IGNORE(int ret) { } From 33051ad82e95816765cd93def9ecff51bb4342cc Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 20 Mar 2022 16:12:30 +0000 Subject: [PATCH 11/20] Latest GUI --- gui | 2 +- src/web_static/web_server.home.js.h | 6 ++-- src/web_static/web_server.lib.js.h | 6 ++-- src/web_static/web_server.term.js.h | 2 +- test/ovms.http | 49 +++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 test/ovms.http diff --git a/gui b/gui index c58bd513..bfd5e1f2 160000 --- a/gui +++ b/gui @@ -1 +1 @@ -Subproject commit c58bd513a62c0d17c2f25a361b10c8ce7ae7cba6 +Subproject commit bfd5e1f22d73d16ef9616873e23b2d05177f0d2d diff --git a/src/web_static/web_server.home.js.h b/src/web_static/web_server.home.js.h index e7354eb2..cda28e1c 100644 --- a/src/web_static/web_server.home.js.h +++ b/src/web_static/web_server.home.js.h @@ -1,4 +1,4 @@ -static const char CONTENT_HOME_JS[] PROGMEM = - "\"use strict\";function _createForOfIteratorHelper(e,t){var n=\"undefined\"!=typeof Symbol&&e[Symbol.iterator]||e[\"@@iterator\"];if(!n){if(Array.isArray(e)||(n=_unsupportedIterableToArray(e))||t&&e&&\"number\"==typeof e.length){n&&(e=n);var o=0,t=function(){};return{s:t,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:t}}throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")}var r,a=!0,i=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){i=!0,r=e},f:function(){try{a||null==n.return||n.return()}finally{if(i)throw r}}}}function _unsupportedIterableToArray(e,t){if(e){if(\"string\"==typeof e)return _arrayLikeToArray(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return\"Map\"===(n=\"Object\"===n&&e.constructor?e.constructor.name:n)||\"Set\"===n?Array.from(e):\"Arguments\"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);n= 0 = no time limit\"}]},{cmd:\"G4\",ret:ko.observable(\"\"),description:\"get auth lock (needs AUTH_LOCK defined and AUTH_LOCK_REG undefined)\",tokens:[{name:\"lockstate\",val:ko.observable(\"\"),description:\"0=unlocked, 1=locked\"}]},{cmd:\"GA\",ret:ko.observable(\"\"),description:\"get ammeter settings\",tokens:[{name:\"currentscalefactor\",val:ko.observable(\"\"),description:\"\"},{name:\"currentoffset\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GC\",ret:ko.observable(\"\"),description:\"get current capacity info, all values are decimal.
n.b. maxamps,emaxamps values are dependent on the active service level (L1/L2)\",tokens:[{name:\"minamps\",val:ko.observable(\"\"),description:\"min allowed current capacity\"},{name:\"hmaxamps\",val:ko.observable(\"\"),description:\"max hardware allowed current capacity MAX_CURRENT_CAPACITY_Ln\"},{name:\"pilotamps\",val:ko.observable(\"\"),description:\"current capacity advertised by pilot\"},{name:\"cmaxamps\",val:ko.observable(\"\"),description:\"max configured allowed current capacity (saved to EEPROM)\"}]},{cmd:\"GD\",ret:ko.observable(\"\"),description:\"get Delay timer, all values decimal, if timer disabled, starthr=startmin=endhr=endmin=0\",tokens:[{name:\"starthr\",val:ko.observable(\"\"),description:\"\"},{name:\"startmin\",val:ko.observable(\"\"),description:\"\"},{name:\"endhr\",val:ko.observable(\"\"),description:\"\"},{name:\"endmin\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GE\",ret:ko.observable(\"\"),description:\"get settings\",tokens:[{name:\"amps\",val:ko.observable(\"\"),description:\"(decimal)\"},{name:\"flags\",val:r.flags,description:\"(hex)\",parsed:ko.computed(function(){var e=[],t=parseInt(r.flags(),16);if(!isNaN(t))for(var n in o)Object.hasOwnProperty.call(o,n)&&t&o[n]&&e.push({val:n});return e})}]},{cmd:\"GF\",ret:ko.observable(\"\"),description:\"get fault counters, all values hex, maximum trip count = 0xFF for any counter\",tokens:[{name:\"gfitripcnt\",val:ko.observable(\"\"),description:\"\"},{name:\"nogndtripcnt\",val:ko.observable(\"\"),description:\"\"},{name:\"stuckrelaytripcnt\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GG\",ret:ko.observable(\"\"),description:\"get charging current and voltage. AMMETER must be defined in order to get amps, otherwise returns -1 amps\",tokens:[{name:\"milliamps\",val:ko.observable(\"\"),description:\"\"},{name:\"millivolts\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GH\",ret:ko.observable(\"\"),description:\"get cHarge limit\",tokens:[{name:\"kWh\",val:ko.observable(\"\"),description:\"0 = no charge limit\"}]},{cmd:\"GI\",ret:ko.observable(\"\"),description:\"get MCU ID - requires MCU_ID_LEN to be defined.
n.b. MCU_ID_LEN must be defined in order to get MCU ID WARNING: mcuid is guaranteed to be unique only for the 328PB. Uniqueness is unknown in 328P. The first 6 characters are ASCII, and the rest are hexadecimal.\",tokens:[{name:\"mcuid\",val:ko.observable(\"\"),description:\"AVR serial number, mcuid is 6 ASCII characters followed by 4 hex digits. First hex digit = FF for 328P\"}]},{cmd:\"GM\",ret:ko.observable(\"\"),description:\"get voltMeter settings\",tokens:[{name:\"voltcalefactor\",val:ko.observable(\"\"),description:\"\"},{name:\"voltoffset\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GO\",ret:ko.observable(\"\"),description:\"get Overtemperature thresholds, thresholds are in 10ths of a degree Celcius\",tokens:[{name:\"ambientthresh\",val:ko.observable(\"\"),description:\"\"},{name:\"irthresh\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GP\",ret:ko.observable(\"\"),description:\"get temPerature (v1.0.3+), all temperatures are in 10th's of a degree Celcius
if any temperature sensor is not installed, its return value is -2560\",tokens:[{name:\"ds3231temp\",val:ko.observable(\"\"),description:\"temperature from DS3231 RTC\"},{name:\"mcp9808temp\",val:ko.observable(\"\"),description:\"temperature from MCP9808\"},{name:\"tmp007temp\",val:ko.observable(\"\"),description:\"temperature from TMP007\"}]},{cmd:\"GS\",ret:ko.observable(\"\"),description:\"get state\",tokens:[{name:\"evsestate\",val:r.evsestate,description:\"(hex), EVSE_STATE_xxx\",parsed:ko.computed(function(){var e=parseInt(r.evsestate(),16);return!isNaN(e)&&e in t?[{val:t[e]}]:[{val:\"UNKNOWN\"}]})},{name:\"elapsed\",val:ko.observable(\"\"),description:\"(dec), elapsed charge time in seconds of current or last charging session\"},{name:\"pilotstate\",val:r.pilotstate,description:\"(hex), EVSE_STATE_xxx\",parsed:ko.computed(function(){var e=parseInt(r.pilotstate(),16);return!isNaN(e)&&e in t?[{val:t[e]}]:[{val:\"UNKNOWN\"}]})},{name:\"vflags\",val:r.vflags,description:\"(hex), EVCF_xxx\",parsed:ko.computed(function(){var e=[],t=parseInt(r.vflags(),16);if(!isNaN(t))for(var n in a)Object.hasOwnProperty.call(a,n)&&t&a[n]&&e.push({val:n});return e})}]},{cmd:\"GT\",ret:ko.observable(\"\"),description:\"get time (RTC)\",tokens:[{name:\"yr\",val:ko.observable(\"\"),description:\"2-digit year\"},{name:\"mo\",val:ko.observable(\"\"),description:\"\"},{name:\"day\",val:ko.observable(\"\"),description:\"\"},{name:\"hr\",val:ko.observable(\"\"),description:\"\"},{name:\"min\",val:ko.observable(\"\"),description:\"\"},{name:\"sec\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GU\",ret:ko.observable(\"\"),description:\"get energy usage (v1.0.3+)\",tokens:[{name:\"Wattseconds\",val:ko.observable(\"\"),description:\"Watt-seconds used this charging session, note you'll divide Wattseconds by 3600 to get Wh\"},{name:\"Whacc\",val:ko.observable(\"\"),description:\"total Wh accumulated over all charging sessions, note you'll divide Wh by 1000 to get kWh\"}]},{cmd:\"GV\",ret:ko.observable(\"\"),description:\"get version\",tokens:[{name:\"firmware_version\",val:ko.observable(\"\"),description:\"\"},{name:\"protocol_version\",val:ko.observable(\"\"),description:\"protocol_version is deprecated. too hard to maintain variants, ignore it, and test commands for compatibility, instead.\"}]},{cmd:\"GY\",ret:ko.observable(\"\"),description:\"Get Hearbeat Supervision Status\",tokens:[{name:\"heartbeatinterval\",val:ko.observable(\"\"),description:\"\"},{name:\"hearbeatcurrentlimit\",val:ko.observable(\"\"),description:\"\"},{name:\"hearbeattrigger\",val:ko.observable(\"\"),description:\"0 - There has never been a missed pulse,
2 - there is a missed pulse, and HS is still in current limit
1 - There was a missed pulse once, but it has since been acknkoledged. Ampacity has been successfully restored to max permitted \"}]}],r.readCount=ko.observable(0),r.read=function(){r.reading(!0),r.readCount(0),r.readNext()},r.regex=/\\$([^^]*)(\\^..)?/,r.readNext=function(){var o;r.readCount()\"+e.ret),r.cmd(e.cmd),r.history(r.history()+\"> \"+e.cmd+\"
< \"+e.ret+\"
\")},\"json\").always(function(){r.rapiSend(!1)})},r.clear=function(){r.history(\"\")}}function TimeViewModel(t){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.vehicleUpdateNow=ko.observable(new Date(0)),o.vehicleUpdateLocal=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(\":\"),e=o.evseTimedate();e.setHours(parseInt(t[0])),e.setMinutes(parseInt(t[1])),o.evseTimedate(e),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)}),t.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)}),t.divert_update.subscribe(function(e){o.divertUpdateNow(new Date(1e3*e)),o.divertUpdateLocal(new Date)}),o.vehicle_state_update=ko.pureComputed(function(){if(null===o.nowTimedate())return!1;var e=o.vehicleUpdateNow().getTime();return Math.floor(e/1e3)}),t.vehicle_state_update.subscribe(function(e){o.vehicleUpdateNow(new Date(1e3*e)),o.vehicleUpdateLocal(new Date)});var n=null;o.automaticTime=ko.observable(!0),o.timeUpdate=function(e){o.hasRTC(!(1=e){o.timeLimit(n.value);break}}},o.selectChargeLimit=function(e){if(o.chargeLimit()!==e)for(var t=0;t=e){o.chargeLimit(n.value);break}}};var a=[function(){return!1===t.time()?o.openevse.time(o.time.timeUpdate):new DummyRequest},function(){return o.openevse.time_limit(function(e){o.selectTimeLimit(e)})},function(){return o.openevse.charge_limit(function(e){o.selectChargeLimit(e)})}];o.updateCount=ko.observable(0),o.updateTotal=ko.observable(a.length),o.updatingTimeLimit=ko.observable(!1),o.savedTimeLimit=ko.observable(!1),o.updatingChargeLimit=ko.observable(!1),o.savedChargeLimit=ko.observable(!1),o.setForTime=function(e,t){e(!0),setTimeout(function(){e(!1)},t)};var i=!(o.generateCurrentList=function(){var e=n.min_current_hard(),t=n.max_current_hard(),t=o.createCurrentArray(e,t);ko.mapping.fromJS(t,{},o.currentLevels)});function s(e){return/([01]\\d|2[0-3]):([0-5]\\d)/.test(e)}o.subscribe=function(){i||(n.min_current_hard.subscribe(function(){o.generateCurrentList()}),n.max_current_hard.subscribe(function(){n.max_current_soft()>n.max_current_hard()&&n.max_current_soft(n.max_current_hard()),o.generateCurrentList()}),o.generateCurrentList(),o.timeLimit.subscribe(function(t){o.updatingTimeLimit(!0),o.openevse.time_limit(function(e){o.setForTime(o.savedTimeLimit,2e3),t!==e&&o.selectTimeLimit(e)},t).always(function(){o.updatingTimeLimit(!1)})}),o.chargeLimit.subscribe(function(t){o.updatingChargeLimit(!0),o.openevse.charge_limit(function(e){o.setForTime(o.savedChargeLimit,2e3),t!==e&&o.selectChargeLimit(e)},t).always(function(){o.updatingChargeLimit(!1)})}),i=!0)},o.update=function(){var e=0a.min()}),this.events=ko.observableArray([]),this.fetching=ko.observable(!1),this.fetchingBlock=ko.observable(!1),this.update=function(){var e=0a.min()&&a.updateNext()})},\"json\").always(function(){a.fetching(!1),e()})},this.updateNext=function(){n(a.block()-1)};var s=-1,c=0,n=function(r){var e=1=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:t}}throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")}var r,a=!0,i=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){i=!0,r=e},f:function(){try{a||null==n.return||n.return()}finally{if(i)throw r}}}}function _unsupportedIterableToArray(e,t){if(e){if(\"string\"==typeof e)return _arrayLikeToArray(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return\"Map\"===(n=\"Object\"===n&&e.constructor?e.constructor.name:n)||\"Set\"===n?Array.from(e):\"Arguments\"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);n= 0 = no time limit\"}]},{cmd:\"G4\",ret:ko.observable(\"\"),description:\"get auth lock (needs AUTH_LOCK defined and AUTH_LOCK_REG undefined)\",tokens:[{name:\"lockstate\",val:ko.observable(\"\"),description:\"0=unlocked, 1=locked\"}]},{cmd:\"GA\",ret:ko.observable(\"\"),description:\"get ammeter settings\",tokens:[{name:\"currentscalefactor\",val:ko.observable(\"\"),description:\"\"},{name:\"currentoffset\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GC\",ret:ko.observable(\"\"),description:\"get current capacity info, all values are decimal.
n.b. maxamps,emaxamps values are dependent on the active service level (L1/L2)\",tokens:[{name:\"minamps\",val:ko.observable(\"\"),description:\"min allowed current capacity\"},{name:\"hmaxamps\",val:ko.observable(\"\"),description:\"max hardware allowed current capacity MAX_CURRENT_CAPACITY_Ln\"},{name:\"pilotamps\",val:ko.observable(\"\"),description:\"current capacity advertised by pilot\"},{name:\"cmaxamps\",val:ko.observable(\"\"),description:\"max configured allowed current capacity (saved to EEPROM)\"}]},{cmd:\"GD\",ret:ko.observable(\"\"),description:\"get Delay timer, all values decimal, if timer disabled, starthr=startmin=endhr=endmin=0\",tokens:[{name:\"starthr\",val:ko.observable(\"\"),description:\"\"},{name:\"startmin\",val:ko.observable(\"\"),description:\"\"},{name:\"endhr\",val:ko.observable(\"\"),description:\"\"},{name:\"endmin\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GE\",ret:ko.observable(\"\"),description:\"get settings\",tokens:[{name:\"amps\",val:ko.observable(\"\"),description:\"(decimal)\"},{name:\"flags\",val:r.flags,description:\"(hex)\",parsed:ko.computed(function(){var e=[],t=parseInt(r.flags(),16);if(!isNaN(t))for(var n in o)Object.hasOwnProperty.call(o,n)&&t&o[n]&&e.push({val:n});return e})}]},{cmd:\"GF\",ret:ko.observable(\"\"),description:\"get fault counters, all values hex, maximum trip count = 0xFF for any counter\",tokens:[{name:\"gfitripcnt\",val:ko.observable(\"\"),description:\"\"},{name:\"nogndtripcnt\",val:ko.observable(\"\"),description:\"\"},{name:\"stuckrelaytripcnt\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GG\",ret:ko.observable(\"\"),description:\"get charging current and voltage. AMMETER must be defined in order to get amps, otherwise returns -1 amps\",tokens:[{name:\"milliamps\",val:ko.observable(\"\"),description:\"\"},{name:\"millivolts\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GH\",ret:ko.observable(\"\"),description:\"get cHarge limit\",tokens:[{name:\"kWh\",val:ko.observable(\"\"),description:\"0 = no charge limit\"}]},{cmd:\"GI\",ret:ko.observable(\"\"),description:\"get MCU ID - requires MCU_ID_LEN to be defined.
n.b. MCU_ID_LEN must be defined in order to get MCU ID WARNING: mcuid is guaranteed to be unique only for the 328PB. Uniqueness is unknown in 328P. The first 6 characters are ASCII, and the rest are hexadecimal.\",tokens:[{name:\"mcuid\",val:ko.observable(\"\"),description:\"AVR serial number, mcuid is 6 ASCII characters followed by 4 hex digits. First hex digit = FF for 328P\"}]},{cmd:\"GM\",ret:ko.observable(\"\"),description:\"get voltMeter settings\",tokens:[{name:\"voltcalefactor\",val:ko.observable(\"\"),description:\"\"},{name:\"voltoffset\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GO\",ret:ko.observable(\"\"),description:\"get Overtemperature thresholds, thresholds are in 10ths of a degree Celcius\",tokens:[{name:\"ambientthresh\",val:ko.observable(\"\"),description:\"\"},{name:\"irthresh\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GP\",ret:ko.observable(\"\"),description:\"get temPerature (v1.0.3+), all temperatures are in 10th's of a degree Celcius
if any temperature sensor is not installed, its return value is -2560\",tokens:[{name:\"ds3231temp\",val:ko.observable(\"\"),description:\"temperature from DS3231 RTC\"},{name:\"mcp9808temp\",val:ko.observable(\"\"),description:\"temperature from MCP9808\"},{name:\"tmp007temp\",val:ko.observable(\"\"),description:\"temperature from TMP007\"}]},{cmd:\"GS\",ret:ko.observable(\"\"),description:\"get state\",tokens:[{name:\"evsestate\",val:r.evsestate,description:\"(hex), EVSE_STATE_xxx\",parsed:ko.computed(function(){var e=parseInt(r.evsestate(),16);return!isNaN(e)&&e in t?[{val:t[e]}]:[{val:\"UNKNOWN\"}]})},{name:\"elapsed\",val:ko.observable(\"\"),description:\"(dec), elapsed charge time in seconds of current or last charging session\"},{name:\"pilotstate\",val:r.pilotstate,description:\"(hex), EVSE_STATE_xxx\",parsed:ko.computed(function(){var e=parseInt(r.pilotstate(),16);return!isNaN(e)&&e in t?[{val:t[e]}]:[{val:\"UNKNOWN\"}]})},{name:\"vflags\",val:r.vflags,description:\"(hex), EVCF_xxx\",parsed:ko.computed(function(){var e=[],t=parseInt(r.vflags(),16);if(!isNaN(t))for(var n in a)Object.hasOwnProperty.call(a,n)&&t&a[n]&&e.push({val:n});return e})}]},{cmd:\"GT\",ret:ko.observable(\"\"),description:\"get time (RTC)\",tokens:[{name:\"yr\",val:ko.observable(\"\"),description:\"2-digit year\"},{name:\"mo\",val:ko.observable(\"\"),description:\"\"},{name:\"day\",val:ko.observable(\"\"),description:\"\"},{name:\"hr\",val:ko.observable(\"\"),description:\"\"},{name:\"min\",val:ko.observable(\"\"),description:\"\"},{name:\"sec\",val:ko.observable(\"\"),description:\"\"}]},{cmd:\"GU\",ret:ko.observable(\"\"),description:\"get energy usage (v1.0.3+)\",tokens:[{name:\"Wattseconds\",val:ko.observable(\"\"),description:\"Watt-seconds used this charging session, note you'll divide Wattseconds by 3600 to get Wh\"},{name:\"Whacc\",val:ko.observable(\"\"),description:\"total Wh accumulated over all charging sessions, note you'll divide Wh by 1000 to get kWh\"}]},{cmd:\"GV\",ret:ko.observable(\"\"),description:\"get version\",tokens:[{name:\"firmware_version\",val:ko.observable(\"\"),description:\"\"},{name:\"protocol_version\",val:ko.observable(\"\"),description:\"protocol_version is deprecated. too hard to maintain variants, ignore it, and test commands for compatibility, instead.\"}]},{cmd:\"GY\",ret:ko.observable(\"\"),description:\"Get Hearbeat Supervision Status\",tokens:[{name:\"heartbeatinterval\",val:ko.observable(\"\"),description:\"\"},{name:\"hearbeatcurrentlimit\",val:ko.observable(\"\"),description:\"\"},{name:\"hearbeattrigger\",val:ko.observable(\"\"),description:\"0 - There has never been a missed pulse,
2 - there is a missed pulse, and HS is still in current limit
1 - There was a missed pulse once, but it has since been acknkoledged. Ampacity has been successfully restored to max permitted \"}]}],r.readCount=ko.observable(0),r.read=function(){r.reading(!0),r.readCount(0),r.readNext()},r.regex=/\\$([^^]*)(\\^..)?/,r.readNext=function(){var o;r.readCount()\"+e.ret),r.cmd(e.cmd),r.history(r.history()+\"> \"+e.cmd+\"
< \"+e.ret+\"
\")},\"json\").always(function(){r.rapiSend(!1)})},r.clear=function(){r.history(\"\")}}function TimeZoneViewModel(e){this.name=ko.observable(e.name),this.value=ko.observable(e.name+\"|\"+e.tz)}function ZonesViewModel(e){var o=this,t=ko.pureComputed(function(){return e()+\"/zones.json\"});o.fetching=ko.observable(!1),o.zones=ko.mapping.fromJS([],{key:function(e){return ko.utils.unwrapObservable(e.name)},create:function(e){return new TimeZoneViewModel(e.data)}}),o.initialValue=function(e){e=e.split(\"|\",2);2==e.length?o.zones.push(new TimeZoneViewModel({name:e[0],tz:e[1]})):o.zones.push(new TimeZoneViewModel({name:\"Default\",tz:e[1]}))},o.update=function(){var e=0=e){o.timeLimit(n.value);break}}},o.selectChargeLimit=function(e){if(o.chargeLimit()!==e)for(var t=0;t=e){o.chargeLimit(n.value);break}}};var a=[function(){return!1===t.time()?o.openevse.time(o.time.timeUpdate):new DummyRequest},function(){return o.openevse.time_limit(function(e){o.selectTimeLimit(e)})},function(){return o.openevse.charge_limit(function(e){o.selectChargeLimit(e)})}];o.updateCount=ko.observable(0),o.updateTotal=ko.observable(a.length),o.updatingTimeLimit=ko.observable(!1),o.savedTimeLimit=ko.observable(!1),o.updatingChargeLimit=ko.observable(!1),o.savedChargeLimit=ko.observable(!1),o.setForTime=function(e,t){e(!0),setTimeout(function(){e(!1)},t)};var i=!(o.generateCurrentList=function(){var e=n.min_current_hard(),t=n.max_current_hard(),t=o.createCurrentArray(e,t);ko.mapping.fromJS(t,{},o.currentLevels)});function s(e){return/([01]\\d|2[0-3]):([0-5]\\d)/.test(e)}o.subscribe=function(){i||(n.min_current_hard.subscribe(function(){o.generateCurrentList()}),n.max_current_hard.subscribe(function(){n.max_current_soft()>n.max_current_hard()&&n.max_current_soft(n.max_current_hard()),o.generateCurrentList()}),o.generateCurrentList(),o.timeLimit.subscribe(function(t){o.updatingTimeLimit(!0),o.openevse.time_limit(function(e){o.setForTime(o.savedTimeLimit,2e3),t!==e&&o.selectTimeLimit(e)},t).always(function(){o.updatingTimeLimit(!1)})}),o.chargeLimit.subscribe(function(t){o.updatingChargeLimit(!0),o.openevse.charge_limit(function(e){o.setForTime(o.savedChargeLimit,2e3),t!==e&&o.selectChargeLimit(e)},t).always(function(){o.updatingChargeLimit(!1)})}),i=!0)},o.update=function(){var e=0a.min()}),this.events=ko.observableArray([]),this.fetching=ko.observable(!1),this.fetchingBlock=ko.observable(!1),this.update=function(){var e=0a.min()&&a.updateNext()})},\"json\").always(function(){a.fetching(!1),e()})},this.updateNext=function(){n(a.block()-1)};var s=-1,c=0,n=function(r){var e=1>10|55296,1023&e|56320))}function r(){C()}var e,d,w,o,i,p,h,g,x,u,c,C,k,a,_,v,s,l,m,T=\"sizzle\"+ +new Date,b=n.document,E=0,y=0,S=ue(),N=ue(),D=ue(),A=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+~]|\"+B+\")\"+B+\"*\"),z=new RegExp(B+\"|>\"),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)(?:\\\\(\"+B+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+B+\"*(?:([+-]|)\"+B+\"*(\\\\d+)|))\"+B+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+B+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+B+\"*((?:-\\\\d)?\\\\d*)\"+B+\"*\\\\)|)(?=[^-]|$)\",\"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}\"+B+\"?|\\\\\\\\([^\\\\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=be(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{L.apply(t=P.call(b.childNodes),b.childNodes),t[b.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=e&&e.ownerDocument,f=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==f&&9!==f&&11!==f)return n;if(!r&&(C(e),e=e||k,_)){if(11!==f&&(s=te.exec(t)))if(c=s[1]){if(9===f){if(!(o=e.getElementById(c)))return n;if(o.id===c)return n.push(o),n}else if(l&&(o=l.getElementById(c))&&m(e,o)&&o.id===c)return n.push(o),n}else{if(s[2])return L.apply(n,e.getElementsByTagName(t)),n;if((c=s[3])&&d.getElementsByClassName&&e.getElementsByClassName)return L.apply(n,e.getElementsByClassName(c)),n}if(d.qsa&&!A[t+\" \"]&&(!v||!v.test(t))&&(1!==f||\"object\"!==e.nodeName.toLowerCase())){if(c=t,l=e,1===f&&(z.test(t)||J.test(t))){for((l=ne.test(t)&&ge(e.parentNode)||e)===e&&d.scope||((a=e.getAttribute(\"id\"))?a=a.replace(ie,oe):e.setAttribute(\"id\",a=T)),i=(u=p(t)).length;i--;)u[i]=(a?\"#\"+a:\":scope\")+\" \"+me(u[i]);c=u.join(\",\")}try{return L.apply(n,l.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{a===T&&e.removeAttribute(\"id\")}}}return g(t.replace(V,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>w.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function ce(e){return e[T]=!0,e}function le(e){var t=k.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}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\"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 he(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 ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,e=e&&(e.ownerDocument||e).documentElement;return!K.test(t||e&&e.nodeName||\"HTML\")},C=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:b;return e!=k&&9===e.nodeType&&e.documentElement&&(a=(k=e).documentElement,_=!i(k),b!=k&&(t=k.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),d.scope=le(function(e){return a.appendChild(e).appendChild(k.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),d.attributes=le(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),d.getElementsByTagName=le(function(e){return e.appendChild(k.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),d.getElementsByClassName=ee.test(k.getElementsByClassName),d.getById=le(function(e){return a.appendChild(e).id=T,!k.getElementsByName||!k.getElementsByName(T).length}),d.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&&_){e=t.getElementById(e);return e?[e]:[]}}):(w.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&_){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=d.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):d.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=d.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&_)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=ee.test(k.querySelectorAll))&&(le(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+B+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+B+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+T+\"-]\").length||v.push(\"~=\"),(t=k.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+B+\"*name\"+B+\"*=\"+B+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+T+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.push(\"[\\\\r\\\\n\\\\f]\")}),le(function(e){e.innerHTML=\"\";var t=k.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&v.push(\"name\"+B+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(d.matchesSelector=ee.test(l=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&le(function(e){d.disconnectedMatch=l.call(e,\"*\"),l.call(e,\"[s!='']:x\"),s.push(\"!=\",$)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),m=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}: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)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==k||e.ownerDocument==b&&m(b,e)?-1:t==k||t.ownerDocument==b&&m(b,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==k?-1:t==k?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]==b?-1:s[r]==b?1:0}),k},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(C(e),d.matchesSelector&&_&&!A[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=l.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(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=p(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=S[e+\" \"];return t||(t=new RegExp(\"(^|\"+B+\")\"+e+\"(\"+B+\"|$)\"))&&S(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-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)}),d.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(I,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(C);_.find=p,_.expr=p.selectors,_.expr[\":\"]=_.expr.pseudos,_.uniqueSort=_.unique=p.uniqueSort,_.text=p.getText,_.isXMLDoc=p.isXML,_.contains=p.contains,_.escapeSelector=p.escape;function x(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&_(e).is(n))break;r.push(e)}return r}function T(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var E=_.expr.match.needsContext;function S(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function D(e,n,r){return y(n)?_.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?_.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?_.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(_.fn.init=function(e,t,n){if(!e)return this;if(n=n||O,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):y(e)?void 0!==n.ready?n.ready(e):e(_):_.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:A.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof _?t[0]:t,_.merge(this,_.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:k,!0)),N.test(r[1])&&_.isPlainObject(t))for(var r in t)y(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=k.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=_.fn;var O=_(k),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}_.fn.extend({has:function(e){var t=_(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,de=/^$|^module$|\\/(?:java|ecma)script/i;f=k.createDocumentFragment().appendChild(k.createElement(\"div\")),(p=k.createElement(\"input\")).setAttribute(\"type\",\"radio\"),p.setAttribute(\"checked\",\"checked\"),p.setAttribute(\"name\",\"t\"),f.appendChild(p),b.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",b.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",b.option=!!f.lastChild;var pe={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&S(e,t)?_.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var ve=/<|&#?\\w+;/;function me(e,t,n,r,i){for(var o,a,s,u,c,l=t.createDocumentFragment(),f=[],d=0,p=e.length;d\\s*$/g;function Se(e,t){return S(e,\"table\")&&S(11!==t.nodeType?t:t.firstChild,\"tr\")&&_(e).children(\"tbody\")[0]||e}function Ne(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function De(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Ae(e,t){var n,r,i,o;if(1===t.nodeType){if(X.hasData(e)&&(o=X.get(e).events))for(i in X.remove(t,\"handle events\"),o)for(n=0,r=o[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 Gt=[],Xt=/(=)\\?(?=&|$)|\\?\\?/;_.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Gt.pop()||_.expando+\"_\"+St.guid++;return this[e]=!0,e}}),_.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Xt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Xt.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(Xt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Nt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return o||_.error(r+\" was not called\"),o[0]},e.dataTypes[0]=\"json\",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?_(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&y(i)&&i(o[0]),o=i=void 0}),\"script\"}),b.createHTMLDocument=((f=k.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),_.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),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=me([e],t,r),r&&r.length&&_(r).remove(),_.merge([],n.childNodes)));var r},_.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(\" \");return-1\").append(_.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},_.expr.pseudos.animated=function(t){return _.grep(_.timers,function(e){return t===e.elem}).length},_.offset={setOffset:function(e,t,n){var r,i,o,a,s=_.css(e,\"position\"),u=_(e),c={};\"static\"===s&&(e.style.position=\"relative\"),o=u.offset(),r=_.css(e,\"top\"),a=_.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(i=(s=u.position()).top,s.left):(i=parseFloat(r)||0,parseFloat(a)||0),null!=(t=y(t)?t.call(e,n,_.extend({},o)):t).top&&(c.top=t.top-o.top+i),null!=t.left&&(c.left=t.left-o.left+a),\"using\"in t?t.using.call(e,c):u.css(c)}},_.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){_.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.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\"===_.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\"===_.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=_(e).offset()).top+=_.css(e,\"borderTopWidth\",!0),i.left+=_.css(e,\"borderLeftWidth\",!0))}return{top:t.top-i.top-_.css(r,\"marginTop\",!0),left:t.left-i.left-_.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===_.css(e,\"position\");)e=e.offsetParent;return e||re})}}),_.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,i){var o=\"pageYOffset\"===i;_.fn[t]=function(e){return $(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[i]:e[t]:void(r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),_.each([\"top\",\"left\"],function(e,n){_.cssHooks[n]=Ge(b.pixelPosition,function(e,t){if(t)return t=ze(e,n),$e.test(t)?_(e).position()[n]+\"px\":t})}),_.each({Height:\"height\",Width:\"width\"},function(a,s){_.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,o){_.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 g(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?_.css(e,t,i):_.style(e,t,n,i)},s,n?e:void 0,n)}})}),_.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){_.fn[t]=function(e){return this.on(t,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)}}),_.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){_.fn[n]=function(e,t){return 0(e=e||\"\").length)&&e.substring(0,t.length)===t},vd: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},Sb:function(e){return N.a.vd(e,e.ownerDocument.documentElement)},kd:function(e){return!!N.a.Lb(e,N.a.Sb)},R:function(e){return e&&e.tagName&&e.tagName.toLowerCase()},Ac:function(e){return N.onError?function(){try{return e.apply(this,arguments)}catch(e){throw N.onError&&N.onError(e),e}}:e},setTimeout:(c=function(e,t){return setTimeout(N.a.Ac(e),t)},h.toString=function(){return c.toString()},h),Gc:function(e){setTimeout(function(){throw N.onError&&N.onError(e),e},0)},B:function(t,e,n){var r=N.a.Ac(n);if(n=l[e],N.options.useOnlyNativeEvents||n||!Ne)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),N.a.K.za(t,function(){t.detachEvent(o,i)})}else t.addEventListener(e,r,!1);else u=u||(\"function\"==typeof Ne(t).on?\"on\":\"bind\"),Ne(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=!(\"input\"!==N.a.R(e)||!e.type||\"click\"!=t.toLowerCase())&&(\"checkbox\"==(n=e.type)||\"radio\"==n);if(N.options.useOnlyNativeEvents||!Ne||n)if(\"function\"==typeof Ee.createEvent){if(\"function\"!=typeof e.dispatchEvent)throw Error(\"The supplied element doesn't support dispatchEvent\");(n=Ee.createEvent(s[t]||\"HTMLEvents\")).initEvent(t,!0,!0,Te,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 Ne(e).trigger(t)},f:function(e){return N.O(e)?e():e},bc:function(e){return N.O(e)?e.v():e},Eb:function(t,e,n){var r;e&&(\"object\"===_typeof(t.classList)?(r=t.classList[n?\"add\":\"remove\"],N.a.D(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))},Bb:function(e,t){var n=N.a.f(t);null!==n&&n!==_e||(n=\"\");t=N.h.firstChild(e);!t||3!=t.nodeType||N.h.nextSibling(t)?N.h.va(e,[e.ownerDocument.createTextNode(n)]):t.data=n,N.a.Ad(e)},Yc:function(e,t){if(e.name=t,d<=7)try{var n=e.name.replace(/[&<>'\"]/g,function(e){return\"&#\"+e.charCodeAt(0)+\";\"});e.mergeAttributes(Ee.createElement(\"\"),!1)}catch(e){}},Ad:function(e){9<=d&&((e=1==e.nodeType?e:e.parentNode).style&&(e.style.zoom=e.style.zoom))},wd:function(e){var t;d&&(t=e.style.width,e.style.width=0,e.style.width=t)},Pd:function(e,t){e=N.a.f(e),t=N.a.f(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:e,tfoot:e,tr:[2,\"\",\"
\"],td:e=[3,\"\",\"
\"],th:e,option:e=[1,\"\"],optgroup:e},f=N.a.W<=8,N.a.ua=function(e,t){var n;if(Ne){if(Ne.parseHTML)n=Ne.parseHTML(e,t)||[];else if((n=Ne.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{var r=(n=!(n=t)?Ee:n).parentWindow||n.defaultView||Te,i=N.a.Db(e).toLowerCase(),o=n.createElement(\"div\"),t=(i=i.match(/^(?:\\x3c!--.*?--\\x3e\\s*?)*?<([a-z]+)[\\s>]/))&&l[i[1]]||u,i=t[0];for(t=\"ignored
\"+t[1]+e+t[2]+\"
\",\"function\"==typeof r.innerShiv?o.appendChild(r.innerShiv(t)):(f&&n.body.appendChild(o),o.innerHTML=t,f&&o.parentNode.removeChild(o));i--;)o=o.lastChild;n=N.a.la(o.lastChild.childNodes)}return n},N.a.Md=function(e,t){t=N.a.ua(e,t);return t.length&&t[0].parentElement||N.a.Yb(t)},N.a.fc=function(e,t){if(N.a.Tb(e),null!==(t=N.a.f(t))&&t!==_e)if(\"string\"!=typeof t&&(t=t.toString()),Ne)Ne(e).html(t);else for(var n=N.a.ua(t,e.ownerDocument),r=0;r]*))?)*\\s+)data-bind\\s*=\\s*([\"'])([\\s\\S]*?)\\3/gi,be=/\\x3c!--\\s*ko\\b\\s*([\\s\\S]*?)\\s*--\\x3e/g,{xd:function(e,t,n){t.isTemplateRewritten(e,n)||t.rewriteTemplate(e,function(e){return N.kc.Ld(e,t)},n)},Ld:function(e,o){return e.replace(me,function(e,t,n,r,i){return Ce(i,t,n,o)}).replace(be,function(e,t){return Ce(t,\"\\x3c!-- ko --\\x3e\",\"#comment\",o)})},md:function(n,r){return N.aa.Xb(function(e,t){e=e.nextSibling;e&&e.nodeName.toLowerCase()===r&&N.ib(e,n,t)})}}),N.b(\"__tr_ambtns\",N.kc.md),function(){N.C={},N.C.F=function(e){var t;(this.F=e)&&(t=N.a.R(e),this.ab=\"script\"===t?1:\"textarea\"===t?2:\"template\"==t&&e.content&&11===e.content.nodeType?3:4)},N.C.F.prototype.text=function(){var e=1===this.ab?\"text\":2===this.ab?\"value\":\"innerHTML\";if(0==arguments.length)return this.F[e];var t=arguments[0];\"innerHTML\"==e?N.a.fc(this.F,t):this.F[e]=t};var t=N.a.g.Z()+\"_\";N.C.F.prototype.data=function(e){if(1===arguments.length)return N.a.g.get(this.F,t+e);N.a.g.set(this.F,t+e,arguments[1])};var i=N.a.g.Z();N.C.F.prototype.nodes=function(){var e=this.F;if(0==arguments.length){var t,n=N.a.g.get(e,i)||{},r=n.lb||(3===this.ab?e.content:4===this.ab?e:_e);return r&&!n.jd||(t=this.text())&&t!==n.bb&&(r=N.a.Md(t,e.ownerDocument),N.a.g.set(e,i,{lb:r,bb:t,jd:!0})),r}n=arguments[0],this.ab!==_e&&this.text(\"\"),N.a.g.set(e,i,{lb:n})},N.C.ia=function(e){this.F=e},N.C.ia.prototype=new N.C.F,N.C.ia.prototype.constructor=N.C.ia,N.C.ia.prototype.text=function(){if(0==arguments.length){var e=N.a.g.get(this.F,i)||{};return e.bb===_e&&e.lb&&(e.bb=e.lb.innerHTML),e.bb}N.a.g.set(this.F,i,{bb:arguments[0]})},N.b(\"templateSources\",N.C),N.b(\"templateSources.domElement\",N.C.F),N.b(\"templateSources.anonymousTemplate\",N.C.ia)}(),function(){function r(e,t,n){var r;for(t=N.h.nextSibling(t);e&&(r=e)!==t;)n(r,e=N.h.nextSibling(r))}function d(e,t){if(e.length){var i=e[0],o=e[e.length-1],n=i.parentNode,a=N.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),N.a.Ua(e,n))}r(i,o,function(e){1!==e.nodeType&&8!==e.nodeType||N.vc(t,e)}),r(i,o,function(e){1!==e.nodeType&&8!==e.nodeType||N.aa.cd(e,[t])}),N.a.Ua(e,n)}}function u(e){return e.nodeType?e:0\"+t+\"<\\/script>\")},0>10|55296,1023&e|56320))}function r(){k()}var e,d,w,i,o,p,h,g,x,u,c,k,C,a,T,v,s,l,m,_=\"sizzle\"+ +new Date,b=n.document,E=0,y=0,S=ue(),N=ue(),D=ue(),A=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,I=function(e,t){for(var n=0,r=e.length;n+~]|\"+H+\")\"+H+\"*\"),z=new RegExp(H+\"|>\"),G=new RegExp($),X=new RegExp(\"^\"+B+\"$\"),Y={ID:new RegExp(\"^#(\"+B+\")\"),CLASS:new RegExp(\"^\\\\.(\"+B+\")\"),TAG:new RegExp(\"^(\"+B+\"|[*])\"),ATTR:new RegExp(\"^\"+F),PSEUDO:new RegExp(\"^\"+$),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+H+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+H+\"*(?:([+-]|)\"+H+\"*(\\\\d+)|))\"+H+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+R+\")$\",\"i\"),needsContext:new RegExp(\"^\"+H+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+H+\"*((?:-\\\\d)?\\\\d*)\"+H+\"*\\\\)|)(?=[^-]|$)\",\"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}\"+H+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),oe=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"�\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},ae=be(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{L.apply(t=P.call(b.childNodes),b.childNodes),t[b.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 o,i,a,s,u,c,l=e&&e.ownerDocument,f=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==f&&9!==f&&11!==f)return n;if(!r&&(k(e),e=e||C,T)){if(11!==f&&(s=te.exec(t)))if(c=s[1]){if(9===f){if(!(i=e.getElementById(c)))return n;if(i.id===c)return n.push(i),n}else if(l&&(i=l.getElementById(c))&&m(e,i)&&i.id===c)return n.push(i),n}else{if(s[2])return L.apply(n,e.getElementsByTagName(t)),n;if((c=s[3])&&d.getElementsByClassName&&e.getElementsByClassName)return L.apply(n,e.getElementsByClassName(c)),n}if(d.qsa&&!A[t+\" \"]&&(!v||!v.test(t))&&(1!==f||\"object\"!==e.nodeName.toLowerCase())){if(c=t,l=e,1===f&&(z.test(t)||J.test(t))){for((l=ne.test(t)&&ge(e.parentNode)||e)===e&&d.scope||((a=e.getAttribute(\"id\"))?a=a.replace(oe,ie):e.setAttribute(\"id\",a=_)),o=(u=p(t)).length;o--;)u[o]=(a?\"#\"+a:\":scope\")+\" \"+me(u[o]);c=u.join(\",\")}try{return L.apply(n,l.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{a===_&&e.removeAttribute(\"id\")}}}return g(t.replace(V,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>w.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function ce(e){return e[_]=!0,e}function le(e){var t=C.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}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\"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 he(a){return ce(function(i){return i=+i,ce(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in d=se.support={},o=se.isXML=function(e){var t=e&&e.namespaceURI,e=e&&(e.ownerDocument||e).documentElement;return!K.test(t||e&&e.nodeName||\"HTML\")},k=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:b;return e!=C&&9===e.nodeType&&e.documentElement&&(a=(C=e).documentElement,T=!o(C),b!=C&&(t=C.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),d.scope=le(function(e){return a.appendChild(e).appendChild(C.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),d.attributes=le(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),d.getElementsByTagName=le(function(e){return e.appendChild(C.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),d.getElementsByClassName=ee.test(C.getElementsByClassName),d.getById=le(function(e){return a.appendChild(e).id=_,!C.getElementsByName||!C.getElementsByName(_).length}),d.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&&T){e=t.getElementById(e);return e?[e]:[]}}):(w.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&T){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i]}return[]}}),w.find.TAG=d.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if(\"*\"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},w.find.CLASS=d.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&T)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=ee.test(C.querySelectorAll))&&(le(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+H+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+H+\"*(?:value|\"+R+\")\"),e.querySelectorAll(\"[id~=\"+_+\"-]\").length||v.push(\"~=\"),(t=C.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+H+\"*name\"+H+\"*=\"+H+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+_+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.push(\"[\\\\r\\\\n\\\\f]\")}),le(function(e){e.innerHTML=\"\";var t=C.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&v.push(\"name\"+H+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(d.matchesSelector=ee.test(l=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&le(function(e){d.disconnectedMatch=l.call(e,\"*\"),l.call(e,\"[s!='']:x\"),s.push(\"!=\",$)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),m=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}: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)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==b&&m(b,e)?-1:t==C||t.ownerDocument==b&&m(b,t)?1:u?I(u,e)-I(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==C?-1:t==C?1:o?-1:i?1:u?I(u,e)-I(u,t):0;if(o===i)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]==b?-1:s[r]==b?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(k(e),d.matchesSelector&&T&&!A[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=l.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(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=p(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=S[e+\" \"];return t||(t=new RegExp(\"(^|\"+H+\")\"+e+\"(\"+H+\"|$)\"))&&S(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-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)}),d.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(R,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(k);T.find=p,T.expr=p.selectors,T.expr[\":\"]=T.expr.pseudos,T.uniqueSort=T.unique=p.uniqueSort,T.text=p.getText,T.isXMLDoc=p.isXML,T.contains=p.contains,T.escapeSelector=p.escape;function x(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&T(e).is(n))break;r.push(e)}return r}function _(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var E=T.expr.match.needsContext;function S(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function D(e,n,r){return y(n)?T.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?T.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?T.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(T.fn.init=function(e,t,n){if(!e)return this;if(n=n||O,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):y(e)?void 0!==n.ready?n.ready(e):e(T):T.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:A.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof T?t[0]:t,T.merge(this,T.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),N.test(r[1])&&T.isPlainObject(t))for(var r in t)y(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=C.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=T.fn;var O=T(C),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}T.fn.extend({has:function(e){var t=T(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,de=/^$|^module$|\\/(?:java|ecma)script/i;f=C.createDocumentFragment().appendChild(C.createElement(\"div\")),(p=C.createElement(\"input\")).setAttribute(\"type\",\"radio\"),p.setAttribute(\"checked\",\"checked\"),p.setAttribute(\"name\",\"t\"),f.appendChild(p),b.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",b.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",b.option=!!f.lastChild;var pe={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&S(e,t)?T.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var ve=/<|&#?\\w+;/;function me(e,t,n,r,o){for(var i,a,s,u,c,l=t.createDocumentFragment(),f=[],d=0,p=e.length;d\\s*$/g;function Se(e,t){return S(e,\"table\")&&S(11!==t.nodeType?t:t.firstChild,\"tr\")&&T(e).children(\"tbody\")[0]||e}function Ne(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function De(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Ae(e,t){var n,r,o,i;if(1===t.nodeType){if(X.hasData(e)&&(i=X.get(e).events))for(o in X.remove(t,\"handle events\"),i)for(n=0,r=i[o].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",o=function(e){r.remove(),o=null,e&&t(\"error\"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){o&&o()}}});var Gt=[],Xt=/(=)\\?(?=&|$)|\\?\\?/;T.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Gt.pop()||T.expando+\"_\"+St.guid++;return this[e]=!0,e}}),T.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Xt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Xt.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(Xt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Nt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return i||T.error(r+\" was not called\"),i[0]},e.dataTypes[0]=\"json\",o=k[r],k[r]=function(){i=arguments},n.always(function(){void 0===o?T(k).removeProp(r):k[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),i&&y(o)&&o(i[0]),i=o=void 0}),\"script\"}),b.createHTMLDocument=((f=C.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),T.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(b.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=C.location.href,t.head.appendChild(r)):t=C),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=me([e],t,r),r&&r.length&&T(r).remove(),T.merge([],n.childNodes)));var r},T.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(\" \");return-1\").append(T.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},T.expr.pseudos.animated=function(t){return T.grep(T.timers,function(e){return t===e.elem}).length},T.offset={setOffset:function(e,t,n){var r,o,i,a,s=T.css(e,\"position\"),u=T(e),c={};\"static\"===s&&(e.style.position=\"relative\"),i=u.offset(),r=T.css(e,\"top\"),a=T.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(o=(s=u.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),null!=(t=y(t)?t.call(e,n,T.extend({},i)):t).top&&(c.top=t.top-i.top+o),null!=t.left&&(c.left=t.left-i.left+a),\"using\"in t?t.using.call(e,c):u.css(c)}},T.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){T.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.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],o={top:0,left:0};if(\"fixed\"===T.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\"===T.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=T(e).offset()).top+=T.css(e,\"borderTopWidth\",!0),o.left+=T.css(e,\"borderLeftWidth\",!0))}return{top:t.top-o.top-T.css(r,\"marginTop\",!0),left:t.left-o.left-T.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===T.css(e,\"position\");)e=e.offsetParent;return e||re})}}),T.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,o){var i=\"pageYOffset\"===o;T.fn[t]=function(e){return $(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[o]:e[t]:void(r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),T.each([\"top\",\"left\"],function(e,n){T.cssHooks[n]=Ge(b.pixelPosition,function(e,t){if(t)return t=ze(e,n),$e.test(t)?T(e).position()[n]+\"px\":t})}),T.each({Height:\"height\",Width:\"width\"},function(a,s){T.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,i){T.fn[i]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),o=r||(!0===e||!0===t?\"margin\":\"border\");return $(this,function(e,t,n){var r;return g(e)?0===i.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?T.css(e,t,o):T.style(e,t,n,o)},s,n?e:void 0,n)}})}),T.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){T.fn[t]=function(e){return this.on(t,e)}}),T.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)}}),T.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){T.fn[n]=function(e,t){return 0(e=e||\"\").length)&&e.substring(0,t.length)===t},vd: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},Sb:function(e){return N.a.vd(e,e.ownerDocument.documentElement)},kd:function(e){return!!N.a.Lb(e,N.a.Sb)},R:function(e){return e&&e.tagName&&e.tagName.toLowerCase()},Ac:function(e){return N.onError?function(){try{return e.apply(this,arguments)}catch(e){throw N.onError&&N.onError(e),e}}:e},setTimeout:(c=function(e,t){return setTimeout(N.a.Ac(e),t)},h.toString=function(){return c.toString()},h),Gc:function(e){setTimeout(function(){throw N.onError&&N.onError(e),e},0)},B:function(t,e,n){var r=N.a.Ac(n);if(n=l[e],N.options.useOnlyNativeEvents||n||!Ne)if(n||\"function\"!=typeof t.addEventListener){if(void 0===t.attachEvent)throw Error(\"Browser doesn't support addEventListener or attachEvent\");var o=function(e){r.call(t,e)},i=\"on\"+e;t.attachEvent(i,o),N.a.K.za(t,function(){t.detachEvent(i,o)})}else t.addEventListener(e,r,!1);else u=u||(\"function\"==typeof Ne(t).on?\"on\":\"bind\"),Ne(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=!(\"input\"!==N.a.R(e)||!e.type||\"click\"!=t.toLowerCase())&&(\"checkbox\"==(n=e.type)||\"radio\"==n);if(N.options.useOnlyNativeEvents||!Ne||n)if(\"function\"==typeof Ee.createEvent){if(\"function\"!=typeof e.dispatchEvent)throw Error(\"The supplied element doesn't support dispatchEvent\");(n=Ee.createEvent(s[t]||\"HTMLEvents\")).initEvent(t,!0,!0,_e,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 Ne(e).trigger(t)},f:function(e){return N.O(e)?e():e},bc:function(e){return N.O(e)?e.v():e},Eb:function(t,e,n){var r;e&&(\"object\"===_typeof(t.classList)?(r=t.classList[n?\"add\":\"remove\"],N.a.D(e.match(p),function(e){r.call(t.classList,e)})):\"string\"==typeof t.className.baseVal?o(t.className,\"baseVal\",e,n):o(t,\"className\",e,n))},Bb:function(e,t){var n=N.a.f(t);null!==n&&n!==Te||(n=\"\");t=N.h.firstChild(e);!t||3!=t.nodeType||N.h.nextSibling(t)?N.h.va(e,[e.ownerDocument.createTextNode(n)]):t.data=n,N.a.Ad(e)},Yc:function(e,t){if(e.name=t,d<=7)try{var n=e.name.replace(/[&<>'\"]/g,function(e){return\"&#\"+e.charCodeAt(0)+\";\"});e.mergeAttributes(Ee.createElement(\"\"),!1)}catch(e){}},Ad:function(e){9<=d&&((e=1==e.nodeType?e:e.parentNode).style&&(e.style.zoom=e.style.zoom))},wd:function(e){var t;d&&(t=e.style.width,e.style.width=0,e.style.width=t)},Pd:function(e,t){e=N.a.f(e),t=N.a.f(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:e,tfoot:e,tr:[2,\"\",\"
\"],td:e=[3,\"\",\"
\"],th:e,option:e=[1,\"\"],optgroup:e},f=N.a.W<=8,N.a.ua=function(e,t){var n;if(Ne){if(Ne.parseHTML)n=Ne.parseHTML(e,t)||[];else if((n=Ne.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{var r=(n=!(n=t)?Ee:n).parentWindow||n.defaultView||_e,o=N.a.Db(e).toLowerCase(),i=n.createElement(\"div\"),t=(o=o.match(/^(?:\\x3c!--.*?--\\x3e\\s*?)*?<([a-z]+)[\\s>]/))&&l[o[1]]||u,o=t[0];for(t=\"ignored
\"+t[1]+e+t[2]+\"
\",\"function\"==typeof r.innerShiv?i.appendChild(r.innerShiv(t)):(f&&n.body.appendChild(i),i.innerHTML=t,f&&i.parentNode.removeChild(i));o--;)i=i.lastChild;n=N.a.la(i.lastChild.childNodes)}return n},N.a.Md=function(e,t){t=N.a.ua(e,t);return t.length&&t[0].parentElement||N.a.Yb(t)},N.a.fc=function(e,t){if(N.a.Tb(e),null!==(t=N.a.f(t))&&t!==Te)if(\"string\"!=typeof t&&(t=t.toString()),Ne)Ne(e).html(t);else for(var n=N.a.ua(t,e.ownerDocument),r=0;r]*))?)*\\s+)data-bind\\s*=\\s*([\"'])([\\s\\S]*?)\\3/gi,be=/\\x3c!--\\s*ko\\b\\s*([\\s\\S]*?)\\s*--\\x3e/g,{xd:function(e,t,n){t.isTemplateRewritten(e,n)||t.rewriteTemplate(e,function(e){return N.kc.Ld(e,t)},n)},Ld:function(e,i){return e.replace(me,function(e,t,n,r,o){return ke(o,t,n,i)}).replace(be,function(e,t){return ke(t,\"\\x3c!-- ko --\\x3e\",\"#comment\",i)})},md:function(n,r){return N.aa.Xb(function(e,t){e=e.nextSibling;e&&e.nodeName.toLowerCase()===r&&N.ib(e,n,t)})}}),N.b(\"__tr_ambtns\",N.kc.md),function(){N.C={},N.C.F=function(e){var t;(this.F=e)&&(t=N.a.R(e),this.ab=\"script\"===t?1:\"textarea\"===t?2:\"template\"==t&&e.content&&11===e.content.nodeType?3:4)},N.C.F.prototype.text=function(){var e=1===this.ab?\"text\":2===this.ab?\"value\":\"innerHTML\";if(0==arguments.length)return this.F[e];var t=arguments[0];\"innerHTML\"==e?N.a.fc(this.F,t):this.F[e]=t};var t=N.a.g.Z()+\"_\";N.C.F.prototype.data=function(e){if(1===arguments.length)return N.a.g.get(this.F,t+e);N.a.g.set(this.F,t+e,arguments[1])};var o=N.a.g.Z();N.C.F.prototype.nodes=function(){var e=this.F;if(0==arguments.length){var t,n=N.a.g.get(e,o)||{},r=n.lb||(3===this.ab?e.content:4===this.ab?e:Te);return r&&!n.jd||(t=this.text())&&t!==n.bb&&(r=N.a.Md(t,e.ownerDocument),N.a.g.set(e,o,{lb:r,bb:t,jd:!0})),r}n=arguments[0],this.ab!==Te&&this.text(\"\"),N.a.g.set(e,o,{lb:n})},N.C.ia=function(e){this.F=e},N.C.ia.prototype=new N.C.F,N.C.ia.prototype.constructor=N.C.ia,N.C.ia.prototype.text=function(){if(0==arguments.length){var e=N.a.g.get(this.F,o)||{};return e.bb===Te&&e.lb&&(e.bb=e.lb.innerHTML),e.bb}N.a.g.set(this.F,o,{bb:arguments[0]})},N.b(\"templateSources\",N.C),N.b(\"templateSources.domElement\",N.C.F),N.b(\"templateSources.anonymousTemplate\",N.C.ia)}(),function(){function r(e,t,n){var r;for(t=N.h.nextSibling(t);e&&(r=e)!==t;)n(r,e=N.h.nextSibling(r))}function d(e,t){if(e.length){var o=e[0],i=e[e.length-1],n=o.parentNode,a=N.ga.instance,s=a.preprocessNode;if(s){if(r(o,i,function(e,t){var n=e.previousSibling,r=s.call(a,e);r&&(e===o&&(o=r[0]||t),e===i&&(i=r[r.length-1]||n))}),e.length=0,!o)return;o===i?e.push(o):(e.push(o,i),N.a.Ua(e,n))}r(o,i,function(e){1!==e.nodeType&&8!==e.nodeType||N.vc(t,e)}),r(o,i,function(e){1!==e.nodeType&&8!==e.nodeType||N.aa.cd(e,[t])}),N.a.Ua(e,n)}}function u(e){return e.nodeType?e:0\"+t+\"<\\/script>\")},0>10|55296,1023&e|56320))}function r(){T()}var e,p,b,i,o,d,h,g,w,u,l,T,C,a,S,m,s,c,y,E=\"sizzle\"+ +new Date,v=n.document,k=0,x=0,A=ue(),N=ue(),j=ue(),D=ue(),q=function(e,t){return e===t&&(l=!0),0},L={}.hasOwnProperty,t=[],H=t.pop,O=t.push,P=t.push,R=t.slice,M=function(e,t){for(var n=0,r=e.length;n+~]|\"+W+\")\"+W+\"*\"),V=new RegExp(W+\"|>\"),G=new RegExp(F),Y=new RegExp(\"^\"+_+\"$\"),Q={ID:new RegExp(\"^#(\"+_+\")\"),CLASS:new RegExp(\"^\\\\.(\"+_+\")\"),TAG:new RegExp(\"^(\"+_+\"|[*])\"),ATTR:new RegExp(\"^\"+$),PSEUDO:new RegExp(\"^\"+F),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+W+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+W+\"*(?:([+-]|)\"+W+\"*(\\\\d+)|))\"+W+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+W+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+W+\"*((?:-\\\\d)?\\\\d*)\"+W+\"*\\\\)|)(?=[^-]|$)\",\"i\")},J=/HTML$/i,K=/^(?: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}\"+W+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),oe=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"�\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},ae=ve(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{P.apply(t=R.call(v.childNodes),v.childNodes),t[v.childNodes.length].nodeType}catch(e){P={apply:t.length?function(e,t){O.apply(e,R.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 o,i,a,s,u,l,c=e&&e.ownerDocument,f=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==f&&9!==f&&11!==f)return n;if(!r&&(T(e),e=e||C,S)){if(11!==f&&(s=te.exec(t)))if(l=s[1]){if(9===f){if(!(i=e.getElementById(l)))return n;if(i.id===l)return n.push(i),n}else if(c&&(i=c.getElementById(l))&&y(e,i)&&i.id===l)return n.push(i),n}else{if(s[2])return P.apply(n,e.getElementsByTagName(t)),n;if((l=s[3])&&p.getElementsByClassName&&e.getElementsByClassName)return P.apply(n,e.getElementsByClassName(l)),n}if(p.qsa&&!D[t+\" \"]&&(!m||!m.test(t))&&(1!==f||\"object\"!==e.nodeName.toLowerCase())){if(l=t,c=e,1===f&&(V.test(t)||X.test(t))){for((c=ne.test(t)&&ge(e.parentNode)||e)===e&&p.scope||((a=e.getAttribute(\"id\"))?a=a.replace(oe,ie):e.setAttribute(\"id\",a=E)),o=(u=d(t)).length;o--;)u[o]=(a?\"#\"+a:\":scope\")+\" \"+ye(u[o]);l=u.join(\",\")}try{return P.apply(n,c.querySelectorAll(l)),n}catch(e){D(t,!0)}finally{a===E&&e.removeAttribute(\"id\")}}}return g(t.replace(z,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>b.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function le(e){return e[E]=!0,e}function ce(e){var t=C.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}function fe(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)b.attrHandle[n[r]]=t}function pe(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 de(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 he(a){return le(function(i){return i=+i,le(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in p=se.support={},o=se.isXML=function(e){var t=e&&e.namespaceURI,e=e&&(e.ownerDocument||e).documentElement;return!J.test(t||e&&e.nodeName||\"HTML\")},T=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:v;return e!=C&&9===e.nodeType&&e.documentElement&&(a=(C=e).documentElement,S=!o(C),v!=C&&(t=C.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),p.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),p.attributes=ce(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),p.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),p.getElementsByClassName=ee.test(C.getElementsByClassName),p.getById=ce(function(e){return a.appendChild(e).id=E,!C.getElementsByName||!C.getElementsByName(E).length}),p.getById?(b.filter.ID=function(e){var t=e.replace(re,f);return function(e){return e.getAttribute(\"id\")===t}},b.find.ID=function(e,t){if(void 0!==t.getElementById&&S){e=t.getElementById(e);return e?[e]:[]}}):(b.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},b.find.ID=function(e,t){if(void 0!==t.getElementById&&S){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i]}return[]}}),b.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=[],o=0,i=t.getElementsByTagName(e);if(\"*\"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},b.find.CLASS=p.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&S)return t.getElementsByClassName(e)},s=[],m=[],(p.qsa=ee.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&m.push(\"[*^$]=\"+W+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||m.push(\"\\\\[\"+W+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+E+\"-]\").length||m.push(\"~=\"),(t=C.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||m.push(\"\\\\[\"+W+\"*name\"+W+\"*=\"+W+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||m.push(\":checked\"),e.querySelectorAll(\"a#\"+E+\"+*\").length||m.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),m.push(\"[\\\\r\\\\n\\\\f]\")}),ce(function(e){e.innerHTML=\"\";var t=C.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&m.push(\"name\"+W+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&m.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&m.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),m.push(\",.*:\")})),(p.matchesSelector=ee.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){p.disconnectedMatch=c.call(e,\"*\"),c.call(e,\"[s!='']:x\"),s.push(\"!=\",F)}),m=m.length&&new RegExp(m.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),y=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},q=t?function(e,t){if(e===t)return l=!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==C||e.ownerDocument==v&&y(v,e)?-1:t==C||t.ownerDocument==v&&y(v,t)?1:u?M(u,e)-M(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==C?-1:t==C?1:o?-1:i?1:u?M(u,e)-M(u,t):0;if(o===i)return pe(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?pe(a[r],s[r]):a[r]==v?-1:s[r]==v?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),p.matchesSelector&&S&&!D[t+\" \"]&&(!s||!s.test(t))&&(!m||!m.test(t)))try{var n=c.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 Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&G.test(n)&&(t=d(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=A[e+\" \"];return t||(t=new RegExp(\"(^|\"+W+\")\"+e+\"(\"+W+\"|$)\"))&&A(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-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&&ce(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}),ce(function(e){return null==e.getAttribute(\"disabled\")})||fe(I,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(T);S.find=d,S.expr=d.selectors,S.expr[\":\"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;function w(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&S(e).is(n))break;r.push(e)}return r}function E(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function j(e,n,r){return x(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(S.fn.init=function(e,t,n){if(!e)return this;if(n=n||q,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):x(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:D.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),N.test(r[1])&&S.isPlainObject(t))for(var r in t)x(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=C.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=S.fn;var q=S(C),L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,pe=/^$|^module$|\\/(?:java|ecma)script/i;f=C.createDocumentFragment().appendChild(C.createElement(\"div\")),(d=C.createElement(\"input\")).setAttribute(\"type\",\"radio\"),d.setAttribute(\"checked\",\"checked\"),d.setAttribute(\"name\",\"t\"),f.appendChild(d),v.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",v.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",v.option=!!f.lastChild;var de={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&A(e,t)?S.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var me=/<|&#?\\w+;/;function ye(e,t,n,r,o){for(var i,a,s,u,l,c=t.createDocumentFragment(),f=[],p=0,d=e.length;p\\s*$/g;function Ae(e,t){return A(e,\"table\")&&A(11!==t.nodeType?t:t.firstChild,\"tr\")&&S(e).children(\"tbody\")[0]||e}function Ne(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function je(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function De(e,t){var n,r,o,i;if(1===t.nodeType){if(Y.hasData(e)&&(i=Y.get(e).events))for(o in Y.remove(t,\"handle events\"),i)for(n=0,r=i[o].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",o=function(e){r.remove(),o=null,e&&t(\"error\"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){o&&o()}}});var Gt=[],Yt=/(=)\\?(?=&|$)|\\?\\?/;S.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Gt.pop()||S.expando+\"_\"+At.guid++;return this[e]=!0,e}}),S.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Yt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Yt.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=x(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Nt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return i||S.error(r+\" was not called\"),i[0]},e.dataTypes[0]=\"json\",o=T[r],T[r]=function(){i=arguments},n.always(function(){void 0===o?S(T).removeProp(r):T[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),i&&x(o)&&o(i[0]),i=o=void 0}),\"script\"}),v.createHTMLDocument=((f=C.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),S.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=C.location.href,t.head.appendChild(r)):t=C),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=ye([e],t,r),r&&r.length&&S(r).remove(),S.merge([],n.childNodes)));var r},S.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(\" \");return-1\").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,o,i,a,s=S.css(e,\"position\"),u=S(e),l={};\"static\"===s&&(e.style.position=\"relative\"),i=u.offset(),r=S.css(e,\"top\"),a=S.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(o=(s=u.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),null!=(t=x(t)?t.call(e,n,S.extend({},i)):t).top&&(l.top=t.top-i.top+o),null!=t.left&&(l.left=t.left-i.left+a),\"using\"in t?t.using.call(e,l):u.css(l)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.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],o={top:0,left:0};if(\"fixed\"===S.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\"===S.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=S(e).offset()).top+=S.css(e,\"borderTopWidth\",!0),o.left+=S.css(e,\"borderLeftWidth\",!0))}return{top:t.top-o.top-S.css(r,\"marginTop\",!0),left:t.left-o.left-S.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===S.css(e,\"position\");)e=e.offsetParent;return e||re})}}),S.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,o){var i=\"pageYOffset\"===o;S.fn[t]=function(e){return F(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[o]:e[t]:void(r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),S.each([\"top\",\"left\"],function(e,n){S.cssHooks[n]=Ge(v.pixelPosition,function(e,t){if(t)return t=Ve(e,n),Fe.test(t)?S(e).position()[n]+\"px\":t})}),S.each({Height:\"height\",Width:\"width\"},function(a,s){S.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,i){S.fn[i]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),o=r||(!0===e||!0===t?\"margin\":\"border\");return F(this,function(e,t,n){var r;return g(e)?0===i.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?S.css(e,t,o):S.style(e,t,n,o)},s,n?e:void 0,n)}})}),S.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.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)}}),S.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){S.fn[n]=function(e,t){return 0 Date: Sun, 20 Mar 2022 16:28:34 +0000 Subject: [PATCH 12/20] Removed old file --- src/CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 src/CMakeLists.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 483bc0cf..00000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# This file was automatically generated for projects -# without default 'CMakeLists.txt' file. - -FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*) - -idf_component_register(SRCS ${app_sources}) From eb44366789879c2c3d06f9851f5d145177e96a42 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 20 Mar 2022 17:01:57 +0000 Subject: [PATCH 13/20] Fixes for build errors --- platformio.ini | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/platformio.ini b/platformio.ini index 65f32152..3411bd59 100644 --- a/platformio.ini +++ b/platformio.ini @@ -124,8 +124,7 @@ monitor_flags = [env:openevse_nodemcu-32s] board = nodemcu-32s -framework = arduino, espidf -src_build_flags = +build_flags = ${common.version}.dev ${common.src_build_flags} ${common.debug_flags} @@ -157,11 +156,6 @@ build_flags = #upload_protocol = espota upload_speed = 2000000 #upload_protocol = ftdi -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions} -lib_extra_dirs = lib -build_type = debug # export PLATFORMIO_UPLOAD_PORT=172.16.0.157 # export PLATFORMIO_UPLOAD_FLAGS="-p 3232" From ec741c403a40846d757be3705e8329ab8c8eb0ec Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 20 Mar 2022 17:13:26 +0000 Subject: [PATCH 14/20] Fix Node MCU build --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 3411bd59..17996d2f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -125,6 +125,7 @@ monitor_flags = [env:openevse_nodemcu-32s] board = nodemcu-32s build_flags = + ${common.build_flags} ${common.version}.dev ${common.src_build_flags} ${common.debug_flags} From f78ed5f20a294a33b6972a85096191b228ea948e Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sun, 20 Mar 2022 17:33:54 +0000 Subject: [PATCH 15/20] Removed duplicate enteries --- platformio.ini | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/platformio.ini b/platformio.ini index 17996d2f..5a242df1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -270,17 +270,11 @@ build_flags = ${common.build_flags} ${common.src_build_flags} ${common.version}.dev - -D WIFI_LED=33 - -D WIFI_LED_ON_STATE=HIGH - -D WIFI_BUTTON=34 - -D WIFI_BUTTON_PRESSED_STATE=LOW -D DEBUG_PORT=Serial - -D RAPI_PORT=Serial2 - -D ENABLE_WIRED_ETHERNET - -D RANDOM_SEED_CHANNEL=1 -D WIFI_LED=25 - -D WIFI_BUTTON=2 -D WIFI_LED_ON_STATE=HIGH + -D WIFI_BUTTON=2 + -D WIFI_BUTTON_PRESSED_STATE=LOW -D RAPI_PORT=Serial1 -D RX1=25 -D TX1=27 From a40f901180518db152aafa86200ab842b854e5d4 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Mon, 16 May 2022 23:47:20 +0100 Subject: [PATCH 16/20] No GUI changes required --- gui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui b/gui index 715d3b80..31ed7f3e 160000 --- a/gui +++ b/gui @@ -1 +1 @@ -Subproject commit 715d3b8037f98467affff88ddf47ce7756d4e451 +Subproject commit 31ed7f3e9632476513c6955f060c4ec2cf9d38e8 From 1a44fec84d967d75345536514bf36ec49144de4b Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Mon, 16 May 2022 23:52:17 +0100 Subject: [PATCH 17/20] Tidy-up of merge mistakes --- src/app_config.cpp | 2 -- src/evse_man.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app_config.cpp b/src/app_config.cpp index ce5b9844..ec8c8f03 100644 --- a/src/app_config.cpp +++ b/src/app_config.cpp @@ -161,8 +161,6 @@ ConfigOpt *opts[] = // LED brightness new ConfigOptDefenition(led_brightness, LED_DEFAULT_BRIGHTNESS, "led_brightness", "lb"), #endif -// RFID storage - new ConfigOptDefenition(rfid_storage, "", "rfid_storage", "rs"), // Flags &flagsOpt, diff --git a/src/evse_man.h b/src/evse_man.h index 80e69607..edf07261 100644 --- a/src/evse_man.h +++ b/src/evse_man.h @@ -55,7 +55,7 @@ typedef uint32_t EvseClient; #define EVSE_VEHICLE_ETA (1 << 2) #ifndef EVSE_MANAGER_MAX_CLIENT_CLAIMS -#define EVSE_MANAGER_MAX_CLIENT_CLAIMS 11 +#define EVSE_MANAGER_MAX_CLIENT_CLAIMS 10 #endif // !EVSE_MANAGER_MAX_CLIENT_CLAIMS class EvseProperties : virtual public JsonSerialize<512> From 9f23319adc539955e3c281a6fb2328227d5e88c0 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sat, 4 Jun 2022 11:54:28 +0100 Subject: [PATCH 18/20] Uplift to Platform IO ESP32 core 4.4 --- .github/workflows/build.yaml | 3 ++ platformio.ini | 11 ++-- src/net_manager.cpp | 100 ++++++++++++++++++++--------------- 3 files changed, 69 insertions(+), 45 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 25b585be..18560c1a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,3 +1,5 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json + name: Build/Release OpenEVSE on: @@ -17,6 +19,7 @@ jobs: env: - openevse_nodemcu-32s - openevse_esp-wrover-kit + - openevse_esp-wrover-kit_latest - openevse_huzzah32_dev - openevse_huzzah32 - openevse_featheresp32 diff --git a/platformio.ini b/platformio.ini index aa1c78b6..bebfa3b0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -101,7 +101,7 @@ neopixel_lib = adafruit/Adafruit NeoPixel@1.7.0 #platform = https://github.com/platformio/platform-espressif32.git#feature/stage #platform = https://github.com/platformio/platform-espressif32.git#develop #platform = espressif32@1.11.1 -platform = espressif32@3.5.0 +platform = espressif32@4.4.0 #framework = arduino, espidf framework = arduino lib_deps = ${common.lib_deps} @@ -113,10 +113,10 @@ upload_speed = 921600 monitor_speed = 115200 extra_scripts = ${common.extra_scripts} board_build.partitions = ${common.build_partitions} -platform_packages = +#platform_packages = # ; use a special branch # framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 - platformio/framework-arduinoespressif32 @ ~3.10006.0 +# platformio/framework-arduinoespressif32 @ ~3.10006.0 monitor_flags = --filter=esp32_exception_decoder @@ -159,6 +159,11 @@ upload_speed = 2000000 # export PLATFORMIO_UPLOAD_PORT=172.16.0.157 # export PLATFORMIO_UPLOAD_FLAGS="-p 3232" + +[env:openevse_esp-wrover-kit_latest] +extends = env:openevse_esp-wrover-kit +platform = espressif32 + [env:openevse_huzzah32_dev] board = featheresp32 build_flags = diff --git a/src/net_manager.cpp b/src/net_manager.cpp index 470ceda4..76d6bad6 100644 --- a/src/net_manager.cpp +++ b/src/net_manager.cpp @@ -239,40 +239,56 @@ static void net_wifi_onAPModeStationDisconnected(const WiFiEventSoftAPModeStatio }; #ifdef ESP32 -void net_event(WiFiEvent_t event, system_event_info_t info) +void net_event(WiFiEvent_t event, arduino_event_info_t info) { DBUGF("Got Network event %s", - SYSTEM_EVENT_WIFI_READY == event ? "SYSTEM_EVENT_WIFI_READY" : - SYSTEM_EVENT_SCAN_DONE == event ? "SYSTEM_EVENT_SCAN_DONE" : - SYSTEM_EVENT_STA_START == event ? "SYSTEM_EVENT_STA_START" : - SYSTEM_EVENT_STA_STOP == event ? "SYSTEM_EVENT_STA_STOP" : - SYSTEM_EVENT_STA_CONNECTED == event ? "SYSTEM_EVENT_STA_CONNECTED" : - SYSTEM_EVENT_STA_DISCONNECTED == event ? "SYSTEM_EVENT_STA_DISCONNECTED" : - SYSTEM_EVENT_STA_AUTHMODE_CHANGE == event ? "SYSTEM_EVENT_STA_AUTHMODE_CHANGE" : - SYSTEM_EVENT_STA_GOT_IP == event ? "SYSTEM_EVENT_STA_GOT_IP" : - SYSTEM_EVENT_STA_LOST_IP == event ? "SYSTEM_EVENT_STA_LOST_IP" : - SYSTEM_EVENT_STA_WPS_ER_SUCCESS == event ? "SYSTEM_EVENT_STA_WPS_ER_SUCCESS" : - SYSTEM_EVENT_STA_WPS_ER_FAILED == event ? "SYSTEM_EVENT_STA_WPS_ER_FAILED" : - SYSTEM_EVENT_STA_WPS_ER_TIMEOUT == event ? "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT" : - SYSTEM_EVENT_STA_WPS_ER_PIN == event ? "SYSTEM_EVENT_STA_WPS_ER_PIN" : - SYSTEM_EVENT_AP_START == event ? "SYSTEM_EVENT_AP_START" : - SYSTEM_EVENT_AP_STOP == event ? "SYSTEM_EVENT_AP_STOP" : - SYSTEM_EVENT_AP_STACONNECTED == event ? "SYSTEM_EVENT_AP_STACONNECTED" : - SYSTEM_EVENT_AP_STADISCONNECTED == event ? "SYSTEM_EVENT_AP_STADISCONNECTED" : - SYSTEM_EVENT_AP_STAIPASSIGNED == event ? "SYSTEM_EVENT_AP_STAIPASSIGNED" : - SYSTEM_EVENT_AP_PROBEREQRECVED == event ? "SYSTEM_EVENT_AP_PROBEREQRECVED" : - SYSTEM_EVENT_GOT_IP6 == event ? "SYSTEM_EVENT_GOT_IP6" : - SYSTEM_EVENT_ETH_START == event ? "SYSTEM_EVENT_ETH_START" : - SYSTEM_EVENT_ETH_STOP == event ? "SYSTEM_EVENT_ETH_STOP" : - SYSTEM_EVENT_ETH_CONNECTED == event ? "SYSTEM_EVENT_ETH_CONNECTED" : - SYSTEM_EVENT_ETH_DISCONNECTED == event ? "SYSTEM_EVENT_ETH_DISCONNECTED" : - SYSTEM_EVENT_ETH_GOT_IP == event ? "SYSTEM_EVENT_ETH_GOT_IP" : + + ARDUINO_EVENT_WIFI_READY == event ? "ARDUINO_EVENT_WIFI_READY" : + ARDUINO_EVENT_WIFI_SCAN_DONE == event ? "ARDUINO_EVENT_WIFI_SCAN_DONE" : + ARDUINO_EVENT_WIFI_STA_START == event ? "ARDUINO_EVENT_WIFI_STA_START" : + ARDUINO_EVENT_WIFI_STA_STOP == event ? "ARDUINO_EVENT_WIFI_STA_STOP" : + ARDUINO_EVENT_WIFI_STA_CONNECTED == event ? "ARDUINO_EVENT_WIFI_STA_CONNECTED" : + ARDUINO_EVENT_WIFI_STA_DISCONNECTED == event ? "ARDUINO_EVENT_WIFI_STA_DISCONNECTED" : + ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE == event ? "ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE" : + ARDUINO_EVENT_WIFI_STA_GOT_IP == event ? "ARDUINO_EVENT_WIFI_STA_GOT_IP" : + ARDUINO_EVENT_WIFI_STA_GOT_IP6 == event ? "ARDUINO_EVENT_WIFI_STA_GOT_IP6" : + ARDUINO_EVENT_WIFI_STA_LOST_IP == event ? "ARDUINO_EVENT_WIFI_STA_LOST_IP" : + ARDUINO_EVENT_WIFI_AP_START == event ? "ARDUINO_EVENT_WIFI_AP_START" : + ARDUINO_EVENT_WIFI_AP_STOP == event ? "ARDUINO_EVENT_WIFI_AP_STOP" : + ARDUINO_EVENT_WIFI_AP_STACONNECTED == event ? "ARDUINO_EVENT_WIFI_AP_STACONNECTED" : + ARDUINO_EVENT_WIFI_AP_STADISCONNECTED == event ? "ARDUINO_EVENT_WIFI_AP_STADISCONNECTED" : + ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED == event ? "ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED" : + ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED == event ? "ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED" : + ARDUINO_EVENT_WIFI_AP_GOT_IP6 == event ? "ARDUINO_EVENT_WIFI_AP_GOT_IP6" : + ARDUINO_EVENT_WIFI_FTM_REPORT == event ? "ARDUINO_EVENT_WIFI_FTM_REPORT" : + ARDUINO_EVENT_ETH_START == event ? "ARDUINO_EVENT_ETH_START" : + ARDUINO_EVENT_ETH_STOP == event ? "ARDUINO_EVENT_ETH_STOP" : + ARDUINO_EVENT_ETH_CONNECTED == event ? "ARDUINO_EVENT_ETH_CONNECTED" : + ARDUINO_EVENT_ETH_DISCONNECTED == event ? "ARDUINO_EVENT_ETH_DISCONNECTED" : + ARDUINO_EVENT_ETH_GOT_IP == event ? "ARDUINO_EVENT_ETH_GOT_IP" : + ARDUINO_EVENT_ETH_GOT_IP6 == event ? "ARDUINO_EVENT_ETH_GOT_IP6" : + ARDUINO_EVENT_WPS_ER_SUCCESS == event ? "ARDUINO_EVENT_WPS_ER_SUCCESS" : + ARDUINO_EVENT_WPS_ER_FAILED == event ? "ARDUINO_EVENT_WPS_ER_FAILED" : + ARDUINO_EVENT_WPS_ER_TIMEOUT == event ? "ARDUINO_EVENT_WPS_ER_TIMEOUT" : + ARDUINO_EVENT_WPS_ER_PIN == event ? "ARDUINO_EVENT_WPS_ER_PIN" : + ARDUINO_EVENT_WPS_ER_PBC_OVERLAP == event ? "ARDUINO_EVENT_WPS_ER_PBC_OVERLAP" : + ARDUINO_EVENT_SC_SCAN_DONE == event ? "ARDUINO_EVENT_SC_SCAN_DONE" : + ARDUINO_EVENT_SC_FOUND_CHANNEL == event ? "ARDUINO_EVENT_SC_FOUND_CHANNEL" : + ARDUINO_EVENT_SC_GOT_SSID_PSWD == event ? "ARDUINO_EVENT_SC_GOT_SSID_PSWD" : + ARDUINO_EVENT_SC_SEND_ACK_DONE == event ? "ARDUINO_EVENT_SC_SEND_ACK_DONE" : + ARDUINO_EVENT_PROV_INIT == event ? "ARDUINO_EVENT_PROV_INIT" : + ARDUINO_EVENT_PROV_DEINIT == event ? "ARDUINO_EVENT_PROV_DEINIT" : + ARDUINO_EVENT_PROV_START == event ? "ARDUINO_EVENT_PROV_START" : + ARDUINO_EVENT_PROV_END == event ? "ARDUINO_EVENT_PROV_END" : + ARDUINO_EVENT_PROV_CRED_RECV == event ? "ARDUINO_EVENT_PROV_CRED_RECV" : + ARDUINO_EVENT_PROV_CRED_FAIL == event ? "ARDUINO_EVENT_PROV_CRED_FAIL" : + ARDUINO_EVENT_PROV_CRED_SUCCESS == event ? "ARDUINO_EVENT_PROV_CRED_SUCCESS" : "UNKNOWN" ); switch (event) { - case SYSTEM_EVENT_AP_START: + case ARDUINO_EVENT_WIFI_AP_START: { if(WiFi.softAPsetHostname(esp_hostname.c_str())) { DBUGF("Set host name to %s", WiFi.softAPgetHostname()); @@ -280,7 +296,7 @@ void net_event(WiFiEvent_t event, system_event_info_t info) DBUGF("Setting host name failed: %s", esp_hostname.c_str()); } } break; - case SYSTEM_EVENT_STA_START: + case ARDUINO_EVENT_WIFI_STA_START: { if(WiFi.setHostname(esp_hostname.c_str())) { DBUGF("Set host name to %s", WiFi.getHostname()); @@ -288,25 +304,25 @@ void net_event(WiFiEvent_t event, system_event_info_t info) DBUGF("Setting host name failed: %s", esp_hostname.c_str()); } } break; - case SYSTEM_EVENT_STA_CONNECTED: + case ARDUINO_EVENT_WIFI_STA_CONNECTED: { - auto& src = info.connected; + auto& src = info.wifi_sta_connected; WiFiEventStationModeConnected dst; dst.ssid = String(reinterpret_cast(src.ssid)); memcpy(dst.bssid, src.bssid, 6); dst.channel = src.channel; net_wifi_onStationModeConnected(dst); } break; - case SYSTEM_EVENT_STA_DISCONNECTED: + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: { - auto& src = info.disconnected; + auto& src = info.wifi_sta_disconnected; WiFiEventStationModeDisconnected dst; dst.ssid = String(reinterpret_cast(src.ssid)); memcpy(dst.bssid, src.bssid, 6); dst.reason = static_cast(src.reason); net_wifi_onStationModeDisconnected(dst); } break; - case SYSTEM_EVENT_STA_GOT_IP: + case ARDUINO_EVENT_WIFI_STA_GOT_IP: { auto& src = info.got_ip.ip_info; WiFiEventStationModeGotIP dst; @@ -315,24 +331,24 @@ void net_event(WiFiEvent_t event, system_event_info_t info) dst.gw = src.gw.addr; net_wifi_onStationModeGotIP(dst); } break; - case SYSTEM_EVENT_AP_STACONNECTED: + case ARDUINO_EVENT_WIFI_AP_STACONNECTED: { - auto& src = info.sta_connected; + auto& src = info.wifi_ap_staconnected; WiFiEventSoftAPModeStationConnected dst; memcpy(dst.mac, src.mac, 6); dst.aid = src.aid; net_wifi_onAPModeStationConnected(dst); } break; - case SYSTEM_EVENT_AP_STADISCONNECTED: + case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: { - auto& src = info.sta_disconnected; + auto& src = info.wifi_ap_stadisconnected; WiFiEventSoftAPModeStationDisconnected dst; memcpy(dst.mac, src.mac, 6); dst.aid = src.aid; net_wifi_onAPModeStationDisconnected(dst); } break; #ifdef ENABLE_WIRED_ETHERNET - case SYSTEM_EVENT_ETH_START: + case ARDUINO_EVENT_ETH_START: DBUGLN("ETH Started"); //set eth hostname here if(ETH.setHostname(esp_hostname.c_str())) { @@ -341,10 +357,10 @@ void net_event(WiFiEvent_t event, system_event_info_t info) DBUGF("Setting host name failed: %s", esp_hostname.c_str()); } break; - case SYSTEM_EVENT_ETH_CONNECTED: + case ARDUINO_EVENT_ETH_CONNECTED: DBUGLN("ETH Connected"); break; - case SYSTEM_EVENT_ETH_GOT_IP: + case ARDUINO_EVENT_ETH_GOT_IP: DBUG("ETH MAC: "); DBUG(ETH.macAddress()); DBUG(", IPv4: "); @@ -359,12 +375,12 @@ void net_event(WiFiEvent_t event, system_event_info_t info) eth_connected = true; net_wifi_disconnect(); break; - case SYSTEM_EVENT_ETH_DISCONNECTED: + case ARDUINO_EVENT_ETH_DISCONNECTED: DBUGLN("ETH Disconnected"); eth_connected = false; net_wifi_start(); break; - case SYSTEM_EVENT_ETH_STOP: + case ARDUINO_EVENT_ETH_STOP: DBUGLN("ETH Stopped"); eth_connected = false; break; From 9482bbc1b93c3d2121695c14eab70cd9955b20bb Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Sat, 4 Jun 2022 13:05:37 +0100 Subject: [PATCH 19/20] Fix setting the hostname over WiFi --- src/net_manager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/net_manager.cpp b/src/net_manager.cpp index 76d6bad6..b3aa63eb 100644 --- a/src/net_manager.cpp +++ b/src/net_manager.cpp @@ -113,10 +113,7 @@ startClient() // DEBUG.print(" epass:"); // DEBUG.println(epass.c_str()); -#ifndef ESP32 WiFi.hostname(esp_hostname.c_str()); -#endif // !ESP32 - WiFi.begin(esid.c_str(), epass.c_str()); ledManager.setWifiMode(true, false); @@ -421,6 +418,7 @@ net_setup() net_wifi_start(); #ifdef ENABLE_WIRED_ETHERNET + //ETH.setHostname(esp_hostname.c_str()); ETH.begin(); #endif From 917734b24c5346aee4d0efd899caa920798a8b89 Mon Sep 17 00:00:00 2001 From: Jeremy Poulter Date: Wed, 15 Jun 2022 23:28:04 +0100 Subject: [PATCH 20/20] The SERIAL_RX_PULLUP_PIN fix/hack is no longer needed We no longer need to explicitly pull up the serial read pin on boards that are based on the Huzzah ESP32 breakout board as the core now sets things up correctly. Also override the upload command for the OpenEVSE WiFi board to use curl to upload via the HTTP upload, this is a lot more reliable for that board --- platformio.ini | 4 +--- src/main.cpp | 6 ------ 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/platformio.ini b/platformio.ini index bebfa3b0..0ff5845a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -177,7 +177,6 @@ build_flags = -D WIFI_BUTTON_PRESSED_STATE=LOW -D RAPI_PORT=Serial -D DEBUG_PORT=Serial2 - -D SERIAL_RX_PULLUP_PIN=3 [env:openevse_huzzah32] board = featheresp32 @@ -191,7 +190,6 @@ build_flags = -D WIFI_BUTTON_PRESSED_STATE=LOW -D RAPI_PORT=Serial -D DEBUG_PORT=Serial2 - -D SERIAL_RX_PULLUP_PIN=3 [env:openevse_featheresp32] board = featheresp32 @@ -223,12 +221,12 @@ build_flags = -D WIFI_BUTTON_PRESSED_STATE=LOW -D RAPI_PORT=Serial -D DEBUG_PORT=Serial1 - -D SERIAL_RX_PULLUP_PIN=3 -D I2C_SDA=21 -D I2C_SCL=22 -D ENABLE_MCP9808 -D ENABLE_PN532 -D TX1=16 +upload_command = curl -F firmware=@$SOURCE http://$UPLOAD_PORT/update --progress-bar | cat [env:openevse_esp32-gateway] #For hardware older than RevE diff --git a/src/main.cpp b/src/main.cpp index 69c1d14c..2bf762d7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -265,12 +265,6 @@ void event_send(JsonDocument &event) void hardware_setup() { debug_setup(); - -#ifdef SERIAL_RX_PULLUP_PIN - // https://forums.adafruit.com/viewtopic.php?f=57&t=153553&p=759890&hilit=esp32+serial+pullup#p769168 - pinMode(SERIAL_RX_PULLUP_PIN, INPUT_PULLUP); -#endif - enableLoopWDT(); }